Edit File: PackageService.php
<?php namespace App\Services\User; use App\Enums\{SubscriptionType, PeriodTypeEnum, SubscriptionStatusEnum}; use App\Http\Resources\Api\User\Package\PackageCollection; use Illuminate\Support\Facades\DB; use App\Traits\PaginationTrait; use App\Models\Package; use Carbon\Carbon; use Exception; class PackageService { use PaginationTrait; public function index($pagination) { return Package::active()->with('subscriptions')->latest('id')->paginate($pagination); } //-------------------------------------------------------------------------------------------------------------------------- public function packageSummary($id) { $package = Package::findOrFail($id); $prices = $this->returnPackageSummary($package); return [ 'key' => 'success', 'msg' => __('apis.success'), 'data' => [ 'price' => $prices['price'], 'vat_value' => $prices['vat_value'], 'total' => $prices['total'], ] ]; } public function subscribe($data) { $package = Package::findOrFail($data['package_id']); DB::beginTransaction(); try { // Delete last active subscription if exists // Get active subscription $activeSubscription = auth()->user()->hasSubscription(); // If active subscription exists, delete it if ($activeSubscription) { return $this->response('fail', __('apis.already_subscribed')); } // 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'), 'data' => auth()->user()->refresh()->getResource()]; } 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() { $user = auth()->user()->refresh()->getResource(); if (auth()->user()->hasUsedFreeTrial()) { return $this->response('fail', __('apis.free_trial_subscribed_before'), $user); } if (auth()->user()->hasSubscription()) { return $this->response('fail', __('apis.already_subscribed'), $user); } // 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 $this->response('success', __('apis.success'), $user); } //-------------------------------------------------------------------------------------------------------------------------- public function myPackages($pagination) { $user = auth()->user(); // Check and add the free trial package if applicable $freeTrialPackage = $this->getFreeTrialPackage(); if ($freeTrialPackage) { return $freeTrialPackage; } // Fetch packages from user subscriptions $packages = $this->getUserPackages($user); if ($packages->isNotEmpty()) { return PackageCollection::make($this->paginateCollection($packages->unique(), $pagination)); } return PackageCollection::make($this->paginateCollection($packages, $pagination)); } //-------------------------------------------------------------------------------------------------------------------------- public function renew($data) { try { if (auth()->user()->hasSubscription()) { return $this->response('fail', __('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 $this->response('success', __('apis.renew_success')); } catch (Exception $e) { return $this->response('fail', $e->getMessage()); } } //-------------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------------- // helper functions //-------------------------------------------------------------------------------------------------------------------------- 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, ]; } private function returnPackageSummary($package) { $price = $package->price; $vatAmount = $price * (settings('vat_ratio') / 100); $total = $price + $vatAmount; return [ 'price' => (float) $price ?? 0, 'vat_value' => (float) $vatAmount ?? 0, 'total' => (float) $total ?? 0, ]; } protected function getUserPackages($user) { return $user->subscriptions() ->with('package') ->whereNotNull('package_id') ->latest() ->get() ->map(fn($subscription) => $subscription->package); } protected function getFreeTrialPackage() { $freeTrialSubscription = auth()->user()->subscriptions() ->where('type', SubscriptionType::FREE_TRIAL) ->where('end_date', '>=', now()->format('Y-m-d')) ->first(); if (!$freeTrialSubscription) return null; $startDate = Carbon::parse($freeTrialSubscription->start_date); $endDate = Carbon::parse($freeTrialSubscription->end_date); $totalDays = $startDate->diffInDays($endDate); $data = [ 'id' => null, 'image' => null, 'name' => __('apis.free_trial'), 'price' => 0, 'currency' => __('apis.r_s'), 'period' => $totalDays . ' ' . __('apis.days'), 'subscription_status' => SubscriptionStatusEnum::ACTIVE, 'start_date' => $freeTrialSubscription->start_date, 'end_date' => $freeTrialSubscription->end_date, ]; $paginated = $this->paginateCollection(collect([$data]), 1); return [ 'pagination' => [ 'total_items' => $paginated->total(), 'count_items' => $paginated->count(), 'per_page' => $paginated->perPage(), 'total_pages' => $paginated->lastPage(), 'current_page' => $paginated->currentPage(), 'next_page_url' => $paginated->nextPageUrl() ?? '', 'prev_page_url' => $paginated->previousPageUrl() ?? '', ], 'data' => $paginated->items(), ]; } protected function response($key, $msg, $data = []) { return [ 'key' => $key, 'msg' => $msg, 'data' => $data ]; } }
Back to File Manager