| @@ 23-99 (lines=77) @@ | ||
| 20 | /** |
|
| 21 | * Class OrderFixedDiscountAction. |
|
| 22 | */ |
|
| 23 | class OrderFixedDiscountAction extends DiscountAction implements DiscountActionContract |
|
| 24 | { |
|
| 25 | const TYPE = 'order_fixed_discount'; |
|
| 26 | ||
| 27 | /** |
|
| 28 | * @var IntegerDistributor |
|
| 29 | */ |
|
| 30 | private $distributor; |
|
| 31 | ||
| 32 | /** |
|
| 33 | * OrderFixedDiscountAction constructor. |
|
| 34 | * |
|
| 35 | * @param IntegerDistributor $distributor |
|
| 36 | */ |
|
| 37 | public function __construct(PercentageIntegerDistributor $distributor) |
|
| 38 | { |
|
| 39 | $this->distributor = $distributor; |
|
| 40 | } |
|
| 41 | ||
| 42 | /** |
|
| 43 | * @param DiscountSubjectContract $subject |
|
| 44 | * @param array $configuration |
|
| 45 | * @param DiscountContract $discount |
|
| 46 | * |
|
| 47 | * @return mixed|void |
|
| 48 | */ |
|
| 49 | public function execute(DiscountSubjectContract $subject, array $configuration, DiscountContract $discount) |
|
| 50 | { |
|
| 51 | $discountAmount = $this->calculateAdjustmentAmount($subject->getCurrentTotal(), $configuration['amount']); |
|
| 52 | ||
| 53 | if (0 === $discountAmount) { |
|
| 54 | return; |
|
| 55 | } |
|
| 56 | ||
| 57 | $adjustment = $this->createAdjustment($discount, $discountAmount); |
|
| 58 | $subject->addAdjustment($adjustment); |
|
| 59 | ||
| 60 | $splitDiscountAmount = $this->distributor->distribute($subject->getItems()->pluck('total')->toArray(), $discountAmount); |
|
| 61 | ||
| 62 | $i = 0; |
|
| 63 | foreach ($subject->getItems() as $item) { |
|
| 64 | $item->divide_order_discount += $splitDiscountAmount[$i++]; |
|
| 65 | $item->recalculateAdjustmentsTotal(); |
|
| 66 | } |
|
| 67 | } |
|
| 68 | ||
| 69 | /** |
|
| 70 | * @param $discountSubjectTotal |
|
| 71 | * @param $targetDiscountAmount |
|
| 72 | * |
|
| 73 | * @return float|int |
|
| 74 | */ |
|
| 75 | private function calculateAdjustmentAmount($discountSubjectTotal, $targetDiscountAmount) |
|
| 76 | { |
|
| 77 | return -1 * min($discountSubjectTotal, $targetDiscountAmount); |
|
| 78 | } |
|
| 79 | ||
| 80 | /** |
|
| 81 | * @param DiscountSubjectContract $subject |
|
| 82 | * @param array $configuration |
|
| 83 | * @param DiscountContract $discount |
|
| 84 | * |
|
| 85 | * @return float|int|mixed |
|
| 86 | */ |
|
| 87 | public function calculate(DiscountSubjectContract $subject, array $configuration, DiscountContract $discount) |
|
| 88 | { |
|
| 89 | $discount->adjustments = new Collection(); |
|
| 90 | ||
| 91 | $discountAmount = $this->calculateAdjustmentAmount($subject->getCurrentTotal(), $configuration['amount']); |
|
| 92 | ||
| 93 | $discount->adjustments->push(['order_id' => $subject->id, 'amount' => $discountAmount]); |
|
| 94 | ||
| 95 | $discount->adjustmentTotal = $discountAmount; |
|
| 96 | ||
| 97 | return $discountAmount; |
|
| 98 | } |
|
| 99 | } |
|
| 100 | ||
| @@ 23-99 (lines=77) @@ | ||
| 20 | /** |
|
| 21 | * Class OrderPercentageDiscountAction. |
|
| 22 | */ |
|
| 23 | class OrderPercentageDiscountAction extends DiscountAction implements DiscountActionContract |
|
| 24 | { |
|
| 25 | const TYPE = 'order_percentage_discount'; |
|
| 26 | ||
| 27 | /** |
|
| 28 | * @var IntegerDistributor |
|
| 29 | */ |
|
| 30 | private $integerDistributor; |
|
| 31 | ||
| 32 | /** |
|
| 33 | * OrderPercentageDiscountAction constructor. |
|
| 34 | * |
|
| 35 | * @param PercentageIntegerDistributor $integerDistributor |
|
| 36 | * @param IntegerDistributor $distributor |
|
| 37 | */ |
|
| 38 | public function __construct(PercentageIntegerDistributor $integerDistributor) |
|
| 39 | { |
|
| 40 | $this->integerDistributor = $integerDistributor; |
|
| 41 | } |
|
| 42 | ||
| 43 | /** |
|
| 44 | * @param DiscountSubjectContract $subject |
|
| 45 | * @param array $configuration |
|
| 46 | * @param DiscountContract $discount |
|
| 47 | * |
|
| 48 | * @return mixed|void |
|
| 49 | */ |
|
| 50 | public function execute(DiscountSubjectContract $subject, array $configuration, DiscountContract $discount) |
|
| 51 | { |
|
| 52 | $discountAmount = $this->calculateAdjustmentAmount($subject->getCurrentTotal(), $configuration['percentage']); |
|
| 53 | if (0 === $discountAmount) { |
|
| 54 | return; |
|
| 55 | } |
|
| 56 | ||
| 57 | $adjustment = $this->createAdjustment($discount, $discountAmount); |
|
| 58 | $subject->addAdjustment($adjustment); |
|
| 59 | ||
| 60 | $splitDiscountAmount = $this->integerDistributor->distribute($subject->getItems()->pluck('total')->toArray(), $discountAmount); |
|
| 61 | ||
| 62 | $i = 0; |
|
| 63 | foreach ($subject->getItems() as $item) { |
|
| 64 | $item->divide_order_discount += $splitDiscountAmount[$i++]; |
|
| 65 | $item->recalculateAdjustmentsTotal(); |
|
| 66 | } |
|
| 67 | } |
|
| 68 | ||
| 69 | /** |
|
| 70 | * @param $discountSubjectTotal |
|
| 71 | * @param $percentage |
|
| 72 | * |
|
| 73 | * @return float|int |
|
| 74 | */ |
|
| 75 | private function calculateAdjustmentAmount($discountSubjectTotal, $percentage) |
|
| 76 | { |
|
| 77 | return -1 * (int) round($discountSubjectTotal * (1 - $percentage / 100)); |
|
| 78 | } |
|
| 79 | ||
| 80 | /** |
|
| 81 | * @param DiscountSubjectContract $subject |
|
| 82 | * @param array $configuration |
|
| 83 | * @param DiscountContract $discount |
|
| 84 | * |
|
| 85 | * @return float|int|mixed |
|
| 86 | */ |
|
| 87 | public function calculate(DiscountSubjectContract $subject, array $configuration, DiscountContract $discount) |
|
| 88 | { |
|
| 89 | $discount->adjustments = new Collection(); |
|
| 90 | ||
| 91 | $discountAmount = $this->calculateAdjustmentAmount($subject->getCurrentTotal(), $configuration['percentage']); |
|
| 92 | ||
| 93 | $discount->adjustments->push(['order_id' => $subject->id, 'amount' => $discountAmount]); |
|
| 94 | ||
| 95 | $discount->adjustmentTotal = $discountAmount; |
|
| 96 | ||
| 97 | return $discountAmount; |
|
| 98 | } |
|
| 99 | } |
|
| 100 | ||