feat: Add shipping method to cart (#6661)

This commit is contained in:
Oli Juhl
2024-03-12 17:52:48 +01:00
committed by GitHub
parent c3c4f49fc2
commit f0c8142635
18 changed files with 491 additions and 23 deletions
@@ -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"