feat(core-flows,types,utils): make payment optional when cart balance is 0 (#11872)
what: - make payment optional when cart balance is 0
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { CartWorkflowDTO } from "@medusajs/framework/types"
|
||||
import {
|
||||
isPresent,
|
||||
MathBN,
|
||||
MedusaError,
|
||||
PaymentSessionStatus,
|
||||
} from "@medusajs/framework/utils"
|
||||
@@ -20,13 +21,13 @@ export const validateCartPaymentsStepId = "validate-cart-payments"
|
||||
/**
|
||||
* This step validates a cart's payment sessions. Their status must
|
||||
* be `pending` or `requires_more`. If not valid, the step throws an error.
|
||||
*
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
*
|
||||
* You can use the {@link retrieveCartStep} to retrieve a cart's details.
|
||||
*
|
||||
*
|
||||
* :::
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* const data = validateCartPaymentsStep({
|
||||
* // retrieve the details of the cart from another workflow
|
||||
@@ -38,9 +39,16 @@ export const validateCartPaymentsStep = createStep(
|
||||
validateCartPaymentsStepId,
|
||||
async (data: ValidateCartPaymentsStepInput) => {
|
||||
const {
|
||||
cart: { payment_collection: paymentCollection },
|
||||
cart: { payment_collection: paymentCollection, total, credit_line_total },
|
||||
} = data
|
||||
|
||||
const canSkipPayment =
|
||||
MathBN.convert(credit_line_total).gte(0) && MathBN.convert(total).lte(0)
|
||||
|
||||
if (canSkipPayment) {
|
||||
return new StepResponse([])
|
||||
}
|
||||
|
||||
if (!isPresent(paymentCollection)) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
UsageComputedActions,
|
||||
} from "@medusajs/framework/types"
|
||||
import {
|
||||
isDefined,
|
||||
Modules,
|
||||
OrderStatus,
|
||||
OrderWorkflowEvents,
|
||||
@@ -167,14 +168,16 @@ export const completeCartWorkflow = createWorkflow(
|
||||
|
||||
const cartToOrder = transform({ cart, payment }, ({ cart, payment }) => {
|
||||
const transactions =
|
||||
payment?.captures?.map((capture) => {
|
||||
return {
|
||||
amount: capture.raw_amount ?? capture.amount,
|
||||
currency_code: payment.currency_code,
|
||||
reference: "capture",
|
||||
reference_id: capture.id,
|
||||
}
|
||||
}) ?? []
|
||||
(payment &&
|
||||
payment?.captures?.map((capture) => {
|
||||
return {
|
||||
amount: capture.raw_amount ?? capture.amount,
|
||||
currency_code: payment.currency_code,
|
||||
reference: "capture",
|
||||
reference_id: capture.id,
|
||||
}
|
||||
})) ??
|
||||
[]
|
||||
|
||||
const allItems = (cart.items ?? []).map((item) => {
|
||||
const input: PrepareLineItemDataInput = {
|
||||
@@ -280,19 +283,31 @@ export const completeCartWorkflow = createWorkflow(
|
||||
}
|
||||
})
|
||||
|
||||
parallelize(
|
||||
createRemoteLinkStep([
|
||||
{
|
||||
[Modules.ORDER]: { order_id: createdOrder.id },
|
||||
[Modules.CART]: { cart_id: cart.id },
|
||||
},
|
||||
{
|
||||
[Modules.ORDER]: { order_id: createdOrder.id },
|
||||
[Modules.PAYMENT]: {
|
||||
payment_collection_id: cart.payment_collection.id,
|
||||
const linksToCreate = transform(
|
||||
{ cart, createdOrder },
|
||||
({ cart, createdOrder }) => {
|
||||
const links: Record<string, any>[] = [
|
||||
{
|
||||
[Modules.ORDER]: { order_id: createdOrder.id },
|
||||
[Modules.CART]: { cart_id: cart.id },
|
||||
},
|
||||
},
|
||||
]),
|
||||
]
|
||||
|
||||
if (isDefined(cart.payment_collection?.id)) {
|
||||
links.push({
|
||||
[Modules.ORDER]: { order_id: createdOrder.id },
|
||||
[Modules.PAYMENT]: {
|
||||
payment_collection_id: cart.payment_collection.id,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return links
|
||||
}
|
||||
)
|
||||
|
||||
parallelize(
|
||||
createRemoteLinkStep(linksToCreate),
|
||||
updateCartsStep([updateCompletedAt]),
|
||||
reserveInventoryStep(formatedInventoryItems),
|
||||
emitEventStep({
|
||||
|
||||
@@ -45,6 +45,10 @@ export const authorizePaymentSessionStep = createStep(
|
||||
Modules.PAYMENT
|
||||
)
|
||||
|
||||
if (!input.id) {
|
||||
return new StepResponse(null)
|
||||
}
|
||||
|
||||
try {
|
||||
payment = await paymentModule.authorizePaymentSession(
|
||||
input.id,
|
||||
|
||||
@@ -1033,6 +1033,16 @@ export interface CartDTO {
|
||||
* The raw original shipping tax total of the cart.
|
||||
*/
|
||||
raw_original_shipping_tax_total: BigNumberRawValue
|
||||
|
||||
/**
|
||||
* The raw credit lines total of the cart.
|
||||
*/
|
||||
raw_credit_line_total: BigNumberRawValue
|
||||
|
||||
/**
|
||||
* The credit lines total of the cart.
|
||||
*/
|
||||
credit_line_total: BigNumberValue
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -768,7 +768,7 @@ describe("Total calculation", function () {
|
||||
},
|
||||
],
|
||||
total: 48,
|
||||
subtotal: 60,
|
||||
subtotal: 100,
|
||||
tax_total: 8,
|
||||
discount_total: 22,
|
||||
discount_subtotal: 20,
|
||||
|
||||
@@ -208,8 +208,6 @@ export function decorateCartTotals(
|
||||
taxRate: creditLinesSumTaxRate,
|
||||
})
|
||||
|
||||
subtotal = MathBN.sub(subtotal, creditLinesSubtotal)
|
||||
|
||||
const taxTotal = MathBN.add(itemsTaxTotal, shippingTaxTotal)
|
||||
|
||||
const originalTaxTotal = MathBN.add(
|
||||
@@ -222,7 +220,7 @@ export function decorateCartTotals(
|
||||
|
||||
// TODO: subtract (cart.gift_card_total + cart.gift_card_tax_total)
|
||||
const tempTotal = MathBN.add(subtotal, taxTotal)
|
||||
const total = MathBN.sub(tempTotal, discountSubtotal)
|
||||
const total = MathBN.sub(tempTotal, discountSubtotal, creditLinesTotal)
|
||||
|
||||
const cart = cartLike as any
|
||||
|
||||
|
||||
Reference in New Issue
Block a user