feat(core-flows, dashboard, link-modules,medusa, types, utils): fulfillment shipping changes (#10902)

**What**
- product <> shipping profile link
- create and update product workflows/endpoints accepts shipping profile
- pass shipping option id when creating fulfillment to allow overriding customer selected SO
- validate shipping profile delete
- dashboard
  - set shipping profile on product create
  - manage shipping profile for a product
  - **update the create fulfillment form**
- other
  - fix create product form infinite rerenders
 
---

CLOSES CMRC-831 CMRC-834 CMRC-836 CMRC-837 CMRC-838 CMRC-857 TRI-761
This commit is contained in:
Frane Polić authored and GitHub committed 2025-01-27 12:00:20 +00:00
1 parent 3e81962503
commit 864d772e34
78 files changed
+3529 -794

No files matched your search

@@ -75,6 +75,7 @@ export type AdminOrderCreateFulfillmentType = z.infer<
export const OrderCreateFulfillment = z.object({
items: z.array(Item),
location_id: z.string().nullish(),
shipping_option_id: z.string().optional(),
no_notification: z.boolean().optional(),
metadata: z.record(z.unknown()).nullish(),
})
@@ -232,6 +232,7 @@ export const CreateProduct = z
options: z.array(CreateProductOption).optional(),
variants: z.array(CreateProductVariant).optional(),
sales_channels: z.array(z.object({ id: z.string() })).optional(),
shipping_profile_id: z.string(),
weight: z.number().nullish(),
length: z.number().nullish(),
height: z.number().nullish(),
@@ -266,6 +267,7 @@ export const UpdateProduct = z
categories: z.array(IdAssociation).optional(),
tags: z.array(IdAssociation).optional(),
sales_channels: z.array(z.object({ id: z.string() })).optional(),
shipping_profile_id: z.string().optional(),
weight: z.number().nullish(),
length: z.number().nullish(),
height: z.number().nullish(),
@@ -0,0 +1,88 @@
import {
createRemoteLinkStep,
createShippingProfilesStep,
useQueryGraphStep,
} from "@medusajs/core-flows"
import { ExecArgs } from "@medusajs/framework/types"
import { ContainerRegistrationKeys, Modules } from "@medusajs/framework/utils"
import {
transform,
when,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import { createWorkflow } from "@medusajs/framework/workflows-sdk"
const assignProductsToShippingProfileWorkflow = createWorkflow(
"assign-products-to-shipping-profile",
() => {
const { data: shippingProfiles } = useQueryGraphStep({
entity: "shipping_profile",
fields: ["id", "name"],
}).config({ name: "get-shipping-profiles" })
const { data: products } = useQueryGraphStep({
entity: "product",
fields: ["id"],
}).config({ name: "get-products" })
const shippingProfileId = transform(
{ shippingProfiles },
({ shippingProfiles }) =>
shippingProfiles.find((sp) =>
sp.name.toLocaleLowerCase().includes("default")
)?.id ?? shippingProfiles[0]?.id
)
const createdShippingProfileId = when(
"create-shipping-profile",
{
shippingProfileId,
},
({ shippingProfileId }) => !shippingProfileId
).then(() => {
const createdShippingProfiles = createShippingProfilesStep([
{
name: "Default Shipping Profile",
type: "default",
},
])
return createdShippingProfiles[0].id
})
const links = transform(
{ products, shippingProfileId, createdShippingProfileId },
({ products, shippingProfileId, createdShippingProfileId }) => {
return products.map((product) => ({
[Modules.PRODUCT]: {
product_id: product.id,
},
[Modules.FULFILLMENT]: {
shipping_profile_id: shippingProfileId ?? createdShippingProfileId,
},
}))
}
)
createRemoteLinkStep(links)
return new WorkflowResponse(void 0)
}
)
export default async function assignProductsToShippingProfile({
container,
}: ExecArgs) {
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
logger.info("Assigning products to shipping profile")
await assignProductsToShippingProfileWorkflow(container)
.run()
.then(() => {
logger.info("Products assigned to shipping profile")
})
.catch((e) => {
logger.error(e)
})
}