feat(core-flows, fulfillment): validate shipping options to stock locations (#8291)
what: - validate shipping options to stock locations RESOLVES CC-232
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
import { ServiceZoneDTO, ShippingOptionDTO } from "@medusajs/types"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
MedusaError,
|
||||
ModuleRegistrationName,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import { createStep, StepResponse } from "@medusajs/workflows-sdk"
|
||||
|
||||
type FulfillmentProviderValidationInput = {
|
||||
id?: string
|
||||
service_zone_id?: string
|
||||
provider_id?: string
|
||||
}
|
||||
|
||||
export const validateFulfillmentProvidersStepId =
|
||||
"validate-fulfillment-providers-step"
|
||||
export const validateFulfillmentProvidersStep = createStep(
|
||||
validateFulfillmentProvidersStepId,
|
||||
async (input: FulfillmentProviderValidationInput[], { container }) => {
|
||||
const dataToValidate: {
|
||||
service_zone_id: string
|
||||
provider_id: string
|
||||
}[] = []
|
||||
const fulfillmentService = container.resolve(
|
||||
ModuleRegistrationName.FULFILLMENT
|
||||
)
|
||||
|
||||
const shippingOptions = await fulfillmentService.listShippingOptions({
|
||||
id: input.map((d) => d.id).filter(Boolean) as string[],
|
||||
})
|
||||
|
||||
const shippingOptionsMap = new Map<string, ShippingOptionDTO>(
|
||||
shippingOptions.map((so) => [so.id, so])
|
||||
)
|
||||
|
||||
const remoteQuery = container.resolve(
|
||||
ContainerRegistrationKeys.REMOTE_QUERY
|
||||
)
|
||||
|
||||
for (const data of input) {
|
||||
if ("id" in data) {
|
||||
const existingShippingOption = shippingOptionsMap.get(data.id!)
|
||||
|
||||
dataToValidate.push({
|
||||
service_zone_id:
|
||||
data.service_zone_id! || existingShippingOption?.service_zone_id!,
|
||||
provider_id:
|
||||
data.provider_id! || existingShippingOption?.provider_id!,
|
||||
})
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if (data.service_zone_id && data.provider_id) {
|
||||
dataToValidate.push({
|
||||
service_zone_id: data.service_zone_id,
|
||||
provider_id: data.provider_id,
|
||||
})
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_ALLOWED,
|
||||
`service_zone_id and provider_id are required to create a shipping option`
|
||||
)
|
||||
}
|
||||
|
||||
const serviceZoneQuery = remoteQueryObjectFromString({
|
||||
entryPoint: "service_zone",
|
||||
fields: ["id", "fulfillment_set.locations.fulfillment_providers.id"],
|
||||
})
|
||||
|
||||
const serviceZones = await remoteQuery(serviceZoneQuery, {
|
||||
id: input.map((d) => d.service_zone_id),
|
||||
})
|
||||
|
||||
const serviceZonesMap = new Map<
|
||||
string,
|
||||
ServiceZoneDTO & {
|
||||
fulfillment_set: {
|
||||
locations: { fulfillment_providers: { id: string }[] }[]
|
||||
}
|
||||
}
|
||||
>(serviceZones.map((sz) => [sz.id, sz]))
|
||||
|
||||
const invalidProviders: string[] = []
|
||||
|
||||
for (const data of dataToValidate) {
|
||||
const serviceZone = serviceZonesMap.get(data.service_zone_id)!
|
||||
const stockLocations = serviceZone.fulfillment_set.locations
|
||||
const fulfillmentProviders: string[] = []
|
||||
|
||||
for (const stockLocation of stockLocations) {
|
||||
const providersForStockLocation =
|
||||
stockLocation.fulfillment_providers.map((fp) => fp.id)
|
||||
|
||||
fulfillmentProviders.push(...providersForStockLocation)
|
||||
}
|
||||
|
||||
if (!fulfillmentProviders.includes(data.provider_id)) {
|
||||
invalidProviders.push(data.provider_id)
|
||||
}
|
||||
}
|
||||
|
||||
if (invalidProviders.length) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_ALLOWED,
|
||||
`Providers (${invalidProviders.join(
|
||||
","
|
||||
)}) are not enabled for the service location`
|
||||
)
|
||||
}
|
||||
|
||||
return new StepResponse(void 0)
|
||||
}
|
||||
)
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
upsertShippingOptionsStep,
|
||||
} from "../steps"
|
||||
import { setShippingOptionsPriceSetsStep } from "../steps/set-shipping-options-price-sets"
|
||||
import { validateFulfillmentProvidersStep } from "../steps/validate-fulfillment-providers"
|
||||
|
||||
export const createShippingOptionsWorkflowId =
|
||||
"create-shipping-options-workflow"
|
||||
@@ -19,6 +20,8 @@ export const createShippingOptionsWorkflow = createWorkflow(
|
||||
FulfillmentWorkflow.CreateShippingOptionsWorkflowInput[]
|
||||
>
|
||||
): WorkflowData<FulfillmentWorkflow.CreateShippingOptionsWorkflowOutput> => {
|
||||
validateFulfillmentProvidersStep(input)
|
||||
|
||||
const data = transform(input, (data) => {
|
||||
const shippingOptionsIndexToPrices = data.map((option, index) => {
|
||||
const prices = option.prices
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
setShippingOptionsPricesStep,
|
||||
upsertShippingOptionsStep,
|
||||
} from "../steps"
|
||||
import { validateFulfillmentProvidersStep } from "../steps/validate-fulfillment-providers"
|
||||
|
||||
export const updateShippingOptionsWorkflowId =
|
||||
"update-shipping-options-workflow"
|
||||
@@ -18,6 +19,8 @@ export const updateShippingOptionsWorkflow = createWorkflow(
|
||||
FulfillmentWorkflow.UpdateShippingOptionsWorkflowInput[]
|
||||
>
|
||||
): WorkflowData<FulfillmentWorkflow.UpdateShippingOptionsWorkflowOutput> => {
|
||||
validateFulfillmentProvidersStep(input)
|
||||
|
||||
const data = transform(input, (data) => {
|
||||
const shippingOptionsIndexToPrices = data.map((option, index) => {
|
||||
const prices = option.prices
|
||||
|
||||
Reference in New Issue
Block a user