removed old subscription backend

This commit is contained in:
Čarodej
2021-11-19 16:18:27 +01:00
parent 34eaf3e411
commit f402141bfb
50 changed files with 13 additions and 2287 deletions

View File

@@ -1,23 +1,17 @@
<?php
use Domain\Plans\Controllers\PlansController;
use Domain\Admin\Controllers\Users\UserController;
use Domain\Pages\Controllers\AdminPagesController;
use Domain\Settings\Controllers\SetEmailController;
use Domain\Settings\Controllers\SetStripeController;
use Domain\Settings\Controllers\FlushCacheController;
use Domain\Invoices\Controllers\AdminInvoiceController;
use Domain\Localization\Controllers\LanguageController;
use Domain\Plans\Controllers\PlanSubscribersController;
use Domain\Admin\Controllers\Users\DeleteUserController;
use Domain\Settings\Controllers\GetSettingsValueController;
use Domain\Admin\Controllers\Dashboard\GetNewbiesController;
use Domain\Admin\Controllers\Users\ChangeUserRoleController;
use Domain\Settings\Controllers\UpdateSettingValueController;
use Domain\Admin\Controllers\Users\ShowUserInvoicesController;
use Domain\Admin\Controllers\Users\ResetUserPasswordController;
use Domain\Admin\Controllers\Dashboard\GetWidgetsValuesController;
use Domain\Admin\Controllers\Users\ShowUserSubscriptionController;
use Domain\Localization\Controllers\UpdateLanguageStringController;
use Domain\Admin\Controllers\Users\ShowUserStorageCapacityController;
use Domain\Admin\Controllers\Users\ChangeUserStorageCapacityController;
@@ -37,30 +31,25 @@ Route::group(['prefix' => 'users'], function () {
Route::delete('/{user}/delete', DeleteUserController::class);
// Subscription
Route::get('/{user}/subscription', ShowUserSubscriptionController::class);
Route::get('/{user}/invoices', ShowUserInvoicesController::class);
//Route::get('/{user}/subscription', ShowUserSubscriptionController::class);
//Route::get('/{user}/invoices', ShowUserInvoicesController::class);
});
Route::apiResource('/users', UserController::class);
// Plans
Route::get('/plans/{id}/subscribers', PlanSubscribersController::class);
Route::apiResource('/', PlansController::class);
// Pages
Route::apiResource('/pages', AdminPagesController::class);
// Invoices
Route::get('/invoices', [AdminInvoiceController::class, 'index']);
// Settings
Route::group(['prefix' => 'settings'], function () {
Route::patch('/', UpdateSettingValueController::class);
Route::get('/', GetSettingsValueController::class);
Route::get('/flush-cache', FlushCacheController::class);
Route::post('/stripe', SetStripeController::class);
Route::post('/email', SetEmailController::class);
// TODO: stripe setup
//Route::post('/stripe', SetStripeController::class);
});
// Language

View File

@@ -9,7 +9,6 @@ use App\Users\Controllers\ResetPasswordController;
use Domain\Files\Controllers\UploadFileController;
use App\Users\Controllers\ForgotPasswordController;
use Domain\Folders\Controllers\FavouriteController;
use Domain\Plans\Controllers\ActivePlansController;
use Domain\Folders\Controllers\CreateFolderController;
use Domain\Browsing\Controllers\BrowseFolderController;
use Domain\Sharing\Controllers\ShareViaEmailController;
@@ -30,7 +29,6 @@ Route::apiResource('/page', PagesController::class);
// Homepage
Route::post('/contact', SendContactMessageController::class);
Route::get('/pricing', ActivePlansController::class);
Route::get('/settings', GetSettingsValueController::class);
// Register user

View File

@@ -16,5 +16,4 @@ Route::group(['middleware' => ['auth:sanctum']], function () {
Route::post('/folders/{folder}/convert', ConvertFolderIntoTeamFolderController::class);
Route::delete('/folders/{folder}/leave', LeaveTeamFolderController::class);
Route::get('/folders/{folder}/tree', NavigationTreeController::class);
});

View File

@@ -1,19 +1,12 @@
<?php
use Domain\Payments\Controllers\PaymentMethodsController;
use App\Users\Controllers\Account\AccountDetailsController;
use App\Users\Controllers\Account\UpdatePasswordController;
use App\Users\Controllers\Account\StorageCapacityController;
use App\Users\Controllers\Verification\VerifyEmailController;
use Domain\Invoices\Controllers\UserProfileInvoiceController;
use Domain\Subscriptions\Controllers\GetSetupIntentController;
use App\Users\Controllers\Verification\ResendVerificationEmail;
use App\Users\Controllers\Authentication\CheckAccountController;
use App\Users\Controllers\Account\UpdateProfileSettingsController;
use Domain\Subscriptions\Controllers\SubscriptionCancelController;
use Domain\Subscriptions\Controllers\SubscriptionResumeController;
use Domain\Subscriptions\Controllers\SubscriptionDetailsController;
use Domain\Subscriptions\Controllers\SubscriptionUpgradeController;
use App\Users\Controllers\Authentication\AccountAccessTokenController;
Route::post('/check', CheckAccountController::class);
@@ -34,17 +27,4 @@ Route::group(['middleware' => ['auth:sanctum']], function () {
Route::post('/password', UpdatePasswordController::class);
Route::get('/storage', StorageCapacityController::class);
Route::get('/', AccountDetailsController::class);
// Subscription
Route::group(['prefix' => 'subscription'], function () {
Route::get('/setup-intent', GetSetupIntentController::class);
Route::apiResource('/payment-cards', PaymentMethodsController::class);
Route::get('/invoices', UserProfileInvoiceController::class);
Route::get('/', SubscriptionDetailsController::class);
Route::post('/upgrade', SubscriptionUpgradeController::class);
Route::post('/cancel', SubscriptionCancelController::class);
Route::post('/resume', SubscriptionResumeController::class);
});
});

View File

@@ -1,16 +1,10 @@
<?php
use Domain\Homepage\Controllers\IndexController;
use Domain\Invoices\Controllers\AdminInvoiceController;
use Domain\Sharing\Controllers\SharePublicIndexController;
use Domain\Sharing\Controllers\WebCrawlerOpenGraphController;
use Domain\Subscriptions\Controllers\StripeWebhookController;
use Domain\Localization\Controllers\CurrentLocalizationController;
// Subscription Services
//Route::post('/stripe/webhook', [StripeWebhookController::class, 'handleWebhook']);
Route::get('/invoice/{customer}/{token}', [AdminInvoiceController::class, 'show'])->middleware(['auth:sanctum']);
// Translations
Route::get('/translations/{lang}', CurrentLocalizationController::class);

View File

