feat(medusa,types,workflows,utils,product): PricingModule Integration of PriceLists into Core (#5536)

This commit is contained in:
Philip Korsholm authored and GitHub committed 2023-11-21 17:42:37 +00:00
1 parent 9c7ac7332a
commit dc5750dd66
94 files changed
+5697 -880

No files matched your search

@@ -1,3 +1,4 @@
export * from "./cart"
export * from "./product"
export * from "./inventory"
export * from './price-list'
@@ -0,0 +1,74 @@
import {
TransactionStepsDefinition,
WorkflowManager,
} from "@medusajs/orchestration"
import { PricingTypes, WorkflowTypes } from "@medusajs/types"
import { exportWorkflow, pipe } from "../../helper"
import { Workflows } from "../../definitions"
import { PriceListHandlers } from "../../handlers"
export enum CreatePriceListActions {
prepare = "prepare",
createPriceList = "createPriceList",
}
const workflowSteps: TransactionStepsDefinition = {
next: {
action: CreatePriceListActions.prepare,
noCompensation: true,
next: {
action: CreatePriceListActions.createPriceList,
},
},
}
const handlers = new Map([
[
CreatePriceListActions.prepare,
{
invoke: pipe(
{
inputAlias: CreatePriceListActions.prepare,
merge: true,
invoke: {
from: CreatePriceListActions.prepare,
},
},
PriceListHandlers.prepareCreatePriceLists
),
},
],
[
CreatePriceListActions.createPriceList,
{
invoke: pipe(
{
invoke: {
from: CreatePriceListActions.prepare,
alias: PriceListHandlers.createPriceLists.aliases.priceLists,
},
},
PriceListHandlers.createPriceLists
),
compensate: pipe(
{
invoke: {
from: CreatePriceListActions.createPriceList,
alias: PriceListHandlers.removePriceLists.aliases.priceLists,
},
},
PriceListHandlers.removePriceLists
),
},
],
])
WorkflowManager.register(Workflows.CreatePriceList, workflowSteps, handlers)
export const createPriceLists = exportWorkflow<
WorkflowTypes.PriceListWorkflow.CreatePriceListWorkflowInputDTO,
{
priceList: PricingTypes.CreatePriceListDTO
}[]
>(Workflows.CreatePriceList, CreatePriceListActions.createPriceList)
@@ -0,0 +1,5 @@
export * from "./create-price-lists"
export * from "./remove-price-lists"
export * from "./remove-product-prices"
export * from "./remove-variant-prices"
export * from "./update-price-lists"
@@ -0,0 +1,71 @@
import {
TransactionStepsDefinition,
WorkflowManager,
} from "@medusajs/orchestration"
import { WorkflowTypes } from "@medusajs/types"
import { exportWorkflow, pipe } from "../../helper"
import { Workflows } from "../../definitions"
import { PriceListHandlers } from "../../handlers"
export enum RemovePriceListPricesActions {
prepare = "prepare",
removePriceListPrices = "removePriceListPrices",
}
const workflowSteps: TransactionStepsDefinition = {
next: {
action: RemovePriceListPricesActions.prepare,
noCompensation: true,
next: {
action: RemovePriceListPricesActions.removePriceListPrices,
noCompensation: true,
},
},
}
const handlers = new Map([
[
RemovePriceListPricesActions.prepare,
{
invoke: pipe(
{
inputAlias: RemovePriceListPricesActions.prepare,
merge: true,
invoke: {
from: RemovePriceListPricesActions.prepare,
},
},
PriceListHandlers.prepareRemovePriceListPrices
),
},
],
[
RemovePriceListPricesActions.removePriceListPrices,
{
invoke: pipe(
{
merge: true,
invoke: {
from: RemovePriceListPricesActions.prepare,
},
},
PriceListHandlers.removePrices
),
},
],
])
WorkflowManager.register(
Workflows.RemovePriceListPrices,
workflowSteps,
handlers
)
export const removePriceListProductPrices = exportWorkflow<
WorkflowTypes.PriceListWorkflow.RemovePriceListPricesWorkflowInputDTO,
string[]
>(
Workflows.RemovePriceListPrices,
RemovePriceListPricesActions.removePriceListPrices
)
@@ -0,0 +1,57 @@
import { WorkflowTypes } from "@medusajs/types"
import {
TransactionStepsDefinition,
WorkflowManager,
} from "@medusajs/orchestration"
import { exportWorkflow, pipe } from "../../helper"
import { PriceListHandlers } from "../../handlers"
import { Workflows } from "../../definitions"
export enum RemovePriceListActions {
removePriceList = "removePriceList",
}
const workflowSteps: TransactionStepsDefinition = {
next: {
action: RemovePriceListActions.removePriceList,
noCompensation: true,
},
}
const handlers = new Map([
[
RemovePriceListActions.removePriceList,
{
invoke: pipe(
{
inputAlias: RemovePriceListActions.removePriceList,
merge: true,
invoke: {
from: RemovePriceListActions.removePriceList,
},
},
PriceListHandlers.removePriceLists
),
},
],
])
WorkflowManager.register(Workflows.DeletePriceLists, workflowSteps, handlers)
export const removePriceLists = exportWorkflow<
WorkflowTypes.PriceListWorkflow.RemovePriceListWorkflowInputDTO,
{
price_list_ids: string[]
}
>(
Workflows.DeletePriceLists,
RemovePriceListActions.removePriceList,
async (data) => {
return {
price_lists: data.price_lists.map((priceListId) => ({
price_list: { id: priceListId },
})),
}
}
)
@@ -0,0 +1,72 @@
import {
TransactionStepsDefinition,
WorkflowManager,
} from "@medusajs/orchestration"
import { WorkflowTypes } from "@medusajs/types"
import { exportWorkflow, pipe } from "../../helper"
import { Workflows } from "../../definitions"
import { PriceListHandlers } from "../../handlers"
export enum RemoveProductPricesActions {
prepare = "prepare",
removePriceListPriceSetPrices = "removePriceListPriceSetPrices",
}
const workflowSteps: TransactionStepsDefinition = {
next: {
action: RemoveProductPricesActions.prepare,
noCompensation: true,
next: {
action: RemoveProductPricesActions.removePriceListPriceSetPrices,
noCompensation: true,
},
},
}
const handlers = new Map([
[
RemoveProductPricesActions.prepare,
{
invoke: pipe(
{
inputAlias: RemoveProductPricesActions.prepare,
merge: true,
invoke: {
from: RemoveProductPricesActions.prepare,
},
},
PriceListHandlers.prepareRemoveProductPrices
),
},
],
[
RemoveProductPricesActions.removePriceListPriceSetPrices,
{
invoke: pipe(
{
merge: true,
invoke: {
from: RemoveProductPricesActions.prepare,
alias: PriceListHandlers.createPriceLists.aliases.priceLists,
},
},
PriceListHandlers.removePriceListPriceSetPrices
),
},
],
])
WorkflowManager.register(
Workflows.RemovePriceListProductPrices,
workflowSteps,
handlers
)
export const removePriceListProductPrices = exportWorkflow<
WorkflowTypes.PriceListWorkflow.RemovePriceListProductsWorkflowInputDTO,
string[]
>(
Workflows.RemovePriceListProductPrices,
RemoveProductPricesActions.removePriceListPriceSetPrices
)
@@ -0,0 +1,72 @@
import {
TransactionStepsDefinition,
WorkflowManager,
} from "@medusajs/orchestration"
import { WorkflowTypes } from "@medusajs/types"
import { exportWorkflow, pipe } from "../../helper"
import { Workflows } from "../../definitions"
import { PriceListHandlers } from "../../handlers"
export enum RemoveVariantPricesActions {
prepare = "prepare",
removePriceListPriceSetPrices = "removePriceListPriceSetPrices",
}
const workflowSteps: TransactionStepsDefinition = {
next: {
action: RemoveVariantPricesActions.prepare,
noCompensation: true,
next: {
action: RemoveVariantPricesActions.removePriceListPriceSetPrices,
noCompensation: true,
},
},
}
const handlers = new Map([
[
RemoveVariantPricesActions.prepare,
{
invoke: pipe(
{
inputAlias: RemoveVariantPricesActions.prepare,
merge: true,
invoke: {
from: RemoveVariantPricesActions.prepare,
},
},
PriceListHandlers.prepareRemoveVariantPrices
),
},
],
[
RemoveVariantPricesActions.removePriceListPriceSetPrices,
{
invoke: pipe(
{
merge: true,
invoke: {
from: RemoveVariantPricesActions.prepare,
alias: PriceListHandlers.createPriceLists.aliases.priceLists,
},
},
PriceListHandlers.removePriceListPriceSetPrices
),
},
],
])
WorkflowManager.register(
Workflows.RemovePriceListVariantPrices,
workflowSteps,
handlers
)
export const removePriceListVariantPrices = exportWorkflow<
WorkflowTypes.PriceListWorkflow.RemovePriceListVariantsWorkflowInputDTO,
string[]
>(
Workflows.RemovePriceListVariantPrices,
RemoveVariantPricesActions.removePriceListPriceSetPrices
)
@@ -0,0 +1,65 @@
import {
TransactionStepsDefinition,
WorkflowManager,
} from "@medusajs/orchestration"
import { WorkflowTypes } from "@medusajs/types"
import { exportWorkflow, pipe } from "../../helper"
import { Workflows } from "../../definitions"
import { PriceListHandlers } from "../../handlers"
export enum UpdatePriceListActions {
prepare = "prepare",
updatePriceList = "updatePriceList",
}
const workflowSteps: TransactionStepsDefinition = {
action: UpdatePriceListActions.prepare,
noCompensation: true,
next: {
next: {
noCompensation: true,
action: UpdatePriceListActions.updatePriceList,
},
},
}
const handlers = new Map([
[
UpdatePriceListActions.prepare,
{
invoke: pipe(
{
inputAlias: UpdatePriceListActions.prepare,
merge: true,
invoke: {
from: UpdatePriceListActions.prepare,
},
},
PriceListHandlers.prepareUpdatePriceLists
),
},
],
[
UpdatePriceListActions.updatePriceList,
{
invoke: pipe(
{
inputAlias: UpdatePriceListActions.updatePriceList,
merge: true,
invoke: {
from: UpdatePriceListActions.prepare,
},
},
PriceListHandlers.updatePriceLists
),
},
],
])
WorkflowManager.register(Workflows.UpdatePriceLists, workflowSteps, handlers)
export const updatePriceLists = exportWorkflow<
WorkflowTypes.PriceListWorkflow.UpdatePriceListWorkflowInputDTO,
{ priceList: WorkflowTypes.PriceListWorkflow.UpdatePriceListWorkflowDTO }[]
>(Workflows.UpdatePriceLists, UpdatePriceListActions.updatePriceList)
@@ -0,0 +1,121 @@
import {
TransactionStepsDefinition,
WorkflowManager,
} from "@medusajs/orchestration"
import { InputAlias, Workflows } from "../../definitions"
import { exportWorkflow, pipe } from "../../helper"
import { ProductTypes, WorkflowTypes } from "@medusajs/types"
import { ProductHandlers } from "../../handlers"
export enum CreateProductVariantsActions {
prepare = "prepare",
createProductVariants = "createProductVariants",
revertProductVariantsCreate = "revertProductVariantsCreate",
upsertPrices = "upsertPrices",
}
export const workflowSteps: TransactionStepsDefinition = {
next: {
action: CreateProductVariantsActions.prepare,
noCompensation: true,
next: {
action: CreateProductVariantsActions.createProductVariants,
next: [
{
action: CreateProductVariantsActions.upsertPrices,
},
],
},
},
}
const handlers = new Map([
[
CreateProductVariantsActions.prepare,
{
invoke: pipe(
{
merge: true,
inputAlias: InputAlias.ProductVariantsCreateInputData,
invoke: {
from: InputAlias.ProductVariantsCreateInputData,
},
},
ProductHandlers.createProductVariantsPrepareData
),
},
],
[
CreateProductVariantsActions.createProductVariants,
{
invoke: pipe(
{
merge: true,
invoke: {
from: CreateProductVariantsActions.prepare,
},
},
ProductHandlers.createProductVariants
),
compensate: pipe(
{
merge: true,
invoke: [
{
from: CreateProductVariantsActions.prepare,
},
{
from: CreateProductVariantsActions.createProductVariants,
},
],
},
ProductHandlers.removeProductVariants
),
},
],
[
CreateProductVariantsActions.upsertPrices,
{
invoke: pipe(
{
merge: true,
invoke: [
{
from: CreateProductVariantsActions.createProductVariants,
},
],
},
ProductHandlers.upsertVariantPrices
),
compensate: pipe(
{
merge: true,
invoke: [
{
from: CreateProductVariantsActions.prepare,
},
{
from: CreateProductVariantsActions.upsertPrices,
},
],
},
ProductHandlers.revertVariantPrices
),
},
],
])
WorkflowManager.register(
Workflows.CreateProductVariants,
workflowSteps,
handlers
)
export const createProductVariants = exportWorkflow<
WorkflowTypes.ProductWorkflow.CreateProductVariantsWorkflowInputDTO,
ProductTypes.ProductVariantDTO[]
>(
Workflows.CreateProductVariants,
CreateProductVariantsActions.createProductVariants
)
@@ -1,3 +1,4 @@
export * as CreateProductVariants from "./create-product-variants"
export * from "./create-products"
export * as UpdateProductVariants from "./update-product-variants"
export * from "./update-products"
+10
View File
@@ -4,12 +4,21 @@ export enum Workflows {
UpdateProducts = "update-products",
// Product Variant workflows
CreateProductVariants = "create-product-variants",
UpdateProductVariants = "update-product-variants",
// Cart workflows
CreateCart = "create-cart",
CreateInventoryItems = "create-inventory-items",
// Price list workflows
CreatePriceList = "create-price-list",
UpdatePriceLists = "update-price-lists",
DeletePriceLists = "delete-price-lists",
RemovePriceListProductPrices = "remove-price-list-products",
RemovePriceListVariantPrices = "remove-price-list-variants",
RemovePriceListPrices = "remove-price-list-prices",
}
export enum InputAlias {
@@ -19,6 +28,7 @@ export enum InputAlias {
ProductVariants = "productVariants",
ProductVariantsUpdateInputData = "productVariantsUpdateInputData",
ProductVariantsCreateInputData = "productVariantsCreateInputData",
InventoryItems = "inventoryItems",
RemovedInventoryItems = "removedInventoryItems",
+1
View File
@@ -4,6 +4,7 @@ export * as CommonHandlers from "./common"
export * as CustomerHandlers from "./customer"
export * as InventoryHandlers from "./inventory"
export * as MiddlewaresHandlers from "./middlewares"
export * as PriceListHandlers from "./price-list"
export * as ProductHandlers from "./product"
export * as RegionHandlers from "./region"
export * as SalesChannelHandlers from "./sales-channel"
@@ -0,0 +1,42 @@
import {
CreatePriceListDTO,
IPricingModuleService,
PriceListDTO,
} from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { WorkflowArguments } from "../../helper"
type Result = {
priceList: PriceListDTO
}[]
type Input = {
tag?: string
priceList: CreatePriceListDTO
}[]
export async function createPriceLists({
container,
data,
}: WorkflowArguments<{
priceLists: Input
}>): Promise<Result> {
const pricingService: IPricingModuleService = container.resolve(
ModuleRegistrationName.PRICING
)
return await Promise.all(
data.priceLists.map(async (item) => {
const [priceList] = await pricingService!.createPriceLists([
item.priceList,
])
return { tag: item.tag ?? priceList.id, priceList }
})
)
}
createPriceLists.aliases = {
priceLists: "priceLists",
}
@@ -0,0 +1,10 @@
export * from "./create-price-list"
export * from "./prepare-create-price-list"
export * from "./prepare-update-price-lists"
export * from "./remove-price-list"
export * from "./update-price-lists"
export * from "./prepare-remove-product-prices"
export * from "./remove-price-set-price-list-prices"
export * from "./prepare-remove-variant-prices"
export * from "./prepare-remove-price-list-prices"
export * from "./remove-prices"
@@ -0,0 +1,87 @@
import { CreatePriceListDTO, PriceListWorkflow } from "@medusajs/types"
import { MedusaError } from "@medusajs/utils"
import { WorkflowArguments } from "../../helper"
type Result = {
tag?: string
priceList: CreatePriceListDTO
}[]
export async function prepareCreatePriceLists({
container,
data,
}: WorkflowArguments<{
price_lists: (PriceListWorkflow.CreatePriceListWorkflowDTO & {
_associationTag?: string
})[]
}>): Promise<Result | void> {
const remoteQuery = container.resolve("remoteQuery")
const { price_lists } = data
const variantIds = price_lists
.map((priceList) => priceList.prices.map((price) => price.variant_id))
.flat()
const variables = {
variant_id: variantIds,
}
const query = {
product_variant_price_set: {
__args: variables,
fields: ["variant_id", "price_set_id"],
},
}
const variantPriceSets = await remoteQuery(query)
const variantIdPriceSetIdMap: Map<string, string> = new Map(
variantPriceSets.map((variantPriceSet) => [
variantPriceSet.variant_id,
variantPriceSet.price_set_id,
])
)
const variantsWithoutPriceSets: string[] = []
for (const variantId of variantIds) {
if (!variantIdPriceSetIdMap.has(variantId)) {
variantsWithoutPriceSets.push(variantId)
}
}
if (variantsWithoutPriceSets.length) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`No priceSet exist for variants: ${variantsWithoutPriceSets.join(", ")}`
)
}
return price_lists.map((priceListDTO) => {
priceListDTO.title ??= priceListDTO.name
const { _associationTag, name, prices, ...rest } = priceListDTO
const priceList = rest as CreatePriceListDTO
priceList.rules ??= {}
priceList.prices =
prices?.map((price) => {
const price_set_id = variantIdPriceSetIdMap.get(price.variant_id)!
return {
currency_code: price.currency_code,
amount: price.amount,
min_quantity: price.min_quantity,
max_quantity: price.max_quantity,
price_set_id,
}
}) ?? []
return { priceList, tag: _associationTag }
})
}
prepareCreatePriceLists.aliases = {
payload: "payload",
}
@@ -0,0 +1,48 @@
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { IPricingModuleService } from "@medusajs/types"
import { WorkflowArguments } from "../../helper"
type Result = {
moneyAmountIds: string[]
priceListId: string
}
export async function prepareRemovePriceListPrices({
container,
data,
}: WorkflowArguments<{
money_amount_ids: string[]
price_list_id: string
}>): Promise<Result | void> {
const pricingService: IPricingModuleService = container.resolve(
ModuleRegistrationName.PRICING
)
const {
price_list_id: priceListId,
money_amount_ids: moneyAmountIdsToDelete,
} = data
const moneyAmounts = await pricingService.listMoneyAmounts(
{ id: moneyAmountIdsToDelete },
{
relations: [
"price_set_money_amount",
"price_set_money_amount.price_list",
],
}
)
const moneyAmountIds = moneyAmounts
.filter(
(moneyAmount) =>
moneyAmount?.price_set_money_amount?.price_list?.id === priceListId
)
.map((ma) => ma.id)
return { moneyAmountIds, priceListId }
}
prepareRemovePriceListPrices.aliases = {
payload: "payload",
}
@@ -0,0 +1,62 @@
import { WorkflowArguments } from "../../helper"
import { prepareCreatePriceLists } from "./prepare-create-price-list"
type Result = {
priceSetIds: string[]
priceListId: string
}
export async function prepareRemoveProductPrices({
container,
data,
}: WorkflowArguments<{
product_ids: string[]
price_list_id: string
}>): Promise<Result | void> {
const remoteQuery = container.resolve("remoteQuery")
const { price_list_id, product_ids } = data
const variables = {
id: product_ids,
}
const query = {
product: {
__args: variables,
...defaultAdminProductRemoteQueryObject,
},
}
const productsWithVariantPriceSets: QueryResult[] = await remoteQuery(query)
const priceSetIds = productsWithVariantPriceSets
.map(({ variants }) => variants.map(({ price }) => price.price_set_id))
.flat()
return { priceSetIds, priceListId: price_list_id }
}
prepareCreatePriceLists.aliases = {
payload: "payload",
}
type QueryResult = {
id: string
variants: {
id: string
price: {
price_set_id: string
variant_id: string
}
}[]
}
const defaultAdminProductRemoteQueryObject = {
fields: ["id"],
variants: {
price: {
fields: ["variant_id", "price_set_id"],
},
},
}
@@ -0,0 +1,56 @@
import { WorkflowArguments } from "../../helper"
import { prepareCreatePriceLists } from "./prepare-create-price-list"
type Result = {
priceSetIds: string[]
priceListId: string
}
export async function prepareRemoveVariantPrices({
container,
data,
}: WorkflowArguments<{
variant_ids: string[]
price_list_id: string
}>): Promise<Result | void> {
const remoteQuery = container.resolve("remoteQuery")
const { price_list_id, variant_ids } = data
const variables = {
variant_id: variant_ids,
}
const query = {
product_variant_price_set: {
__args: variables,
fields: ["variant_id", "price_set_id"],
},
}
const productsWithVariantPriceSets: QueryResult[] = await remoteQuery(query)
const priceSetIds = productsWithVariantPriceSets.map(
(variantPriceSet) => variantPriceSet.price_set_id
)
return { priceSetIds, priceListId: price_list_id }
}
prepareCreatePriceLists.aliases = {
payload: "payload",
}
type QueryResult = {
price_set_id: string
variant_id: string
}
const defaultAdminProductRemoteQueryObject = {
fields: ["id"],
variants: {
price: {
fields: ["variant_id", "price_set_id"],
},
},
}
@@ -0,0 +1,87 @@
import {
PriceListPriceDTO,
UpdatePriceListDTO,
WorkflowTypes,
} from "@medusajs/types"
import { WorkflowArguments } from "../../helper"
type Result = {
priceLists: UpdatePriceListDTO[]
priceListPricesMap: Map<string, PriceListPriceDTO[]>
}
export async function prepareUpdatePriceLists({
container,
data,
}: WorkflowArguments<{
price_lists: WorkflowTypes.PriceListWorkflow.UpdatePriceListWorkflowDTO[]
}>): Promise<Result> {
const { price_lists: priceListsData } = data
const remoteQuery = container.resolve("remoteQuery")
const variantPriceSetMap = new Map<string, string>()
const priceListPricesMap = new Map<string, PriceListPriceDTO[]>()
const variantIds = priceListsData
.map((priceListData) => priceListData.prices?.map((p) => p.variant_id))
.flat()
const variables = {
variant_id: variantIds,
}
const query = {
product_variant_price_set: {
__args: variables,
fields: ["variant_id", "price_set_id"],
},
}
const variantPriceSets = await remoteQuery(query)
for (const { variant_id, price_set_id } of variantPriceSets) {
variantPriceSetMap.set(variant_id, price_set_id)
}
const priceLists = priceListsData.map((priceListData) => {
const priceListPrices: PriceListPriceDTO[] = []
priceListData.prices?.forEach((price) => {
const { variant_id, ...priceData } = price
if (!variant_id) {
return
}
priceListPrices.push({
id: priceData.id,
price_set_id: variantPriceSetMap.get(variant_id) as string,
currency_code: priceData.currency_code as string,
amount: priceData.amount,
min_quantity: priceData.min_quantity,
max_quantity: priceData.max_quantity,
})
return
})
priceListPricesMap.set(priceListData.id, priceListPrices)
delete priceListData?.prices
const priceListDataClone: UpdatePriceListDTO = {
...priceListData,
}
if (priceListData.name) {
priceListDataClone.title = priceListData.name
}
return priceListDataClone
})
return { priceLists, priceListPricesMap }
}
prepareUpdatePriceLists.aliases = {
payload: "prepare",
}
@@ -0,0 +1,31 @@
import { IPricingModuleService, PriceListDTO } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { WorkflowArguments } from "../../helper"
export async function removePriceLists({
container,
data,
}: WorkflowArguments<{
price_lists: {
price_list: PriceListDTO
}[]
}>): Promise<
{
price_list: PriceListDTO
}[]
> {
const pricingService: IPricingModuleService = container.resolve(
ModuleRegistrationName.PRICING
)
await pricingService!.deletePriceLists(
data.price_lists.map(({ price_list }) => price_list.id)
)
return data.price_lists
}
removePriceLists.aliases = {
priceLists: "priceLists",
}
@@ -0,0 +1,39 @@
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { IPricingModuleService } from "@medusajs/types"
import { WorkflowArguments } from "../../helper"
import { prepareCreatePriceLists } from "./prepare-create-price-list"
export async function removePriceListPriceSetPrices({
container,
data,
}: WorkflowArguments<{
priceSetIds: string[]
priceListId: string
}>): Promise<string[]> {
const { priceSetIds, priceListId } = data
const pricingService: IPricingModuleService = container.resolve(
ModuleRegistrationName.PRICING
)
const priceSetMoneyAmounts = await pricingService.listPriceSetMoneyAmounts(
{
price_set_id: priceSetIds,
price_list_id: [priceListId],
},
{
relations: ["money_amount"],
}
)
const moneyAmountIDs = priceSetMoneyAmounts
.map((priceSetMoneyAmount) => priceSetMoneyAmount.money_amount?.id)
.filter((moneyAmountId): moneyAmountId is string => !!moneyAmountId)
await pricingService.deleteMoneyAmounts(moneyAmountIDs)
return moneyAmountIDs
}
prepareCreatePriceLists.aliases = {
payload: "payload",
}
@@ -0,0 +1,29 @@
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { IPricingModuleService } from "@medusajs/types"
import { WorkflowArguments } from "../../helper"
type Result = {
deletedPriceIds: string[]
}
export async function removePrices({
container,
data,
}: WorkflowArguments<{
moneyAmountIds: string[]
}>): Promise<Result> {
const { moneyAmountIds } = data
const pricingService: IPricingModuleService = container.resolve(
ModuleRegistrationName.PRICING
)
await pricingService.deleteMoneyAmounts(moneyAmountIds)
return {
deletedPriceIds: moneyAmountIds,
}
}
removePrices.aliases = {
payload: "payload",
}
@@ -0,0 +1,63 @@
import {
AddPriceListPricesDTO,
IPricingModuleService,
PriceListDTO,
PriceListPriceDTO,
UpdateMoneyAmountDTO,
UpdatePriceListDTO,
} from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { WorkflowArguments } from "../../helper"
type Result = {
priceLists: PriceListDTO[]
}
export async function updatePriceLists({
container,
data,
}: WorkflowArguments<{
priceLists: UpdatePriceListDTO[]
priceListPricesMap: Map<string, PriceListPriceDTO[]>
}>): Promise<Result> {
const { priceLists: priceListsData, priceListPricesMap } = data
const pricingService: IPricingModuleService = container.resolve(
ModuleRegistrationName.PRICING
)
const priceLists = await pricingService.updatePriceLists(priceListsData)
const addPriceListPricesData: AddPriceListPricesDTO[] = []
const moneyAmountsToUpdate: UpdateMoneyAmountDTO[] = []
for (const [priceListId, prices] of priceListPricesMap.entries()) {
const moneyAmountsToCreate: PriceListPriceDTO[] = []
for (const price of prices) {
if (price.id) {
moneyAmountsToUpdate.push(price as UpdateMoneyAmountDTO)
} else {
moneyAmountsToCreate.push(price)
}
}
addPriceListPricesData.push({
priceListId,
prices: moneyAmountsToCreate,
})
}
if (addPriceListPricesData.length) {
await pricingService.addPriceListPrices(addPriceListPricesData)
}
if (moneyAmountsToUpdate.length) {
await pricingService.updateMoneyAmounts(moneyAmountsToUpdate)
}
return { priceLists }
}
updatePriceLists.aliases = {
payload: "updatePriceLists",
}
@@ -0,0 +1,67 @@
import { ProductWorkflow, WorkflowTypes } from "@medusajs/types"
import { WorkflowArguments } from "../../helper"
type VariantPrice = {
region_id?: string
currency_code?: string
amount: number
min_quantity?: number
max_quantity?: number
}
export type CreateProductVariantsPreparedData = {
productVariants: ProductWorkflow.CreateProductVariantsInputDTO[]
variantIndexPricesMap: Map<number, VariantPrice[]>
productVariantsMap: Map<
string,
ProductWorkflow.CreateProductVariantsInputDTO[]
>
}
export async function createProductVariantsPrepareData({
container,
data,
}: WorkflowArguments<WorkflowTypes.ProductWorkflow.CreateProductVariantsWorkflowInputDTO>): Promise<CreateProductVariantsPreparedData> {
const featureFlagRouter = container.resolve("featureFlagRouter")
const productVariants: ProductWorkflow.CreateProductVariantsInputDTO[] =
data.productVariants || []
const variantIndexPricesMap = new Map<number, VariantPrice[]>()
const productVariantsMap = new Map<
string,
ProductWorkflow.CreateProductVariantsInputDTO[]
>()
for (const [index, productVariantData] of productVariants.entries()) {
if (!productVariantData.product_id) {
continue
}
variantIndexPricesMap.set(index, productVariantData.prices || [])
delete productVariantData.prices
const productVariants = productVariantsMap.get(
productVariantData.product_id
)
if (productVariants) {
productVariants.push(productVariantData)
} else {
productVariantsMap.set(productVariantData.product_id, [
productVariantData,
])
}
}
return {
productVariants,
variantIndexPricesMap,
productVariantsMap,
}
}
createProductVariantsPrepareData.aliases = {
payload: "payload",
}
@@ -0,0 +1,46 @@
import { Modules, ModulesDefinition } from "@medusajs/modules-sdk"
import { ProductTypes } from "@medusajs/types"
import { WorkflowArguments } from "../../helper"
type VariantPrice = {
region_id?: string
currency_code?: string
amount: number
min_quantity?: number
max_quantity?: number
}
type HandlerInput = {
productVariantsMap: Map<string, ProductTypes.CreateProductVariantDTO[]>
variantIndexPricesMap: Map<number, VariantPrice[]>
}
export async function createProductVariants({
container,
data,
}: WorkflowArguments<HandlerInput>): Promise<{
productVariants: ProductTypes.ProductVariantDTO[]
variantPricesMap: Map<string, VariantPrice[]>
}> {
const { productVariantsMap, variantIndexPricesMap } = data
const variantPricesMap = new Map<string, VariantPrice[]>()
const productModuleService: ProductTypes.IProductModuleService =
container.resolve(ModulesDefinition[Modules.PRODUCT].registrationName)
const productVariants = await productModuleService.createVariants(
[...productVariantsMap.values()].flat()
)
productVariants.forEach((variant, index) => {
variantPricesMap.set(variant.id, variantIndexPricesMap.get(index) || [])
})
return {
productVariants,
variantPricesMap,
}
}
createProductVariants.aliases = {
payload: "payload",
}
@@ -1,8 +1,8 @@
import { ProductTypes, SalesChannelTypes, WorkflowTypes } from "@medusajs/types"
import {
FeatureFlagUtils,
ShippingProfileUtils,
kebabCase,
ShippingProfileUtils,
} from "@medusajs/utils"
import { WorkflowArguments } from "../../helper"
@@ -114,23 +114,17 @@ export async function createProductsPrepareData({
}
if (product.variants) {
const hasPrices = product.variants.some((variant) => {
return (variant.prices?.length ?? 0) > 0
const items =
productsHandleVariantsIndexPricesMap.get(product.handle!) ?? []
product.variants.forEach((variant, index) => {
items.push({
index,
prices: variant.prices!,
})
})
if (hasPrices) {
const items =
productsHandleVariantsIndexPricesMap.get(product.handle!) ?? []
product.variants.forEach((variant, index) => {
items.push({
index,
prices: variant.prices!,
})
})
productsHandleVariantsIndexPricesMap.set(product.handle!, items)
}
productsHandleVariantsIndexPricesMap.set(product.handle!, items)
}
}
@@ -1,10 +1,13 @@
export * from "./attach-sales-channel-to-products"
export * from "./attach-shipping-profile-to-products"
export * from "./create-product-variants"
export * from "./create-product-variants-prepare-data"
export * from "./create-products"
export * from "./create-products-prepare-data"
export * from "./detach-sales-channel-from-products"
export * from "./detach-shipping-profile-from-products"
export * from "./list-products"
export * from "./remove-product-variants"
export * from "./remove-products"
export * from "./revert-update-products"
export * from "./revert-variant-prices"
@@ -0,0 +1,26 @@
import { Modules, ModulesDefinition } from "@medusajs/modules-sdk"
import { IProductModuleService } from "@medusajs/types"
import { WorkflowArguments } from "../../helper"
type HandlerInput = { productVariants: { id: string }[] }
export async function removeProductVariants({
container,
data,
}: WorkflowArguments<HandlerInput>): Promise<void> {
if (!data.productVariants.length) {
return
}
const productModuleService: IProductModuleService = container.resolve(
ModulesDefinition[Modules.PRODUCT].registrationName
)
await productModuleService.deleteVariants(
data.productVariants.map((p) => p.id)
)
}
removeProductVariants.aliases = {
productVariants: "productVariants",
}
@@ -23,11 +23,9 @@ type HandlerInput = {
export async function upsertVariantPrices({
container,
context,
data,
}: WorkflowArguments<HandlerInput>) {
const { variantPricesMap } = data
const featureFlagRouter = container.resolve("featureFlagRouter")
if (!featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) {
@@ -129,16 +127,16 @@ export async function upsertVariantPrices({
priceSetId = createdPriceSet?.id
createdPriceSets.push(createdPriceSet)
}
linksToCreate.push({
productService: {
variant_id: variantId,
},
pricingService: {
price_set_id: priceSetId,
},
})
linksToCreate.push({
productService: {
variant_id: variantId,
},
pricingService: {
price_set_id: priceSetId,
},
})
}
}
const createdLinks = await remoteLink.create(linksToCreate)