Browse Source

fix(core): Fix transition to PaymentSettled with multiple payments

Fixes #847
Michael Bromley 4 years ago
parent
commit
c60fad724c

+ 1 - 1
packages/core/e2e/fixtures/test-payment-methods.ts

@@ -59,7 +59,7 @@ export const partialPaymentMethod = new PaymentMethodHandler({
     createPayment: (ctx, order, amount, args, metadata) => {
         return {
             amount: metadata.amount,
-            state: 'Settled',
+            state: metadata.authorizeOnly ? 'Authorized' : 'Settled',
             transactionId: '12345',
             metadata: { public: metadata },
         };

+ 49 - 0
packages/core/e2e/order.e2e-spec.ts

@@ -1911,6 +1911,55 @@ describe('Orders resolver', () => {
                 orderTotalWithTax - PARTIAL_PAYMENT_AMOUNT,
             );
         });
+
+        // https://github.com/vendure-ecommerce/vendure/issues/847
+        it('manual call to settlePayment works with multiple payments', async () => {
+            const result = await createTestOrder(
+                adminClient,
+                shopClient,
+                customers[1].emailAddress,
+                password,
+            );
+            await proceedToArrangingPayment(shopClient);
+            await shopClient.query<AddPaymentToOrder.Mutation, AddPaymentToOrder.Variables>(ADD_PAYMENT, {
+                input: {
+                    method: partialPaymentMethod.code,
+                    metadata: {
+                        amount: PARTIAL_PAYMENT_AMOUNT,
+                        authorizeOnly: true,
+                    },
+                },
+            });
+            const { addPaymentToOrder: order } = await shopClient.query<
+                AddPaymentToOrder.Mutation,
+                AddPaymentToOrder.Variables
+            >(ADD_PAYMENT, {
+                input: {
+                    method: singleStageRefundablePaymentMethod.code,
+                    metadata: {},
+                },
+            });
+            orderGuard.assertSuccess(order);
+
+            expect(order.state).toBe('PaymentAuthorized');
+
+            const { settlePayment } = await adminClient.query<
+                SettlePayment.Mutation,
+                SettlePayment.Variables
+            >(SETTLE_PAYMENT, {
+                id: order.payments![0].id,
+            });
+
+            paymentGuard.assertSuccess(settlePayment);
+
+            expect(settlePayment.state).toBe('Settled');
+
+            const { order: order2 } = await adminClient.query<GetOrder.Query, GetOrder.Variables>(GET_ORDER, {
+                id: order.id,
+            });
+
+            expect(order2?.state).toBe('PaymentSettled');
+        });
     });
 
     describe('issues', () => {

+ 5 - 11
packages/core/src/service/services/order.service.ts

@@ -820,7 +820,7 @@ export class OrderService {
         if (orderTotalIsCovered(order, 'Settled')) {
             return this.transitionToState(ctx, orderId, 'PaymentSettled');
         }
-        if (orderTotalIsCovered(order, 'Authorized')) {
+        if (orderTotalIsCovered(order, ['Authorized', 'Settled'])) {
             return this.transitionToState(ctx, orderId, 'PaymentAuthorized');
         }
         return order;
@@ -867,16 +867,10 @@ export class OrderService {
             if (payment.state !== 'Settled') {
                 return new SettlePaymentError(payment.errorMessage || '');
             }
-            const orderTotalSettled = payment.amount === payment.order.totalWithTax;
-            if (
-                orderTotalSettled &&
-                this.orderStateMachine.canTransition(payment.order.state, 'PaymentSettled')
-            ) {
-                const orderTransitionResult = await this.transitionToState(
-                    ctx,
-                    payment.order.id,
-                    'PaymentSettled',
-                );
+            const order = await this.findOne(ctx, payment.order.id);
+            if (order) {
+                order.payments = await this.getOrderPayments(ctx, order.id);
+                const orderTransitionResult = await this.transitionOrderIfTotalIsCovered(ctx, order);
                 if (isGraphQlErrorResult(orderTransitionResult)) {
                     return orderTransitionResult;
                 }