Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/MOL-587: Resolve develop #118

Merged
merged 6 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 196 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,202 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).

## v1.2.0-alpha
## v1.2.1

Added

- New custom field for transaction: `sctm_transaction_refund_for_mollie_payment` which would store the Mollie Payment ID that need to be refunded

Fixes

[Create Refund](./docs/CreateRefund.md)
- Handling the Refund Creation for the case that the Payment has more than one Success Charge transaction
- Changing the way to determine the Create Refund action:
- Before
```Typescript
// processor/src/utils/paymentAction.utils.ts

if (groups.successCharge.length === 1 && groups.initialRefund.length) {
return ConnectorActions.CreateRefund;
}
```

- After
```Typescript
// processor/src/utils/paymentAction.utils.ts

if (groups.successCharge.length >= 1 && groups.initialRefund.length) {
return ConnectorActions.CreateRefund;
}
```

- We are supporting to create the refund for the payment which has more than one Success Charge transactions
- By default, we will create the Refund for the latest Success Charge transaction. For example:
```Typescript
// CommerceTools Payment
{
id: 'payment-id',
transactions: [
{
type: 'Charge',
state: 'Success',
interactionId: 'tr_123456' // Mollie Payment ID
},
{
type: 'Charge',
state: 'Success',
interactionId: 'tr_999999' // Mollie Payment ID
},
{
type: 'Refund',
state: 'Initial', // Creating a Refund for the Mollie Payment tr_999999
},
]
}
```

- However, you can also specify the Mollie Payment ID (which stored in the `interactionId` of the Success Charge transaction) that you want to create a refund for by adding the Mollie Payment ID to the custom field `sctm_transaction_refund_for_mollie_payment` of the Initial Refund transaction. For example:

```Typescript
// CommerceTools Payment
{
id: 'payment-id',
transactions: [
{
type: 'Charge',
state: 'Success',
interactionId: 'tr_123456' // Mollie Payment ID
},
{
type: 'Charge',
state: 'Success',
interactionId: 'tr_999999' // Mollie Payment ID
},
{
type: 'Refund',
state: 'Initial',
custom: {
type: {
...
},
fields: {
sctm_transaction_refund_for_mollie_payment: 'tr_123456' // Creating a Refund for the Mollie Payment tr_123456
}
}
},
]
}
```

[Cancel Refund](./docs/CancelPaymentRefund.md)
- Following the changes for creating refund, we also updated the handler for Refund Cancellation to match with the above changes
- Changing the way to determine the Cancel Refund action:
- Before
```Typescript
// processor/src/utils/paymentAction.utils.ts

if (
groups.successCharge.length === 1 &&
groups.pendingRefund.length === 1 &&
groups.initialCancelAuthorization.length === 1
) {
return ConnectorActions.CancelRefund;
}
```

- After
```Typescript
// processor/src/utils/paymentAction.utils.ts

if (
groups.successCharge.length >= 1 &&
groups.pendingRefund.length >= 1 &&
groups.initialCancelAuthorization.length === 1
) {
return ConnectorActions.CancelRefund;
}
```

- To support the old versions, we will create the cancellation for the latest Pending Refund transaction (which is a pending refund for the latest Success Charge transaction in that payment). For example:
```Typescript
// CommerceTools Payment
{
id: 'payment-id',
transactions: [
{
type: 'Charge',
state: 'Success',
interactionId: 'tr_123456' // Mollie Payment ID
},
{
type: 'Charge',
state: 'Success',
interactionId: 'tr_999999' // Mollie Payment ID
},
{
id: 'refund-transaction-1',
type: 'Refund',
state: 'Pending',
interactionId: 're_123456', // Mollie Refund ID
},
{
id: 'refund-transaction-2',
type: 'Refund',
state: 'Pending',
interactionId: 're_999999', // Mollie Refund ID
},
{
type: 'CancelAuthorization',
state: 'Initial'
// interactionId is not set
}
]
}

// In this case, this will be considered as a Cancellation request for the Pending Refund with id: refund-transaction-2
```
__*Note:* The above solution is just for supporting the old versions and will be remove in the near future (in next versions). From this version, please follow the below solution.__

- However, to do it in a correct way, from this version, you should specify the Mollie Refund ID (which stored in the `interactionId` of the Pending Refund transaction) that you want to cancel by putting it in the `interactionId` of the Initial CancelAuthorization. For example:
```Typescript
// CommerceTools Payment
{
id: 'payment-id',
transactions: [
{
type: 'Charge',
state: 'Success',
interactionId: 'tr_123456' // Mollie Payment ID
},
{
type: 'Charge',
state: 'Success',
interactionId: 'tr_999999' // Mollie Payment ID
},
{
id: 'refund-transaction-1',
type: 'Refund',
state: 'Pending',
interactionId: 're_123456', // Mollie Refund ID
},
{
id: 'refund-transaction-2',
type: 'Refund',
state: 'Pending',
interactionId: 're_999999', // Mollie Refund ID
},
{
type: 'CancelAuthorization',
state: 'Initial',
interactionId: 're_123456' // Mollie Refund ID that you want to cancel
}
]
}

// In this case, this will be considered as a Cancellation request for the Pending Refund with id: refund-transaction-1
```

## v1.2.0

Added

