feat: List shipping options for cart (#6677)

This commit is contained in:
Oli Juhl
2024-03-13 09:08:47 +00:00
committed by GitHub
parent db26dafa85
commit 25d176b851
23 changed files with 855 additions and 142 deletions
@@ -3,6 +3,7 @@ import { IPricingModuleService, PricingContext } from "@medusajs/types"
import {
ContainerRegistrationKeys,
MedusaError,
arrayDifference,
remoteQueryObjectFromString,
} from "@medusajs/utils"
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
@@ -12,7 +13,7 @@ interface StepInput {
context?: Record<string, unknown>
}
export const getShippingOptionPriceSetsStepId = "get-variant-price-sets"
export const getShippingOptionPriceSetsStepId = "get-shipping-option-price-sets"
export const getShippingOptionPriceSetsStep = createStep(
getShippingOptionPriceSetsStepId,
async (data: StepInput, { container }) => {
@@ -38,26 +39,22 @@ export const getShippingOptionPriceSetsStep = createStep(
const optionPriceSets = await remoteQuery(query)
const notFound: string[] = []
const priceSetIds: string[] = []
const optionsMissingPrices = arrayDifference(
data.optionIds,
optionPriceSets.map((v) => v.shipping_option_id)
)
optionPriceSets.forEach((v) => {
if (v.price_set_id) {
priceSetIds.push(v.price_set_id)
} else {
notFound.push(v.shipping_option_id)
}
})
if (notFound.length) {
if (optionsMissingPrices.length) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Shipping options with IDs ${notFound.join(", ")} do not have a price`
`Shipping options with IDs ${optionsMissingPrices.join(
", "
)} do not have a price`
)
}
const calculatedPriceSets = await pricingModuleService.calculatePrices(
{ id: priceSetIds },
{ id: optionPriceSets.map((v) => v.price_set_id) },
{ context: data.context as PricingContext["context"] }
)
@@ -2,6 +2,7 @@ export * from "./add-shipping-method-to-cart"
export * from "./add-to-cart"
export * from "./create-carts"
export * from "./create-payment-collection-for-cart"
export * from "./list-shipping-options-for-cart"
export * from "./refresh-payment-collection"
export * from "./update-cart"
export * from "./update-cart-promotions"
@@ -0,0 +1,93 @@
import { ListShippingOptionsForCartWorkflowInputDTO } from "@medusajs/types"
import {
WorkflowData,
createWorkflow,
transform,
} from "@medusajs/workflows-sdk"
import { useRemoteQueryStep } from "../../../common/steps/use-remote-query"
import { listShippingOptionsForContextStep } from "../../../shipping-options"
import { getShippingOptionPriceSetsStep } from "../steps"
export const listShippingOptionsForCartWorkflowId =
"list-shipping-options-for-cart"
export const listShippingOptionsForCartWorkflow = createWorkflow(
listShippingOptionsForCartWorkflowId,
(input: WorkflowData<ListShippingOptionsForCartWorkflowInputDTO>) => {
const scLocationFulfillmentSets = useRemoteQueryStep({
entry_point: "sales_channels",
fields: ["stock_locations.fulfillment_sets.id"],
variables: { id: input.sales_channel_id },
})
const listOptionsInput = transform(
{ scLocationFulfillmentSets, input },
(data) => {
const fulfillmentSetIds = data.scLocationFulfillmentSets
.map((sc) =>
sc.stock_locations.map((loc) =>
loc.fulfillment_sets.map(({ id }) => id)
)
)
.flat(2)
return {
context: {
fulfillment_set_id: fulfillmentSetIds,
service_zone: {
geo_zones: {
city: data.input.shipping_address?.city,
country_code: data.input.shipping_address?.country_code,
province_code: data.input.shipping_address?.province,
},
},
},
config: {
select: [
"id",
"name",
"price_type",
"service_zone_id",
"shipping_profile_id",
"provider_id",
"data",
"amount",
],
relations: ["type", "provider"],
},
}
}
)
const options = listShippingOptionsForContextStep(listOptionsInput)
const optionIds = transform({ options }, (data) =>
data.options.map((option) => option.id)
)
// TODO: Separate shipping options based on price_type, flat_rate vs calculated
const priceSets = getShippingOptionPriceSetsStep({
optionIds,
context: {
currency_code: input.currency_code,
},
})
const shippingOptionsWithPrice = transform(
{ priceSets, options },
(data) => {
const options = data.options.map((option) => {
const price = data.priceSets?.[option.id].calculated_amount
return {
...option,
amount: price,
}
})
return options
}
)
return shippingOptionsWithPrice
}
)
+1
View File
@@ -9,6 +9,7 @@ export * from "./payment"
export * from "./product"
export * from "./promotion"
export * from "./region"
export * from "./shipping-options"
export * from "./store"
export * from "./tax"
export * from "./user"
@@ -0,0 +1 @@
export * from "./steps"
@@ -0,0 +1 @@
export * from "./list-shipping-options-for-context"
@@ -0,0 +1,30 @@
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import {
FindConfig,
IFulfillmentModuleService,
ShippingOptionDTO,
} from "@medusajs/types"
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
interface StepInput {
context: Record<string, unknown>
config?: FindConfig<ShippingOptionDTO>
}
export const listShippingOptionsForContextStepId =
"list-shipping-options-for-context"
export const listShippingOptionsForContextStep = createStep(
listShippingOptionsForContextStepId,
async (data: StepInput, { container }) => {
const fulfillmentService = container.resolve<IFulfillmentModuleService>(
ModuleRegistrationName.FULFILLMENT
)
const shippingOptions = await fulfillmentService.listShippingOptions(
data.context,
data.config
)
return new StepResponse(shippingOptions)
}
)