From 112a8e450a7a33354eda7e0156036d3f9b29d77b Mon Sep 17 00:00:00 2001 From: Nghia Tran Date: Wed, 11 Dec 2024 15:37:56 +0700 Subject: [PATCH] Fix based on reviews --- processor/src/service/payment.service.ts | 18 ++- .../tests/service/payment.service.spec.ts | 148 ++++++++++++++++++ 2 files changed, 161 insertions(+), 5 deletions(-) diff --git a/processor/src/service/payment.service.ts b/processor/src/service/payment.service.ts index 01d678b..7323a88 100644 --- a/processor/src/service/payment.service.ts +++ b/processor/src/service/payment.service.ts @@ -71,6 +71,7 @@ import { convertCentToEUR, parseStringToJsonObject, roundSurchargeAmountToCent, + sortTransactionsByLatestCreationTime, } from '../utils/app.utils'; import ApplePaySession from '@mollie/api-client/dist/types/src/data/applePaySession/ApplePaySession'; import { getMethodConfigObjects, getSingleMethodConfigObject } from '../commercetools/customObjects.commercetools'; @@ -536,9 +537,9 @@ export const handleCreateRefund = async (ctPayment: Payment): Promise transaction.type === CTTransactionType.Charge && transaction.state === CTTransactionState.Success, ); @@ -605,20 +606,27 @@ export const handlePaymentCancelRefund = async (ctPayment: Payment): Promise transaction.type === CTTransactionType.Refund && transaction.state === CTTransactionState.Pending, ); - successChargeTransaction = reversedTransactions.find( + successChargeTransaction = latestTransactions.find( (transaction) => transaction.type === CTTransactionType.Charge && transaction.state === CTTransactionState.Success, ); diff --git a/processor/tests/service/payment.service.spec.ts b/processor/tests/service/payment.service.spec.ts index b9dc840..1aab09e 100644 --- a/processor/tests/service/payment.service.spec.ts +++ b/processor/tests/service/payment.service.spec.ts @@ -1724,6 +1724,7 @@ describe('Test handleCreateRefund', () => { transactions: [ { id: uuid, + timestamp: '2024-06-24T08:28:43.474Z', type: 'Charge', interactionId: 'tr_123123', amount: { @@ -1736,6 +1737,7 @@ describe('Test handleCreateRefund', () => { }, { id: 'test-123', + timestamp: '2024-06-24T08:30:43.474Z', type: 'Charge', interactionId: targetedMolliePaymentId, amount: { @@ -2335,6 +2337,152 @@ describe('Test handlePaymentCancelRefund', () => { paymentId: CTPaymentMocked.transactions[1].interactionId, }); }); + + it('should throw error if valid Success Charge transaction was not found (interactionId is defined in the Initial CancelAuthorization transaction)', async () => { + const CTPaymentMocked: Payment = { + id: '5c8b0375-305a-4f19-ae8e-07806b101999', + version: 1, + createdAt: '2024-07-04T14:07:35.625Z', + lastModifiedAt: '2024-07-04T14:07:35.625Z', + amountPlanned: { + type: 'centPrecision', + currencyCode: 'EUR', + centAmount: 1000, + fractionDigits: 2, + }, + paymentStatus: {}, + transactions: [ + { + id: '5c8b0375-305a-4f19-ae8e-07806b101992', + type: 'Charge', + interactionId: 'tr_test123123', + amount: { + type: 'centPrecision', + currencyCode: 'EUR', + centAmount: 1000, + fractionDigits: 2, + }, + state: 'Success', + }, + { + id: '5c8b0375-305a-4f19-ae8e-07806b101999', + type: 'Charge', + interactionId: 'tr_dummy', + amount: { + type: 'centPrecision', + currencyCode: 'EUR', + centAmount: 1000, + fractionDigits: 2, + }, + state: 'Success', + }, + { + id: '5c8b0375-305a-4f19-ae8e-07806b102011', + type: 'Refund', + interactionId: 're_TEST', + amount: { + type: 'centPrecision', + currencyCode: 'EUR', + centAmount: 1000, + fractionDigits: 2, + }, + state: 'Pending', + }, + { + id: '5c8b0375-305a-4f19-ae8e-07806b102000', + type: 'Refund', + interactionId: 're_4qqhO89gsT', + amount: { + type: 'centPrecision', + currencyCode: 'EUR', + centAmount: 1000, + fractionDigits: 2, + }, + state: 'Pending', + custom: { + type: { + typeId: 'type', + id: 'custom-type', + }, + fields: { + [CustomFieldName.transactionRefundForMolliePayment]: 'tr_123123', + }, + }, + }, + { + id: '5c8b0375-305a-4f19-ae8e-07806b102000', + type: 'CancelAuthorization', + interactionId: 're_4qqhO89gsT', + amount: { + type: 'centPrecision', + currencyCode: 'EUR', + centAmount: 1000, + fractionDigits: 2, + }, + state: 'Initial', + custom: { + type: { + typeId: 'type', + id: 'sctm_payment_cancel_reason', + }, + fields: { + reasonText: 'dummy reason', + }, + }, + }, + ], + interfaceInteractions: [], + paymentMethodInfo: { + method: 'creditcard', + }, + }; + + const mollieRefund: Refund = { + resource: 'refund', + id: CTPaymentMocked.transactions[3].interactionId, + description: 'Order', + amount: { + currency: 'EUR', + value: '5.95', + }, + status: 'pending', + metadata: '{"bookkeeping_id":12345}', + paymentId: 'tr_7UhSN1zuXS', + createdAt: '2023-03-14T17:09:02.0Z', + _links: { + self: { + href: '...', + type: 'application/hal+json', + }, + payment: { + href: 'https://api.mollie.com/v2/payments/tr_7UhSN1zuXS', + type: 'application/hal+json', + }, + documentation: { + href: '...', + type: 'text/html', + }, + }, + } as Refund; + + (getPaymentRefund as jest.Mock).mockReturnValueOnce(mollieRefund); + + (cancelPaymentRefund as jest.Mock).mockReturnValueOnce(true); + + (getPaymentCancelActions as jest.Mock).mockReturnValueOnce([]); + + try { + await handlePaymentCancelRefund(CTPaymentMocked); + } catch (error: any) { + expect(getPaymentRefund).toBeCalledTimes(0); + expect(cancelPaymentRefund).toBeCalledTimes(0); + + expect(error).toBeInstanceOf(CustomError); + expect((error as CustomError).message).toBe( + 'SCTM - handlePaymentCancelRefund - Cannot find the valid Success Charge transaction.', + ); + } + }); }); describe('Test handlePaymentWebhook', () => {