frontend & backend update

This commit is contained in:
carodej
2020-06-19 08:03:29 +02:00
parent 95bc310def
commit a2cab6198e
83 changed files with 4464 additions and 1907 deletions

View File

@@ -5,6 +5,8 @@ namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Resources\GatewayCollection;
use App\Http\Resources\GatewayResource;
use App\Http\Resources\InvoiceCollection;
use App\Invoice;
use App\PaymentGateway;
use Illuminate\Http\Request;
@@ -33,6 +35,19 @@ class GatewayController extends Controller
return new GatewayResource($gateway);
}
/**
* Get single payment gateway by slug
*
* @param $slug
* @return InvoiceCollection
*/
public function show_transactions($slug)
{
return new InvoiceCollection(
Invoice::where('provider', $slug)->get()
);
}
/**
* Update payment gateway options
*

View File

@@ -8,12 +8,21 @@ use App\Http\Resources\PlanResource;
use App\Http\Resources\UserResource;
use App\Http\Resources\UsersCollection;
use App\Plan;
use App\Services\StripeService;
use App\User;
use Illuminate\Http\Request;
use Rinvex\Subscriptions\Models\PlanFeature;
class PlanController extends Controller
{
/**
* PlanController constructor.
*/
public function __construct(StripeService $stripe)
{
$this->stripe = $stripe;
}
/**
* Get all plans
*
@@ -22,7 +31,7 @@ class PlanController extends Controller
public function index()
{
return new PlanCollection(
app('rinvex.subscriptions.plan')->all()
$this->stripe->getPlans()
);
}
@@ -35,7 +44,7 @@ class PlanController extends Controller
public function show($id)
{
return new PlanResource(
app('rinvex.subscriptions.plan')->find($id)
$this->stripe->getPlan($id)
);
}
@@ -47,26 +56,9 @@ class PlanController extends Controller
*/
public function store(Request $request)
{
$plan = app('rinvex.subscriptions.plan')->create([
'description' => $request->input('attributes.description'),
'price' => $request->input('attributes.price'),
'name' => $request->input('attributes.name'),
'currency' => 'USD',
'invoice_period' => 1,
'sort_order' => 1,
'signup_fee' => 0,
]);
// Create multiple plan features at once
$plan->features()->saveMany([
new PlanFeature([
'name' => 'Storage capacity',
'value' => $request->input('attributes.capacity'),
'sort_order' => 1
]),
]);
return new PlanResource($plan);
return new PlanResource(
$this->stripe->createPlan($request)
);
}
/**
@@ -78,18 +70,24 @@ class PlanController extends Controller
*/
public function update(Request $request, $id)
{
// TODO: validation request
$plan = app('rinvex.subscriptions.plan')->find($id);
if ($request->name === 'capacity') {
$plan->getFeatureBySlug('storage-capacity')->update(['value' => $request->value]);
} else {
$plan->update(make_single_input($request));
}
$this->stripe->updatePlan($request, $id);
return response('Saved!', 204);
}
/**
* Delete plan
*
* @param $id
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
*/
public function delete($id)
{
$this->stripe->deletePlan($id);
return response('Done!', 204);
}
/**
* Get subscriptions
*

View File

@@ -258,11 +258,6 @@ class EditItemsController extends Controller
return Demo::upload($request);
}
// Check if user can upload
if (config('vuefilemanager.limit_storage_by_capacity') && user_storage_percentage() >= 100) {
abort(423, 'You exceed your storage limit!');
}
// Check permission to upload for authenticated editor
if ($request->user()->tokenCan('editor')) {

View File

@@ -4,19 +4,32 @@ namespace App\Http\Controllers\General;
use App\Http\Controllers\Controller;
use App\Http\Resources\PricingCollection;
use App\Services\StripeService;
use Illuminate\Http\Request;
class PricingController extends Controller
{
/**
* PlanController constructor.
*/
public function __construct(StripeService $stripe)
{
$this->stripe = $stripe;
}
/**
* Get all active plans
*
* @return PricingCollection
*/
public function index() {
return new PricingCollection(
app('rinvex.subscriptions.plan')->where('is_active', 1)->get()
public function index()
{
$collection = new PricingCollection(
$this->stripe->getActivePlans()
);
return $collection->sortBy('product.metadata.capacity')
->values()
->all();
}
}

View File

@@ -0,0 +1,107 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Http\Resources\PaymentCardCollection;
use App\Http\Resources\PaymentCardResource;
use App\Http\Resources\PaymentDefaultCardResource;
use App\Services\PaymentService;
use App\UserCard;
use Auth;
use Illuminate\Http\Request;
use Laravel\Cashier\PaymentMethod;
class PaymentCardsController extends Controller
{
/**
* @var PaymentService
*/
private $payment;
/**
* PaymentCardsController constructor.
*/
public function __construct(PaymentService $payment)
{
$this->payment = $payment;
}
/**
* Update card detail
*
* @param Request $request
* @param $id
*/
public function update(Request $request, $id)
{
$user = Auth::user();
// Update DefaultPayment Method
$user->updateDefaultPaymentMethod($id);
// Sync default payment method
$user->updateDefaultPaymentMethodFromStripe();
}
/**
* Delete user credit card
*
*/
public function delete($id)
{
$user = Auth::user();
// Get payment method
$paymentMethod = $user->findPaymentMethod($id);
// Delete payment method
$paymentMethod->delete();
// Sync default payment method
$user->updateDefaultPaymentMethodFromStripe();
return response('Done!', 204);
}
/**
* Get user payment methods sorted by default and others
*
* @return array
*/
public function payment_methods()
{
$user = Auth::user();
// Get default payment method
$defaultPaymentMethodObject = $user->defaultPaymentMethod();
$defaultPaymentMethod = $defaultPaymentMethodObject instanceof PaymentMethod
? $defaultPaymentMethodObject->asStripePaymentMethod()
: $defaultPaymentMethodObject;
// filter payment methods without default payment
$paymentMethods = $user->paymentMethods()->filter(function ($paymentMethod) use ($defaultPaymentMethod) {
return $paymentMethod->id !== $defaultPaymentMethod->id;
});
// Get payment methods
$paymentMethodsMapped = $paymentMethods->map(function ($paymentMethod) {
return $paymentMethod->asStripePaymentMethod();
})->values()->all();
if (is_null($paymentMethodsMapped) && is_null($paymentMethodsMapped)) {
return [
'default' => null,
'others' => [],
];
}
return [
'default' => $defaultPaymentMethod instanceof PaymentMethod
? new PaymentCardResource($defaultPaymentMethod)
: new PaymentDefaultCardResource($defaultPaymentMethod),
'others' => new PaymentCardCollection($paymentMethodsMapped),
];
}
}

View File

@@ -3,53 +3,82 @@
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Http\Requests\Subscription\StoreUpgradeAccountRequest;
use App\Http\Resources\UserSubscription;
use App\Invoice;
use App\Services\PaymentService;
use App\Services\StripeService;
use Auth;
use Cartalyst\Stripe\Exception\CardErrorException;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Http\Request;
use Laravel\Cashier\Exceptions\IncompletePayment;
use Symfony\Component\HttpKernel\Exception\HttpException;
class SubscriptionController extends Controller
{
private $stripe;
/**
* SubscriptionController constructor.
* @param $payment
*/
public function __construct(StripeService $stripe)
{
$this->stripe = $stripe;
}
/**
* Generate setup intent
*
* @return \Stripe\SetupIntent
*/
public function stripe_setup_intent()
{
// Get user
$user = Auth::user();
// Create stripe customer if not exist
$user->createOrGetStripeCustomer();
// Return setup intent
return $user->createSetupIntent();
}
public function show()
{
return new UserSubscription(
Auth::user()
);
}
/**
* Upgrade account to subscription
*
* @param Request $request
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
* @param StoreUpgradeAccountRequest $request
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function upgrade(Request $request)
public function upgrade(StoreUpgradeAccountRequest $request)
{
// TODO: validation request
// Get user
$user = Auth::user();
// Get requested plan
$plan = app('rinvex.subscriptions.plan')
->find($request->input('plan.data.id'));
$plan = $this->stripe->getPlan($request->input('plan.data.id'));
// Check if user have subscription
if ($user->activeSubscriptions()->count() !== 0) {
// Set user billing
$user->setBilling($request->input('billing'));
// Get old subscription
$subscription = $user->subscription('main');
// Change subscription plan
$subscription->changePlan($plan);
} else {
// Create subscription
$user->newSubscription('main', $plan);
}
// Make subscription
$this->stripe->createOrReplaceSubscription($request, $user);
// Update user storage limit
$user->settings()->update([
'storage_capacity' => $plan->features->first()->value
'storage_capacity' => $plan['product']['metadata']['capacity']
]);
// Store invoice
Invoice::create(
get_invoice_data($user, $plan)
);
Invoice::create(get_invoice_data($user, $plan, 'stripe'));
return response('Done!', 204);
}
@@ -57,15 +86,25 @@ class SubscriptionController extends Controller
/**
* Cancel Subscription
*
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function cancel() {
// Get user
$user = Auth::user();
public function cancel()
{
// Cancel subscription
$user->subscription('main')->cancel();
Auth::user()->subscription('main')->cancel();
return response('Done!', 204);
}
/**
* Resume Subscription
*
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function resume()
{
// Resume subscription
Auth::user()->subscription('main')->resume();
return response('Done!', 204);
}

View File

@@ -27,7 +27,14 @@ function get_invoice_number()
}
}
function get_invoice_data($user, $plan)
/**
* Get data to render in invoice tempalte
* @param $user
* @param $plan
* @param $provider
* @return array
*/
function get_invoice_data($user, $plan, $provider)
{
$subscription = $user->subscription('main');
$order_number = get_invoice_number();
@@ -36,15 +43,17 @@ function get_invoice_data($user, $plan)
return [
'token' => $token,
'order' => $order_number,
'provider' => $provider,
'user_id' => $user->id,
'plan_id' => $plan->id,
'total' => $plan->price,
'plan_id' => $plan['plan']['id'],
'total' => $plan['plan']['amount'],
'currency' => 'USD',
'bag' => [
[
'description' => 'Subscription - ' . $plan->name,
'date' => format_date($subscription->starts_at, '%d. %B. %Y') . ' - ' . format_date($subscription->ends_at, '%d. %B. %Y'),
'amount' => $plan->price,
'description' => 'Subscription - ' . $plan['product']['name'],
//'date' => format_date($subscription->starts_at, '%d. %B. %Y') . ' - ' . format_date($subscription->ends_at, '%d. %B. %Y'),
'date' => format_date(Carbon::now(),'%d. %B. %Y'),
'amount' => $plan['plan']['amount'],
]
],
'seller' => [
@@ -282,15 +291,21 @@ function get_storage_fill_percentage($used, $capacity)
}
/**
* Get user capacity fill percentage
* Get user capacity fill by percentage
*
* @return string
*/
function user_storage_percentage()
function user_storage_percentage($id, $additionals = null)
{
$user = Auth::user();
$user = \App\User::findOrFail($id);
return get_storage_fill_percentage($user->used_capacity, $user->settings->storage_capacity);
$used = $user->used_capacity;
if ($additionals) {
$used = $user->used_capacity + $additionals;
}
return get_storage_fill_percentage($used, $user->settings->storage_capacity);
}
/**

View File

@@ -0,0 +1,23 @@
<?php
/**
* Check if current user subscribed plan is highest
*
* @param $id
* @param $subscribed_capacity
* @return int
*/
function is_highest_plan($plan)
{
$plans = app('rinvex.subscriptions.plan')->all();
$unsubscribed = $plans->filter(function ($item) use ($plan) {
return $item->id !== $plan->id;
});
$capacities = $unsubscribed->map(function ($item) {
return $item->features->first()->value;
});
return max(Arr::flatten($capacities)) < $plan->features->first()->value ? 1 : 0;
}

View File

@@ -0,0 +1,56 @@
<?php
namespace App\Http\Requests\Subscription;
use Illuminate\Foundation\Http\FormRequest;
class StoreUpgradeAccountRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
// Billings
'billing' => 'required|array',
'billing.billing_address' => 'required|string',
'billing.billing_city' => 'required|string',
'billing.billing_country' => 'required|string',
'billing.billing_name' => 'required|string',
'billing.billing_phone_number' => 'required|string',
'billing.billing_postal_code' => 'required|string',
'billing.billing_state' => 'required|string',
// Payment
'payment' => 'required|array',
'payment.type' => 'required|string',
'payment.meta' => 'required|sometimes|array',
'payment.meta.pm' => 'required|sometimes|string',
// Plan
'plan.data' => 'required|array',
'plan.data.attributes' => 'required|array',
'plan.data.attributes.capacity' => 'required|digits_between:1,9',
'plan.data.attributes.capacity_formatted' => 'required|string',
'plan.data.attributes.currency' => 'required|string',
'plan.data.attributes.description' => 'required|string',
'plan.data.attributes.name' => 'required|string',
'plan.data.attributes.price' => 'required|string',
'plan.data.id' => 'required|string',
'plan.data.type' => 'required|string',
];
}
}

View File

@@ -19,15 +19,16 @@ class GatewayResource extends JsonResource
'id' => (string)$this->id,
'type' => 'gateways',
'attributes' => [
'status' => $this->status,
'sandbox' => $this->sandbox,
'name' => $this->name,
'slug' => $this->slug,
'logo' => $this->logo,
'client_id' => $this->client_id,
'secret' => $this->secret,
'webhook' => $this->webhook,
'optional' => $this->optional,
'status' => $this->status,
'sandbox' => $this->sandbox,
'name' => $this->name,
'slug' => $this->slug,
'logo' => $this->logo,
'client_id' => $this->client_id,
'secret' => $this->secret,
'webhook' => $this->webhook,
'payment_processed' => $this->payment_processed,
'optional' => $this->optional,
]
]
];

