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:
Riqwan Thamir authored and GitHub committed 2024-05-02 22:24:50 +00:00
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 || [],
})
})