Edit File: PackageService.php
<?php namespace App\Services\User; use App\Enums\PeriodTypeEnum; use App\Enums\SubscriptionType; use App\Models\Package; use App\Traits\PaginationTrait; use Exception; use Illuminate\Support\Facades\DB; class PackageService { use PaginationTrait; public function index($pagination) { return Package::active()->with('subscriptions')->latest('id')->paginate($pagination); } //-------------------------------------------------------------------------------------------------------------------------- public function subscribe($data) { $package = Package::findOrFail($data['package_id']); DB::beginTransaction(); try { // Delete last active subscription if exists $this->checkAndDeleteLastSubscription(); // calculate Dates $dates = $this->calculateDates($package); // Calculate prices once $prices = $this->calculatePrices($package); // Create new subscription auth()->user()->subscriptions()->create([ 'package_id' => $data['package_id'], 'start_date' => $dates['start_date'], 'end_date' => $dates['end_date'], 'price' => $prices['price'], 'vat_amount' => $prices['vat_amount'], 'final_price' => $prices['final_price'], 'vat_ratio' => $prices['vat_ratio'], ]); // Commit transaction if everything succeeds DB::commit(); return ['key' => 'success', 'msg' => __('apis.package_subscribed')]; } catch (Exception $e) { // Rollback transaction if an error occurs DB::rollBack(); // Return an error message to the user return ['key' => 'fail', 'msg' => $e->getMessage()]; } } //-------------------------------------------------------------------------------------------------------------------------- public function freeTrial() { if (auth()->user()->hasUsedFreeTrial()) { return ['key' => 'fail', 'msg' => __('apis.free_trial_subscribed_before')]; } if (auth()->user()->hasSubscription()) { return ['key' => 'fail', 'msg' => __('apis.already_subscribed')]; } // Cache or retrieve VAT ratio $free_trial_period = cache()->remember('free_trial_period', 60 * 60, function () { return (float) DB::table('site_settings')->where('key', 'free_trial_period')->value('value'); }); auth()->user()->subscriptions()->create([ 'start_date' => now()->format('Y-m-d'), 'end_date' => now()->addDays($free_trial_period ?? 7)->format('Y-m-d'), 'type' => SubscriptionType::FREE_TRIAL, ]); return ['key' => 'success', 'msg' => __('apis.success')]; } //-------------------------------------------------------------------------------------------------------------------------- public function myPackages($pagination) { // Fetch subscriptions with related packages and load their subscriptions eagerly $subscriptions = auth()->user()->subscriptions() ->with('package.subscriptions') ->whereNotNull('package_id') ->latest() ->get(); // Get unique packages from subscriptions $packages = $subscriptions->map(function ($subscription) { return $subscription->package; })->unique(); // Paginate the result manually since it's a collection $packagesPaginator = $this->paginateCollection($packages, $pagination); return $packagesPaginator; } //-------------------------------------------------------------------------------------------------------------------------- public function renew($data) { try { if (auth()->user()->hasSubscription()) { return ['key' => 'fail', 'msg' => __('apis.already_subscribed')]; } DB::transaction(function () use ($data) { $subscription = auth()->user()->subscriptions()->where('package_id', $data['package_id'])->first(); $dates = $this->calculateDates($subscription->package); $subscription->update([ 'start_date' => $dates['start_date'], 'end_date' => $dates['end_date'], 'is_active' => true, ]); }); return ['key' => 'success', 'msg' => __('apis.renew_success')]; } catch (Exception $e) { return ['key' => 'fail', 'msg' => $e->getMessage()]; } } //-------------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------------- // helper functions //-------------------------------------------------------------------------------------------------------------------------- protected function checkAndDeleteLastSubscription() { $user = auth()->user(); // Get active subscription $activeSubscription = $user->subscriptions() ->where('is_active', true) ->whereDate('start_date', '<=', now()->format('Y-m-d')) ->whereDate('end_date', '>=', now()->format('Y-m-d')) ->first(); // If active subscription exists, delete it if ($activeSubscription) { $activeSubscription->delete(); } return true; } protected function calculateDates($package) { $start_date = now()->format('Y-m-d'); // Calculate the end date based on the package's period type switch ($package->period_type) { case PeriodTypeEnum::DAYS: $end_date = now()->addDays($package->period)->format('Y-m-d'); break; case PeriodTypeEnum::WEEKS: $end_date = now()->addWeeks($package->period)->format('Y-m-d'); break; case PeriodTypeEnum::MONTHS: $end_date = now()->addMonths($package->period)->format('Y-m-d'); break; case PeriodTypeEnum::YEARS: $end_date = now()->addYears($package->period)->format('Y-m-d'); break; default: $end_date = now()->addDays($package->period)->format('Y-m-d'); break; } // Return an array of start and end dates return [ 'start_date' => $start_date, 'end_date' => $end_date ]; } protected function calculatePrices($package) { // Cache or retrieve VAT ratio $vatRatio = cache()->remember('vat_ratio', 60 * 60, function () { return (float) DB::table('site_settings')->where('key', 'vat_ratio')->value('value'); }); $price = (float) $package->price; $vatAmount = $price * ($vatRatio / 100); $finalPrice = $price + $vatAmount; return [ 'vat_ratio' => $vatRatio, 'price' => $price, 'vat_amount' => $vatAmount, 'final_price' => $finalPrice, ]; } }
Back to File Manager