Chore(order): endpoints - Part 1:N (#7360)
This commit is contained in:
@@ -18,8 +18,9 @@ export * from "./pricing"
|
||||
export * from "./product"
|
||||
export * from "./product-category"
|
||||
export * from "./promotion"
|
||||
export * from "./reservation"
|
||||
export * from "./region"
|
||||
export * from "./reservation"
|
||||
export * from "./return-reason"
|
||||
export * from "./sales-channel"
|
||||
export * from "./shipping-options"
|
||||
export * from "./shipping-profile"
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { IOrderModuleService } from "@medusajs/types"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
|
||||
type CompleteOrdersStepInput = {
|
||||
order_ids: string[]
|
||||
}
|
||||
|
||||
export const archiveOrdersStepId = "archive-orders"
|
||||
export const archiveOrdersStep = createStep(
|
||||
archiveOrdersStepId,
|
||||
async (data: CompleteOrdersStepInput, { container }) => {
|
||||
const service = container.resolve<IOrderModuleService>(
|
||||
ModuleRegistrationName.ORDER
|
||||
)
|
||||
|
||||
const archived = await service.archive(data.order_ids)
|
||||
return new StepResponse(
|
||||
archived,
|
||||
archived.map((store) => {
|
||||
return {
|
||||
id: store.id,
|
||||
status: store.status,
|
||||
}
|
||||
})
|
||||
)
|
||||
},
|
||||
async (archived, { container }) => {
|
||||
if (!archived?.length) {
|
||||
return
|
||||
}
|
||||
|
||||
const service = container.resolve<IOrderModuleService>(
|
||||
ModuleRegistrationName.ORDER
|
||||
)
|
||||
|
||||
await service.update(archived)
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,39 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { IOrderModuleService } from "@medusajs/types"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
|
||||
type CompleteOrdersStepInput = {
|
||||
order_ids: string[]
|
||||
}
|
||||
|
||||
export const completeOrdersStepId = "complete-orders"
|
||||
export const completeOrdersStep = createStep(
|
||||
completeOrdersStepId,
|
||||
async (data: CompleteOrdersStepInput, { container }) => {
|
||||
const service = container.resolve<IOrderModuleService>(
|
||||
ModuleRegistrationName.ORDER
|
||||
)
|
||||
|
||||
const completed = await service.completeOrder(data.order_ids)
|
||||
return new StepResponse(
|
||||
completed,
|
||||
completed.map((store) => {
|
||||
return {
|
||||
id: store.id,
|
||||
status: store.status,
|
||||
}
|
||||
})
|
||||
)
|
||||
},
|
||||
async (completed, { container }) => {
|
||||
if (!completed?.length) {
|
||||
return
|
||||
}
|
||||
|
||||
const service = container.resolve<IOrderModuleService>(
|
||||
ModuleRegistrationName.ORDER
|
||||
)
|
||||
|
||||
await service.update(completed)
|
||||
}
|
||||
)
|
||||
@@ -1,3 +1,5 @@
|
||||
export * from "./archive-orders"
|
||||
export * from "./complete-orders"
|
||||
export * from "./create-orders"
|
||||
export * from "./get-item-tax-lines"
|
||||
export * from "./link-order-payment-collection"
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
export const productVariantsFields = [
|
||||
"id",
|
||||
"title",
|
||||
"sku",
|
||||
"manage_inventory",
|
||||
"allow_backorder",
|
||||
"barcode",
|
||||
"product.id",
|
||||
"product.title",
|
||||
"product.description",
|
||||
"product.subtitle",
|
||||
"product.thumbnail",
|
||||
"product.type",
|
||||
"product.collection",
|
||||
"product.handle",
|
||||
"calculated_price.calculated_amount",
|
||||
"inventory_items.inventory_item_id",
|
||||
"inventory_items.required_quantity",
|
||||
"inventory_items.inventory.location_levels.stock_locations.id",
|
||||
"inventory_items.inventory.location_levels.stock_locations.name",
|
||||
"inventory_items.inventory.location_levels.stock_locations.sales_channels.id",
|
||||
"inventory_items.inventory.location_levels.stock_locations.sales_channels.name",
|
||||
]
|
||||
@@ -0,0 +1,17 @@
|
||||
import { OrderDTO } from "@medusajs/types"
|
||||
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
|
||||
import { archiveOrdersStep } from "../steps"
|
||||
|
||||
type ArchiveOrdersStepInput = {
|
||||
order_ids: string[]
|
||||
}
|
||||
|
||||
export const archiveOrderWorkflowId = "archive-order-workflow"
|
||||
export const archiveOrderWorkflow = createWorkflow(
|
||||
archiveOrderWorkflowId,
|
||||
(input: WorkflowData<ArchiveOrdersStepInput>): WorkflowData<OrderDTO[]> => {
|
||||
const archivedOrders = archiveOrdersStep(input)
|
||||
|
||||
return archivedOrders
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
import { OrderDTO } from "@medusajs/types"
|
||||
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
|
||||
import { completeOrdersStep } from "../steps"
|
||||
|
||||
type CompleteOrdersStepInput = {
|
||||
order_ids: string[]
|
||||
}
|
||||
|
||||
export const completeOrderWorkflowId = "complete-order-workflow"
|
||||
export const completeOrderWorkflow = createWorkflow(
|
||||
completeOrderWorkflowId,
|
||||
(input: WorkflowData<CompleteOrdersStepInput>): WorkflowData<OrderDTO[]> => {
|
||||
const completedOrders = completeOrdersStep(input)
|
||||
|
||||
// TODO: Emit event "OrderModuleService.Order.COMPLETED"
|
||||
// id + no_notification
|
||||
|
||||
return completedOrders
|
||||
}
|
||||
)
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CreateOrderDTO, OrderDTO } from "@medusajs/types"
|
||||
import { MathBN, MedusaError } from "@medusajs/utils"
|
||||
import { MathBN } from "@medusajs/utils"
|
||||
import {
|
||||
WorkflowData,
|
||||
createWorkflow,
|
||||
@@ -7,17 +7,67 @@ import {
|
||||
transform,
|
||||
} from "@medusajs/workflows-sdk"
|
||||
import { useRemoteQueryStep } from "../../common"
|
||||
import { confirmInventoryStep } from "../../definition/cart/steps/confirm-inventory"
|
||||
import { findOneOrAnyRegionStep } from "../../definition/cart/steps/find-one-or-any-region"
|
||||
import { findOrCreateCustomerStep } from "../../definition/cart/steps/find-or-create-customer"
|
||||
import { findSalesChannelStep } from "../../definition/cart/steps/find-sales-channel"
|
||||
import { getVariantPriceSetsStep } from "../../definition/cart/steps/get-variant-price-sets"
|
||||
import { getVariantsStep } from "../../definition/cart/steps/get-variants"
|
||||
import { prepareConfirmInventoryInput } from "../../definition/cart/utils/prepare-confirm-inventory-input"
|
||||
import { validateVariantPricesStep } from "../../definition/cart/steps/validate-variant-prices"
|
||||
import { prepareLineItemData } from "../../definition/cart/utils/prepare-line-item-data"
|
||||
import { confirmVariantInventoryWorkflow } from "../../definition/cart/workflows/confirm-variant-inventory"
|
||||
import { createOrdersStep, updateOrderTaxLinesStep } from "../steps"
|
||||
import { productVariantsFields } from "../utils/fields"
|
||||
import { prepareCustomLineItemData } from "../utils/prepare-custom-line-item-data"
|
||||
|
||||
function prepareLineItems(data) {
|
||||
const items = (data.input.items ?? []).map((item) => {
|
||||
const variant = data.variants.find((v) => v.id === item.variant_id)!
|
||||
|
||||
if (!variant) {
|
||||
return prepareCustomLineItemData({
|
||||
variant: {
|
||||
...item,
|
||||
},
|
||||
unitPrice: MathBN.max(0, item.unit_price),
|
||||
quantity: item.quantity as number,
|
||||
metadata: item?.metadata ?? {},
|
||||
})
|
||||
}
|
||||
|
||||
return prepareLineItemData({
|
||||
variant: variant,
|
||||
unitPrice: MathBN.max(
|
||||
0,
|
||||
item.unit_price ?? data.priceSets[item.variant_id!]?.calculated_amount
|
||||
),
|
||||
quantity: item.quantity as number,
|
||||
metadata: item?.metadata ?? {},
|
||||
taxLines: item.tax_lines || [],
|
||||
adjustments: item.adjustments || [],
|
||||
})
|
||||
})
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
function getOrderInput(data) {
|
||||
const data_ = {
|
||||
...data.input,
|
||||
currency_code: data.input.currency_code ?? data.region.currency_code,
|
||||
region_id: data.region.id,
|
||||
}
|
||||
|
||||
if (data.customerData.customer?.id) {
|
||||
data_.customer_id = data.customerData.customer.id
|
||||
data_.email = data.input?.email ?? data.customerData.customer.email
|
||||
}
|
||||
|
||||
if (data.salesChannel?.id) {
|
||||
data_.sales_channel_id = data.salesChannel.id
|
||||
}
|
||||
|
||||
return data_
|
||||
}
|
||||
|
||||
export const createOrdersWorkflowId = "create-orders"
|
||||
export const createOrdersWorkflow = createWorkflow(
|
||||
createOrdersWorkflowId,
|
||||
@@ -39,75 +89,8 @@ export const createOrdersWorkflow = createWorkflow(
|
||||
customerId: input.customer_id,
|
||||
email: input.email,
|
||||
})
|
||||
// validateVariantsExistStep({ variantIds })
|
||||
)
|
||||
|
||||
const variants = getVariantsStep({
|
||||
filter: { id: variantIds },
|
||||
config: {
|
||||
select: [
|
||||
"id",
|
||||
"title",
|
||||
"sku",
|
||||
"manage_inventory",
|
||||
"barcode",
|
||||
"product.id",
|
||||
"product.title",
|
||||
"product.description",
|
||||
"product.subtitle",
|
||||
"product.thumbnail",
|
||||
"product.type",
|
||||
"product.collection",
|
||||
"product.handle",
|
||||
],
|
||||
relations: ["product"],
|
||||
},
|
||||
})
|
||||
|
||||
const salesChannelLocations = useRemoteQueryStep({
|
||||
entry_point: "sales_channels",
|
||||
fields: ["id", "name", "stock_locations.id", "stock_locations.name"],
|
||||
variables: { id: salesChannel.id },
|
||||
})
|
||||
|
||||
const productVariantInventoryItems = useRemoteQueryStep({
|
||||
entry_point: "product_variant_inventory_items",
|
||||
fields: ["variant_id", "inventory_item_id", "required_quantity"],
|
||||
variables: { variant_id: variantIds },
|
||||
}).config({ name: "inventory-items" })
|
||||
|
||||
const confirmInventoryInput = transform(
|
||||
{ productVariantInventoryItems, salesChannelLocations, input, variants },
|
||||
(data) => {
|
||||
if (!data.input.items) {
|
||||
return { items: [] }
|
||||
}
|
||||
|
||||
if (!data.salesChannelLocations.length) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`Sales channel ${data.input.sales_channel_id} is not associated with any stock locations.`
|
||||
)
|
||||
}
|
||||
|
||||
const items = prepareConfirmInventoryInput({
|
||||
product_variant_inventory_items: data.productVariantInventoryItems,
|
||||
location_ids: data.salesChannelLocations[0].stock_locations.map(
|
||||
(l) => l.id
|
||||
),
|
||||
items: data.input.items!,
|
||||
variants: data.variants.map((v) => ({
|
||||
id: v.id,
|
||||
manage_inventory: v.manage_inventory,
|
||||
})),
|
||||
})
|
||||
|
||||
return { items }
|
||||
}
|
||||
)
|
||||
|
||||
confirmInventoryStep(confirmInventoryInput)
|
||||
|
||||
// TODO: This is on par with the context used in v1.*, but we can be more flexible.
|
||||
const pricingContext = transform(
|
||||
{ input, region, customerData },
|
||||
@@ -120,6 +103,28 @@ export const createOrdersWorkflow = createWorkflow(
|
||||
}
|
||||
)
|
||||
|
||||
const variants = useRemoteQueryStep({
|
||||
entry_point: "variants",
|
||||
fields: productVariantsFields,
|
||||
variables: {
|
||||
id: variantIds,
|
||||
calculated_price: {
|
||||
context: pricingContext,
|
||||
},
|
||||
},
|
||||
throw_if_key_not_found: true,
|
||||
})
|
||||
|
||||
validateVariantPricesStep({ variants })
|
||||
|
||||
confirmVariantInventoryWorkflow.runAsStep({
|
||||
input: {
|
||||
sales_channel_id: salesChannel.id,
|
||||
variants,
|
||||
items: input.items!,
|
||||
},
|
||||
})
|
||||
|
||||
const priceSets = getVariantPriceSetsStep({
|
||||
variantIds,
|
||||
context: pricingContext,
|
||||
@@ -127,57 +132,13 @@ export const createOrdersWorkflow = createWorkflow(
|
||||
|
||||
const orderInput = transform(
|
||||
{ input, region, customerData, salesChannel },
|
||||
(data) => {
|
||||
const data_ = {
|
||||
...data.input,
|
||||
currency_code: data.input.currency_code ?? data.region.currency_code,
|
||||
region_id: data.region.id,
|
||||
}
|
||||
|
||||
if (data.customerData.customer?.id) {
|
||||
data_.customer_id = data.customerData.customer.id
|
||||
data_.email = data.input?.email ?? data.customerData.customer.email
|
||||
}
|
||||
|
||||
if (data.salesChannel?.id) {
|
||||
data_.sales_channel_id = data.salesChannel.id
|
||||
}
|
||||
|
||||
return data_
|
||||
}
|
||||
getOrderInput
|
||||
)
|
||||
|
||||
const lineItems = transform({ priceSets, input, variants }, (data) => {
|
||||
const items = (data.input.items ?? []).map((item) => {
|
||||
const variant = data.variants.find((v) => v.id === item.variant_id)!
|
||||
|
||||
if (!variant) {
|
||||
return prepareCustomLineItemData({
|
||||
variant: {
|
||||
...item,
|
||||
},
|
||||
unitPrice: MathBN.max(0, item.unit_price),
|
||||
quantity: item.quantity as number,
|
||||
metadata: item?.metadata ?? {},
|
||||
})
|
||||
}
|
||||
|
||||
return prepareLineItemData({
|
||||
variant: variant,
|
||||
unitPrice: MathBN.max(
|
||||
0,
|
||||
item.unit_price ??
|
||||
data.priceSets[item.variant_id!]?.calculated_amount
|
||||
),
|
||||
quantity: item.quantity as number,
|
||||
metadata: item?.metadata ?? {},
|
||||
taxLines: item.tax_lines || [],
|
||||
adjustments: item.adjustments || [],
|
||||
})
|
||||
})
|
||||
|
||||
return items
|
||||
})
|
||||
const lineItems = transform(
|
||||
{ priceSets, input, variants },
|
||||
prepareLineItems
|
||||
)
|
||||
|
||||
const orderToCreate = transform({ lineItems, orderInput }, (data) => {
|
||||
return {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export * from "./archive-orders"
|
||||
export * from "./complete-orders"
|
||||
export * from "./create-orders"
|
||||
export * from "./update-tax-lines"
|
||||
export * from "./create-return"
|
||||
export * from "./update-tax-lines"
|
||||
|
||||
Reference in New Issue
Block a user