Pārlūkot izejas kodu

fix(core): Fix NaN error thrown when modifying pro-rated discounted OrderLine to 0 (#3009)

jyling 1 gadu atpakaļ
vecāks
revīzija
fa50770467

+ 72 - 0
packages/core/e2e/order-modification.e2e-spec.ts

@@ -2461,6 +2461,78 @@ describe('Order modification', () => {
             expect(modifyOrder.totalWithTax).toBe(getOrderPaymentsTotalWithRefunds(modifyOrder));
             expect(modifyOrder.payments![0].refunds[0].total).toBe(shippingWithTax);
         });
+
+        it('adjustOrderLines empty quantity with discounts', async () => {
+            const PercentDiscount50Percent = '50PERCENT';
+            await adminClient.query<
+                Codegen.CreatePromotionMutation,
+                Codegen.CreatePromotionMutationVariables
+            >(CREATE_PROMOTION, {
+                input: {
+                    enabled: true,
+                    couponCode: PercentDiscount50Percent,
+                    conditions: [
+                        {
+                            code: 'minimum_order_amount',
+                            arguments: [
+                                { name: 'amount', value: '0' },
+                                { name: 'taxInclusive', value: 'false' },
+                            ],
+                        },
+                    ],
+                    actions: [
+                        {
+                            code: orderPercentageDiscount.code,
+                            arguments: [{ name: 'discount', value: '50' }],
+                        },
+                    ],
+                    translations: [{ languageCode: LanguageCode.en, name: 'half price' }],
+                },
+            });
+            await shopClient.asUserWithCredentials('trevor_donnelly96@hotmail.com', 'test');
+            await shopClient.query(gql(ADD_ITEM_TO_ORDER_WITH_CUSTOM_FIELDS), {
+                productVariantId: 'T_1',
+                quantity: 1,
+            } as any);
+            await shopClient.query(gql(ADD_ITEM_TO_ORDER_WITH_CUSTOM_FIELDS), {
+                productVariantId: 'T_2',
+                quantity: 1,
+            } as any);
+
+            await proceedToArrangingPayment(shopClient);
+            const paidOrder = await addPaymentToOrder(shopClient, testSuccessfulPaymentMethod);
+            orderGuard.assertSuccess(paidOrder);
+
+            const transitionOrderToState = await adminTransitionOrderToState(paidOrder.id, 'Modifying');
+            orderGuard.assertSuccess(transitionOrderToState);
+
+            expect(transitionOrderToState.state).toBe('Modifying');
+
+            // modify order should not throw an error when setting quantity to 0 for a order line
+            const { modifyOrder } = await adminClient.query<
+                Codegen.ModifyOrderMutation,
+                Codegen.ModifyOrderMutationVariables
+            >(MODIFY_ORDER, {
+                input: {
+                    dryRun: true,
+                    orderId: order.id,
+                    couponCodes: [PercentDiscount50Percent],
+                    adjustOrderLines: [{ orderLineId: order.lines[0].id, quantity: 0 }],
+                },
+            });
+
+            orderGuard.assertSuccess(modifyOrder);
+            expect(modifyOrder.id).toBeDefined();
+
+            // ensure correct adjustments applied
+            // The first line should have a linePrice of 0 because it has zero quantity
+            expect(modifyOrder.lines[0].linePriceWithTax).toBe(0);
+            expect(modifyOrder.lines[0].proratedLinePriceWithTax).toBe(0);
+            // The second line should have the proratedLinePriceWithTax discounted per the promotion
+            expect(modifyOrder.lines[1].proratedLinePriceWithTax).toBe(
+                modifyOrder.lines[1].discountedLinePriceWithTax / 2,
+            );
+        });
     });
 
     async function adminTransitionOrderToState(id: string, state: string) {

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

@@ -248,9 +248,9 @@ export class OrderCalculator {
                     const adjustment = await promotion.apply(ctx, { order }, state);
                     if (adjustment && adjustment.amount !== 0) {
                         const amount = adjustment.amount;
-                        const weights = order.lines
-                            .filter(l => l.quantity !== 0)
-                            .map(l => l.proratedLinePriceWithTax);
+                        const weights = order.lines.map(l =>
+                            l.quantity !== 0 ? l.proratedLinePriceWithTax : 0,
+                        );
                         const distribution = prorate(weights, amount);
                         order.lines.forEach((line, i) => {
                             const shareOfAmount = distribution[i];