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
+1902
-2353
No files matched your search
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/core-flows": patch
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
"@medusajs/utils": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
feat(core-flows,medusa,utils): added price list prices upsert and delete workflows + endpoints
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/core-flows": patch
|
||||||
|
"@medusajs/pricing": patch
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
"@medusajs/types": patch
|
||||||
|
"@medusajs/utils": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
feat(core-flows,medusa,pricing,types,utils): added price list workflows + endpoints
|
||||||
@@ -1,175 +0,0 @@
|
|||||||
import {
|
|
||||||
simpleCustomerGroupFactory,
|
|
||||||
simpleProductFactory,
|
|
||||||
simpleRegionFactory,
|
|
||||||
} from "../../../../factories"
|
|
||||||
|
|
||||||
import { IPricingModuleService } from "@medusajs/types"
|
|
||||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
|
||||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
|
||||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
|
||||||
import { medusaIntegrationTestRunner } from "medusa-test-utils"
|
|
||||||
|
|
||||||
jest.setTimeout(50000)
|
|
||||||
|
|
||||||
const adminHeaders = {
|
|
||||||
headers: {
|
|
||||||
"x-medusa-access-token": "test_token",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const env = {
|
|
||||||
MEDUSA_FF_MEDUSA_V2: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
medusaIntegrationTestRunner({
|
|
||||||
env,
|
|
||||||
testSuite: ({ dbConnection, getContainer, api }) => {
|
|
||||||
describe.skip("POST /admin/price-lists", () => {
|
|
||||||
let appContainer
|
|
||||||
let product
|
|
||||||
let variant
|
|
||||||
let pricingModuleService: IPricingModuleService
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
appContainer = getContainer()
|
|
||||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
|
||||||
})
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await adminSeeder(dbConnection)
|
|
||||||
await createDefaultRuleTypes(appContainer)
|
|
||||||
await simpleCustomerGroupFactory(dbConnection, {
|
|
||||||
id: "customer-group-1",
|
|
||||||
name: "Test Group",
|
|
||||||
})
|
|
||||||
|
|
||||||
await simpleRegionFactory(dbConnection, {
|
|
||||||
id: "test-region",
|
|
||||||
name: "Test Region",
|
|
||||||
currency_code: "usd",
|
|
||||||
tax_rate: 0,
|
|
||||||
})
|
|
||||||
|
|
||||||
product = await simpleProductFactory(dbConnection, {
|
|
||||||
id: "test-product-with-variant",
|
|
||||||
variants: [
|
|
||||||
{
|
|
||||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
id: "test-product-option-1",
|
|
||||||
title: "Test option 1",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
variant = product.variants[0]
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should create price list and money amounts", async () => {
|
|
||||||
await createVariantPriceSet({
|
|
||||||
container: appContainer,
|
|
||||||
variantId: variant.id,
|
|
||||||
prices: [
|
|
||||||
{
|
|
||||||
amount: 3000,
|
|
||||||
currency_code: "usd",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
name: "test price list",
|
|
||||||
description: "test",
|
|
||||||
type: "override",
|
|
||||||
customer_groups: [{ id: "customer-group-1" }],
|
|
||||||
status: "active",
|
|
||||||
starts_at: new Date(),
|
|
||||||
prices: [
|
|
||||||
{
|
|
||||||
amount: 400,
|
|
||||||
variant_id: variant.id,
|
|
||||||
currency_code: "usd",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await api.post(`admin/price-lists`, data, adminHeaders)
|
|
||||||
|
|
||||||
let response = await api.get(
|
|
||||||
`/admin/price-lists/${result.data.price_list.id}`,
|
|
||||||
adminHeaders
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(response.status).toEqual(200)
|
|
||||||
expect(response.data.price_list).toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
name: "test price list",
|
|
||||||
description: "test",
|
|
||||||
type: "override",
|
|
||||||
status: "active",
|
|
||||||
starts_at: expect.any(String),
|
|
||||||
ends_at: null,
|
|
||||||
customer_groups: [
|
|
||||||
{
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
name: "Test Group",
|
|
||||||
metadata: null,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
prices: [
|
|
||||||
expect.objectContaining({
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
currency_code: "usd",
|
|
||||||
amount: 400,
|
|
||||||
min_quantity: null,
|
|
||||||
max_quantity: null,
|
|
||||||
price_list_id: expect.any(String),
|
|
||||||
region_id: null,
|
|
||||||
variant: expect.objectContaining({
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
title: expect.any(String),
|
|
||||||
product_id: expect.any(String),
|
|
||||||
sku: null,
|
|
||||||
barcode: null,
|
|
||||||
ean: null,
|
|
||||||
upc: null,
|
|
||||||
variant_rank: 0,
|
|
||||||
inventory_quantity: 10,
|
|
||||||
allow_backorder: false,
|
|
||||||
manage_inventory: true,
|
|
||||||
hs_code: null,
|
|
||||||
origin_country: null,
|
|
||||||
mid_code: null,
|
|
||||||
material: null,
|
|
||||||
weight: null,
|
|
||||||
length: null,
|
|
||||||
height: null,
|
|
||||||
width: null,
|
|
||||||
metadata: null,
|
|
||||||
}),
|
|
||||||
variant_id: expect.any(String),
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
import {
|
|
||||||
simpleProductFactory,
|
|
||||||
simpleRegionFactory,
|
|
||||||
} from "../../../../factories"
|
|
||||||
|
|
||||||
import { IPricingModuleService } from "@medusajs/types"
|
|
||||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
|
||||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
|
||||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
|
||||||
import { medusaIntegrationTestRunner } from "medusa-test-utils"
|
|
||||||
|
|
||||||
jest.setTimeout(50000)
|
|
||||||
|
|
||||||
const adminHeaders = {
|
|
||||||
headers: {
|
|
||||||
"x-medusa-access-token": "test_token",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const env = {
|
|
||||||
MEDUSA_FF_MEDUSA_V2: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
medusaIntegrationTestRunner({
|
|
||||||
env,
|
|
||||||
testSuite: ({ dbConnection, getContainer, api }) => {
|
|
||||||
describe.skip("DELETE /admin/price-lists/:id", () => {
|
|
||||||
let appContainer
|
|
||||||
let product
|
|
||||||
let variant
|
|
||||||
let pricingModuleService: IPricingModuleService
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
appContainer = getContainer()
|
|
||||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
|
||||||
})
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await adminSeeder(dbConnection)
|
|
||||||
await createDefaultRuleTypes(appContainer)
|
|
||||||
|
|
||||||
await simpleRegionFactory(dbConnection, {
|
|
||||||
id: "test-region",
|
|
||||||
name: "Test Region",
|
|
||||||
currency_code: "usd",
|
|
||||||
tax_rate: 0,
|
|
||||||
})
|
|
||||||
|
|
||||||
product = await simpleProductFactory(dbConnection, {
|
|
||||||
id: "test-product-with-variant",
|
|
||||||
variants: [
|
|
||||||
{
|
|
||||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
id: "test-product-option-1",
|
|
||||||
title: "Test option 1",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
variant = product.variants[0]
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should delete price list and money amounts", async () => {
|
|
||||||
const priceSet = await createVariantPriceSet({
|
|
||||||
container: appContainer,
|
|
||||||
variantId: variant.id,
|
|
||||||
prices: [
|
|
||||||
{
|
|
||||||
amount: 3000,
|
|
||||||
currency_code: "usd",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
name: "test price list",
|
|
||||||
description: "test",
|
|
||||||
type: "override",
|
|
||||||
customer_groups: [],
|
|
||||||
status: "active",
|
|
||||||
prices: [
|
|
||||||
{
|
|
||||||
amount: 400,
|
|
||||||
variant_id: variant.id,
|
|
||||||
currency_code: "usd",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await api.post(`admin/price-lists`, data, adminHeaders)
|
|
||||||
const priceListId = result.data.price_list.id
|
|
||||||
|
|
||||||
const getResponse = await api.get(
|
|
||||||
`/admin/price-lists/${priceListId}`,
|
|
||||||
adminHeaders
|
|
||||||
)
|
|
||||||
expect(getResponse.status).toEqual(200)
|
|
||||||
|
|
||||||
let psmas = await pricingModuleService.listPriceSetMoneyAmounts({
|
|
||||||
price_list_id: [priceListId],
|
|
||||||
})
|
|
||||||
expect(psmas.length).toEqual(1)
|
|
||||||
|
|
||||||
const deleteRes = await api.delete(
|
|
||||||
`/admin/price-lists/${priceListId}`,
|
|
||||||
adminHeaders
|
|
||||||
)
|
|
||||||
expect(deleteRes.status).toEqual(200)
|
|
||||||
|
|
||||||
const afterDelete = await api
|
|
||||||
.get(`/admin/price-lists/${priceListId}`, adminHeaders)
|
|
||||||
.catch((err) => {
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
expect(afterDelete.response.status).toEqual(404)
|
|
||||||
|
|
||||||
psmas = await pricingModuleService.listPriceSetMoneyAmounts({
|
|
||||||
price_list_id: [priceListId],
|
|
||||||
})
|
|
||||||
expect(psmas.length).toEqual(0)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
import { simpleProductFactory } from "../../../../factories"
|
|
||||||
|
|
||||||
import {
|
|
||||||
IPricingModuleService,
|
|
||||||
PriceListStatus,
|
|
||||||
PriceListType,
|
|
||||||
} from "@medusajs/types"
|
|
||||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
|
||||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
|
||||||
import { medusaIntegrationTestRunner } from "medusa-test-utils"
|
|
||||||
|
|
||||||
jest.setTimeout(50000)
|
|
||||||
|
|
||||||
const adminHeaders = {
|
|
||||||
headers: {
|
|
||||||
"x-medusa-access-token": "test_token",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const env = {
|
|
||||||
MEDUSA_FF_MEDUSA_V2: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
medusaIntegrationTestRunner({
|
|
||||||
env,
|
|
||||||
testSuite: ({ dbConnection, getContainer, api }) => {
|
|
||||||
describe.skip("GET /admin/price-lists/:id", () => {
|
|
||||||
let appContainer
|
|
||||||
let product
|
|
||||||
let variant
|
|
||||||
let pricingModuleService: IPricingModuleService
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
appContainer = getContainer()
|
|
||||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
|
||||||
})
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await adminSeeder(dbConnection)
|
|
||||||
|
|
||||||
product = await simpleProductFactory(dbConnection, {
|
|
||||||
id: "test-product-with-variant",
|
|
||||||
variants: [
|
|
||||||
{
|
|
||||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
id: "test-product-option-1",
|
|
||||||
title: "Test option 1",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
variant = product.variants[0]
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should get price list and its money amounts with variants", async () => {
|
|
||||||
const priceSet = await createVariantPriceSet({
|
|
||||||
container: appContainer,
|
|
||||||
variantId: variant.id,
|
|
||||||
prices: [
|
|
||||||
{
|
|
||||||
amount: 3000,
|
|
||||||
currency_code: "usd",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
rules: [],
|
|
||||||
})
|
|
||||||
|
|
||||||
const [priceList] = await pricingModuleService.createPriceLists([
|
|
||||||
{
|
|
||||||
title: "test price list",
|
|
||||||
description: "test",
|
|
||||||
ends_at: new Date(),
|
|
||||||
starts_at: new Date(),
|
|
||||||
status: PriceListStatus.ACTIVE,
|
|
||||||
type: PriceListType.OVERRIDE,
|
|
||||||
prices: [
|
|
||||||
{
|
|
||||||
amount: 5000,
|
|
||||||
currency_code: "usd",
|
|
||||||
price_set_id: priceSet.id,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
await pricingModuleService.createPriceLists([
|
|
||||||
{
|
|
||||||
title: "test price list 1",
|
|
||||||
description: "test 1",
|
|
||||||
ends_at: new Date(),
|
|
||||||
starts_at: new Date(),
|
|
||||||
status: PriceListStatus.ACTIVE,
|
|
||||||
type: PriceListType.OVERRIDE,
|
|
||||||
prices: [
|
|
||||||
{
|
|
||||||
amount: 5000,
|
|
||||||
currency_code: "usd",
|
|
||||||
price_set_id: priceSet.id,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
const response = await api.get(
|
|
||||||
`/admin/price-lists/${priceList.id}`,
|
|
||||||
adminHeaders
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(response.status).toEqual(200)
|
|
||||||
expect(response.data.price_list).toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
name: "test price list",
|
|
||||||
description: "test",
|
|
||||||
type: "override",
|
|
||||||
status: "active",
|
|
||||||
starts_at: expect.any(String),
|
|
||||||
ends_at: expect.any(String),
|
|
||||||
customer_groups: [],
|
|
||||||
prices: [
|
|
||||||
expect.objectContaining({
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
currency_code: "usd",
|
|
||||||
amount: 5000,
|
|
||||||
min_quantity: null,
|
|
||||||
max_quantity: null,
|
|
||||||
price_list_id: expect.any(String),
|
|
||||||
region_id: null,
|
|
||||||
variant: expect.objectContaining({
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
title: expect.any(String),
|
|
||||||
product_id: expect.any(String),
|
|
||||||
sku: null,
|
|
||||||
barcode: null,
|
|
||||||
ean: null,
|
|
||||||
upc: null,
|
|
||||||
variant_rank: 0,
|
|
||||||
inventory_quantity: 10,
|
|
||||||
allow_backorder: false,
|
|
||||||
manage_inventory: true,
|
|
||||||
hs_code: null,
|
|
||||||
origin_country: null,
|
|
||||||
mid_code: null,
|
|
||||||
material: null,
|
|
||||||
weight: null,
|
|
||||||
length: null,
|
|
||||||
height: null,
|
|
||||||
width: null,
|
|
||||||
metadata: null,
|
|
||||||
}),
|
|
||||||
variant_id: expect.any(String),
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should throw an error when price list is not found", async () => {
|
|
||||||
const error = await api
|
|
||||||
.get(`/admin/price-lists/does-not-exist`, adminHeaders)
|
|
||||||
.catch((e) => e)
|
|
||||||
|
|
||||||
expect(error.response.status).toBe(404)
|
|
||||||
expect(error.response.data).toEqual({
|
|
||||||
type: "not_found",
|
|
||||||
message: "Price list with id: does-not-exist was not found",
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@@ -1,152 +0,0 @@
|
|||||||
import { simpleProductFactory } from "../../../../factories"
|
|
||||||
|
|
||||||
import {
|
|
||||||
IPricingModuleService,
|
|
||||||
PriceListStatus,
|
|
||||||
PriceListType,
|
|
||||||
} from "@medusajs/types"
|
|
||||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
|
||||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
|
||||||
import { medusaIntegrationTestRunner } from "medusa-test-utils"
|
|
||||||
|
|
||||||
jest.setTimeout(50000)
|
|
||||||
|
|
||||||
const adminHeaders = {
|
|
||||||
headers: {
|
|
||||||
"x-medusa-access-token": "test_token",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const env = {
|
|
||||||
MEDUSA_FF_MEDUSA_V2: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
medusaIntegrationTestRunner({
|
|
||||||
env,
|
|
||||||
testSuite: ({ dbConnection, getContainer, api }) => {
|
|
||||||
describe.skip("GET /admin/price-lists", () => {
|
|
||||||
let appContainer
|
|
||||||
let product
|
|
||||||
let variant
|
|
||||||
let pricingModuleService: IPricingModuleService
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
appContainer = getContainer()
|
|
||||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
|
||||||
})
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await adminSeeder(dbConnection)
|
|
||||||
|
|
||||||
product = await simpleProductFactory(dbConnection, {
|
|
||||||
id: "test-product-with-variant",
|
|
||||||
variants: [
|
|
||||||
{
|
|
||||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
id: "test-product-option-1",
|
|
||||||
title: "Test option 1",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
variant = product.variants[0]
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should get price list and its money amounts with variants", async () => {
|
|
||||||
const priceSet = await createVariantPriceSet({
|
|
||||||
container: appContainer,
|
|
||||||
variantId: variant.id,
|
|
||||||
prices: [
|
|
||||||
{
|
|
||||||
amount: 3000,
|
|
||||||
currency_code: "usd",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
rules: [],
|
|
||||||
})
|
|
||||||
|
|
||||||
const [priceList] = await pricingModuleService.createPriceLists([
|
|
||||||
{
|
|
||||||
title: "test price list",
|
|
||||||
description: "test",
|
|
||||||
ends_at: new Date(),
|
|
||||||
starts_at: new Date(),
|
|
||||||
status: PriceListStatus.ACTIVE,
|
|
||||||
type: PriceListType.OVERRIDE,
|
|
||||||
prices: [
|
|
||||||
{
|
|
||||||
amount: 5000,
|
|
||||||
currency_code: "usd",
|
|
||||||
price_set_id: priceSet.id,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
const response = await api.get(`/admin/price-lists`, adminHeaders)
|
|
||||||
|
|
||||||
expect(response.status).toEqual(200)
|
|
||||||
expect(response.data.count).toEqual(1)
|
|
||||||
expect(response.data.price_lists).toEqual([
|
|
||||||
expect.objectContaining({
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
name: "test price list",
|
|
||||||
description: "test",
|
|
||||||
type: "override",
|
|
||||||
status: "active",
|
|
||||||
starts_at: expect.any(String),
|
|
||||||
ends_at: expect.any(String),
|
|
||||||
customer_groups: [],
|
|
||||||
prices: [
|
|
||||||
expect.objectContaining({
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
currency_code: "usd",
|
|
||||||
amount: 5000,
|
|
||||||
min_quantity: null,
|
|
||||||
max_quantity: null,
|
|
||||||
price_list_id: expect.any(String),
|
|
||||||
region_id: null,
|
|
||||||
variant: expect.objectContaining({
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
title: expect.any(String),
|
|
||||||
product_id: expect.any(String),
|
|
||||||
sku: null,
|
|
||||||
barcode: null,
|
|
||||||
ean: null,
|
|
||||||
upc: null,
|
|
||||||
variant_rank: 0,
|
|
||||||
inventory_quantity: 10,
|
|
||||||
allow_backorder: false,
|
|
||||||
manage_inventory: true,
|
|
||||||
hs_code: null,
|
|
||||||
origin_country: null,
|
|
||||||
mid_code: null,
|
|
||||||
material: null,
|
|
||||||
weight: null,
|
|
||||||
length: null,
|
|
||||||
height: null,
|
|
||||||
width: null,
|
|
||||||
metadata: null,
|
|
||||||
}),
|
|
||||||
variant_id: expect.any(String),
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@@ -258,6 +258,351 @@ medusaIntegrationTestRunner({
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("POST /admin/price-lists", () => {
|
||||||
|
it("should create price list and money amounts", async () => {
|
||||||
|
await createVariantPriceSet({
|
||||||
|
container: appContainer,
|
||||||
|
variantId: variant.id,
|
||||||
|
prices: [{ amount: 3000, currency_code: "usd" }],
|
||||||
|
})
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
title: "test price list",
|
||||||
|
description: "test",
|
||||||
|
type: "override",
|
||||||
|
status: "active",
|
||||||
|
starts_at: new Date(),
|
||||||
|
rules: {
|
||||||
|
customer_group_id: [customerGroup.id],
|
||||||
|
},
|
||||||
|
prices: [
|
||||||
|
{
|
||||||
|
amount: 400,
|
||||||
|
variant_id: variant.id,
|
||||||
|
currency_code: "usd",
|
||||||
|
rules: { region_id: region.id },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await api.post(
|
||||||
|
`admin/price-lists`,
|
||||||
|
data,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
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,
|
||||||
|
rules: {
|
||||||
|
customer_group_id: [customerGroup.id],
|
||||||
|
},
|
||||||
|
prices: [
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
currency_code: "usd",
|
||||||
|
amount: 400,
|
||||||
|
min_quantity: null,
|
||||||
|
max_quantity: null,
|
||||||
|
variant_id: variant.id,
|
||||||
|
rules: {
|
||||||
|
region_id: region.id,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should throw error when required attributes are not provided", async () => {
|
||||||
|
const data = {
|
||||||
|
prices: [
|
||||||
|
{
|
||||||
|
amount: 400,
|
||||||
|
currency_code: "usd",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const errorResponse = await api
|
||||||
|
.post(`admin/price-lists`, data, adminHeaders)
|
||||||
|
.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"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("DELETE /admin/price-lists/:id", () => {
|
||||||
|
it("should delete price list and money amounts", async () => {
|
||||||
|
await createVariantPriceSet({
|
||||||
|
container: appContainer,
|
||||||
|
variantId: variant.id,
|
||||||
|
prices: [{ amount: 3000, currency_code: "usd" }],
|
||||||
|
})
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
title: "test price list",
|
||||||
|
description: "test",
|
||||||
|
type: "override",
|
||||||
|
status: "active",
|
||||||
|
starts_at: new Date(),
|
||||||
|
prices: [
|
||||||
|
{ amount: 400, variant_id: variant.id, currency_code: "usd" },
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await api.post(`admin/price-lists`, data, adminHeaders)
|
||||||
|
const priceListId = result.data.price_list.id
|
||||||
|
|
||||||
|
let psmas = await pricingModule.listPriceSetMoneyAmounts({
|
||||||
|
price_list_id: [priceListId],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(psmas.length).toEqual(1)
|
||||||
|
|
||||||
|
const deleteRes = await api.delete(
|
||||||
|
`/admin/price-lists/${priceListId}`,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(deleteRes.status).toEqual(200)
|
||||||
|
|
||||||
|
const afterDelete = await api
|
||||||
|
.get(`/admin/price-lists/${priceListId}`, adminHeaders)
|
||||||
|
.catch((e) => e)
|
||||||
|
|
||||||
|
expect(afterDelete.response.status).toEqual(404)
|
||||||
|
|
||||||
|
psmas = await pricingModule.listPriceSetMoneyAmounts({
|
||||||
|
price_list_id: [priceListId],
|
||||||
|
})
|
||||||
|
expect(psmas.length).toEqual(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should idempotently return a success even if price lists dont exist", async () => {
|
||||||
|
const deleteRes = await api.delete(
|
||||||
|
`/admin/price-lists/does-not-exist`,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(deleteRes.status).toEqual(200)
|
||||||
|
expect(deleteRes.data).toEqual({
|
||||||
|
id: "does-not-exist",
|
||||||
|
object: "price_list",
|
||||||
|
deleted: true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("POST /admin/price-lists/:id", () => {
|
||||||
|
it("should throw error when trying to update a price list that does not exist", async () => {
|
||||||
|
const updateRes = await api
|
||||||
|
.post(
|
||||||
|
`admin/price-lists/does-not-exist`,
|
||||||
|
{ title: "new price list name" },
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
.catch((e) => e)
|
||||||
|
|
||||||
|
expect(updateRes.response.status).toEqual(404)
|
||||||
|
expect(updateRes.response.data.message).toEqual(
|
||||||
|
"Price lists with id: does-not-exist was not found"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should update price lists successfully", async () => {
|
||||||
|
await createVariantPriceSet({
|
||||||
|
container: appContainer,
|
||||||
|
variantId: variant.id,
|
||||||
|
prices: [{ amount: 3000, currency_code: "usd" }],
|
||||||
|
})
|
||||||
|
|
||||||
|
const [priceList] = await pricingModule.createPriceLists([
|
||||||
|
{
|
||||||
|
title: "test price list",
|
||||||
|
description: "test",
|
||||||
|
ends_at: new Date(),
|
||||||
|
starts_at: new Date(),
|
||||||
|
status: PriceListStatus.ACTIVE,
|
||||||
|
type: PriceListType.OVERRIDE,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
title: "new price list name",
|
||||||
|
description: "new price list description",
|
||||||
|
rules: {
|
||||||
|
customer_group_id: [customerGroup.id],
|
||||||
|
},
|
||||||
|
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}`,
|
||||||
|
data,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.price_list).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
created_at: expect.any(String),
|
||||||
|
updated_at: expect.any(String),
|
||||||
|
title: "new price list name",
|
||||||
|
description: "new price list description",
|
||||||
|
type: "override",
|
||||||
|
status: "active",
|
||||||
|
starts_at: expect.any(String),
|
||||||
|
ends_at: expect.any(String),
|
||||||
|
rules: {
|
||||||
|
customer_group_id: [customerGroup.id],
|
||||||
|
},
|
||||||
|
prices: [
|
||||||
|
{
|
||||||
|
id: expect.any(String),
|
||||||
|
currency_code: "usd",
|
||||||
|
amount: 400,
|
||||||
|
min_quantity: null,
|
||||||
|
max_quantity: null,
|
||||||
|
variant_id: variant.id,
|
||||||
|
rules: {
|
||||||
|
region_id: region.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("POST /admin/price-lists/:id/prices", () => {
|
||||||
|
it("should upsert 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: [
|
||||||
|
{
|
||||||
|
amount: 400,
|
||||||
|
variant_id: variant.id,
|
||||||
|
currency_code: "usd",
|
||||||
|
rules: { region_id: region.id },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "test-price-id",
|
||||||
|
variant_id: variant.id,
|
||||||
|
amount: 200,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await api.post(
|
||||||
|
`admin/price-lists/${priceList.id}/prices`,
|
||||||
|
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: 200,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("DELETE /admin/price-lists/:id/prices", () => {
|
||||||
|
it("should delete price list prices", async () => {
|
||||||
|
const priceSet = await createVariantPriceSet({
|
||||||
|
container: appContainer,
|
||||||
|
variantId: variant.id,
|
||||||
|
prices: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
let response = await api.delete(
|
||||||
|
`/admin/price-lists/${priceList.id}/prices`,
|
||||||
|
{ ...adminHeaders, data: { ids: ["test-price-id"] } }
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data).toEqual({
|
||||||
|
ids: ["test-price-id"],
|
||||||
|
object: "price_list_prices",
|
||||||
|
deleted: true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -1,265 +0,0 @@
|
|||||||
import {
|
|
||||||
simpleCustomerGroupFactory,
|
|
||||||
simpleProductFactory,
|
|
||||||
simpleRegionFactory,
|
|
||||||
} from "../../../../factories"
|
|
||||||
|
|
||||||
import {
|
|
||||||
IPricingModuleService,
|
|
||||||
PriceListStatus,
|
|
||||||
PriceListType,
|
|
||||||
} from "@medusajs/types"
|
|
||||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
|
||||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
|
||||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
|
||||||
import { medusaIntegrationTestRunner } from "medusa-test-utils"
|
|
||||||
|
|
||||||
jest.setTimeout(50000)
|
|
||||||
|
|
||||||
const adminHeaders = {
|
|
||||||
headers: {
|
|
||||||
"x-medusa-access-token": "test_token",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const env = {
|
|
||||||
MEDUSA_FF_MEDUSA_V2: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
medusaIntegrationTestRunner({
|
|
||||||
env,
|
|
||||||
testSuite: ({ dbConnection, getContainer, api }) => {
|
|
||||||
describe.skip("POST /admin/price-lists/:id", () => {
|
|
||||||
let appContainer
|
|
||||||
let product
|
|
||||||
let variant
|
|
||||||
let variant2
|
|
||||||
let pricingModuleService: IPricingModuleService
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
appContainer = getContainer()
|
|
||||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
|
||||||
})
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await adminSeeder(dbConnection)
|
|
||||||
await createDefaultRuleTypes(appContainer)
|
|
||||||
await simpleCustomerGroupFactory(dbConnection, {
|
|
||||||
id: "customer-group-2",
|
|
||||||
name: "Test Group 2",
|
|
||||||
})
|
|
||||||
|
|
||||||
await simpleRegionFactory(dbConnection, {
|
|
||||||
id: "test-region",
|
|
||||||
name: "Test Region",
|
|
||||||
currency_code: "usd",
|
|
||||||
tax_rate: 0,
|
|
||||||
})
|
|
||||||
|
|
||||||
product = await simpleProductFactory(dbConnection, {
|
|
||||||
id: "test-product-with-variant",
|
|
||||||
variants: [
|
|
||||||
{
|
|
||||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
options: [
|
|
||||||
{ option_id: "test-product-option-2", value: "test 2" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
id: "test-product-option-1",
|
|
||||||
title: "Test option 1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "test-product-option-2",
|
|
||||||
title: "Test option 2",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
variant = product.variants[0]
|
|
||||||
variant2 = product.variants[1]
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should update price lists successfully with prices", async () => {
|
|
||||||
const var2PriceSet = await createVariantPriceSet({
|
|
||||||
container: appContainer,
|
|
||||||
variantId: variant2.id,
|
|
||||||
prices: [],
|
|
||||||
})
|
|
||||||
|
|
||||||
const [priceList] = await pricingModuleService.createPriceLists([
|
|
||||||
{
|
|
||||||
title: "test price list",
|
|
||||||
description: "test",
|
|
||||||
ends_at: new Date(),
|
|
||||||
starts_at: new Date(),
|
|
||||||
status: PriceListStatus.ACTIVE,
|
|
||||||
type: PriceListType.OVERRIDE,
|
|
||||||
prices: [
|
|
||||||
{
|
|
||||||
amount: 3000,
|
|
||||||
currency_code: "usd",
|
|
||||||
price_set_id: var2PriceSet.id,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
await createVariantPriceSet({
|
|
||||||
container: appContainer,
|
|
||||||
variantId: variant.id,
|
|
||||||
prices: [
|
|
||||||
{
|
|
||||||
amount: 3000,
|
|
||||||
currency_code: "usd",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
name: "new price list name",
|
|
||||||
description: "new price list description",
|
|
||||||
customer_groups: [{ id: "customer-group-2" }],
|
|
||||||
prices: [
|
|
||||||
{
|
|
||||||
variant_id: variant.id,
|
|
||||||
amount: 5000,
|
|
||||||
currency_code: "usd",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: priceList?.price_set_money_amounts?.[0].money_amount?.id,
|
|
||||||
amount: 6000,
|
|
||||||
currency_code: "usd",
|
|
||||||
variant_id: variant2.id,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
await api.post(`admin/price-lists/${priceList.id}`, data, adminHeaders)
|
|
||||||
|
|
||||||
const response = await api.get(
|
|
||||||
`/admin/price-lists/${priceList.id}`,
|
|
||||||
adminHeaders
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(response.status).toEqual(200)
|
|
||||||
expect(response.data.price_list).toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
name: "new price list name",
|
|
||||||
description: "new price list description",
|
|
||||||
type: "override",
|
|
||||||
status: "active",
|
|
||||||
starts_at: expect.any(String),
|
|
||||||
ends_at: expect.any(String),
|
|
||||||
customer_groups: [
|
|
||||||
{
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
name: "Test Group 2",
|
|
||||||
metadata: null,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
prices: expect.arrayContaining([
|
|
||||||
expect.objectContaining({
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
currency_code: "usd",
|
|
||||||
amount: 5000,
|
|
||||||
min_quantity: null,
|
|
||||||
max_quantity: null,
|
|
||||||
price_list_id: priceList.id,
|
|
||||||
region_id: null,
|
|
||||||
variant: expect.objectContaining({
|
|
||||||
id: variant.id,
|
|
||||||
}),
|
|
||||||
variant_id: variant.id,
|
|
||||||
}),
|
|
||||||
expect.objectContaining({
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
currency_code: "usd",
|
|
||||||
amount: 6000,
|
|
||||||
min_quantity: null,
|
|
||||||
max_quantity: null,
|
|
||||||
price_list_id: priceList.id,
|
|
||||||
region_id: null,
|
|
||||||
variant: expect.objectContaining({
|
|
||||||
id: variant2.id,
|
|
||||||
}),
|
|
||||||
variant_id: variant2.id,
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should not delete customer groups if customer_groups is not passed as a param", async () => {
|
|
||||||
await createVariantPriceSet({
|
|
||||||
container: appContainer,
|
|
||||||
variantId: variant2.id,
|
|
||||||
prices: [],
|
|
||||||
})
|
|
||||||
|
|
||||||
const [priceList] = await pricingModuleService.createPriceLists([
|
|
||||||
{
|
|
||||||
title: "test price list",
|
|
||||||
description: "test",
|
|
||||||
status: PriceListStatus.DRAFT,
|
|
||||||
rules: {
|
|
||||||
customer_group_id: ["customer-group-2"],
|
|
||||||
},
|
|
||||||
prices: [],
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
await createVariantPriceSet({
|
|
||||||
container: appContainer,
|
|
||||||
variantId: variant.id,
|
|
||||||
prices: [],
|
|
||||||
})
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
status: PriceListStatus.ACTIVE,
|
|
||||||
}
|
|
||||||
|
|
||||||
await api.post(`admin/price-lists/${priceList.id}`, data, adminHeaders)
|
|
||||||
|
|
||||||
const response = await api.get(
|
|
||||||
`/admin/price-lists/${priceList.id}`,
|
|
||||||
adminHeaders
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(response.status).toEqual(200)
|
|
||||||
expect(response.data.price_list).toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
id: expect.any(String),
|
|
||||||
customer_groups: [
|
|
||||||
{
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
name: "Test Group 2",
|
|
||||||
metadata: null,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@@ -2,5 +2,4 @@ export * from "./cart"
|
|||||||
export * from "./inventory"
|
export * from "./inventory"
|
||||||
export * from "./line-item"
|
export * from "./line-item"
|
||||||
export * from "./payment-collection"
|
export * from "./payment-collection"
|
||||||
export * from "./price-list"
|
|
||||||
export * from "./product"
|
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 CustomerHandlers from "./customer"
|
||||||
export * as InventoryHandlers from "./inventory"
|
export * as InventoryHandlers from "./inventory"
|
||||||
export * as MiddlewaresHandlers from "./middlewares"
|
export * as MiddlewaresHandlers from "./middlewares"
|
||||||
export * as PriceListHandlers from "./price-list"
|
|
||||||
export * as ProductHandlers from "./product"
|
export * as ProductHandlers from "./product"
|
||||||
export * as RegionHandlers from "./region"
|
export * as RegionHandlers from "./region"
|
||||||
export * as SalesChannelHandlers from "./sales-channel"
|
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 * as Handlers from "./handlers"
|
||||||
export * from "./invite"
|
export * from "./invite"
|
||||||
export * from "./payment"
|
export * from "./payment"
|
||||||
|
export * from "./price-list"
|
||||||
export * from "./pricing"
|
export * from "./pricing"
|
||||||
export * from "./product"
|
export * from "./product"
|
||||||
export * from "./promotion"
|
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 "./create-price-lists"
|
||||||
export * from "./remove-price-lists"
|
export * from "./delete-price-lists"
|
||||||
export * from "./remove-price-list-prices"
|
export * from "./remove-price-list-prices"
|
||||||
export * from "./remove-product-prices"
|
|
||||||
export * from "./remove-variant-prices"
|
|
||||||
export * from "./update-price-lists"
|
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,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { FindParams, extendedFindParamsMixin } from "../../../types/common"
|
import { Type } from "class-transformer"
|
||||||
import {
|
import {
|
||||||
IsArray,
|
IsArray,
|
||||||
IsDateString,
|
IsDateString,
|
||||||
@@ -9,10 +9,9 @@ import {
|
|||||||
IsString,
|
IsString,
|
||||||
ValidateNested,
|
ValidateNested,
|
||||||
} from "class-validator"
|
} from "class-validator"
|
||||||
import { Transform, Type } from "class-transformer"
|
import { FindParams, extendedFindParamsMixin } from "../../../types/common"
|
||||||
|
|
||||||
import { CampaignBudgetType } from "@medusajs/utils"
|
import { CampaignBudgetType } from "@medusajs/utils"
|
||||||
import { transformOptionalDate } from "../../../utils/validators/date-transform"
|
|
||||||
|
|
||||||
export class AdminGetCampaignsCampaignParams extends FindParams {}
|
export class AdminGetCampaignsCampaignParams extends FindParams {}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
import {
|
||||||
|
removePriceListPricesWorkflow,
|
||||||
|
upsertPriceListPricesWorkflow,
|
||||||
|
} from "@medusajs/core-flows"
|
||||||
|
import {
|
||||||
|
AuthenticatedMedusaRequest,
|
||||||
|
MedusaResponse,
|
||||||
|
} from "../../../../../types/routing"
|
||||||
|
import { listPriceLists } from "../../queries"
|
||||||
|
import {
|
||||||
|
adminPriceListRemoteQueryFields,
|
||||||
|
defaultAdminPriceListFields,
|
||||||
|
} from "../../query-config"
|
||||||
|
import {
|
||||||
|
AdminDeletePriceListsPriceListPricesReq,
|
||||||
|
AdminPostPriceListsPriceListPricesReq,
|
||||||
|
} from "../../validators"
|
||||||
|
|
||||||
|
export const POST = async (
|
||||||
|
req: AuthenticatedMedusaRequest<AdminPostPriceListsPriceListPricesReq>,
|
||||||
|
res: MedusaResponse
|
||||||
|
) => {
|
||||||
|
const { prices } = req.validatedBody
|
||||||
|
const id = req.params.id
|
||||||
|
const workflow = upsertPriceListPricesWorkflow(req.scope)
|
||||||
|
const { errors } = await workflow.run({
|
||||||
|
input: {
|
||||||
|
price_lists_data: [{ id, prices }],
|
||||||
|
},
|
||||||
|
throwOnError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (Array.isArray(errors) && errors[0]) {
|
||||||
|
throw errors[0].error
|
||||||
|
}
|
||||||
|
|
||||||
|
const [[priceList]] = await listPriceLists({
|
||||||
|
container: req.scope,
|
||||||
|
remoteQueryFields: adminPriceListRemoteQueryFields,
|
||||||
|
apiFields: defaultAdminPriceListFields,
|
||||||
|
variables: { filters: { id }, skip: 0, take: 1 },
|
||||||
|
})
|
||||||
|
|
||||||
|
res.status(200).json({ price_list: priceList })
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DELETE = async (
|
||||||
|
req: AuthenticatedMedusaRequest<AdminDeletePriceListsPriceListPricesReq>,
|
||||||
|
res: MedusaResponse
|
||||||
|
) => {
|
||||||
|
const { ids } = req.validatedBody
|
||||||
|
const workflow = removePriceListPricesWorkflow(req.scope)
|
||||||
|
|
||||||
|
const { errors } = await workflow.run({
|
||||||
|
input: { ids },
|
||||||
|
throwOnError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (Array.isArray(errors) && errors[0]) {
|
||||||
|
throw errors[0].error
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
ids,
|
||||||
|
object: "price_list_prices",
|
||||||
|
deleted: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,10 +1,18 @@
|
|||||||
|
import {
|
||||||
|
deletePriceListsWorkflow,
|
||||||
|
updatePriceListsWorkflow,
|
||||||
|
} from "@medusajs/core-flows"
|
||||||
import { MedusaError } from "@medusajs/utils"
|
import { MedusaError } from "@medusajs/utils"
|
||||||
import {
|
import {
|
||||||
AuthenticatedMedusaRequest,
|
AuthenticatedMedusaRequest,
|
||||||
MedusaResponse,
|
MedusaResponse,
|
||||||
} from "../../../../types/routing"
|
} from "../../../../types/routing"
|
||||||
import { listPriceLists } from "../queries"
|
import { listPriceLists } from "../queries"
|
||||||
import { adminPriceListRemoteQueryFields } from "../query-config"
|
import {
|
||||||
|
adminPriceListRemoteQueryFields,
|
||||||
|
defaultAdminPriceListFields,
|
||||||
|
} from "../query-config"
|
||||||
|
import { AdminPostPriceListsPriceListReq } from "../validators"
|
||||||
|
|
||||||
export const GET = async (
|
export const GET = async (
|
||||||
req: AuthenticatedMedusaRequest,
|
req: AuthenticatedMedusaRequest,
|
||||||
@@ -31,3 +39,52 @@ export const GET = async (
|
|||||||
|
|
||||||
res.status(200).json({ price_list: priceList })
|
res.status(200).json({ price_list: priceList })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const POST = async (
|
||||||
|
req: AuthenticatedMedusaRequest<AdminPostPriceListsPriceListReq>,
|
||||||
|
res: MedusaResponse
|
||||||
|
) => {
|
||||||
|
const id = req.params.id
|
||||||
|
const workflow = updatePriceListsWorkflow(req.scope)
|
||||||
|
|
||||||
|
const { errors } = await workflow.run({
|
||||||
|
input: { price_lists_data: [{ id, ...req.validatedBody }] },
|
||||||
|
throwOnError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (Array.isArray(errors) && errors[0]) {
|
||||||
|
throw errors[0].error
|
||||||
|
}
|
||||||
|
|
||||||
|
const [[priceList]] = await listPriceLists({
|
||||||
|
container: req.scope,
|
||||||
|
remoteQueryFields: adminPriceListRemoteQueryFields,
|
||||||
|
apiFields: defaultAdminPriceListFields,
|
||||||
|
variables: { filters: { id }, skip: 0, take: 1 },
|
||||||
|
})
|
||||||
|
|
||||||
|
res.status(200).json({ price_list: priceList })
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DELETE = async (
|
||||||
|
req: AuthenticatedMedusaRequest,
|
||||||
|
res: MedusaResponse
|
||||||
|
) => {
|
||||||
|
const id = req.params.id
|
||||||
|
const workflow = deletePriceListsWorkflow(req.scope)
|
||||||
|
|
||||||
|
const { errors } = await workflow.run({
|
||||||
|
input: { ids: [id] },
|
||||||
|
throwOnError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (Array.isArray(errors) && errors[0]) {
|
||||||
|
throw errors[0].error
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
id,
|
||||||
|
object: "price_list",
|
||||||
|
deleted: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,10 +1,14 @@
|
|||||||
import { transformQuery } from "../../../api/middlewares"
|
import { transformBody, transformQuery } from "../../../api/middlewares"
|
||||||
import { MiddlewareRoute } from "../../../loaders/helpers/routing/types"
|
import { MiddlewareRoute } from "../../../loaders/helpers/routing/types"
|
||||||
import { authenticate } from "../../../utils/authenticate-middleware"
|
import { authenticate } from "../../../utils/authenticate-middleware"
|
||||||
import * as QueryConfig from "./query-config"
|
import * as QueryConfig from "./query-config"
|
||||||
import {
|
import {
|
||||||
|
AdminDeletePriceListsPriceListPricesReq,
|
||||||
AdminGetPriceListsParams,
|
AdminGetPriceListsParams,
|
||||||
AdminGetPriceListsPriceListParams,
|
AdminGetPriceListsPriceListParams,
|
||||||
|
AdminPostPriceListsPriceListPricesReq,
|
||||||
|
AdminPostPriceListsPriceListReq,
|
||||||
|
AdminPostPriceListsReq,
|
||||||
} from "./validators"
|
} from "./validators"
|
||||||
|
|
||||||
export const adminPriceListsRoutesMiddlewares: MiddlewareRoute[] = [
|
export const adminPriceListsRoutesMiddlewares: MiddlewareRoute[] = [
|
||||||
@@ -33,4 +37,24 @@ export const adminPriceListsRoutesMiddlewares: MiddlewareRoute[] = [
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
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",
|
||||||
|
middlewares: [transformBody(AdminPostPriceListsPriceListPricesReq)],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: ["DELETE"],
|
||||||
|
matcher: "/admin/price-lists/:id/prices",
|
||||||
|
middlewares: [transformBody(AdminDeletePriceListsPriceListPricesReq)],
|
||||||
|
},
|
||||||
]
|
]
|
||||||
@@ -1,11 +1,8 @@
|
|||||||
import {
|
import { MedusaContainer } from "@medusajs/types"
|
||||||
MedusaContainer,
|
|
||||||
PriceListRuleDTO,
|
|
||||||
PriceSetMoneyAmountDTO,
|
|
||||||
ProductVariantDTO,
|
|
||||||
} from "@medusajs/types"
|
|
||||||
import {
|
import {
|
||||||
ContainerRegistrationKeys,
|
ContainerRegistrationKeys,
|
||||||
|
buildPriceListRules,
|
||||||
|
buildPriceSetPricesForCore,
|
||||||
remoteQueryObjectFromString,
|
remoteQueryObjectFromString,
|
||||||
} from "@medusajs/utils"
|
} from "@medusajs/utils"
|
||||||
import { cleanResponseData } from "../../../../utils/clean-response-data"
|
import { cleanResponseData } from "../../../../utils/clean-response-data"
|
||||||
@@ -37,7 +34,7 @@ export async function listPriceLists({
|
|||||||
|
|
||||||
for (const priceList of priceLists) {
|
for (const priceList of priceLists) {
|
||||||
priceList.rules = buildPriceListRules(priceList.price_list_rules || [])
|
priceList.rules = buildPriceListRules(priceList.price_list_rules || [])
|
||||||
priceList.prices = buildPriceSetPrices(
|
priceList.prices = buildPriceSetPricesForCore(
|
||||||
priceList.price_set_money_amounts || []
|
priceList.price_set_money_amounts || []
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -48,43 +45,3 @@ export async function listPriceLists({
|
|||||||
|
|
||||||
return [sanitizedPriceLists, metadata.count]
|
return [sanitizedPriceLists, metadata.count]
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildPriceListRules(
|
|
||||||
priceListRules: PriceListRuleDTO[]
|
|
||||||
): Record<string, string[]> {
|
|
||||||
return priceListRules.reduce((acc, curr) => {
|
|
||||||
const ruleAttribute = curr.rule_type.rule_attribute
|
|
||||||
const ruleValues = curr.price_list_rule_values || []
|
|
||||||
|
|
||||||
if (ruleAttribute) {
|
|
||||||
acc[ruleAttribute] = ruleValues.map((ruleValue) => ruleValue.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
return acc
|
|
||||||
}, {})
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildPriceSetPrices(
|
|
||||||
priceSetMoneyAmounts: (PriceSetMoneyAmountDTO & {
|
|
||||||
price_set: PriceSetMoneyAmountDTO["price_set"] & {
|
|
||||||
variant?: ProductVariantDTO
|
|
||||||
}
|
|
||||||
})[]
|
|
||||||
): Record<string, any>[] {
|
|
||||||
return priceSetMoneyAmounts.map((priceSetMoneyAmount) => {
|
|
||||||
const productVariant = priceSetMoneyAmount.price_set?.variant
|
|
||||||
const rules = priceSetMoneyAmount.price_rules?.reduce((acc, curr) => {
|
|
||||||
if (curr.rule_type.rule_attribute) {
|
|
||||||
acc[curr.rule_type.rule_attribute] = curr.value
|
|
||||||
}
|
|
||||||
|
|
||||||
return acc
|
|
||||||
}, {})
|
|
||||||
|
|
||||||
return {
|
|
||||||
...priceSetMoneyAmount.money_amount,
|
|
||||||
variant_id: productVariant?.id ?? null,
|
|
||||||
rules,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
|
import { createPriceListsWorkflow } from "@medusajs/core-flows"
|
||||||
import {
|
import {
|
||||||
AuthenticatedMedusaRequest,
|
AuthenticatedMedusaRequest,
|
||||||
MedusaResponse,
|
MedusaResponse,
|
||||||
} from "../../../types/routing"
|
} from "../../../types/routing"
|
||||||
import { listPriceLists } from "./queries"
|
import { listPriceLists } from "./queries"
|
||||||
import { adminPriceListRemoteQueryFields } from "./query-config"
|
import {
|
||||||
|
adminPriceListRemoteQueryFields,
|
||||||
|
defaultAdminPriceListFields,
|
||||||
|
} from "./query-config"
|
||||||
|
import { AdminPostPriceListsReq } from "./validators"
|
||||||
|
|
||||||
export const GET = async (
|
export const GET = async (
|
||||||
req: AuthenticatedMedusaRequest,
|
req: AuthenticatedMedusaRequest,
|
||||||
@@ -29,3 +34,31 @@ export const GET = async (
|
|||||||
limit,
|
limit,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const POST = async (
|
||||||
|
req: AuthenticatedMedusaRequest<AdminPostPriceListsReq>,
|
||||||
|
res: MedusaResponse
|
||||||
|
) => {
|
||||||
|
const workflow = createPriceListsWorkflow(req.scope)
|
||||||
|
const { result, errors } = await workflow.run({
|
||||||
|
input: { price_lists_data: [req.validatedBody] },
|
||||||
|
throwOnError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (Array.isArray(errors) && errors[0]) {
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
res.status(200).json({ price_list: priceList })
|
||||||
|
}
|
||||||
@@ -1,4 +1,152 @@
|
|||||||
|
import { PriceListStatus, PriceListType } from "@medusajs/types"
|
||||||
|
import { Transform, Type } from "class-transformer"
|
||||||
|
import {
|
||||||
|
IsArray,
|
||||||
|
IsEnum,
|
||||||
|
IsInt,
|
||||||
|
IsObject,
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
ValidateIf,
|
||||||
|
ValidateNested,
|
||||||
|
} from "class-validator"
|
||||||
import { FindParams } from "../../../types/common"
|
import { FindParams } from "../../../types/common"
|
||||||
|
import { transformOptionalDate } from "../../../utils/validators/date-transform"
|
||||||
|
|
||||||
export class AdminGetPriceListsParams extends FindParams {}
|
export class AdminGetPriceListsParams extends FindParams {}
|
||||||
export class AdminGetPriceListsPriceListParams extends FindParams {}
|
export class AdminGetPriceListsPriceListParams extends FindParams {}
|
||||||
|
|
||||||
|
export class AdminPostPriceListsReq {
|
||||||
|
@IsString()
|
||||||
|
title: string
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
description: string
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@Transform(transformOptionalDate)
|
||||||
|
starts_at?: string
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@Transform(transformOptionalDate)
|
||||||
|
ends_at?: string
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsEnum(PriceListStatus)
|
||||||
|
status?: PriceListStatus
|
||||||
|
|
||||||
|
@IsEnum(PriceListType)
|
||||||
|
type: PriceListType
|
||||||
|
|
||||||
|
@IsArray()
|
||||||
|
@Type(() => AdminPriceListPricesCreateReq)
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
prices: AdminPriceListPricesCreateReq[]
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsObject()
|
||||||
|
rules?: Record<string, string[]>
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AdminPriceListPricesCreateReq {
|
||||||
|
@IsString()
|
||||||
|
currency_code: string
|
||||||
|
|
||||||
|
@IsInt()
|
||||||
|
amount: number
|
||||||
|
|
||||||
|
@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 | AdminPriceListPricesUpdateReq)[]
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsObject()
|
||||||
|
rules?: Record<string, string[]>
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AdminPostPriceListsPriceListPricesReq {
|
||||||
|
@IsOptional()
|
||||||
|
@IsArray()
|
||||||
|
prices: (AdminPriceListPricesCreateReq | AdminPriceListPricesUpdateReq)[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AdminDeletePriceListsPriceListPricesReq {
|
||||||
|
@IsOptional()
|
||||||
|
@IsArray()
|
||||||
|
@IsString({ each: true })
|
||||||
|
ids: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AdminPriceListPricesUpdateReq {
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
id: string
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@ValidateIf((object) => !object.id)
|
||||||
|
@IsString()
|
||||||
|
currency_code?: string
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@ValidateIf((object) => !object.id)
|
||||||
|
@IsInt()
|
||||||
|
amount?: number
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@ValidateIf((object) => !object.id)
|
||||||
|
@IsString()
|
||||||
|
variant_id: string
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsInt()
|
||||||
|
min_quantity?: number
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsInt()
|
||||||
|
max_quantity?: number
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsObject()
|
||||||
|
rules?: Record<string, string>
|
||||||
|
}
|
||||||
@@ -1,6 +1,3 @@
|
|||||||
import { updatePriceLists } from "@medusajs/core-flows"
|
|
||||||
import { MedusaContainer } from "@medusajs/types"
|
|
||||||
import { MedusaV2Flag } from "@medusajs/utils"
|
|
||||||
import { Type } from "class-transformer"
|
import { Type } from "class-transformer"
|
||||||
import { IsArray, IsBoolean, IsOptional, ValidateNested } from "class-validator"
|
import { IsArray, IsBoolean, IsOptional, ValidateNested } from "class-validator"
|
||||||
import { EntityManager } from "typeorm"
|
import { EntityManager } from "typeorm"
|
||||||
@@ -9,7 +6,6 @@ import { PriceList } from "../../../.."
|
|||||||
import PriceListService from "../../../../services/price-list"
|
import PriceListService from "../../../../services/price-list"
|
||||||
import { AdminPriceListPricesUpdateReq } from "../../../../types/price-list"
|
import { AdminPriceListPricesUpdateReq } from "../../../../types/price-list"
|
||||||
import { validator } from "../../../../utils/validator"
|
import { validator } from "../../../../utils/validator"
|
||||||
import { getPriceListPricingModule } from "./modules-queries"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [post] /admin/price-lists/{id}/prices/batch
|
* @oas [post] /admin/price-lists/{id}/prices/batch
|
||||||
@@ -124,48 +120,22 @@ import { getPriceListPricingModule } from "./modules-queries"
|
|||||||
*/
|
*/
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const { id } = req.params
|
const { id } = req.params
|
||||||
let priceList
|
|
||||||
const featureFlagRouter = req.scope.resolve("featureFlagRouter")
|
|
||||||
const manager: EntityManager = req.scope.resolve("manager")
|
const manager: EntityManager = req.scope.resolve("manager")
|
||||||
const priceListService: PriceListService =
|
const priceListService: PriceListService =
|
||||||
req.scope.resolve("priceListService")
|
req.scope.resolve("priceListService")
|
||||||
|
|
||||||
const validated = await validator(AdminPostPriceListPricesPricesReq, req.body)
|
const validated = await validator(AdminPostPriceListPricesPricesReq, req.body)
|
||||||
|
|
||||||
if (featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) {
|
|
||||||
const updatePriceListWorkflow = updatePriceLists(req.scope)
|
|
||||||
|
|
||||||
const input = {
|
|
||||||
price_lists: [
|
|
||||||
{
|
|
||||||
id,
|
|
||||||
...validated,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
await updatePriceListWorkflow.run({
|
|
||||||
input,
|
|
||||||
context: {
|
|
||||||
manager,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
priceList = await getPriceListPricingModule(id, {
|
|
||||||
container: req.scope as MedusaContainer,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
await manager.transaction(async (transactionManager) => {
|
await manager.transaction(async (transactionManager) => {
|
||||||
await priceListService
|
await priceListService
|
||||||
.withTransaction(transactionManager)
|
.withTransaction(transactionManager)
|
||||||
.addPrices(id, validated.prices, validated.override)
|
.addPrices(id, validated.prices, validated.override)
|
||||||
})
|
})
|
||||||
|
|
||||||
priceList = await priceListService.retrieve(id, {
|
const priceList = await priceListService.retrieve(id, {
|
||||||
select: defaultAdminPriceListFields as (keyof PriceList)[],
|
select: defaultAdminPriceListFields as (keyof PriceList)[],
|
||||||
relations: defaultAdminPriceListRelations,
|
relations: defaultAdminPriceListRelations,
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
res.json({ price_list: priceList })
|
res.json({ price_list: priceList })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,4 @@
|
|||||||
import { MedusaContainer, PricingTypes, WorkflowTypes } from "@medusajs/types"
|
import { PriceListStatus, PriceListType } from "@medusajs/utils"
|
||||||
import {
|
|
||||||
FlagRouter,
|
|
||||||
MedusaV2Flag,
|
|
||||||
PriceListStatus,
|
|
||||||
PriceListType,
|
|
||||||
} from "@medusajs/utils"
|
|
||||||
import { createPriceLists } from "@medusajs/core-flows"
|
|
||||||
import { Transform, Type } from "class-transformer"
|
import { Transform, Type } from "class-transformer"
|
||||||
import {
|
import {
|
||||||
IsArray,
|
IsArray,
|
||||||
@@ -26,7 +19,6 @@ import {
|
|||||||
CreatePriceListInput,
|
CreatePriceListInput,
|
||||||
} from "../../../../types/price-list"
|
} from "../../../../types/price-list"
|
||||||
import { FeatureFlagDecorators } from "../../../../utils/feature-flag-decorators"
|
import { FeatureFlagDecorators } from "../../../../utils/feature-flag-decorators"
|
||||||
import { getPriceListPricingModule } from "./modules-queries"
|
|
||||||
import { transformOptionalDate } from "../../../../utils/validators/date-transform"
|
import { transformOptionalDate } from "../../../../utils/validators/date-transform"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -155,47 +147,8 @@ export default async (req: Request, res) => {
|
|||||||
req.scope.resolve("priceListService")
|
req.scope.resolve("priceListService")
|
||||||
|
|
||||||
const manager: EntityManager = req.scope.resolve("manager")
|
const manager: EntityManager = req.scope.resolve("manager")
|
||||||
const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter")
|
|
||||||
let priceList
|
|
||||||
|
|
||||||
const isMedusaV2FlagEnabled = featureFlagRouter.isFeatureEnabled(
|
let priceList = await manager.transaction(async (transactionManager) => {
|
||||||
MedusaV2Flag.key
|
|
||||||
)
|
|
||||||
|
|
||||||
if (isMedusaV2FlagEnabled) {
|
|
||||||
const createPriceListWorkflow = createPriceLists(req.scope)
|
|
||||||
const validatedInput = req.validatedBody as CreatePriceListInput
|
|
||||||
const rules: PricingTypes.CreatePriceListRules = {}
|
|
||||||
const customerGroups = validatedInput?.customer_groups || []
|
|
||||||
delete validatedInput.customer_groups
|
|
||||||
|
|
||||||
if (customerGroups.length) {
|
|
||||||
rules["customer_group_id"] = customerGroups.map((cg) => cg.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
const input = {
|
|
||||||
price_lists: [
|
|
||||||
{
|
|
||||||
...validatedInput,
|
|
||||||
rules,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
} as WorkflowTypes.PriceListWorkflow.CreatePriceListWorkflowInputDTO
|
|
||||||
|
|
||||||
const { result } = await createPriceListWorkflow.run({
|
|
||||||
input,
|
|
||||||
context: {
|
|
||||||
manager,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
priceList = result[0]!.priceList
|
|
||||||
|
|
||||||
priceList = await getPriceListPricingModule(priceList.id, {
|
|
||||||
container: req.scope as MedusaContainer,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
priceList = await manager.transaction(async (transactionManager) => {
|
|
||||||
return await priceListService
|
return await priceListService
|
||||||
.withTransaction(transactionManager)
|
.withTransaction(transactionManager)
|
||||||
.create(req.validatedBody as CreatePriceListInput)
|
.create(req.validatedBody as CreatePriceListInput)
|
||||||
@@ -205,7 +158,6 @@ export default async (req: Request, res) => {
|
|||||||
select: defaultAdminPriceListFields as (keyof PriceList)[],
|
select: defaultAdminPriceListFields as (keyof PriceList)[],
|
||||||
relations: defaultAdminPriceListRelations,
|
relations: defaultAdminPriceListRelations,
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
res.json({ price_list: priceList })
|
res.json({ price_list: priceList })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
import { WorkflowTypes } from "@medusajs/types"
|
|
||||||
import { FlagRouter, MedusaV2Flag } from "@medusajs/utils"
|
|
||||||
import { removePriceLists } from "@medusajs/core-flows"
|
|
||||||
import { EntityManager } from "typeorm"
|
import { EntityManager } from "typeorm"
|
||||||
import PriceListService from "../../../../services/price-list"
|
import PriceListService from "../../../../services/price-list"
|
||||||
|
|
||||||
@@ -86,34 +83,13 @@ import PriceListService from "../../../../services/price-list"
|
|||||||
*/
|
*/
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const { id } = req.params
|
const { id } = req.params
|
||||||
|
|
||||||
const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter")
|
|
||||||
const manager: EntityManager = req.scope.resolve("manager")
|
const manager: EntityManager = req.scope.resolve("manager")
|
||||||
|
|
||||||
const isMedusaV2FlagEnabled = featureFlagRouter.isFeatureEnabled(
|
|
||||||
MedusaV2Flag.key
|
|
||||||
)
|
|
||||||
|
|
||||||
if (isMedusaV2FlagEnabled) {
|
|
||||||
const removePriceListsWorkflow = removePriceLists(req.scope)
|
|
||||||
|
|
||||||
const input = {
|
|
||||||
price_lists: [id],
|
|
||||||
} as WorkflowTypes.PriceListWorkflow.RemovePriceListWorkflowInputDTO
|
|
||||||
|
|
||||||
await removePriceListsWorkflow.run({
|
|
||||||
input,
|
|
||||||
context: {
|
|
||||||
manager,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
const priceListService: PriceListService =
|
const priceListService: PriceListService =
|
||||||
req.scope.resolve("priceListService")
|
req.scope.resolve("priceListService")
|
||||||
await manager.transaction(async (transactionManager) => {
|
await manager.transaction(async (transactionManager) => {
|
||||||
await priceListService.withTransaction(transactionManager).delete(id)
|
await priceListService.withTransaction(transactionManager).delete(id)
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
id,
|
id,
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import { FlagRouter, MedusaV2Flag } from "@medusajs/utils"
|
|
||||||
import { ArrayNotEmpty, IsString } from "class-validator"
|
import { ArrayNotEmpty, IsString } from "class-validator"
|
||||||
import { EntityManager } from "typeorm"
|
import { EntityManager } from "typeorm"
|
||||||
import PriceListService from "../../../../services/price-list"
|
import PriceListService from "../../../../services/price-list"
|
||||||
import { validator } from "../../../../utils/validator"
|
import { validator } from "../../../../utils/validator"
|
||||||
import { WorkflowTypes } from "@medusajs/types"
|
|
||||||
import { removePriceListPrices } from "@medusajs/core-flows"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [delete] /admin/price-lists/{id}/prices/batch
|
* @oas [delete] /admin/price-lists/{id}/prices/batch
|
||||||
@@ -101,43 +98,20 @@ import { removePriceListPrices } from "@medusajs/core-flows"
|
|||||||
*/
|
*/
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const { id } = req.params
|
const { id } = req.params
|
||||||
|
|
||||||
const validated = await validator(
|
const validated = await validator(
|
||||||
AdminDeletePriceListPricesPricesReq,
|
AdminDeletePriceListPricesPricesReq,
|
||||||
req.body
|
req.body
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const manager: EntityManager = req.scope.resolve("manager")
|
||||||
const priceListService: PriceListService =
|
const priceListService: PriceListService =
|
||||||
req.scope.resolve("priceListService")
|
req.scope.resolve("priceListService")
|
||||||
const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter")
|
|
||||||
|
|
||||||
const manager: EntityManager = req.scope.resolve("manager")
|
|
||||||
|
|
||||||
const isMedusaV2FlagEnabled = featureFlagRouter.isFeatureEnabled(
|
|
||||||
MedusaV2Flag.key
|
|
||||||
)
|
|
||||||
|
|
||||||
if (isMedusaV2FlagEnabled) {
|
|
||||||
const deletePriceListPricesWorkflow = removePriceListPrices(req.scope)
|
|
||||||
|
|
||||||
const input = {
|
|
||||||
price_list_id: id,
|
|
||||||
money_amount_ids: validated.price_ids,
|
|
||||||
} as WorkflowTypes.PriceListWorkflow.RemovePriceListPricesWorkflowInputDTO
|
|
||||||
|
|
||||||
await deletePriceListPricesWorkflow.run({
|
|
||||||
input,
|
|
||||||
context: {
|
|
||||||
manager,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
await manager.transaction(async (transactionManager) => {
|
await manager.transaction(async (transactionManager) => {
|
||||||
await priceListService
|
await priceListService
|
||||||
.withTransaction(transactionManager)
|
.withTransaction(transactionManager)
|
||||||
.deletePrices(id, validated.price_ids)
|
.deletePrices(id, validated.price_ids)
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
res.json({ ids: validated.price_ids, object: "money-amount", deleted: true })
|
res.json({ ids: validated.price_ids, object: "money-amount", deleted: true })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
import { WorkflowTypes } from "@medusajs/types"
|
|
||||||
import { FlagRouter, MedusaV2Flag } from "@medusajs/utils"
|
|
||||||
import { removePriceListProductPrices } from "@medusajs/core-flows"
|
|
||||||
import { EntityManager } from "typeorm"
|
import { EntityManager } from "typeorm"
|
||||||
import PriceListService from "../../../../services/price-list"
|
import PriceListService from "../../../../services/price-list"
|
||||||
|
|
||||||
@@ -94,47 +91,18 @@ import PriceListService from "../../../../services/price-list"
|
|||||||
*/
|
*/
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const { id, product_id } = req.params
|
const { id, product_id } = req.params
|
||||||
|
|
||||||
const priceListService: PriceListService =
|
const priceListService: PriceListService =
|
||||||
req.scope.resolve("priceListService")
|
req.scope.resolve("priceListService")
|
||||||
|
|
||||||
const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter")
|
|
||||||
const manager: EntityManager = req.scope.resolve("manager")
|
const manager: EntityManager = req.scope.resolve("manager")
|
||||||
|
|
||||||
const isMedusaV2FlagEnabled = featureFlagRouter.isFeatureEnabled(
|
|
||||||
MedusaV2Flag.key
|
|
||||||
)
|
|
||||||
|
|
||||||
let deletedPriceIds: string[] = []
|
let deletedPriceIds: string[] = []
|
||||||
|
|
||||||
if (isMedusaV2FlagEnabled) {
|
const [deletedIds] = await manager.transaction(async (transactionManager) => {
|
||||||
const deletePriceListProductsWorkflow = removePriceListProductPrices(
|
|
||||||
req.scope
|
|
||||||
)
|
|
||||||
|
|
||||||
const input = {
|
|
||||||
product_ids: [product_id],
|
|
||||||
price_list_id: id,
|
|
||||||
} as WorkflowTypes.PriceListWorkflow.RemovePriceListProductsWorkflowInputDTO
|
|
||||||
|
|
||||||
const { result } = await deletePriceListProductsWorkflow.run({
|
|
||||||
input,
|
|
||||||
context: {
|
|
||||||
manager,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
deletedPriceIds = result
|
|
||||||
} else {
|
|
||||||
const [deletedIds] = await manager.transaction(
|
|
||||||
async (transactionManager) => {
|
|
||||||
return await priceListService
|
return await priceListService
|
||||||
.withTransaction(transactionManager)
|
.withTransaction(transactionManager)
|
||||||
.deleteProductPrices(id, [product_id])
|
.deleteProductPrices(id, [product_id])
|
||||||
}
|
})
|
||||||
)
|
|
||||||
deletedPriceIds = deletedIds
|
deletedPriceIds = deletedIds
|
||||||
}
|
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
ids: deletedPriceIds,
|
ids: deletedPriceIds,
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
import { FlagRouter, MedusaV2Flag } from "@medusajs/utils"
|
|
||||||
import { removePriceListProductPrices } from "@medusajs/core-flows"
|
|
||||||
import { ArrayNotEmpty, IsString } from "class-validator"
|
import { ArrayNotEmpty, IsString } from "class-validator"
|
||||||
import { Request, Response } from "express"
|
import { Request, Response } from "express"
|
||||||
import { EntityManager } from "typeorm"
|
import { EntityManager } from "typeorm"
|
||||||
import PriceListService from "../../../../services/price-list"
|
import PriceListService from "../../../../services/price-list"
|
||||||
import { validator } from "../../../../utils/validator"
|
import { validator } from "../../../../utils/validator"
|
||||||
import { WorkflowTypes } from "@medusajs/types"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [delete] /admin/price-lists/{id}/products/prices/batch
|
* @oas [delete] /admin/price-lists/{id}/products/prices/batch
|
||||||
@@ -114,43 +111,16 @@ export default async (req: Request, res: Response) => {
|
|||||||
const priceListService: PriceListService =
|
const priceListService: PriceListService =
|
||||||
req.scope.resolve("priceListService")
|
req.scope.resolve("priceListService")
|
||||||
|
|
||||||
const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter")
|
|
||||||
const manager: EntityManager = req.scope.resolve("manager")
|
const manager: EntityManager = req.scope.resolve("manager")
|
||||||
|
|
||||||
const isMedusaV2FlagEnabled = featureFlagRouter.isFeatureEnabled(
|
|
||||||
MedusaV2Flag.key
|
|
||||||
)
|
|
||||||
|
|
||||||
let deletedPriceIds: string[] = []
|
let deletedPriceIds: string[] = []
|
||||||
|
|
||||||
if (isMedusaV2FlagEnabled) {
|
const [deletedIds] = await manager.transaction(async (transactionManager) => {
|
||||||
const deletePriceListProductsWorkflow = removePriceListProductPrices(
|
|
||||||
req.scope
|
|
||||||
)
|
|
||||||
|
|
||||||
const input = {
|
|
||||||
product_ids: validated.product_ids,
|
|
||||||
price_list_id: id,
|
|
||||||
} as WorkflowTypes.PriceListWorkflow.RemovePriceListProductsWorkflowInputDTO
|
|
||||||
|
|
||||||
const { result } = await deletePriceListProductsWorkflow.run({
|
|
||||||
input,
|
|
||||||
context: {
|
|
||||||
manager,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
deletedPriceIds = result
|
|
||||||
} else {
|
|
||||||
const [deletedIds] = await manager.transaction(
|
|
||||||
async (transactionManager) => {
|
|
||||||
return await priceListService
|
return await priceListService
|
||||||
.withTransaction(transactionManager)
|
.withTransaction(transactionManager)
|
||||||
.deleteProductPrices(id, validated.product_ids)
|
.deleteProductPrices(id, validated.product_ids)
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
|
||||||
deletedPriceIds = deletedIds
|
deletedPriceIds = deletedIds
|
||||||
}
|
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
ids: deletedPriceIds,
|
ids: deletedPriceIds,
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
import { FlagRouter, MedusaV2Flag } from "@medusajs/utils"
|
|
||||||
import { removePriceListVariantPrices } from "@medusajs/core-flows"
|
|
||||||
import { EntityManager } from "typeorm"
|
import { EntityManager } from "typeorm"
|
||||||
import PriceListService from "../../../../services/price-list"
|
import PriceListService from "../../../../services/price-list"
|
||||||
import { WorkflowTypes } from "@medusajs/types"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [delete] /admin/price-lists/{id}/variants/{variant_id}/prices
|
* @oas [delete] /admin/price-lists/{id}/variants/{variant_id}/prices
|
||||||
@@ -97,46 +94,16 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
const priceListService: PriceListService =
|
const priceListService: PriceListService =
|
||||||
req.scope.resolve("priceListService")
|
req.scope.resolve("priceListService")
|
||||||
const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter")
|
|
||||||
const manager: EntityManager = req.scope.resolve("manager")
|
const manager: EntityManager = req.scope.resolve("manager")
|
||||||
|
|
||||||
const isMedusaV2FlagEnabled = featureFlagRouter.isFeatureEnabled(
|
const [deletedIds] = await manager.transaction(async (transactionManager) => {
|
||||||
MedusaV2Flag.key
|
|
||||||
)
|
|
||||||
|
|
||||||
let deletedPriceIds: string[] = []
|
|
||||||
|
|
||||||
if (isMedusaV2FlagEnabled) {
|
|
||||||
const deletePriceListProductsWorkflow = removePriceListVariantPrices(
|
|
||||||
req.scope
|
|
||||||
)
|
|
||||||
|
|
||||||
const input = {
|
|
||||||
variant_ids: [variant_id],
|
|
||||||
price_list_id: id,
|
|
||||||
} as WorkflowTypes.PriceListWorkflow.RemovePriceListVariantsWorkflowInputDTO
|
|
||||||
|
|
||||||
const { result } = await deletePriceListProductsWorkflow.run({
|
|
||||||
input,
|
|
||||||
context: {
|
|
||||||
manager,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
deletedPriceIds = result
|
|
||||||
} else {
|
|
||||||
const [deletedIds] = await manager.transaction(
|
|
||||||
async (transactionManager) => {
|
|
||||||
return await priceListService
|
return await priceListService
|
||||||
.withTransaction(transactionManager)
|
.withTransaction(transactionManager)
|
||||||
.deleteVariantPrices(id, [variant_id])
|
.deleteVariantPrices(id, [variant_id])
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
|
||||||
deletedPriceIds = deletedIds
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
ids: deletedPriceIds,
|
ids: deletedIds,
|
||||||
object: "money-amount",
|
object: "money-amount",
|
||||||
deleted: true,
|
deleted: true,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -11,13 +11,12 @@ import {
|
|||||||
extendedFindParamsMixin,
|
extendedFindParamsMixin,
|
||||||
} from "../../../../types/common"
|
} from "../../../../types/common"
|
||||||
|
|
||||||
import { FlagRouter, MedusaV2Flag } from "@medusajs/utils"
|
|
||||||
import { Type } from "class-transformer"
|
import { Type } from "class-transformer"
|
||||||
import { Request } from "express"
|
import { Request } from "express"
|
||||||
import { ProductStatus } from "../../../../models"
|
import { ProductStatus } from "../../../../models"
|
||||||
import PriceListService from "../../../../services/price-list"
|
import PriceListService from "../../../../services/price-list"
|
||||||
import { FilterableProductProps } from "../../../../types/product"
|
import { FilterableProductProps } from "../../../../types/product"
|
||||||
import { IsType, listProducts } from "../../../../utils"
|
import { IsType } from "../../../../utils"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [get] /admin/price-lists/{id}/products
|
* @oas [get] /admin/price-lists/{id}/products
|
||||||
@@ -228,10 +227,6 @@ import { IsType, listProducts } from "../../../../utils"
|
|||||||
export default async (req: Request, res) => {
|
export default async (req: Request, res) => {
|
||||||
const { id } = req.params
|
const { id } = req.params
|
||||||
const { offset, limit } = req.validatedQuery
|
const { offset, limit } = req.validatedQuery
|
||||||
const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter")
|
|
||||||
let products
|
|
||||||
let count
|
|
||||||
|
|
||||||
const priceListService: PriceListService =
|
const priceListService: PriceListService =
|
||||||
req.scope.resolve("priceListService")
|
req.scope.resolve("priceListService")
|
||||||
|
|
||||||
@@ -240,19 +235,11 @@ export default async (req: Request, res) => {
|
|||||||
price_list_id: [id],
|
price_list_id: [id],
|
||||||
}
|
}
|
||||||
|
|
||||||
if (featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) {
|
const [products, count] = await priceListService.listProducts(
|
||||||
;[products, count] = await listProducts(
|
|
||||||
req.scope,
|
|
||||||
filterableFields,
|
|
||||||
req.listConfig
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
;[products, count] = await priceListService.listProducts(
|
|
||||||
id,
|
id,
|
||||||
filterableFields,
|
filterableFields,
|
||||||
req.listConfig
|
req.listConfig
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
products,
|
products,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { MedusaContainer, PricingTypes, WorkflowTypes } from "@medusajs/types"
|
import { PriceListStatus, PriceListType } from "@medusajs/utils"
|
||||||
import { MedusaV2Flag, PriceListStatus, PriceListType } from "@medusajs/utils"
|
|
||||||
import {
|
import {
|
||||||
IsArray,
|
IsArray,
|
||||||
IsBoolean,
|
IsBoolean,
|
||||||
@@ -10,7 +9,6 @@ import {
|
|||||||
} from "class-validator"
|
} from "class-validator"
|
||||||
import { defaultAdminPriceListFields, defaultAdminPriceListRelations } from "."
|
import { defaultAdminPriceListFields, defaultAdminPriceListRelations } from "."
|
||||||
|
|
||||||
import { updatePriceLists } from "@medusajs/core-flows"
|
|
||||||
import { Transform, Type } from "class-transformer"
|
import { Transform, Type } from "class-transformer"
|
||||||
import { EntityManager } from "typeorm"
|
import { EntityManager } from "typeorm"
|
||||||
import { PriceList } from "../../../.."
|
import { PriceList } from "../../../.."
|
||||||
@@ -19,7 +17,6 @@ import PriceListService from "../../../../services/price-list"
|
|||||||
import { AdminPriceListPricesUpdateReq } from "../../../../types/price-list"
|
import { AdminPriceListPricesUpdateReq } from "../../../../types/price-list"
|
||||||
import { FeatureFlagDecorators } from "../../../../utils/feature-flag-decorators"
|
import { FeatureFlagDecorators } from "../../../../utils/feature-flag-decorators"
|
||||||
import { validator } from "../../../../utils/validator"
|
import { validator } from "../../../../utils/validator"
|
||||||
import { getPriceListPricingModule } from "./modules-queries"
|
|
||||||
import { transformOptionalDate } from "../../../../utils/validators/date-transform"
|
import { transformOptionalDate } from "../../../../utils/validators/date-transform"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -119,8 +116,6 @@ import { transformOptionalDate } from "../../../../utils/validators/date-transfo
|
|||||||
*/
|
*/
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const { id } = req.params
|
const { id } = req.params
|
||||||
let priceList
|
|
||||||
const featureFlagRouter = req.scope.resolve("featureFlagRouter")
|
|
||||||
const manager: EntityManager = req.scope.resolve("manager")
|
const manager: EntityManager = req.scope.resolve("manager")
|
||||||
const priceListService: PriceListService =
|
const priceListService: PriceListService =
|
||||||
req.scope.resolve("priceListService")
|
req.scope.resolve("priceListService")
|
||||||
@@ -130,48 +125,16 @@ export default async (req, res) => {
|
|||||||
req.body
|
req.body
|
||||||
)
|
)
|
||||||
|
|
||||||
if (featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) {
|
|
||||||
const updateVariantsWorkflow = updatePriceLists(req.scope)
|
|
||||||
const customerGroups = validated.customer_groups
|
|
||||||
delete validated.customer_groups
|
|
||||||
|
|
||||||
const updatePriceListInput = {
|
|
||||||
id,
|
|
||||||
...validated,
|
|
||||||
} as PricingTypes.UpdatePriceListDTO
|
|
||||||
|
|
||||||
if (Array.isArray(customerGroups)) {
|
|
||||||
updatePriceListInput.rules = {
|
|
||||||
customer_group_id: customerGroups.map((group) => group.id),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const input = {
|
|
||||||
price_lists: [updatePriceListInput],
|
|
||||||
} as WorkflowTypes.PriceListWorkflow.UpdatePriceListWorkflowInputDTO
|
|
||||||
|
|
||||||
await updateVariantsWorkflow.run({
|
|
||||||
input,
|
|
||||||
context: {
|
|
||||||
manager,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
priceList = await getPriceListPricingModule(id, {
|
|
||||||
container: req.scope as MedusaContainer,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
await manager.transaction(async (transactionManager) => {
|
await manager.transaction(async (transactionManager) => {
|
||||||
return await priceListService
|
return await priceListService
|
||||||
.withTransaction(transactionManager)
|
.withTransaction(transactionManager)
|
||||||
.update(id, validated)
|
.update(id, validated)
|
||||||
})
|
})
|
||||||
|
|
||||||
priceList = await priceListService.retrieve(id, {
|
const priceList = await priceListService.retrieve(id, {
|
||||||
select: defaultAdminPriceListFields as (keyof PriceList)[],
|
select: defaultAdminPriceListFields as (keyof PriceList)[],
|
||||||
relations: defaultAdminPriceListRelations,
|
relations: defaultAdminPriceListRelations,
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
res.json({ price_list: priceList })
|
res.json({ price_list: priceList })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import express from "express"
|
|||||||
import loaders from "../loaders"
|
import loaders from "../loaders"
|
||||||
import Logger from "../loaders/logger"
|
import Logger from "../loaders/logger"
|
||||||
import { PriceList } from "../models"
|
import { PriceList } from "../models"
|
||||||
import { CurrencyService, PriceListService } from "../services"
|
import { PriceListService } from "../services"
|
||||||
import { createDefaultRuleTypes } from "./utils/create-default-rule-types"
|
import { createDefaultRuleTypes } from "./utils/create-default-rule-types"
|
||||||
import { migrateProductVariantPricing } from "./utils/migrate-money-amounts-to-pricing-module"
|
import { migrateProductVariantPricing } from "./utils/migrate-money-amounts-to-pricing-module"
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ const migratePriceLists = async (container: AwilixContainer) => {
|
|||||||
pricingModuleService.addPriceListPrices(
|
pricingModuleService.addPriceListPrices(
|
||||||
priceListsToUpdate.map((priceList) => {
|
priceListsToUpdate.map((priceList) => {
|
||||||
return {
|
return {
|
||||||
priceListId: priceList.id,
|
price_list_id: priceList.id,
|
||||||
prices: priceList.prices
|
prices: priceList.prices
|
||||||
.filter((price) =>
|
.filter((price) =>
|
||||||
variantIdPriceSetIdMap.has(price.variants?.[0]?.id)
|
variantIdPriceSetIdMap.has(price.variants?.[0]?.id)
|
||||||
@@ -136,7 +136,7 @@ const migratePriceLists = async (container: AwilixContainer) => {
|
|||||||
pricingModuleService.createPriceLists(
|
pricingModuleService.createPriceLists(
|
||||||
priceListsToCreate.map(
|
priceListsToCreate.map(
|
||||||
({ name: title, prices, customer_groups, ...priceList }) => {
|
({ name: title, prices, customer_groups, ...priceList }) => {
|
||||||
const createData: PricingTypes.CreatePriceListDTO = {
|
const createData: any = {
|
||||||
...priceList,
|
...priceList,
|
||||||
title,
|
title,
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -1,3 +1,4 @@
|
|||||||
|
import { Modules } from "@medusajs/modules-sdk"
|
||||||
import {
|
import {
|
||||||
CreatePriceRuleDTO,
|
CreatePriceRuleDTO,
|
||||||
CreatePriceSetDTO,
|
CreatePriceSetDTO,
|
||||||
@@ -5,9 +6,8 @@ import {
|
|||||||
PricingTypes,
|
PricingTypes,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
import { PriceListType } from "@medusajs/utils"
|
import { PriceListType } from "@medusajs/utils"
|
||||||
|
import { SuiteOptions, moduleIntegrationTestRunner } from "medusa-test-utils"
|
||||||
import { seedPriceData } from "../../../__fixtures__/seed-price-data"
|
import { seedPriceData } from "../../../__fixtures__/seed-price-data"
|
||||||
import { Modules } from "@medusajs/modules-sdk"
|
|
||||||
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
|
|
||||||
|
|
||||||
jest.setTimeout(30000)
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ const defaultRules = {
|
|||||||
region_id: ["DE", "DK"],
|
region_id: ["DE", "DK"],
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultPriceListPrices: PricingTypes.PriceListPriceDTO[] = [
|
const defaultPriceListPrices: PricingTypes.CreatePriceListPriceDTO[] = [
|
||||||
{
|
{
|
||||||
amount: 232,
|
amount: 232,
|
||||||
currency_code: "PLN",
|
currency_code: "PLN",
|
||||||
|
|||||||
+5
-5
@@ -1,10 +1,10 @@
|
|||||||
|
import { Modules } from "@medusajs/modules-sdk"
|
||||||
import { IPricingModuleService } from "@medusajs/types"
|
import { IPricingModuleService } from "@medusajs/types"
|
||||||
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||||
|
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
|
||||||
import { createPriceLists } from "../../../__fixtures__/price-list"
|
import { createPriceLists } from "../../../__fixtures__/price-list"
|
||||||
import { createPriceListRules } from "../../../__fixtures__/price-list-rules"
|
import { createPriceListRules } from "../../../__fixtures__/price-list-rules"
|
||||||
import { createRuleTypes } from "../../../__fixtures__/rule-type"
|
import { createRuleTypes } from "../../../__fixtures__/rule-type"
|
||||||
import { Modules } from "@medusajs/modules-sdk"
|
|
||||||
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
|
|
||||||
|
|
||||||
jest.setTimeout(30000)
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
@@ -240,7 +240,7 @@ moduleIntegrationTestRunner({
|
|||||||
])
|
])
|
||||||
|
|
||||||
await service.setPriceListRules({
|
await service.setPriceListRules({
|
||||||
priceListId: "price-list-1",
|
price_list_id: "price-list-1",
|
||||||
rules: {
|
rules: {
|
||||||
sales_channel: "sc-1",
|
sales_channel: "sc-1",
|
||||||
},
|
},
|
||||||
@@ -280,7 +280,7 @@ moduleIntegrationTestRunner({
|
|||||||
])
|
])
|
||||||
|
|
||||||
await service.setPriceListRules({
|
await service.setPriceListRules({
|
||||||
priceListId: "price-list-1",
|
price_list_id: "price-list-1",
|
||||||
rules: {
|
rules: {
|
||||||
sales_channel: ["sc-1", "sc-2"],
|
sales_channel: ["sc-1", "sc-2"],
|
||||||
},
|
},
|
||||||
@@ -315,7 +315,7 @@ moduleIntegrationTestRunner({
|
|||||||
describe("removePriceListRules", () => {
|
describe("removePriceListRules", () => {
|
||||||
it("should remove a priceListRule from a priceList", async () => {
|
it("should remove a priceListRule from a priceList", async () => {
|
||||||
await service.removePriceListRules({
|
await service.removePriceListRules({
|
||||||
priceListId: "price-list-1",
|
price_list_id: "price-list-1",
|
||||||
rules: ["currency_code"],
|
rules: ["currency_code"],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
+201
-4
@@ -1,8 +1,8 @@
|
|||||||
import { Modules } from "@medusajs/modules-sdk"
|
import { Modules } from "@medusajs/modules-sdk"
|
||||||
import { IPricingModuleService } from "@medusajs/types"
|
import { IPricingModuleService } from "@medusajs/types"
|
||||||
|
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
|
||||||
import { createPriceLists } from "../../../__fixtures__/price-list"
|
import { createPriceLists } from "../../../__fixtures__/price-list"
|
||||||
import { createPriceSets } from "../../../__fixtures__/price-set"
|
import { createPriceSets } from "../../../__fixtures__/price-set"
|
||||||
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
|
|
||||||
|
|
||||||
jest.setTimeout(30000)
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
@@ -666,7 +666,7 @@ moduleIntegrationTestRunner({
|
|||||||
it("should add a price to a priceList successfully", async () => {
|
it("should add a price to a priceList successfully", async () => {
|
||||||
await service.addPriceListPrices([
|
await service.addPriceListPrices([
|
||||||
{
|
{
|
||||||
priceListId: "price-list-1",
|
price_list_id: "price-list-1",
|
||||||
prices: [
|
prices: [
|
||||||
{
|
{
|
||||||
amount: 123,
|
amount: 123,
|
||||||
@@ -734,7 +734,7 @@ moduleIntegrationTestRunner({
|
|||||||
try {
|
try {
|
||||||
await service.addPriceListPrices([
|
await service.addPriceListPrices([
|
||||||
{
|
{
|
||||||
priceListId: "price-list-1",
|
price_list_id: "price-list-1",
|
||||||
prices: [
|
prices: [
|
||||||
{
|
{
|
||||||
amount: 123,
|
amount: 123,
|
||||||
@@ -774,7 +774,7 @@ moduleIntegrationTestRunner({
|
|||||||
|
|
||||||
await service.addPriceListPrices([
|
await service.addPriceListPrices([
|
||||||
{
|
{
|
||||||
priceListId: "price-list-1",
|
price_list_id: "price-list-1",
|
||||||
prices: [
|
prices: [
|
||||||
{
|
{
|
||||||
amount: 123,
|
amount: 123,
|
||||||
@@ -843,6 +843,203 @@ moduleIntegrationTestRunner({
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("updatePriceListPrices", () => {
|
||||||
|
it("should update a price to a priceList successfully", async () => {
|
||||||
|
const [priceSet] = await service.create([
|
||||||
|
{
|
||||||
|
rules: [
|
||||||
|
{ rule_attribute: "region_id" },
|
||||||
|
{ rule_attribute: "customer_group_id" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
await service.addPriceListPrices([
|
||||||
|
{
|
||||||
|
price_list_id: "price-list-1",
|
||||||
|
prices: [
|
||||||
|
{
|
||||||
|
id: "test-price-id",
|
||||||
|
amount: 123,
|
||||||
|
currency_code: "EUR",
|
||||||
|
price_set_id: priceSet.id,
|
||||||
|
rules: {
|
||||||
|
region_id: "test",
|
||||||
|
},
|
||||||
|
} as any,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
await service.updatePriceListPrices([
|
||||||
|
{
|
||||||
|
price_list_id: "price-list-1",
|
||||||
|
prices: [
|
||||||
|
{
|
||||||
|
id: "test-price-id",
|
||||||
|
price_set_id: priceSet.id,
|
||||||
|
rules: {
|
||||||
|
region_id: "new test",
|
||||||
|
customer_group_id: "new test",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const [priceList] = await service.listPriceLists(
|
||||||
|
{ id: ["price-list-1"] },
|
||||||
|
{
|
||||||
|
relations: [
|
||||||
|
"price_set_money_amounts.money_amount",
|
||||||
|
"price_set_money_amounts.price_set",
|
||||||
|
"price_set_money_amounts.price_rules",
|
||||||
|
"price_set_money_amounts.price_rules.rule_type",
|
||||||
|
"price_list_rules.price_list_rule_values",
|
||||||
|
"price_list_rules.rule_type",
|
||||||
|
],
|
||||||
|
select: [
|
||||||
|
"id",
|
||||||
|
"price_set_money_amounts.price_rules.value",
|
||||||
|
"price_set_money_amounts.price_rules.rule_type.rule_attribute",
|
||||||
|
"price_set_money_amounts.rules_count",
|
||||||
|
"price_set_money_amounts.money_amount.amount",
|
||||||
|
"price_set_money_amounts.money_amount.currency_code",
|
||||||
|
"price_set_money_amounts.money_amount.price_list_id",
|
||||||
|
"price_list_rules.price_list_rule_values.value",
|
||||||
|
"price_list_rules.rule_type.rule_attribute",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(priceList).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
price_set_money_amounts: expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
rules_count: 2,
|
||||||
|
price_rules: expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
value: "new test",
|
||||||
|
rule_type: expect.objectContaining({
|
||||||
|
rule_attribute: "region_id",
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
value: "new test",
|
||||||
|
rule_type: expect.objectContaining({
|
||||||
|
rule_attribute: "customer_group_id",
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
price_list: expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
}),
|
||||||
|
money_amount: expect.objectContaining({
|
||||||
|
amount: 123,
|
||||||
|
currency_code: "EUR",
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
price_list_rules: [],
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should fail to add a price with non-existing rule-types in the price-set to a priceList", async () => {
|
||||||
|
await service.createRuleTypes([
|
||||||
|
{ name: "twitter_handle", rule_attribute: "twitter_handle" },
|
||||||
|
{ name: "region_id", rule_attribute: "region_id" },
|
||||||
|
])
|
||||||
|
|
||||||
|
const [priceSet] = await service.create([
|
||||||
|
{ rules: [{ rule_attribute: "region_id" }] },
|
||||||
|
])
|
||||||
|
|
||||||
|
await service.addPriceListPrices([
|
||||||
|
{
|
||||||
|
price_list_id: "price-list-1",
|
||||||
|
prices: [
|
||||||
|
{
|
||||||
|
id: "test-price-id",
|
||||||
|
amount: 123,
|
||||||
|
currency_code: "EUR",
|
||||||
|
price_set_id: priceSet.id,
|
||||||
|
rules: { region_id: "test" },
|
||||||
|
} as any,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const error = await service
|
||||||
|
.updatePriceListPrices([
|
||||||
|
{
|
||||||
|
price_list_id: "price-list-1",
|
||||||
|
prices: [
|
||||||
|
{
|
||||||
|
id: "test-price-id",
|
||||||
|
amount: 123,
|
||||||
|
price_set_id: priceSet.id,
|
||||||
|
rules: { twitter_handle: "owjuhl" },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.catch((e) => e)
|
||||||
|
|
||||||
|
expect(error.message).toEqual(
|
||||||
|
`Invalid rule type configuration: Price set rules doesn't exist for rule_attribute "twitter_handle" in price set ${priceSet.id}`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("removePrices", () => {
|
||||||
|
it("should remove prices from a priceList successfully", async () => {
|
||||||
|
const [priceSet] = await service.create([
|
||||||
|
{ rules: [{ rule_attribute: "region_id" }] },
|
||||||
|
])
|
||||||
|
|
||||||
|
await service.addPriceListPrices([
|
||||||
|
{
|
||||||
|
price_list_id: "price-list-1",
|
||||||
|
prices: [
|
||||||
|
{
|
||||||
|
amount: 123,
|
||||||
|
currency_code: "EUR",
|
||||||
|
price_set_id: priceSet.id,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
let [priceList] = await service.listPriceLists(
|
||||||
|
{ id: ["price-list-1"] },
|
||||||
|
{
|
||||||
|
relations: ["price_set_money_amounts"],
|
||||||
|
select: ["price_set_money_amounts.id"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
await service.removePrices(
|
||||||
|
priceList.price_set_money_amounts!.map((psma) => psma.id)
|
||||||
|
)
|
||||||
|
;[priceList] = await service.listPriceLists(
|
||||||
|
{ id: ["price-list-1"] },
|
||||||
|
{
|
||||||
|
relations: ["price_set_money_amounts"],
|
||||||
|
select: ["id", "price_set_money_amounts.id"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(priceList).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
price_set_money_amounts: [],
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
+2
-2
@@ -5,10 +5,10 @@ import {
|
|||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||||
|
|
||||||
import { PriceSetRuleType } from "../../../../src"
|
|
||||||
import { seedPriceData } from "../../../__fixtures__/seed-price-data"
|
|
||||||
import { Modules } from "@medusajs/modules-sdk"
|
import { Modules } from "@medusajs/modules-sdk"
|
||||||
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
|
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
|
||||||
|
import { PriceSetRuleType } from "../../../../src"
|
||||||
|
import { seedPriceData } from "../../../__fixtures__/seed-price-data"
|
||||||
|
|
||||||
jest.setTimeout(30000)
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
|
|||||||
@@ -1031,9 +1031,7 @@ export default class PricingModuleService<
|
|||||||
.flat()
|
.flat()
|
||||||
|
|
||||||
const existingPriceListRules = await this.listPriceListRules(
|
const existingPriceListRules = await this.listPriceListRules(
|
||||||
{
|
{ id: priceListRuleIds },
|
||||||
id: priceListRuleIds,
|
|
||||||
},
|
|
||||||
{},
|
{},
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
@@ -1046,9 +1044,7 @@ export default class PricingModuleService<
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ruleTypes = await this.listRuleTypes(
|
const ruleTypes = await this.listRuleTypes(
|
||||||
{
|
{ rule_attribute: ruleAttributes },
|
||||||
rule_attribute: ruleAttributes,
|
|
||||||
},
|
|
||||||
{ take: null },
|
{ take: null },
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
@@ -1059,6 +1055,7 @@ export default class PricingModuleService<
|
|||||||
|
|
||||||
for (const priceListData of data) {
|
for (const priceListData of data) {
|
||||||
const { rules, ...priceListOnlyData } = priceListData
|
const { rules, ...priceListOnlyData } = priceListData
|
||||||
|
|
||||||
const updatePriceListData: any = {
|
const updatePriceListData: any = {
|
||||||
...priceListOnlyData,
|
...priceListOnlyData,
|
||||||
}
|
}
|
||||||
@@ -1083,12 +1080,7 @@ export default class PricingModuleService<
|
|||||||
|
|
||||||
if (!ruleType) {
|
if (!ruleType) {
|
||||||
;[ruleType] = await this.createRuleTypes(
|
;[ruleType] = await this.createRuleTypes(
|
||||||
[
|
[{ name: ruleAttribute, rule_attribute: ruleAttribute }],
|
||||||
{
|
|
||||||
name: ruleAttribute,
|
|
||||||
rule_attribute: ruleAttribute,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1107,12 +1099,7 @@ export default class PricingModuleService<
|
|||||||
|
|
||||||
for (const ruleValue of ruleValues as string[]) {
|
for (const ruleValue of ruleValues as string[]) {
|
||||||
await this.priceListRuleValueService_.create(
|
await this.priceListRuleValueService_.create(
|
||||||
[
|
[{ price_list_rule: priceListRule, value: ruleValue }],
|
||||||
{
|
|
||||||
price_list_rule: priceListRule,
|
|
||||||
value: ruleValue,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1161,6 +1148,185 @@ export default class PricingModuleService<
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@InjectManager("baseRepository_")
|
||||||
|
async updatePriceListPrices(
|
||||||
|
data: PricingTypes.UpdatePriceListPricesDTO[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<PricingTypes.PriceListDTO[]> {
|
||||||
|
return await this.updatePriceListPrices_(data, sharedContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager("baseRepository_")
|
||||||
|
protected async updatePriceListPrices_(
|
||||||
|
data: PricingTypes.UpdatePriceListPricesDTO[],
|
||||||
|
sharedContext: Context = {}
|
||||||
|
): Promise<PricingTypes.PriceListDTO[]> {
|
||||||
|
const ruleTypeAttributes: string[] = []
|
||||||
|
const priceListIds: string[] = []
|
||||||
|
const moneyAmountIds: string[] = []
|
||||||
|
const priceSetIds = data
|
||||||
|
.map((d) => d.prices.map((price) => price.price_set_id))
|
||||||
|
.flat()
|
||||||
|
|
||||||
|
for (const priceListData of data) {
|
||||||
|
priceListIds.push(priceListData.price_list_id)
|
||||||
|
|
||||||
|
for (const price of priceListData.prices) {
|
||||||
|
moneyAmountIds.push(price.id)
|
||||||
|
ruleTypeAttributes.push(...Object.keys(price.rules || {}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const moneyAmounts = await this.listMoneyAmounts(
|
||||||
|
{ id: moneyAmountIds },
|
||||||
|
{
|
||||||
|
take: null,
|
||||||
|
relations: [
|
||||||
|
"price_set_money_amount",
|
||||||
|
"price_set_money_amount.price_rules",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
const moneyAmountMap: Map<string, PricingTypes.MoneyAmountDTO> = new Map(
|
||||||
|
moneyAmounts.map((ma) => [ma.id, ma])
|
||||||
|
)
|
||||||
|
|
||||||
|
const ruleTypes = await this.listRuleTypes(
|
||||||
|
{ rule_attribute: ruleTypeAttributes },
|
||||||
|
{ take: null },
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
const ruleTypeMap: Map<string, RuleTypeDTO> = new Map(
|
||||||
|
ruleTypes.map((rt) => [rt.rule_attribute, rt])
|
||||||
|
)
|
||||||
|
|
||||||
|
const priceSets = await this.list(
|
||||||
|
{ id: priceSetIds },
|
||||||
|
{ relations: ["rule_types"] },
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
const priceSetRuleTypeMap: Map<string, Set<string>> = priceSets.reduce(
|
||||||
|
(acc, curr) => {
|
||||||
|
const priceSetRuleAttributeSet: Set<string> =
|
||||||
|
acc.get(curr.id) || new Set()
|
||||||
|
|
||||||
|
for (const rt of curr.rule_types ?? []) {
|
||||||
|
priceSetRuleAttributeSet.add(rt.rule_attribute)
|
||||||
|
}
|
||||||
|
|
||||||
|
acc.set(curr.id, priceSetRuleAttributeSet)
|
||||||
|
return acc
|
||||||
|
},
|
||||||
|
new Map()
|
||||||
|
)
|
||||||
|
|
||||||
|
const ruleTypeErrors: string[] = []
|
||||||
|
|
||||||
|
for (const priceListData of data) {
|
||||||
|
for (const price of priceListData.prices) {
|
||||||
|
for (const ruleAttribute of Object.keys(price.rules ?? {})) {
|
||||||
|
if (
|
||||||
|
!priceSetRuleTypeMap.get(price.price_set_id)?.has(ruleAttribute)
|
||||||
|
) {
|
||||||
|
ruleTypeErrors.push(
|
||||||
|
`rule_attribute "${ruleAttribute}" in price set ${price.price_set_id}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ruleTypeErrors.length) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.INVALID_DATA,
|
||||||
|
`Invalid rule type configuration: Price set rules doesn't exist for ${ruleTypeErrors.join(
|
||||||
|
", "
|
||||||
|
)}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const priceLists = await this.listPriceLists(
|
||||||
|
{ id: priceListIds },
|
||||||
|
{ take: null },
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
const priceListMap = new Map(priceLists.map((p) => [p.id, p]))
|
||||||
|
|
||||||
|
for (const { price_list_id: priceListId, prices } of data) {
|
||||||
|
const priceList = priceListMap.get(priceListId)
|
||||||
|
|
||||||
|
if (!priceList) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.INVALID_DATA,
|
||||||
|
`Price list with id: ${priceListId} not found`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const moneyAmountsToUpdate: PricingTypes.UpdateMoneyAmountDTO[] = []
|
||||||
|
const priceRulesToDelete: string[] = []
|
||||||
|
const priceRulesToCreate: PricingTypes.CreatePriceRuleDTO[] = []
|
||||||
|
const psmaToUpdate: ServiceTypes.UpdatePriceSetMoneyAmountDTO[] = []
|
||||||
|
|
||||||
|
for (const price of prices) {
|
||||||
|
const { rules, price_set_id, ...priceData } = price
|
||||||
|
const moneyAmount = moneyAmountMap.get(price.id)!
|
||||||
|
const priceSetMoneyAmount = moneyAmount.price_set_money_amount!
|
||||||
|
const priceRules = priceSetMoneyAmount.price_rules!
|
||||||
|
|
||||||
|
moneyAmountsToUpdate.push(priceData)
|
||||||
|
|
||||||
|
if (typeof rules === "undefined") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
psmaToUpdate.push({
|
||||||
|
id: priceSetMoneyAmount!.id,
|
||||||
|
rules_count: Object.keys(rules).length,
|
||||||
|
})
|
||||||
|
|
||||||
|
priceRulesToDelete.push(...priceRules.map((pr) => pr.id))
|
||||||
|
priceRulesToCreate.push(
|
||||||
|
...Object.entries(rules).map(([ruleAttribute, ruleValue]) => ({
|
||||||
|
price_set_id: price.price_set_id,
|
||||||
|
rule_type_id: ruleTypeMap.get(ruleAttribute)!.id,
|
||||||
|
value: ruleValue,
|
||||||
|
price_set_money_amount_id: priceSetMoneyAmount.id,
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
this.moneyAmountService_.update(moneyAmountsToUpdate),
|
||||||
|
this.priceRuleService_.delete(priceRulesToDelete),
|
||||||
|
this.priceRuleService_.create(priceRulesToCreate),
|
||||||
|
this.priceSetMoneyAmountService_.update(psmaToUpdate),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
return priceLists
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager("baseRepository_")
|
||||||
|
async removePrices(
|
||||||
|
ids: string[],
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<void> {
|
||||||
|
await this.removePrices_(ids, sharedContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager("baseRepository_")
|
||||||
|
protected async removePrices_(
|
||||||
|
ids: string[],
|
||||||
|
sharedContext: Context = {}
|
||||||
|
): Promise<void> {
|
||||||
|
await this.priceSetMoneyAmountService_.delete(ids, sharedContext)
|
||||||
|
}
|
||||||
|
|
||||||
@InjectManager("baseRepository_")
|
@InjectManager("baseRepository_")
|
||||||
async addPriceListPrices(
|
async addPriceListPrices(
|
||||||
data: PricingTypes.AddPriceListPricesDTO[],
|
data: PricingTypes.AddPriceListPricesDTO[],
|
||||||
@@ -1179,7 +1345,7 @@ export default class PricingModuleService<
|
|||||||
const priceSetIds: string[] = []
|
const priceSetIds: string[] = []
|
||||||
|
|
||||||
for (const priceListData of data) {
|
for (const priceListData of data) {
|
||||||
priceListIds.push(priceListData.priceListId)
|
priceListIds.push(priceListData.price_list_id)
|
||||||
|
|
||||||
for (const price of priceListData.prices) {
|
for (const price of priceListData.prices) {
|
||||||
ruleTypeAttributes.push(...Object.keys(price.rules || {}))
|
ruleTypeAttributes.push(...Object.keys(price.rules || {}))
|
||||||
@@ -1251,7 +1417,7 @@ export default class PricingModuleService<
|
|||||||
|
|
||||||
const priceListMap = new Map(priceLists.map((p) => [p.id, p]))
|
const priceListMap = new Map(priceLists.map((p) => [p.id, p]))
|
||||||
|
|
||||||
for (const { priceListId, prices } of data) {
|
for (const { price_list_id: priceListId, prices } of data) {
|
||||||
const priceList = priceListMap.get(priceListId)
|
const priceList = priceListMap.get(priceListId)
|
||||||
|
|
||||||
if (!priceList) {
|
if (!priceList) {
|
||||||
@@ -1322,7 +1488,7 @@ export default class PricingModuleService<
|
|||||||
sharedContext: Context = {}
|
sharedContext: Context = {}
|
||||||
): Promise<PricingTypes.PriceListDTO[]> {
|
): Promise<PricingTypes.PriceListDTO[]> {
|
||||||
const priceLists = await this.priceListService_.list(
|
const priceLists = await this.priceListService_.list(
|
||||||
{ id: data.map((d) => d.priceListId) },
|
{ id: data.map((d) => d.price_list_id) },
|
||||||
{
|
{
|
||||||
relations: ["price_list_rules", "price_list_rules.rule_type"],
|
relations: ["price_list_rules", "price_list_rules.rule_type"],
|
||||||
},
|
},
|
||||||
@@ -1347,7 +1513,7 @@ export default class PricingModuleService<
|
|||||||
|
|
||||||
const priceRuleValues = new Map<string, Map<string, string[]>>()
|
const priceRuleValues = new Map<string, Map<string, string[]>>()
|
||||||
|
|
||||||
for (const { priceListId, rules } of data) {
|
for (const { price_list_id: priceListId, rules } of data) {
|
||||||
const priceList = priceListMap.get(priceListId)
|
const priceList = priceListMap.get(priceListId)
|
||||||
|
|
||||||
if (!priceList) {
|
if (!priceList) {
|
||||||
@@ -1465,7 +1631,7 @@ export default class PricingModuleService<
|
|||||||
sharedContext: Context = {}
|
sharedContext: Context = {}
|
||||||
): Promise<PricingTypes.PriceListDTO[]> {
|
): Promise<PricingTypes.PriceListDTO[]> {
|
||||||
const priceLists = await this.priceListService_.list(
|
const priceLists = await this.priceListService_.list(
|
||||||
{ id: data.map((d) => d.priceListId) },
|
{ id: data.map((d) => d.price_list_id) },
|
||||||
{
|
{
|
||||||
relations: ["price_list_rules", "price_list_rules.rule_type"],
|
relations: ["price_list_rules", "price_list_rules.rule_type"],
|
||||||
},
|
},
|
||||||
@@ -1475,7 +1641,7 @@ export default class PricingModuleService<
|
|||||||
const priceListMap = new Map(priceLists.map((p) => [p.id, p]))
|
const priceListMap = new Map(priceLists.map((p) => [p.id, p]))
|
||||||
|
|
||||||
const idsToDelete: string[] = []
|
const idsToDelete: string[] = []
|
||||||
for (const { priceListId, rules } of data) {
|
for (const { price_list_id: priceListId, rules } of data) {
|
||||||
const priceList = priceListMap.get(priceListId)
|
const priceList = priceListMap.get(priceListId)
|
||||||
|
|
||||||
if (!priceList) {
|
if (!priceList) {
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import { PriceListStatus, PriceListType } from "@medusajs/utils"
|
|||||||
export interface CreatePriceListDTO {
|
export interface CreatePriceListDTO {
|
||||||
title: string
|
title: string
|
||||||
description: string
|
description: string
|
||||||
starts_at?: Date | string | null
|
starts_at?: string | null
|
||||||
ends_at?: Date | string | null
|
ends_at?: string | null
|
||||||
status?: PriceListStatus
|
status?: PriceListStatus
|
||||||
type?: PriceListType
|
type?: PriceListType
|
||||||
rules_count?: number
|
rules_count?: number
|
||||||
@@ -13,8 +13,8 @@ export interface CreatePriceListDTO {
|
|||||||
export interface UpdatePriceListDTO {
|
export interface UpdatePriceListDTO {
|
||||||
id: string
|
id: string
|
||||||
title?: string
|
title?: string
|
||||||
starts_at?: Date | string | null
|
starts_at?: string | null
|
||||||
ends_at?: Date | string | null
|
ends_at?: string | null
|
||||||
status?: PriceListStatus
|
status?: PriceListStatus
|
||||||
number_rules?: number
|
number_rules?: number
|
||||||
}
|
}
|
||||||
@@ -18,10 +18,10 @@ export interface UpdateMoneyAmountDTO {
|
|||||||
|
|
||||||
export interface MoneyAmountDTO {
|
export interface MoneyAmountDTO {
|
||||||
id: string
|
id: string
|
||||||
currency_code?: string
|
currency_code?: string | null
|
||||||
amount?: number
|
amount?: number | null
|
||||||
min_quantity?: number
|
min_quantity?: number | null
|
||||||
max_quantity?: number
|
max_quantity?: number | null
|
||||||
price_set_money_amount?: PriceSetMoneyAmountDTO
|
price_set_money_amount?: PriceSetMoneyAmountDTO
|
||||||
created_at: Date
|
created_at: Date
|
||||||
updated_at: Date
|
updated_at: Date
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { PriceListStatus, PriceListType } from "@medusajs/utils"
|
|
||||||
import {
|
import {
|
||||||
BaseFilterable,
|
BaseFilterable,
|
||||||
MoneyAmountDTO,
|
MoneyAmountDTO,
|
||||||
@@ -6,12 +5,13 @@ import {
|
|||||||
PriceSetMoneyAmountDTO,
|
PriceSetMoneyAmountDTO,
|
||||||
RuleTypeDTO,
|
RuleTypeDTO,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
|
import { PriceListStatus, PriceListType } from "@medusajs/utils"
|
||||||
|
|
||||||
export interface CreatePriceListDTO {
|
export interface CreatePriceListDTO {
|
||||||
title: string
|
title: string
|
||||||
description: string
|
description: string
|
||||||
starts_at?: Date | string | null
|
starts_at?: string | null
|
||||||
ends_at?: Date | string | null
|
ends_at?: string | null
|
||||||
status?: PriceListStatus
|
status?: PriceListStatus
|
||||||
type?: PriceListType
|
type?: PriceListType
|
||||||
number_rules?: number
|
number_rules?: number
|
||||||
@@ -20,8 +20,8 @@ export interface CreatePriceListDTO {
|
|||||||
export interface UpdatePriceListDTO {
|
export interface UpdatePriceListDTO {
|
||||||
id: string
|
id: string
|
||||||
title?: string
|
title?: string
|
||||||
starts_at?: Date | string | null
|
starts_at?: string | null
|
||||||
ends_at?: Date | string | null
|
ends_at?: string | null
|
||||||
status?: PriceListStatus
|
status?: PriceListStatus
|
||||||
number_rules?: number
|
number_rules?: number
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export interface UpdatePriceSetMoneyAmountDTO {
|
|||||||
title?: string
|
title?: string
|
||||||
price_set?: PriceSetDTO
|
price_set?: PriceSetDTO
|
||||||
money_amount?: MoneyAmountDTO
|
money_amount?: MoneyAmountDTO
|
||||||
|
rules_count?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CreatePriceSetMoneyAmountDTO {
|
export interface CreatePriceSetMoneyAmountDTO {
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ export interface UpdateMoneyAmountDTO {
|
|||||||
/**
|
/**
|
||||||
* The code of the currency to associate with the money amount.
|
* The code of the currency to associate with the money amount.
|
||||||
*/
|
*/
|
||||||
currency_code?: string
|
currency_code?: string | null
|
||||||
/**
|
/**
|
||||||
* The price of this money amount.
|
* The price of this money amount.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import { CreateMoneyAmountDTO, MoneyAmountDTO } from "./money-amount";
|
import { BaseFilterable } from "../../dal"
|
||||||
|
import {
|
||||||
import { BaseFilterable } from "../../dal";
|
CreateMoneyAmountDTO,
|
||||||
import { PriceSetMoneyAmountDTO } from "./price-set-money-amount";
|
MoneyAmountDTO,
|
||||||
import { RuleTypeDTO } from "./rule-type";
|
UpdateMoneyAmountDTO,
|
||||||
|
} from "./money-amount"
|
||||||
|
import { PriceSetMoneyAmountDTO } from "./price-set-money-amount"
|
||||||
|
import { RuleTypeDTO } from "./rule-type"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @enum
|
* @enum
|
||||||
@@ -106,7 +109,18 @@ export interface PriceListDTO {
|
|||||||
*
|
*
|
||||||
* The prices associated with a price list.
|
* The prices associated with a price list.
|
||||||
*/
|
*/
|
||||||
export interface PriceListPriceDTO extends CreateMoneyAmountDTO {
|
export interface CreatePriceListPriceDTO extends CreateMoneyAmountDTO {
|
||||||
|
/**
|
||||||
|
* The ID of the associated price set.
|
||||||
|
*/
|
||||||
|
price_set_id: string
|
||||||
|
/**
|
||||||
|
* The rules to add to the price. The object's keys are rule types' `rule_attribute` attribute, and values are the value of that rule associated with this price.
|
||||||
|
*/
|
||||||
|
rules?: CreatePriceSetPriceRules
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdatePriceListPriceDTO extends UpdateMoneyAmountDTO {
|
||||||
/**
|
/**
|
||||||
* The ID of the associated price set.
|
* The ID of the associated price set.
|
||||||
*/
|
*/
|
||||||
@@ -152,11 +166,11 @@ export interface CreatePriceListDTO {
|
|||||||
/**
|
/**
|
||||||
* The price list is enabled starting from this date.
|
* The price list is enabled starting from this date.
|
||||||
*/
|
*/
|
||||||
starts_at?: Date | string | null
|
starts_at?: string | null
|
||||||
/**
|
/**
|
||||||
* The price list expires after this date.
|
* The price list expires after this date.
|
||||||
*/
|
*/
|
||||||
ends_at?: Date | string | null
|
ends_at?: string | null
|
||||||
/**
|
/**
|
||||||
* The price list's status.
|
* The price list's status.
|
||||||
*/
|
*/
|
||||||
@@ -176,7 +190,7 @@ export interface CreatePriceListDTO {
|
|||||||
/**
|
/**
|
||||||
* The prices associated with the price list.
|
* The prices associated with the price list.
|
||||||
*/
|
*/
|
||||||
prices?: PriceListPriceDTO[]
|
prices?: CreatePriceListPriceDTO[]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -200,11 +214,11 @@ export interface UpdatePriceListDTO {
|
|||||||
/**
|
/**
|
||||||
* The price list is enabled starting from this date.
|
* The price list is enabled starting from this date.
|
||||||
*/
|
*/
|
||||||
starts_at?: Date | string | null
|
starts_at?: string | null
|
||||||
/**
|
/**
|
||||||
* The price list expires after this date.
|
* The price list expires after this date.
|
||||||
*/
|
*/
|
||||||
ends_at?: Date | string | null
|
ends_at?: string | null
|
||||||
/**
|
/**
|
||||||
* The price list's status.
|
* The price list's status.
|
||||||
*/
|
*/
|
||||||
@@ -412,11 +426,27 @@ export interface AddPriceListPricesDTO {
|
|||||||
/**
|
/**
|
||||||
* The ID of the price list to add prices to.
|
* The ID of the price list to add prices to.
|
||||||
*/
|
*/
|
||||||
priceListId: string
|
price_list_id: string
|
||||||
/**
|
/**
|
||||||
* The prices to add.
|
* The prices to add.
|
||||||
*/
|
*/
|
||||||
prices: PriceListPriceDTO[]
|
prices: CreatePriceListPriceDTO[]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @interface
|
||||||
|
*
|
||||||
|
* The prices to be added to a price list.
|
||||||
|
*/
|
||||||
|
export interface UpdatePriceListPricesDTO {
|
||||||
|
/**
|
||||||
|
* The ID of the price list to add prices to.
|
||||||
|
*/
|
||||||
|
price_list_id: string
|
||||||
|
/**
|
||||||
|
* The prices to add.
|
||||||
|
*/
|
||||||
|
prices: UpdatePriceListPriceDTO[]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -428,7 +458,7 @@ export interface SetPriceListRulesDTO {
|
|||||||
/**
|
/**
|
||||||
* The ID of the price list to add rules to.
|
* The ID of the price list to add rules to.
|
||||||
*/
|
*/
|
||||||
priceListId: string
|
price_list_id: string
|
||||||
/**
|
/**
|
||||||
* The rules to add to the price list. Each key of the object is a rule type's `rule_attribute`, and its value
|
* The rules to add to the price list. Each key of the object is a rule type's `rule_attribute`, and its value
|
||||||
* is the value(s) of the rule.
|
* is the value(s) of the rule.
|
||||||
@@ -445,7 +475,7 @@ export interface RemovePriceListRulesDTO {
|
|||||||
/**
|
/**
|
||||||
* The ID of the price list to remove rules from.
|
* The ID of the price list to remove rules from.
|
||||||
*/
|
*/
|
||||||
priceListId: string
|
price_list_id: string
|
||||||
/**
|
/**
|
||||||
* The rules to remove from the price list. Each item being a rule type's `rule_attribute`.
|
* The rules to remove from the price list. Each item being a rule type's `rule_attribute`.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { BaseFilterable } from "../../dal"
|
import { BaseFilterable } from "../../dal"
|
||||||
import { PriceSetDTO } from "./price-set"
|
import { PriceSetDTO } from "./price-set"
|
||||||
import { PriceSetMoneyAmountDTO } from "./price-set-money-amount"
|
|
||||||
import { RuleTypeDTO } from "./rule-type"
|
import { RuleTypeDTO } from "./rule-type"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,18 +72,10 @@ export interface CreatePriceRuleDTO {
|
|||||||
* The ID of the associated price set.
|
* The ID of the associated price set.
|
||||||
*/
|
*/
|
||||||
price_set_id?: string
|
price_set_id?: string
|
||||||
/**
|
|
||||||
* The ID or object of the associated price set.
|
|
||||||
*/
|
|
||||||
price_set?: string | PriceSetDTO
|
|
||||||
/**
|
/**
|
||||||
* The ID of the associated rule type.
|
* The ID of the associated rule type.
|
||||||
*/
|
*/
|
||||||
rule_type_id?: string
|
rule_type_id?: string
|
||||||
/**
|
|
||||||
* The ID of the associated rule type.
|
|
||||||
*/
|
|
||||||
rule_type?: string | RuleTypeDTO
|
|
||||||
/**
|
/**
|
||||||
* The value of the price rule.
|
* The value of the price rule.
|
||||||
*/
|
*/
|
||||||
@@ -97,10 +88,6 @@ export interface CreatePriceRuleDTO {
|
|||||||
* The ID of the associated price set money amount.
|
* The ID of the associated price set money amount.
|
||||||
*/
|
*/
|
||||||
price_set_money_amount_id?: string
|
price_set_money_amount_id?: string
|
||||||
/**
|
|
||||||
* The ID or object of the associated price set money amount.
|
|
||||||
*/
|
|
||||||
price_set_money_amount?: string | PriceSetMoneyAmountDTO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { BaseFilterable } from "../../dal";
|
import { BaseFilterable } from "../../dal"
|
||||||
import { MoneyAmountDTO } from "./money-amount";
|
import { MoneyAmountDTO } from "./money-amount"
|
||||||
import { PriceListDTO } from "./price-list";
|
import { PriceListDTO } from "./price-list"
|
||||||
import { PriceRuleDTO } from "./price-rule";
|
import { PriceRuleDTO } from "./price-rule"
|
||||||
import { PriceSetDTO } from "./price-set";
|
import { PriceSetDTO } from "./price-set"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @interface
|
* @interface
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
export * from "./common"
|
export * from "./common"
|
||||||
export * from "./service"
|
export * from "./service"
|
||||||
|
export * from "./workflows"
|
||||||
@@ -33,6 +33,7 @@ import {
|
|||||||
SetPriceListRulesDTO,
|
SetPriceListRulesDTO,
|
||||||
UpdateMoneyAmountDTO,
|
UpdateMoneyAmountDTO,
|
||||||
UpdatePriceListDTO,
|
UpdatePriceListDTO,
|
||||||
|
UpdatePriceListPricesDTO,
|
||||||
UpdatePriceListRuleDTO,
|
UpdatePriceListRuleDTO,
|
||||||
UpdatePriceRuleDTO,
|
UpdatePriceRuleDTO,
|
||||||
UpdatePriceSetDTO,
|
UpdatePriceSetDTO,
|
||||||
@@ -3397,6 +3398,11 @@ export interface IPricingModuleService extends IModuleService {
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<PriceListDTO[]>
|
): Promise<PriceListDTO[]>
|
||||||
|
|
||||||
|
updatePriceListPrices(
|
||||||
|
data: UpdatePriceListPricesDTO[],
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<PriceListDTO[]>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is used to set the rules of a price list.
|
* This method is used to set the rules of a price list.
|
||||||
*
|
*
|
||||||
@@ -3454,4 +3460,6 @@ export interface IPricingModuleService extends IModuleService {
|
|||||||
data: RemovePriceListRulesDTO,
|
data: RemovePriceListRulesDTO,
|
||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<PriceListDTO>
|
): Promise<PriceListDTO>
|
||||||
|
|
||||||
|
removePrices(ids: string[], sharedContext?: Context): Promise<void>
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { PriceListStatus } from "./common"
|
||||||
|
|
||||||
|
export interface CreatePriceListPriceWorkflowDTO {
|
||||||
|
amount: number
|
||||||
|
currency_code: string
|
||||||
|
variant_id: string
|
||||||
|
max_quantity?: number
|
||||||
|
min_quantity?: number
|
||||||
|
rules?: Record<string, string>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdatePriceListPriceWorkflowDTO {
|
||||||
|
id: string
|
||||||
|
amount?: number
|
||||||
|
currency_code?: string
|
||||||
|
variant_id?: string
|
||||||
|
max_quantity?: number
|
||||||
|
min_quantity?: number
|
||||||
|
rules?: Record<string, string>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CreatePriceListWorkflowInputDTO {
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
starts_at?: string | null
|
||||||
|
ends_at?: string | null
|
||||||
|
status?: PriceListStatus
|
||||||
|
rules?: Record<string, string[]>
|
||||||
|
prices?: CreatePriceListPriceWorkflowDTO[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdatePriceListWorkflowInputDTO {
|
||||||
|
id: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
starts_at?: string | null
|
||||||
|
ends_at?: string | null
|
||||||
|
status?: PriceListStatus
|
||||||
|
rules?: Record<string, string[]>
|
||||||
|
prices?: (UpdatePriceListPriceWorkflowDTO | CreatePriceListPriceWorkflowDTO)[]
|
||||||
|
}
|
||||||
@@ -3,6 +3,9 @@ import { isObject } from "./is-object"
|
|||||||
|
|
||||||
export function getSelectsAndRelationsFromObjectArray(
|
export function getSelectsAndRelationsFromObjectArray(
|
||||||
dataArray: object[],
|
dataArray: object[],
|
||||||
|
options: { objectFields: string[] } = {
|
||||||
|
objectFields: [],
|
||||||
|
},
|
||||||
prefix?: string
|
prefix?: string
|
||||||
): {
|
): {
|
||||||
selects: string[]
|
selects: string[]
|
||||||
@@ -13,10 +16,11 @@ export function getSelectsAndRelationsFromObjectArray(
|
|||||||
|
|
||||||
for (const data of dataArray) {
|
for (const data of dataArray) {
|
||||||
for (const [key, value] of Object.entries(data)) {
|
for (const [key, value] of Object.entries(data)) {
|
||||||
if (isObject(value)) {
|
if (isObject(value) && !options.objectFields.includes(key)) {
|
||||||
relations.push(setKey(key, prefix))
|
relations.push(setKey(key, prefix))
|
||||||
const res = getSelectsAndRelationsFromObjectArray(
|
const res = getSelectsAndRelationsFromObjectArray(
|
||||||
[value],
|
[value],
|
||||||
|
options,
|
||||||
setKey(key, prefix)
|
setKey(key, prefix)
|
||||||
)
|
)
|
||||||
selects.push(...res.selects)
|
selects.push(...res.selects)
|
||||||
@@ -25,6 +29,7 @@ export function getSelectsAndRelationsFromObjectArray(
|
|||||||
relations.push(setKey(key, prefix))
|
relations.push(setKey(key, prefix))
|
||||||
const res = getSelectsAndRelationsFromObjectArray(
|
const res = getSelectsAndRelationsFromObjectArray(
|
||||||
value,
|
value,
|
||||||
|
options,
|
||||||
setKey(key, prefix)
|
setKey(key, prefix)
|
||||||
)
|
)
|
||||||
selects.push(...res.selects)
|
selects.push(...res.selects)
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import {
|
||||||
|
PriceListRuleDTO,
|
||||||
|
PriceRuleDTO,
|
||||||
|
PriceSetMoneyAmountDTO,
|
||||||
|
ProductVariantDTO,
|
||||||
|
UpdatePriceListPriceDTO,
|
||||||
|
} from "@medusajs/types"
|
||||||
|
|
||||||
|
export function buildPriceListRules(
|
||||||
|
priceListRules: PriceListRuleDTO[]
|
||||||
|
): Record<string, string[]> {
|
||||||
|
return priceListRules.reduce((acc, curr) => {
|
||||||
|
const ruleAttribute = curr.rule_type.rule_attribute
|
||||||
|
const ruleValues = curr.price_list_rule_values || []
|
||||||
|
|
||||||
|
acc[ruleAttribute] = ruleValues.map((ruleValue) => ruleValue.value)
|
||||||
|
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildPriceSetRules(
|
||||||
|
priceRules: PriceRuleDTO[]
|
||||||
|
): Record<string, string> {
|
||||||
|
return priceRules.reduce((acc, curr) => {
|
||||||
|
const ruleAttribute = curr.rule_type.rule_attribute
|
||||||
|
const ruleValue = curr.value
|
||||||
|
|
||||||
|
acc[ruleAttribute] = ruleValue
|
||||||
|
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildPriceSetPricesForCore(
|
||||||
|
priceSetMoneyAmounts: (PriceSetMoneyAmountDTO & {
|
||||||
|
price_set: PriceSetMoneyAmountDTO["price_set"] & {
|
||||||
|
variant?: ProductVariantDTO
|
||||||
|
}
|
||||||
|
})[]
|
||||||
|
): Record<string, any>[] {
|
||||||
|
return priceSetMoneyAmounts.map((priceSetMoneyAmount) => {
|
||||||
|
const productVariant = (priceSetMoneyAmount.price_set as any).variant
|
||||||
|
const rules: Record<string, string> = priceSetMoneyAmount.price_rules
|
||||||
|
? buildPriceSetRules(priceSetMoneyAmount.price_rules)
|
||||||
|
: {}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...priceSetMoneyAmount.money_amount,
|
||||||
|
variant_id: productVariant?.id ?? null,
|
||||||
|
rules,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildPriceSetPricesForModule(
|
||||||
|
priceSetMoneyAmounts: PriceSetMoneyAmountDTO[]
|
||||||
|
): UpdatePriceListPriceDTO[] {
|
||||||
|
return priceSetMoneyAmounts.map((priceSetMoneyAmount) => {
|
||||||
|
const rules: Record<string, string> = priceSetMoneyAmount.price_rules
|
||||||
|
? buildPriceSetRules(priceSetMoneyAmount.price_rules)
|
||||||
|
: {}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...priceSetMoneyAmount.money_amount!,
|
||||||
|
price_set_id: priceSetMoneyAmount.price_set!?.id!,
|
||||||
|
rules,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
|
export * from "./builders"
|
||||||
export * from "./price-list"
|
export * from "./price-list"
|
||||||
export * from "./rule-type"
|
export * from "./rule-type"
|
||||||
@@ -2,9 +2,9 @@ import {
|
|||||||
TransactionStepsDefinition,
|
TransactionStepsDefinition,
|
||||||
WorkflowManager,
|
WorkflowManager,
|
||||||
} from "@medusajs/orchestration"
|
} from "@medusajs/orchestration"
|
||||||
import { isString, OrchestrationUtils } from "@medusajs/utils"
|
import { OrchestrationUtils, isString } from "@medusajs/utils"
|
||||||
import { ulid } from "ulid"
|
import { ulid } from "ulid"
|
||||||
import { resolveValue, StepResponse } from "./helpers"
|
import { StepResponse, resolveValue } from "./helpers"
|
||||||
import { proxify } from "./helpers/proxy"
|
import { proxify } from "./helpers/proxy"
|
||||||
import {
|
import {
|
||||||
CreateWorkflowComposerContext,
|
CreateWorkflowComposerContext,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { OrchestrationUtils } from "@medusajs/utils"
|
|
||||||
import { PermanentStepFailureError } from "@medusajs/orchestration"
|
import { PermanentStepFailureError } from "@medusajs/orchestration"
|
||||||
|
import { OrchestrationUtils } from "@medusajs/utils"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is used to create the response returned by a step. A step return its data by returning an instance of `StepResponse`.
|
* This class is used to create the response returned by a step. A step return its data by returning an instance of `StepResponse`.
|
||||||
|
|||||||
Reference in new issue
Block a user