@@ -13,7 +13,6 @@ use Kyslik\ColumnSortable\Sortable;
use Illuminate\Support\Facades\Storage;
use Illuminate\Notifications\Notifiable;
use App\Users\Notifications\ResetPassword;
use Domain\Subscriptions\Traits\Subscription;
use Laravel\Fortify\TwoFactorAuthenticatable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Relations\HasOne;
@@ -39,7 +38,6 @@ use VueFileManager\Subscription\App\User\Traits\Billable;
class User extends Authenticatable implements MustVerifyEmail
{
use TwoFactorAuthenticatable;
use Subscription;
use HasApiTokens;
use Notifiable;
use HasFactory;

View File

@@ -21,9 +21,6 @@ class UserResource extends JsonResource
'type' => 'user',
'attributes' => [
'storage_capacity' => $this->settings->storage_capacity,
//'subscription' => $this->subscribed('main'),
//'incomplete_payment' => $this->hasIncompletePayment('main') ? route('cashier.payment', $this->subscription('main')->latestPayment()->id) : null,
'stripe_customer' => is_null($this->stripe_id) ? false : true,
'email' => is_demo() ? obfuscate_email($this->email) : $this->email,
'role' => $this->role,
'two_factor_authentication' => $this->two_factor_secret ? true : false,

View File

@@ -10,10 +10,6 @@ class GetWidgetsValuesController extends Controller
{
public function __invoke(): array
{
// Get total premium users
$premium_users = Subscription::whereStripeStatus('active')
->count();
// Get total storage usage
$storage_usage = Metric::bytes(
\DB::table('files')->sum('filesize')
@@ -24,7 +20,6 @@ class GetWidgetsValuesController extends Controller
'app_version' => config('vuefilemanager.version'),
'total_users' => User::count(),
'total_used_space' => $storage_usage,
'total_premium_users' => $premium_users,
];
}
}

View File

@@ -22,9 +22,10 @@ class DeleteUserController extends Controller
return response('Done.', 204);
}
if ($user->subscribed('main')) {
// TODO: secure deletion
/*if ($user->subscription) {
abort(202, "You can\'t delete this account while user have active subscription.");
}
}*/
if ($user->id === Auth::id()) {
abort(406, "You can\'t delete your account");

View File

@@ -1,25 +0,0 @@
<?php
namespace Domain\Admin\Controllers\Users;
use App\Users\Models\User;
use App\Http\Controllers\Controller;
use Domain\Invoices\Resources\InvoiceCollection;
use Domain\Subscriptions\Services\StripeService;
class ShowUserInvoicesController extends Controller
{
public function __construct(
private StripeService $stripe
) {
}
/**
* Get user storage details
*/
public function __invoke(User $user): InvoiceCollection
{
$invoices = $this->stripe->getUserInvoices($user);
return new InvoiceCollection($invoices);
}
}

View File

@@ -1,22 +0,0 @@
<?php
namespace Domain\Admin\Controllers\Users;
use App\Users\Models\User;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use App\Users\Resources\UserSubscription;
class ShowUserSubscriptionController extends Controller
{
/**
* Get user subscription details
*/
public function __invoke(User $user): UserSubscription | Response
{
if (! $user->stripeId() || ! $user->subscription('main')) {
return response("User doesn't have any subscription.", 404);
}
return new UserSubscription($user);
}
}

View File

@@ -1,22 +0,0 @@
<?php
namespace Domain\Admin\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class InvoiceAdminCollection extends ResourceCollection
{
public $collects = InvoiceAdminResource::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

@@ -1,65 +0,0 @@
<?php
namespace Domain\Admin\Resources;
use App\Users\Models\User;
use Laravel\Cashier\Cashier;
use Illuminate\Http\Resources\Json\JsonResource;
class InvoiceAdminResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
$user = User::where('stripe_id', $this['customer'])
->first();
return [
'data' => [
'id' => $this['id'],
'type' => 'invoices',
'attributes' => [
'customer' => $this['customer'],
'total' => Cashier::formatAmount($this['total']),
'currency' => $this['currency'],
'created_at_formatted' => format_date($this['created']),
'created_at' => $this['created'],
'order' => $this['number'],
'user_id' => $user->id ?? null,
'client' => [
'billing_address' => $this['customer_address'],
'billing_name' => $this['customer_name'],
'billing_phone_number' => $this['customer_phone'],
],
'bag' => [
'amount' => $this['lines']['data'][0]['amount'],
'currency' => $this['lines']['data'][0]['currency'],
'type' => $this['lines']['data'][0]['type'],
'description' => $this['lines']['data'][0]['description'],
],
'seller' => null,
],
$this->mergeWhen($user, function () use ($user) {
return [
'relationships' => [
'user' => [
'data' => [
'id' => $user->id,
'type' => 'user',
'attributes' => [
'name' => $user->settings->name,
'avatar' => $user->settings->avatar,
],
],
],
],
];
}),
],
];
}
}

View File

@@ -1,35 +0,0 @@
<?php
namespace Domain\Invoices\Controllers;
use Illuminate\View\View;
use App\Http\Controllers\Controller;
use Domain\Subscriptions\Services\StripeService;
use Domain\Admin\Resources\InvoiceAdminCollection;
class AdminInvoiceController extends Controller
{
public function __construct(
private StripeService $stripe
) {
}
/**
* Get all invoices
*/
public function index(): InvoiceAdminCollection
{
return new InvoiceAdminCollection(
$this->stripe->getInvoices()['data']
);
}
/**
* Get single invoice by invoice $token
*/
public function show(string $customer, string $token): View
{
return view('vuefilemanager.invoice')
->with('settings', get_settings_in_json())
->with('invoice', $this->stripe->getUserInvoice($customer, $token));
}
}

View File

@@ -1,19 +0,0 @@
<?php
namespace Domain\Invoices\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Domain\Invoices\Resources\InvoiceCollection;
class UserProfileInvoiceController extends Controller
{
/**
* Get user invoices
*/
public function __invoke(): InvoiceCollection
{
$user = Auth::user()->invoices();
return new InvoiceCollection($user);
}
}

View File

@@ -1,22 +0,0 @@
<?php
namespace Domain\Invoices\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class InvoiceCollection extends ResourceCollection
{
public $collects = InvoiceResource::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

@@ -1,96 +0,0 @@
<?php
namespace Domain\Invoices\Resources;
use App\Users\Models\User;
use Illuminate\Http\Resources\Json\JsonResource;
class InvoiceResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
$user = User::whereStripeId($this->customer)
->first();
return [
'data' => [
'id' => $this->id,
'type' => 'invoices',
'attributes' => [
'customer' => $this->customer,
'total' => $this->total(),
'currency' => $this->currency,
'created_at_formatted' => format_date($this->date(), '%d. %B. %Y'),
'created_at' => $this->created,
'order' => $this->number,
'user_id' => $user->id ?? null,
'client' => [
'billing_address' => $this->customer_address,
'billing_name' => $this->customer_name,
'billing_phone_number' => $this->customer_phone,
],
'seller' => null,
'invoice_items' => $this->get_invoice_items(),
'invoice_subscriptions' => $this->get_invoice_subscriptions(),
],
$this->mergeWhen($user, [
'relationships' => [
'user' => [
'data' => [
'id' => $user->id,
'type' => 'user',
'attributes' => [
'name' => $user->settings->name,
'avatar' => $user->settings->avatar,
],
],
],
],
]),
],
];
}
/**
* @return array
*/
private function get_invoice_subscriptions(): array
{
$array = [];
foreach ($this->subscriptions() as $item) {
array_push($array, [
'amount' => $item->total(),
'description' => $item->description,
'currency' => $item->currency,
'type' => $item->type,
]);
}
return $array;
}
/**
* @return array
*/
private function get_invoice_items(): array
{
$array = [];
foreach ($this->invoiceItems() as $item) {
array_push($array, [
'amount' => $item->total(),
'description' => $item->description,
'currency' => $item->currency,
'type' => $item->type,
]);
}
return $array;
}
}

View File

@@ -1,144 +0,0 @@
<?php
namespace Domain\Payments\Controllers;
use Auth;
use Illuminate\Http\Response;
use Laravel\Cashier\PaymentMethod;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;
use Domain\Subscriptions\Services\StripeService;
use Domain\Payments\Resources\PaymentCardResource;
use Domain\Payments\Resources\PaymentCardCollection;
use Domain\Payments\Resources\PaymentDefaultCardResource;
use Domain\Payments\Requests\RegisterNewPaymentMethodRequest;
class PaymentMethodsController extends Controller
{
public function __construct(
private StripeService $stripe,
) {
}
/**
* Get user payment methods grouped by default and others
*/
public function index(): array
{
$user = Auth::user();
if (! $user->hasPaymentMethod()) {
return abort(204, 'User don\'t have any payment methods');
}
$slug_payment_methods = 'payment-methods-user-' . $user->id;
$slug_default_payment_method = 'default-payment-methods-user-' . $user->id;
if (Cache::has($slug_payment_methods) && Cache::has($slug_default_payment_method)) {
$defaultPaymentMethod = Cache::get($slug_default_payment_method);
$paymentMethodsMapped = Cache::get($slug_payment_methods);
} else {
// Get default payment method
$defaultPaymentMethod = Cache::rememberForever($slug_default_payment_method, function () use ($user) {
$defaultPaymentMethodObject = $user->defaultPaymentMethod();
return $defaultPaymentMethodObject instanceof PaymentMethod
? $defaultPaymentMethodObject->asStripePaymentMethod()
: $defaultPaymentMethodObject;
});
// filter payment methods without default payment
$paymentMethodsMapped = Cache::rememberForever($slug_payment_methods, function () use ($defaultPaymentMethod, $user) {
$paymentMethods = $user->paymentMethods()->filter(fn ($paymentMethod) => $paymentMethod->id !== $defaultPaymentMethod->id);
// Get payment methods
return $paymentMethods->map(fn ($paymentMethod) => $paymentMethod->asStripePaymentMethod())->values()->all();
});
}
if (! $user->card_brand || ! $user->stripe_id || 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),
];
}
/**
* Update default payment method
*/
public function update(string $id): Response
{
$user = Auth::user();
// Check if is demo
abort_if(is_demo_account('howdy@hi5ve.digital'), 204, 'Done.');
// Update DefaultPayment Method
$user->updateDefaultPaymentMethod($id);
// Sync default payment method
$user->updateDefaultPaymentMethodFromStripe();
// Clear cached payment methods
cache_forget_many([
"payment-methods-user-{$user->id}",
"default-payment-methods-user-{$user->id}",
]);
return response('Done', 204);
}
/**
* Register new payment method for user
*/
public function store(RegisterNewPaymentMethodRequest $request): Response
{
// Get user
$user = Auth::user();
// Check if is demo
if (is_demo_account($user->email)) {
return response('Done', 201);
}
// Register new payment method
$this->stripe->registerNewPaymentMethod($request, $user);
return response('Done', 201);
}
/**
* Delete user payment method
*/
public function delete($id): Response
{
$user = Auth::user();
// Check if is demo
abort_if(is_demo_account($user->email), 204, 'Done.');
// Get payment method
$paymentMethod = $user->findPaymentMethod($id);
// Delete payment method
$paymentMethod->delete();
// Sync default payment method
$user->updateDefaultPaymentMethodFromStripe();
// Clear cached payment methods
cache_forget_many([
"payment-methods-user-{$user->id}",
"default-payment-methods-user-{$user->id}",
]);
return response('Done.', 204);
}
}