View File

@@ -0,0 +1,23 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class PaymentCardCollection extends ResourceCollection
{
public $collects = PaymentCardResource::class;
/**
* Transform the resource collection into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'data' => $this->collection,
];
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class PaymentCardResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'data' => [
'id' => (string)$this['id'],
'type' => 'payment_method',
'attributes' => [
'provider' => 'stripe',
'card_id' => $this['id'],
'brand' => strtolower($this['card']['brand']),
'last4' => $this['card']['last4'],
'exp_month' => $this['card']['exp_month'],
'exp_year' => $this['card']['exp_year'],
'created_at' => format_date($this['created_at'], '%d. %B. %Y'),
'status' => 'active',
'default' => 0,
]
]
];
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class PaymentDefaultCardResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'data' => [
'id' => (string)$this['id'],
'type' => 'payment_method',
'attributes' => [
'provider' => 'stripe',
'card_id' => $this['id'],
'brand' => isset($this['brand']) ? strtolower($this['brand']) : strtolower($this['card']['brand']),
'last4' => isset($this['last4']) ? $this['last4'] : $this['card']['last4'],
'exp_month' => isset($this['exp_month']) ? $this['exp_month'] : $this['card']['exp_month'],
'exp_year' => isset($this['exp_year']) ? $this['exp_year'] : $this['card']['exp_year'],
'created_at' => format_date($this['created_at'], '%d. %B. %Y'),
'status' => 'active',
'default' => 0,
]
]
];
}
}

View File

@@ -16,19 +16,18 @@ class PlanResource extends JsonResource
{
return [
'data' => [
'id' => (string)$this->id,
'id' => $this['plan']['id'],
'type' => 'plans',
'attributes' => [
'subscribers' => $this->subscriptions->count(),
'status' => $this->is_active,
'name' => $this->name,
'description' => $this->description,
'price' => $this->price,
'capacity_formatted' => format_gigabytes($this->features->first()->value),
'capacity' => $this->features->first()->value,
'created_at_formatted' => format_date($this->created_at),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'subscribers' => $this['plan']['aggregate_usage'],
'status' => $this['plan']['active'],
'name' => $this['product']['name'],
'description' => $this['product']['description'],
'price' => $this['plan']['amount'],
'capacity_formatted' => format_gigabytes($this['product']['metadata']['capacity']),
'capacity' => $this['product']['metadata']['capacity'],
'created_at_formatted' => format_date($this['plan']['created']),
'created_at' => $this['plan']['created'],
]
]
];

View File

@@ -3,28 +3,29 @@
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
use Laravel\Cashier\Cashier;
class PricingResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'data' => [
'id' => (string)$this->id,
'id' => $this['plan']['id'],
'type' => 'plans',
'attributes' => [
'name' => $this->name,
'description' => $this->description,
'price' => $this->price,
'capacity_formatted' => format_gigabytes($this->features->first()->value),
'capacity' => (int) $this->features->first()->value,
'currency' => 'USD',
'name' => $this['product']['name'],
'description' => $this['product']['description'],
'price' => Cashier::formatAmount($this['plan']['amount']),
'capacity_formatted' => format_gigabytes($this['product']['metadata']['capacity']),
'capacity' => (int) $this['product']['metadata']['capacity'],
'currency' => 'USD',
]
]
];

View File

@@ -2,6 +2,9 @@
namespace App\Http\Resources;
use App\Services\StripeService;
use App\User;
use Cartalyst\Stripe\Api\PaymentMethods;
use Faker\Factory;
use Illuminate\Http\Resources\Json\JsonResource;
@@ -27,16 +30,14 @@ class UserResource extends JsonResource
'email' => env('APP_DEMO') ? $faker->email : $this->email,
'avatar' => $this->avatar,
'role' => $this->role,
'subscription' => $this->subscribed('main'),
'created_at_formatted' => format_date($this->created_at, '%d. %B. %Y'),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
]
],
'relationships' => [
'subscription' => $this->activeSubscriptions()->count() !== 0
? new UserSubscription($this->subscription('main'))
: null,
'settings' => [
'settings' => [
'data' => [
'id' => (string)$this->settings->id,
'type' => 'settings',
@@ -51,14 +52,14 @@ class UserResource extends JsonResource
]
]
],
'storage' => [
'storage' => [
'data' => [
'id' => '1',
'type' => 'storage',
'attributes' => $this->storage
]
],
'favourites' => [
'favourites' => [
'data' => [
'id' => '1',
'type' => 'folders_favourite',
@@ -67,7 +68,7 @@ class UserResource extends JsonResource
],
],
],
'tree' => [
'tree' => [
'data' => [
'id' => '1',
'type' => 'folders_tree',
@@ -76,6 +77,7 @@ class UserResource extends JsonResource
],
],
],
'payment_methods' => new PaymentCardCollection($this->payment_cards)
]
];
}

View File

@@ -14,21 +14,33 @@ class UserSubscription extends JsonResource
*/
public function toArray($request)
{
$stripe = resolve('App\Services\StripeService');
$active_subscription = $this->subscription('main')->asStripeSubscription();
// Get subscription details
$subscription = $stripe->getPlan($this->subscription('main')->stripe_plan);
// Retrieve the timestamp from Stripe
$current_period_end = $active_subscription["current_period_end"];
$current_period_start = $active_subscription["current_period_start"];
$canceled_at = $active_subscription["canceled_at"];
return [
'data' => [
'id' => $this->id,
'id' => $subscription['plan']['id'],
'type' => 'subscription',
'attributes' => [
'active' => $this->active(),
'canceled' => $this->canceled(),
'name' => $this->plan->name,
'capacity' => (int) $this->plan->features->first()->value,
'capacity_formatted' => format_gigabytes($this->plan->features->first()->value),
'slug' => $this->slug,
'canceled_at' => format_date($this->created_at, '%d. %B. %Y'),
'created_at' => format_date($this->created_at, '%d. %B. %Y'),
'starts_at' => format_date($this->starts_at, '%d. %B. %Y'),
'ends_at' => format_date($this->ends_at, '%d. %B. %Y'),
/*'is_highest' => is_highest_plan($this->plan),*/
'active' => $subscription['plan']['active'],
'canceled' => $this->subscription('main')->cancelled(),
'name' => $subscription['product']['name'],
'capacity' => (int)$subscription['product']['metadata']['capacity'],
'capacity_formatted' => format_gigabytes($subscription['product']['metadata']['capacity']),
'slug' => $subscription['plan']['id'],
'canceled_at' => format_date($canceled_at, '%d. %B. %Y'),
'created_at' => format_date($current_period_start, '%d. %B. %Y'),
'ends_at' => format_date($current_period_end, '%d. %B. %Y'),
]
]
];

View File

@@ -197,14 +197,20 @@ class Editor
*/
public static function upload($request, $shared = null)
{
// Get user data
$user_scope = is_null($shared) ? $request->user()->token()->scopes[0] : 'editor';
$user_id = is_null($shared) ? Auth::id() : $shared->user_id;
// Get parent_id from request
$folder_id = $request->parent_id === 0 ? 0 : $request->parent_id;
$file = $request->file('file');
// Get user data
$user_scope = is_null($shared) ? $request->user()->token()->scopes[0] : 'editor';
$user_id = is_null($shared) ? Auth::id() : $shared->user_id;
$user_storage_used = user_storage_percentage($user_id, $file->getSize());
// Check if user can upload
if (config('vuefilemanager.limit_storage_by_capacity') && $user_storage_used >= 100) {
abort(423, 'You exceed your storage limit!');
}
// File
$filename = Str::random() . '-' . str_replace(' ', '', $file->getClientOriginalName());
$filetype = get_file_type($file);