fix(): Cart workflow price calculation for different items but same variant (#13511)

RESOLVES CORE-1204

**What**
- Fix wrong price tier when multiple items are targetting the same variant
- fix type import from the wrong package

**Notes**
If you are struggling navigating the changes, you can focus on the following files:
```
integration-tests/http/__tests__/cart/store/cart.spec.ts
integration-tests/modules/__tests__/cart/store/cart.workflows.spec.ts
packages/core/core-flows/src/cart/steps/get-promotion-codes-to-apply.ts
packages/core/core-flows/src/cart/steps/get-variant-price-sets.ts
packages/core/core-flows/src/cart/workflows/add-to-cart.ts
packages/core/core-flows/src/cart/workflows/create-carts.ts
packages/core/core-flows/src/cart/workflows/get-variants-and-items-with-prices.ts
packages/core/core-flows/src/cart/workflows/refresh-cart-items.ts
packages/core/core-flows/src/order/workflows/add-line-items.ts
packages/core/core-flows/src/order/workflows/create-order.ts
```
This commit is contained in:
Adrien de Peretti
2025-09-26 09:19:46 +02:00
committed by GitHub
parent 3960c80e9f
commit 5ea32aaa44
281 changed files with 1864 additions and 1466 deletions
@@ -1,4 +1,4 @@
import { IApiKeyModuleService } from "@medusajs/framework/types"
import type { IApiKeyModuleService } from "@medusajs/framework/types"
import { Modules } from "@medusajs/framework/utils"
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
@@ -1,4 +1,4 @@
import { LinkWorkflowInput } from "@medusajs/framework/types"
import type { LinkWorkflowInput } from "@medusajs/framework/types"
import {
ContainerRegistrationKeys,
Modules,
@@ -8,7 +8,7 @@ import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
/**
* The data to manage the sales channels of a publishable API key.
*
*
* @property id - The ID of the publishable API key.
* @property add - The sales channel IDs to add to the publishable API key.
* @property remove - The sales channel IDs to remove from the publishable API key.
@@ -18,7 +18,7 @@ export type LinkSalesChannelsToApiKeyStepInput = LinkWorkflowInput
export const linkSalesChannelsToApiKeyStepId = "link-sales-channels-to-api-key"
/**
* This step manages the sales channels of a publishable API key.
*
*
* @example
* const data = linkSalesChannelsToApiKeyStep({
* id: "apk_123",
@@ -1,4 +1,4 @@
import { ISalesChannelModuleService } from "@medusajs/framework/types"
import type { ISalesChannelModuleService } from "@medusajs/framework/types"
import {
MedusaError,
Modules,
@@ -1,4 +1,4 @@
import { ApiKeyDTO, CreateApiKeyDTO } from "@medusajs/framework/types"
import type { ApiKeyDTO, CreateApiKeyDTO } from "@medusajs/framework/types"
import {
WorkflowData,
WorkflowResponse,
@@ -1,4 +1,4 @@
import { LinkWorkflowInput } from "@medusajs/framework/types"
import type { LinkWorkflowInput } from "@medusajs/framework/types"
import { WorkflowData, createWorkflow } from "@medusajs/framework/workflows-sdk"
import {
linkSalesChannelsToApiKeyStep,
@@ -7,7 +7,7 @@ import {
/**
* The data to manage the sales channels of a publishable API key.
*
*
* @property id - The ID of the publishable API key.
* @property add - The sales channel IDs to add to the publishable API key.
* @property remove - The sales channel IDs to remove from the publishable API key.
@@ -19,10 +19,10 @@ export const linkSalesChannelsToApiKeyWorkflowId =
/**
* This workflow manages the sales channels of a publishable API key. It's used by the
* [Manage Sales Channels API Route](https://docs.medusajs.com/api/admin#api-keys_postapikeysidsaleschannels).
*
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to
* manage the sales channels of a publishable API key within your custom flows.
*
*
* @example
* const { result } = await linkSalesChannelsToApiKeyWorkflow(container)
* .run({
@@ -32,7 +32,7 @@ export const linkSalesChannelsToApiKeyWorkflowId =
* remove: ["sc_321"]
* }
* })
*
*
* @summary
* Manage the sales channels of a publishable API key.
*/
@@ -1,6 +1,6 @@
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
import { IAuthModuleService } from "@medusajs/framework/types"
import type { IAuthModuleService } from "@medusajs/framework/types"
import { isDefined, Modules } from "@medusajs/framework/utils"
export type SetAuthAppMetadataStepInput = {
@@ -14,16 +14,16 @@ export const setAuthAppMetadataStepId = "set-auth-app-metadata"
* This step sets the `app_metadata` property of an auth identity. This is useful to
* associate a user (whether it's an admin user or customer) with an auth identity
* that allows them to authenticate into Medusa.
*
* You can learn more about auth identites in
*
* You can learn more about auth identites in
* [this documentation](https://docs.medusajs.com/resources/commerce-modules/auth/auth-identity-and-actor-types).
*
*
* To use this for a custom actor type, check out [this guide](https://docs.medusajs.com/resources/commerce-modules/auth/create-actor-type)
* that explains how to create a custom `manager` actor type and manage its users.
*
*
* @example
* To associate an auth identity with an actor type (user, customer, or other actor types):
*
*
* ```ts
* const data = setAuthAppMetadataStep({
* authIdentityId: "au_1234",
@@ -31,9 +31,9 @@ export const setAuthAppMetadataStepId = "set-auth-app-metadata"
* value: "user_123"
* })
* ```
*
*
* To remove the association with an actor type, such as when deleting the user:
*
*
* ```ts
* const data = setAuthAppMetadataStep({
* authIdentityId: "au_1234",
@@ -9,7 +9,7 @@ import {
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import { emitEventStep, useRemoteQueryStep } from "../../common"
import { ProjectConfigOptions } from "@medusajs/framework/types"
import type { ProjectConfigOptions } from "@medusajs/framework/types"
/**
* This workflow generates a reset password token for a user. It's used by the
@@ -1,4 +1,4 @@
import { Logger } from "@medusajs/framework/types"
import type { Logger } from "@medusajs/framework/types"
import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
import { refundPaymentAndRecreatePaymentSessionWorkflow } from "../workflows/refund-payment-recreate-payment-session"
@@ -1,4 +1,7 @@
import { BigNumberInput, IInventoryService } from "@medusajs/framework/types"
import type {
BigNumberInput,
IInventoryService,
} from "@medusajs/framework/types"
import {
MathBN,
MedusaError,
@@ -1,4 +1,7 @@
import { CreateCartDTO, ICartModuleService } from "@medusajs/framework/types"
import type {
CreateCartDTO,
ICartModuleService,
} from "@medusajs/framework/types"
import { Modules } from "@medusajs/framework/utils"
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
@@ -1,4 +1,7 @@
import { CustomerDTO, ICustomerModuleService } from "@medusajs/framework/types"
import type {
CustomerDTO,
ICustomerModuleService,
} from "@medusajs/framework/types"
import { isDefined, Modules, validateEmail } from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
@@ -1,4 +1,7 @@
import { CartDTO, IPromotionModuleService } from "@medusajs/framework/types"
import type {
CartDTO,
IPromotionModuleService,
} from "@medusajs/framework/types"
import { Modules } from "@medusajs/framework/utils"
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
@@ -1,4 +1,4 @@
import { IPromotionModuleService } from "@medusajs/framework/types"
import type { IPromotionModuleService } from "@medusajs/framework/types"
import {
MedusaError,
Modules,
@@ -79,7 +79,7 @@ export const getPromotionCodesToApply = createStep(
const adjustmentCodes: string[] = []
items.concat(shipping_methods).forEach((object) => {
object.adjustments?.forEach((adjustment) => {
if (adjustment.code && !adjustmentCodes.includes(adjustment.code)) {
if (adjustment.code) {
adjustmentCodes.push(adjustment.code)
}
})
@@ -34,6 +34,10 @@ export interface GetVariantPriceSetsStepBulkInput {
* The variants to get price sets for.
*/
data: {
/**
* The ID of the item.
*/
id?: string
/**
* The ID of the variant to get the price set for.
*/
@@ -51,6 +55,10 @@ interface VariantPriceSetData {
}
interface PriceCalculationItem {
/**
* The ID of the item. In case of variants we wont have an item id
*/
id?: string
variantId: string
priceSetId: string
context?: Record<string, unknown>
@@ -124,7 +132,7 @@ async function processVariantPriceSets(
for (const item of groupItems) {
const calculatedPriceSet = priceSetMap.get(item.priceSetId)
if (calculatedPriceSet) {
result[item.variantId] = calculatedPriceSet
result[item.id ?? item.variantId] = calculatedPriceSet
}
}
}
@@ -196,6 +204,7 @@ function createCalculationItemsFromBulkData(
const priceSetId = variantToPriceSetId.get(item.variantId)
if (priceSetId) {
calculationItems.push({
id: item.id,
variantId: item.variantId,
priceSetId,
context: item.context,
@@ -1,4 +1,4 @@
import { ICartModuleService } from "@medusajs/framework/types"
import type { ICartModuleService } from "@medusajs/framework/types"
import { Modules } from "@medusajs/framework/utils"
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
@@ -1,4 +1,4 @@
import { ICartModuleService } from "@medusajs/framework/types"
import type { ICartModuleService } from "@medusajs/framework/types"
import { Modules } from "@medusajs/framework/utils"
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
@@ -1,4 +1,4 @@
import { ICartModuleService } from "@medusajs/framework/types"
import type { ICartModuleService } from "@medusajs/framework/types"
import { Modules } from "@medusajs/framework/utils"
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
@@ -16,7 +16,10 @@ export interface RemoveShippingMethodFromCartStepInput {
* The shipping methods removed from the cart, along with IDs of related records
* that were removed.
*/
export type RemoveShippingMethodFromCartStepOutput = Record<string, string[]> | void
export type RemoveShippingMethodFromCartStepOutput = Record<
string,
string[]
> | void
export const removeShippingMethodFromCartStepId =
"remove-shipping-method-to-cart-step"
@@ -37,7 +40,7 @@ export const removeShippingMethodFromCartStep = createStep(
)
return new StepResponse(
methods as RemoveShippingMethodFromCartStepOutput,
methods as RemoveShippingMethodFromCartStepOutput,
data.shipping_method_ids
)
},
@@ -1,6 +1,6 @@
import { MathBN, Modules } from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
import { BigNumberInput } from "@medusajs/types"
import type { BigNumberInput } from "@medusajs/framework/types"
/**
* The details of the items and their quantity to reserve.
@@ -1,4 +1,4 @@
import { IPromotionModuleService } from "@medusajs/framework/types"
import type { IPromotionModuleService } from "@medusajs/framework/types"
import {
ContainerRegistrationKeys,
Modules,
@@ -1,4 +1,4 @@
import { CartWorkflowDTO } from "@medusajs/framework/types"
import type { CartWorkflowDTO } from "@medusajs/framework/types"
import {
isPresent,
MathBN,
@@ -1,5 +1,12 @@
import { CartDTO, IFulfillmentModuleService } from "@medusajs/framework/types"
import { arrayDifference, MedusaError, Modules, } from "@medusajs/framework/utils"
import type {
CartDTO,
IFulfillmentModuleService,
} from "@medusajs/framework/types"
import {
arrayDifference,
MedusaError,
Modules,
} from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
/**
@@ -39,7 +46,7 @@ export const validateCartShippingOptionsStepId =
/**
* This step validates shipping options to ensure they can be applied on a cart.
* If not valid, the step throws an error.
*
*
* @example
* const data = validateCartShippingOptionsStep({
* // retrieve the details of the cart from another workflow
@@ -52,7 +59,12 @@ export const validateCartShippingOptionsStepId =
export const validateCartShippingOptionsStep = createStep(
validateCartShippingOptionsStepId,
async (data: ValidateCartShippingOptionsStepInput, { container }) => {
const { option_ids: optionIds = [], cart, shippingOptionsContext, prefetched_shipping_options: prefetchedShippingOptions } = data
const {
option_ids: optionIds = [],
cart,
shippingOptionsContext,
prefetched_shipping_options: prefetchedShippingOptions,
} = data
if (!optionIds.length) {
return new StepResponse(void 0)
@@ -1,4 +1,4 @@
import { CartDTO, CartWorkflowDTO } from "@medusajs/framework/types"
import type { CartDTO, CartWorkflowDTO } from "@medusajs/framework/types"
import { MedusaError } from "@medusajs/framework/utils"
import { createStep } from "@medusajs/framework/workflows-sdk"
@@ -16,13 +16,13 @@ export const validateCartStepId = "validate-cart"
/**
* This step validates a cart to ensure it exists and is not completed.
* If not valid, the step throws an error.
*
*
* :::tip
*
*
* You can use the {@link retrieveCartStep} to retrieve a cart's details.
*
*
* :::
*
*
* @example
* const data = validateCartStep({
* // retrieve the details of the cart from another workflow
@@ -1,7 +1,7 @@
import { MedusaError } from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
import { SalesChannelDTO } from "@medusajs/types"
import type { SalesChannelDTO } from "@medusajs/framework/types"
export const validateSalesChannelStep = createStep(
"validate-sales-channel",
@@ -2,7 +2,7 @@ import { Modules, promiseAll } from "@medusajs/framework/utils"
import {
IFulfillmentModuleService,
ValidateFulfillmentDataContext,
} from "@medusajs/types"
} from "@medusajs/framework/types"
import { createStep, StepResponse } from "@medusajs/workflows-sdk"
/**
@@ -19,7 +19,7 @@ export type ValidateShippingMethodsDataInput = {
*/
provider_id: string
/**
* The `data` property of the shipping option that the shipping method was
* The `data` property of the shipping option that the shipping method was
* created from.
*/
option_data: Record<string, unknown>
@@ -36,16 +36,18 @@ export type ValidateShippingMethodsDataInput = {
/**
* The validated data of the shipping methods.
*/
export type ValidateShippingMethodsDataOutput = void | {
[x: string]: Record<string, unknown>;
}[]
export type ValidateShippingMethodsDataOutput =
| void
| {
[x: string]: Record<string, unknown>
}[]
export const validateAndReturnShippingMethodsDataStepId =
"validate-and-return-shipping-methods-data"
/**
* This step validates shipping options to ensure they can be applied on a cart.
* The step either returns the validated data or void.
*
*
* @example
* const data = validateAndReturnShippingMethodsDataStep({
* id: "sm_123",
@@ -4,7 +4,7 @@ import {
CartWorkflowDTO,
ProductVariantDTO,
ShippingOptionDTO,
} from "@medusajs/types"
} from "@medusajs/framework/types"
import { createStep, StepResponse } from "@medusajs/workflows-sdk"
/**
@@ -1,4 +1,4 @@
import { BigNumberInput } from "@medusajs/framework/types"
import type { BigNumberInput } from "@medusajs/framework/types"
import { MedusaError, isPresent } from "@medusajs/framework/utils"
import { createStep } from "@medusajs/framework/workflows-sdk"
@@ -30,7 +30,7 @@ export const validateVariantPricesStepId = "validate-variant-prices"
/**
* This step validates the specified variant objects to ensure they have prices.
* If not valid, the step throws an error.
*
*
* @example
* const data = validateVariantPricesStep({
* variants: [
@@ -1,4 +1,4 @@
import { ConfirmVariantInventoryWorkflowInputDTO } from "@medusajs/framework/types"
import type { ConfirmVariantInventoryWorkflowInputDTO } from "@medusajs/framework/types"
import { MedusaError } from "@medusajs/framework/utils"
import { prepareConfirmInventoryInput } from "../prepare-confirm-inventory-input"
@@ -2,12 +2,11 @@ import {
AdditionalData,
AddToCartWorkflowInputDTO,
ConfirmVariantInventoryWorkflowInputDTO,
WithCalculatedPrice,
CreateLineItemForCartDTO,
} from "@medusajs/framework/types"
import {
CartWorkflowEvents,
deduplicate,
filterObjectByKeys,
isDefined,
} from "@medusajs/framework/utils"
import {
@@ -16,7 +15,6 @@ import {
parallelize,
transform,
when,
WorkflowData,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import { useQueryGraphStep } from "../../common"
@@ -25,12 +23,10 @@ import { acquireLockStep, releaseLockStep } from "../../locking"
import {
createLineItemsStep,
getLineItemActionsStep,
getVariantPriceSetsStep,
updateLineItemsStep,
} from "../steps"
import { validateCartStep } from "../steps/validate-cart"
import { validateLineItemPricesStep } from "../steps/validate-line-item-prices"
import { validateVariantPricesStep } from "../steps/validate-variant-prices"
import {
cartFieldsForPricingContext,
productVariantsFields,
@@ -43,6 +39,7 @@ import {
} from "../utils/prepare-line-item-data"
import { pricingContextResult } from "../utils/schemas"
import { confirmVariantInventoryWorkflow } from "./confirm-variant-inventory"
import { getVariantsAndItemsWithPrices } from "./get-variants-and-items-with-prices"
import { refreshCartItemsWorkflow } from "./refresh-cart-items"
const cartFields = ["completed_at"].concat(cartFieldsForPricingContext)
@@ -119,32 +116,30 @@ export const addToCartWorkflow = createWorkflow(
name: addToCartWorkflowId,
idempotent: false,
},
(input: WorkflowData<AddToCartWorkflowInputDTO & AdditionalData>) => {
(input: AddToCartWorkflowInputDTO & AdditionalData) => {
acquireLockStep({
key: input.cart_id,
timeout: 2,
ttl: 10,
})
const cartQuery = useQueryGraphStep({
const { data: cart } = useQueryGraphStep({
entity: "cart",
filters: { id: input.cart_id },
fields: cartFields,
options: { throwIfKeyNotFound: true },
options: { throwIfKeyNotFound: true, isList: false },
}).config({ name: "get-cart" })
const cart = transform({ cartQuery }, ({ cartQuery }) => {
return cartQuery.data[0]
})
validateCartStep({ cart })
const validate = createHook("validate", {
input,
cart,
})
const variantIds = transform({ input }, (data) => {
return (data.input.items ?? []).map((i) => i.variant_id).filter(Boolean)
const variantIds = transform({ input }, (data): string[] => {
return (data.input.items ?? [])
.map((i) => i.variant_id)
.filter((v): v is string => !!v)
})
const setPricingContext = createHook(
@@ -162,43 +157,46 @@ export const addToCartWorkflow = createWorkflow(
const setPricingContextResult = setPricingContext.getResult()
const variants = when(
const { variants: variantsData, lineItems: lineItemsData } = when(
"should-calculate-prices",
{ variantIds },
({ variantIds }) => {
return !!variantIds.length
}
).then(() => {
const pricingContext = transform(
{ cart, items: input.items, setPricingContextResult },
(data): { variantId: string; context: Record<string, unknown> }[] => {
const baseContext = {
...filterObjectByKeys(data.cart, cartFieldsForPricingContext),
...(data.setPricingContextResult
? data.setPricingContextResult
: {}),
currency_code: data.cart.currency_code,
region_id: data.cart.region_id,
region: data.cart.region,
customer_id: data.cart.customer_id,
customer: data.cart.customer,
}
const { variants: variantsData, lineItems: items } =
getVariantsAndItemsWithPrices.runAsStep({
input: {
cart,
items: input.items,
setPricingContextResult: setPricingContextResult!,
variants: {
id: variantIds,
fields: deduplicate([
...productVariantsFields,
...requiredVariantFieldsForInventoryConfirmation,
]),
},
},
})
return data.items
.filter((i) => i.variant_id)
.map((item) => {
return {
variantId: item.variant_id!,
context: {
...baseContext,
quantity: item.quantity,
},
}
})
}
)
const lineItems = transform({ items }, ({ items }) => {
return items.map((item) => {
return item.data as CreateLineItemForCartDTO
})
})
const { data: variantsData } = useQueryGraphStep({
return { variants: variantsData, lineItems }
})
const fetchedVariants = when(
"fetch-variants",
{ variantsData, variantIds },
({ variantsData, variantIds }) => {
return !variantsData?.length && !!variantIds.length
}
).then(() => {
return useQueryGraphStep({
entity: "variants",
fields: deduplicate([
...productVariantsFields,
@@ -207,55 +205,50 @@ export const addToCartWorkflow = createWorkflow(
filters: {
id: variantIds,
},
})
const calculatedPriceSets = getVariantPriceSetsStep({
data: pricingContext,
})
const variants = transform(
{ variantsData, calculatedPriceSets },
({ variantsData, calculatedPriceSets }) => {
return variantsData.map((variant) => {
variant.calculated_price = calculatedPriceSets[variant.id]
return variant
})
}
)
validateVariantPricesStep({ variants })
return variants as (PrepareVariantLineItemInput &
ConfirmVariantInventoryWorkflowInputDTO["variants"][number] &
WithCalculatedPrice)[]
}).config({ name: "fetch-variants" })
})
const lineItems = transform({ input, variants }, (data) => {
const items = (data.input.items ?? []).map((item) => {
const variant = (data.variants ?? []).find(
(v) => v.id === item.variant_id
)!
const variants = transform(
{ variantsData, fetchedVariants },
({ variantsData, fetchedVariants }) => {
return (variantsData ??
fetchedVariants) as unknown as PrepareVariantLineItemInput[]
}
)
const input: PrepareLineItemDataInput = {
item,
variant: variant,
cartId: data.input.cart_id,
unitPrice: item.unit_price,
isTaxInclusive:
item.is_tax_inclusive ??
variant?.calculated_price?.is_calculated_price_tax_inclusive,
isCustomPrice: isDefined(item?.unit_price),
const lineItems = transform(
{ cart_id: input.cart_id, items: input.items, lineItemsData, variants },
({ cart_id, items: items_, lineItemsData, variants }) => {
if (lineItemsData?.length) {
return lineItemsData
}
if (variant && !isDefined(input.unitPrice)) {
input.unitPrice = variant.calculated_price?.calculated_amount
}
const items = (items_ ?? []).map((item) => {
const variant = (variants ?? []).find(
(v) => v.id === item.variant_id
)!
return prepareLineItemData(input)
})
const input: PrepareLineItemDataInput = {
item,
variant: variant,
cartId: cart_id,
unitPrice: item.unit_price,
isTaxInclusive:
item.is_tax_inclusive ??
variant?.calculated_price?.is_calculated_price_tax_inclusive,
isCustomPrice: isDefined(item?.unit_price),
}
return items
})
if (variant && !isDefined(input.unitPrice)) {
input.unitPrice = variant.calculated_price?.calculated_amount
}
return prepareLineItemData(input)
})
return items
}
)
validateLineItemPricesStep({ items: lineItems })
@@ -287,7 +280,8 @@ export const addToCartWorkflow = createWorkflow(
confirmVariantInventoryWorkflow.runAsStep({
input: {
sales_channel_id: cart.sales_channel_id,
variants,
variants:
variants as unknown as ConfirmVariantInventoryWorkflowInputDTO["variants"],
items: input.items,
itemsToUpdate: itemsToConfirmInventory,
},
@@ -1,11 +1,11 @@
import { ConfirmVariantInventoryWorkflowInputDTO } from "@medusajs/framework/types"
import type { ConfirmVariantInventoryWorkflowInputDTO } from "@medusajs/framework/types"
import {
WorkflowData,
WorkflowResponse,
createWorkflow,
transform,
} from "@medusajs/framework/workflows-sdk"
import { BigNumberInput } from "@medusajs/types"
import type { BigNumberInput } from "@medusajs/framework/types"
import { confirmInventoryStep } from "../steps"
import { prepareConfirmInventoryInput } from "../utils/prepare-confirm-inventory-input"
@@ -1,11 +1,12 @@
import {
AdditionalData,
ConfirmVariantInventoryWorkflowInputDTO,
CreateCartDTO,
CreateCartWorkflowInputDTO,
} from "@medusajs/framework/types"
import {
CartWorkflowEvents,
deduplicate,
isDefined,
MedusaError,
} from "@medusajs/framework/utils"
import {
@@ -13,30 +14,22 @@ import {
createWorkflow,
parallelize,
transform,
when,
WorkflowData,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import { useQueryGraphStep } from "../../common"
import { emitEventStep } from "../../common/steps/emit-event"
import {
createCartsStep,
findOneOrAnyRegionStep,
findOrCreateCustomerStep,
findSalesChannelStep,
getVariantPriceSetsStep,
} from "../steps"
import { validateLineItemPricesStep } from "../steps/validate-line-item-prices"
import { validateSalesChannelStep } from "../steps/validate-sales-channel"
import { validateVariantPricesStep } from "../steps/validate-variant-prices"
import { productVariantsFields } from "../utils/fields"
import { requiredVariantFieldsForInventoryConfirmation } from "../utils/prepare-confirm-inventory-input"
import {
prepareLineItemData,
PrepareLineItemDataInput,
} from "../utils/prepare-line-item-data"
import { pricingContextResult } from "../utils/schemas"
import { confirmVariantInventoryWorkflow } from "./confirm-variant-inventory"
import { getVariantsAndItemsWithPrices } from "./get-variants-and-items-with-prices"
import { refreshPaymentCollectionForCartWorkflow } from "./refresh-payment-collection"
import { updateCartPromotionsWorkflow } from "./update-cart-promotions"
import { updateTaxLinesWorkflow } from "./update-tax-lines"
@@ -119,7 +112,9 @@ export const createCartWorkflow = createWorkflow(
createCartWorkflowId,
(input: WorkflowData<CreateCartWorkflowInput>) => {
const variantIds = transform({ input }, (data) => {
return (data.input.items ?? []).map((i) => i.variant_id).filter(Boolean)
return (data.input.items ?? [])
.map((i) => i.variant_id)
.filter((v): v is string => !!v)
})
const [salesChannel, region, customerData] = parallelize(
@@ -151,79 +146,31 @@ export const createCartWorkflow = createWorkflow(
)
const setPricingContextResult = setPricingContext.getResult()
// TODO: This is on par with the context used in v1.*, but we can be more flexible.
const pricingContext = transform(
{ input, region, customerData, setPricingContextResult },
(data) => {
if (!data.region) {
throw new MedusaError(MedusaError.Types.NOT_FOUND, "No regions found")
}
return {
...(data.setPricingContextResult ? data.setPricingContextResult : {}),
currency_code: data.input.currency_code ?? data.region.currency_code,
region_id: data.region.id,
customer_id: data.customerData.customer?.id,
}
}
)
const variants = when("has-variants", { variantIds }, ({ variantIds }) => {
return !!variantIds.length
}).then(() => {
const { data: variantsData } = useQueryGraphStep({
entity: "variants",
fields: deduplicate([
...productVariantsFields,
...requiredVariantFieldsForInventoryConfirmation,
]),
filters: {
id: variantIds,
const { variants, lineItems } = getVariantsAndItemsWithPrices.runAsStep({
input: {
cart: {
currency_code: input.currency_code,
region,
region_id: region.id,
customer_id: customerData.customer?.id,
},
})
const calculatedPriceContext = transform(
{ pricingContext, items: input.items },
(data): { variantId: string; context: Record<string, unknown> }[] => {
const baseContext = data.pricingContext
return (data.items ?? [])
.filter((i) => i.variant_id)
.map((item) => {
return {
variantId: item.variant_id!,
context: {
...baseContext,
quantity: item.quantity,
},
}
})
}
)
const calculatedPriceSets = getVariantPriceSetsStep({
data: calculatedPriceContext,
})
const variants = transform(
{ variantsData, calculatedPriceSets },
({ variantsData, calculatedPriceSets }) => {
return variantsData.map((variant) => {
variant.calculated_price = calculatedPriceSets[variant.id]
return variant
})
}
)
validateVariantPricesStep({ variants })
return variants
items: input.items,
setPricingContextResult: setPricingContextResult!,
variants: {
id: variantIds,
fields: deduplicate([
...productVariantsFields,
...requiredVariantFieldsForInventoryConfirmation,
]),
},
},
})
confirmVariantInventoryWorkflow.runAsStep({
input: {
sales_channel_id: salesChannel.id,
variants: variants!,
variants:
variants as unknown as ConfirmVariantInventoryWorkflowInputDTO["variants"],
items: input.items!,
},
})
@@ -262,39 +209,11 @@ export const createCartWorkflow = createWorkflow(
}
)
const lineItems = transform({ input, variants }, (data) => {
const items = (data.input.items ?? []).map((item) => {
const variant = (data.variants ?? []).find(
(v) => v.id === item.variant_id
)!
const input: PrepareLineItemDataInput = {
item,
variant: variant,
unitPrice: item.unit_price,
isTaxInclusive:
item.is_tax_inclusive ??
variant?.calculated_price?.is_calculated_price_tax_inclusive,
isCustomPrice: isDefined(item?.unit_price),
}
if (variant && !input.unitPrice) {
input.unitPrice = variant.calculated_price?.calculated_amount
}
return prepareLineItemData(input)
})
return items
})
validateLineItemPricesStep({ items: lineItems })
const cartToCreate = transform({ lineItems, cartInput }, (data) => {
return {
...data.cartInput,
items: data.lineItems,
}
items: data.lineItems.map((i) => i.data),
} as unknown as CreateCartDTO
})
const validate = createHook("validate", {
@@ -0,0 +1,226 @@
import {
BigNumberInput,
CartDTO,
CartLineItemDTO,
CreateCartCreateLineItemDTO,
CustomerDTO,
OrderWorkflow,
RegionDTO,
UpdateLineItemDTO,
UpdateLineItemWithSelectorDTO,
} from "@medusajs/framework/types"
import {
filterObjectByKeys,
isDefined,
MedusaError,
simpleHash,
} from "@medusajs/framework/utils"
import {
createWorkflow,
transform,
WorkflowData,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import { useQueryGraphStep } from "../../common"
import { getVariantPriceSetsStep } from "../steps"
import {
cartFieldsForPricingContext,
productVariantsFields,
} from "../utils/fields"
import {
prepareLineItemData,
PrepareLineItemDataInput,
} from "../utils/prepare-line-item-data"
interface GetVariantsAndItemsWithPricesWorkflowInput {
cart: Partial<CartDTO> & {
region?: Partial<RegionDTO>
region_id?: string
customer?: Partial<CustomerDTO>
customer_id?: string
}
items?: Partial<
| CreateCartCreateLineItemDTO
| CartLineItemDTO
| OrderWorkflow.OrderAddLineItemWorkflowInput["items"][number]
>[]
setPricingContextResult: object
variants?: {
id?: string[]
fields?: string[]
}
}
type GetVariantsAndItemsWithPricesWorkflowOutput = {
// The variant can depend on the requested fields and therefore the caller will know better
variants: (object & {
calculated_price: {
calculated_price: {
price_list_type: string
}
is_calculated_price_tax_inclusive: boolean
original_amount: BigNumberInput
calculated_amount: BigNumberInput
}
})[]
lineItems: UpdateLineItemWithSelectorDTO[]
}
export const getVariantsAndItemsWithPricesId =
"get-variant-items-with-prices-workflow"
export const getVariantsAndItemsWithPrices = createWorkflow(
getVariantsAndItemsWithPricesId,
(
input: WorkflowData<GetVariantsAndItemsWithPricesWorkflowInput>
): WorkflowResponse<GetVariantsAndItemsWithPricesWorkflowOutput> => {
const variantIds = transform(
{ cart: input.cart, items: input.items, variantIds: input.variants?.id },
(data): string[] => {
if (data.variantIds) {
return data.variantIds
}
return Array.from(
new Set(
(data.cart.items ?? data.items ?? []).map((i) => i.variant_id)
)
).filter((v): v is string => !!v)
}
)
const cartPricingContext = transform(
{
cart: input.cart,
items: input.items,
setPricingContextResult: input.setPricingContextResult,
},
(
data
): {
id: string
variantId: string
context: Record<string, unknown>
}[] => {
const cart = data.cart
const baseContext = {
...filterObjectByKeys(cart, cartFieldsForPricingContext),
...(data.setPricingContextResult ? data.setPricingContextResult : {}),
currency_code: cart.currency_code ?? cart.region?.currency_code,
region_id: cart.region_id,
region: cart.region,
customer_id: cart.customer_id,
customer: cart.customer,
}
return (data.items ?? cart.items ?? [])
.filter((i) => i.variant_id)
.map((item) => {
const idLike =
(item as CartLineItemDTO).id ?? simpleHash(JSON.stringify(item))
return {
id: idLike,
variantId: item.variant_id!,
context: {
...baseContext,
quantity: item.quantity,
},
}
})
}
)
const variantQueryFields = transform(
{ variants: input.variants },
(data) => {
return data.variants?.fields ?? productVariantsFields
}
)
const { data: variantsData } = useQueryGraphStep({
entity: "variants",
fields: variantQueryFields,
filters: {
id: variantIds,
},
}).config({ name: "fetch-variants" })
const calculatedPriceSets = getVariantPriceSetsStep({
data: cartPricingContext,
})
const variantsItemsWithPrices = transform(
{
cart: input.cart,
items: input.items,
variantsData,
calculatedPriceSets,
},
({
cart,
items: inputItems,
variantsData,
calculatedPriceSets,
}): GetVariantsAndItemsWithPricesWorkflowOutput => {
const priceNotFound: string[] = []
const items = (inputItems ?? cart.items ?? []).map((item) => {
const item_ = item as any
const idLike =
(item as CartLineItemDTO).id ?? simpleHash(JSON.stringify(item))
let calculatedPriceSet = calculatedPriceSets[idLike]
if (!calculatedPriceSet) {
calculatedPriceSet = calculatedPriceSets[item_.variant_id!]
}
if (!calculatedPriceSet && item_.variant_id) {
priceNotFound.push(item_.variant_id)
}
const variant = variantsData.find((v) => v.id === item.variant_id)
if (variant) {
variant.calculated_price = calculatedPriceSet
}
const isCustomPrice =
item_.is_custom_price ?? isDefined(item?.unit_price)
const input: PrepareLineItemDataInput = {
item: item_,
variant: variant,
cartId: cart.id,
unitPrice: item_.unit_price,
isTaxInclusive:
item_.is_tax_inclusive ??
calculatedPriceSet?.is_calculated_price_tax_inclusive,
isCustomPrice: isCustomPrice,
}
if (variant && !isCustomPrice) {
input.unitPrice = calculatedPriceSet.calculated_amount
input.isTaxInclusive =
calculatedPriceSet.is_calculated_price_tax_inclusive
}
const preparedItem = prepareLineItemData(input)
return {
selector: { id: (item_ as CartLineItemDTO).id },
data: preparedItem as Partial<UpdateLineItemDTO>,
}
})
if (priceNotFound.length > 0) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Variants with IDs ${priceNotFound.join(", ")} do not have a price`
)
}
return { variants: variantsData, lineItems: items }
}
)
return new WorkflowResponse(variantsItemsWithPrices)
}
)
@@ -11,7 +11,7 @@ import {
AdditionalData,
CalculateShippingOptionPriceDTO,
ListShippingOptionsForCartWithPricingWorkflowInput,
} from "@medusajs/types"
} from "@medusajs/framework/types"
import { useQueryGraphStep, validatePresenceOfStep } from "../../common"
import { useRemoteQueryStep } from "../../common/steps/use-remote-query"
@@ -14,9 +14,16 @@ import { cartFieldsForPricingContext } from "../utils/fields"
import {
AdditionalData,
ListShippingOptionsForCartWorkflowInput,
} from "@medusajs/types"
import { deduplicate, filterObjectByKeys, isDefined } from "@medusajs/framework/utils"
import { pricingContextResult, shippingOptionsContextResult } from "../utils/schemas"
} from "@medusajs/framework/types"
import {
deduplicate,
filterObjectByKeys,
isDefined,
} from "@medusajs/framework/utils"
import {
pricingContextResult,
shippingOptionsContextResult,
} from "../utils/schemas"
export const listShippingOptionsForCartWorkflowId =
"list-shipping-options-for-cart"
@@ -81,26 +88,26 @@ export const listShippingOptionsForCartWorkflowId =
* Learn more about prices calculation context in the [Prices Calculation](https://docs.medusajs.com/resources/commerce-modules/pricing/price-calculation) documentation.
*
* :::
*
*
* @property hooks.setShippingOptionsContext - This hook is executed after the cart is retrieved and before the shipping options are queried. You can consume this hook to return any custom context useful for the shipping options retrieval.
*
* For example, you can consume the hook to add the customer Id to the context:
*
*
* ```ts
* import { listShippingOptionsForCartWithPricingWorkflow } from "@medusajs/medusa/core-flows"
* import { StepResponse } from "@medusajs/workflows-sdk"
*
*
* listShippingOptionsForCartWithPricingWorkflow.hooks.setShippingOptionsContext(
* async ({ cart }, { container }) => {
*
*
* if (cart.customer_id) {
* return new StepResponse({
* customer_id: cart.customer_id,
* })
* }
*
*
* const query = container.resolve("query")
*
*
* const { data: carts } = await query.graph({
* entity: "cart",
* filters: {
@@ -108,20 +115,20 @@ export const listShippingOptionsForCartWorkflowId =
* },
* fields: ["customer_id"],
* })
*
*
* return new StepResponse({
* customer_id: carts[0].customer_id,
* })
* }
* )
* ```
*
*
* The `customer_id` property will be added to the context along with other properties such as `is_return` and `enabled_in_store`.
*
*
* :::note
*
*
* You should also consume the `setShippingOptionsContext` hook in the {@link listShippingOptionsForCartWithPricingWorkflow} workflow to ensure that the context is consistent when listing shipping options across workflows.
*
*
* :::
*/
export const listShippingOptionsForCartWorkflow = createWorkflow(
@@ -209,16 +216,31 @@ export const listShippingOptionsForCartWorkflow = createWorkflow(
resultValidator: shippingOptionsContextResult,
}
)
const setShippingOptionsContextResult = setShippingOptionsContext.getResult()
const setShippingOptionsContextResult =
setShippingOptionsContext.getResult()
const queryVariables = transform(
{ input, fulfillmentSetIds, cart, setPricingContextResult, setShippingOptionsContextResult },
({ input, fulfillmentSetIds, cart, setPricingContextResult, setShippingOptionsContextResult }) => {
{
input,
fulfillmentSetIds,
cart,
setPricingContextResult,
setShippingOptionsContextResult,
},
({
input,
fulfillmentSetIds,
cart,
setPricingContextResult,
setShippingOptionsContextResult,
}) => {
return {
id: input.option_ids,
context: {
...(setShippingOptionsContextResult ? setShippingOptionsContextResult : {}),
...(setShippingOptionsContextResult
? setShippingOptionsContextResult
: {}),
is_return: input.is_return ? "true" : "false",
enabled_in_store: !isDefined(input.enabled_in_store)
? "true"
@@ -1,8 +1,5 @@
import {
filterObjectByKeys,
isDefined,
PromotionActions,
} from "@medusajs/framework/utils"
import type { AdditionalData } from "@medusajs/framework/types"
import { isDefined, PromotionActions } from "@medusajs/framework/utils"
import {
createHook,
createWorkflow,
@@ -11,22 +8,13 @@ import {
WorkflowData,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import { AdditionalData, CartDTO } from "@medusajs/types"
import { useQueryGraphStep } from "../../common"
import { useRemoteQueryStep } from "../../common/steps/use-remote-query"
import { acquireLockStep, releaseLockStep } from "../../locking"
import { getVariantPriceSetsStep, updateLineItemsStep } from "../steps"
import { validateVariantPricesStep } from "../steps/validate-variant-prices"
import {
cartFieldsForPricingContext,
cartFieldsForRefreshSteps,
productVariantsFields,
} from "../utils/fields"
import {
prepareLineItemData,
PrepareLineItemDataInput,
} from "../utils/prepare-line-item-data"
import { updateLineItemsStep } from "../steps"
import { cartFieldsForRefreshSteps } from "../utils/fields"
import { pricingContextResult } from "../utils/schemas"
import { getVariantsAndItemsWithPrices } from "./get-variants-and-items-with-prices"
import { refreshCartShippingMethodsWorkflow } from "./refresh-cart-shipping-methods"
import { refreshPaymentCollectionForCartWorkflow } from "./refresh-payment-collection"
import { updateCartPromotionsWorkflow } from "./update-cart-promotions"
@@ -168,93 +156,11 @@ export const refreshCartItemsWorkflow = createWorkflow(
},
})
const variantIds = transform({ cart }, (data: { cart: CartDTO }) => {
return (data.cart.items ?? []).map((i) => i.variant_id).filter(Boolean)
})
const cartPricingContext = transform(
{ cart, setPricingContextResult },
(data): { variantId: string; context: Record<string, unknown> }[] => {
const cart = data.cart
const baseContext = {
...filterObjectByKeys(cart, cartFieldsForPricingContext),
...(data.setPricingContextResult
? data.setPricingContextResult
: {}),
currency_code: cart.currency_code,
region_id: cart.region_id,
region: cart.region,
customer_id: cart.customer_id,
customer: cart.customer,
}
return cart.items
.filter((i) => i.variant_id)
.map((item) => {
return {
variantId: item.variant_id,
context: {
...baseContext,
quantity: item.quantity,
},
}
})
}
)
const { data: variantsData } = useQueryGraphStep({
entity: "variants",
fields: productVariantsFields,
filters: {
id: variantIds,
const { lineItems } = getVariantsAndItemsWithPrices.runAsStep({
input: {
cart,
setPricingContextResult: setPricingContextResult!,
},
}).config({ name: "fetch-variants" })
const calculatedPriceSets = getVariantPriceSetsStep({
data: cartPricingContext,
})
const variants = transform(
{ variantsData, calculatedPriceSets },
({ variantsData, calculatedPriceSets }) => {
return variantsData.map((variant) => {
variant.calculated_price = calculatedPriceSets[variant.id]
return variant
})
}
)
validateVariantPricesStep({ variants })
const lineItems = transform({ cart, variants }, ({ cart, variants }) => {
const items = cart.items.map((item) => {
const variant = (variants ?? []).find(
(v) => v.id === item.variant_id
)!
const input: PrepareLineItemDataInput = {
item,
variant: variant,
cartId: cart.id,
unitPrice: item.unit_price,
isTaxInclusive: item.is_tax_inclusive,
}
if (variant && !item.is_custom_price) {
input.unitPrice = variant.calculated_price?.calculated_amount
input.isTaxInclusive =
variant.calculated_price?.is_calculated_price_tax_inclusive
}
const preparedItem = prepareLineItemData(input)
return {
selector: { id: item.id },
data: preparedItem,
}
})
return items
})
updateLineItemsStep({
@@ -1,4 +1,7 @@
import { BigNumberInput, PaymentSessionDTO } from "@medusajs/framework/types"
import type {
BigNumberInput,
PaymentSessionDTO,
} from "@medusajs/framework/types"
import {
createWorkflow,
WorkflowData,
@@ -1,5 +1,5 @@
import { Link } from "@medusajs/framework/modules-sdk"
import { LinkDefinition } from "@medusajs/framework/types"
import type { LinkDefinition } from "@medusajs/framework/types"
import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
@@ -1,5 +1,5 @@
import { Link } from "@medusajs/framework/modules-sdk"
import { LinkDefinition } from "@medusajs/framework/types"
import type { LinkDefinition } from "@medusajs/framework/types"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
@@ -1,5 +1,5 @@
import { Link } from "@medusajs/framework/modules-sdk"
import { LinkDefinition } from "@medusajs/framework/types"
import type { LinkDefinition } from "@medusajs/framework/types"
import {
ContainerRegistrationKeys,
MedusaError,
@@ -1,4 +1,7 @@
import { BatchWorkflowInput, LinkDefinition } from "@medusajs/framework/types"
import type {
BatchWorkflowInput,
LinkDefinition,
} from "@medusajs/framework/types"
import {
WorkflowData,
WorkflowResponse,
@@ -12,12 +15,12 @@ import { updateRemoteLinksStep } from "../steps/update-remote-links"
export const batchLinksWorkflowId = "batch-links"
/**
* This workflow manages one or more links to create, update, or dismiss them.
*
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to
* manage links within your custom flows.
*
*
* Learn more about links in [this documentation](https://docs.medusajs.com/learn/fundamentals/module-links/link).
*
*
* @example
* const { result } = await batchLinksWorkflow(container)
* .run({
@@ -59,9 +62,9 @@ export const batchLinksWorkflowId = "batch-links"
* ]
* }
* })
*
*
* @summary
*
*
* Manage links between two records of linked data models.
*/
export const batchLinksWorkflow = createWorkflow(
@@ -1,4 +1,4 @@
import { LinkDefinition } from "@medusajs/framework/types"
import type { LinkDefinition } from "@medusajs/framework/types"
import {
WorkflowData,
WorkflowResponse,
@@ -9,12 +9,12 @@ import { createRemoteLinkStep } from "../steps/create-remote-links"
export const createLinksWorkflowId = "create-link"
/**
* This workflow creates one or more links between records.
*
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to
* create links within your custom flows.
*
*
* Learn more about links in [this documentation](https://docs.medusajs.com/learn/fundamentals/module-links/link).
*
*
* @example
* const { result } = await createLinksWorkflow(container)
* .run({
@@ -30,9 +30,9 @@ export const createLinksWorkflowId = "create-link"
* }
* ]
* })
*
*
* @summary
*
*
* Create links between two records of linked data models.
*/
export const createLinksWorkflow = createWorkflow(
@@ -1,4 +1,4 @@
import { LinkDefinition } from "@medusajs/framework/types"
import type { LinkDefinition } from "@medusajs/framework/types"
import {
WorkflowData,
WorkflowResponse,
@@ -9,12 +9,12 @@ import { dismissRemoteLinkStep } from "../steps/dismiss-remote-links"
export const dismissLinksWorkflowId = "dismiss-link"
/**
* This workflow dismisses one or more links between records.
*
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to
* dismiss links within your custom flows.
*
*
* Learn more about links in [this documentation](https://docs.medusajs.com/learn/fundamentals/module-links/link).
*
*
* @example
* const { result } = await dismissLinksWorkflow(container)
* .run({
@@ -30,9 +30,9 @@ export const dismissLinksWorkflowId = "dismiss-link"
* }
* ]
* })
*
*
* @summary
*
*
* Dismiss links between two records of linked data models.
*/
export const dismissLinksWorkflow = createWorkflow(
@@ -1,4 +1,4 @@
import { LinkDefinition } from "@medusajs/framework/types"
import type { LinkDefinition } from "@medusajs/framework/types"
import {
WorkflowData,
WorkflowResponse,
@@ -9,12 +9,12 @@ import { updateRemoteLinksStep } from "../steps/update-remote-links"
export const updateLinksWorkflowId = "update-link"
/**
* This workflow updates one or more links between records.
*
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to
* update links within your custom flows.
*
*
* Learn more about links in [this documentation](https://docs.medusajs.com/learn/fundamentals/module-links/link).
*
*
* @example
* const { result } = await updateLinksWorkflow(container)
* .run({
@@ -35,9 +35,9 @@ export const updateLinksWorkflowId = "update-link"
* }
* ]
* })
*
*
* @summary
*
*
* Update links between two records of linked data models.
*/
export const updateLinksWorkflow = createWorkflow(
@@ -1,4 +1,4 @@
import { ICustomerModuleService } from "@medusajs/framework/types"
import type { ICustomerModuleService } from "@medusajs/framework/types"
import { Modules } from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
@@ -1,10 +1,10 @@
import { LinkWorkflowInput } from "@medusajs/framework/types"
import type { LinkWorkflowInput } from "@medusajs/framework/types"
import { WorkflowData, createWorkflow } from "@medusajs/framework/workflows-sdk"
import { linkCustomerGroupsToCustomerStep } from "../steps"
/**
* The data to manage the customer groups of a customer.
*
*
* @property id - The ID of the customer to manage its groups.
* @property add - The IDs of the customer groups to add the customer to.
* @property remove - The IDs of the customer groups to remove the customer from.
@@ -14,12 +14,12 @@ export type LinkCustomerGroupsToCustomerWorkflowInput = LinkWorkflowInput
export const linkCustomerGroupsToCustomerWorkflowId =
"link-customer-groups-to-customer"
/**
* This workflow manages the customer groups a customer is in. It's used by the
* This workflow manages the customer groups a customer is in. It's used by the
* [Manage Groups of Customer Admin API Route](https://docs.medusajs.com/api/admin#customers_postcustomersidcustomergroups).
*
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to
* manage the customer groups of a customer in your custom flow.
*
*
* @example
* const { result } = await linkCustomerGroupsToCustomerWorkflow(container)
* .run({
@@ -29,14 +29,16 @@ export const linkCustomerGroupsToCustomerWorkflowId =
* remove: ["cusgrp_456"]
* }
* })
*
*
* @summary
*
*
* Manage groups of a customer.
*/
export const linkCustomerGroupsToCustomerWorkflow = createWorkflow(
linkCustomerGroupsToCustomerWorkflowId,
(input: WorkflowData<LinkCustomerGroupsToCustomerWorkflowInput>): WorkflowData<void> => {
(
input: WorkflowData<LinkCustomerGroupsToCustomerWorkflowInput>
): WorkflowData<void> => {
return linkCustomerGroupsToCustomerStep(input)
}
)
@@ -1,10 +1,10 @@
import { LinkWorkflowInput } from "@medusajs/framework/types"
import type { LinkWorkflowInput } from "@medusajs/framework/types"
import { WorkflowData, createWorkflow } from "@medusajs/framework/workflows-sdk"
import { linkCustomersToCustomerGroupStep } from "../steps"
/**
* The data to manage the customers of a group.
*
*
* @property id - The ID of the customer group to manage its customers.
* @property add - The IDs of the customers to add to the customer group.
* @property remove - The IDs of the customers to remove from the customer group.
@@ -14,12 +14,12 @@ export type LinkCustomersToCustomerGroupWorkflow = LinkWorkflowInput
export const linkCustomersToCustomerGroupWorkflowId =
"link-customers-to-customer-group"
/**
* This workflow manages the customers of a customer group. It's used by the
* This workflow manages the customers of a customer group. It's used by the
* [Manage Customers of Group Admin API Route](https://docs.medusajs.com/api/admin#customer-groups_postcustomergroupsidcustomers).
*
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to
* manage the customers of a customer group within your custom flows.
*
*
* @example
* const { result } = await linkCustomersToCustomerGroupWorkflow(container)
* .run({
@@ -29,14 +29,16 @@ export const linkCustomersToCustomerGroupWorkflowId =
* remove: ["cus_456"]
* }
* })
*
*
* @summary
*
*
* Manage the customers of a customer group.
*/
export const linkCustomersToCustomerGroupWorkflow = createWorkflow(
linkCustomersToCustomerGroupWorkflowId,
(input: WorkflowData<LinkCustomersToCustomerGroupWorkflow>): WorkflowData<void> => {
(
input: WorkflowData<LinkCustomersToCustomerGroupWorkflow>
): WorkflowData<void> => {
return linkCustomersToCustomerGroupStep(input)
}
)
@@ -1,4 +1,4 @@
import { ICustomerModuleService } from "@medusajs/framework/types"
import type { ICustomerModuleService } from "@medusajs/framework/types"
import { Modules } from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
@@ -1,4 +1,4 @@
import { ICustomerModuleService } from "@medusajs/framework/types"
import type { ICustomerModuleService } from "@medusajs/framework/types"
import { Modules } from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
@@ -1,4 +1,4 @@
import { CreateCustomerDTO, CustomerDTO } from "@medusajs/framework/types"
import type { CreateCustomerDTO, CustomerDTO } from "@medusajs/framework/types"
import {
createWorkflow,
transform,
@@ -27,13 +27,13 @@ export const createCustomerAccountWorkflowId = "create-customer-account"
/**
* This workflow creates a customer and attaches it to an auth identity. It's used by the
* [Register Customer Store API Route](https://docs.medusajs.com/api/store#customers_postcustomers).
*
*
* You can create an auth identity first using the [Retrieve Registration JWT Token API Route](https://docs.medusajs.com/api/store#auth_postactor_typeauth_provider_register).
* Learn more about basic authentication flows in [this documentation](https://docs.medusajs.com/resources/commerce-modules/auth/authentication-route).
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to
* register or create customer accounts within your custom flows.
*
*
* @example
* const { result } = await createCustomerAccountWorkflow(container)
* .run({
@@ -46,9 +46,9 @@ export const createCustomerAccountWorkflowId = "create-customer-account"
* }
* }
* })
*
*
* @summary
*
*
* Create or register a customer account.
*/
export const createCustomerAccountWorkflow = createWorkflow(
@@ -1,4 +1,7 @@
import { AdditionalData, CreateCustomerDTO } from "@medusajs/framework/types"
import type {
AdditionalData,
CreateCustomerDTO,
} from "@medusajs/framework/types"
import { CustomerWorkflowEvents } from "@medusajs/framework/utils"
import {
WorkflowData,
@@ -23,11 +26,11 @@ export type CreateCustomersWorkflowInput = {
export const createCustomersWorkflowId = "create-customers"
/**
* This workflow creates one or more customers. It's used by the [Create Customer Admin API Route](https://docs.medusajs.com/api/admin#customers_postcustomers).
*
*
* This workflow has a hook that allows you to perform custom actions on the created customer. You can see an example in [this guide](https://docs.medusajs.com/resources/commerce-modules/customer/extend).
*
*
* You can also use this workflow within your customizations or your own custom workflows, allowing you to wrap custom logic around creating customers.
*
*
* @example
* const { result } = await createCustomersWorkflow(container)
* .run({
@@ -44,11 +47,11 @@ export const createCustomersWorkflowId = "create-customers"
* }
* }
* })
*
*
* @summary
*
*
* Create one or more customers.
*
*
* @property hooks.customersCreated - This hook is executed after the customers are created. You can consume this hook to perform custom actions on the created customers.
*/
export const createCustomersWorkflow = createWorkflow(
@@ -3,7 +3,7 @@ import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
import {
CreateLineItemAdjustmentDTO,
IOrderModuleService,
} from "@medusajs/types"
} from "@medusajs/framework/types"
export const createDraftOrderLineItemAdjustmentsStepId =
"create-draft-order-line-item-adjustments"
@@ -24,7 +24,7 @@ export interface CreateDraftOrderLineItemAdjustmentsStepInput {
/**
* This step creates line item adjustments for a draft order.
*
*
* @example
* const data = createDraftOrderLineItemAdjustmentsStep({
* order_id: "order_123",
@@ -3,7 +3,7 @@ import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
import {
CreateShippingMethodAdjustmentDTO,
IOrderModuleService,
} from "@medusajs/types"
} from "@medusajs/framework/types"
export const createDraftOrderShippingMethodAdjustmentsStepId =
"create-draft-order-shipping-method-adjustments"
@@ -20,7 +20,7 @@ export interface CreateDraftOrderShippingMethodAdjustmentsStepInput {
/**
* This step creates shipping method adjustments for a draft order.
*
*
* @example
* const data = createDraftOrderShippingMethodAdjustmentsStep({
* shippingMethodAdjustmentsToCreate: [
@@ -1,4 +1,4 @@
import { IOrderModuleService } from "@medusajs/framework/types"
import type { IOrderModuleService } from "@medusajs/framework/types"
import { createStep } from "@medusajs/framework/workflows-sdk"
import { Modules } from "@medusajs/framework/utils"
@@ -1,6 +1,6 @@
import { Modules } from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
import { IOrderModuleService, OrderDTO } from "@medusajs/types"
import type { IOrderModuleService, OrderDTO } from "@medusajs/framework/types"
/**
* The details of the draft order to get the promotion context for.
@@ -14,14 +14,14 @@ export interface GetDraftOrderPromotionContextStepInput {
/**
* This step gets the promotion context for a draft order.
*
*
* :::note
*
*
* You can retrieve a draft order's details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query),
* or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep).
*
*
* :::
*
*
* @example
* const data = getDraftOrderPromotionContextStep({
* order: {
@@ -1,6 +1,6 @@
import { Modules } from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
import { IOrderModuleService } from "@medusajs/types"
import type { IOrderModuleService } from "@medusajs/framework/types"
export const removeDraftOrderLineItemAdjustmentsStepId =
"remove-draft-order-line-item-adjustments"
@@ -16,7 +16,7 @@ export interface RemoveDraftOrderLineItemAdjustmentsStepInput {
/**
* This step removes line item adjustments from a draft order.
*
*
* @example
* const data = removeDraftOrderLineItemAdjustmentsStep({
* lineItemAdjustmentIdsToRemove: ["adj_123", "adj_456"],
@@ -1,6 +1,6 @@
import { Modules } from "@medusajs/framework/utils"
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
import { IOrderModuleService } from "@medusajs/types"
import type { IOrderModuleService } from "@medusajs/framework/types"
export const removeDraftOrderShippingMethodAdjustmentsStepId =
"remove-draft-order-shipping-method-adjustments"
@@ -17,7 +17,7 @@ export interface RemoveDraftOrderShippingMethodAdjustmentsStepInput {
/**
* This step removes shipping method adjustments from a draft order.
*
*
* @example
* const data = removeDraftOrderShippingMethodAdjustmentsStep({
* shippingMethodAdjustmentIdsToRemove: ["adj_123", "adj_456"],
@@ -1,6 +1,9 @@
import { Modules } from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
import { BigNumberInput, IOrderModuleService } from "@medusajs/types"
import type {
BigNumberInput,
IOrderModuleService,
} from "@medusajs/framework/types"
export const restoreDraftOrderShippingMethodsStepId =
"restore-draft-order-shipping-methods"
@@ -49,20 +52,20 @@ export interface RestoreDraftOrderShippingMethodsStepInput {
/**
* This step restores the shipping methods of a draft order.
* It's useful when you need to revert changes made by a canceled draft order edit.
*
*
* @example
* const data = restoreDraftOrderShippingMethodsStep({
* shippingMethods: [
* {
* id: "shipping_method_123",
* before: {
* shipping_option_id: "shipping_option_123",
* amount: 10
* },
* after: {
* shipping_option_id: "shipping_option_123",
* amount: 10
* }
* {
* id: "shipping_method_123",
* before: {
* shipping_option_id: "shipping_option_123",
* amount: 10
* },
* after: {
* shipping_option_id: "shipping_option_123",
* amount: 10
* }
* },
* ],
* })
@@ -4,7 +4,7 @@ import {
PromotionActions,
} from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
import { IPromotionModuleService } from "@medusajs/types"
import type { IPromotionModuleService } from "@medusajs/framework/types"
export const updateDraftOrderPromotionsStepId = "update-draft-order-promotions"
@@ -22,7 +22,7 @@ export interface UpdateDraftOrderPromotionsStepInput {
promo_codes: string[]
/**
* The action to perform on the promotions. You can either:
*
*
* - Add the promotions to the draft order.
* - Replace the existing promotions with the new ones.
* - Remove the promotions from the draft order.
@@ -32,7 +32,7 @@ export interface UpdateDraftOrderPromotionsStepInput {
/**
* This step updates the promotions of a draft order.
*
*
* @example
* const data = updateDraftOrderPromotionsStep({
* id: "order_123",
@@ -1,6 +1,9 @@
import { MedusaError, Modules } from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
import { BigNumberInput, IOrderModuleService } from "@medusajs/types"
import type {
BigNumberInput,
IOrderModuleService,
} from "@medusajs/framework/types"
export const updateDraftOrderShippingMethodStepId =
"update-draft-order-shipping-method"
@@ -33,7 +36,7 @@ export interface UpdateDraftOrderShippingMethodStepInput {
/**
* This step updates the shipping method of a draft order.
*
*
* @example
* const data = updateDraftOrderShippingMethodStep({
* order_id: "order_123",
@@ -1,5 +1,5 @@
import { createStep } from "@medusajs/framework/workflows-sdk"
import { OrderChangeDTO, OrderDTO } from "@medusajs/types"
import type { OrderChangeDTO, OrderDTO } from "@medusajs/framework/types"
import { throwIfOrderChangeIsNotActive } from "../../order/utils/order-validation"
import { throwIfNotDraftOrder } from "../utils/validation"
@@ -22,14 +22,14 @@ export const validateDraftOrderChangeStepId = "validate-draft-order-change"
/**
* This step validates that a draft order and its change are valid. It throws an error if the
* order is not a draft order or the order change is not active.
*
*
* :::note
*
*
* You can retrieve a draft order and its change's details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query),
* or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep).
*
*
* :::
*
*
* @example
* const data = validateDraftOrderChangeStep({
* order: {
@@ -1,8 +1,8 @@
import { OrderChangeActionDTO } from "@medusajs/types"
import type { OrderChangeActionDTO } from "@medusajs/framework/types"
import { ChangeActionType, MedusaError } from "@medusajs/framework/utils"
import { createStep } from "@medusajs/framework/workflows-sdk"
import { OrderChangeDTO, OrderWorkflow } from "@medusajs/types"
import type { OrderChangeDTO, OrderWorkflow } from "@medusajs/framework/types"
/**
* The details of the draft order and its change to validate.
@@ -21,14 +21,14 @@ export interface ValidateDraftOrderUpdateActionItemStepInput {
/**
* This step validates that an item change can be removed from a draft order edit. It throws an error if the
* item change is not in the draft order edit, or if the item change is not adding or updating an item.
*
*
* :::note
*
*
* You can retrieve a draft order change's details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query),
* or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep).
*
*
* :::
*
*
* @example
* const data = validateDraftOrderRemoveActionItemStep({
* input: {
@@ -4,7 +4,7 @@ import {
OrderChangeActionDTO,
OrderChangeDTO,
OrderWorkflow,
} from "@medusajs/types"
} from "@medusajs/framework/types"
/**
* The details of the draft order and its change to validate.
@@ -23,14 +23,14 @@ export interface ValidateDraftOrderShippingMethodActionStepInput {
/**
* This step validates that a shipping method change can be removed from a draft order edit. It throws an error if the
* shipping method change is not in the draft order edit, or if the shipping method change is not adding a shipping method.
*
*
* :::note
*
*
* You can retrieve a draft order change's details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query),
* or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep).
*
*
* :::
*
*
* @example
* const data = validateDraftOrderShippingMethodActionStep({
* input: {
@@ -1,8 +1,8 @@
import { OrderChangeActionDTO } from "@medusajs/types"
import type { OrderChangeActionDTO } from "@medusajs/framework/types"
import { ChangeActionType, MedusaError } from "@medusajs/framework/utils"
import { createStep } from "@medusajs/framework/workflows-sdk"
import { OrderChangeDTO, OrderWorkflow } from "@medusajs/types"
import type { OrderChangeDTO, OrderWorkflow } from "@medusajs/framework/types"
/**
* The details of the draft order and its change to validate.
@@ -21,14 +21,14 @@ export interface ValidateDraftOrderUpdateActionItemStepInput {
/**
* This step validates that a new item can be updated in a draft order edit. It throws an error if the
* item change is not in the draft order edit, or if the item change is not adding an item.
*
*
* :::note
*
*
* You can retrieve a draft order change's details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query),
* or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep).
*
*
* :::
*
*
* @example
* const data = validateDraftOrderUpdateActionItemStep({
* input: {
@@ -1,6 +1,6 @@
import { MedusaError, OrderStatus } from "@medusajs/framework/utils"
import { createStep } from "@medusajs/framework/workflows-sdk"
import { OrderDTO } from "@medusajs/types"
import type { OrderDTO } from "@medusajs/framework/types"
/**
* The details of the draft order to validate.
@@ -14,14 +14,14 @@ export interface ValidateDraftOrderStepInput {
/**
* This step validates that an order is a draft order. It throws an error otherwise.
*
*
* :::note
*
*
* You can retrieve a draft order's details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query),
* or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep).
*
*
* :::
*
*
* @example
* const data = validateDraftOrderStep({
* order: {
@@ -1,5 +1,5 @@
import { createStep } from "@medusajs/framework/workflows-sdk"
import { PromotionDTO } from "@medusajs/types"
import type { PromotionDTO } from "@medusajs/framework/types"
import {
throwIfCodesAreInactive,
throwIfCodesAreMissing,
@@ -24,23 +24,23 @@ export interface ValidatePromoCodesToAddStepInput {
/**
* This step validates that the promo codes to add to a draft order are valid. It throws an error if the
* promo codes don't exist or are inactive.
*
*
* :::note
*
*
* You can retrieve a promotion's details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query),
* or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep).
*
*
* :::
*
*
* @example
* const data = validatePromoCodesToAddStep({
* promo_codes: ["PROMO_123", "PROMO_456"],
* promotions: [{
* id: "promo_123",
* code: "PROMO_123"
* }, {
* id: "promo_456",
* code: "PROMO_456"
* promotions: [{
* id: "promo_123",
* code: "PROMO_123"
* }, {
* id: "promo_456",
* code: "PROMO_456"
* }],
* })
*/
@@ -1,5 +1,5 @@
import { createStep } from "@medusajs/framework/workflows-sdk"
import { PromotionDTO } from "@medusajs/types"
import type { PromotionDTO } from "@medusajs/framework/types"
import { throwIfCodesAreMissing } from "../utils/validation"
export const validatePromoCodesToRemoveId = "validate-promo-codes-to-remove"
@@ -21,23 +21,23 @@ export interface ValidatePromoCodesToRemoveStepInput {
/**
* This step validates that the promo codes can be removed from a draft order. It throws an error if the promo
* codes don't exist.
*
*
* :::note
*
*
* You can retrieve a promotion's details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query),
* or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep).
*
*
* :::
*
*
* @example
* const data = validatePromoCodesToRemoveStep({
* promo_codes: ["PROMO_123", "PROMO_456"],
* promotions: [{
* id: "promo_123",
* code: "PROMO_123"
* }, {
* id: "promo_456",
* code: "PROMO_456"
* promotions: [{
* id: "promo_123",
* code: "PROMO_123"
* }, {
* id: "promo_456",
* code: "PROMO_456"
* }],
* })
*/
@@ -3,7 +3,7 @@ import {
OrderStatus,
PromotionStatus,
} from "@medusajs/framework/utils"
import { OrderDTO, PromotionDTO } from "@medusajs/types"
import type { OrderDTO, PromotionDTO } from "@medusajs/framework/types"
interface ThrowIfNotDraftOrderInput {
order: OrderDTO
@@ -10,7 +10,11 @@ import {
WorkflowData,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import { OrderChangeDTO, OrderDTO, OrderWorkflow } from "@medusajs/types"
import {
OrderChangeDTO,
OrderDTO,
OrderWorkflow,
} from "@medusajs/framework/types"
import { useRemoteQueryStep } from "../../common"
import {
addOrderLineItemsWorkflow,
@@ -9,7 +9,11 @@ import {
WorkflowData,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import { OrderChangeDTO, OrderDTO, PromotionDTO } from "@medusajs/types"
import {
OrderChangeDTO,
OrderDTO,
PromotionDTO,
} from "@medusajs/framework/types"
import { useRemoteQueryStep } from "../../common"
import {
createOrderChangeActionsWorkflow,
@@ -39,10 +43,10 @@ export interface AddDraftOrderPromotionWorkflowInput {
/**
* This workflow adds promotions to a draft order. It's used by the
* [Add Promotion to Draft Order Admin API Route](https://docs.medusajs.com/api/admin#draft-orders_postdraftordersideditpromotions).
*
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to wrap custom logic around adding promotions to
* a draft order.
*
*
* @example
* const { result } = await addDraftOrderPromotionWorkflow(container)
* .run({
@@ -51,9 +55,9 @@ export interface AddDraftOrderPromotionWorkflowInput {
* promo_codes: ["PROMO_CODE_1", "PROMO_CODE_2"]
* }
* })
*
*
* @summary
*
*
* Add promotions to a draft order.
*/
export const addDraftOrderPromotionWorkflow = createWorkflow(
@@ -19,7 +19,7 @@ import {
OrderChangeDTO,
OrderDTO,
ShippingOptionDTO,
} from "@medusajs/types"
} from "@medusajs/framework/types"
import { useRemoteQueryStep } from "../../common"
import {
createOrderChangeActionsWorkflow,
@@ -4,7 +4,7 @@ import {
WorkflowData,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import { OrderDTO, OrderWorkflow } from "@medusajs/types"
import type { OrderDTO, OrderWorkflow } from "@medusajs/framework/types"
import { useRemoteQueryStep } from "../../common"
import { createOrderChangeStep, previewOrderChangeStep } from "../../order"
import { validateDraftOrderStep } from "../steps"
@@ -14,12 +14,12 @@ export const beginDraftOrderEditWorkflowId = "begin-draft-order-edit"
/**
* This workflow begins a draft order edit. It's used by the
* [Create Draft Order Edit Admin API Route](https://docs.medusajs.com/api/admin#draft-orders_postdraftordersidedit).
*
*
* The draft order edit can later be requested using {@link requestDraftOrderEditWorkflow} or confirmed using {@link confirmDraftOrderEditWorkflow}.
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to wrap custom logic around
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to wrap custom logic around
* creating a draft order edit request.
*
*
* @example
* const { result } = await beginDraftOrderEditWorkflow(container)
* .run({
@@ -27,9 +27,9 @@ export const beginDraftOrderEditWorkflowId = "begin-draft-order-edit"
* order_id: "order_123",
* }
* })
*
*
* @summary
*
*
* Create a draft order edit request.
*/
export const beginDraftOrderEditWorkflow = createWorkflow(
@@ -10,7 +10,7 @@ import {
when,
WorkflowData,
} from "@medusajs/framework/workflows-sdk"
import { OrderChangeDTO, OrderDTO } from "@medusajs/types"
import type { OrderChangeDTO, OrderDTO } from "@medusajs/framework/types"
import { useRemoteQueryStep } from "../../common"
import { deleteOrderChangesStep, deleteOrderShippingMethods } from "../../order"
import { restoreDraftOrderShippingMethodsStep } from "../steps/restore-draft-order-shipping-methods"
@@ -8,7 +8,11 @@ import {
transform,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import { BigNumberInput, OrderChangeDTO, OrderDTO } from "@medusajs/types"
import {
BigNumberInput,
OrderChangeDTO,
OrderDTO,
} from "@medusajs/framework/types"
import { reserveInventoryStep } from "../../cart"
import {
prepareConfirmInventoryInput,
@@ -10,7 +10,7 @@ import {
WorkflowData,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import { IOrderModuleService, OrderDTO } from "@medusajs/types"
import type { IOrderModuleService, OrderDTO } from "@medusajs/framework/types"
import { emitEventStep, useRemoteQueryStep } from "../../common"
import { validateDraftOrderStep } from "../steps/validate-draft-order"
@@ -78,10 +78,10 @@ export const convertDraftOrderStep = createStep(
/**
* This workflow converts a draft order to a pending order. It's used by the
* [Convert Draft Order to Order Admin API Route](https://docs.medusajs.com/api/admin#draft-orders_postdraftordersidconverttoorder).
*
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to wrap custom logic around
* converting a draft order to a pending order.
*
*
* @example
* const { result } = await convertDraftOrderWorkflow(container)
* .run({
@@ -89,9 +89,9 @@ export const convertDraftOrderStep = createStep(
* id: "order_123",
* }
* })
*
*
* @summary
*
*
* Convert a draft order to a pending order.
*/
export const convertDraftOrderWorkflow = createWorkflow(
@@ -5,7 +5,7 @@ import {
createWorkflow,
transform,
} from "@medusajs/framework/workflows-sdk"
import { OrderDTO } from "@medusajs/framework/types"
import type { OrderDTO } from "@medusajs/framework/types"
import { Modules } from "@medusajs/framework/utils"
import { removeRemoteLinkStep, useQueryGraphStep } from "../../common"
@@ -5,7 +5,7 @@ import {
WorkflowData,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import { OrderDTO } from "@medusajs/types"
import type { OrderDTO } from "@medusajs/framework/types"
import {
getActionsToComputeFromPromotionsStep,
getPromotionCodesToApply,
@@ -11,7 +11,7 @@ import {
OrderDTO,
OrderPreviewDTO,
OrderWorkflow,
} from "@medusajs/types"
} from "@medusajs/framework/types"
import { useRemoteQueryStep } from "../../common"
import {
deleteOrderChangeActionsStep,
@@ -13,7 +13,7 @@ import {
OrderDTO,
OrderPreviewDTO,
OrderWorkflow,
} from "@medusajs/types"
} from "@medusajs/framework/types"
import { useRemoteQueryStep } from "../../common"
import {
deleteOrderChangeActionsStep,
@@ -9,7 +9,11 @@ import {
WorkflowData,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import { OrderChangeDTO, OrderDTO, PromotionDTO } from "@medusajs/types"
import {
OrderChangeDTO,
OrderDTO,
PromotionDTO,
} from "@medusajs/framework/types"
import { useRemoteQueryStep } from "../../common"
import {
createOrderChangeActionsWorkflow,
@@ -40,10 +44,10 @@ export interface RemoveDraftOrderPromotionsWorkflowInput {
/**
* This workflow removes promotions from a draft order edit. It's used by the
* [Remove Promotions from Draft Order Edit Admin API Route](https://docs.medusajs.com/api/admin#draft-orders_deletedraftordersideditpromotions).
*
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to wrap custom logic around
* removing promotions from a draft order edit.
*
*
* @example
* const { result } = await removeDraftOrderPromotionsWorkflow(container)
* .run({
@@ -52,9 +56,9 @@ export interface RemoveDraftOrderPromotionsWorkflowInput {
* promo_codes: ["PROMO_CODE_1", "PROMO_CODE_2"],
* }
* })
*
*
* @summary
*
*
* Remove promotions from a draft order edit.
*/
export const removeDraftOrderPromotionsWorkflow = createWorkflow(
@@ -10,7 +10,7 @@ import {
WorkflowData,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import { OrderChangeDTO, OrderDTO } from "@medusajs/types"
import type { OrderChangeDTO, OrderDTO } from "@medusajs/framework/types"
import { useRemoteQueryStep } from "../../common"
import {
createOrderChangeActionsWorkflow,
@@ -4,7 +4,7 @@ import {
transform,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import { OrderChangeDTO, OrderDTO } from "@medusajs/types"
import type { OrderChangeDTO, OrderDTO } from "@medusajs/framework/types"
import { useRemoteQueryStep } from "../../common"
import {
createOrUpdateOrderPaymentCollectionWorkflow,
@@ -51,10 +51,10 @@ export type RequestDraftOrderEditWorkflowInput = {
/**
* This workflow requests a draft order edit. It's used by the
* [Request Draft Order Edit Admin API Route](https://docs.medusajs.com/api/admin#draft-orders_postdraftordersideditrequest).
*
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to wrap custom logic around
* requesting a draft order edit.
*
*
* @example
* const { result } = await requestDraftOrderEditWorkflow(container)
* .run({
@@ -63,9 +63,9 @@ export type RequestDraftOrderEditWorkflowInput = {
* requested_by: "user_123",
* }
* })
*
*
* @summary
*
*
* Request a draft order edit.
*/
export const requestDraftOrderEditWorkflow = createWorkflow(
@@ -11,7 +11,7 @@ import {
OrderChangeDTO,
OrderDTO,
OrderWorkflow,
} from "@medusajs/types"
} from "@medusajs/framework/types"
import { useRemoteQueryStep } from "../../common"
import {
previewOrderChangeStep,
@@ -13,7 +13,7 @@ import {
OrderDTO,
OrderPreviewDTO,
OrderWorkflow,
} from "@medusajs/types"
} from "@medusajs/framework/types"
import { useRemoteQueryStep } from "../../common"
import {
previewOrderChangeStep,
@@ -17,7 +17,7 @@ import {
OrderDTO,
OrderPreviewDTO,
OrderWorkflow,
} from "@medusajs/types"
} from "@medusajs/framework/types"
import { useRemoteQueryStep } from "../../common"
import {
createOrderChangeActionsWorkflow,
@@ -10,7 +10,11 @@ import {
WorkflowData,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import { BigNumberInput, OrderChangeDTO, OrderDTO } from "@medusajs/types"
import {
BigNumberInput,
OrderChangeDTO,
OrderDTO,
} from "@medusajs/framework/types"
import { useRemoteQueryStep } from "../../common"
import {
createOrderChangeActionsWorkflow,
@@ -13,7 +13,7 @@ import {
RegisterOrderChangeDTO,
UpdateOrderDTO,
UpsertOrderAddressDTO,
} from "@medusajs/types"
} from "@medusajs/framework/types"
import { emitEventStep, useRemoteQueryStep } from "../../common"
import { previewOrderChangeStep, registerOrderChangesStep } from "../../order"
import { validateDraftOrderStep } from "../steps/validate-draft-order"
@@ -74,14 +74,14 @@ export interface UpdateDraftOrderStepInput {
/**
* This step updates a draft order's details.
*
*
* :::note
*
*
* You can retrieve a draft order's details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query),
* or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep).
*
*
* :::
*
*
* @example
* const data = updateDraftOrderStep({
* order: {
@@ -123,15 +123,15 @@ export const updateDraftOrderStep = createStep(
/**
* This workflow updates a draft order's details. It's used by the
* [Update Draft Order Admin API Route](https://docs.medusajs.com/api/admin#draft-orders_postdraftordersid).
*
* This workflow doesn't update the draft order's items, shipping methods, or promotions. Instead, you have to
*
* This workflow doesn't update the draft order's items, shipping methods, or promotions. Instead, you have to
* create a draft order edit using {@link beginDraftOrderEditWorkflow} and make updates in the draft order edit.
* Then, you can confirm the draft order edit using {@link confirmDraftOrderEditWorkflow} or request a draft order edit
* using {@link requestDraftOrderEditWorkflow}.
*
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to wrap custom logic around
* updating a draft order.
*
*
* @example
* const { result } = await updateDraftOrderWorkflow(container)
* .run({
@@ -141,9 +141,9 @@ export const updateDraftOrderStep = createStep(
* customer_id: "cus_123",
* }
* })
*
*
* @summary
*
*
* Update a draft order's details.
*/
export const updateDraftOrderWorkflow = createWorkflow(
@@ -1,4 +1,4 @@
import { IFileModuleService } from "@medusajs/framework/types"
import type { IFileModuleService } from "@medusajs/framework/types"
import { Modules } from "@medusajs/framework/utils"
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
@@ -12,7 +12,7 @@ export const deleteFilesStepId = "delete-files"
* This step deletes one or more files using the installed
* [File Module Provider](https://docs.medusajs.com/resources/infrastructure-modules/file). The files
* will be removed from the database and the storage.
*
*
* @example
* const data = deleteFilesStep([
* "id_123"
@@ -1,4 +1,4 @@
import { IFileModuleService } from "@medusajs/framework/types"
import type { IFileModuleService } from "@medusajs/framework/types"
import { Modules } from "@medusajs/framework/utils"
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
@@ -16,13 +16,13 @@ export type UploadFilesStepInput = {
filename: string
/**
* The MIME type of the file.
*
*
* @example
* img/jpg
*/
mimeType: string
/**
* The content of the file. For images, for example,
* The content of the file. For images, for example,
* use binary string. For CSV files, use the CSV content.
*/
content: string
@@ -41,7 +41,7 @@ export const uploadFilesStepId = "upload-files"
/**
* This step uploads one or more files using the installed
* [File Module Provider](https://docs.medusajs.com/resources/infrastructure-modules/file).
*
*
* @example
* const data = uploadFilesStep({
* files: [
@@ -1,4 +1,4 @@
import { FileDTO } from "@medusajs/framework/types"
import type { FileDTO } from "@medusajs/framework/types"
import {
WorkflowData,
WorkflowResponse,
@@ -20,13 +20,13 @@ export type UploadFilesWorkflowInput = {
filename: string
/**
* The MIME type of the file.
*
*
* @example
* img/jpg
*/
mimeType: string
/**
* The content of the file. For images, for example,
* The content of the file. For images, for example,
* use binary string. For CSV files, use the CSV content.
*/
content: string
@@ -34,7 +34,7 @@ export type UploadFilesWorkflowInput = {
* The access level of the file. Use `public` for the file that
* can be accessed by anyone. For example, for images that are displayed
* on the storefront. Use `private` for files that are only accessible
* by authenticated users. For example, for CSV files used to
* by authenticated users. For example, for CSV files used to
* import data.
*/
access: "public" | "private"
@@ -43,13 +43,13 @@ export type UploadFilesWorkflowInput = {
export const uploadFilesWorkflowId = "upload-files"
/**
* This workflow uploads one or more files using the installed
* This workflow uploads one or more files using the installed
* [File Module Provider](https://docs.medusajs.com/resources/infrastructure-modules/file). The workflow is used by the
* [Upload Files Admin API Route](https://docs.medusajs.com/api/admin#uploads_postuploads).
*
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to
* upload files within your custom flows.
*
*
* @example
* const { result } = await uploadFilesWorkflow(container)
* .run({
@@ -64,9 +64,9 @@ export const uploadFilesWorkflowId = "upload-files"
* ]
* }
* })
*
*
* @summary
*
*
* Upload files using the installed File Module Provider.
*/
export const uploadFilesWorkflow = createWorkflow(
@@ -1,4 +1,4 @@
import { IFulfillmentModuleService } from "@medusajs/framework/types"
import type { IFulfillmentModuleService } from "@medusajs/framework/types"
import { Modules } from "@medusajs/framework/utils"
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
@@ -1,4 +1,4 @@
import { IFulfillmentModuleService } from "@medusajs/framework/types"
import type { IFulfillmentModuleService } from "@medusajs/framework/types"
import { Modules } from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
@@ -1,4 +1,4 @@
import { IFulfillmentModuleService } from "@medusajs/framework/types"
import type { IFulfillmentModuleService } from "@medusajs/framework/types"
import { Modules } from "@medusajs/framework/utils"
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
@@ -1,5 +1,5 @@
import { DeleteEntityInput } from "@medusajs/framework/modules-sdk"
import { IFulfillmentModuleService } from "@medusajs/framework/types"
import type { IFulfillmentModuleService } from "@medusajs/framework/types"
import { Modules } from "@medusajs/framework/utils"
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
@@ -1,5 +1,5 @@
import { Link } from "@medusajs/framework/modules-sdk"
import { RemoteQueryFunction } from "@medusajs/framework/types"
import type { RemoteQueryFunction } from "@medusajs/framework/types"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
import {
ContainerRegistrationKeys,
@@ -1,4 +1,7 @@
import { ServiceZoneDTO, ShippingOptionDTO } from "@medusajs/framework/types"
import type {
ServiceZoneDTO,
ShippingOptionDTO,
} from "@medusajs/framework/types"
import {
ContainerRegistrationKeys,
MedusaError,
@@ -1,4 +1,4 @@
import { IFulfillmentModuleService } from "@medusajs/framework/types"
import type { IFulfillmentModuleService } from "@medusajs/framework/types"
import { MedusaError, Modules } from "@medusajs/framework/utils"
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
@@ -1,7 +1,11 @@
import { FulfillmentWorkflow } from "@medusajs/framework/types"
import { MedusaError, Modules, ShippingOptionPriceType, } from "@medusajs/framework/utils"
import type { FulfillmentWorkflow } from "@medusajs/framework/types"
import {
MedusaError,
Modules,
ShippingOptionPriceType,
} from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
import { CreateShippingOptionDTO } from "@medusajs/types"
import type { CreateShippingOptionDTO } from "@medusajs/framework/types"
/**
* The data to validate shipping option prices.
@@ -1,4 +1,4 @@
import { FulfillmentWorkflow } from "@medusajs/framework/types"
import type { FulfillmentWorkflow } from "@medusajs/framework/types"
import {
createWorkflow,
transform,
@@ -14,17 +14,17 @@ export const calculateShippingOptionsPricesWorkflowId =
/**
* This workflow calculates the prices for one or more shipping options in a cart. It's used by the
* [Calculate Shipping Option Price Store API Route](https://docs.medusajs.com/api/store#shipping-options_postshippingoptionsidcalculate).
*
*
* :::note
*
*
* Calculating shipping option prices may require sending requests to third-party fulfillment services.
* This depends on the implementation of the fulfillment provider associated with the shipping option.
*
*
* :::
*
*
* You can use this workflow within your own customizations or custom workflows, allowing you to
* calculate the prices of shipping options within your custom flows.
*
*
* @example
* const { result } = await calculateShippingOptionsPricesWorkflow(container)
* .run({
@@ -41,9 +41,9 @@ export const calculateShippingOptionsPricesWorkflowId =
* ]
* }
* })
*
*
* @summary
*
*
* Calculate shipping option prices in a cart.
*/
export const calculateShippingOptionsPricesWorkflow = createWorkflow(
@@ -1,4 +1,7 @@
import { FulfillmentWorkflow, ServiceZoneDTO } from "@medusajs/framework/types"
import type {
FulfillmentWorkflow,
ServiceZoneDTO,
} from "@medusajs/framework/types"
import {
WorkflowData,
WorkflowResponse,
@@ -15,10 +18,10 @@ export const createServiceZonesWorkflowId = "create-service-zones-workflow"
/**
* This workflow creates one or more service zones. It's used by the
* [Add Service Zone to Fulfillment Set Admin API Route](https://docs.medusajs.com/api/admin#fulfillment-sets_postfulfillmentsetsidservicezones).
*
*
* You can use this workflow within your own customizations or custom workflows, allowing you to
* create service zones within your custom flows.
*
*
* @example
* const { result } = await createServiceZonesWorkflow(container)
* .run({
@@ -37,9 +40,9 @@ export const createServiceZonesWorkflowId = "create-service-zones-workflow"
* ]
* }
* })
*
*
* @summary
*
*
* Create one or more service zones.
*/
export const createServiceZonesWorkflow = createWorkflow(
@@ -1,4 +1,4 @@
import { FulfillmentWorkflow } from "@medusajs/framework/types"
import type { FulfillmentWorkflow } from "@medusajs/framework/types"
import {
WorkflowData,
WorkflowResponse,
@@ -12,10 +12,10 @@ export const createShipmentWorkflowId = "create-shipment-workflow"
/**
* This workflow creates shipments for a fulfillment. It's used by the
* [Create Shipment Admin API Route](https://docs.medusajs.com/api/admin#fulfillments_postfulfillmentsidshipment).
*
*
* You can use this workflow within your own customizations or custom workflows, allowing you to
* create shipments within your custom flows.
*
*
* @example
* const { result } = await createShipmentWorkflow(container)
* .run({
@@ -30,9 +30,9 @@ export const createShipmentWorkflowId = "create-shipment-workflow"
* ]
* }
* })
*
*
* @summary
*
*
* Create a shipment for a fulfillment.
*/
export const createShipmentWorkflow = createWorkflow(
@@ -1,4 +1,4 @@
import { FulfillmentWorkflow } from "@medusajs/framework/types"
import type { FulfillmentWorkflow } from "@medusajs/framework/types"
import {
createWorkflow,
parallelize,
@@ -6,7 +6,10 @@ import {
WorkflowData,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import { createShippingOptionsPriceSetsStep, upsertShippingOptionsStep, } from "../steps"
import {
createShippingOptionsPriceSetsStep,
upsertShippingOptionsStep,
} from "../steps"
import { setShippingOptionsPriceSetsStep } from "../steps/set-shipping-options-price-sets"
import { validateFulfillmentProvidersStep } from "../steps/validate-fulfillment-providers"
import { validateShippingOptionPricesStep } from "../steps/validate-shipping-option-prices"
@@ -14,27 +17,28 @@ import { validateShippingOptionPricesStep } from "../steps/validate-shipping-opt
/**
* The data to create the shipping options.
*/
export type CreateShippingOptionsWorkflowInput = FulfillmentWorkflow.CreateShippingOptionsWorkflowInput[]
export type CreateShippingOptionsWorkflowInput =
FulfillmentWorkflow.CreateShippingOptionsWorkflowInput[]
export const createShippingOptionsWorkflowId =
"create-shipping-options-workflow"
/**
* This workflow creates one or more shipping options. It's used by the
* This workflow creates one or more shipping options. It's used by the
* [Create Shipping Option Admin API Route](https://docs.medusajs.com/api/admin#shipping-options_postshippingoptions).
*
*
* You can use this workflow within your own customizations or custom workflows, allowing you to
* create shipping options within your custom flows.
*
*
* @example
* To calculate a shipping option with flat rate prices:
*
*
* :::note
*
* Learn more about adding rules to the shipping option's prices in the Pricing Module's
*
* Learn more about adding rules to the shipping option's prices in the Pricing Module's
* [Price Rules](https://docs.medusajs.com/resources/commerce-modules/pricing/price-rules) documentation.
*
*
* :::
*
*
* ```ts
* const { result } = await createShippingOptionsWorkflow(container)
* .run({
@@ -60,15 +64,15 @@ export const createShippingOptionsWorkflowId =
* ]
* })
* ```
*
*
* To calculate shipping option with calculated prices, set `price_type` to `calculated` and don't pass a `prices` array:
*
*
* :::note
*
*
* You can calculate the shipping option's price for a cart using the [calculateShippingOptionsPricesWorkflow](https://docs.medusajs.com/resources/references/medusa-workflows/calculateShippingOptionsPricesWorkflow).
*
*
* :::
*
*
* ```ts
* const { result } = await createShippingOptionsWorkflow(container)
* .run({
@@ -88,9 +92,9 @@ export const createShippingOptionsWorkflowId =
* ]
* })
* ```
*
*
* @summary
*
*
* Create shipping options.
*/
export const createShippingOptionsWorkflow = createWorkflow(

Some files were not shown because too many files have changed in this diff Show More