View File

@@ -1,67 +0,0 @@
<?php
namespace Domain\Payments\Notifications;
use Laravel\Cashier\Payment;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class ConfirmPayment extends Notification implements ShouldQueue
{
use Queueable;
/**
* The PaymentIntent identifier.
*
* @var string
*/
public $paymentId;
/**
* The payment amount.
*
* @var string
*/
public $amount;
/**
* Create a new payment confirmation notification.
*
* @param \Laravel\Cashier\Payment $payment
* @return void
*/
public function __construct(Payment $payment)
{
$this->paymentId = $payment->id;
$this->amount = $payment->amount();
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
$url = route('cashier.payment', ['id' => $this->paymentId]);
return (new MailMessage)
->subject(__('cashier.confirm_payment'))
->greeting(__('cashier.confirm_amount', ['amount' => $this->amount]))
->line(__('cashier.confirm_description'))
->action(__('cashier.confirm_button'), $url);
}
}

View File

@@ -1,30 +0,0 @@
<?php
namespace Domain\Payments\Requests;
use Illuminate\Foundation\Http\FormRequest;
class RegisterNewPaymentMethodRequest 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 [
'token' => 'required|string',
'default' => 'required|boolean',
];
}
}

View File

@@ -1,22 +0,0 @@
<?php
namespace Domain\Payments\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

@@ -1,34 +0,0 @@
<?php
namespace Domain\Payments\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

@@ -1,34 +0,0 @@
<?php
namespace Domain\Payments\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

@@ -1,27 +0,0 @@
<?php
namespace Domain\Plans\Controllers;
use Illuminate\Support\Facades\Cache;
use Domain\Plans\Resources\PricingCollection;
use Domain\Subscriptions\Services\StripeService;
class ActivePlansController
{
/**
* Get all active storage plans
*/
public function __invoke(): PricingCollection
{
// Get pricing from cache
$pricing = Cache::rememberForever('pricing', fn () => resolve(StripeService::class)->getActivePlans());
// Format pricing to collection
$collection = new PricingCollection($pricing);
// Sort and return pricing
return $collection
->sortBy('product.metadata.capacity')
->values()
->all();
}
}

