feat: Add shipping method to cart (#6661)
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import { CreateShippingMethodDTO, ICartModuleService } from "@medusajs/types"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
import { ModuleRegistrationName } from "../../../../../modules-sdk/dist"
|
||||
|
||||
interface StepInput {
|
||||
shipping_methods: CreateShippingMethodDTO[]
|
||||
}
|
||||
|
||||
export const addShippingMethodToCartStepId = "add-shipping-method-to-cart-step"
|
||||
export const addShippingMethodToCartStep = createStep(
|
||||
addShippingMethodToCartStepId,
|
||||
async (data: StepInput, { container }) => {
|
||||
const cartService = container.resolve<ICartModuleService>(
|
||||
ModuleRegistrationName.CART
|
||||
)
|
||||
|
||||
const methods = await cartService.addShippingMethods(data.shipping_methods)
|
||||
|
||||
return new StepResponse(methods, methods)
|
||||
},
|
||||
async (methods, { container }) => {
|
||||
const cartService: ICartModuleService = container.resolve(
|
||||
ModuleRegistrationName.CART
|
||||
)
|
||||
if (!methods?.length) {
|
||||
return
|
||||
}
|
||||
|
||||
await cartService.deleteShippingMethods(methods.map((m) => m.id))
|
||||
}
|
||||
)
|
||||
@@ -16,7 +16,7 @@ export const addToCartStep = createStep(
|
||||
|
||||
const items = await cartService.addLineItems(data.items)
|
||||
|
||||
return new StepResponse(items)
|
||||
return new StepResponse(items, items)
|
||||
},
|
||||
async (createdLineItems, { container }) => {
|
||||
const cartService: ICartModuleService = container.resolve(
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { IPricingModuleService, PricingContext } from "@medusajs/types"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
MedusaError,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
|
||||
interface StepInput {
|
||||
optionIds: string[]
|
||||
context?: Record<string, unknown>
|
||||
}
|
||||
|
||||
export const getShippingOptionPriceSetsStepId = "get-variant-price-sets"
|
||||
export const getShippingOptionPriceSetsStep = createStep(
|
||||
getShippingOptionPriceSetsStepId,
|
||||
async (data: StepInput, { container }) => {
|
||||
if (!data.optionIds.length) {
|
||||
return new StepResponse({})
|
||||
}
|
||||
|
||||
const pricingModuleService = container.resolve<IPricingModuleService>(
|
||||
ModuleRegistrationName.PRICING
|
||||
)
|
||||
|
||||
const remoteQuery = container.resolve(
|
||||
ContainerRegistrationKeys.REMOTE_QUERY
|
||||
)
|
||||
|
||||
const query = remoteQueryObjectFromString({
|
||||
entryPoint: "shipping_option_price_set",
|
||||
fields: ["id", "shipping_option_id", "price_set_id"],
|
||||
variables: {
|
||||
shipping_option_id: data.optionIds,
|
||||
},
|
||||
})
|
||||
|
||||
const optionPriceSets = await remoteQuery(query)
|
||||
|
||||
const notFound: string[] = []
|
||||
const priceSetIds: string[] = []
|
||||
|
||||
optionPriceSets.forEach((v) => {
|
||||
if (v.price_set_id) {
|
||||
priceSetIds.push(v.price_set_id)
|
||||
} else {
|
||||
notFound.push(v.shipping_option_id)
|
||||
}
|
||||
})
|
||||
|
||||
if (notFound.length) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`Shipping options with IDs ${notFound.join(", ")} do not have a price`
|
||||
)
|
||||
}
|
||||
|
||||
const calculatedPriceSets = await pricingModuleService.calculatePrices(
|
||||
{ id: priceSetIds },
|
||||
{ context: data.context as PricingContext["context"] }
|
||||
)
|
||||
|
||||
const idToPriceSet = new Map<string, Record<string, any>>(
|
||||
calculatedPriceSets.map((p) => [p.id, p])
|
||||
)
|
||||
|
||||
const optionToCalculatedPriceSets = optionPriceSets.reduce(
|
||||
(acc, { shipping_option_id, price_set_id }) => {
|
||||
const calculatedPriceSet = idToPriceSet.get(price_set_id)
|
||||
if (calculatedPriceSet) {
|
||||
acc[shipping_option_id] = calculatedPriceSet
|
||||
}
|
||||
|
||||
return acc
|
||||
},
|
||||
{}
|
||||
)
|
||||
|
||||
return new StepResponse(optionToCalculatedPriceSets)
|
||||
}
|
||||
)
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from "./add-shipping-method-to-cart"
|
||||
export * from "./add-to-cart"
|
||||
export * from "./create-carts"
|
||||
export * from "./create-line-item-adjustments"
|
||||
@@ -7,6 +8,7 @@ export * from "./find-or-create-customer"
|
||||
export * from "./find-sales-channel"
|
||||
export * from "./get-actions-to-compute-from-promotions"
|
||||
export * from "./get-item-tax-lines"
|
||||
export * from "./get-shipping-option-price-sets"
|
||||
export * from "./get-variant-price-sets"
|
||||
export * from "./get-variants"
|
||||
export * from "./prepare-adjustments-from-promotion-actions"
|
||||
@@ -18,3 +20,4 @@ export * from "./set-tax-lines-for-items"
|
||||
export * from "./update-cart-promotions"
|
||||
export * from "./update-carts"
|
||||
export * from "./validate-variants-existence"
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
import {
|
||||
WorkflowData,
|
||||
createWorkflow,
|
||||
transform,
|
||||
} from "@medusajs/workflows-sdk"
|
||||
import { useRemoteQueryStep } from "../../../common/steps/use-remote-query"
|
||||
import { addShippingMethodToCartStep } from "../steps"
|
||||
import { getShippingOptionPriceSetsStep } from "../steps/get-shipping-option-price-sets"
|
||||
import { refreshCartPromotionsStep } from "../steps/refresh-cart-promotions"
|
||||
import { updateTaxLinesStep } from "../steps/update-tax-lines"
|
||||
|
||||
interface AddShippingMethodToCartWorkflowInput {
|
||||
cart_id: string
|
||||
currency_code: string
|
||||
options: {
|
||||
id: string
|
||||
data?: Record<string, unknown>
|
||||
}[]
|
||||
}
|
||||
|
||||
export const addShippingMethodToCartWorkflowId = "add-shipping-method-to-cart"
|
||||
export const addShippingMethodToWorkflow = createWorkflow(
|
||||
addShippingMethodToCartWorkflowId,
|
||||
(
|
||||
input: WorkflowData<AddShippingMethodToCartWorkflowInput>
|
||||
): WorkflowData<void> => {
|
||||
const optionIds = transform({ input }, (data) => {
|
||||
return (data.input.options ?? []).map((i) => i.id)
|
||||
})
|
||||
|
||||
const priceSets = getShippingOptionPriceSetsStep({
|
||||
optionIds: optionIds,
|
||||
context: { currency_code: input.currency_code },
|
||||
})
|
||||
|
||||
const shippingOptions = useRemoteQueryStep({
|
||||
entry_point: "shipping_option",
|
||||
fields: ["id", "name"],
|
||||
variables: {
|
||||
id: optionIds,
|
||||
},
|
||||
})
|
||||
|
||||
const shippingMethodInput = transform(
|
||||
{ priceSets, input, shippingOptions },
|
||||
(data) => {
|
||||
const options = (data.input.options ?? []).map((option) => {
|
||||
const shippingOption = data.shippingOptions.find(
|
||||
(so) => so.id === option.id
|
||||
)!
|
||||
|
||||
const price = data.priceSets[option.id].calculated_amount
|
||||
|
||||
return {
|
||||
shipping_option_id: shippingOption.id,
|
||||
amount: price,
|
||||
data: option.data ?? {},
|
||||
name: shippingOption.name,
|
||||
cart_id: data.input.cart_id,
|
||||
}
|
||||
})
|
||||
|
||||
return options
|
||||
}
|
||||
)
|
||||
|
||||
const shippingMethods = addShippingMethodToCartStep({
|
||||
shipping_methods: shippingMethodInput,
|
||||
})
|
||||
refreshCartPromotionsStep({ id: input.cart_id })
|
||||
updateTaxLinesStep({
|
||||
cart_or_cart_id: input.cart_id,
|
||||
shipping_methods: shippingMethods,
|
||||
})
|
||||
}
|
||||
)
|
||||
@@ -92,7 +92,6 @@ export const addToCartWorkflow = createWorkflow(
|
||||
updateTaxLinesStep({
|
||||
cart_or_cart_id: input.cart,
|
||||
items,
|
||||
// TODO: add shipping methods here when its ready
|
||||
})
|
||||
|
||||
refreshCartPromotionsStep({ id: input.cart.id })
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from "./add-shipping-method-to-cart"
|
||||
export * from "./add-to-cart"
|
||||
export * from "./create-carts"
|
||||
export * from "./create-payment-collection-for-cart"
|
||||
|
||||
Reference in New Issue
Block a user