laravelshoppingcart icon indicating copy to clipboard operation
laravelshoppingcart copied to clipboard

check if user already used coupon code

Open robertnicjoo opened this issue 6 years ago • 2 comments

Hi,

I have trouble with checking if user already used coupon code, currently user can use same coupon code over and over.

How can I check if user already used any coupon code once then stop him of using it for second time?

here is my update function:

public function update(Request $request, $id)
    {
      // quantity
      $qty = $request->input('quantity');
      $products = Product::findOrFail($request->proId);
      $stock = $products->stock;
      $mytime = Carbon::now();
      $couponcode = $request->input('coupon');
      $userId = Auth::user()->id;

      $catId = Coupon::where('category_id', $products->category_id)
                    ->where('value_to', '>=', $mytime)
                    ->when($couponcode, function ($query) use ($couponcode) {
                          return $query->where('title', $couponcode);
                      })
                      ->first();

      if (!empty($qty) && !empty($couponcode)) { // 1. if both (quantity and couponcode) are given
          if ($qty < $stock && (!is_null($catId) && $catId->title == $couponcode)) { // if quantity < stock AND coupon-code is correct

              $coupon = new \Darryldecode\Cart\CartCondition(array(
                  'name' => $catId->title,
                  'type' => 'coupon',
                  'target' => 'item',
                  'value' => -$catId->amount,
              ));

              Cart::update($id, array(
                  'quantity' => array(
                      'relative' => false,
                      'value' => $qty,
                  ),
              ));
              Cart::addItemCondition($id, $coupon);

              Session::flash('success', 'Cart updated.');
              return redirect()->route('cart.index');

          } elseif ($qty > $stock) {
              Session::flash('danger', 'quantity not available!');
              return redirect()->route('cart.index');
          } else {
              Session::flash('danger', 'invalid coupon code!');
              return redirect()->route('cart.index');
          }
      } elseif (!empty($qty)) { // 2. if just quantity is given   
          if ($qty < $stock) {

              Cart::update($id, array(
                  'quantity' => array(
                      'relative' => false,
                      'value' => $qty,
                  ),
              ));

              Session::flash('success', 'Cart updated.');
              return redirect()->route('cart.index');

          } else {
              Session::flash('danger', 'quantity not available!');
              return redirect()->route('cart.index');
          }
      } elseif (!empty($couponcode)) { // 3. if just couponcode is given
          if (!is_null($catId) && $catId->title == $couponcode) {

              $coupon = new \Darryldecode\Cart\CartCondition(array(
                  'name' => $catId->title,
                  'type' => 'coupon',
                  'target' => 'item',
                  'value' => -$catId->amount,
              ));
              
              // Cart::addItemCondition($id, $coupon);
              Cart::session($userId)->addItemCondition($id, $coupon);

              Session::flash('success', 'Coupon applied successfully.');
              return redirect()->route('cart.index');

          } else {
              Session::flash('danger', 'invalid coupon code!');
              return redirect()->route('cart.index');
          }
      } else{ // 1. if nothing is given
            Session::flash('danger', 'Your request cannot be handle, please try again!');
            return redirect()->route('cart.index');
        }
    }

thanks.

robertnicjoo avatar Mar 11 '18 14:03 robertnicjoo

I dont know how is your coupon table in database, but my sugestion is to create a table named "coupon_user" with a column named "uses" and another with "user_id", and then, when you use a coupon, you subtract the value by -1 until reaches to 0, after that the only thing you need is making validations to disallow the user to use again the coupon when the "uses" have reached to 0.

Hope it helps! :D

DSPNeves avatar Jun 05 '18 10:06 DSPNeves

You should be doing this check in a validator. Reiterating what @DSPNeves has said, you could have a form request class like this

<?php

namespace App\Http\Requests;

use App\Coupon;
use Illuminate\Foundation\Http\FormRequest;

class ApplyCouponToShoppingCartRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'coupon_code' => ['required', 'string'],
        ];
    }

    /**
     * Configure the validator instance.
     *
     * @param \Illuminate\Validation\Validator $validator
     */
    public function withValidator($validator)
    {
        $validator->after(function ($validator) {
            $coupon = Coupon::whereCode($this->input('coupon_code'))->first();
            if (!$coupon) {
                return $validator->errors()->add('coupon_code', 'The coupon code is invalid.');
            }

            if ($this->usedByUser($coupon)) {
                return $validator->errors()->add('coupon_code', 'This coupon has been used by your account.');
            }

            if ($this->numberOfUsersExceeded($coupon)) {
                return $validator->errors()->add('coupon_code', 'Coupon number of users exceeded.');
            }
        });
    }

    private function usedByUser($coupon)
    {
        return $coupon->users()->where('user_id', auth()->id())->exists() ? true : false;
    }

    private function numberOfUsersExceeded($coupon)
    {
        $coupon->loadCount('users');

        return ($coupon->users_count + 1) > $coupon->no_of_users ? true : false;
    }
}

simioluwatomi avatar Jun 24 '20 17:06 simioluwatomi