View File

@@ -1,24 +0,0 @@
<?php
namespace Domain\Plans\Controllers;
use App\Users\Models\User;
use Laravel\Cashier\Subscription;
use App\Http\Controllers\Controller;
use App\Users\Resources\UsersCollection;
class PlanSubscribersController extends Controller
{
/**
* Get plan subscriptions
*/
public function __invoke(string $id): UsersCollection
{
$subscribers = Subscription::whereStripePlan($id)
->pluck('user_id');
$users = User::sortable()
->findMany($subscribers);
return new UsersCollection($users);
}
}

View File

@@ -1,98 +0,0 @@
<?php
namespace Domain\Plans\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use Domain\Plans\Resources\PlanResource;
use Domain\Plans\Resources\PlanCollection;
use Domain\Subscriptions\Services\StripeService;
class PlansController extends Controller
{
public function __construct(
private StripeService $stripe,
) {
}
/**
* Get all plans
*/
public function index(): Response
{
// Store or Get plans to cache
$plans = cache()
->rememberForever('plans', fn () => $this->stripe->getPlans());
return response(new PlanCollection($plans), 200);
}
/**
* Get plan record
*/
public function show(string $id): Response
{
// Store or Get plan to cache
$plan = cache()
->rememberForever("plan-$id", fn () => $this->stripe->getPlan($id));
return response(new PlanResource($plan), 200);
}
/**
* Create new plan
* TODO: store request
*/
public function store(Request $request): Response | PlanResource
{
if (is_demo()) {
$plan = cache()
->rememberForever('plan-starter-pack', fn () => $this->stripe->getPlan('starter-pack'));
return new PlanResource($plan);
}
$plan = new PlanResource(
$this->stripe->createPlan($request)
);
// Clear cached plans
cache_forget_many(['plans', 'pricing']);
return response($plan, 201);
}
/**
* Update plan attribute
*/
public function update(Request $request, string $id): Response
{
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.');
// Update plan
$this->stripe->updatePlan($request, $id);
// Clear cached plans
cache_forget_many(['plans', 'pricing', "plan-$id"]);
return response('Saved!', 201);
}
/**
* Delete plan
*/
public function delete($id): Response
{
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.');
// Delete plan
$this->stripe->deletePlan($id);
// Clear cached plans
cache_forget_many(['plans', 'pricing']);
return response('Done.', 204);
}
}

View File

@@ -1,22 +0,0 @@
<?php
namespace Domain\Plans\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class PlanCollection extends ResourceCollection
{
public $collects = PlanResource::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

@@ -1,40 +0,0 @@
<?php
namespace Domain\Plans\Resources;
use Laravel\Cashier\Cashier;
use Laravel\Cashier\Subscription;
use Illuminate\Http\Resources\Json\JsonResource;
class PlanResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
// Get subscribers
$subscriber_count = Subscription::where('stripe_plan', $this['plan']['id'])->where('stripe_status', 'active')->get();
return [
'data' => [
'id' => $this['plan']['id'],
'type' => 'plans',
'attributes' => [
'subscribers' => $subscriber_count->count(),
'status' => $this['plan']['active'] ? 1 : 0,
'name' => $this['product']['name'],
'description' => $this['product']['description'],
'price' => $this['plan']['amount'],
'price_formatted' => Cashier::formatAmount($this['plan']['amount']),
'capacity_formatted' => format_gigabytes($this['product']['metadata']['capacity']),
'capacity' => (int) $this['product']['metadata']['capacity'],
'created_at_formatted' => format_date($this['plan']['created']),
'created_at' => $this['plan']['created'],
],
],
];
}
}

View File

@@ -1,22 +0,0 @@
<?php
namespace Domain\Plans\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class PricingCollection extends ResourceCollection
{
public $collects = PricingResource::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

@@ -1,34 +0,0 @@
<?php
namespace Domain\Plans\Resources;
use Laravel\Cashier\Cashier;
use Domain\Subscriptions\Services\StripeService;
use Illuminate\Http\Resources\Json\JsonResource;
class PricingResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'data' => [
'id' => $this['plan']['id'],
'type' => 'plans',
'attributes' => [
'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' => config('cashier.currency'),
'tax_rates' => resolve(StripeService::class)->get_tax_rates($this['plan']['amount']),
],
],
];
}
}

View File

@@ -1,26 +0,0 @@
<?php
namespace Domain\Subscriptions\Controllers;
use Auth;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use Domain\Subscriptions\Services\StripeService;
/**
* Generate setup intent
*/
class GetSetupIntentController extends Controller
{
public function __construct(
public StripeService $stripe,
) {
}
public function __invoke(): Response
{
return response(
$this->stripe->getSetupIntent(Auth::user()),
201
);
}
}

View File

@@ -1,67 +0,0 @@
<?php
namespace Domain\Subscriptions\Controllers;
use App\Users\Models\User;
use Domain\Subscriptions\Services\StripeService;
use Laravel\Cashier\Http\Controllers\WebhookController as CashierController;
class StripeWebhookController extends CashierController
{
public function __construct(
public StripeService $stripe
) {
}
/**
* Handle a cancelled customer from a Stripe subscription.
*
* @param array $payload
* @return \Symfony\Component\HttpFoundation\Response
*/
public function handleCustomerSubscriptionDeleted($payload)
{
if ($user = $this->getUserByStripeId($payload['data']['object']['customer'])) {
$user->subscriptions->filter(fn ($subscription) => $subscription->stripe_id === $payload['data']['object']['id'])->each(function ($subscription) {
$subscription->markAsCancelled();
});
}
// Get user
$user = User::whereStripeId($payload['data']['object']['customer'])
->firstOrFail();
// Update storage capacity
$user
->settings()
->update([
'storage_capacity' => get_settings('storage_default'),
]);
return $this->successMethod();
}
/**
* Handle Invoice Payment Succeeded
*
* @param $payload
* @return \Symfony\Component\HttpFoundation\Response
*/
public function handleInvoicePaymentSucceeded($payload)
{
// Get user
$user = User::whereStripeId($payload['data']['object']['customer'])
->firstOrFail();
// Get requested plan
$plan = $this->stripe->getPlan($user->subscription('main')->stripe_plan);
// Update user storage limit
$user
->settings()
->update([
'storage_capacity' => $plan['product']['metadata']['capacity'],
]);
return $this->successMethod();
}
}

View File

