feat(medusa,core-flows): complete cart [part-1] (#7201)
what: - adds a very basic complete cart endpoint that creates an order - the complete cart workflow currently does the following: - create tax lines - create order
This commit is contained in:
1 parent
e78362c000
commit
f129415650
19 files changed
+554
-34
No files matched your search
@@ -0,0 +1,57 @@
|
||||
import { CartWorkflowDTO } from "@medusajs/types"
|
||||
import { OrderStatus } from "@medusajs/utils"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
import { createOrdersWorkflow } from "../../../order/workflows/create-orders"
|
||||
|
||||
interface StepInput {
|
||||
cart: CartWorkflowDTO
|
||||
}
|
||||
|
||||
export const createOrderFromCartStepId = "create-order-from-cart"
|
||||
export const createOrderFromCartStep = createStep(
|
||||
createOrderFromCartStepId,
|
||||
async (input: StepInput, { container }) => {
|
||||
const { cart } = input
|
||||
|
||||
const itemAdjustments = (cart.items || [])
|
||||
?.map((item) => item.adjustments || [])
|
||||
.flat(1)
|
||||
const shippingAdjustments = (cart.shipping_methods || [])
|
||||
?.map((sm) => sm.adjustments || [])
|
||||
.flat(1)
|
||||
|
||||
const promoCodes = [...itemAdjustments, ...shippingAdjustments]
|
||||
.map((adjustment) => adjustment.code)
|
||||
.filter((code) => Boolean) as string[]
|
||||
|
||||
const { transaction, result } = await createOrdersWorkflow(container).run({
|
||||
input: {
|
||||
region_id: cart.region?.id,
|
||||
customer_id: cart.customer?.id,
|
||||
sales_channel_id: cart.sales_channel_id,
|
||||
status: OrderStatus.PENDING,
|
||||
email: cart.email,
|
||||
currency_code: cart.currency_code,
|
||||
shipping_address: cart.shipping_address,
|
||||
billing_address: cart.billing_address,
|
||||
// TODO: This should be handle correctly
|
||||
no_notification: false,
|
||||
items: cart.items,
|
||||
shipping_methods: cart.shipping_methods,
|
||||
metadata: cart.metadata,
|
||||
promo_codes: promoCodes,
|
||||
},
|
||||
})
|
||||
|
||||
return new StepResponse(result, { transaction })
|
||||
},
|
||||
async (flow, { container }) => {
|
||||
if (!flow) {
|
||||
return
|
||||
}
|
||||
|
||||
await createOrdersWorkflow(container).cancel({
|
||||
transaction: flow.transaction,
|
||||
})
|
||||
}
|
||||
)
|
||||
@@ -3,6 +3,7 @@ export * from "./add-to-cart"
|
||||
export * from "./confirm-inventory"
|
||||
export * from "./create-carts"
|
||||
export * from "./create-line-item-adjustments"
|
||||
export * from "./create-order-from-cart"
|
||||
export * from "./create-shipping-method-adjustments"
|
||||
export * from "./find-one-or-any-region"
|
||||
export * from "./find-or-create-customer"
|
||||
|
||||
@@ -10,3 +10,43 @@ export const cartFieldsForRefreshSteps = [
|
||||
"customer.*",
|
||||
"customer.groups.*",
|
||||
]
|
||||
|
||||
export const completeCartFields = [
|
||||
"id",
|
||||
"currency_code",
|
||||
"email",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"total",
|
||||
"subtotal",
|
||||
"tax_total",
|
||||
"discount_total",
|
||||
"discount_tax_total",
|
||||
"original_total",
|
||||
"original_tax_total",
|
||||
"item_total",
|
||||
"item_subtotal",
|
||||
"item_tax_total",
|
||||
"sales_channel_id",
|
||||
"original_item_total",
|
||||
"original_item_subtotal",
|
||||
"original_item_tax_total",
|
||||
"shipping_total",
|
||||
"shipping_subtotal",
|
||||
"shipping_tax_total",
|
||||
"original_shipping_tax_total",
|
||||
"original_shipping_tax_subtotal",
|
||||
"original_shipping_total",
|
||||
"items.*",
|
||||
"items.tax_lines.*",
|
||||
"items.adjustments.*",
|
||||
"customer.*",
|
||||
"shipping_methods.*",
|
||||
"shipping_methods.tax_lines.*",
|
||||
"shipping_methods.adjustments.*",
|
||||
"shipping_address.*",
|
||||
"billing_address.*",
|
||||
"region.*",
|
||||
"payment_collection.*",
|
||||
"payment_collection.payment_sessions.*",
|
||||
]
|
||||
@@ -1,15 +1,30 @@
|
||||
import { BigNumberInput, ProductVariantDTO } from "@medusajs/types"
|
||||
import {
|
||||
BigNumberInput,
|
||||
CreateOrderAdjustmentDTO,
|
||||
CreateOrderLineItemTaxLineDTO,
|
||||
ProductVariantDTO,
|
||||
} from "@medusajs/types"
|
||||
|
||||
interface Input {
|
||||
quantity: BigNumberInput
|
||||
metadata?: Record<string, any>
|
||||
unitPrice: BigNumberInput
|
||||
variant: ProductVariantDTO
|
||||
taxLines?: CreateOrderLineItemTaxLineDTO[]
|
||||
adjustments?: CreateOrderAdjustmentDTO[]
|
||||
cartId?: string
|
||||
}
|
||||
|
||||
export function prepareLineItemData(data: Input) {
|
||||
const { variant, unitPrice, quantity, metadata, cartId } = data
|
||||
const {
|
||||
variant,
|
||||
unitPrice,
|
||||
quantity,
|
||||
metadata,
|
||||
cartId,
|
||||
taxLines,
|
||||
adjustments,
|
||||
} = data
|
||||
|
||||
if (!variant.product) {
|
||||
throw new Error("Variant does not have a product")
|
||||
@@ -39,9 +54,37 @@ export function prepareLineItemData(data: Input) {
|
||||
metadata,
|
||||
}
|
||||
|
||||
if (taxLines) {
|
||||
lineItem.tax_lines = prepareTaxLinesData(taxLines)
|
||||
}
|
||||
|
||||
if (adjustments) {
|
||||
lineItem.adjustments = prepareAdjustmentsData(adjustments)
|
||||
}
|
||||
|
||||
if (cartId) {
|
||||
lineItem.cart_id = cartId
|
||||
}
|
||||
|
||||
return lineItem
|
||||
}
|
||||
|
||||
export function prepareTaxLinesData(data: CreateOrderLineItemTaxLineDTO[]) {
|
||||
return data.map((d) => ({
|
||||
description: d.description,
|
||||
tax_rate_id: d.tax_rate_id,
|
||||
code: d.code,
|
||||
rate: d.rate,
|
||||
provider_id: d.provider_id,
|
||||
}))
|
||||
}
|
||||
|
||||
export function prepareAdjustmentsData(data: CreateOrderAdjustmentDTO[]) {
|
||||
return data.map((d) => ({
|
||||
code: d.code,
|
||||
amount: d.amount,
|
||||
description: d.description,
|
||||
promotion_id: d.promotion_id,
|
||||
provider_id: d.promotion_id,
|
||||
}))
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { CompleteCartWorkflowInputDTO, OrderDTO } from "@medusajs/types"
|
||||
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
|
||||
import { useRemoteQueryStep } from "../../../common"
|
||||
import { createOrderFromCartStep } from "../steps"
|
||||
import { updateTaxLinesStep } from "../steps/update-tax-lines"
|
||||
import { completeCartFields } from "../utils/fields"
|
||||
|
||||
/*
|
||||
- [] Create Tax Lines
|
||||
- [] Authorize Payment
|
||||
- fail:
|
||||
- [] Delete Tax lines
|
||||
- [] Reserve Item from inventory (if enabled)
|
||||
- fail:
|
||||
- [] Delete reservations
|
||||
- [] Cancel Payment
|
||||
- [] Create order
|
||||
*/
|
||||
export const completeCartWorkflowId = "complete-cart"
|
||||
export const completeCartWorkflow = createWorkflow(
|
||||
completeCartWorkflowId,
|
||||
(
|
||||
input: WorkflowData<CompleteCartWorkflowInputDTO>
|
||||
): WorkflowData<OrderDTO> => {
|
||||
const cart = useRemoteQueryStep({
|
||||
entry_point: "cart",
|
||||
fields: completeCartFields,
|
||||
variables: { id: input.id },
|
||||
list: false,
|
||||
})
|
||||
|
||||
updateTaxLinesStep({ cart_or_cart_id: cart, force_tax_calculation: true })
|
||||
|
||||
const finalCart = useRemoteQueryStep({
|
||||
entry_point: "cart",
|
||||
fields: completeCartFields,
|
||||
variables: { id: input.id },
|
||||
list: false,
|
||||
}).config({ name: "final-cart" })
|
||||
|
||||
return createOrderFromCartStep({ cart: finalCart })
|
||||
}
|
||||
)
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from "./add-shipping-method-to-cart"
|
||||
export * from "./add-to-cart"
|
||||
export * from "./complete-cart"
|
||||
export * from "./create-carts"
|
||||
export * from "./create-payment-collection-for-cart"
|
||||
export * from "./list-shipping-options-for-cart"
|
||||
|
||||
@@ -7,15 +7,13 @@ import {
|
||||
transform,
|
||||
} from "@medusajs/workflows-sdk"
|
||||
import { useRemoteQueryStep } from "../../common"
|
||||
import {
|
||||
confirmInventoryStep,
|
||||
findOneOrAnyRegionStep,
|
||||
findOrCreateCustomerStep,
|
||||
findSalesChannelStep,
|
||||
getVariantPriceSetsStep,
|
||||
getVariantsStep,
|
||||
validateVariantsExistStep,
|
||||
} from "../../definition/cart"
|
||||
import { confirmInventoryStep } from "../../definition/cart/steps/confirm-inventory"
|
||||
import { findOneOrAnyRegionStep } from "../../definition/cart/steps/find-one-or-any-region"
|
||||
import { findOrCreateCustomerStep } from "../../definition/cart/steps/find-or-create-customer"
|
||||
import { findSalesChannelStep } from "../../definition/cart/steps/find-sales-channel"
|
||||
import { getVariantPriceSetsStep } from "../../definition/cart/steps/get-variant-price-sets"
|
||||
import { getVariantsStep } from "../../definition/cart/steps/get-variants"
|
||||
import { validateVariantsExistStep } from "../../definition/cart/steps/validate-variants-existence"
|
||||
import { prepareConfirmInventoryInput } from "../../definition/cart/utils/prepare-confirm-inventory-input"
|
||||
import { prepareLineItemData } from "../../definition/cart/utils/prepare-line-item-data"
|
||||
import { createOrdersStep, updateOrderTaxLinesStep } from "../steps"
|
||||
@@ -174,6 +172,8 @@ export const createOrdersWorkflow = createWorkflow(
|
||||
),
|
||||
quantity: item.quantity as number,
|
||||
metadata: item?.metadata ?? {},
|
||||
taxLines: item.tax_lines || [],
|
||||
adjustments: item.adjustments || [],
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in new issue
Block a user