فهرست منبع

Implement coupons for the other gateways.

Ferks-FK 2 سال پیش
والد
کامیت
24ce267962

+ 30 - 5
app/Extensions/PaymentGateways/Mollie/MollieExtension.php

@@ -9,10 +9,12 @@ use App\Models\PartnerDiscount;
 use App\Models\Payment;
 use App\Models\ShopProduct;
 use App\Models\User;
+use App\Models\Coupon;
+use App\Traits\Coupon as CouponTrait;
+use App\Events\CouponUsedEvent;
 use Exception;
 use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Request;
-use Illuminate\Http\Response;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Redirect;
 use Illuminate\Support\Facades\Log;
@@ -23,6 +25,8 @@ use Illuminate\Support\Facades\Http;
  */
 class MollieExtension extends AbstractExtension
 {
+    use CouponTrait;
+
     public static function getConfig(): array
     {
         return [
@@ -33,7 +37,7 @@ class MollieExtension extends AbstractExtension
         ];
     }
 
-    static function pay(Request $request): void
+    public function pay(Request $request): void
     {
         $url = 'https://api.mollie.com/v2/payments';
         $settings = new MollieSettings();
@@ -41,6 +45,18 @@ class MollieExtension extends AbstractExtension
         $user = Auth::user();
         $shopProduct = ShopProduct::findOrFail($request->shopProduct);
         $discount = PartnerDiscount::getDiscount();
+        $couponCode = $request->input('couponCode');
+        $isValidCoupon = $this->validateCoupon($request->user(), $couponCode, $request->shopProduct);
+        $price = $shopProduct->price;
+
+        // Coupon Discount.
+        if ($isValidCoupon->getStatusCode() == 200) {
+            $price = $this->calcDiscount($price, $isValidCoupon->getData());
+        }
+
+        // Partner Discount.
+        $price = $price - ($price * $discount / 100);
+        $price = number_format($price, 2, thousands_separator: '');
 
         // create a new payment
         $payment = Payment::create([
@@ -50,7 +66,7 @@ class MollieExtension extends AbstractExtension
             'type' => $shopProduct->type,
             'status' => 'open',
             'amount' => $shopProduct->quantity,
-            'price' => $shopProduct->price - ($shopProduct->price * $discount / 100),
+            'price' => $price,
             'tax_value' => $shopProduct->getTaxValue(),
             'tax_percent' => $shopProduct->getTaxPercent(),
             'total_price' => $shopProduct->getTotalPrice(),
@@ -65,10 +81,10 @@ class MollieExtension extends AbstractExtension
             ])->post($url, [
                 'amount' => [
                     'currency' => $shopProduct->currency_code,
-                    'value' => number_format($shopProduct->getTotalPrice(), 2, '.', ''),
+                    'value' => $price,
                 ],
                 'description' => "Order #{$payment->id} - " . $shopProduct->name,
-                'redirectUrl' => route('payment.MollieSuccess'),
+                'redirectUrl' => route('payment.MollieSuccess', ['couponCode' => $couponCode]),
                 'cancelUrl' => route('payment.Cancel'),
                 'webhookUrl' => url('/extensions/payment/MollieWebhook'),
                 'metadata' => [
@@ -103,6 +119,15 @@ class MollieExtension extends AbstractExtension
     {
         $payment = Payment::findOrFail($request->input('payment'));
         $payment->status = 'pending';
+        $coupon_code = $request->input('couponCode');
+
+        // increase the use of the coupon when the payment is confirmed.
+        if ($coupon_code) {
+            $coupon = new Coupon;
+            $coupon->incrementUses($coupon_code);
+
+            event(new CouponUsedEvent($coupon));
+        }
 
         Redirect::route('home')->with('success', 'Your payment is being processed')->send();
         return;

+ 2 - 2
app/Extensions/PaymentGateways/Mollie/web_routes.php

@@ -4,8 +4,8 @@ use Illuminate\Support\Facades\Route;
 use App\Extensions\PaymentGateways\Mollie\MollieExtension;
 
 Route::middleware(['web', 'auth'])->group(function () {
-    Route::get('payment/MolliePay/{shopProduct}', function () {
-        MollieExtension::pay(request());
+    Route::get('payment/MolliePay/{shopProduct}', function (MollieExtension $mollieExtension) {
+        $mollieExtension->pay(request());
     })->name('payment.MolliePay');
 
     Route::get(

+ 30 - 6
app/Extensions/PaymentGateways/Stripe/StripeExtension.php

@@ -4,12 +4,15 @@ namespace App\Extensions\PaymentGateways\Stripe;
 
 use App\Helpers\AbstractExtension;
 use App\Events\PaymentEvent;
+use App\Events\CouponUsedEvent;
 use App\Events\UserUpdateCreditsEvent;
 use App\Extensions\PaymentGateways\Stripe\StripeSettings;
 use App\Models\PartnerDiscount;
 use App\Models\Payment;
 use App\Models\ShopProduct;
 use App\Models\User;
+use App\Models\Coupon;
+use App\Traits\Coupon as CouponTrait;
 use App\Notifications\ConfirmPaymentNotification;
 use Exception;
 use Illuminate\Http\Request;
@@ -21,6 +24,8 @@ use Stripe\StripeClient;
 
 class StripeExtension extends AbstractExtension
 {
+    use CouponTrait;
+
     public static function getConfig(): array
     {
         return [
@@ -35,10 +40,14 @@ class StripeExtension extends AbstractExtension
      * @param  Request  $request
      * @param  ShopProduct  $shopProduct
      */
-    public static function StripePay(Request $request)
+    public function StripePay(Request $request)
     {
         $user = Auth::user();
         $shopProduct = ShopProduct::findOrFail($request->shopProduct);
+        $discount = PartnerDiscount::getDiscount();
+        $couponCode = $request->input('couponCode');
+        $isValidCoupon = $this->validateCoupon($request->user(), $couponCode, $request->shopProduct);
+        $price = $shopProduct->price;
 
         // check if the price is valid for stripe
         if (!self::checkPriceAmount($shopProduct->getTotalPrice(), strtoupper($shopProduct->currency_code), 'stripe')) {
@@ -46,7 +55,14 @@ class StripeExtension extends AbstractExtension
             return;
         }
 
-        $discount = PartnerDiscount::getDiscount();
+        // Coupon Discount.
+        if ($isValidCoupon->getStatusCode() == 200) {
+            $price = $this->calcDiscount($price, $isValidCoupon->getData());
+        }
+
+        // Partner Discount.
+        $price = $price - ($price * $discount / 100);
+        $price = number_format($price, 2);
 
 
         // create payment
@@ -57,7 +73,7 @@ class StripeExtension extends AbstractExtension
             'type' => $shopProduct->type,
             'status' => 'open',
             'amount' => $shopProduct->quantity,
-            'price' => $shopProduct->price - ($shopProduct->price * $discount / 100),
+            'price' => $price,
             'tax_value' => $shopProduct->getTaxValue(),
             'total_price' => $shopProduct->getTotalPrice(),
             'tax_percent' => $shopProduct->getTaxPercent(),
@@ -75,7 +91,7 @@ class StripeExtension extends AbstractExtension
                             'name' => $shopProduct->display . ($discount ? (' (' . __('Discount') . ' ' . $discount . '%)') : ''),
                             'description' => $shopProduct->description,
                         ],
-                        'unit_amount_decimal' => round($shopProduct->getPriceAfterDiscount() * 100, 2),
+                        'unit_amount_decimal' => $price,
                     ],
                     'quantity' => 1,
                 ],
@@ -93,7 +109,7 @@ class StripeExtension extends AbstractExtension
             ],
 
             'mode' => 'payment',
-            'success_url' => route('payment.StripeSuccess', ['payment' => $payment->id]) . '&session_id={CHECKOUT_SESSION_ID}',
+            'success_url' => route('payment.StripeSuccess', ['payment' => $payment->id, 'couponCode' => $couponCode]) . '&session_id={CHECKOUT_SESSION_ID}',
             'cancel_url' => route('payment.Cancel'),
             'payment_intent_data' => [
                 'metadata' => [
@@ -114,7 +130,7 @@ class StripeExtension extends AbstractExtension
         $user = User::findOrFail($user->id);
         $payment = Payment::findOrFail($request->input('payment'));
         $shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id);
-
+        $couponCode = $request->input('couponCode');
 
         Redirect::route('home')->with('success', 'Please wait for success')->send();
 
@@ -136,6 +152,14 @@ class StripeExtension extends AbstractExtension
                     'status' => 'paid',
                 ]);
 
+                 // increase the use of the coupon when the payment is confirmed.
+                 if ($couponCode) {
+                    $coupon = new Coupon;
+                    $coupon->incrementUses($couponCode);
+
+                    event(new CouponUsedEvent($coupon));
+                }
+
                 //payment notification
                 $user->notify(new ConfirmPaymentNotification($payment));
 

+ 2 - 2
app/Extensions/PaymentGateways/Stripe/web_routes.php

@@ -4,8 +4,8 @@ use Illuminate\Support\Facades\Route;
 use App\Extensions\PaymentGateways\Stripe\StripeExtension;
 
 Route::middleware(['web', 'auth'])->group(function () {
-    Route::get('payment/StripePay/{shopProduct}', function () {
-        StripeExtension::StripePay(request());
+    Route::get('payment/StripePay/{shopProduct}', function (StripeExtension $stripeExtension) {
+        $stripeExtension->StripePay(request());
     })->name('payment.StripePay');
 
     Route::get(

+ 13 - 54
app/Models/Coupon.php

@@ -4,11 +4,21 @@ namespace App\Models;
 
 use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
+use Spatie\Activitylog\LogOptions;
+use Spatie\Activitylog\Traits\LogsActivity;
 use Carbon\Carbon;
 
 class Coupon extends Model
 {
-    use HasFactory;
+    use HasFactory, LogsActivity;
+
+    public function getActivitylogOptions(): LogOptions
+    {
+        return LogOptions::defaults()
+            ->logOnlyDirty()
+            ->logOnly(['*'])
+            ->dontSubmitEmptyLogs();
+    }
 
     /**
      * @var string[]
@@ -97,67 +107,16 @@ class Coupon extends Model
         return $coupons;
     }
 
-    /**
-     * Standardize queries into one single function.
-     *
-     * @param string $code Coupon Code.
-     * @param array $attributes Attributes to be returned.
-     *
-     * @return mixed
-     */
-    protected function getQueryData(string $code, array $attributes): mixed
-    {
-        $query = (Coupon::where('code', $code)
-            ->where('expires_at', '>', Carbon::now())
-            ->whereColumn('uses', '<=', 'max_uses')
-            ->get($attributes)->toArray()
-        );
-
-        // When there are results, it comes nested arrays, idk why. This is the solution for now.
-        $results = count($query) > 0 ? $query[0] : $query;
-
-        if (empty($results)) {
-            return [];
-        }
-
-        return $results;
-    }
-
-    /**
-     * Get the data from a coupon.
-     *
-     * @param string $code Coupon Code.
-     * @param array $attributes Attributes of a coupon.
-     *
-     * @return mixed
-     */
-    public function getCoupon(string $code, array $attributes = ['percentage']): mixed
-    {
-        $coupon = $this->getQueryData($code, $attributes);
-
-        if (is_null($coupon)) {
-            return null;
-        }
-
-        return $coupon;
-    }
-
     /**
      * Increments the use of a coupon.
      *
      * @param string $code Coupon Code.
      * @param int $amount Amount to increment.
      *
-     * @return null|bool
+     * @return bool
      */
-    public function incrementUses(string $code, int $amount = 1): null|bool
+    public function incrementUses(string $code, int $amount = 1): bool
     {
-        $coupon = $this->getQueryData($code, ['uses', 'max_uses']);
-
-        if (empty($coupon) || $coupon['uses'] == $coupon['max_uses']) {
-            return null;
-        }
-
         $this->where('code', $code)->increment('uses', $amount);
 
         return true;

+ 1 - 1
app/Settings/CouponSettings.php

@@ -43,7 +43,7 @@ class CouponSettings extends Settings
                 'description' => 'Maximum number of uses that a user can make of the same coupon.'
             ],
             'delete_coupon_on_expires' => [
-                'label' => 'Delete Coupon On Expires',
+                'label' => 'Auto Delete Expired Coupons',
                 'type' => 'boolean',
                 'description' => 'Automatically deletes the coupon if it expires.'
             ],