diff --git a/app/Http/Controllers/ClientSubscriptionController.php b/app/Http/Controllers/ClientSubscriptionController.php new file mode 100644 index 000000000000..bf0a9b39b167 --- /dev/null +++ b/app/Http/Controllers/ClientSubscriptionController.php @@ -0,0 +1,410 @@ +client_subscription_repo = $client_subscription_repo; + } + + /** + * Show the list of ClientSubscriptions. + * + * @return Response + * + * @OA\Get( + * path="/api/v1/client_subscriptions", + * operationId="getClientSubscriptions", + * tags={"client_subscriptions"}, + * summary="Gets a list of client_subscriptions", + * description="Lists client_subscriptions.", + * + * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), + * @OA\Parameter(ref="#/components/parameters/X-Api-Token"), + * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), + * @OA\Parameter(ref="#/components/parameters/include"), + * @OA\Response( + * response=200, + * description="A list of client_subscriptions", + * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * @OA\JsonContent(ref="#/components/schemas/ClientSubscription"), + * ), + * @OA\Response( + * response=422, + * description="Validation error", + * @OA\JsonContent(ref="#/components/schemas/ValidationError"), + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) + */ + + public function index(): \Illuminate\Http\Response + { + $client_subscriptions = ClientSubscription::query()->company(); + + return $this->listResponse($client_subscriptions); + } + + /** + * Show the form for creating a new resource. + * + * @param CreateClientSubscriptionRequest $request The request + * + * @return Response + * + * + * @OA\Get( + * path="/api/v1/client_subscriptions/create", + * operationId="getClientSubscriptionsCreate", + * tags={"client_subscriptions"}, + * summary="Gets a new blank client_subscriptions object", + * description="Returns a blank object with default values", + * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), + * @OA\Parameter(ref="#/components/parameters/X-Api-Token"), + * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), + * @OA\Parameter(ref="#/components/parameters/include"), + * @OA\Response( + * response=200, + * description="A blank client_subscriptions object", + * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * @OA\JsonContent(ref="#/components/schemas/ClientSubscription"), + * ), + * @OA\Response( + * response=422, + * description="Validation error", + * @OA\JsonContent(ref="#/components/schemas/ValidationError"), + * + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) + */ + public function create(CreateClientSubscriptionRequest $request): \Illuminate\Http\Response + { + $client_subscription = ClientSubscriptionFactory::create(auth()->user()->company()->id, auth()->user()->id); + + return $this->itemResponse($client_subscription); + } + + /** + * Store a newly created resource in storage. + * + * @param StoreClientSubscriptionRequest $request The request + * + * @return Response + * + * + * @OA\Post( + * path="/api/v1/client_subscriptions", + * operationId="storeClientSubscription", + * tags={"client_subscriptions"}, + * summary="Adds a client_subscriptions", + * description="Adds an client_subscriptions to the system", + * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), + * @OA\Parameter(ref="#/components/parameters/X-Api-Token"), + * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), + * @OA\Parameter(ref="#/components/parameters/include"), + * @OA\Response( + * response=200, + * description="Returns the saved client_subscriptions object", + * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * @OA\JsonContent(ref="#/components/schemas/ClientSubscription"), + * ), + * @OA\Response( + * response=422, + * description="Validation error", + * @OA\JsonContent(ref="#/components/schemas/ValidationError"), + * + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) + */ + public function store(StoreClientSubscriptionRequest $request): \Illuminate\Http\Response + { + $client_subscription = $this->client_subscription_repo->save($request->all(), ClientSubscriptionFactory::create(auth()->user()->company()->id, auth()->user()->id)); + + event(new ClientsubscriptionWasCreated($client_subscription, $client_subscription->company, Ninja::eventVars())); + + return $this->itemResponse($client_subscription); + } + + /** + * Display the specified resource. + * + * @param ShowClientSubscriptionRequest $request The request + * @param Invoice $client_subscription The invoice + * + * @return Response + * + * + * @OA\Get( + * path="/api/v1/client_subscriptions/{id}", + * operationId="showClientSubscription", + * tags={"client_subscriptions"}, + * summary="Shows an client_subscriptions", + * description="Displays an client_subscriptions by id", + * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), + * @OA\Parameter(ref="#/components/parameters/X-Api-Token"), + * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), + * @OA\Parameter(ref="#/components/parameters/include"), + * @OA\Parameter( + * name="id", + * in="path", + * description="The ClientSubscription Hashed ID", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="Returns the ClientSubscription object", + * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * @OA\JsonContent(ref="#/components/schemas/ClientSubscription"), + * ), + * @OA\Response( + * response=422, + * description="Validation error", + * @OA\JsonContent(ref="#/components/schemas/ValidationError"), + * + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) + */ + public function show(ShowClientSubscriptionRequest $request, ClientSubscription $client_subscription): \Illuminate\Http\Response + { + return $this->itemResponse($client_subscription); + } + + /** + * Show the form for editing the specified resource. + * + * @param EditClientSubscriptionRequest $request The request + * @param Invoice $client_subscription The invoice + * + * @return Response + * + * @OA\Get( + * path="/api/v1/client_subscriptions/{id}/edit", + * operationId="editClientSubscription", + * tags={"client_subscriptions"}, + * summary="Shows an client_subscriptions for editting", + * description="Displays an client_subscriptions by id", + * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), + * @OA\Parameter(ref="#/components/parameters/X-Api-Token"), + * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), + * @OA\Parameter(ref="#/components/parameters/include"), + * @OA\Parameter( + * name="id", + * in="path", + * description="The ClientSubscription Hashed ID", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="Returns the invoice object", + * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * @OA\JsonContent(ref="#/components/schemas/ClientSubscription"), + * ), + * @OA\Response( + * response=422, + * description="Validation error", + * @OA\JsonContent(ref="#/components/schemas/ValidationError"), + * + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) + */ + public function edit(EditClientSubscriptionRequest $request, ClientSubscription $client_subscription): \Illuminate\Http\Response + { + return $this->itemResponse($client_subscription); + } + + /** + * Update the specified resource in storage. + * + * @param UpdateClientSubscriptionRequest $request The request + * @param ClientSubscription $client_subscription The invoice + * + * @return Response + * + * + * @OA\Put( + * path="/api/v1/client_subscriptions/{id}", + * operationId="updateClientSubscription", + * tags={"client_subscriptions"}, + * summary="Updates an client_subscriptions", + * description="Handles the updating of an client_subscriptions by id", + * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), + * @OA\Parameter(ref="#/components/parameters/X-Api-Token"), + * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), + * @OA\Parameter(ref="#/components/parameters/include"), + * @OA\Parameter( + * name="id", + * in="path", + * description="The ClientSubscription Hashed ID", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="Returns the client_subscriptions object", + * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * @OA\JsonContent(ref="#/components/schemas/ClientSubscription"), + * ), + * @OA\Response( + * response=422, + * description="Validation error", + * @OA\JsonContent(ref="#/components/schemas/ValidationError"), + * + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) + */ + public function update(UpdateClientSubscriptionRequest $request, ClientSubscription $client_subscription) + { + if ($request->entityIsDeleted($client_subscription)) { + return $request->disallowUpdate(); + } + + $client_subscription = $this->client_subscription_repo->save($request->all(), $client_subscription); + + return $this->itemResponse($client_subscription); + } + + /** + * Remove the specified resource from storage. + * + * @param DestroyClientSubscriptionRequest $request + * @param ClientSubscription $invoice + * + * @return Response + * + * @throws \Exception + * @OA\Delete( + * path="/api/v1/client_subscriptions/{id}", + * operationId="deleteClientSubscription", + * tags={"client_subscriptions"}, + * summary="Deletes a client_subscriptions", + * description="Handles the deletion of an client_subscriptions by id", + * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), + * @OA\Parameter(ref="#/components/parameters/X-Api-Token"), + * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), + * @OA\Parameter(ref="#/components/parameters/include"), + * @OA\Parameter( + * name="id", + * in="path", + * description="The ClientSubscription Hashed ID", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="Returns a HTTP status", + * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * ), + * @OA\Response( + * response=422, + * description="Validation error", + * @OA\JsonContent(ref="#/components/schemas/ValidationError"), + * + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) + */ + public function destroy(DestroyClientSubscriptionRequest $request, ClientSubscription $client_subscription): \Illuminate\Http\Response + { + $this->client_subscription_repo->delete($client_subscription); + + return $this->itemResponse($client_subscription->fresh()); + } +} diff --git a/app/Http/Controllers/OpenAPI/BillingSubscription.php b/app/Http/Controllers/OpenAPI/BillingSubscription.php index c618f39c85a2..fad9b1eac32f 100644 --- a/app/Http/Controllers/OpenAPI/BillingSubscription.php +++ b/app/Http/Controllers/OpenAPI/BillingSubscription.php @@ -26,7 +26,10 @@ * @OA\Property(property="plan_map", type="string", example="1", description="map describing the available upgrade/downgrade plans for this subscription"), * @OA\Property(property="refund_period", type="integer", example="2", description="______"), * @OA\Property(property="webhook_configuration", type="string", example="2", description="______"), - * @OA\Property(property="is_deleted", type="boolean", example="2", description="______"), + * @OA\Property(property="is_deleted", type="boolean", example="true", description="______"), + * @OA\Property(property="archived_at", type="number", format="integer", example="1434342123", description="Timestamp"), + * @OA\Property(property="created_at", type="number", format="integer", example="134341234234", description="Timestamp"), + * @OA\Property(property="updated_at", type="number", format="integer", example="134341234234", description="Timestamp"), * ) */ \ No newline at end of file diff --git a/app/Http/Controllers/OpenAPI/ClientSubscription.php b/app/Http/Controllers/OpenAPI/ClientSubscription.php new file mode 100644 index 000000000000..9ea5beae440d --- /dev/null +++ b/app/Http/Controllers/OpenAPI/ClientSubscription.php @@ -0,0 +1,19 @@ +user()->can('create', ClientSubscription::class); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + // + ]; + } +} diff --git a/app/Http/Requests/ClientSubscription/DestroyClientSubscriptionRequest.php b/app/Http/Requests/ClientSubscription/DestroyClientSubscriptionRequest.php new file mode 100644 index 000000000000..609b88bcf1e6 --- /dev/null +++ b/app/Http/Requests/ClientSubscription/DestroyClientSubscriptionRequest.php @@ -0,0 +1,40 @@ +user()->can('edit', $this->client_subscription); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + // + ]; + } +} diff --git a/app/Http/Requests/ClientSubscription/EditClientSubscriptionRequest.php b/app/Http/Requests/ClientSubscription/EditClientSubscriptionRequest.php new file mode 100644 index 000000000000..bf152757d735 --- /dev/null +++ b/app/Http/Requests/ClientSubscription/EditClientSubscriptionRequest.php @@ -0,0 +1,40 @@ +user()->can('edit', $this->client_subscription); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + // + ]; + } +} diff --git a/app/Http/Requests/ClientSubscription/ShowClientSubscriptionRequest.php b/app/Http/Requests/ClientSubscription/ShowClientSubscriptionRequest.php new file mode 100644 index 000000000000..bf2430e7ba5e --- /dev/null +++ b/app/Http/Requests/ClientSubscription/ShowClientSubscriptionRequest.php @@ -0,0 +1,40 @@ +user()->can('view', $this->client_subscription); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + // + ]; + } +} diff --git a/app/Http/Requests/ClientSubscription/StoreClientSubscriptionRequest.php b/app/Http/Requests/ClientSubscription/StoreClientSubscriptionRequest.php new file mode 100644 index 000000000000..5c29cd1a44a5 --- /dev/null +++ b/app/Http/Requests/ClientSubscription/StoreClientSubscriptionRequest.php @@ -0,0 +1,38 @@ +user()->can('create', ClientSubscription::class); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return []; + } +} diff --git a/app/Http/Requests/ClientSubscription/UpdateClientSubscriptionRequest.php b/app/Http/Requests/ClientSubscription/UpdateClientSubscriptionRequest.php new file mode 100644 index 000000000000..47f989631d8b --- /dev/null +++ b/app/Http/Requests/ClientSubscription/UpdateClientSubscriptionRequest.php @@ -0,0 +1,42 @@ +user()->can('edit', $this->client_subscription); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + // + ]; + } +} diff --git a/app/Http/Requests/Request.php b/app/Http/Requests/Request.php index df4edd1d94b3..a67b610c70d8 100644 --- a/app/Http/Requests/Request.php +++ b/app/Http/Requests/Request.php @@ -70,6 +70,10 @@ class Request extends FormRequest public function decodePrimaryKeys($input) { + if (array_key_exists('subscription_id', $input) && is_string($input['subscription_id'])) { + $input['subscription_id'] = $this->decodePrimaryKey($input['subscription_id']); + } + if (array_key_exists('assigned_user_id', $input) && is_string($input['assigned_user_id'])) { $input['assigned_user_id'] = $this->decodePrimaryKey($input['assigned_user_id']); } diff --git a/app/Models/ClientSubscription.php b/app/Models/ClientSubscription.php index ac7000cea2c0..bf38456dbc53 100644 --- a/app/Models/ClientSubscription.php +++ b/app/Models/ClientSubscription.php @@ -9,13 +9,47 @@ * @license https://opensource.org/licenses/AAL */ - namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; -use Illuminate\Database\Eloquent\Model; -class ClientSubscription extends Model +class ClientSubscription extends BaseModel { use HasFactory; + + protected $fillable = [ + // 'subscription_id', + // 'recurring_invoice_id', + // 'client_id', + // 'trial_started', + // 'trial_ends', + // 'is_deleted', + ]; + + protected $casts = [ + 'is_deleted' => 'boolean', + 'updated_at' => 'timestamp', + 'created_at' => 'timestamp', + 'deleted_at' => 'timestamp', + ]; + + public function company(): \Illuminate\Database\Eloquent\Relations\BelongsTo + { + return $this->belongsTo(Company::class); + } + + public function recurring_invoice(): \Illuminate\Database\Eloquent\Relations\BelongsTo + { + return $this->belongsTo(RecurringInvoice::class); + } + + public function client(): \Illuminate\Database\Eloquent\Relations\BelongsTo + { + return $this->belongsTo(Client::class); + } + + public function subscription(): \Illuminate\Database\Eloquent\Relations\BelongsTo + { + return $this->belongsTo(BillingSubscription::class); + } } diff --git a/app/Models/Company.php b/app/Models/Company.php index 16bc053a5a5a..3d1745444829 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -159,6 +159,16 @@ class Company extends BaseModel return $this->hasMany(ExpenseCategory::class)->withTrashed(); } + public function client_subscriptions() + { + return $this->hasMany(ClientSubscription::class)->withTrashed(); + } + + public function billing_subscriptions() + { + return $this->hasMany(BillingSubscription::class)->withTrashed(); + } + public function task_statuses() { return $this->hasMany(TaskStatus::class)->withTrashed(); diff --git a/app/Models/Credit.php b/app/Models/Credit.php index aecb446a18a5..8acf5a3dd9eb 100644 --- a/app/Models/Credit.php +++ b/app/Models/Credit.php @@ -77,6 +77,7 @@ class Credit extends BaseModel 'design_id', 'assigned_user_id', 'exchange_rate', + 'subscription_id', ]; protected $casts = [ diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index f4cd530696a8..22a9698a5bd4 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -91,6 +91,7 @@ class Invoice extends BaseModel 'design_id', 'assigned_user_id', 'exchange_rate', + 'subscription_id', ]; protected $casts = [ diff --git a/app/Models/Quote.php b/app/Models/Quote.php index 1f2b740ea81b..2f0c414ec75b 100644 --- a/app/Models/Quote.php +++ b/app/Models/Quote.php @@ -78,6 +78,7 @@ class Quote extends BaseModel 'design_id', 'assigned_user_id', 'exchange_rate', + 'subscription_id', ]; protected $casts = [ diff --git a/app/Policies/ClientSubscriptionPolicy.php b/app/Policies/ClientSubscriptionPolicy.php new file mode 100644 index 000000000000..e85df1028e4d --- /dev/null +++ b/app/Policies/ClientSubscriptionPolicy.php @@ -0,0 +1,31 @@ +isAdmin() || $user->hasPermission('create_client_subscription') || $user->hasPermission('create_all'); + } +} diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 60281db3b3fe..d71a5ae1435f 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -14,6 +14,7 @@ namespace App\Providers; use App\Models\Activity; use App\Models\BillingSubscription; use App\Models\Client; +use App\Models\ClientSubscription; use App\Models\Company; use App\Models\CompanyGateway; use App\Models\CompanyToken; @@ -40,6 +41,7 @@ use App\Models\Webhook; use App\Policies\ActivityPolicy; use App\Policies\BillingSubscriptionPolicy; use App\Policies\ClientPolicy; +use App\Policies\ClientSubscriptionPolicy; use App\Policies\CompanyGatewayPolicy; use App\Policies\CompanyPolicy; use App\Policies\CompanyTokenPolicy; @@ -77,6 +79,7 @@ class AuthServiceProvider extends ServiceProvider Activity::class => ActivityPolicy::class, BillingSubscription::class => BillingSubscriptionPolicy::class, Client::class => ClientPolicy::class, + ClientSubscription::class => ClientSubscriptionPolicy::class, Company::class => CompanyPolicy::class, CompanyToken::class => CompanyTokenPolicy::class, CompanyGateway::class => CompanyGatewayPolicy::class, diff --git a/app/Repositories/ClientSubscriptionRepository.php b/app/Repositories/ClientSubscriptionRepository.php new file mode 100644 index 000000000000..4cb88cb2ca53 --- /dev/null +++ b/app/Repositories/ClientSubscriptionRepository.php @@ -0,0 +1,28 @@ +fill($data) + ->save(); + + return $client_subscription; + } +} diff --git a/app/Transformers/ClientSubscriptionTransformer.php b/app/Transformers/ClientSubscriptionTransformer.php new file mode 100644 index 000000000000..5ed3c31d5539 --- /dev/null +++ b/app/Transformers/ClientSubscriptionTransformer.php @@ -0,0 +1,78 @@ + $this->encodePrimaryKey($client_subscription->id), + 'subscription_id' => $this->encodePrimaryKey($client_subscription->subscription_id), + 'company_id' => $this->encodePrimaryKey($client_subscription->company_id), + 'recurring_invoice_id' => $this->encodePrimaryKey($client_subscription->recurring_invoice_id), + 'client_id' => $this->encodePrimaryKey($client_subscription->client_id), + 'trial_started' => (string)$client_subscription->trial_started ?: '', + 'trial_ends' => (string)$client_subscription->trial_ends ?: '', + 'is_deleted' => (bool)$client_subscription->is_deleted, + 'created_at' => (int)$client_subscription->created_at, + 'updated_at' => (int)$client_subscription->updated_at, + 'archived_at' => (int)$client_subscription->deleted_at, + ]; + } + + public function includeClient(ClientSubscription $client_subscription): \League\Fractal\Resource\Item + { + $transformer = new ClientTransformer($this->serializer); + + return $this->includeItem($client_subscription->client, $transformer, Client::class); + } + + public function includeRecurringInvoice(ClientSubscription $client_subscription): \League\Fractal\Resource\Item + { + $transformer = new RecurringInvoiceTransformer($this->serializer); + + return $this->includeItem($client_subscription->recurring_invoice, $transformer, RecurringInvoice::class); + } + + public function includeSubscription(ClientSubscription $client_subscription): \League\Fractal\Resource\Item + { + $transformer = new BillingSubscriptionTransformer($this->serializer); + + return $this->includeItem($client_subscription->subscription, $transformer, BillingSubscription::class); + } +} + diff --git a/app/Transformers/CompanyTransformer.php b/app/Transformers/CompanyTransformer.php index 308cf6cde8b7..8620fefd7b2a 100644 --- a/app/Transformers/CompanyTransformer.php +++ b/app/Transformers/CompanyTransformer.php @@ -13,7 +13,9 @@ namespace App\Transformers; use App\Models\Account; use App\Models\Activity; +use App\Models\BillingSubscription; use App\Models\Client; +use App\Models\ClientSubscription; use App\Models\Company; use App\Models\CompanyGateway; use App\Models\CompanyLedger; @@ -90,6 +92,7 @@ class CompanyTransformer extends EntityTransformer 'system_logs', 'expense_categories', 'task_statuses', + 'client_subscriptions', ]; /** @@ -358,4 +361,18 @@ class CompanyTransformer extends EntityTransformer return $this->includeCollection($company->system_logs, $transformer, SystemLog::class); } + + public function includeClientSubscriptions(Company $company) + { + $transformer = new ClientSubscriptionTransformer($this->serializer); + + return $this->includeCollection($company->client_subscriptions, $transformer, ClientSubscription::class); + } + + public function includeBillingSubscriptions(Company $company) + { + $transformer = new BillingSubscriptionTransformer($this->serializer); + + return $this->includeCollection($company->billing_subscriptions, $transformer, BillingSubscription::class); + } } diff --git a/app/Transformers/CreditTransformer.php b/app/Transformers/CreditTransformer.php index 8d48f1b0b264..27d052e91cc4 100644 --- a/app/Transformers/CreditTransformer.php +++ b/app/Transformers/CreditTransformer.php @@ -137,6 +137,7 @@ class CreditTransformer extends EntityTransformer 'entity_type' => 'credit', 'exchange_rate' => (float) $credit->exchange_rate, 'paid_to_date' => (float) $credit->paid_to_date, + 'subscription_id' => $this->encodePrimaryKey($credit->subscription_id), ]; } } diff --git a/app/Transformers/InvoiceTransformer.php b/app/Transformers/InvoiceTransformer.php index 7a31a4b7760c..836c15e2c86d 100644 --- a/app/Transformers/InvoiceTransformer.php +++ b/app/Transformers/InvoiceTransformer.php @@ -141,6 +141,7 @@ class InvoiceTransformer extends EntityTransformer 'reminder3_sent' => $invoice->reminder3_sent ?: '', 'reminder_last_sent' => $invoice->reminder_last_sent ?: '', 'paid_to_date' => (float) $invoice->paid_to_date, + 'subscription_id' => $this->encodePrimaryKey($invoice->subscription_id), ]; } diff --git a/app/Transformers/QuoteTransformer.php b/app/Transformers/QuoteTransformer.php index ae8cd498c0b9..a3ecfc9938ac 100644 --- a/app/Transformers/QuoteTransformer.php +++ b/app/Transformers/QuoteTransformer.php @@ -139,6 +139,8 @@ class QuoteTransformer extends EntityTransformer 'exchange_rate' => (float) $quote->exchange_rate, 'paid_to_date' => (float) $quote->paid_to_date, 'project_id' => $this->encodePrimaryKey($quote->project_id), + 'subscription_id' => $this->encodePrimaryKey($quote->subscription_id), + ]; } } diff --git a/database/migrations/2021_03_08_123729_create_billing_subscriptions_table.php b/database/migrations/2021_03_08_123729_create_billing_subscriptions_table.php index 6268b9638f48..6f76050fb056 100644 --- a/database/migrations/2021_03_08_123729_create_billing_subscriptions_table.php +++ b/database/migrations/2021_03_08_123729_create_billing_subscriptions_table.php @@ -46,15 +46,20 @@ class CreateBillingSubscriptionsTable extends Migration Schema::create('client_subscriptions', function (Blueprint $table) { $table->increments('id'); + $table->unsignedInteger('company_id'); $table->unsignedInteger('subscription_id'); $table->unsignedInteger('recurring_invoice_id'); $table->unsignedInteger('client_id'); $table->unsignedInteger('trial_started')->nullable(); $table->unsignedInteger('trial_ends')->nullable(); + $table->boolean('is_deleted')->default(false); + $table->softDeletes('deleted_at', 6); $table->timestamps(); $table->foreign('subscription_id')->references('id')->on('billing_subscriptions'); $table->foreign('recurring_invoice_id')->references('id')->on('recurring_invoices'); $table->foreign('client_id')->references('id')->on('clients'); + $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade'); + $table->index(['company_id', 'deleted_at']); }); } diff --git a/database/migrations/2021_03_09_132242_add_currency_id_to_billing_subscriptions_table.php b/database/migrations/2021_03_09_132242_add_currency_id_to_billing_subscriptions_table.php index bc687317a449..ab3da33f51bd 100644 --- a/database/migrations/2021_03_09_132242_add_currency_id_to_billing_subscriptions_table.php +++ b/database/migrations/2021_03_09_132242_add_currency_id_to_billing_subscriptions_table.php @@ -16,6 +16,18 @@ class AddCurrencyIdToBillingSubscriptionsTable extends Migration Schema::table('billing_subscriptions', function (Blueprint $table) { $table->unsignedInteger('currency_id')->nullable(); }); + + Schema::table('invoices', function (Blueprint $table) { + $table->unsignedInteger('subscription_id')->nullable(); + }); + + Schema::table('quotes', function (Blueprint $table) { + $table->unsignedInteger('subscription_id')->nullable(); + }); + + Schema::table('credits', function (Blueprint $table) { + $table->unsignedInteger('subscription_id')->nullable(); + }); } /** diff --git a/routes/api.php b/routes/api.php index 1af077d5fbeb..6c3877a345b8 100644 --- a/routes/api.php +++ b/routes/api.php @@ -174,6 +174,7 @@ Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'a // Route::delete('hooks/{subscription_id}', 'SubscriptionController@unsubscribe')->name('hooks.unsubscribe'); Route::resource('billing_subscriptions', 'BillingSubscriptionController'); + Route::resource('cliente_subscriptions', 'ClientSubscriptionController'); }); Route::match(['get', 'post'], 'payment_webhook/{company_key}/{company_gateway_id}', 'PaymentWebhookController')