From bcad5052afee4b6474b1fe8389dcbcdfebb61d0e Mon Sep 17 00:00:00 2001 From: Riqwan Thamir Date: Sun, 4 Aug 2024 17:32:06 +0200 Subject: [PATCH] fix(payment): validate total amount when refunding payment (#8437) Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com> --- .../services/payment-module/index.spec.ts | 37 ++++++++++++++++++- .../payment/src/services/payment-module.ts | 13 +++++-- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/packages/modules/payment/integration-tests/__tests__/services/payment-module/index.spec.ts b/packages/modules/payment/integration-tests/__tests__/services/payment-module/index.spec.ts index 2a68d21470..7d810ba2c7 100644 --- a/packages/modules/payment/integration-tests/__tests__/services/payment-module/index.spec.ts +++ b/packages/modules/payment/integration-tests/__tests__/services/payment-module/index.spec.ts @@ -1,12 +1,12 @@ import { IPaymentModuleService } from "@medusajs/types" import { Module, Modules, promiseAll } from "@medusajs/utils" +import { PaymentModuleService } from "@services" import { moduleIntegrationTestRunner } from "medusa-test-utils" import { createPaymentCollections, createPayments, createPaymentSessions, } from "../../../__fixtures__" -import { PaymentModuleService } from "@services" jest.setTimeout(30000) @@ -693,6 +693,41 @@ moduleIntegrationTestRunner({ "You cannot refund more than what is captured on the payment." ) }) + + it("should throw if total refunded amount is greater than captured amount", async () => { + await service.capturePayment({ + amount: 100, + payment_id: "pay-id-1", + }) + + const refundedPayment1 = await service.refundPayment({ + amount: 50, + payment_id: "pay-id-1", + }) + + expect(refundedPayment1).toEqual( + expect.objectContaining({ + id: "pay-id-1", + amount: 100, + refunds: [ + expect.objectContaining({ + amount: 50, + }), + ], + }) + ) + + const error = await service + .refundPayment({ + amount: 60, + payment_id: "pay-id-1", + }) + .catch((e) => e) + + expect(error.message).toEqual( + "You cannot refund more than what is captured on the payment." + ) + }) }) describe("cancel", () => { diff --git a/packages/modules/payment/src/services/payment-module.ts b/packages/modules/payment/src/services/payment-module.ts index eee96f5fa1..e66cf91d3b 100644 --- a/packages/modules/payment/src/services/payment-module.ts +++ b/packages/modules/payment/src/services/payment-module.ts @@ -750,7 +750,7 @@ export default class PaymentModuleService "amount", "raw_amount", ], - relations: ["captures.raw_amount"], + relations: ["captures.raw_amount", "refunds.raw_amount"], }, sharedContext ) @@ -763,9 +763,16 @@ export default class PaymentModuleService const amountAsBigNumber = new BigNumber(next.raw_amount) return MathBN.add(captureAmount, amountAsBigNumber) }, MathBN.convert(0)) - const refundAmount = new BigNumber(data.amount) + const refundedAmount = payment.refunds.reduce((refundedAmount, next) => { + return MathBN.add(refundedAmount, next.raw_amount) + }, MathBN.convert(0)) - if (MathBN.lt(capturedAmount, refundAmount)) { + const totalRefundedAmount = MathBN.add( + refundedAmount, + data.amount + ) + + if (MathBN.lt(capturedAmount, totalRefundedAmount)) { throw new MedusaError( MedusaError.Types.INVALID_DATA, `You cannot refund more than what is captured on the payment.`