Skip to content

Commit

Permalink
Fix based on reviews
Browse files Browse the repository at this point in the history
  • Loading branch information
NghiaDTr committed Dec 11, 2024
1 parent ba3966a commit 112a8e4
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 5 deletions.
18 changes: 13 additions & 5 deletions processor/src/service/payment.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -536,9 +537,9 @@ export const handleCreateRefund = async (ctPayment: Payment): Promise<Controller
} else {
logger.debug('SCTM - handleCreateRefund - creating a refund for the latest success charge transaction');

const reversedTransactions = Object.assign([], ctPayment.transactions).reverse() as Transaction[];
const latestTransactions = sortTransactionsByLatestCreationTime(ctPayment.transactions);

successChargeTransaction = reversedTransactions.find(
successChargeTransaction = latestTransactions.find(
(transaction) =>
transaction.type === CTTransactionType.Charge && transaction.state === CTTransactionState.Success,
);
Expand Down Expand Up @@ -605,20 +606,27 @@ export const handlePaymentCancelRefund = async (ctPayment: Payment): Promise<Con
pendingRefundTransaction?.custom?.fields[CustomFields.transactionRefundForMolliePayment],
) as Transaction;
}

if (!successChargeTransaction) {
throw new CustomError(
400,
'SCTM - handlePaymentCancelRefund - Cannot find the valid Success Charge transaction.',
);
}
}

/**
* @deprecated v1.2 - Will be remove in the next version
*/
if (!pendingRefundTransaction || !successChargeTransaction) {
const reversedTransactions = Object.assign([], ctPayment.transactions).reverse() as Transaction[];
const latestTransactions = sortTransactionsByLatestCreationTime(ctPayment.transactions);

pendingRefundTransaction = reversedTransactions.find(
pendingRefundTransaction = latestTransactions.find(
(transaction) =>
transaction.type === CTTransactionType.Refund && transaction.state === CTTransactionState.Pending,
);

successChargeTransaction = reversedTransactions.find(
successChargeTransaction = latestTransactions.find(
(transaction) =>
transaction.type === CTTransactionType.Charge && transaction.state === CTTransactionState.Success,
);
Expand Down
148 changes: 148 additions & 0 deletions processor/tests/service/payment.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1724,6 +1724,7 @@ describe('Test handleCreateRefund', () => {
transactions: [
{
id: uuid,
timestamp: '2024-06-24T08:28:43.474Z',
type: 'Charge',
interactionId: 'tr_123123',
amount: {
Expand All @@ -1736,6 +1737,7 @@ describe('Test handleCreateRefund', () => {
},
{
id: 'test-123',
timestamp: '2024-06-24T08:30:43.474Z',
type: 'Charge',
interactionId: targetedMolliePaymentId,
amount: {
Expand Down Expand Up @@ -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', () => {
Expand Down

0 comments on commit 112a8e4

Please sign in to comment.