'boolean', 'is_active' => 'boolean', ]; /** * The attributes that should be mutated to dates. * * @var array */ protected $dates = ['start_date', 'end_date', 'deleted_at']; /** * The attributes that are translatable. * * @var array */ protected $translatedAttributes = ['name']; /** * Perform any actions required after the model boots. * * @return void */ protected static function booted() { static::saved(function ($coupon) { $coupon->saveRelations(request()->all()); }); static::addActiveGlobalScope(); } public static function findByCode($code) { return self::where(DB::raw('BINARY `code`'), $code)->first(); } public function freeShipping() { return $this->free_shipping ? $this : (object) ['free_shipping' => 0]; } public function valid() { if ($this->hasStartDate() && $this->hasEndDate()) { return $this->startDateIsValid() && $this->endDateIsValid(); } if ($this->hasStartDate()) { return $this->startDateIsValid(); } if ($this->hasEndDate()) { return $this->endDateIsValid(); } return true; } public function invalid() { return ! $this->valid(); } private function hasStartDate() { return ! is_null($this->start_date); } private function hasEndDate() { return ! is_null($this->end_date); } private function startDateIsValid() { return today() >= $this->start_date; } private function endDateIsValid() { return today() <= $this->end_date; } public function usageLimitReached($customerEmail = null) { return $this->perCouponUsageLimitReached() || $this->perCustomerUsageLimitReached($customerEmail); } public function perCouponUsageLimitReached() { if (is_null($this->usage_limit_per_coupon)) { return false; } return $this->used >= $this->usage_limit_per_coupon; } public function perCustomerUsageLimitReached($customerEmail = null) { if ($this->couponHasNoUsageLimitForCustomers() || $this->userIsNotLoggedInWhenAddingCouponToCart($customerEmail) ) { return false; } $customerEmail = $customerEmail ?: auth()->user()->email; $used = $this->orders() ->where('customer_email', $customerEmail) ->count(); return $used >= $this->usage_limit_per_customer; } private function couponHasNoUsageLimitForCustomers() { return is_null($this->usage_limit_per_customer); } private function userIsNotLoggedInWhenAddingCouponToCart($customerEmail = null) { return is_null($customerEmail) && auth()->guest(); } public function didNotSpendTheRequiredAmount() { if (is_null($this->minimum_spend)) { return false; } return Cart::subTotal()->lessThan($this->minimum_spend); } public function spentMoreThanMaximumAmount() { if (is_null($this->maximum_spend)) { return false; } return Cart::subTotal()->greaterThan($this->maximum_spend); } public function products() { return $this->belongsToMany(Product::class, 'coupon_products') ->withPivot('exclude') ->wherePivot('exclude', false); } public function excludeProducts() { return $this->belongsToMany(Product::class, 'coupon_products') ->withPivot('exclude') ->wherePivot('exclude', true); } public function categories() { return $this->belongsToMany(Category::class, 'coupon_categories') ->withPivot('exclude') ->wherePivot('exclude', false); } public function excludeCategories() { return $this->belongsToMany(Category::class, 'coupon_categories') ->withPivot('exclude') ->wherePivot('exclude', true); } public function orders() { return $this->hasMany(Order::class)->withTrashed(); } public function customers() { return $this->hasManyThrough( User::class, Order::class, 'coupon_id', 'id', 'id', 'customer_id' )->withTrashed(); } public function getValueAttribute($value) { if ($this->is_percent) { return $value; } return Money::inDefaultCurrency($value); } public function getMinimumSpendAttribute($minimumSpend) { if (! is_null($minimumSpend)) { return Money::inDefaultCurrency($minimumSpend); } } public function getMaximumSpendAttribute($maximumSpend) { if (! is_null($maximumSpend)) { return Money::inDefaultCurrency($maximumSpend); } } public function getTotalAttribute($total) { return Money::inDefaultCurrency($total); } /** * Get table data for the resource * * @return \Illuminate\Http\JsonResponse */ public function table() { return new CouponTable($this->newQuery()->withoutGlobalScope('active')); } /** * Save associated relations for the coupon. * * @param array $attributes * @return void */ public function saveRelations(array $attributes) { $this->syncProducts(array_get($attributes, 'products', [])); $this->syncExcludeProducts(array_get($attributes, 'exclude_products', [])); $this->syncCategories(array_get($attributes, 'categories', [])); $this->syncExcludeCategories(array_get($attributes, 'exclude_categories', [])); } }