33namespace Drupal \commerce_promotion \Plugin \Commerce \PromotionOffer ;
44
55use Drupal \commerce_order \Adjustment ;
6+ use Drupal \commerce_order \PriceSplitterInterface ;
7+ use Drupal \commerce_price \RounderInterface ;
68use Drupal \commerce_promotion \Entity \PromotionInterface ;
79use Drupal \Core \Entity \EntityInterface ;
10+ use Symfony \Component \DependencyInjection \ContainerInterface ;
811
912/**
1013 * Provides the fixed amount off offer for orders.
1114 *
15+ * The discount is split between order items, to simplify VAT taxes and refunds.
16+ *
1217 * @CommercePromotionOffer(
1318 * id = "order_fixed_amount_off",
1419 * label = @Translation("Fixed amount off the order subtotal"),
1722 */
1823class OrderFixedAmountOff extends FixedAmountOffBase {
1924
25+ /**
26+ * The price splitter.
27+ *
28+ * @var \Drupal\commerce_order\PriceSplitterInterface
29+ */
30+ protected $ splitter ;
31+
32+ /**
33+ * Constructs a new OrderFixedAmountOff object.
34+ *
35+ * @param array $configuration
36+ * A configuration array containing information about the plugin instance.
37+ * @param string $plugin_id
38+ * The pluginId for the plugin instance.
39+ * @param mixed $plugin_definition
40+ * The plugin implementation definition.
41+ * @param \Drupal\commerce_price\RounderInterface $rounder
42+ * The rounder.
43+ * @param \Drupal\commerce_order\PriceSplitterInterface $splitter
44+ * The splitter.
45+ */
46+ public function __construct (array $ configuration , $ plugin_id , $ plugin_definition , RounderInterface $ rounder , PriceSplitterInterface $ splitter ) {
47+ parent ::__construct ($ configuration , $ plugin_id , $ plugin_definition , $ rounder );
48+
49+ $ this ->splitter = $ splitter ;
50+ }
51+
52+ /**
53+ * {@inheritdoc}
54+ */
55+ public static function create (ContainerInterface $ container , array $ configuration , $ plugin_id , $ plugin_definition ) {
56+ return new static (
57+ $ configuration ,
58+ $ plugin_id ,
59+ $ plugin_definition ,
60+ $ container ->get ('commerce_price.rounder ' ),
61+ $ container ->get ('commerce_order.price_splitter ' )
62+ );
63+ }
64+
2065 /**
2166 * {@inheritdoc}
2267 */
@@ -25,23 +70,29 @@ public function apply(EntityInterface $entity, PromotionInterface $promotion) {
2570 /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
2671 $ order = $ entity ;
2772 $ subtotal_price = $ order ->getSubTotalPrice ();
28- $ adjustment_amount = $ this ->getAmount ();
29- if ($ subtotal_price ->getCurrencyCode () != $ adjustment_amount ->getCurrencyCode ()) {
73+ $ amount = $ this ->getAmount ();
74+ if ($ subtotal_price ->getCurrencyCode () != $ amount ->getCurrencyCode ()) {
3075 return ;
3176 }
3277 // The promotion amount can't be larger than the subtotal, to avoid
3378 // potentially having a negative order total.
34- if ($ adjustment_amount ->greaterThan ($ subtotal_price )) {
35- $ adjustment_amount = $ subtotal_price ;
79+ if ($ amount ->greaterThan ($ subtotal_price )) {
80+ $ amount = $ subtotal_price ;
3681 }
82+ // Split the amount between order items.
83+ $ amounts = $ this ->splitter ->split ($ order , $ amount );
3784
38- $ order ->addAdjustment (new Adjustment ([
39- 'type ' => 'promotion ' ,
40- // @todo Change to label from UI when added in #2770731.
41- 'label ' => t ('Discount ' ),
42- 'amount ' => $ adjustment_amount ->multiply ('-1 ' ),
43- 'source_id ' => $ promotion ->id (),
44- ]));
85+ foreach ($ order ->getItems () as $ order_item ) {
86+ if (isset ($ amounts [$ order_item ->id ()])) {
87+ $ order_item ->addAdjustment (new Adjustment ([
88+ 'type ' => 'promotion ' ,
89+ // @todo Change to label from UI when added in #2770731.
90+ 'label ' => t ('Discount ' ),
91+ 'amount ' => $ amounts [$ order_item ->id ()]->multiply ('-1 ' ),
92+ 'source_id ' => $ promotion ->id (),
93+ ]));
94+ }
95+ }
4596 }
4697
4798}
0 commit comments