@@ -1,31 +0,0 @@
<?php
namespace Domain\Subscriptions\Controllers;
use Auth;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;
class SubscriptionCancelController extends Controller
{
/**
* Cancel Subscription
*/
public function __invoke(): Response
{
$user = Auth::user();
// Check if is demo
if (is_demo_account($user->email)) {
return response('Done.', 204);
}
// Cancel subscription
$user->subscription('main')->cancel();
// Forget user subscription
Cache::forget("subscription-user-{$user->id}");
return response('Done.', 204);
}
}

View File

@@ -1,29 +0,0 @@
<?php
namespace Domain\Subscriptions\Controllers;
use Auth;
use App\Http\Controllers\Controller;
use App\Users\Resources\UserSubscription;
class SubscriptionDetailsController extends Controller
{
public function __invoke(): mixed
{
$user = Auth::user();
if (! $user->subscription('main')) {
return abort(204, "User don't have any subscription");
}
$slug = "subscription-user-{$user->id}";
if (cache()->has($slug)) {
return cache()->get($slug);
}
return cache()->rememberForever(
$slug,
fn () => new UserSubscription($user)
);
}
}

View File

@@ -1,31 +0,0 @@
<?php
namespace Domain\Subscriptions\Controllers;
use Auth;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;
class SubscriptionResumeController extends Controller
{
/**
* Resume Subscription
*/
public function __invoke(): Response
{
$user = Auth::user();
// Check if is demo
if (is_demo_account($user->email)) {
return response('Done.', 204);
}
// Resume subscription
$user->subscription('main')->resume();
// Forget user subscription
Cache::forget("subscription-user-{$user->id}");
return response('Done.', 204);
}
}

View File

@@ -1,58 +0,0 @@
<?php
namespace Domain\Subscriptions\Controllers;
use Auth;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;
use Domain\Subscriptions\Services\StripeService;
use Domain\Teams\Requests\StoreUpgradeAccountRequest;
/**
* Upgrade account to subscription
*/
class SubscriptionUpgradeController extends Controller
{
public function __construct(
public StripeService $stripe,
) {
}
public function __invoke(StoreUpgradeAccountRequest $request): Response
{
$user = Auth::user();
// Check if is demo
if (is_demo_account($user->email)) {
return response('Done.', 204);
}
// Forget user subscription
Cache::forget("subscription-user-{$user->id}");
// Get requested plan
$plan = $this->stripe->getPlan(
$request->input('plan.data.id')
);
// Set user billing
$user->setBilling(
$request->input('billing')
);
// Update stripe customer billing info
$this->stripe->updateCustomerDetails($user);
// Make subscription
$this->stripe->createOrReplaceSubscription($request, $user);
// Update user storage limit
$user
->settings()
->update([
'storage_capacity' => $plan['product']['metadata']['capacity'],
]);
return response('Done.', 204);
}
}

View File

@@ -1,55 +0,0 @@
<?php
namespace Domain\Subscriptions\Requests;
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' => 'sometimes|string|nullable',
'plan.data.attributes.name' => 'required|string',
'plan.data.attributes.price' => 'required|string',
'plan.data.id' => 'required|string',
'plan.data.type' => 'required|string',
];
}
}

View File

