feat(core-flows,medusa,pricing,types,utils): added price list workflows + endpoints (#6648)
Apologies for the giant PR in advance, but most of these are removing of files and migrations from old workflows and routes to new. What: - Adds CRUD endpoints for price lists - Migrate workflows from old sdk to new - Added missing updatePriceListPrices method to pricing module
This commit is contained in:
1 parent
c3f26a6826
commit
9288f53327
81 files changed
+1959
-2410
No files matched your search
@@ -2,5 +2,4 @@ export * from "./cart"
|
||||
export * from "./inventory"
|
||||
export * from "./line-item"
|
||||
export * from "./payment-collection"
|
||||
export * from "./price-list"
|
||||
export * from "./product"
|
||||
@@ -1,74 +0,0 @@
|
||||
import {
|
||||
TransactionStepsDefinition,
|
||||
WorkflowManager,
|
||||
} from "@medusajs/orchestration"
|
||||
import { PricingTypes, WorkflowTypes } from "@medusajs/types"
|
||||
import { exportWorkflow, pipe } from "@medusajs/workflows-sdk"
|
||||
|
||||
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)
|
||||
@@ -1,71 +0,0 @@
|
||||
import {
|
||||
TransactionStepsDefinition,
|
||||
WorkflowManager,
|
||||
} from "@medusajs/orchestration"
|
||||
import { WorkflowTypes } from "@medusajs/types"
|
||||
import { exportWorkflow, pipe } from "@medusajs/workflows-sdk"
|
||||
|
||||
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 removePriceListPrices = exportWorkflow<
|
||||
WorkflowTypes.PriceListWorkflow.RemovePriceListPricesWorkflowInputDTO,
|
||||
string[]
|
||||
>(
|
||||
Workflows.RemovePriceListPrices,
|
||||
RemovePriceListPricesActions.removePriceListPrices
|
||||
)
|
||||
@@ -1,57 +0,0 @@
|
||||
import { WorkflowTypes } from "@medusajs/types"
|
||||
import {
|
||||
TransactionStepsDefinition,
|
||||
WorkflowManager,
|
||||
} from "@medusajs/orchestration"
|
||||
import { exportWorkflow, pipe } from "@medusajs/workflows-sdk"
|
||||
|
||||
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 },
|
||||
})),
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -1,72 +0,0 @@
|
||||
import {
|
||||
TransactionStepsDefinition,
|
||||
WorkflowManager,
|
||||
} from "@medusajs/orchestration"
|
||||
import { WorkflowTypes } from "@medusajs/types"
|
||||
import { exportWorkflow, pipe } from "@medusajs/workflows-sdk"
|
||||
|
||||
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
|
||||
)
|
||||
@@ -1,72 +0,0 @@
|
||||
import {
|
||||
TransactionStepsDefinition,
|
||||
WorkflowManager,
|
||||
} from "@medusajs/orchestration"
|
||||
import { WorkflowTypes } from "@medusajs/types"
|
||||
import { exportWorkflow, pipe } from "@medusajs/workflows-sdk"
|
||||
|
||||
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
|
||||
)
|
||||
@@ -1,65 +0,0 @@
|
||||
import {
|
||||
TransactionStepsDefinition,
|
||||
WorkflowManager,
|
||||
} from "@medusajs/orchestration"
|
||||
import { WorkflowTypes } from "@medusajs/types"
|
||||
import { exportWorkflow, pipe } from "@medusajs/workflows-sdk"
|
||||
|
||||
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)
|
||||
@@ -3,7 +3,6 @@ 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"
|
||||
@@ -1,42 +0,0 @@
|
||||
import {
|
||||
CreatePriceListDTO,
|
||||
IPricingModuleService,
|
||||
PriceListDTO,
|
||||
} from "@medusajs/types"
|
||||
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
||||
|
||||
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",
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
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"
|
||||
@@ -1,108 +0,0 @@
|
||||
import { CreatePriceListDTO, PriceListWorkflow } from "@medusajs/types"
|
||||
import { MedusaError } from "@medusajs/utils"
|
||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
||||
|
||||
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 regionService = container.resolve("regionService")
|
||||
|
||||
const { price_lists } = data
|
||||
|
||||
const variantIds = price_lists
|
||||
.map((priceList) => priceList.prices.map((price) => price.variant_id))
|
||||
.flat()
|
||||
|
||||
const variables = {
|
||||
variant_id: variantIds,
|
||||
take: null,
|
||||
}
|
||||
|
||||
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(", ")}`
|
||||
)
|
||||
}
|
||||
|
||||
const regionIds = price_lists
|
||||
.map(({ prices }) => prices?.map((price) => price.region_id) ?? [])
|
||||
.flat(2)
|
||||
const regions = await regionService.list({ id: regionIds }, {})
|
||||
const regionIdCurrencyCodeMap: Map<string, string> = new Map(
|
||||
regions.map((region: { id: string; currency_code: string }) => [
|
||||
region.id,
|
||||
region.currency_code,
|
||||
])
|
||||
)
|
||||
|
||||
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)!
|
||||
|
||||
const rules: Record<string, string> = {}
|
||||
if (price.region_id) {
|
||||
rules.region_id = price.region_id
|
||||
}
|
||||
|
||||
return {
|
||||
currency_code:
|
||||
regionIdCurrencyCodeMap.get(price.region_id as string) ??
|
||||
(price.currency_code as string),
|
||||
amount: price.amount,
|
||||
min_quantity: price.min_quantity,
|
||||
max_quantity: price.max_quantity,
|
||||
price_set_id,
|
||||
rules,
|
||||
}
|
||||
}) ?? []
|
||||
|
||||
return { priceList, tag: _associationTag }
|
||||
})
|
||||
}
|
||||
|
||||
prepareCreatePriceLists.aliases = {
|
||||
payload: "payload",
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { IPricingModuleService } from "@medusajs/types"
|
||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
||||
|
||||
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",
|
||||
],
|
||||
take: null,
|
||||
}
|
||||
)
|
||||
|
||||
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",
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
||||
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,
|
||||
take: null,
|
||||
}
|
||||
|
||||
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"],
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
||||
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,
|
||||
take: null,
|
||||
}
|
||||
|
||||
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"],
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
import {
|
||||
PriceListPriceDTO,
|
||||
UpdatePriceListDTO,
|
||||
WorkflowTypes,
|
||||
} from "@medusajs/types"
|
||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
||||
|
||||
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 regionService = container.resolve("regionService")
|
||||
|
||||
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,
|
||||
take: null,
|
||||
}
|
||||
|
||||
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 regionIds = priceListsData
|
||||
.map(({ prices }) => prices?.map((price) => price.region_id) ?? [])
|
||||
.flat(2)
|
||||
const regions = await regionService.list({ id: regionIds })
|
||||
const regionsMap: Map<string, string> = new Map(
|
||||
regions.map((region: { id: string; currency_code: string }) => [
|
||||
region.id,
|
||||
region.currency_code,
|
||||
])
|
||||
)
|
||||
|
||||
const priceLists = priceListsData.map((priceListData) => {
|
||||
const priceListPrices: PriceListPriceDTO[] = []
|
||||
|
||||
priceListData.prices?.forEach((price) => {
|
||||
const { variant_id, ...priceData } = price
|
||||
if (!variant_id) {
|
||||
return
|
||||
}
|
||||
|
||||
const rules: Record<string, string> = {}
|
||||
if (price.region_id) {
|
||||
rules.region_id = price.region_id
|
||||
}
|
||||
|
||||
priceListPrices.push({
|
||||
id: priceData.id,
|
||||
price_set_id: variantPriceSetMap.get(variant_id) as string,
|
||||
currency_code:
|
||||
regionsMap.get(priceData.region_id as string) ??
|
||||
(priceData.currency_code as string),
|
||||
amount: priceData.amount,
|
||||
min_quantity: priceData.min_quantity,
|
||||
max_quantity: priceData.max_quantity,
|
||||
rules,
|
||||
})
|
||||
|
||||
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",
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import { IPricingModuleService, PriceListDTO } from "@medusajs/types"
|
||||
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
||||
|
||||
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",
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { IPricingModuleService } from "@medusajs/types"
|
||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
||||
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"],
|
||||
take: null,
|
||||
}
|
||||
)
|
||||
|
||||
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",
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { IPricingModuleService } from "@medusajs/types"
|
||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
||||
|
||||
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",
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
import {
|
||||
AddPriceListPricesDTO,
|
||||
IPricingModuleService,
|
||||
PriceListDTO,
|
||||
PriceListPriceDTO,
|
||||
UpdateMoneyAmountDTO,
|
||||
UpdatePriceListDTO,
|
||||
} from "@medusajs/types"
|
||||
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { WorkflowArguments } from "@medusajs/workflows-sdk"
|
||||
|
||||
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",
|
||||
}
|
||||
@@ -8,6 +8,7 @@ export * from "./fulfillment"
|
||||
export * as Handlers from "./handlers"
|
||||
export * from "./invite"
|
||||
export * from "./payment"
|
||||
export * from "./price-list"
|
||||
export * from "./pricing"
|
||||
export * from "./product"
|
||||
export * from "./promotion"
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from "./steps"
|
||||
export * from "./workflows"
|
||||
@@ -0,0 +1,58 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import {
|
||||
CreatePriceListDTO,
|
||||
CreatePriceListWorkflowInputDTO,
|
||||
IPricingModuleService,
|
||||
} from "@medusajs/types"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
|
||||
type WorkflowStepInput = {
|
||||
data: CreatePriceListWorkflowInputDTO[]
|
||||
variant_price_map: Record<string, string>
|
||||
}
|
||||
|
||||
export const createPriceListsStepId = "create-price-lists"
|
||||
export const createPriceListsStep = createStep(
|
||||
createPriceListsStepId,
|
||||
async (stepInput: WorkflowStepInput, { container }) => {
|
||||
const { data, variant_price_map: variantPriceMap } = stepInput
|
||||
|
||||
const pricingModule = container.resolve<IPricingModuleService>(
|
||||
ModuleRegistrationName.PRICING
|
||||
)
|
||||
|
||||
const createData = data.map((priceListDTO) => {
|
||||
const { prices = [], ...rest } = priceListDTO
|
||||
const createPriceListData: CreatePriceListDTO = { ...rest }
|
||||
|
||||
createPriceListData.prices = prices.map((price) => ({
|
||||
currency_code: price.currency_code,
|
||||
amount: price.amount,
|
||||
min_quantity: price.min_quantity,
|
||||
max_quantity: price.max_quantity,
|
||||
price_set_id: variantPriceMap[price.variant_id],
|
||||
rules: price.rules,
|
||||
}))
|
||||
|
||||
return createPriceListData
|
||||
})
|
||||
|
||||
const createdPriceLists = await pricingModule.createPriceLists(createData)
|
||||
|
||||
return new StepResponse(
|
||||
createdPriceLists,
|
||||
createdPriceLists.map((createdPriceLists) => createdPriceLists.id)
|
||||
)
|
||||
},
|
||||
async (createdPriceListIds, { container }) => {
|
||||
if (!createdPriceListIds?.length) {
|
||||
return
|
||||
}
|
||||
|
||||
const pricingModule = container.resolve<IPricingModuleService>(
|
||||
ModuleRegistrationName.PRICING
|
||||
)
|
||||
|
||||
await pricingModule.deletePriceLists(createdPriceListIds)
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,30 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { IPricingModuleService } from "@medusajs/types"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
|
||||
export const deletePriceListsStepId = "delete-campaigns"
|
||||
export const deletePriceListsStep = createStep(
|
||||
deletePriceListsStepId,
|
||||
async (ids: string[], { container }) => {
|
||||
const pricingModule = container.resolve<IPricingModuleService>(
|
||||
ModuleRegistrationName.PRICING
|
||||
)
|
||||
|
||||
// TODO: Implement soft delete price lists
|
||||
await pricingModule.deletePriceLists(ids)
|
||||
|
||||
return new StepResponse(void 0, ids)
|
||||
},
|
||||
async (idsToRestore, { container }) => {
|
||||
if (!idsToRestore?.length) {
|
||||
return
|
||||
}
|
||||
|
||||
const pricingModule = container.resolve<IPricingModuleService>(
|
||||
ModuleRegistrationName.PRICING
|
||||
)
|
||||
|
||||
// TODO: Implement restore price lists
|
||||
// await pricingModule.restorePriceLists(idsToRestore)
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
export * from "./create-price-lists"
|
||||
export * from "./delete-price-lists"
|
||||
export * from "./remove-price-list-prices"
|
||||
export * from "./update-price-lists"
|
||||
export * from "./upsert-price-list-prices"
|
||||
export * from "./validate-price-lists"
|
||||
export * from "./validate-variant-price-links"
|
||||
@@ -0,0 +1,41 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { IPricingModuleService } from "@medusajs/types"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
|
||||
export const removePriceListPricesStepId = "remove-price-list-prices"
|
||||
export const removePriceListPricesStep = createStep(
|
||||
removePriceListPricesStepId,
|
||||
async (ids: string[], { container }) => {
|
||||
if (!ids.length) {
|
||||
return new StepResponse(null, [])
|
||||
}
|
||||
|
||||
const pricingModule = container.resolve<IPricingModuleService>(
|
||||
ModuleRegistrationName.PRICING
|
||||
)
|
||||
|
||||
const psmas = await pricingModule.listPriceSetMoneyAmounts(
|
||||
{ id: ids },
|
||||
{ relations: ["price_list"] }
|
||||
)
|
||||
|
||||
await pricingModule.removePrices(psmas.map((psma) => psma.id))
|
||||
|
||||
return new StepResponse(
|
||||
null,
|
||||
psmas.map((psma) => psma.id)
|
||||
)
|
||||
},
|
||||
async (ids, { container }) => {
|
||||
if (!ids) {
|
||||
return
|
||||
}
|
||||
|
||||
const pricingModule = container.resolve<IPricingModuleService>(
|
||||
ModuleRegistrationName.PRICING
|
||||
)
|
||||
|
||||
// TODO: This needs to be implemented
|
||||
// pricingModule.restorePrices(ids)
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,105 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import {
|
||||
IPricingModuleService,
|
||||
UpdatePriceListDTO,
|
||||
UpdatePriceListWorkflowInputDTO,
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
buildPriceListRules,
|
||||
convertItemResponseToUpdateRequest,
|
||||
getSelectsAndRelationsFromObjectArray,
|
||||
} from "@medusajs/utils"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
|
||||
export const updatePriceListsStepId = "update-price-lists"
|
||||
export const updatePriceListsStep = createStep(
|
||||
updatePriceListsStepId,
|
||||
async (data: UpdatePriceListDTO[], { container }) => {
|
||||
const pricingModule = container.resolve<IPricingModuleService>(
|
||||
ModuleRegistrationName.PRICING
|
||||
)
|
||||
|
||||
const { dataBeforeUpdate, selects, relations } = await getDataBeforeUpdate(
|
||||
pricingModule,
|
||||
data
|
||||
)
|
||||
|
||||
const updatedPriceLists = await pricingModule.updatePriceLists(data)
|
||||
|
||||
return new StepResponse(updatedPriceLists, {
|
||||
dataBeforeUpdate,
|
||||
selects,
|
||||
relations,
|
||||
})
|
||||
},
|
||||
async (revertInput, { container }) => {
|
||||
if (!revertInput) {
|
||||
return
|
||||
}
|
||||
|
||||
const { dataBeforeUpdate, selects, relations } = revertInput
|
||||
const pricingModule = container.resolve<IPricingModuleService>(
|
||||
ModuleRegistrationName.PRICING
|
||||
)
|
||||
|
||||
await pricingModule.updatePriceLists(
|
||||
dataBeforeUpdate.map((data) => {
|
||||
const { price_list_rules: priceListRules = [], rules, ...rest } = data
|
||||
|
||||
const updateData: UpdatePriceListDTO = {
|
||||
...rest,
|
||||
rules: buildPriceListRules(priceListRules),
|
||||
}
|
||||
|
||||
return convertItemResponseToUpdateRequest(
|
||||
updateData,
|
||||
selects,
|
||||
relations
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
// Since rules is an API level abstraction, we need to do this dance of data fetching
|
||||
// to its actual attributes in the module to do perform a revert in case a rollback needs to happen.
|
||||
// TODO: Check if there is a better way to approach this. Preferably the module should be handling this
|
||||
// if this is not the response the module provides.
|
||||
async function getDataBeforeUpdate(
|
||||
pricingModule: IPricingModuleService,
|
||||
data: UpdatePriceListWorkflowInputDTO[]
|
||||
) {
|
||||
const { selects, relations } = getSelectsAndRelationsFromObjectArray(data, {
|
||||
objectFields: ["rules"],
|
||||
})
|
||||
const selectsClone = [...selects]
|
||||
const relationsClone = [...relations]
|
||||
|
||||
if (selectsClone.includes("rules")) {
|
||||
const index = selectsClone.indexOf("rules", 0)
|
||||
|
||||
if (index > -1) {
|
||||
selectsClone.splice(index, 1)
|
||||
}
|
||||
|
||||
selectsClone.push(
|
||||
"price_list_rules.price_list_rule_values.value",
|
||||
"price_list_rules.rule_type.rule_attribute"
|
||||
)
|
||||
relationsClone.push(
|
||||
"price_list_rules.price_list_rule_values",
|
||||
"price_list_rules.rule_type"
|
||||
)
|
||||
}
|
||||
|
||||
const dataBeforeUpdate = await pricingModule.listPriceLists(
|
||||
{ id: data.map((d) => d.id) },
|
||||
{ relations: relationsClone, select: selectsClone }
|
||||
)
|
||||
|
||||
return {
|
||||
dataBeforeUpdate,
|
||||
selects,
|
||||
relations,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import {
|
||||
AddPriceListPricesDTO,
|
||||
CreatePriceListPriceDTO,
|
||||
CreatePriceListPriceWorkflowDTO,
|
||||
IPricingModuleService,
|
||||
PriceSetMoneyAmountDTO,
|
||||
UpdatePriceListPriceDTO,
|
||||
UpdatePriceListPriceWorkflowDTO,
|
||||
UpdatePriceListPricesDTO,
|
||||
UpdatePriceListWorkflowInputDTO,
|
||||
} from "@medusajs/types"
|
||||
import { buildPriceSetPricesForModule, promiseAll } from "@medusajs/utils"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
|
||||
type WorkflowStepInput = {
|
||||
data: Pick<UpdatePriceListWorkflowInputDTO, "id" | "prices">[]
|
||||
variant_price_map: Record<string, string>
|
||||
}
|
||||
|
||||
export const upsertPriceListPricesStepId = "upsert-price-list-prices"
|
||||
export const upsertPriceListPricesStep = createStep(
|
||||
upsertPriceListPricesStepId,
|
||||
async (stepInput: WorkflowStepInput, { container }) => {
|
||||
const { data, variant_price_map: variantPriceSetMap } = stepInput
|
||||
|
||||
const priceListPricesToUpdate: UpdatePriceListPricesDTO[] = []
|
||||
const priceListPricesToAdd: AddPriceListPricesDTO[] = []
|
||||
const pricingModule = container.resolve<IPricingModuleService>(
|
||||
ModuleRegistrationName.PRICING
|
||||
)
|
||||
|
||||
for (const upsertPriceListPricesData of data) {
|
||||
const { prices = [], id } = upsertPriceListPricesData
|
||||
|
||||
const pricesToAdd: CreatePriceListPriceDTO[] = []
|
||||
const pricesToUpdate: UpdatePriceListPriceDTO[] = []
|
||||
|
||||
for (const price of prices) {
|
||||
const priceSetId = variantPriceSetMap[price.variant_id!]
|
||||
|
||||
if (isPriceUpdate(price)) {
|
||||
pricesToUpdate.push({ ...price, price_set_id: priceSetId })
|
||||
} else {
|
||||
pricesToAdd.push({ ...price, price_set_id: priceSetId })
|
||||
}
|
||||
}
|
||||
|
||||
if (pricesToUpdate.length) {
|
||||
priceListPricesToUpdate.push({
|
||||
price_list_id: id,
|
||||
prices: pricesToUpdate,
|
||||
})
|
||||
}
|
||||
|
||||
if (pricesToAdd.length) {
|
||||
priceListPricesToAdd.push({
|
||||
price_list_id: id,
|
||||
prices: pricesToAdd,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const updatedPriceSetMoneyAmounts =
|
||||
await pricingModule.listPriceSetMoneyAmounts(
|
||||
{
|
||||
id: priceListPricesToUpdate
|
||||
.map((priceListData) =>
|
||||
priceListData.prices.map((price) => price.id)
|
||||
)
|
||||
.filter(Boolean)
|
||||
.flat(1),
|
||||
},
|
||||
{ relations: ["price_list"] }
|
||||
)
|
||||
|
||||
const priceListPsmaMap = new Map<string, PriceSetMoneyAmountDTO[]>()
|
||||
const dataBeforePriceUpdate: UpdatePriceListPricesDTO[] = []
|
||||
|
||||
for (const priceSetMoneyAmount of updatedPriceSetMoneyAmounts) {
|
||||
const priceListId = priceSetMoneyAmount.price_list!.id
|
||||
const psmas = priceListPsmaMap.get(priceListId) || []
|
||||
|
||||
priceListPsmaMap.set(priceListId, psmas)
|
||||
}
|
||||
|
||||
for (const [priceListId, psmas] of Object.entries(priceListPsmaMap)) {
|
||||
dataBeforePriceUpdate.push({
|
||||
price_list_id: priceListId,
|
||||
prices: buildPriceSetPricesForModule(psmas),
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: `addPriceListPrices` will return a list of price lists
|
||||
// This should be reworked to return prices instead, as we need to
|
||||
// do a revert incase this step fails
|
||||
const [createdPriceListPrices, _] = await promiseAll([
|
||||
pricingModule.addPriceListPrices(priceListPricesToAdd),
|
||||
pricingModule.updatePriceListPrices(priceListPricesToUpdate),
|
||||
])
|
||||
|
||||
return new StepResponse(null, {
|
||||
createdPriceListPrices,
|
||||
updatedPriceListPrices: dataBeforePriceUpdate,
|
||||
})
|
||||
},
|
||||
async (data, { container }) => {
|
||||
if (!data) {
|
||||
return
|
||||
}
|
||||
|
||||
const { createdPriceListPrices = [], updatedPriceListPrices = [] } = data
|
||||
const pricingModule = container.resolve<IPricingModuleService>(
|
||||
ModuleRegistrationName.PRICING
|
||||
)
|
||||
|
||||
if (createdPriceListPrices.length) {
|
||||
await pricingModule.removePrices(createdPriceListPrices.map((p) => p.id))
|
||||
}
|
||||
|
||||
if (updatedPriceListPrices.length) {
|
||||
await pricingModule.updatePriceListPrices(updatedPriceListPrices)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
function isPriceUpdate(
|
||||
data: UpdatePriceListPriceWorkflowDTO | CreatePriceListPriceWorkflowDTO
|
||||
): data is UpdatePriceListPriceWorkflowDTO {
|
||||
return "id" in data
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import {
|
||||
IPricingModuleService,
|
||||
PriceListDTO,
|
||||
UpdatePriceListDTO,
|
||||
} from "@medusajs/types"
|
||||
import { MedusaError, arrayDifference } from "@medusajs/utils"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
|
||||
export const validatePriceListsStepId = "validate-price-lists"
|
||||
export const validatePriceListsStep = createStep(
|
||||
validatePriceListsStepId,
|
||||
async (data: Pick<UpdatePriceListDTO, "id">[], { container }) => {
|
||||
const pricingModule = container.resolve<IPricingModuleService>(
|
||||
ModuleRegistrationName.PRICING
|
||||
)
|
||||
|
||||
const priceListIds = data.map((d) => d.id)
|
||||
const priceLists = await pricingModule.listPriceLists({ id: priceListIds })
|
||||
|
||||
const diff = arrayDifference(
|
||||
priceListIds,
|
||||
priceLists.map((pl) => pl.id)
|
||||
)
|
||||
|
||||
if (diff.length) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
`Price lists with id: ${diff.join(", ")} was not found`
|
||||
)
|
||||
}
|
||||
|
||||
const priceListMap: Record<string, PriceListDTO> = {}
|
||||
|
||||
for (const priceList of priceLists) {
|
||||
priceListMap[priceList.id] = priceList
|
||||
}
|
||||
|
||||
return new StepResponse(priceListMap)
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,48 @@
|
||||
import { UpdatePriceListWorkflowInputDTO } from "@medusajs/types"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
MedusaError,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
|
||||
type WorkflowStepInput = Pick<UpdatePriceListWorkflowInputDTO, "prices">[]
|
||||
|
||||
export const validateVariantPriceLinksStepId = "validate-variant-price-links"
|
||||
export const validateVariantPriceLinksStep = createStep(
|
||||
validateVariantPriceLinksStepId,
|
||||
async (data: WorkflowStepInput, { container }) => {
|
||||
const remoteQuery = container.resolve(
|
||||
ContainerRegistrationKeys.REMOTE_QUERY
|
||||
)
|
||||
|
||||
const variantIds: string[] = data
|
||||
.map((pl) => pl?.prices?.map((price) => price.variant_id!) || [])
|
||||
.filter(Boolean)
|
||||
.flat(1)
|
||||
|
||||
const variantPricingLinkQuery = remoteQueryObjectFromString({
|
||||
entryPoint: "product_variant_price_set",
|
||||
fields: ["variant_id", "price_set_id"],
|
||||
variables: { variant_id: variantIds, take: null },
|
||||
})
|
||||
|
||||
const links = await remoteQuery(variantPricingLinkQuery)
|
||||
const variantPriceSetMap: Record<string, string> = {}
|
||||
|
||||
for (const link of links) {
|
||||
variantPriceSetMap[link.variant_id] = link.price_set_id
|
||||
}
|
||||
|
||||
const withoutLinks = variantIds.filter((id) => !variantPriceSetMap[id])
|
||||
|
||||
if (withoutLinks.length) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`No price set exist for variants: ${withoutLinks.join(", ")}`
|
||||
)
|
||||
}
|
||||
|
||||
return new StepResponse(variantPriceSetMap)
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
import { CreatePriceListWorkflowInputDTO, PriceListDTO } from "@medusajs/types"
|
||||
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
|
||||
import { createPriceListsStep, validateVariantPriceLinksStep } from "../steps"
|
||||
|
||||
type WorkflowInput = { price_lists_data: CreatePriceListWorkflowInputDTO[] }
|
||||
|
||||
export const createPriceListsWorkflowId = "create-price-lists"
|
||||
export const createPriceListsWorkflow = createWorkflow(
|
||||
createPriceListsWorkflowId,
|
||||
(input: WorkflowData<WorkflowInput>): WorkflowData<PriceListDTO[]> => {
|
||||
const variantPriceMap = validateVariantPriceLinksStep(
|
||||
input.price_lists_data
|
||||
)
|
||||
|
||||
return createPriceListsStep({
|
||||
data: input.price_lists_data,
|
||||
variant_price_map: variantPriceMap,
|
||||
})
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createWorkflow, WorkflowData } from "@medusajs/workflows-sdk"
|
||||
import { deletePriceListsStep } from "../steps"
|
||||
|
||||
type WorkflowInput = { ids: string[] }
|
||||
|
||||
export const deletePriceListsWorkflowId = "delete-price-lists"
|
||||
export const deletePriceListsWorkflow = createWorkflow(
|
||||
deletePriceListsWorkflowId,
|
||||
(input: WorkflowData<WorkflowInput>): WorkflowData<void> => {
|
||||
return deletePriceListsStep(input.ids)
|
||||
}
|
||||
)
|
||||
+2
-3
@@ -1,6 +1,5 @@
|
||||
export * from "./create-price-lists"
|
||||
export * from "./remove-price-lists"
|
||||
export * from "./delete-price-lists"
|
||||
export * from "./remove-price-list-prices"
|
||||
export * from "./remove-product-prices"
|
||||
export * from "./remove-variant-prices"
|
||||
export * from "./update-price-lists"
|
||||
export * from "./upsert-price-list-prices"
|
||||
@@ -0,0 +1,12 @@
|
||||
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
|
||||
import { removePriceListPricesStep } from "../steps"
|
||||
|
||||
type WorkflowInput = { ids: string[] }
|
||||
|
||||
export const removePriceListPricesWorkflowId = "remove-price-list-prices"
|
||||
export const removePriceListPricesWorkflow = createWorkflow(
|
||||
removePriceListPricesWorkflowId,
|
||||
(input: WorkflowData<WorkflowInput>): WorkflowData<void> => {
|
||||
removePriceListPricesStep(input.ids)
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,47 @@
|
||||
import { UpdatePriceListWorkflowInputDTO } from "@medusajs/types"
|
||||
import {
|
||||
WorkflowData,
|
||||
createWorkflow,
|
||||
parallelize,
|
||||
transform,
|
||||
} from "@medusajs/workflows-sdk"
|
||||
import {
|
||||
updatePriceListsStep,
|
||||
upsertPriceListPricesStep,
|
||||
validatePriceListsStep,
|
||||
validateVariantPriceLinksStep,
|
||||
} from "../steps"
|
||||
|
||||
type WorkflowInput = { price_lists_data: UpdatePriceListWorkflowInputDTO[] }
|
||||
|
||||
export const updatePriceListsWorkflowId = "update-price-lists"
|
||||
export const updatePriceListsWorkflow = createWorkflow(
|
||||
updatePriceListsWorkflowId,
|
||||
(input: WorkflowData<WorkflowInput>): WorkflowData<void> => {
|
||||
const [priceListsMap, variantPriceMap] = parallelize(
|
||||
validatePriceListsStep(input.price_lists_data),
|
||||
validateVariantPriceLinksStep(input.price_lists_data)
|
||||
)
|
||||
|
||||
const updatePricesInput = transform(
|
||||
{ priceListsMap, variantPriceMap, input },
|
||||
(data) => ({
|
||||
data: data.input.price_lists_data,
|
||||
price_lists_map: data.priceListsMap,
|
||||
variant_price_map: data.variantPriceMap,
|
||||
})
|
||||
)
|
||||
|
||||
upsertPriceListPricesStep(updatePricesInput)
|
||||
|
||||
const updatePriceListInput = transform({ input }, (data) => {
|
||||
return data.input.price_lists_data.map((priceListData) => {
|
||||
delete priceListData.prices
|
||||
|
||||
return priceListData
|
||||
})
|
||||
})
|
||||
|
||||
updatePriceListsStep(updatePriceListInput)
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,31 @@
|
||||
import { UpdatePriceListWorkflowInputDTO } from "@medusajs/types"
|
||||
import {
|
||||
WorkflowData,
|
||||
createWorkflow,
|
||||
parallelize,
|
||||
} from "@medusajs/workflows-sdk"
|
||||
import {
|
||||
upsertPriceListPricesStep,
|
||||
validatePriceListsStep,
|
||||
validateVariantPriceLinksStep,
|
||||
} from "../steps"
|
||||
|
||||
type WorkflowInput = {
|
||||
price_lists_data: Pick<UpdatePriceListWorkflowInputDTO, "id" | "prices">[]
|
||||
}
|
||||
|
||||
export const upsertPriceListPricesWorkflowId = "upsert-price-list-prices"
|
||||
export const upsertPriceListPricesWorkflow = createWorkflow(
|
||||
upsertPriceListPricesWorkflowId,
|
||||
(input: WorkflowData<WorkflowInput>): WorkflowData<void> => {
|
||||
const [_, variantPriceMap] = parallelize(
|
||||
validatePriceListsStep(input.price_lists_data),
|
||||
validateVariantPriceLinksStep(input.price_lists_data)
|
||||
)
|
||||
|
||||
upsertPriceListPricesStep({
|
||||
data: input.price_lists_data,
|
||||
variant_price_map: variantPriceMap,
|
||||
})
|
||||
}
|
||||
)
|
||||
Reference in new issue
Block a user