Browse Source

fix(core): Order calculator supports multiple shipping lines

Fixes #1897
Michael Bromley 3 years ago
parent
commit
06e2be2362

+ 31 - 0
packages/core/src/service/helpers/order-calculator/order-calculator.spec.ts

@@ -155,6 +155,37 @@ describe('OrderCalculator', () => {
             expect(order.totalWithTax).toBe(order.subTotalWithTax + 500);
             assertOrderTotalsAddUp(order);
         });
+
+        it('multiple shipping lines', async () => {
+            const ctx = createRequestContext({ pricesIncludeTax: false });
+            const order = createOrder({
+                ctx,
+                lines: [
+                    {
+                        listPrice: 100,
+                        taxCategory: taxCategoryStandard,
+                        quantity: 1,
+                    },
+                ],
+            });
+            order.shippingLines = [
+                new ShippingLine({
+                    shippingMethodId: mockShippingMethodId,
+                }),
+                new ShippingLine({
+                    shippingMethodId: mockShippingMethodId,
+                }),
+            ];
+            await orderCalculator.applyPriceAdjustments(ctx, order, []);
+
+            expect(order.shippingLines.length).toBe(2);
+            expect(order.subTotal).toBe(100);
+            expect(order.shipping).toBe(1000);
+            expect(order.shippingWithTax).toBe(1200);
+            expect(order.total).toBe(order.subTotal + 1000);
+            expect(order.totalWithTax).toBe(order.subTotalWithTax + 1200);
+            assertOrderTotalsAddUp(order);
+        });
     });
 
     describe('promotions', () => {

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

@@ -398,45 +398,46 @@ export class OrderCalculator {
     }
 
     private async applyShipping(ctx: RequestContext, order: Order) {
-        const shippingLine: ShippingLine | undefined = order.shippingLines[0];
-        const currentShippingMethod =
-            shippingLine?.shippingMethodId &&
-            (await this.shippingMethodService.findOne(ctx, shippingLine.shippingMethodId));
-        if (!currentShippingMethod) {
-            return;
-        }
-        const currentMethodStillEligible = await currentShippingMethod.test(ctx, order);
-        if (currentMethodStillEligible) {
-            const result = await currentShippingMethod.apply(ctx, order);
-            if (result) {
-                shippingLine.listPrice = result.price;
-                shippingLine.listPriceIncludesTax = result.priceIncludesTax;
+        for (const shippingLine of order.shippingLines) {
+            const currentShippingMethod =
+                shippingLine?.shippingMethodId &&
+                (await this.shippingMethodService.findOne(ctx, shippingLine.shippingMethodId));
+            if (!currentShippingMethod) {
+                return;
+            }
+            const currentMethodStillEligible = await currentShippingMethod.test(ctx, order);
+            if (currentMethodStillEligible) {
+                const result = await currentShippingMethod.apply(ctx, order);
+                if (result) {
+                    shippingLine.listPrice = result.price;
+                    shippingLine.listPriceIncludesTax = result.priceIncludesTax;
+                    shippingLine.taxLines = [
+                        {
+                            description: 'shipping tax',
+                            taxRate: result.taxRate,
+                        },
+                    ];
+                }
+                continue;
+            }
+            const results = await this.shippingCalculator.getEligibleShippingMethods(ctx, order, [
+                currentShippingMethod.id,
+            ]);
+            if (results && results.length) {
+                const cheapest = results[0];
+                shippingLine.listPrice = cheapest.result.price;
+                shippingLine.listPriceIncludesTax = cheapest.result.priceIncludesTax;
+                shippingLine.shippingMethod = cheapest.method;
+                shippingLine.shippingMethodId = cheapest.method.id;
                 shippingLine.taxLines = [
                     {
                         description: 'shipping tax',
-                        taxRate: result.taxRate,
+                        taxRate: cheapest.result.taxRate,
                     },
                 ];
+            } else {
+                order.shippingLines = order.shippingLines.filter(sl => sl !== shippingLine);
             }
-            return;
-        }
-        const results = await this.shippingCalculator.getEligibleShippingMethods(ctx, order, [
-            currentShippingMethod.id,
-        ]);
-        if (results && results.length) {
-            const cheapest = results[0];
-            shippingLine.listPrice = cheapest.result.price;
-            shippingLine.listPriceIncludesTax = cheapest.result.priceIncludesTax;
-            shippingLine.shippingMethod = cheapest.method;
-            shippingLine.shippingMethodId = cheapest.method.id;
-            shippingLine.taxLines = [
-                {
-                    description: 'shipping tax',
-                    taxRate: cheapest.result.taxRate,
-                },
-            ];
-        } else {
-            order.shippingLines = [];
         }
     }
 

+ 1 - 6
packages/core/src/service/services/promotion.service.ts

@@ -165,12 +165,7 @@ export class PromotionService {
         }
         promotion.priorityScore = this.calculatePriorityScore(input);
         await this.connection.getRepository(ctx, Promotion).save(updatedPromotion, { reload: false });
-        await this.customFieldRelationService.updateRelations(
-            ctx,
-            Promotion,
-            input,
-            updatedPromotion,
-        );
+        await this.customFieldRelationService.updateRelations(ctx, Promotion, input, updatedPromotion);
         this.eventBus.publish(new PromotionEvent(ctx, promotion, 'updated', input));
         return assertFound(this.findOne(ctx, updatedPromotion.id));
     }