Parcourir la source

fix(core): Correctly prorate order discounts over differing tax rates

Fixes #653
Michael Bromley il y a 5 ans
Parent
commit
b128425977

+ 44 - 2
packages/core/src/service/helpers/order-calculator/order-calculator.spec.ts

@@ -613,6 +613,48 @@ describe('OrderCalculator', () => {
                     assertOrderTotalsAddUp(order);
                 });
             });
+
+            it('correct proration', async () => {
+                const promotion = new Promotion({
+                    id: 1,
+                    name: '$5 off order',
+                    conditions: [{ code: alwaysTrueCondition.code, args: [] }],
+                    promotionConditions: [alwaysTrueCondition],
+                    actions: [
+                        {
+                            code: fixedDiscountOrderAction.code,
+                            args: [],
+                        },
+                    ],
+                    promotionActions: [fixedDiscountOrderAction],
+                });
+
+                const ctx = createRequestContext({ pricesIncludeTax: true });
+                const order = createOrder({
+                    ctx,
+                    lines: [
+                        {
+                            listPrice: 500,
+                            taxCategory: taxCategoryStandard,
+                            quantity: 1,
+                        },
+                        {
+                            listPrice: 500,
+                            taxCategory: taxCategoryZero,
+                            quantity: 1,
+                        },
+                    ],
+                });
+                await orderCalculator.applyPriceAdjustments(ctx, order, [promotion]);
+
+                expect(order.subTotalWithTax).toBe(500);
+                expect(order.discounts.length).toBe(1);
+                expect(order.discounts[0].description).toBe('$5 off order');
+                expect(order.lines[0].proratedLinePriceWithTax).toBe(250);
+                expect(order.lines[1].proratedLinePriceWithTax).toBe(250);
+                expect(order.totalWithTax).toBe(500);
+                assertOrderTotalsAddUp(order);
+            });
         });
 
         describe('Shipping-level discounts', () => {
@@ -1052,7 +1094,7 @@ describe('OrderCalculator', () => {
                     ]);
 
                     expect(order.subTotal).toBe(5719);
-                    expect(order.subTotalWithTax).toBe(6440);
+                    expect(order.subTotalWithTax).toBe(6448);
                     assertOrderTotalsAddUp(order);
                 });
 
@@ -1084,7 +1126,7 @@ describe('OrderCalculator', () => {
                         $5OffOrderPromo,
                     ]);
 
-                    expect(order.subTotal).toBe(5084);
+                    expect(order.subTotal).toBe(5082);
                     expect(order.subTotalWithTax).toBe(5719);
                     assertOrderTotalsAddUp(order);
                 });

+ 1 - 1
packages/core/src/service/helpers/order-calculator/order-calculator.ts

@@ -276,7 +276,7 @@ export class OrderCalculator {
                     const adjustment = await promotion.apply(ctx, { order });
                     if (adjustment && adjustment.amount !== 0) {
                         const amount = adjustment.amount;
-                        const weights = order.lines.map(l => l.proratedLinePrice * Math.max(l.taxRate, 1));
+                        const weights = order.lines.map(l => l.proratedLinePriceWithTax);
                         const distribution = prorate(weights, amount);
                         order.lines.forEach((line, i) => {
                             const shareOfAmount = distribution[i];