@@ -1,411 +0,0 @@
<?php
namespace Domain\Subscriptions\Services;
use Stripe;
use App\Users\Models\User;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Laravel\Cashier\Cashier;
use Illuminate\Support\Facades\Cache;
use Laravel\Cashier\Exceptions\IncompletePayment;
use Laravel\Cashier\Exceptions\PaymentActionRequired;
use Symfony\Component\HttpKernel\Exception\HttpException;
class StripeService
{
private \Cartalyst\Stripe\Stripe $stripe;
/**
* Stripe Service constructor.
*/
public function __construct()
{
$this->stripe = Stripe::make(config('cashier.secret'), '2020-03-02');
}
/**
* Get setup intent
*
* @param $user
* @return mixed
*/
public function getSetupIntent($user)
{
// Create stripe customer if not exist
$user->createOrGetStripeCustomer();
// Return setup intent
return $user->createSetupIntent();
}
/**
* Get tax rate ids
* @return array
*/
public function getTaxRates()
{
return $this->stripe
->taxRates()
->all()['data'];
}
/**
* Get plan tax rates
*
* @param $amount
* @return array
*/
public function get_tax_rates($amount): array
{
$rates_public = [];
foreach ($this->getTaxRates() as $rate) {
// Continue when is not active
if (! $rate['active']) {
continue;
}
// Calculate tax
$tax = $amount * ($rate['percentage'] / 100);
array_push($rates_public, [
'id' => $rate['id'],
'active' => $rate['active'],
'country' => $rate['country'],
'percentage' => $rate['percentage'],
'plan_price_formatted' => Cashier::formatAmount(round($amount + $tax)),
]);
}
return $rates_public;
}
/**
* Get default payment option or set new default payment
*
* @param $request
* @param $user
* @return mixed
*/
public function getOrSetDefaultPaymentMethod($request, $user)
{
// Check payment method
if (! $request->has('payment.meta.pm') && $user->hasDefaultPaymentMethod()) {
// Get default payment
return $user->defaultPaymentMethod()->paymentMethod;
}
// Clear cached payment methods
cache_forget_many([
'payment-methods-user-' . $user->id,
'default-payment-methods-user-' . $user->id,
]);
if ($request->has('payment.meta.pm') && $user->hasDefaultPaymentMethod()) {
// Set new payment
return $user->addPaymentMethod($request->input('payment.meta.pm'))->paymentMethod;
} elseif ($request->has('payment.meta.pm') && ! $user->hasDefaultPaymentMethod()) {
// Set new payment
return $user->updateDefaultPaymentMethod($request->input('payment.meta.pm'))->paymentMethod;
}
throw new HttpException(400, 'Something went wrong.');
}
/**
* Register new payment method
*
* @param $request
* @param $user
*/
public function registerNewPaymentMethod($request, $user): void
{
// Clear cached payment methods
cache_forget_many([
'payment-methods-user-' . $user->id,
'default-payment-methods-user-' . $user->id,
]);
// Set new payment method
$user->addPaymentMethod($request->token)->paymentMethod;
// Set new default payment
if ($request->default) {
$user->updateDefaultPaymentMethod($request->token)->paymentMethod;
}
}
/**
* Create new subscription or replace by new subscription
*
* @param $request
* @param $user
*/
public function createOrReplaceSubscription($request, $user): void
{
try {
// Get payment method
$paymentMethod = $this->getOrSetDefaultPaymentMethod($request, $user);
// Check if user have subscription
if ($user->subscribed('main')) {
// Change subscription plan
$user->subscription('main')->skipTrial()->swap($request->input('plan.data.id'));
} else {
// Create subscription
$user->newSubscription('main', $request->input('plan.data.id'))->create($paymentMethod);
}
} catch (IncompletePayment $exception) {
if ($exception instanceof PaymentActionRequired) {
$cashier_route = route('cashier.payment', [$exception->payment->id, 'redirect' => url('/settings/subscription')]);
throw new HttpException(402, $cashier_route);
}
throw new HttpException(400, $exception->getMessage());
}
}
/**
* Update customer details
*
* @param $user
*/
public function updateCustomerDetails($user)
{
$user->updateStripeCustomer([
'name' => $user->settings->name,
'phone' => $user->settings->phone_number,
'address' => [
'line1' => $user->settings->address,
'city' => $user->settings->city,
'country' => $user->settings->country,
'postal_code' => $user->settings->postal_code,
'state' => $user->settings->state,
],
'preferred_locales' => [
$user->settings->country, 'en',
],
]);
}
/**
* Get all plans
*
* @return mixed
*/
public function getPlans()
{
// Get stripe plans
$stripe_plans = $this->stripe->plans()->all([
'limit' => 100,
]);
// Plans container
$plans = [];
foreach ($stripe_plans['data'] as $plan) {
// Get stripe product
$product = $this->stripe->products()->find($plan['product']);
// Push data to $plan container
if ($product['active'] && isset($product['metadata']['capacity'])) {
array_push($plans, [
'plan' => $plan,
'product' => $product,
]);
}
}
return $plans;
}
/**
* Get all active plans
*
* @return mixed
*/
public function getActivePlans()
{
// Get stripe plans
$stripe_plans = $this->stripe->plans()->all([
'limit' => 100,
]);
// Plans container
$plans = [];
foreach ($stripe_plans['data'] as $plan) {
if ($plan['active']) {
// Get stripe product
$product = $this->stripe->products()->find($plan['product']);
// Push data to $plan container
if ($product['active'] && isset($product['metadata']['capacity'])) {
array_push($plans, [
'plan' => $plan,
'product' => $product,
]);
}
}
}
return $plans;
}
/**
* Get plan details
*
* @param $id
* @return mixed
*/
public function getPlan($id)
{
if (Cache::has("plan-$id")) {
return Cache::get("plan-$id");
}
return Cache::rememberForever("plan-$id", function () use ($id) {
$plan = $this->stripe->plans()->find($id);
$product = $this->stripe->products()->find($plan['product']);
return [
'plan' => $plan,
'product' => $product,
];
});
}
/**
* Create plan
*
* @param $data
* @return mixed
*/
public function createPlan($data)
{
if ($data instanceof Request) {
$plan = [
'name' => $data->input('attributes.name'),
'description' => $data->input('attributes.description'),
'price' => $data->input('attributes.price'),
'capacity' => $data->input('attributes.capacity'),
];
} else {
$plan = [
'name' => $data['attributes']['name'],
'description' => $data['attributes']['description'],
'price' => $data['attributes']['price'],
'capacity' => $data['attributes']['capacity'],
];
}
$product = $this->stripe->products()->create([
'name' => $plan['name'],
'description' => $plan['description'],
'metadata' => [
'capacity' => $plan['capacity'],
],
]);
$plan = $this->stripe->plans()->create([
'id' => Str::slug($plan['name']),
'amount' => $plan['price'],
'currency' => config('cashier.currency'),
'interval' => 'month',
'product' => $product['id'],
]);
return compact('plan', 'product');
}
/**
* Update plan
*
* @param $request
* @param $id
*/
public function updatePlan($request, $id)
{
$plan_colls = ['is_active', 'price'];
$product_colls = ['name', 'description', 'capacity'];
$plan = $this->stripe->plans()->find($id);
// Update product
if (in_array($request->name, $product_colls)) {
if ($request->name === 'capacity') {
$this->stripe->products()->update($plan['product'], ['metadata' => ['capacity' => $request->value]]);
}
if ($request->name === 'name') {
$this->stripe->products()->update($plan['product'], ['name' => $request->value]);
}
if ($request->name === 'description') {
$this->stripe->products()->update($plan['product'], ['description' => $request->value]);
}
}
// Update plan
if (in_array($request->name, $plan_colls)) {
if ($request->name === 'is_active') {
$this->stripe->plans()->update($id, ['active' => $request->value]);
}
}
}
/**
* Delete plan
*
* @param $slug
*/
public function deletePlan($slug)
{
$this
->stripe
->plans()
->delete($slug);
}
/**
* Get all user invoices
*
* @param $user
* @return mixed
*/
public function getUserInvoices($user)
{
return $user
->invoices();
}
/**
* Get user invoice by id
*
* @param $customer
* @param $id
* @return \Laravel\Cashier\Invoice|null
*/
public function getUserInvoice($customer, $id)
{
return User::whereStripeId($customer)
->firstOrFail()
->findInvoice($id);
}
/**
* Get all invoices
*
* @return mixed
*/
public function getInvoices()
{
return $this
->stripe
->invoices()
->all([
'limit' => 20,
]);
}
}

View File

@@ -1,42 +0,0 @@
<?php
namespace Domain\Subscriptions\Traits;
use App\Users\Models\UserSettings;
use Domain\Subscriptions\Services\StripeService;
trait Subscription
{
/**
* Get tax rate id for user
*/
public function userTaxRates(): array
{
// Get tax rates
$rates = collect(
resolve(StripeService::class)->getTaxRates()
);
// Find tax rate
$user_tax_rate = $rates->first(fn ($item) => $item['country'] === $this->settings->country && $item['active']);
return $user_tax_rate ? [$user_tax_rate['id']] : [];
}
/**
* Set user billing info into user settings table
*/
public function setBilling($billing): UserSettings
{
$this->settings()->update([
'address' => $billing['billing_address'],
'city' => $billing['billing_city'],
'country' => $billing['billing_country'],
'name' => $billing['billing_name'],
'phone_number' => $billing['billing_phone_number'],
'postal_code' => $billing['billing_postal_code'],
'state' => $billing['billing_state'],
]);
return $this->settings;
}
}

View File

