PATH:
home
/
rwabteecom
/
project_11
/
app
/
Services
/
Plan
/
Editing: PlanServices.php
<?php namespace App\Services\Plan; use App\Interfaces\ServiceInterface; use App\Models\Invoice; use App\Models\Plan; use App\Models\UserPlan; use App\Services\User\UserServices; use Carbon\Carbon; use DB; use Exception; use Illuminate\Support\Collection; class PlanServices implements ServiceInterface { public function index($active = false): Collection { if ($active) { return Plan::query()->active()->get(); } return Plan::query()->get(); } public function findOrFail($id, $active = false): Plan { if ($active) { return Plan::query()->active()->findOrFail($id); } return Plan::query()->findOrFail($id); } public function findWithoutFail($id, $active = false): Plan|null { if ($active) { return Plan::query()->active()->find($id); } return Plan::query()->find($id); } public function store($request): void { DB::transaction(function () use ($request) { $plan = Plan::query()->create([ "title" => $request->title, "price" => $request->price, "order" => $request->order, "duration_in_days" => $request->duration_in_days, ]); $plan->features()->sync($request->features ?? []); }); } public function update($id, $request): void { DB::transaction(function () use ($request, $id) { $plan = $this->findOrFail($id); $plan->update([ "title" => $request->title, "price" => $request->price, "order" => $request->order, "duration_in_days" => $request->duration_in_days, ]); $plan->features()->sync($request->features ?? []); }); } public function destroy($id): void { DB::transaction(function () use ($id) { $plan = $this->findOrFail($id); if ($plan->is_free_plan) { throw new Exception(__("You can't delete free plan, you can disable it instead")); } $plan->delete(); }); } public function attachPlanToUser($plan_id, $user_id, $plan_expired_at, $is_paid): void { DB::transaction(function () use ($user_id, $plan_id, $plan_expired_at, $is_paid) { $plan = $this->findOrFail($plan_id, true); $user = (new UserServices())->findUserById($user_id); if ($plan->is_free_plan && $user->is_subscribed_to_free_plan) { throw new Exception(__("User already subscribed to free plan before")); } if ($plan->is_free_plan && $user->plans()->count()) { throw new Exception(__("User already subscribed to paid plans, can't subscribe to free plan")); } if ($user->plans()->count() > 0 && $plan->order < $user->currentPlan?->order) { throw new Exception(__("User can't downgrade current plan")); } if ($plan->is_free_plan) { $this->attachFreePlan($user, $plan_expired_at); } else { $this->attachPaidPlan($user, $plan, $plan_expired_at, $is_paid); } }); } private function attachPaidPlan($user, $plan, $plan_expired_at, $is_paid): void { $user->update([ "current_plan_expired_at" => Carbon::parse($plan_expired_at)->format("Y-m-d") ]); $price = $this->calculatePlanPrice( user: $user, requestedPlan: $plan, ); if ($price == 0) { throw new Exception(__("Price is equal zero , please check selected plan")); } $userPlan = UserPlan::query()->create([ "user_id" => $user->id, "title" => [ "ar" => $plan->getTranslation("title", "ar"), "en" => $plan->getTranslation("title", "en"), ], "description" => [ "ar" => $plan->getTranslation("description", "ar"), "en" => $plan->getTranslation("description", "en"), ], "order" => $plan->order, "plan_id" => $plan->id, "price" => $price, "plan_end_at" => Carbon::parse($plan_expired_at)->format("Y-m-d"), ]); $invoice = Invoice::query()->create([ "user_plan_id" => $userPlan->id, "user_id" => $user->id, "price" => $price, "is_paid" => $is_paid ]); $invoice->update([ "invoice_number" => "00000" . $invoice->id ]); } private function attachFreePlan($user, $plan_expired_at): void { $user->update([ "is_subscribed_to_free_plan" => 1, "current_plan_expired_at" => Carbon::parse($plan_expired_at)->format("Y-m-d") ]); } private function calculatePlanPrice($user, $requestedPlan): float { $priceForRemainingDays = 0; $paidPlans = $user->plans()->whereHas('invoice', fn($query) => $query->where("is_paid", 1))->get(); foreach ($paidPlans as $userPlan) { $currentPlanExpiredAt = Carbon::parse($userPlan->plan_end_at)->addDay(); $diffInDays = $currentPlanExpiredAt->diffInDays(now()); $pricePerDay = $userPlan->price / ($userPlan->created_at->diffInDays($currentPlanExpiredAt)); $priceForRemainingDays += $diffInDays * $pricePerDay; } return $requestedPlan->price - $priceForRemainingDays; } }
SAVE
CANCEL