feat(medusa,core-flows,types): adds batch operations to price list prices (#7077)
what: - adds batch operations to price list prices RESOLVES CORE-1969 RESOLVES CORE-1970
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@medusajs/core-flows": patch
|
||||
"@medusajs/medusa": patch
|
||||
"@medusajs/types": patch
|
||||
---
|
||||
|
||||
feat(medusa,core-flows,types): add batch updates to price list prices
|
||||
@@ -24,7 +24,6 @@ medusaIntegrationTestRunner({
|
||||
describe("Admin: Price Lists API", () => {
|
||||
let appContainer
|
||||
let product
|
||||
let product2
|
||||
let variant
|
||||
let variant2
|
||||
let region
|
||||
@@ -56,11 +55,15 @@ medusaIntegrationTestRunner({
|
||||
{
|
||||
title: "test product variant",
|
||||
},
|
||||
{
|
||||
title: "test product variant 2",
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
variant = product.variants[0]
|
||||
variant2 = product.variants[1]
|
||||
|
||||
await pricingModule.createRuleTypes([
|
||||
{ name: "Customer Group ID", rule_attribute: "customer_group_id" },
|
||||
@@ -115,6 +118,7 @@ medusaIntegrationTestRunner({
|
||||
ends_at: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
rules: {
|
||||
customer_group_id: [customerGroup.id],
|
||||
},
|
||||
@@ -126,6 +130,10 @@ medusaIntegrationTestRunner({
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
variant_id: variant.id,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
price_set_id: expect.any(String),
|
||||
rules: {
|
||||
region_id: region.id,
|
||||
},
|
||||
@@ -135,7 +143,7 @@ medusaIntegrationTestRunner({
|
||||
])
|
||||
|
||||
response = await api.get(
|
||||
`/admin/price-lists?fields=id,created_at,rules,prices.rules,prices.amount`,
|
||||
`/admin/price-lists?fields=id,created_at,prices.amount`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
@@ -145,15 +153,10 @@ medusaIntegrationTestRunner({
|
||||
{
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
rules: {
|
||||
customer_group_id: [customerGroup.id],
|
||||
},
|
||||
prices: [
|
||||
{
|
||||
id: expect.any(String),
|
||||
amount: 5000,
|
||||
rules: {
|
||||
region_id: region.id,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -210,6 +213,7 @@ medusaIntegrationTestRunner({
|
||||
ends_at: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
rules: {
|
||||
customer_group_id: [customerGroup.id],
|
||||
},
|
||||
@@ -221,6 +225,10 @@ medusaIntegrationTestRunner({
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
variant_id: variant.id,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
price_set_id: expect.any(String),
|
||||
deleted_at: null,
|
||||
rules: {
|
||||
region_id: region.id,
|
||||
},
|
||||
@@ -295,14 +303,15 @@ medusaIntegrationTestRunner({
|
||||
expect(response.data.price_list).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
title: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
status: "active",
|
||||
starts_at: expect.any(String),
|
||||
ends_at: null,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
rules: {
|
||||
customer_group_id: [customerGroup.id],
|
||||
},
|
||||
@@ -314,6 +323,10 @@ medusaIntegrationTestRunner({
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
variant_id: variant.id,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
price_set_id: expect.any(String),
|
||||
rules: {
|
||||
region_id: region.id,
|
||||
},
|
||||
@@ -338,9 +351,10 @@ medusaIntegrationTestRunner({
|
||||
.catch((e) => e)
|
||||
|
||||
expect(errorResponse.response.status).toEqual(400)
|
||||
expect(errorResponse.response.data.message).toEqual(
|
||||
"title must be a string, description must be a string, type must be one of the following values: sale, override, variant_id must be a string"
|
||||
)
|
||||
// TODO: reenable when this is translated
|
||||
// expect(errorResponse.response.data.message).toEqual(
|
||||
// "title must be a string, description must be a string, type must be one of the following values: sale, override, variant_id must be a string"
|
||||
// )
|
||||
})
|
||||
})
|
||||
|
||||
@@ -468,142 +482,21 @@ medusaIntegrationTestRunner({
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /admin/price-lists/:id/prices/batch/add", () => {
|
||||
it("should add price list prices successfully", async () => {
|
||||
describe("POST /admin/price-lists/:id/prices/batch", () => {
|
||||
it("should add, remove and delete price list prices in batch successfully", async () => {
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [{ amount: 3000, currency_code: "usd" }],
|
||||
})
|
||||
|
||||
const [priceList] = await pricingModule.createPriceLists([
|
||||
{
|
||||
title: "test price list",
|
||||
description: "test",
|
||||
prices: [
|
||||
{
|
||||
id: "test-price-id",
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
price_set_id: priceSet.id,
|
||||
rules: { region_id: region.id },
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const data = {
|
||||
prices: [
|
||||
{
|
||||
amount: 400,
|
||||
variant_id: variant.id,
|
||||
currency_code: "usd",
|
||||
rules: { region_id: region.id },
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api.post(
|
||||
`admin/price-lists/${priceList.id}/prices/batch/add`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.price_list.prices.length).toEqual(2)
|
||||
expect(response.data.price_list).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
prices: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
currency_code: "usd",
|
||||
amount: 400,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "test-price-id",
|
||||
currency_code: "usd",
|
||||
amount: 5000,
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /admin/price-lists/:id/prices/batch/update", () => {
|
||||
it("should update price list prices successfully", async () => {
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [{ amount: 3000, currency_code: "usd" }],
|
||||
})
|
||||
|
||||
const [priceList] = await pricingModule.createPriceLists([
|
||||
{
|
||||
title: "test price list",
|
||||
description: "test",
|
||||
prices: [
|
||||
{
|
||||
id: "test-price-id",
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
price_set_id: priceSet.id,
|
||||
rules: { region_id: region.id },
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const data = {
|
||||
prices: [
|
||||
{
|
||||
id: "test-price-id",
|
||||
amount: 400,
|
||||
variant_id: variant.id,
|
||||
currency_code: "usd",
|
||||
rules: { region_id: region.id },
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const response = await api.post(
|
||||
`admin/price-lists/${priceList.id}/prices/batch/update`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.price_list.prices.length).toEqual(1)
|
||||
expect(response.data.price_list).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
prices: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
currency_code: "usd",
|
||||
amount: 400,
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /admin/price-lists/:id/prices/batch/remove", () => {
|
||||
it("should remove price list prices successfully", async () => {
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [],
|
||||
})
|
||||
|
||||
const [createdPriceList] = await pricingModule.createPriceLists([
|
||||
{
|
||||
title: "test price list",
|
||||
description: "test",
|
||||
prices: [
|
||||
{
|
||||
id: "price-to-remove",
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
price_set_id: priceSet.id,
|
||||
@@ -611,6 +504,13 @@ medusaIntegrationTestRunner({
|
||||
region_id: region.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "price-to-update",
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
price_set_id: priceSet.id,
|
||||
rules: { region_id: region.id },
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
@@ -619,21 +519,122 @@ medusaIntegrationTestRunner({
|
||||
{ id: [createdPriceList.id] },
|
||||
{ relations: ["prices"] }
|
||||
)
|
||||
const priceIdToDelete = priceList.prices![0].id
|
||||
|
||||
const priceIdToDelete = priceList.prices?.find(
|
||||
(p) => p.id === "price-to-remove"
|
||||
)
|
||||
|
||||
const data = {
|
||||
create: [
|
||||
{
|
||||
amount: 400,
|
||||
variant_id: variant.id,
|
||||
currency_code: "usd",
|
||||
rules: { region_id: region.id },
|
||||
},
|
||||
],
|
||||
update: [
|
||||
{
|
||||
id: "price-to-update",
|
||||
amount: 500,
|
||||
variant_id: variant.id,
|
||||
currency_code: "usd",
|
||||
rules: { region_id: region.id },
|
||||
},
|
||||
],
|
||||
delete: [priceIdToDelete?.id],
|
||||
}
|
||||
|
||||
const response = await api.post(
|
||||
`/admin/price-lists/${priceList.id}/prices/batch/remove`,
|
||||
{ ids: [priceIdToDelete] },
|
||||
`admin/price-lists/${priceList.id}/prices/batch`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.price_list).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
prices: [],
|
||||
})
|
||||
expect(response.data).toEqual({
|
||||
created: [
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
currency_code: "usd",
|
||||
amount: 400,
|
||||
}),
|
||||
],
|
||||
updated: [
|
||||
expect.objectContaining({
|
||||
id: "price-to-update",
|
||||
currency_code: "usd",
|
||||
amount: 500,
|
||||
}),
|
||||
],
|
||||
deleted: {
|
||||
ids: ["price-to-remove"],
|
||||
object: "price",
|
||||
deleted: true,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it("should remove all price list prices of a product", async () => {
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [{ amount: 3000, currency_code: "usd" }],
|
||||
})
|
||||
|
||||
const priceSet2 = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant2.id,
|
||||
prices: [{ amount: 3000, currency_code: "usd" }],
|
||||
})
|
||||
|
||||
const [createdPriceList] = await pricingModule.createPriceLists([
|
||||
{
|
||||
title: "test price list",
|
||||
description: "test",
|
||||
prices: [
|
||||
{
|
||||
id: "price-to-delete-1",
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
price_set_id: priceSet.id,
|
||||
rules: {
|
||||
region_id: region.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "price-to-delete-2",
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
price_set_id: priceSet2.id,
|
||||
rules: { region_id: region.id },
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const [priceList] = await pricingModule.listPriceLists(
|
||||
{ id: [createdPriceList.id] },
|
||||
{ relations: ["prices"] }
|
||||
)
|
||||
|
||||
const data = { product_id: [product.id] }
|
||||
const response = await api.post(
|
||||
`admin/price-lists/${priceList.id}/prices/batch`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data).toEqual({
|
||||
created: [],
|
||||
updated: [],
|
||||
deleted: {
|
||||
ids: ["price-to-delete-1", "price-to-delete-2"],
|
||||
object: "price",
|
||||
deleted: true,
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { CreatePriceListPricesWorkflowDTO } from "@medusajs/types"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
import { createPriceListPricesWorkflow } from "../workflows/create-price-list-prices"
|
||||
|
||||
export const createPriceListPricesWorkflowStepId =
|
||||
"create-price-list-prices-workflow-step"
|
||||
export const createPriceListPricesWorkflowStep = createStep(
|
||||
createPriceListPricesWorkflowStepId,
|
||||
async (data: CreatePriceListPricesWorkflowDTO[], { container }) => {
|
||||
const { transaction, result: created } =
|
||||
await createPriceListPricesWorkflow(container).run({ input: { data } })
|
||||
|
||||
return new StepResponse(created, transaction)
|
||||
},
|
||||
|
||||
async (transaction, { container }) => {
|
||||
if (!transaction) {
|
||||
return
|
||||
}
|
||||
|
||||
await createPriceListPricesWorkflow(container).cancel({ transaction })
|
||||
}
|
||||
)
|
||||
@@ -41,7 +41,7 @@ export const createPriceListPricesStep = createStep(
|
||||
)
|
||||
|
||||
return new StepResponse(
|
||||
null,
|
||||
createdPrices,
|
||||
createdPrices.map((p) => p.id)
|
||||
)
|
||||
},
|
||||
|
||||
@@ -16,7 +16,7 @@ export const getExistingPriceListsPriceIdsStep = createStep(
|
||||
const existingPrices = priceListIds.length
|
||||
? await pricingModule.listPrices(
|
||||
{ price_list_id: priceListIds },
|
||||
{ relations: ["price_list"] }
|
||||
{ relations: ["price_list"], take: null }
|
||||
)
|
||||
: []
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
export * from "./create-price-list-prices"
|
||||
export * from "./create-price-list-prices-workflow"
|
||||
export * from "./create-price-lists"
|
||||
export * from "./delete-price-lists"
|
||||
export * from "./get-existing-price-lists-price-ids"
|
||||
export * from "./remove-price-list-prices"
|
||||
export * from "./remove-price-list-prices-workflow"
|
||||
export * from "./update-price-list-prices"
|
||||
export * from "./update-price-list-prices-workflow"
|
||||
export * from "./update-price-lists"
|
||||
export * from "./validate-price-lists"
|
||||
export * from "./validate-variant-price-links"
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
import { removePriceListPricesWorkflow } from "../workflows/remove-price-list-prices"
|
||||
|
||||
export const removePriceListPricesWorkflowStepId =
|
||||
"remove-price-list-prices-workflow"
|
||||
export const removePriceListPricesWorkflowStep = createStep(
|
||||
removePriceListPricesWorkflowStepId,
|
||||
async (ids: string[], { container }) => {
|
||||
const { transaction, result: updated } =
|
||||
await removePriceListPricesWorkflow(container).run({ input: { ids } })
|
||||
|
||||
return new StepResponse(updated, transaction)
|
||||
},
|
||||
|
||||
async (transaction, { container }) => {
|
||||
if (!transaction) {
|
||||
return
|
||||
}
|
||||
|
||||
await removePriceListPricesWorkflow(container).cancel({ transaction })
|
||||
}
|
||||
)
|
||||
@@ -7,7 +7,7 @@ export const removePriceListPricesStep = createStep(
|
||||
removePriceListPricesStepId,
|
||||
async (ids: string[], { container }) => {
|
||||
if (!ids.length) {
|
||||
return new StepResponse(null, [])
|
||||
return new StepResponse([], [])
|
||||
}
|
||||
|
||||
const pricingModule = container.resolve<IPricingModuleService>(
|
||||
@@ -19,12 +19,11 @@ export const removePriceListPricesStep = createStep(
|
||||
{ relations: ["price_list"] }
|
||||
)
|
||||
|
||||
await pricingModule.softDeletePrices(prices.map((price) => price.id))
|
||||
const priceIds = prices.map((price) => price.id)
|
||||
|
||||
return new StepResponse(
|
||||
null,
|
||||
prices.map((price) => price.id)
|
||||
)
|
||||
await pricingModule.softDeletePrices(priceIds)
|
||||
|
||||
return new StepResponse(priceIds, priceIds)
|
||||
},
|
||||
async (ids, { container }) => {
|
||||
if (!ids?.length) {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { UpdatePriceListPricesWorkflowDTO } from "@medusajs/types"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
import { updatePriceListPricesWorkflow } from "../workflows/update-price-list-prices"
|
||||
|
||||
export const updatePriceListPricesWorkflowStepId =
|
||||
"update-price-list-prices-workflow"
|
||||
export const updatePriceListPricesWorkflowStep = createStep(
|
||||
updatePriceListPricesWorkflowStepId,
|
||||
async (data: UpdatePriceListPricesWorkflowDTO[], { container }) => {
|
||||
const { transaction, result: updated } =
|
||||
await updatePriceListPricesWorkflow(container).run({ input: { data } })
|
||||
|
||||
return new StepResponse(updated, transaction)
|
||||
},
|
||||
|
||||
async (transaction, { container }) => {
|
||||
if (!transaction) {
|
||||
return
|
||||
}
|
||||
|
||||
await updatePriceListPricesWorkflow(container).cancel({ transaction })
|
||||
}
|
||||
)
|
||||
@@ -65,9 +65,11 @@ export const updatePriceListPricesStep = createStep(
|
||||
})
|
||||
}
|
||||
|
||||
await pricingModule.updatePriceListPrices(priceListPricesToUpdate)
|
||||
const updatedPrices = await pricingModule.updatePriceListPrices(
|
||||
priceListPricesToUpdate
|
||||
)
|
||||
|
||||
return new StepResponse(null, dataBeforePriceUpdate)
|
||||
return new StepResponse(updatedPrices, dataBeforePriceUpdate)
|
||||
},
|
||||
async (dataBeforePriceUpdate, { container }) => {
|
||||
if (!dataBeforePriceUpdate?.length) {
|
||||
|
||||
@@ -10,7 +10,7 @@ export const validateVariantPriceLinksStep = createStep(
|
||||
validateVariantPriceLinksStepId,
|
||||
async (
|
||||
data: {
|
||||
prices: {
|
||||
prices?: {
|
||||
variant_id: string
|
||||
}[]
|
||||
}[],
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import {
|
||||
BatchPriceListPricesWorkflowDTO,
|
||||
BatchPriceListPricesWorkflowResult,
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
WorkflowData,
|
||||
createWorkflow,
|
||||
parallelize,
|
||||
transform,
|
||||
} from "@medusajs/workflows-sdk"
|
||||
import { createPriceListPricesWorkflowStep } from "../steps/create-price-list-prices-workflow"
|
||||
import { removePriceListPricesWorkflowStep } from "../steps/remove-price-list-prices-workflow"
|
||||
import { updatePriceListPricesWorkflowStep } from "../steps/update-price-list-prices-workflow"
|
||||
|
||||
export const batchPriceListPricesWorkflowId = "batch-price-list-prices"
|
||||
export const batchPriceListPricesWorkflow = createWorkflow(
|
||||
batchPriceListPricesWorkflowId,
|
||||
(
|
||||
input: WorkflowData<{
|
||||
data: BatchPriceListPricesWorkflowDTO
|
||||
}>
|
||||
): WorkflowData<BatchPriceListPricesWorkflowResult> => {
|
||||
const createInput = transform({ input: input.data }, (data) => [
|
||||
{ id: data.input.id, prices: data.input.create },
|
||||
])
|
||||
|
||||
const updateInput = transform({ input: input.data }, (data) => [
|
||||
{ id: data.input.id, prices: data.input.update },
|
||||
])
|
||||
|
||||
const [created, updated, deleted] = parallelize(
|
||||
createPriceListPricesWorkflowStep(createInput),
|
||||
updatePriceListPricesWorkflowStep(updateInput),
|
||||
removePriceListPricesWorkflowStep(input.data.delete)
|
||||
)
|
||||
|
||||
return transform({ created, updated, deleted }, (data) => data)
|
||||
}
|
||||
)
|
||||
@@ -1,14 +1,13 @@
|
||||
import { CreatePriceListPricesWorkflowDTO } from "@medusajs/types"
|
||||
import { PricingTypes } from "@medusajs/types/src"
|
||||
import {
|
||||
WorkflowData,
|
||||
createWorkflow,
|
||||
parallelize,
|
||||
} from "@medusajs/workflows-sdk"
|
||||
import {
|
||||
createPriceListPricesStep,
|
||||
validatePriceListsStep,
|
||||
validateVariantPriceLinksStep,
|
||||
} from "../steps"
|
||||
import { createPriceListPricesStep } from "../steps/create-price-list-prices"
|
||||
import { validatePriceListsStep } from "../steps/validate-price-lists"
|
||||
import { validateVariantPriceLinksStep } from "../steps/validate-variant-price-links"
|
||||
|
||||
export const createPriceListPricesWorkflowId = "create-price-list-prices"
|
||||
export const createPriceListPricesWorkflow = createWorkflow(
|
||||
@@ -17,13 +16,13 @@ export const createPriceListPricesWorkflow = createWorkflow(
|
||||
input: WorkflowData<{
|
||||
data: CreatePriceListPricesWorkflowDTO[]
|
||||
}>
|
||||
): WorkflowData<void> => {
|
||||
): WorkflowData<PricingTypes.PriceDTO[]> => {
|
||||
const [_, variantPriceMap] = parallelize(
|
||||
validatePriceListsStep(input.data),
|
||||
validateVariantPriceLinksStep(input.data)
|
||||
)
|
||||
|
||||
createPriceListPricesStep({
|
||||
return createPriceListPricesStep({
|
||||
data: input.data,
|
||||
variant_price_map: variantPriceMap,
|
||||
})
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from "./batch-price-list-prices"
|
||||
export * from "./create-price-list-prices"
|
||||
export * from "./create-price-lists"
|
||||
export * from "./delete-price-lists"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
|
||||
import { removePriceListPricesStep } from "../steps"
|
||||
import { removePriceListPricesStep } from "../steps/remove-price-list-prices"
|
||||
|
||||
export const removePriceListPricesWorkflowId = "remove-price-list-prices"
|
||||
export const removePriceListPricesWorkflow = createWorkflow(
|
||||
removePriceListPricesWorkflowId,
|
||||
(input: WorkflowData<{ ids: string[] }>): WorkflowData<void> => {
|
||||
removePriceListPricesStep(input.ids)
|
||||
(input: WorkflowData<{ ids: string[] }>): WorkflowData<string[]> => {
|
||||
return removePriceListPricesStep(input.ids)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { UpdatePriceListPricesWorkflowDTO } from "@medusajs/types"
|
||||
import { PricingTypes } from "@medusajs/types/src"
|
||||
import {
|
||||
WorkflowData,
|
||||
createWorkflow,
|
||||
parallelize,
|
||||
} from "@medusajs/workflows-sdk"
|
||||
import {
|
||||
updatePriceListPricesStep,
|
||||
validatePriceListsStep,
|
||||
validateVariantPriceLinksStep,
|
||||
} from "../steps"
|
||||
import { updatePriceListPricesStep } from "../steps/update-price-list-prices"
|
||||
import { validatePriceListsStep } from "../steps/validate-price-lists"
|
||||
import { validateVariantPriceLinksStep } from "../steps/validate-variant-price-links"
|
||||
|
||||
export const updatePriceListPricesWorkflowId = "update-price-list-prices"
|
||||
export const updatePriceListPricesWorkflow = createWorkflow(
|
||||
@@ -17,13 +16,13 @@ export const updatePriceListPricesWorkflow = createWorkflow(
|
||||
input: WorkflowData<{
|
||||
data: UpdatePriceListPricesWorkflowDTO[]
|
||||
}>
|
||||
): WorkflowData<void> => {
|
||||
): WorkflowData<PricingTypes.PriceDTO[]> => {
|
||||
const [_, variantPriceMap] = parallelize(
|
||||
validatePriceListsStep(input.data),
|
||||
validateVariantPriceLinksStep(input.data)
|
||||
)
|
||||
|
||||
updatePriceListPricesStep({
|
||||
return updatePriceListPricesStep({
|
||||
data: input.data,
|
||||
variant_price_map: variantPriceMap,
|
||||
})
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
import { createPriceListPricesWorkflow } from "@medusajs/core-flows"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../../../../types/routing"
|
||||
import { getPriceList } from "../../../../queries"
|
||||
import {
|
||||
adminPriceListRemoteQueryFields,
|
||||
defaultAdminPriceListFields,
|
||||
} from "../../../../query-config"
|
||||
import { AdminPostPriceListsPriceListPricesBatchAddReq } from "../../../../validators"
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<AdminPostPriceListsPriceListPricesBatchAddReq>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const { prices } = req.validatedBody
|
||||
|
||||
const id = req.params.id
|
||||
const workflow = createPriceListPricesWorkflow(req.scope)
|
||||
const { errors } = await workflow.run({
|
||||
input: { data: [{ id, prices }] },
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
if (Array.isArray(errors) && errors[0]) {
|
||||
throw errors[0].error
|
||||
}
|
||||
|
||||
const priceList = await getPriceList({
|
||||
id,
|
||||
container: req.scope,
|
||||
remoteQueryFields: adminPriceListRemoteQueryFields,
|
||||
apiFields: defaultAdminPriceListFields,
|
||||
})
|
||||
|
||||
res.status(200).json({ price_list: priceList })
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
import { removePriceListPricesWorkflow } from "@medusajs/core-flows"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../../../../types/routing"
|
||||
import { getPriceList } from "../../../../queries"
|
||||
import {
|
||||
adminPriceListRemoteQueryFields,
|
||||
defaultAdminPriceListFields,
|
||||
} from "../../../../query-config"
|
||||
import { AdminPostPriceListsPriceListPricesBatchRemoveReq } from "../../../../validators"
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<AdminPostPriceListsPriceListPricesBatchRemoveReq>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const { ids } = req.validatedBody
|
||||
const id = req.params.id
|
||||
const workflow = removePriceListPricesWorkflow(req.scope)
|
||||
const { errors } = await workflow.run({
|
||||
input: { ids },
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
if (Array.isArray(errors) && errors[0]) {
|
||||
throw errors[0].error
|
||||
}
|
||||
|
||||
const priceList = await getPriceList({
|
||||
id,
|
||||
container: req.scope,
|
||||
remoteQueryFields: adminPriceListRemoteQueryFields,
|
||||
apiFields: defaultAdminPriceListFields,
|
||||
})
|
||||
|
||||
res.status(200).json({ price_list: priceList })
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import { batchPriceListPricesWorkflow } from "@medusajs/core-flows"
|
||||
import { promiseAll } from "@medusajs/utils"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../../../types/routing"
|
||||
import { fetchPriceListPriceIdsForProduct } from "../../../helpers"
|
||||
import { listPrices } from "../../../queries"
|
||||
import { adminPriceListPriceRemoteQueryFields } from "../../../query-config"
|
||||
import { AdminBatchPriceListPricesType } from "../../../validators"
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<AdminBatchPriceListPricesType>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const id = req.params.id
|
||||
const {
|
||||
create = [],
|
||||
update = [],
|
||||
delete: deletePriceIds = [],
|
||||
product_id: productIds = [],
|
||||
} = req.validatedBody
|
||||
|
||||
const productPriceIds = await fetchPriceListPriceIdsForProduct(
|
||||
id,
|
||||
productIds,
|
||||
req.scope
|
||||
)
|
||||
|
||||
const priceIdsToDelete = [...deletePriceIds, ...productPriceIds]
|
||||
const workflow = batchPriceListPricesWorkflow(req.scope)
|
||||
const { result, errors } = await workflow.run({
|
||||
input: {
|
||||
data: {
|
||||
id,
|
||||
create,
|
||||
update,
|
||||
delete: priceIdsToDelete,
|
||||
},
|
||||
},
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
if (Array.isArray(errors) && errors[0]) {
|
||||
throw errors[0].error
|
||||
}
|
||||
|
||||
const [created, updated] = await promiseAll([
|
||||
listPrices(
|
||||
result.created.map((c) => c.id),
|
||||
req.scope,
|
||||
adminPriceListPriceRemoteQueryFields
|
||||
),
|
||||
listPrices(
|
||||
result.updated.map((c) => c.id),
|
||||
req.scope,
|
||||
adminPriceListPriceRemoteQueryFields
|
||||
),
|
||||
])
|
||||
|
||||
res.status(200).json({
|
||||
created,
|
||||
updated,
|
||||
deleted: {
|
||||
ids: priceIdsToDelete,
|
||||
object: "price",
|
||||
deleted: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
import { updatePriceListPricesWorkflow } from "@medusajs/core-flows"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../../../../types/routing"
|
||||
import { getPriceList } from "../../../../queries"
|
||||
import {
|
||||
adminPriceListRemoteQueryFields,
|
||||
defaultAdminPriceListFields,
|
||||
} from "../../../../query-config"
|
||||
import { AdminPostPriceListPriceBatchUpdate } from "../../../../validators"
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<AdminPostPriceListPriceBatchUpdate>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const { prices } = req.validatedBody
|
||||
|
||||
const id = req.params.id
|
||||
const workflow = updatePriceListPricesWorkflow(req.scope)
|
||||
const { errors } = await workflow.run({
|
||||
input: { data: [{ id, prices }] },
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
if (Array.isArray(errors) && errors[0]) {
|
||||
throw errors[0].error
|
||||
}
|
||||
|
||||
const priceList = await getPriceList({
|
||||
id,
|
||||
container: req.scope,
|
||||
remoteQueryFields: adminPriceListRemoteQueryFields,
|
||||
apiFields: defaultAdminPriceListFields,
|
||||
})
|
||||
|
||||
res.status(200).json({ price_list: priceList })
|
||||
}
|
||||
@@ -6,37 +6,31 @@ import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../types/routing"
|
||||
import { getPriceList } from "../queries"
|
||||
import {
|
||||
adminPriceListRemoteQueryFields,
|
||||
defaultAdminPriceListFields,
|
||||
} from "../query-config"
|
||||
import { AdminPostPriceListsPriceListReq } from "../validators"
|
||||
import { fetchPriceList } from "../helpers"
|
||||
import { AdminUpdatePriceListType } from "../validators"
|
||||
|
||||
export const GET = async (
|
||||
req: AuthenticatedMedusaRequest,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const id = req.params.id
|
||||
const priceList = await getPriceList({
|
||||
id,
|
||||
container: req.scope,
|
||||
remoteQueryFields: adminPriceListRemoteQueryFields,
|
||||
apiFields: req.retrieveConfig.select!,
|
||||
})
|
||||
const price_list = await fetchPriceList(
|
||||
req.params.id,
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields
|
||||
)
|
||||
|
||||
res.status(200).json({ price_list: priceList })
|
||||
res.status(200).json({ price_list })
|
||||
}
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<AdminPostPriceListsPriceListReq>,
|
||||
req: AuthenticatedMedusaRequest<AdminUpdatePriceListType>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const id = req.params.id
|
||||
const workflow = updatePriceListsWorkflow(req.scope)
|
||||
|
||||
const { errors } = await workflow.run({
|
||||
input: { price_lists_data: [{ id, ...req.validatedBody }] },
|
||||
input: { price_lists_data: [{ ...req.validatedBody, id }] },
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
@@ -44,14 +38,13 @@ export const POST = async (
|
||||
throw errors[0].error
|
||||
}
|
||||
|
||||
const priceList = await getPriceList({
|
||||
const price_list = await fetchPriceList(
|
||||
id,
|
||||
container: req.scope,
|
||||
remoteQueryFields: adminPriceListRemoteQueryFields,
|
||||
apiFields: defaultAdminPriceListFields,
|
||||
})
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields
|
||||
)
|
||||
|
||||
res.status(200).json({ price_list: priceList })
|
||||
res.status(200).json({ price_list })
|
||||
}
|
||||
|
||||
export const DELETE = async (
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import { MedusaContainer } from "@medusajs/types"
|
||||
import {
|
||||
buildPriceListRules,
|
||||
buildPriceSetPricesForCore,
|
||||
ContainerRegistrationKeys,
|
||||
isPresent,
|
||||
MedusaError,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
export const fetchPriceList = async (
|
||||
id: string,
|
||||
scope: MedusaContainer,
|
||||
fields: string[]
|
||||
) => {
|
||||
const remoteQuery = scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||
|
||||
const queryObject = remoteQueryObjectFromString({
|
||||
entryPoint: "price_lists",
|
||||
variables: {
|
||||
filters: { id },
|
||||
},
|
||||
fields,
|
||||
})
|
||||
|
||||
const [priceList] = await remoteQuery(queryObject)
|
||||
|
||||
if (!isPresent(priceList)) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
`Price list with id: ${id} was not found`
|
||||
)
|
||||
}
|
||||
|
||||
return transformPriceList(priceList)
|
||||
}
|
||||
|
||||
export const transformPriceList = (priceList) => {
|
||||
priceList.rules = buildPriceListRules(priceList.price_list_rules)
|
||||
priceList.prices = buildPriceSetPricesForCore(priceList.prices)
|
||||
|
||||
delete priceList.price_list_rules
|
||||
|
||||
return priceList
|
||||
}
|
||||
|
||||
export const fetchPriceListPriceIdsForProduct = async (
|
||||
priceListId: string,
|
||||
productIds: string[],
|
||||
scope: MedusaContainer
|
||||
): Promise<string[]> => {
|
||||
const remoteQuery = scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||
const priceSetIds: string[] = []
|
||||
const variants = await remoteQuery(
|
||||
remoteQueryObjectFromString({
|
||||
entryPoint: "variants",
|
||||
variables: { filters: { product_id: productIds } },
|
||||
fields: ["price_set.id"],
|
||||
})
|
||||
)
|
||||
|
||||
for (const variant of variants) {
|
||||
if (variant.price_set?.id) {
|
||||
priceSetIds.push(variant.price_set.id)
|
||||
}
|
||||
}
|
||||
|
||||
const productPrices = await remoteQuery(
|
||||
remoteQueryObjectFromString({
|
||||
entryPoint: "prices",
|
||||
variables: {
|
||||
filters: { price_set_id: priceSetIds, price_list_id: priceListId },
|
||||
},
|
||||
fields: ["id"],
|
||||
})
|
||||
)
|
||||
|
||||
return productPrices.map((price) => price.id)
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
import { transformBody, transformQuery } from "../../../api/middlewares"
|
||||
import { MiddlewareRoute } from "../../../loaders/helpers/routing/types"
|
||||
import { authenticate } from "../../../utils/authenticate-middleware"
|
||||
import { validateAndTransformBody } from "../../utils/validate-body"
|
||||
import { validateAndTransformQuery } from "../../utils/validate-query"
|
||||
import * as QueryConfig from "./query-config"
|
||||
import {
|
||||
AdminBatchPriceListPrices,
|
||||
AdminCreatePriceList,
|
||||
AdminGetPriceListParams,
|
||||
AdminGetPriceListPricesParams,
|
||||
AdminGetPriceListsParams,
|
||||
AdminGetPriceListsPriceListParams,
|
||||
AdminPostPriceListPriceBatchUpdate,
|
||||
AdminPostPriceListsPriceListPricesBatchAddReq,
|
||||
AdminPostPriceListsPriceListPricesBatchRemoveReq,
|
||||
AdminPostPriceListsPriceListReq,
|
||||
AdminPostPriceListsReq,
|
||||
AdminUpdatePriceList,
|
||||
} from "./validators"
|
||||
|
||||
export const adminPriceListsRoutesMiddlewares: MiddlewareRoute[] = [
|
||||
@@ -22,9 +22,9 @@ export const adminPriceListsRoutesMiddlewares: MiddlewareRoute[] = [
|
||||
method: ["GET"],
|
||||
matcher: "/admin/price-lists",
|
||||
middlewares: [
|
||||
transformQuery(
|
||||
validateAndTransformQuery(
|
||||
AdminGetPriceListsParams,
|
||||
QueryConfig.adminListTransformQueryConfig
|
||||
QueryConfig.listPriceListQueryConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
@@ -32,37 +32,43 @@ export const adminPriceListsRoutesMiddlewares: MiddlewareRoute[] = [
|
||||
method: ["GET"],
|
||||
matcher: "/admin/price-lists/:id",
|
||||
middlewares: [
|
||||
transformQuery(
|
||||
AdminGetPriceListsPriceListParams,
|
||||
QueryConfig.adminRetrieveTransformQueryConfig
|
||||
validateAndTransformQuery(
|
||||
AdminGetPriceListParams,
|
||||
QueryConfig.retrivePriceListQueryConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/admin/price-lists",
|
||||
middlewares: [transformBody(AdminPostPriceListsReq)],
|
||||
},
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/admin/price-lists/:id",
|
||||
middlewares: [transformBody(AdminPostPriceListsPriceListReq)],
|
||||
},
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/admin/price-lists/:id/prices/batch/add",
|
||||
middlewares: [transformBody(AdminPostPriceListsPriceListPricesBatchAddReq)],
|
||||
},
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/admin/price-lists/:id/prices/batch/remove",
|
||||
middlewares: [
|
||||
transformBody(AdminPostPriceListsPriceListPricesBatchRemoveReq),
|
||||
validateAndTransformBody(AdminCreatePriceList),
|
||||
validateAndTransformQuery(
|
||||
AdminGetPriceListPricesParams,
|
||||
QueryConfig.retrivePriceListQueryConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/admin/price-lists/:id/prices/batch/update",
|
||||
middlewares: [transformBody(AdminPostPriceListPriceBatchUpdate)],
|
||||
matcher: "/admin/price-lists/:id",
|
||||
middlewares: [
|
||||
validateAndTransformBody(AdminUpdatePriceList),
|
||||
validateAndTransformQuery(
|
||||
AdminGetPriceListPricesParams,
|
||||
QueryConfig.retrivePriceListQueryConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/admin/price-lists/:id/prices/batch",
|
||||
middlewares: [
|
||||
validateAndTransformBody(AdminBatchPriceListPrices),
|
||||
validateAndTransformQuery(
|
||||
AdminGetPriceListPricesParams,
|
||||
QueryConfig.listPriceListPriceQueryConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
@@ -7,14 +7,15 @@ import { AdminPriceListRemoteQueryDTO } from "../types"
|
||||
|
||||
export * from "./get-price-list"
|
||||
export * from "./list-price-lists"
|
||||
export * from "./list-prices"
|
||||
|
||||
export function buildPriceListResponse(
|
||||
priceLists,
|
||||
apiFields
|
||||
): AdminPriceListRemoteQueryDTO[] {
|
||||
for (const priceList of priceLists) {
|
||||
priceList.rules = buildPriceListRules(priceList.price_list_rules || [])
|
||||
priceList.prices = buildPriceSetPricesForCore(priceList.prices || [])
|
||||
priceList.rules = buildPriceListRules(priceList.price_list_rules)
|
||||
priceList.prices = buildPriceSetPricesForCore(priceList.prices)
|
||||
}
|
||||
|
||||
return priceLists.map((priceList) => cleanResponseData(priceList, apiFields))
|
||||
|
||||
@@ -4,17 +4,14 @@ import {
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import { AdminPriceListRemoteQueryDTO } from "../types"
|
||||
import { buildPriceListResponse } from "./"
|
||||
|
||||
export async function listPriceLists({
|
||||
container,
|
||||
remoteQueryFields,
|
||||
apiFields,
|
||||
variables,
|
||||
}: {
|
||||
container: MedusaContainer
|
||||
remoteQueryFields: string[]
|
||||
apiFields: string[]
|
||||
variables: Record<string, any>
|
||||
}): Promise<[AdminPriceListRemoteQueryDTO[], number]> {
|
||||
const remoteQuery = container.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||
@@ -26,11 +23,5 @@ export async function listPriceLists({
|
||||
|
||||
const { rows: priceLists, metadata } = await remoteQuery(queryObject)
|
||||
|
||||
if (!metadata.count) {
|
||||
return [[], 0]
|
||||
}
|
||||
|
||||
const sanitizedPriceLists = buildPriceListResponse(priceLists, apiFields)
|
||||
|
||||
return [sanitizedPriceLists, metadata.count]
|
||||
return [priceLists, metadata.count]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { MedusaContainer } from "@medusajs/types"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
export const listPrices = (
|
||||
ids: string[],
|
||||
scope: MedusaContainer,
|
||||
fields: string[]
|
||||
) => {
|
||||
const remoteQuery = scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||
const queryObject = remoteQueryObjectFromString({
|
||||
entryPoint: "price",
|
||||
variables: {
|
||||
filters: { id: ids },
|
||||
},
|
||||
fields,
|
||||
})
|
||||
|
||||
return remoteQuery(queryObject)
|
||||
}
|
||||
@@ -2,6 +2,20 @@ export enum PriceListRelations {
|
||||
PRICES = "prices",
|
||||
}
|
||||
|
||||
export const adminPriceListPriceRemoteQueryFields = [
|
||||
"id",
|
||||
"currency_code",
|
||||
"amount",
|
||||
"min_quantity",
|
||||
"max_quantity",
|
||||
"created_at",
|
||||
"deleted_at",
|
||||
"updated_at",
|
||||
"price_set.variant.id",
|
||||
"price_rules.value",
|
||||
"price_rules.rule_type.rule_attribute",
|
||||
]
|
||||
|
||||
export const adminPriceListRemoteQueryFields = [
|
||||
"id",
|
||||
"type",
|
||||
@@ -13,56 +27,27 @@ export const adminPriceListRemoteQueryFields = [
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"deleted_at",
|
||||
"prices.id",
|
||||
"prices.currency_code",
|
||||
"prices.amount",
|
||||
"prices.min_quantity",
|
||||
"prices.max_quantity",
|
||||
"prices.created_at",
|
||||
"prices.deleted_at",
|
||||
"prices.updated_at",
|
||||
"prices.price_set.variant.id",
|
||||
"prices.price_rules.value",
|
||||
"prices.price_rules.rule_type.rule_attribute",
|
||||
"price_list_rules.price_list_rule_values.value",
|
||||
"price_list_rules.rule_type.rule_attribute",
|
||||
...adminPriceListPriceRemoteQueryFields.map((field) => `prices.${field}`),
|
||||
]
|
||||
|
||||
export const defaultAdminPriceListFields = [
|
||||
"id",
|
||||
"type",
|
||||
"description",
|
||||
"title",
|
||||
"status",
|
||||
"starts_at",
|
||||
"ends_at",
|
||||
"rules",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"prices.amount",
|
||||
"prices.id",
|
||||
"prices.currency_code",
|
||||
"prices.amount",
|
||||
"prices.min_quantity",
|
||||
"prices.max_quantity",
|
||||
"prices.variant_id",
|
||||
"prices.rules",
|
||||
]
|
||||
export const retrivePriceListPriceQueryConfig = {
|
||||
defaults: adminPriceListPriceRemoteQueryFields,
|
||||
isList: false,
|
||||
}
|
||||
|
||||
export const defaultAdminPriceListRelations = []
|
||||
export const allowedAdminPriceListRelations = [PriceListRelations.PRICES]
|
||||
|
||||
export const adminListTransformQueryConfig = {
|
||||
defaultLimit: 50,
|
||||
defaultFields: defaultAdminPriceListFields,
|
||||
defaultRelations: defaultAdminPriceListRelations,
|
||||
allowedRelations: allowedAdminPriceListRelations,
|
||||
export const listPriceListPriceQueryConfig = {
|
||||
...retrivePriceListPriceQueryConfig,
|
||||
isList: true,
|
||||
}
|
||||
|
||||
export const adminRetrieveTransformQueryConfig = {
|
||||
defaultFields: defaultAdminPriceListFields,
|
||||
defaultRelations: defaultAdminPriceListRelations,
|
||||
allowedRelations: allowedAdminPriceListRelations,
|
||||
export const retrivePriceListQueryConfig = {
|
||||
defaults: adminPriceListRemoteQueryFields,
|
||||
isList: false,
|
||||
}
|
||||
|
||||
export const listPriceListQueryConfig = {
|
||||
...retrivePriceListQueryConfig,
|
||||
isList: true,
|
||||
}
|
||||
|
||||
@@ -1,42 +1,43 @@
|
||||
import { createPriceListsWorkflow } from "@medusajs/core-flows"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../types/routing"
|
||||
import { listPriceLists } from "./queries"
|
||||
import {
|
||||
adminPriceListRemoteQueryFields,
|
||||
defaultAdminPriceListFields,
|
||||
} from "./query-config"
|
||||
import { AdminPostPriceListsReq } from "./validators"
|
||||
import { fetchPriceList, transformPriceList } from "./helpers"
|
||||
import { AdminCreatePriceListType } from "./validators"
|
||||
|
||||
export const GET = async (
|
||||
req: AuthenticatedMedusaRequest,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const { limit, offset } = req.validatedQuery
|
||||
const [priceLists, count] = await listPriceLists({
|
||||
container: req.scope,
|
||||
apiFields: req.listConfig.select!,
|
||||
remoteQueryFields: adminPriceListRemoteQueryFields,
|
||||
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||
|
||||
const queryObject = remoteQueryObjectFromString({
|
||||
entryPoint: "price_list",
|
||||
variables: {
|
||||
filters: req.filterableFields,
|
||||
order: req.listConfig.order,
|
||||
skip: req.listConfig.skip,
|
||||
take: req.listConfig.take,
|
||||
...req.remoteQueryConfig.pagination,
|
||||
},
|
||||
fields: req.remoteQueryConfig.fields,
|
||||
})
|
||||
|
||||
const { rows: priceLists, metadata } = await remoteQuery(queryObject)
|
||||
|
||||
res.json({
|
||||
count,
|
||||
price_lists: priceLists,
|
||||
count: metadata.count,
|
||||
price_lists: priceLists.map((priceList) => transformPriceList(priceList)),
|
||||
offset,
|
||||
limit,
|
||||
})
|
||||
}
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<AdminPostPriceListsReq>,
|
||||
req: AuthenticatedMedusaRequest<AdminCreatePriceListType>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const workflow = createPriceListsWorkflow(req.scope)
|
||||
@@ -49,16 +50,11 @@ export const POST = async (
|
||||
throw errors[0].error
|
||||
}
|
||||
|
||||
const [[priceList]] = await listPriceLists({
|
||||
container: req.scope,
|
||||
apiFields: defaultAdminPriceListFields,
|
||||
remoteQueryFields: adminPriceListRemoteQueryFields,
|
||||
variables: {
|
||||
filters: { id: result[0].id },
|
||||
skip: 0,
|
||||
take: 1,
|
||||
},
|
||||
})
|
||||
const price_list = await fetchPriceList(
|
||||
result[0].id,
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields
|
||||
)
|
||||
|
||||
res.status(200).json({ price_list: priceList })
|
||||
res.status(200).json({ price_list })
|
||||
}
|
||||
|
||||
@@ -1,151 +1,77 @@
|
||||
import { PriceListStatus, PriceListType } from "@medusajs/types"
|
||||
import { Transform, Type } from "class-transformer"
|
||||
import {
|
||||
IsArray,
|
||||
IsEnum,
|
||||
IsInt,
|
||||
IsObject,
|
||||
IsOptional,
|
||||
IsString,
|
||||
ValidateNested,
|
||||
} from "class-validator"
|
||||
import { FindParams } from "../../../types/common"
|
||||
import { transformOptionalDate } from "../../../utils/validators/date-transform"
|
||||
import { z } from "zod"
|
||||
import { createFindParams, createSelectParams } from "../../utils/validators"
|
||||
|
||||
export class AdminGetPriceListsParams extends FindParams {}
|
||||
export class AdminGetPriceListsPriceListParams extends FindParams {}
|
||||
export const AdminGetPriceListPricesParams = createSelectParams()
|
||||
export const AdminGetPriceListsParams = createFindParams({
|
||||
offset: 0,
|
||||
limit: 50,
|
||||
})
|
||||
|
||||
export class AdminPostPriceListsReq {
|
||||
@IsString()
|
||||
title: string
|
||||
export const AdminGetPriceListParams = createFindParams({
|
||||
offset: 0,
|
||||
limit: 50,
|
||||
})
|
||||
|
||||
@IsString()
|
||||
description: string
|
||||
export const AdminCreatePriceListPrice = z.object({
|
||||
currency_code: z.string(),
|
||||
amount: z.number(),
|
||||
variant_id: z.string(),
|
||||
min_quantity: z.number().optional(),
|
||||
max_quantity: z.number().optional(),
|
||||
rules: z.record(z.string(), z.string()).optional(),
|
||||
})
|
||||
|
||||
@IsOptional()
|
||||
@Transform(transformOptionalDate)
|
||||
starts_at?: string
|
||||
export type AdminCreatePriceListPriceType = z.infer<
|
||||
typeof AdminCreatePriceListPrice
|
||||
>
|
||||
|
||||
@IsOptional()
|
||||
@Transform(transformOptionalDate)
|
||||
ends_at?: string
|
||||
export const AdminUpdatePriceListPrice = z.object({
|
||||
id: z.string(),
|
||||
currency_code: z.string().optional(),
|
||||
amount: z.number().optional(),
|
||||
variant_id: z.string(),
|
||||
min_quantity: z.number().optional(),
|
||||
max_quantity: z.number().optional(),
|
||||
rules: z.record(z.string(), z.string()).optional(),
|
||||
})
|
||||
|
||||
@IsOptional()
|
||||
@IsEnum(PriceListStatus)
|
||||
status?: PriceListStatus
|
||||
export type AdminUpdatePriceListPriceType = z.infer<
|
||||
typeof AdminUpdatePriceListPrice
|
||||
>
|
||||
|
||||
@IsEnum(PriceListType)
|
||||
type: PriceListType
|
||||
export const AdminBatchPriceListPrices = z.object({
|
||||
create: z.array(AdminCreatePriceListPrice).optional(),
|
||||
update: z.array(AdminUpdatePriceListPrice).optional(),
|
||||
delete: z.array(z.string()).optional(),
|
||||
product_id: z.array(z.string()).optional(),
|
||||
})
|
||||
|
||||
@IsArray()
|
||||
@Type(() => AdminPriceListPricesCreateReq)
|
||||
@ValidateNested({ each: true })
|
||||
prices: AdminPriceListPricesCreateReq[]
|
||||
export type AdminBatchPriceListPricesType = z.infer<
|
||||
typeof AdminBatchPriceListPrices
|
||||
>
|
||||
|
||||
@IsOptional()
|
||||
@IsObject()
|
||||
rules?: Record<string, string[]>
|
||||
}
|
||||
export const AdminCreatePriceList = z.object({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
starts_at: z.string().optional(),
|
||||
ends_at: z.string().optional(),
|
||||
status: z.nativeEnum(PriceListStatus).optional(),
|
||||
type: z.nativeEnum(PriceListType).optional(),
|
||||
rules: z.record(z.string(), z.array(z.string())).optional(),
|
||||
prices: z.array(AdminCreatePriceListPrice).optional(),
|
||||
})
|
||||
|
||||
export class AdminPriceListPricesCreateReq {
|
||||
@IsString()
|
||||
currency_code: string
|
||||
export type AdminCreatePriceListType = z.infer<typeof AdminCreatePriceList>
|
||||
|
||||
@IsInt()
|
||||
amount: number
|
||||
export const AdminUpdatePriceList = z.object({
|
||||
title: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
starts_at: z.string().optional(),
|
||||
ends_at: z.string().optional(),
|
||||
status: z.nativeEnum(PriceListStatus).optional(),
|
||||
type: z.nativeEnum(PriceListType).optional(),
|
||||
rules: z.record(z.string(), z.array(z.string())).optional(),
|
||||
})
|
||||
|
||||
@IsString()
|
||||
variant_id: string
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
min_quantity?: number
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
max_quantity?: number
|
||||
|
||||
@IsOptional()
|
||||
@IsObject()
|
||||
rules?: Record<string, string>
|
||||
}
|
||||
|
||||
export class AdminPostPriceListsPriceListReq {
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
title?: string
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
description?: string
|
||||
|
||||
@IsOptional()
|
||||
@Transform(transformOptionalDate)
|
||||
starts_at?: string
|
||||
|
||||
@IsOptional()
|
||||
@Transform(transformOptionalDate)
|
||||
ends_at?: string
|
||||
|
||||
@IsOptional()
|
||||
@IsEnum(PriceListStatus)
|
||||
status?: PriceListStatus
|
||||
|
||||
@IsOptional()
|
||||
@IsEnum(PriceListType)
|
||||
type?: PriceListType
|
||||
|
||||
@IsOptional()
|
||||
@IsArray()
|
||||
prices: AdminPriceListPricesCreateReq[]
|
||||
|
||||
@IsOptional()
|
||||
@IsObject()
|
||||
rules?: Record<string, string[]>
|
||||
}
|
||||
|
||||
export class AdminPostPriceListsPriceListPricesBatchAddReq {
|
||||
@IsOptional()
|
||||
@IsArray()
|
||||
prices: AdminPriceListPricesCreateReq[]
|
||||
}
|
||||
|
||||
export class AdminPostPriceListPriceBatchUpdate {
|
||||
@IsOptional()
|
||||
@IsArray()
|
||||
prices: AdminPostPriceListPriceUpdate[]
|
||||
}
|
||||
|
||||
export class AdminPostPriceListsPriceListPricesBatchRemoveReq {
|
||||
@IsArray()
|
||||
@IsString({ each: true })
|
||||
ids: string[]
|
||||
}
|
||||
|
||||
export class AdminPostPriceListPriceUpdate {
|
||||
@IsString()
|
||||
id: string
|
||||
|
||||
@IsString()
|
||||
variant_id: string
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
currency_code?: string
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
amount?: number
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
min_quantity?: number
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
max_quantity?: number
|
||||
|
||||
@IsOptional()
|
||||
@IsObject()
|
||||
rules?: Record<string, string>
|
||||
}
|
||||
export type AdminUpdatePriceListType = z.infer<typeof AdminUpdatePriceList>
|
||||
|
||||
+1
-2
@@ -715,14 +715,13 @@ moduleIntegrationTestRunner({
|
||||
|
||||
describe("addRules", () => {
|
||||
it("should add rules to existing price set", async () => {
|
||||
console.log("1")
|
||||
await service.addRules([
|
||||
{
|
||||
priceSetId: "price-set-1",
|
||||
rules: [{ attribute: "region_id" }],
|
||||
},
|
||||
])
|
||||
console.log("2")
|
||||
|
||||
const [priceSet] = await service.list(
|
||||
{ id: ["price-set-1"] },
|
||||
{ relations: ["rule_types"] }
|
||||
|
||||
@@ -39,5 +39,11 @@ export const joinerConfig: ModuleJoinerConfig = {
|
||||
methodSuffix: "PriceLists",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["price", "prices"],
|
||||
args: {
|
||||
methodSuffix: "Prices",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
AddPricesDTO,
|
||||
Context,
|
||||
CreatePriceListRuleDTO,
|
||||
CreatePriceRuleDTO,
|
||||
CreatePricesDTO,
|
||||
CreatePriceSetDTO,
|
||||
DAL,
|
||||
@@ -23,7 +24,7 @@ import {
|
||||
groupBy,
|
||||
InjectManager,
|
||||
InjectTransactionManager,
|
||||
isDefined, isPresent,
|
||||
isPresent,
|
||||
isString,
|
||||
MedusaContext,
|
||||
MedusaError,
|
||||
@@ -44,12 +45,12 @@ import {
|
||||
RuleType,
|
||||
} from "@models"
|
||||
|
||||
import {PriceListService, RuleTypeService} from "@services"
|
||||
import {validatePriceListDates} from "@utils"
|
||||
import {entityNameToLinkableKeysMap, joinerConfig} from "../joiner-config"
|
||||
import {PriceSetIdPrefix} from "../models/price-set"
|
||||
import {PriceListIdPrefix} from "../models/price-list"
|
||||
import {UpdatePriceSetInput} from "src/types/services"
|
||||
import { PriceListService, RuleTypeService } from "@services"
|
||||
import { validatePriceListDates } from "@utils"
|
||||
import { UpdatePriceSetInput } from "src/types/services"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { PriceListIdPrefix } from "../models/price-list"
|
||||
import { PriceSetIdPrefix } from "../models/price-set"
|
||||
|
||||
type InjectedDependencies = {
|
||||
baseRepository: DAL.RepositoryService
|
||||
@@ -373,7 +374,7 @@ export default class PricingModuleService<
|
||||
...price,
|
||||
price_set_id: priceSet.id,
|
||||
price_rules: hasRulesInput ? rules : undefined,
|
||||
rules_count: hasRulesInput ? rules.length : undefined
|
||||
rules_count: hasRulesInput ? rules.length : undefined,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -598,8 +599,10 @@ export default class PricingModuleService<
|
||||
async updatePriceListPrices(
|
||||
data: PricingTypes.UpdatePriceListPricesDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<PricingTypes.PriceListDTO[]> {
|
||||
return await this.updatePriceListPrices_(data, sharedContext)
|
||||
): Promise<PricingTypes.PriceDTO[]> {
|
||||
const prices = await this.updatePriceListPrices_(data, sharedContext)
|
||||
|
||||
return await this.baseRepository_.serialize<PricingTypes.PriceDTO[]>(prices)
|
||||
}
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
@@ -614,8 +617,10 @@ export default class PricingModuleService<
|
||||
async addPriceListPrices(
|
||||
data: PricingTypes.AddPriceListPricesDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<PricingTypes.PriceListDTO[]> {
|
||||
return await this.addPriceListPrices_(data, sharedContext)
|
||||
): Promise<PricingTypes.PriceDTO[]> {
|
||||
const prices = await this.addPriceListPrices_(data, sharedContext)
|
||||
|
||||
return await this.baseRepository_.serialize<PricingTypes.PriceDTO[]>(prices)
|
||||
}
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
@@ -1141,7 +1146,7 @@ export default class PricingModuleService<
|
||||
protected async updatePriceListPrices_(
|
||||
data: PricingTypes.UpdatePriceListPricesDTO[],
|
||||
sharedContext: Context = {}
|
||||
): Promise<PricingTypes.PriceListDTO[]> {
|
||||
): Promise<TPrice[]> {
|
||||
const ruleTypeAttributes: string[] = []
|
||||
const priceListIds: string[] = []
|
||||
const priceIds: string[] = []
|
||||
@@ -1233,6 +1238,10 @@ export default class PricingModuleService<
|
||||
|
||||
const priceListMap = new Map(priceLists.map((p) => [p.id, p]))
|
||||
|
||||
const pricesToUpdate: Partial<TPrice>[] = []
|
||||
const priceRuleIdsToDelete: string[] = []
|
||||
const priceRulesToCreate: CreatePriceRuleDTO[] = []
|
||||
|
||||
for (const { price_list_id: priceListId, prices } of data) {
|
||||
const priceList = priceListMap.get(priceListId)
|
||||
|
||||
@@ -1243,43 +1252,37 @@ export default class PricingModuleService<
|
||||
)
|
||||
}
|
||||
|
||||
const priceRuleIdsToDelete: string[] = []
|
||||
const priceRulesToCreate: PricingTypes.CreatePriceRuleDTO[] = []
|
||||
const pricesToUpdate: Partial<TPrice>[] = []
|
||||
|
||||
for (const priceData of prices) {
|
||||
const { rules, price_set_id, ...rest } = priceData
|
||||
const { rules = {}, price_set_id, ...rest } = priceData
|
||||
const price = priceMap.get(rest.id)!
|
||||
const priceRules = price.price_rules!
|
||||
|
||||
if (!isDefined(rules)) {
|
||||
continue
|
||||
}
|
||||
priceRulesToCreate.push(
|
||||
...Object.entries(rules).map(([ruleAttribute, ruleValue]) => ({
|
||||
price_set_id,
|
||||
rule_type_id: ruleTypeMap.get(ruleAttribute)!.id,
|
||||
value: ruleValue,
|
||||
price_id: price.id,
|
||||
}))
|
||||
)
|
||||
|
||||
pricesToUpdate.push({
|
||||
...rest,
|
||||
rules_count: Object.keys(rules).length,
|
||||
price_rules: Object.entries(rules).map(
|
||||
([ruleAttribute, ruleValue]) => ({
|
||||
price_set_id,
|
||||
rule_type_id: ruleTypeMap.get(ruleAttribute)!.id,
|
||||
value: ruleValue,
|
||||
price_id: price.id,
|
||||
})
|
||||
),
|
||||
} as unknown as TPrice)
|
||||
|
||||
priceRuleIdsToDelete.push(...priceRules.map((pr) => pr.id))
|
||||
}
|
||||
}
|
||||
|
||||
const [_deletedPriceRule, _createdPriceRule, updatedPrices] =
|
||||
await promiseAll([
|
||||
this.priceRuleService_.delete(priceRuleIdsToDelete),
|
||||
this.priceRuleService_.create(priceRulesToCreate),
|
||||
this.priceService_.update(pricesToUpdate),
|
||||
])
|
||||
}
|
||||
|
||||
return priceLists
|
||||
return updatedPrices
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
@@ -1294,7 +1297,7 @@ export default class PricingModuleService<
|
||||
protected async addPriceListPrices_(
|
||||
data: PricingTypes.AddPriceListPricesDTO[],
|
||||
sharedContext: Context = {}
|
||||
): Promise<PricingTypes.PriceListDTO[]> {
|
||||
): Promise<TPrice[]> {
|
||||
const ruleTypeAttributes: string[] = []
|
||||
const priceListIds: string[] = []
|
||||
const priceSetIds: string[] = []
|
||||
@@ -1411,9 +1414,7 @@ export default class PricingModuleService<
|
||||
pricesToCreate.push(...priceListPricesToCreate)
|
||||
}
|
||||
|
||||
await this.priceService_.create(pricesToCreate, sharedContext)
|
||||
|
||||
return priceLists
|
||||
return await this.priceService_.create(pricesToCreate, sharedContext)
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
import { FindConfig } from "../common"
|
||||
import { RestoreReturn, SoftDeleteReturn } from "../dal"
|
||||
import { IModuleService } from "../modules-sdk"
|
||||
import { Context } from "../shared-context"
|
||||
import {
|
||||
AddPriceListPricesDTO,
|
||||
AddPricesDTO,
|
||||
@@ -33,10 +37,6 @@ import {
|
||||
UpdateRuleTypeDTO,
|
||||
UpsertPriceSetDTO,
|
||||
} from "./common"
|
||||
import { FindConfig } from "../common"
|
||||
import { RestoreReturn, SoftDeleteReturn } from "../dal"
|
||||
import { IModuleService } from "../modules-sdk"
|
||||
import { Context } from "../shared-context"
|
||||
|
||||
/**
|
||||
* The main service interface for the Pricing Module.
|
||||
@@ -1734,7 +1734,7 @@ export interface IPricingModuleService extends IModuleService {
|
||||
addPriceListPrices(
|
||||
data: AddPriceListPricesDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<PriceListDTO[]>
|
||||
): Promise<PriceDTO[]>
|
||||
|
||||
/**
|
||||
* This method updates existing price list's prices.
|
||||
@@ -1742,7 +1742,7 @@ export interface IPricingModuleService extends IModuleService {
|
||||
* @param {UpdatePriceListPricesDTO[]} data - The attributes to update in a price list's prices. The price list's ID is specified
|
||||
* in the `price_list_id` field.
|
||||
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
|
||||
* @returns {Promise<PriceListDTO[]>} The updated price list's prices.
|
||||
* @returns {Promise<PriceDTO[]>} The updated price list's prices.
|
||||
*
|
||||
* @example
|
||||
* const priceLists =
|
||||
@@ -1763,7 +1763,7 @@ export interface IPricingModuleService extends IModuleService {
|
||||
updatePriceListPrices(
|
||||
data: UpdatePriceListPricesDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<PriceListDTO[]>
|
||||
): Promise<PriceDTO[]>
|
||||
|
||||
/**
|
||||
* This method is used to set the rules of a price list. Previous rules are removed.
|
||||
@@ -1771,7 +1771,7 @@ export interface IPricingModuleService extends IModuleService {
|
||||
* @param {SetPriceListRulesDTO} data - The rules to set for a price list. The price list is identified by the
|
||||
* `price_list_id` property.
|
||||
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
|
||||
* @returns {Promise<PriceListDTO>} The updated price list.
|
||||
* @returns {Promise<PriceDTO>} The updated price list's prices.
|
||||
*
|
||||
* @example
|
||||
* const priceList =
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { PricingTypes } from "../bundles"
|
||||
import { PriceListStatus } from "./common"
|
||||
|
||||
export interface CreatePriceListPriceWorkflowDTO {
|
||||
@@ -9,6 +10,16 @@ export interface CreatePriceListPriceWorkflowDTO {
|
||||
rules?: Record<string, string>
|
||||
}
|
||||
|
||||
export interface UpdatePriceListPriceWorkflowDTO {
|
||||
id: string
|
||||
variant_id: string
|
||||
amount?: number
|
||||
currency_code?: string
|
||||
max_quantity?: number
|
||||
min_quantity?: number
|
||||
rules?: Record<string, string>
|
||||
}
|
||||
|
||||
export interface CreatePriceListWorkflowInputDTO {
|
||||
title: string
|
||||
description: string
|
||||
@@ -16,7 +27,7 @@ export interface CreatePriceListWorkflowInputDTO {
|
||||
ends_at?: string | null
|
||||
status?: PriceListStatus
|
||||
rules?: Record<string, string[]>
|
||||
prices: CreatePriceListPriceWorkflowDTO[]
|
||||
prices?: CreatePriceListPriceWorkflowDTO[]
|
||||
}
|
||||
|
||||
export interface UpdatePriceListWorkflowInputDTO {
|
||||
@@ -31,15 +42,20 @@ export interface UpdatePriceListWorkflowInputDTO {
|
||||
|
||||
export interface UpdatePriceListPricesWorkflowDTO {
|
||||
id: string
|
||||
prices: {
|
||||
id: string
|
||||
variant_id: string
|
||||
amount?: number
|
||||
currency_code?: string
|
||||
max_quantity?: number
|
||||
min_quantity?: number
|
||||
rules?: Record<string, string>
|
||||
}[]
|
||||
prices: UpdatePriceListPriceWorkflowDTO[]
|
||||
}
|
||||
|
||||
export interface BatchPriceListPricesWorkflowDTO {
|
||||
id: string
|
||||
create: CreatePriceListPriceWorkflowDTO[]
|
||||
update: UpdatePriceListPriceWorkflowDTO[]
|
||||
delete: string[]
|
||||
}
|
||||
|
||||
export interface BatchPriceListPricesWorkflowResult {
|
||||
created: PricingTypes.PriceDTO[]
|
||||
updated: PricingTypes.PriceDTO[]
|
||||
deleted: string[]
|
||||
}
|
||||
|
||||
export interface CreatePriceListPricesWorkflowDTO {
|
||||
|
||||
@@ -7,9 +7,9 @@ import {
|
||||
} from "@medusajs/types"
|
||||
|
||||
export function buildPriceListRules(
|
||||
priceListRules: PriceListRuleDTO[]
|
||||
): Record<string, string[]> {
|
||||
return priceListRules.reduce((acc, curr) => {
|
||||
priceListRules?: PriceListRuleDTO[]
|
||||
): Record<string, string[]> | undefined {
|
||||
return priceListRules?.reduce((acc, curr) => {
|
||||
const ruleAttribute = curr.rule_type.rule_attribute
|
||||
const ruleValues = curr.price_list_rule_values || []
|
||||
|
||||
@@ -20,9 +20,13 @@ export function buildPriceListRules(
|
||||
}
|
||||
|
||||
export function buildPriceSetRules(
|
||||
priceRules: PriceRuleDTO[]
|
||||
): Record<string, string> {
|
||||
return priceRules.reduce((acc, curr) => {
|
||||
priceRules?: PriceRuleDTO[]
|
||||
): Record<string, string> | undefined {
|
||||
if (typeof priceRules === "undefined") {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return priceRules?.reduce((acc, curr) => {
|
||||
const ruleAttribute = curr.rule_type.rule_attribute
|
||||
const ruleValue = curr.value
|
||||
|
||||
@@ -34,20 +38,24 @@ export function buildPriceSetRules(
|
||||
|
||||
export function buildPriceSetPricesForCore(
|
||||
prices: (PriceDTO & {
|
||||
price_set: PriceDTO["price_set"] & {
|
||||
price_set?: PriceDTO["price_set"] & {
|
||||
variant?: ProductVariantDTO
|
||||
}
|
||||
})[]
|
||||
): Record<string, any>[] {
|
||||
return prices.map((price) => {
|
||||
const productVariant = (price.price_set as any).variant
|
||||
const rules: Record<string, string> = price.price_rules
|
||||
? buildPriceSetRules(price.price_rules)
|
||||
: {}
|
||||
return prices?.map((price) => {
|
||||
const productVariant = (price.price_set as any)?.variant
|
||||
const rules: Record<string, string> | undefined =
|
||||
typeof price.price_rules === "undefined"
|
||||
? undefined
|
||||
: buildPriceSetRules(price.price_rules || [])
|
||||
|
||||
delete price.price_rules
|
||||
delete price.price_set
|
||||
|
||||
return {
|
||||
...price,
|
||||
variant_id: productVariant?.id ?? null,
|
||||
variant_id: productVariant?.id ?? undefined,
|
||||
rules,
|
||||
}
|
||||
})
|
||||
@@ -56,10 +64,11 @@ export function buildPriceSetPricesForCore(
|
||||
export function buildPriceSetPricesForModule(
|
||||
prices: PriceDTO[]
|
||||
): UpdatePriceListPriceDTO[] {
|
||||
return prices.map((price) => {
|
||||
const rules: Record<string, string> = price.price_rules
|
||||
? buildPriceSetRules(price.price_rules)
|
||||
: {}
|
||||
return prices?.map((price) => {
|
||||
const rules: Record<string, string> | undefined =
|
||||
typeof price.price_rules === "undefined"
|
||||
? undefined
|
||||
: buildPriceSetRules(price.price_rules || [])
|
||||
|
||||
return {
|
||||
...price,
|
||||
|
||||
Reference in New Issue
Block a user