@@ -6,6 +6,7 @@ use Domain\Zip\Actions\ZipAction;
use App\Http\Controllers\Controller;
use Domain\Traffic\Actions\RecordDownloadAction;
use Domain\Zip\Actions\GetItemsListFromUrlParamAction;
use ZipStream\ZipStream;
class ZipController extends Controller
{
@@ -18,7 +19,7 @@ class ZipController extends Controller
public function __invoke(
Request $request,
): \ZipStream\ZipStream {
): ZipStream {
// Get list of folders and files from requested url parameter
list($folders, $files) = ($this->getItemsListFromUrlParam)(auth()->id());

View File

@@ -32,6 +32,7 @@ class UserAccountTest extends TestCase
Storage::disk('local')
->assertExists('files/' . User::first()->id);
}
/**
* todo: finish test
*/
@@ -140,9 +141,6 @@ class UserAccountTest extends TestCase
'type' => 'user',
'attributes' => [
'storage_capacity' => '5',
'subscription' => false,
'incomplete_payment' => null,
'stripe_customer' => false,
'email' => $user->email,
'role' => $user->role,
'two_factor_authentication' => false,

View File

@@ -59,7 +59,7 @@ class AdminTest extends TestCase
}
/**
* @test
* todo: complete test
*/
public function it_get_non_existed_user_subscription()
{

View File

@@ -27,14 +27,6 @@ class DashboardTest extends TestCase
'value' => 'Regular',
]);
DB::table('subscriptions')
->insert([
'user_id' => $user->id,
'name' => 'main',
'stripe_id' => 'sub_Hp4jgdIpPDDWXw',
'stripe_status' => 'active',
]);
$this
->actingAs($user)
->getJson('/api/admin/dashboard')
@@ -44,7 +36,6 @@ class DashboardTest extends TestCase
'app_version' => config('vuefilemanager.version'),
'total_users' => 1,
'total_used_space' => '2.00MB',
'total_premium_users' => 1,
]);
}

View File

@@ -1,34 +0,0 @@
<?php
namespace Tests\Domain\Invoices;
use Tests\TestCase;
use App\Users\Models\User;
use Laravel\Sanctum\Sanctum;
class UserInvoicesTest extends TestCase
{
/**
*
*/
public function it_get_user_invoices()
{
$user = User::factory(User::class)
->create($this->user);
Sanctum::actingAs($user);
$this->postJson('/api/user/subscription/upgrade', [
'billing' => $this->billing,
'plan' => $this->plan,
'payment' => [
'type' => 'stripe',
],
])->assertStatus(204);
$this->getJson('/api/user/subscription/invoices')
->assertStatus(200)
->assertJsonFragment([
'customer' => $this->user['stripe_id'],
]);
}
}

View File

@@ -1,189 +0,0 @@
<?php
namespace Tests\Domain\Plans;
use Tests\TestCase;
use App\Users\Models\User;
use Illuminate\Support\Str;
use Laravel\Sanctum\Sanctum;
class AdminPlansTest extends TestCase
{
/**
*
*/
public function it_get_single_plan_from_admin()
{
$admin = User::factory(User::class)
->create(['role' => 'admin']);
$this
->actingAs($admin)
->getJson('/api/admin/plans/' . $this->plan['data']['id'])
->assertStatus(200);
}
/**
*
*/
public function it_create_single_plan_from_admin()
{
$admin = User::factory(User::class)
->create(['role' => 'admin']);
$plan_name = 'test-plan-' . Str::random(16);
$this
->actingAs($admin)
->postJson('/api/admin/plans', [
'type' => 'plan',
'attributes' => [
'name' => $plan_name,
'price' => (string) rand(1, 99),
'description' => 'Some random description',
'capacity' => rand(1, 999),
],
])
->assertStatus(201)
->assertJsonFragment([
'name' => $plan_name,
]);
}
/**
*
*/
public function it_update_single_plan_from_admin()
{
$admin = User::factory(User::class)
->create(['role' => 'admin']);
Sanctum::actingAs($admin);
$plan_name = 'test-plan-' . Str::random(16);
$this->postJson('/api/admin/plans', [
'type' => 'plan',
'attributes' => [
'name' => $plan_name,
'price' => (string) rand(1, 99),
'description' => 'Some random description',
'capacity' => rand(1, 999),
],
])
->assertStatus(201)
->assertJsonFragment([
'name' => $plan_name,
]);
$this->patchJson('/api/admin/plans/' . strtolower($plan_name), [
'name' => 'description',
'value' => 'updated description',
])->assertStatus(201);
}
/**
*
*/
public function it_get_subscribers_from_plan_from_admin()
{
$user = User::factory(User::class)
->create($this->user);
$this
->actingAs($user)
->postJson('/api/user/subscription/upgrade', [
'billing' => $this->billing,
'plan' => $this->plan,
'payment' => [
'type' => 'stripe',
],
])->assertStatus(204);
$admin = User::factory(User::class)
->create(['role' => 'admin']);
$this
->actingAs($admin)
->getJson('/api/admin/plans/' . $this->plan['data']['id'] . '/subscribers')
->assertStatus(200)
->assertJsonFragment([
'id' => $user->id,
]);
}
/**
*
*/
public function it_get_all_invoices_from_admin()
{
$admin = User::factory(User::class)
->create(['role' => 'admin']);
$this
->actingAs($admin)
->getJson('/api/admin/invoices')
->assertStatus(200);
}
/**
*
*/
public function it_get_single_user_invoice_page_from_admin()
{
$user = User::factory(User::class)
->create($this->user);
$invoices = $this
->actingAs($user)
->getJson('/api/user/subscription/invoices')
->assertStatus(200)
->assertJsonFragment([
'customer' => $this->user['stripe_id'],
]);
$admin = User::factory(User::class)
->create(['role' => 'admin']);
$invoice_id = json_decode($invoices->content(), true)['data'][0]['data']['id'];
$this
->actingAs($admin)
->get("/invoice/{$this->user['stripe_id']}/$invoice_id")
->assertStatus(200)
->assertSee('Invoice');
}
/**
*
*/
public function it_get_user_invoices_from_admin()
{
$user = User::factory(User::class)
->create($this->user);
$admin = User::factory(User::class)
->create(['role' => 'admin']);
$this
->actingAs($admin)
->getJson("/api/admin/users/$user->id/invoices")
->assertStatus(200)
->assertJsonFragment([
'customer' => $this->user['stripe_id'],
]);
}
/**
*
*/
public function it_get_all_plans_from_admin()
{
$admin = User::factory(User::class)
->create(['role' => 'admin']);
$this
->actingAs($admin)
->getJson('/api/admin/plans')
->assertStatus(200);
}
}

View File

@@ -1,49 +0,0 @@
<?php
namespace Tests\Domain\Plans;
use Tests\TestCase;
use App\Users\Models\User;
use Illuminate\Support\Str;
use Laravel\Sanctum\Sanctum;
class PlansTest extends TestCase
{
/**
*
*/
public function it_get_all_plans_for_index_page()
{
$this->getJson('/api/pricing')
->assertStatus(200);
}
/**
*
*/
public function it_delete_single_plan()
{
$admin = User::factory(User::class)
->create(['role' => 'admin']);
Sanctum::actingAs($admin);
$plan_name = 'test-plan-' . Str::random(16);
$this->postJson('/api/admin/plans', [
'type' => 'plan',
'attributes' => [
'name' => $plan_name,
'price' => (string) rand(1, 99),
'description' => 'Some random description',
'capacity' => rand(1, 999),
],
])
->assertStatus(201)
->assertJsonFragment([
'name' => $plan_name,
]);
$this->deleteJson('/api/admin/plans/' . strtolower($plan_name))
->assertStatus(204);
}
}

