feat(core-flows,types): Refunds can only be performed when order is imbalanced (#8944)

* feat(core-flows,types): Refunds can only be performed when order is imbalanced

* Apply suggestions from code review

Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>

* chore: fix tests

---------

Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
Riqwan Thamir
2024-09-03 13:53:20 +02:00
committed by GitHub
co-authored by Oli Juhl
parent 9a34e03ae1
commit 230acb700b
8 changed files with 382 additions and 581 deletions
@@ -1,8 +1,9 @@
import { BigNumberInput } from "@medusajs/types"
import { MathBN, PaymentEvents } from "@medusajs/utils"
import { BigNumberInput, OrderDTO, PaymentDTO } from "@medusajs/types"
import { MathBN, MedusaError, PaymentEvents } from "@medusajs/utils"
import {
WorkflowData,
WorkflowResponse,
createStep,
createWorkflow,
transform,
when,
@@ -11,6 +12,41 @@ import { emitEventStep, useRemoteQueryStep } from "../../common"
import { addOrderTransactionStep } from "../../order/steps/add-order-transaction"
import { refundPaymentStep } from "../steps/refund-payment"
/**
* This step validates that the refund is valid for the order
*/
export const validateRefundStep = createStep(
"validate-refund-step",
async function ({
order,
payment,
amount,
}: {
order: OrderDTO
payment: PaymentDTO
amount?: BigNumberInput
}) {
const pendingDifference = order.summary?.raw_pending_difference!
if (MathBN.gte(pendingDifference, 0)) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Order does not have an outstanding balance to refund`
)
}
const amountPending = MathBN.mult(pendingDifference, -1)
const amountToRefund = amount ?? payment.raw_amount ?? payment.amount
if (MathBN.gt(amountToRefund, amountPending)) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Cannot refund more than pending difference - ${amountPending}`
)
}
}
)
export const refundPaymentWorkflowId = "refund-payment-workflow"
/**
* This workflow refunds a payment.
@@ -24,28 +60,52 @@ export const refundPaymentWorkflow = createWorkflow(
amount?: BigNumberInput
}>
) => {
const payment = refundPaymentStep(input)
const payment = useRemoteQueryStep({
entry_point: "payment",
fields: [
"id",
"payment_collection_id",
"currency_code",
"amount",
"raw_amount",
],
variables: { id: input.payment_id },
list: false,
throw_if_key_not_found: true,
})
const orderPayment = useRemoteQueryStep({
const orderPaymentCollection = useRemoteQueryStep({
entry_point: "order_payment_collection",
fields: ["order.id"],
variables: { payment_collection_id: payment.payment_collection_id },
list: false,
})
throw_if_key_not_found: true,
}).config({ name: "order-payment-collection" })
when({ orderPayment }, ({ orderPayment }) => {
return !!orderPayment?.order?.id
const order = useRemoteQueryStep({
entry_point: "order",
fields: ["id", "summary", "currency_code", "region_id"],
variables: { id: orderPaymentCollection.order.id },
throw_if_key_not_found: true,
list: false,
}).config({ name: "order" })
validateRefundStep({ order, payment, amount: input.amount })
refundPaymentStep(input)
when({ orderPaymentCollection }, ({ orderPaymentCollection }) => {
return !!orderPaymentCollection?.order?.id
}).then(() => {
const orderTransactionData = transform(
{ input, payment, orderPayment },
({ input, payment, orderPayment }) => {
{ input, payment, orderPaymentCollection },
({ input, payment, orderPaymentCollection }) => {
return {
order_id: orderPayment.order.id,
order_id: orderPaymentCollection.order.id,
amount: MathBN.mult(
input.amount ?? payment.raw_amount ?? payment.amount,
-1
),
currency_code: payment.currency_code,
currency_code: payment.currency_code ?? order.currency_code,
reference_id: payment.id,
reference: "refund",
}