cart = $cart; $this->coupon = $coupon; $this->couponCondition = $couponCondition; } public function entity() { return $this->coupon; } public function id() { return $this->coupon->id; } public function isFreeShipping() { return $this->coupon->free_shipping; } public function usageLimitReached($customerEmail) { return $this->fresh()->coupon->usageLimitReached($customerEmail); } public function fresh(): static { $this->coupon = $this->coupon->refresh(); return $this; } public function didNotSpendTheRequiredAmount() { return $this->fresh()->coupon->didNotSpendTheRequiredAmount(); } public function spentMoreThanMaximumAmount() { return $this->fresh()->coupon->spentMoreThanMaximumAmount(); } public function usedOnce() { $this->coupon->increment('used'); } public function __toString() { return json_encode($this->jsonSerialize()); } public function jsonSerialize() { return $this->toArray(); } public function toArray(): array { return [ 'code' => $this->code(), 'value' => $this->value(), 'free_shipping' => $this->coupon->free_shipping, ]; } public function code() { return $this->coupon->code; } public function value() { return Money::inDefaultCurrency($this->calculate()); } public function __get($attribute) { return $this->coupon->{$attribute}; } private function calculate() { return $this->couponCondition->getCalculatedValue($this->couponApplicableProductsTotalPrice()); } private function couponApplicableProductsTotalPrice() { return $this->couponApplicableProducts()->sum(function ($cartItem) { return $cartItem->totalPrice()->amount(); }); } private function couponApplicableProducts() { return $this->cart->items()->filter(function ($cartItem) { return $this->inApplicableProducts($cartItem); })->reject(function ($cartItem) { return $this->inExcludedProducts($cartItem); })->filter(function ($cartItem) { return $this->inApplicableCategories($cartItem); })->reject(function ($cartItem) { return $this->inExcludedCategories($cartItem); }); } private function inApplicableProducts($cartItem) { if ($this->coupon->products->isEmpty()) { return true; } return $this->coupon->products->contains($cartItem->product); } private function inExcludedProducts($cartItem) { if ($this->coupon->excludeProducts->isEmpty()) { return false; } return $this->coupon->excludeProducts->contains($cartItem->product); } private function inApplicableCategories($cartItem) { if ($this->coupon->categories->isEmpty()) { return true; } return $this->coupon->categories->intersect($cartItem->product->categories)->isNotEmpty(); } private function inExcludedCategories($cartItem) { if ($this->coupon->excludeCategories->isEmpty()) { return false; } return $this->coupon->excludeCategories->intersect($cartItem->product->categories)->isNotEmpty(); } }