Expand Down
6 changes: 6 additions & 0 deletions docs/CancelPaymentRefund.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* [Parameters map](#parameters-map)
* [Representation: CT Payment](#representation-ct-payment)
* [Creating CommerceTools actions from Mollie's response](#creating-commercetools-actions-from-mollies-response)
* [Update per version](#update-per-version)

## Overview
This functionality is used to cancel the pending refund which means it is created but not complete yet.
Expand Down Expand Up @@ -155,3 +156,8 @@ When order is successfully cancelled on Mollie, we update commercetools payment
| `changeTransactionState` | `transactionId: <pendingRefundTransactionId>, state: 'Failure'` |
| `changeTransactionState` | `transactionId: <initialCancelAuthorizationTransactionId>, state: 'Success'` |
| `setTransactionCustomType` | `transactionId: <pendingRefundTransactionId>, type.key:sctm_payment_cancel_reason, fields: {reasonText: "cancellation reason", statusText: "cancelled from shop side"}` |

## Update per version

The function was updated at:
- [v1.2.1](../CHANGELOG.md#v121)
10 changes: 7 additions & 3 deletions docs/CreateRefund.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* [Parameters map](#parameters-map)
* [Representation: CommerceTools Payment](#representation-ct-payment)
* [Creating commercetools actions from Mollie's response](#creating-commercetools-actions-from-mollies-response)
* [Update per version](#update-per-version)

## Overview

Expand All @@ -24,8 +25,6 @@ A transaction with type "Refund" and state "Initial" triggers a refund.

In commercetools, we have a Payment which has one Transaction. This maps to an order in mollie. The commercetools Payment's key is the mollie orderId, and the commercetools Transaction maps to the payment in mollie.

In commercetools, we have a Payment which has one Transaction. This maps to an order in mollie. The commercetools Payment's key is the mollie orderId, and the commercetools Transaction maps to the payment in mollie.

```
{
id: "c0887a2d-bfbf-4f77-8f3d-fc33fb4c0920",
Expand Down Expand Up @@ -96,4 +95,9 @@ transactions: [
]
```

When the refund is completed, this transaction's state will be updated by the notifications module to "Success" or "Failure".
When the refund is completed, this transaction's state will be updated by the notifications module to "Success" or "Failure".

## Update per version

The function was updated at:
- [v1.2.1](../CHANGELOG.md#v121)
82 changes: 81 additions & 1 deletion processor/src/commercetools/customFields.commercetools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ export async function createTransactionSurchargeCustomType(): Promise<void> {
.types()
.post({
body: {
key: CustomFields.createPayment.interfaceInteraction.key,
key: CustomFields.transactionSurchargeCost,
name: {
en: 'SCTM - Transaction surcharge amount',
de: 'SCTM - Betrag des Transaktionszuschlags',
Expand Down Expand Up @@ -379,3 +379,83 @@ export async function createTransactionSurchargeCustomType(): Promise<void> {
return;
}
}

export async function createTransactionRefundForMolliePaymentCustomType(): Promise<void> {
const apiRoot = createApiRoot();
const customFields: FieldDefinition[] = [
{
name: CustomFields.transactionRefundForMolliePayment,
label: {
en: 'Identify the Mollie payment which is being refunded',
de: 'Identifizieren Sie die Mollie-Zahlung, die zurückerstattet wird',
},
required: false,
type: {
name: 'String',
},
inputHint: 'MultiLine',
},
];

const {
body: { results: types },
} = await apiRoot
.types()
.get({
queryArgs: {
where: `key = "${CustomFields.transactionRefundForMolliePayment}"`,
},
})
.execute();

if (types.length <= 0) {
await apiRoot
.types()
.post({
body: {
key: CustomFields.transactionRefundForMolliePayment,
name: {
en: 'Identify the Mollie payment which is being refunded',
de: 'Identifizieren Sie die Mollie-Zahlung, die zurückerstattet wird',
},
resourceTypeIds: ['transaction'],
fieldDefinitions: customFields,
},
})
.execute();

return;
}

const type = types[0];
const definitions = type.fieldDefinitions;

if (definitions.length > 0) {
const actions: TypeUpdateAction[] = [];
definitions.forEach((definition) => {
actions.push({
action: 'removeFieldDefinition',
fieldName: definition.name,
});
});
customFields.forEach((field) => {
actions.push({
action: 'addFieldDefinition',
fieldDefinition: field,
});
});

await apiRoot
.types()
.withKey({ key: CustomFields.transactionRefundForMolliePayment })
.post({
body: {
version: type.version,
actions,
},
})
.execute();

return;
}
}
2 changes: 2 additions & 0 deletions processor/src/service/connector.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import {
createCustomPaymentInterfaceInteractionType,
createCustomPaymentTransactionCancelReasonType,
createTransactionSurchargeCustomType,
createTransactionRefundForMolliePaymentCustomType,
} from '../commercetools/customFields.commercetools';
export const createExtensionAndCustomFields = async (extensionUrl: string): Promise<void> => {
await createPaymentExtension(extensionUrl);
await createCustomPaymentType();
await createCustomPaymentInterfaceInteractionType();
await createCustomPaymentTransactionCancelReasonType();
await createTransactionSurchargeCustomType();
await createTransactionRefundForMolliePaymentCustomType();
};

export const removeExtension = async (): Promise<void> => {
Expand Down
Loading
Loading