View File

@@ -1,37 +0,0 @@
<?php
namespace Tests\Domain\Plans;
use Tests\TestCase;
use Illuminate\Support\Str;
class SetupWizardPlansTest extends TestCase
{
/**
*
*/
public function it_store_stripe_plans_via_setup_wizard()
{
$this->postJson('/api/setup/stripe-plans', [
'plans' => [
[
'type' => 'plan',
'attributes' => [
'name' => 'test-plan-' . Str::random(),
'price' => (string) rand(1, 99),
'description' => 'Some random description',
'capacity' => rand(1, 999),
],
],
[
'type' => 'plan',
'attributes' => [
'name' => 'test-plan-' . Str::random(),
'price' => (string) rand(1, 99),
'description' => 'Some random description',
'capacity' => rand(1, 999),
],
],
],
])->assertStatus(204);
}
}

View File

@@ -136,7 +136,7 @@ class SettingsTest extends TestCase
}
/**
* @test
* TODO: complete test
*/
public function it_set_stripe()
{

View File

@@ -1,53 +0,0 @@
<?php
namespace Tests\Domain\Subscriptions;
use Tests\TestCase;
use App\Users\Models\User;
class AdminSubscriptionTest extends TestCase
{
/**
*
*/
public function it_get_user_subscription_from_admin()
{
$user = User::factory(User::class)
->create($this->user);
$this
->actingAs($user)
->postJson('/api/user/subscription/upgrade', [
'billing' => $this->billing,
'plan' => $this->plan,
'payment' => [
'type' => 'stripe',
],
])->assertStatus(204);
$admin = User::factory(User::class)
->create(['role' => 'admin']);
$this
->actingAs($admin)
->getJson("/api/admin/users/$user->id/subscription")
->assertStatus(200)
->assertExactJson([
'data' => [
'id' => 'business-pack',
'type' => 'subscription',
'attributes' => [
'incomplete' => false,
'active' => true,
'canceled' => false,
'name' => 'Business Packs',
'capacity' => 1000,
'capacity_formatted' => '1TB',
'slug' => 'business-pack',
'canceled_at' => format_date(now(), '%d. %B. %Y'),
'created_at' => format_date(now(), '%d. %B. %Y'),
'ends_at' => format_date(now()->addMonth(), '%d. %B. %Y'),
],
],
]);
}
}

View File

@@ -1,199 +0,0 @@
<?php
namespace Tests\Domain\Subscriptions;
use Tests\TestCase;
use App\Users\Models\User;
use Laravel\Sanctum\Sanctum;
class SubscriptionTest extends TestCase
{
private User $user;
private array $plan;
private array $billing;
public function __construct()
{
parent::__construct();
// Define test user
$this->user = [
'email' => 'howdy@hi5ve.digital',
'stripe_id' => 'cus_HgbhvNCbSwV8Qg',
'card_brand' => 'visa',
'card_last_four' => 4242,
];
// Define test plan to subscribe
$this->plan = [
'data' => [
'id' => 'business-pack',
'type' => 'plans',
'attributes' => [
'name' => 'Business Packs',
'description' => 'When your business start grow up.',
'price' => '$44.99',
'capacity' => 1000,
'capacity_formatted' => '1TB',
'currency' => 'USD',
'tax_rates' => [],
],
],
];
// Define test billing to subscribe
$this->billing = [
'billing_address' => '2794 Alfreda Mount Suite 467 East Crystalberg',
'billing_city' => 'Christianfort',
'billing_country' => 'SK',
'billing_name' => 'Heidi Romaguera PhD',
'billing_phone_number' => '+421',
'billing_postal_code' => '59445',
'billing_state' => 'SK',
];
}
/**
*
*/
public function it_get_setup_intent()
{
$user = User::factory(User::class)
->create();
$this
->actingAs($user)
->getJson('/api/user/subscription/setup-intent')
->assertStatus(201)
->assertJsonFragment([
'object' => 'setup_intent',
]);
$this->assertDatabaseMissing('users', [
'stripe_id' => null,
]);
}
/**
*
*/
public function it_upgrade_plan()
{
$user = User::factory(User::class)
->create($this->user);
$this
->actingAs($user)
->postJson('/api/user/subscription/upgrade', [
'billing' => $this->billing,
'plan' => $this->plan,
'payment' => [
'type' => 'stripe',
],
])->assertStatus(204);
$this->assertDatabaseHas('subscriptions', [
'stripe_status' => 'active',
]);
$this->assertDatabaseHas('user_settings', [
'storage_capacity' => 1000,
]);
}
/**
*
*/
public function it_cancel_subscription()
{
$user = User::factory(User::class)
->create($this->user);
Sanctum::actingAs($user);
$this->postJson('/api/user/subscription/upgrade', [
'billing' => $this->billing,
'plan' => $this->plan,
'payment' => [
'type' => 'stripe',
],
])->assertStatus(204);
$this->postJson('/api/user/subscription/cancel')
->assertStatus(204);
$this->assertDatabaseMissing('subscriptions', [
'ends_at' => null,
]);
}
/**
*
*/
public function it_resume_subscription()
{
$user = User::factory(User::class)
->create($this->user);
Sanctum::actingAs($user);
$this->postJson('/api/user/subscription/upgrade', [
'billing' => $this->billing,
'plan' => $this->plan,
'payment' => [
'type' => 'stripe',
],
])->assertStatus(204);
$this->postJson('/api/user/subscription/cancel')
->assertStatus(204);
$this->postJson('/api/user/subscription/resume')
->assertStatus(204);
$this->assertDatabaseHas('subscriptions', [
'ends_at' => null,
]);
}
/**
*
*/
public function it_get_user_subscription_details()
{
$user = User::factory(User::class)
->create($this->user);
Sanctum::actingAs($user);
$this->postJson('/api/user/subscription/upgrade', [
'billing' => $this->billing,
'plan' => $this->plan,
'payment' => [
'type' => 'stripe',
],
])->assertStatus(204);
$this->getJson('/api/user/subscription')
->assertStatus(200)
->assertExactJson([
'data' => [
'id' => 'business-pack',
'type' => 'subscription',
'attributes' => [
'incomplete' => false,
'active' => true,
'canceled' => false,
'name' => 'Business Packs',
'capacity' => 1000,
'capacity_formatted' => '1TB',
'slug' => 'business-pack',
'canceled_at' => format_date(now(), '%d. %B. %Y'),
'created_at' => format_date(now(), '%d. %B. %Y'),
'ends_at' => format_date(now()->addMonth(), '%d. %B. %Y'),
],
],
]);
}
}