diff --git a/.changeset/chilly-mayflies-melt.md b/.changeset/chilly-mayflies-melt.md new file mode 100644 index 0000000000..0aa7331de9 --- /dev/null +++ b/.changeset/chilly-mayflies-melt.md @@ -0,0 +1,9 @@ +--- +"@medusajs/core-flows": patch +"@medusajs/pricing": patch +"@medusajs/medusa": patch +"@medusajs/types": patch +"@medusajs/utils": patch +--- + +feat(core-flows,pricing,medusa,pricing,types,utils): Price List Prices can have their own rules diff --git a/integration-tests/plugins/__tests__/price-lists/admin/add-price-list-price-batch.spec.ts b/integration-tests/plugins/__tests__/price-lists/admin/add-price-list-price-batch.spec.ts index 1caaef078d..64d0c791b2 100644 --- a/integration-tests/plugins/__tests__/price-lists/admin/add-price-list-price-batch.spec.ts +++ b/integration-tests/plugins/__tests__/price-lists/admin/add-price-list-price-batch.spec.ts @@ -90,8 +90,8 @@ describe("POST /admin/price-lists/:id/prices/batch", () => { { title: "test price list", description: "test", - ends_at: new Date(), - starts_at: new Date(), + ends_at: new Date().toISOString(), + starts_at: new Date().toISOString(), status: PriceListStatus.ACTIVE, type: PriceListType.OVERRIDE, }, @@ -104,7 +104,6 @@ describe("POST /admin/price-lists/:id/prices/batch", () => { { amount: 3000, currency_code: "usd", - rules: {}, }, ], }) @@ -117,6 +116,11 @@ describe("POST /admin/price-lists/:id/prices/batch", () => { amount: 5000, currency_code: "usd", }, + { + amount: 6000, + region_id: "test-region", + variant_id: variant.id, + }, ], } @@ -184,6 +188,44 @@ describe("POST /admin/price-lists/:id/prices/batch", () => { }), variant_id: expect.any(String), }), + 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: expect.any(String), + region_id: "test-region", + 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), + }), ], }) ) diff --git a/integration-tests/plugins/__tests__/price-lists/admin/create-price-list.spec.ts b/integration-tests/plugins/__tests__/price-lists/admin/create-price-list.spec.ts index 831251c175..217e840e15 100644 --- a/integration-tests/plugins/__tests__/price-lists/admin/create-price-list.spec.ts +++ b/integration-tests/plugins/__tests__/price-lists/admin/create-price-list.spec.ts @@ -94,7 +94,6 @@ describe("POST /admin/price-lists", () => { { amount: 3000, currency_code: "usd", - rules: {}, }, ], }) diff --git a/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices-by-product.ts b/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices-by-product.ts index ec8e17fd03..3bc67cd995 100644 --- a/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices-by-product.ts +++ b/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices-by-product.ts @@ -87,7 +87,6 @@ describe("DELETE /admin/price-lists/:id/products/:productId/batch", () => { { amount: 3000, currency_code: "usd", - rules: {}, }, ], }) diff --git a/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices-by-variant.ts b/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices-by-variant.ts index cc0639a075..61b68a8ad5 100644 --- a/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices-by-variant.ts +++ b/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices-by-variant.ts @@ -89,7 +89,6 @@ describe("DELETE /admin/price-lists/:id/variants/:variantId/prices", () => { { amount: 3000, currency_code: "usd", - rules: {}, }, ], }) diff --git a/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices.ts b/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices.ts index 9924193e3e..497c9e1c19 100644 --- a/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices.ts +++ b/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-prices.ts @@ -89,7 +89,6 @@ describe("DELETE /admin/price-lists/:id", () => { { amount: 3000, currency_code: "usd", - rules: {}, }, ], }) diff --git a/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-spec.ts b/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-spec.ts index 47064fed15..f7406c86ce 100644 --- a/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-spec.ts +++ b/integration-tests/plugins/__tests__/price-lists/admin/delete-price-list-spec.ts @@ -89,7 +89,6 @@ describe("DELETE /admin/price-lists/:id", () => { { amount: 3000, currency_code: "usd", - rules: {}, }, ], }) diff --git a/integration-tests/plugins/__tests__/price-lists/admin/get-price-list.spec.ts b/integration-tests/plugins/__tests__/price-lists/admin/get-price-list.spec.ts index 9eed1dd607..1aded99674 100644 --- a/integration-tests/plugins/__tests__/price-lists/admin/get-price-list.spec.ts +++ b/integration-tests/plugins/__tests__/price-lists/admin/get-price-list.spec.ts @@ -81,7 +81,6 @@ describe("GET /admin/price-lists/:id", () => { { amount: 3000, currency_code: "usd", - rules: {}, }, ], rules: [], diff --git a/integration-tests/plugins/__tests__/price-lists/admin/list-price-list-products.spec.ts b/integration-tests/plugins/__tests__/price-lists/admin/list-price-list-products.spec.ts index 1395fa75d8..3b8cfa4113 100644 --- a/integration-tests/plugins/__tests__/price-lists/admin/list-price-list-products.spec.ts +++ b/integration-tests/plugins/__tests__/price-lists/admin/list-price-list-products.spec.ts @@ -99,7 +99,6 @@ describe("GET /admin/price-lists/:id/products", () => { { amount: 3000, currency_code: "usd", - rules: {}, }, ], rules: [], @@ -210,7 +209,6 @@ describe("GET /admin/price-lists/:id/products", () => { { amount: 3000, currency_code: "usd", - rules: {}, }, ], rules: [], diff --git a/integration-tests/plugins/__tests__/price-lists/admin/list-price-list.spec.ts b/integration-tests/plugins/__tests__/price-lists/admin/list-price-list.spec.ts index fbe8a9830f..c68bdd7878 100644 --- a/integration-tests/plugins/__tests__/price-lists/admin/list-price-list.spec.ts +++ b/integration-tests/plugins/__tests__/price-lists/admin/list-price-list.spec.ts @@ -81,7 +81,6 @@ describe("GET /admin/price-lists", () => { { amount: 3000, currency_code: "usd", - rules: {}, }, ], rules: [], diff --git a/integration-tests/plugins/__tests__/price-lists/admin/update-price-list.spec.ts b/integration-tests/plugins/__tests__/price-lists/admin/update-price-list.spec.ts index 72b3fe55bf..ba734a3cfa 100644 --- a/integration-tests/plugins/__tests__/price-lists/admin/update-price-list.spec.ts +++ b/integration-tests/plugins/__tests__/price-lists/admin/update-price-list.spec.ts @@ -131,7 +131,6 @@ describe("POST /admin/price-lists/:id", () => { { amount: 3000, currency_code: "usd", - rules: {}, }, ], }) diff --git a/integration-tests/plugins/__tests__/price-lists/store/get-product.ts b/integration-tests/plugins/__tests__/price-lists/store/get-product.ts index ad5915f910..6ee46064a7 100644 --- a/integration-tests/plugins/__tests__/price-lists/store/get-product.ts +++ b/integration-tests/plugins/__tests__/price-lists/store/get-product.ts @@ -91,12 +91,10 @@ describe("GET /store/products/:id", () => { { amount: 3000, currency_code: "usd", - rules: {}, }, { amount: 4000, currency_code: "usd", - rules: {}, }, ], rules: [], diff --git a/integration-tests/plugins/__tests__/product/admin/update-product-variant.spec.ts b/integration-tests/plugins/__tests__/product/admin/update-product-variant.spec.ts index 2f76bdd06c..a9de8c7069 100644 --- a/integration-tests/plugins/__tests__/product/admin/update-product-variant.spec.ts +++ b/integration-tests/plugins/__tests__/product/admin/update-product-variant.spec.ts @@ -140,7 +140,6 @@ describe("POST /admin/products/:id/variants/:id", () => { { amount: 3000, currency_code: "usd", - rules: {}, }, ], }) diff --git a/integration-tests/plugins/__tests__/product/admin/update-product.spec.ts b/integration-tests/plugins/__tests__/product/admin/update-product.spec.ts index db9750f264..67e492fe5f 100644 --- a/integration-tests/plugins/__tests__/product/admin/update-product.spec.ts +++ b/integration-tests/plugins/__tests__/product/admin/update-product.spec.ts @@ -142,7 +142,6 @@ describe("POST /admin/products/:id", () => { { amount: 3000, currency_code: "usd", - rules: {}, }, ], }) diff --git a/integration-tests/plugins/helpers/create-variant-price-set.ts b/integration-tests/plugins/helpers/create-variant-price-set.ts index 1ea28b1c56..1aef64c4b2 100644 --- a/integration-tests/plugins/helpers/create-variant-price-set.ts +++ b/integration-tests/plugins/helpers/create-variant-price-set.ts @@ -9,7 +9,6 @@ const defaultPrices = [ { amount: 3000, currency_code: "usd", - rules: {}, }, ] diff --git a/packages/core-flows/src/handlers/price-list/prepare-create-price-list.ts b/packages/core-flows/src/handlers/price-list/prepare-create-price-list.ts index c944608b01..48538d6c76 100644 --- a/packages/core-flows/src/handlers/price-list/prepare-create-price-list.ts +++ b/packages/core-flows/src/handlers/price-list/prepare-create-price-list.ts @@ -16,6 +16,7 @@ export async function prepareCreatePriceLists({ })[] }>): Promise { const remoteQuery = container.resolve("remoteQuery") + const regionService = container.resolve("regionService") const { price_lists } = data @@ -59,6 +60,17 @@ export async function prepareCreatePriceLists({ ) } + const regionIds = price_lists + .map(({ prices }) => prices?.map((price) => price.region_id) ?? []) + .flat(2) + const regions = await regionService.list({ id: regionIds }, {}) + const regionIdCurrencyCodeMap: Map = 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 @@ -70,12 +82,20 @@ export async function prepareCreatePriceLists({ prices?.map((price) => { const price_set_id = variantIdPriceSetIdMap.get(price.variant_id)! + const rules: Record = {} + if (price.region_id) { + rules.region_id = price.region_id + } + return { - currency_code: price.currency_code, + 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, } }) ?? [] diff --git a/packages/core-flows/src/handlers/price-list/prepare-update-price-lists.ts b/packages/core-flows/src/handlers/price-list/prepare-update-price-lists.ts index a5f0c5d757..555539c314 100644 --- a/packages/core-flows/src/handlers/price-list/prepare-update-price-lists.ts +++ b/packages/core-flows/src/handlers/price-list/prepare-update-price-lists.ts @@ -18,6 +18,7 @@ export async function prepareUpdatePriceLists({ }>): Promise { const { price_lists: priceListsData } = data const remoteQuery = container.resolve("remoteQuery") + const regionService = container.resolve("regionService") const variantPriceSetMap = new Map() const priceListPricesMap = new Map() @@ -44,6 +45,17 @@ export async function prepareUpdatePriceLists({ 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 = new Map( + regions.map((region: { id: string; currency_code: string }) => [ + region.id, + region.currency_code, + ]) + ) + const priceLists = priceListsData.map((priceListData) => { const priceListPrices: PriceListPriceDTO[] = [] @@ -53,13 +65,21 @@ export async function prepareUpdatePriceLists({ return } + const rules: Record = {} + 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: priceData.currency_code 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 diff --git a/packages/core-flows/src/handlers/product/update-products-variants-prices.ts b/packages/core-flows/src/handlers/product/update-products-variants-prices.ts index c561b221ac..43bb0938e5 100644 --- a/packages/core-flows/src/handlers/product/update-products-variants-prices.ts +++ b/packages/core-flows/src/handlers/product/update-products-variants-prices.ts @@ -65,7 +65,6 @@ export async function updateProductsVariantsPrices({ const obj = { amount: price.amount, currency_code: price.currency_code, - rules: {}, } if (price.region_id) { diff --git a/packages/medusa/src/api/routes/admin/price-lists/add-prices-batch.ts b/packages/medusa/src/api/routes/admin/price-lists/add-prices-batch.ts index 8d76b52ac8..2469bdfdae 100644 --- a/packages/medusa/src/api/routes/admin/price-lists/add-prices-batch.ts +++ b/packages/medusa/src/api/routes/admin/price-lists/add-prices-batch.ts @@ -1,5 +1,6 @@ -import { MedusaV2Flag } from "@medusajs/utils" import { updatePriceLists } from "@medusajs/core-flows" +import { MedusaContainer } from "@medusajs/types" +import { MedusaV2Flag } from "@medusajs/utils" import { Type } from "class-transformer" import { IsArray, IsBoolean, IsOptional, ValidateNested } from "class-validator" import { EntityManager } from "typeorm" @@ -8,7 +9,6 @@ import { PriceList } from "../../../.." import PriceListService from "../../../../services/price-list" import { AdminPriceListPricesUpdateReq } from "../../../../types/price-list" import { validator } from "../../../../utils/validator" -import { MedusaContainer } from "@medusajs/types" import { getPriceListPricingModule } from "./modules-queries" /** diff --git a/packages/medusa/src/api/routes/admin/price-lists/index.ts b/packages/medusa/src/api/routes/admin/price-lists/index.ts index bc324b09a7..575c196928 100644 --- a/packages/medusa/src/api/routes/admin/price-lists/index.ts +++ b/packages/medusa/src/api/routes/admin/price-lists/index.ts @@ -121,6 +121,12 @@ export const defaultAdminPriceListRemoteQueryObject = { "updated_at", ], }, + price_rules: { + fields: ["value"], + rule_type: { + fields: ["rule_attribute"], + }, + }, price_set: { variant_link: { variant: { diff --git a/packages/medusa/src/api/routes/admin/price-lists/modules-queries/list-and-count-price-lists.ts b/packages/medusa/src/api/routes/admin/price-lists/modules-queries/list-and-count-price-lists.ts index 179d160445..b310378f3c 100644 --- a/packages/medusa/src/api/routes/admin/price-lists/modules-queries/list-and-count-price-lists.ts +++ b/packages/medusa/src/api/routes/admin/price-lists/modules-queries/list-and-count-price-lists.ts @@ -65,12 +65,18 @@ export async function listAndCountPriceListPricingModule({ priceList.prices = priceSetMoneyAmounts.map((priceSetMoneyAmount) => { const productVariant = priceSetMoneyAmount.price_set.variant_link.variant + const rules = priceSetMoneyAmount.price_rules.reduce((acc, curr) => { + acc[curr.rule_type.rule_attribute] = curr.value + return acc + }, {}) + return { ...(priceSetMoneyAmount.money_amount as MoneyAmount), price_list_id: priceList.id, variant_id: productVariant?.id ?? null, variant: productVariant ?? null, - region_id: null, + region_id: rules["region_id"] ?? null, + rules, } }) diff --git a/packages/pricing/integration-tests/__fixtures__/price-list/data.ts b/packages/pricing/integration-tests/__fixtures__/price-list/data.ts index fd9610ea03..ff2e869300 100644 --- a/packages/pricing/integration-tests/__fixtures__/price-list/data.ts +++ b/packages/pricing/integration-tests/__fixtures__/price-list/data.ts @@ -3,12 +3,12 @@ export const defaultPriceListData = [ id: "price-list-1", title: "Price List 1", description: "test", - number_rules: 0, + rules_count: 0, }, { id: "price-list-2", title: "Price List 2", description: "test", - number_rules: 0, + rules_count: 0, }, ] diff --git a/packages/pricing/integration-tests/__fixtures__/price-set-money-amount/data.ts b/packages/pricing/integration-tests/__fixtures__/price-set-money-amount/data.ts index 1fa5d67ece..8d6879cb99 100644 --- a/packages/pricing/integration-tests/__fixtures__/price-set-money-amount/data.ts +++ b/packages/pricing/integration-tests/__fixtures__/price-set-money-amount/data.ts @@ -4,20 +4,20 @@ export const defaultPriceSetMoneyAmountsData = [ title: "price set money amount USD", price_set: "price-set-1", money_amount: "money-amount-USD", - number_rules: 1, + rules_count: 1, }, { id: "price-set-money-amount-EUR", title: "price set money amount EUR", price_set: "price-set-2", money_amount: "money-amount-EUR", - number_rules: 1, + rules_count: 1, }, { id: "price-set-money-amount-CAD", title: "price set money amount CAD", price_set: "price-set-3", money_amount: "money-amount-CAD", - number_rules: 1, + rules_count: 1, }, ] diff --git a/packages/pricing/integration-tests/__tests__/services/price-set/index.spec.ts b/packages/pricing/integration-tests/__tests__/services/price-set/index.spec.ts index 6fbb38bba3..994e3a79ed 100644 --- a/packages/pricing/integration-tests/__tests__/services/price-set/index.spec.ts +++ b/packages/pricing/integration-tests/__tests__/services/price-set/index.spec.ts @@ -36,7 +36,6 @@ describe("PriceSet Service", () => { id: "money-amount-USD", currency_code: "EUR", amount: 100, - rules: {}, }, ], }, diff --git a/packages/pricing/integration-tests/__tests__/services/pricing-module/calculate-price.spec.ts b/packages/pricing/integration-tests/__tests__/services/pricing-module/calculate-price.spec.ts index 734c96da15..0b51b03e26 100644 --- a/packages/pricing/integration-tests/__tests__/services/pricing-module/calculate-price.spec.ts +++ b/packages/pricing/integration-tests/__tests__/services/pricing-module/calculate-price.spec.ts @@ -18,7 +18,7 @@ const defaultRules = { region_id: ["DE", "DK"], } -const defaultPriceListPrices = [ +const defaultPriceListPrices: PricingTypes.PriceListPriceDTO[] = [ { amount: 232, currency_code: "PLN", @@ -170,63 +170,63 @@ describe("PricingModule Service - Calculate Price", () => { title: "psma PLN", price_set: "price-set-PLN", money_amount: "money-amount-PLN", - number_rules: 0, + rules_count: 0, }, { id: "psma-company_id-EUR", title: "psma EUR - company_id", price_set: "price-set-EUR", money_amount: "money-amount-company_id-EUR", - number_rules: 1, + rules_count: 1, }, { id: "psma-company_id-PLN", title: "psma PLN - company_id", price_set: "price-set-PLN", money_amount: "money-amount-company_id-PLN", - number_rules: 1, + rules_count: 1, }, { id: "psma-region_id-PLN", title: "psma PLN - region_id", price_set: "price-set-PLN", money_amount: "money-amount-region_id-PLN", - number_rules: 1, + rules_count: 1, }, { id: "psma-region_id+company_id-PLN", title: "psma region_id + company_id", price_set: "price-set-PLN", money_amount: "money-amount-region_id+company_id-PLN", - number_rules: 2, + rules_count: 2, }, { id: "psma-region_id-PLN-5-qty", title: "psma PLN - region_id 5 qty", price_set: "price-set-PLN", money_amount: "money-amount-region_id-PLN-5-qty", - number_rules: 1, + rules_count: 1, }, { id: "psma-region_id_company_id-PL-EUR", title: "psma PLN - region_id PL with EUR currency", price_set: "price-set-PLN", money_amount: "money-amount-region_id-PL-EUR", - number_rules: 2, + rules_count: 2, }, { id: "psma-region_id_company_id-PL-EUR-4-qty", title: "psma PLN - region_id PL with EUR currency for quantity 4", price_set: "price-set-PLN", money_amount: "money-amount-region_id-PL-EUR-4-qty", - number_rules: 2, + rules_count: 2, }, { id: "psma-region_id_company_id-PL-EUR-customer-group", title: "psma PLN - region_id PL with EUR currency for customer group", price_set: "price-set-PLN", money_amount: "money-amount-region_id-PL-EUR-customer-group", - number_rules: 3, + rules_count: 3, }, ] @@ -1846,6 +1846,152 @@ describe("PricingModule Service - Calculate Price", () => { }, ]) }) + + it("should return price list prices when price list conditions match within prices", async () => { + await createPriceLists(service, {}, { region_id: ["DE", "PL"] }, [ + ...defaultPriceListPrices, + { + amount: 111, + currency_code: "PLN", + price_set_id: "price-set-PLN", + rules: { + region_id: "DE", + }, + }, + ]) + + const priceSetsResult = await service.calculatePrices( + { id: ["price-set-EUR", "price-set-PLN"] }, + { + context: { + currency_code: "PLN", + region_id: "DE", + customer_group_id: "vip-customer-group-id", + company_id: "medusa-company-id", + }, + } + ) + + expect(priceSetsResult).toEqual([ + { + id: "price-set-EUR", + is_calculated_price_price_list: false, + calculated_amount: null, + is_original_price_price_list: false, + original_amount: null, + currency_code: null, + calculated_price: { + money_amount_id: null, + price_list_id: null, + price_list_type: null, + min_quantity: null, + max_quantity: null, + }, + original_price: { + money_amount_id: null, + price_list_id: null, + price_list_type: null, + min_quantity: null, + max_quantity: null, + }, + }, + { + id: "price-set-PLN", + is_calculated_price_price_list: true, + calculated_amount: 111, + is_original_price_price_list: false, + original_amount: 400, + currency_code: "PLN", + calculated_price: { + money_amount_id: expect.any(String), + price_list_id: expect.any(String), + price_list_type: "sale", + min_quantity: null, + max_quantity: null, + }, + original_price: { + money_amount_id: expect.any(String), + price_list_id: null, + price_list_type: null, + min_quantity: 1, + max_quantity: 5, + }, + }, + ]) + }) + + it("should not return price list prices when price list conditions are met but price rules are not", async () => { + await createPriceLists(service, {}, { region_id: ["DE", "PL"] }, [ + ...defaultPriceListPrices, + { + amount: 111, + currency_code: "PLN", + price_set_id: "price-set-PLN", + rules: { + region_id: "PL", + }, + }, + ]) + + const priceSetsResult = await service.calculatePrices( + { id: ["price-set-EUR", "price-set-PLN"] }, + { + context: { + currency_code: "PLN", + region_id: "DE", + customer_group_id: "vip-customer-group-id", + company_id: "medusa-company-id", + }, + } + ) + + expect(priceSetsResult).toEqual([ + { + id: "price-set-EUR", + is_calculated_price_price_list: false, + calculated_amount: null, + is_original_price_price_list: false, + original_amount: null, + currency_code: null, + calculated_price: { + money_amount_id: null, + price_list_id: null, + price_list_type: null, + min_quantity: null, + max_quantity: null, + }, + original_price: { + money_amount_id: null, + price_list_id: null, + price_list_type: null, + min_quantity: null, + max_quantity: null, + }, + }, + { + id: "price-set-PLN", + is_calculated_price_price_list: true, + calculated_amount: 232, + is_original_price_price_list: false, + original_amount: 400, + currency_code: "PLN", + calculated_price: { + money_amount_id: expect.any(String), + price_list_id: expect.any(String), + price_list_type: "sale", + min_quantity: null, + max_quantity: null, + }, + original_price: { + money_amount_id: expect.any(String), + price_list_id: null, + price_list_type: null, + min_quantity: 1, + max_quantity: 5, + }, + }, + ]) + }) }) }) }) diff --git a/packages/pricing/integration-tests/__tests__/services/pricing-module/price-list.spec.ts b/packages/pricing/integration-tests/__tests__/services/pricing-module/price-list.spec.ts index 3096a2107c..833fac3a45 100644 --- a/packages/pricing/integration-tests/__tests__/services/pricing-module/price-list.spec.ts +++ b/packages/pricing/integration-tests/__tests__/services/pricing-module/price-list.spec.ts @@ -28,6 +28,16 @@ describe("PriceList Service", () => { await createCurrencies(testManager) await createPriceSets(testManager) await createPriceLists(testManager) + await service.createRuleTypes([ + { + name: "Region ID", + rule_attribute: "region_id", + }, + { + name: "Customer Group ID", + rule_attribute: "customer_group_id", + }, + ]) }) afterEach(async () => { @@ -35,7 +45,7 @@ describe("PriceList Service", () => { }) describe("list", () => { - it("list priceLists", async () => { + it("should list priceLists", async () => { const priceListResult = await service.listPriceLists() expect(priceListResult).toEqual([ @@ -48,7 +58,7 @@ describe("PriceList Service", () => { ]) }) - it("list pricelists by id", async () => { + it("should list pricelists by id", async () => { const priceListResult = await service.listPriceLists({ id: ["price-list-1"], }) @@ -279,8 +289,7 @@ describe("PriceList Service", () => { await service.updatePriceLists([ { id: "does-not-exist", - number_rules: 2, - rules: {}, + rules_count: 2, }, ]) } catch (e) { @@ -293,7 +302,7 @@ describe("PriceList Service", () => { }) }) - describe("create", () => { + describe("createPriceLists", () => { it("should create a priceList successfully", async () => { const [created] = await service.createPriceLists([ { @@ -393,5 +402,346 @@ describe("PriceList Service", () => { }) ) }) + + it("should create a price list with granular rules within prices", async () => { + const [created] = await service.createPriceLists([ + { + title: "test", + description: "test", + starts_at: "10/01/2023", + ends_at: "10/30/2023", + rules: { + customer_group_id: [ + "vip-customer-group-id", + "another-vip-customer-group-id", + ], + region_id: ["DE", "DK"], + }, + prices: [ + { + amount: 400, + currency_code: "EUR", + price_set_id: "price-set-1", + rules: { + region_id: "DE", + }, + }, + { + amount: 600, + currency_code: "EUR", + price_set_id: "price-set-1", + }, + ], + }, + ]) + + const [priceList] = await service.listPriceLists( + { + id: [created.id], + }, + { + relations: [ + "price_set_money_amounts.money_amount", + "price_set_money_amounts.price_set", + "price_set_money_amounts.price_rules", + "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.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: 1, + price_rules: expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(String), + value: "DE", + }), + ]), + price_list: expect.objectContaining({ + id: expect.any(String), + }), + money_amount: expect.objectContaining({ + amount: 400, + currency_code: "EUR", + }), + }), + expect.objectContaining({ + rules_count: 0, + price_rules: [], + price_list: expect.objectContaining({ + id: expect.any(String), + }), + money_amount: expect.objectContaining({ + amount: 600, + currency_code: "EUR", + }), + }), + ]), + price_list_rules: expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(String), + rule_type: expect.objectContaining({ + id: expect.any(String), + rule_attribute: "customer_group_id", + }), + price_list_rule_values: expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(String), + value: "vip-customer-group-id", + }), + expect.objectContaining({ + id: expect.any(String), + value: "another-vip-customer-group-id", + }), + ]), + }), + expect.objectContaining({ + id: expect.any(String), + rule_type: expect.objectContaining({ + id: expect.any(String), + rule_attribute: "region_id", + }), + price_list_rule_values: expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(String), + value: "DE", + }), + expect.objectContaining({ + id: expect.any(String), + value: "DK", + }), + ]), + }), + ]), + }) + ) + }) + + it("should throw error when rule type does not exist", async () => { + const error = await service + .createPriceLists([ + { + title: "test", + description: "test", + rules: { + region_id: ["DE", "DK"], + missing_1: ["test-missing-1"], + }, + prices: [ + { + amount: 400, + currency_code: "EUR", + price_set_id: "price-set-1", + rules: { + region_id: "DE", + missing_2: "test-missing-2", + }, + }, + ], + }, + ]) + .catch((e) => e) + + expect(error.message).toEqual( + "Cannot find RuleTypes with rule_attribute - missing_1, missing_2" + ) + }) + }) + + describe("addPriceListPrices", () => { + it("should add a price to a priceList successfully", async () => { + await service.addPriceListPrices([ + { + priceListId: "price-list-1", + prices: [ + { + amount: 123, + currency_code: "EUR", + price_set_id: "price-set-1", + }, + ], + }, + ]) + + 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_list_rules.price_list_rule_values", + "price_list_rules.rule_type", + ], + select: [ + "id", + "price_set_money_amounts.price_rules.value", + "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: 0, + 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", + }, + ]) + + let error + try { + await service.addPriceListPrices([ + { + priceListId: "price-list-1", + prices: [ + { + amount: 123, + currency_code: "EUR", + price_set_id: "price-set-1", + rules: { + twitter_handle: "owjuhl", + }, + }, + ], + }, + ]) + } catch (err) { + error = err + } + + expect(error.message).toEqual( + "" + + `Invalid rule type configuration: Price set rules doesn't exist for rule_attribute "twitter_handle" in price set price-set-1` + ) + }) + + it("should add a price with rules to a priceList successfully", async () => { + await service.createRuleTypes([ + { + name: "region_id", + rule_attribute: "region_id", + }, + ]) + + const r = await service.addRules([ + { + priceSetId: "price-set-1", + rules: [{ attribute: "region_id" }], + }, + ]) + + await service.addPriceListPrices([ + { + priceListId: "price-list-1", + prices: [ + { + amount: 123, + currency_code: "EUR", + price_set_id: "price-set-1", + rules: { + region_id: "EU", + }, + }, + ], + }, + ]) + + 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: 1, + price_list: expect.objectContaining({ + id: expect.any(String), + }), + price_rules: [ + expect.objectContaining({ + value: "EU", + rule_type: expect.objectContaining({ + rule_attribute: "region_id", + }), + }), + ], + money_amount: expect.objectContaining({ + amount: 123, + currency_code: "EUR", + }), + }), + ]), + price_list_rules: [], + }) + ) + }) }) }) diff --git a/packages/pricing/integration-tests/__tests__/services/pricing-module/price-set.spec.ts b/packages/pricing/integration-tests/__tests__/services/pricing-module/price-set.spec.ts index 158f7af075..54b8f4073f 100644 --- a/packages/pricing/integration-tests/__tests__/services/pricing-module/price-set.spec.ts +++ b/packages/pricing/integration-tests/__tests__/services/pricing-module/price-set.spec.ts @@ -6,7 +6,7 @@ import { import { SqlEntityManager } from "@mikro-orm/postgresql" import { PriceSet } from "@models" -import { PriceSetRuleType, initialize } from "../../../../src" +import { initialize, PriceSetRuleType } from "../../../../src" import { seedPriceData } from "../../../__fixtures__/seed-price-data" import { DB_URL, MikroOrmWrapper } from "../../../utils" @@ -400,7 +400,6 @@ describe("PricingModule Service - PriceSet", () => { { amount: 150, currency_code: "USD", - rules: {}, }, ], }, diff --git a/packages/pricing/src/migrations/.snapshot-medusa-pricing.json b/packages/pricing/src/migrations/.snapshot-medusa-pricing.json index fe83287144..403a6b2e35 100644 --- a/packages/pricing/src/migrations/.snapshot-medusa-pricing.json +++ b/packages/pricing/src/migrations/.snapshot-medusa-pricing.json @@ -1,7 +1,5 @@ { - "namespaces": [ - "public" - ], + "namespaces": ["public"], "name": "public", "tables": [ { @@ -48,9 +46,7 @@ "indexes": [ { "keyName": "currency_pkey", - "columnNames": [ - "code" - ], + "columnNames": ["code"], "composite": false, "primary": true, "unique": true @@ -143,18 +139,14 @@ "schema": "public", "indexes": [ { - "columnNames": [ - "currency_code" - ], + "columnNames": ["currency_code"], "composite": false, "keyName": "IDX_money_amount_currency_code", "primary": false, "unique": false }, { - "columnNames": [ - "deleted_at" - ], + "columnNames": ["deleted_at"], "composite": false, "keyName": "IDX_money_amount_deleted_at", "primary": false, @@ -162,9 +154,7 @@ }, { "keyName": "money_amount_pkey", - "columnNames": [ - "id" - ], + "columnNames": ["id"], "composite": false, "primary": true, "unique": true @@ -174,13 +164,9 @@ "foreignKeys": { "money_amount_currency_code_foreign": { "constraintName": "money_amount_currency_code_foreign", - "columnNames": [ - "currency_code" - ], + "columnNames": ["currency_code"], "localTableName": "public.money_amount", - "referencedColumnNames": [ - "code" - ], + "referencedColumnNames": ["code"], "referencedTableName": "public.currency", "deleteRule": "set null", "updateRule": "cascade" @@ -224,10 +210,7 @@ "primary": false, "nullable": false, "default": "'draft'", - "enumItems": [ - "active", - "draft" - ], + "enumItems": ["active", "draft"], "mappedType": "enum" }, "type": { @@ -238,10 +221,7 @@ "primary": false, "nullable": false, "default": "'sale'", - "enumItems": [ - "sale", - "override" - ], + "enumItems": ["sale", "override"], "mappedType": "enum" }, "starts_at": { @@ -264,8 +244,8 @@ "length": 6, "mappedType": "datetime" }, - "number_rules": { - "name": "number_rules", + "rules_count": { + "name": "rules_count", "type": "integer", "unsigned": false, "autoincrement": false, @@ -311,9 +291,7 @@ "schema": "public", "indexes": [ { - "columnNames": [ - "deleted_at" - ], + "columnNames": ["deleted_at"], "composite": false, "keyName": "IDX_price_list_deleted_at", "primary": false, @@ -321,9 +299,7 @@ }, { "keyName": "price_list_pkey", - "columnNames": [ - "id" - ], + "columnNames": ["id"], "composite": false, "primary": true, "unique": true @@ -349,9 +325,7 @@ "indexes": [ { "keyName": "price_set_pkey", - "columnNames": [ - "id" - ], + "columnNames": ["id"], "composite": false, "primary": true, "unique": true @@ -398,8 +372,8 @@ "nullable": false, "mappedType": "text" }, - "number_rules": { - "name": "number_rules", + "rules_count": { + "name": "rules_count", "type": "integer", "unsigned": false, "autoincrement": false, @@ -422,36 +396,28 @@ "schema": "public", "indexes": [ { - "columnNames": [ - "price_set_id" - ], + "columnNames": ["price_set_id"], "composite": false, "keyName": "IDX_price_set_money_amount_price_set_id", "primary": false, "unique": false }, { - "columnNames": [ - "money_amount_id" - ], + "columnNames": ["money_amount_id"], "composite": false, "keyName": "IDX_price_set_money_amount_money_amount_id", "primary": false, "unique": false }, { - "columnNames": [ - "money_amount_id" - ], + "columnNames": ["money_amount_id"], "composite": false, "keyName": "price_set_money_amount_money_amount_id_unique", "primary": false, "unique": true }, { - "columnNames": [ - "price_list_id" - ], + "columnNames": ["price_list_id"], "composite": false, "keyName": "IDX_price_rule_price_list_id", "primary": false, @@ -459,9 +425,7 @@ }, { "keyName": "price_set_money_amount_pkey", - "columnNames": [ - "id" - ], + "columnNames": ["id"], "composite": false, "primary": true, "unique": true @@ -471,39 +435,27 @@ "foreignKeys": { "price_set_money_amount_price_set_id_foreign": { "constraintName": "price_set_money_amount_price_set_id_foreign", - "columnNames": [ - "price_set_id" - ], + "columnNames": ["price_set_id"], "localTableName": "public.price_set_money_amount", - "referencedColumnNames": [ - "id" - ], + "referencedColumnNames": ["id"], "referencedTableName": "public.price_set", "deleteRule": "cascade", "updateRule": "cascade" }, "price_set_money_amount_money_amount_id_foreign": { "constraintName": "price_set_money_amount_money_amount_id_foreign", - "columnNames": [ - "money_amount_id" - ], + "columnNames": ["money_amount_id"], "localTableName": "public.price_set_money_amount", - "referencedColumnNames": [ - "id" - ], + "referencedColumnNames": ["id"], "referencedTableName": "public.money_amount", "deleteRule": "cascade", "updateRule": "cascade" }, "price_set_money_amount_price_list_id_foreign": { "constraintName": "price_set_money_amount_price_list_id_foreign", - "columnNames": [ - "price_list_id" - ], + "columnNames": ["price_list_id"], "localTableName": "public.price_set_money_amount", - "referencedColumnNames": [ - "id" - ], + "referencedColumnNames": ["id"], "referencedTableName": "public.price_list", "deleteRule": "cascade", "updateRule": "cascade" @@ -554,9 +506,7 @@ "schema": "public", "indexes": [ { - "columnNames": [ - "rule_attribute" - ], + "columnNames": ["rule_attribute"], "composite": false, "keyName": "IDX_rule_type_rule_attribute", "primary": false, @@ -564,9 +514,7 @@ }, { "keyName": "rule_type_pkey", - "columnNames": [ - "id" - ], + "columnNames": ["id"], "composite": false, "primary": true, "unique": true @@ -609,18 +557,14 @@ "schema": "public", "indexes": [ { - "columnNames": [ - "price_set_id" - ], + "columnNames": ["price_set_id"], "composite": false, "keyName": "IDX_price_set_rule_type_price_set_id", "primary": false, "unique": false }, { - "columnNames": [ - "rule_type_id" - ], + "columnNames": ["rule_type_id"], "composite": false, "keyName": "IDX_price_set_rule_type_rule_type_id", "primary": false, @@ -628,9 +572,7 @@ }, { "keyName": "price_set_rule_type_pkey", - "columnNames": [ - "id" - ], + "columnNames": ["id"], "composite": false, "primary": true, "unique": true @@ -640,26 +582,18 @@ "foreignKeys": { "price_set_rule_type_price_set_id_foreign": { "constraintName": "price_set_rule_type_price_set_id_foreign", - "columnNames": [ - "price_set_id" - ], + "columnNames": ["price_set_id"], "localTableName": "public.price_set_rule_type", - "referencedColumnNames": [ - "id" - ], + "referencedColumnNames": ["id"], "referencedTableName": "public.price_set", "deleteRule": "cascade", "updateRule": "cascade" }, "price_set_rule_type_rule_type_id_foreign": { "constraintName": "price_set_rule_type_rule_type_id_foreign", - "columnNames": [ - "rule_type_id" - ], + "columnNames": ["rule_type_id"], "localTableName": "public.price_set_rule_type", - "referencedColumnNames": [ - "id" - ], + "referencedColumnNames": ["id"], "referencedTableName": "public.rule_type", "updateRule": "cascade" } @@ -708,18 +642,14 @@ "schema": "public", "indexes": [ { - "columnNames": [ - "price_set_money_amount_id" - ], + "columnNames": ["price_set_money_amount_id"], "composite": false, "keyName": "IDX_price_set_money_amount_rules_price_set_money_amount_id", "primary": false, "unique": false }, { - "columnNames": [ - "rule_type_id" - ], + "columnNames": ["rule_type_id"], "composite": false, "keyName": "IDX_price_set_money_amount_rules_rule_type_id", "primary": false, @@ -727,9 +657,7 @@ }, { "keyName": "price_set_money_amount_rules_pkey", - "columnNames": [ - "id" - ], + "columnNames": ["id"], "composite": false, "primary": true, "unique": true @@ -739,26 +667,18 @@ "foreignKeys": { "price_set_money_amount_rules_price_set_money_amount_id_foreign": { "constraintName": "price_set_money_amount_rules_price_set_money_amount_id_foreign", - "columnNames": [ - "price_set_money_amount_id" - ], + "columnNames": ["price_set_money_amount_id"], "localTableName": "public.price_set_money_amount_rules", - "referencedColumnNames": [ - "id" - ], + "referencedColumnNames": ["id"], "referencedTableName": "public.price_set_money_amount", "deleteRule": "cascade", "updateRule": "cascade" }, "price_set_money_amount_rules_rule_type_id_foreign": { "constraintName": "price_set_money_amount_rules_rule_type_id_foreign", - "columnNames": [ - "rule_type_id" - ], + "columnNames": ["rule_type_id"], "localTableName": "public.price_set_money_amount_rules", - "referencedColumnNames": [ - "id" - ], + "referencedColumnNames": ["id"], "referencedTableName": "public.rule_type", "updateRule": "cascade" } @@ -836,27 +756,21 @@ "schema": "public", "indexes": [ { - "columnNames": [ - "price_set_id" - ], + "columnNames": ["price_set_id"], "composite": false, "keyName": "IDX_price_rule_price_set_id", "primary": false, "unique": false }, { - "columnNames": [ - "rule_type_id" - ], + "columnNames": ["rule_type_id"], "composite": false, "keyName": "IDX_price_rule_rule_type_id", "primary": false, "unique": false }, { - "columnNames": [ - "price_set_money_amount_id" - ], + "columnNames": ["price_set_money_amount_id"], "composite": false, "keyName": "IDX_price_rule_price_set_money_amount_id", "primary": false, @@ -864,9 +778,7 @@ }, { "keyName": "price_rule_pkey", - "columnNames": [ - "id" - ], + "columnNames": ["id"], "composite": false, "primary": true, "unique": true @@ -876,38 +788,26 @@ "foreignKeys": { "price_rule_price_set_id_foreign": { "constraintName": "price_rule_price_set_id_foreign", - "columnNames": [ - "price_set_id" - ], + "columnNames": ["price_set_id"], "localTableName": "public.price_rule", - "referencedColumnNames": [ - "id" - ], + "referencedColumnNames": ["id"], "referencedTableName": "public.price_set", "deleteRule": "cascade", "updateRule": "cascade" }, "price_rule_rule_type_id_foreign": { "constraintName": "price_rule_rule_type_id_foreign", - "columnNames": [ - "rule_type_id" - ], + "columnNames": ["rule_type_id"], "localTableName": "public.price_rule", - "referencedColumnNames": [ - "id" - ], + "referencedColumnNames": ["id"], "referencedTableName": "public.rule_type", "updateRule": "cascade" }, "price_rule_price_set_money_amount_id_foreign": { "constraintName": "price_rule_price_set_money_amount_id_foreign", - "columnNames": [ - "price_set_money_amount_id" - ], + "columnNames": ["price_set_money_amount_id"], "localTableName": "public.price_rule", - "referencedColumnNames": [ - "id" - ], + "referencedColumnNames": ["id"], "referencedTableName": "public.price_set_money_amount", "deleteRule": "cascade", "updateRule": "cascade" @@ -948,18 +848,14 @@ "schema": "public", "indexes": [ { - "columnNames": [ - "rule_type_id" - ], + "columnNames": ["rule_type_id"], "composite": false, "keyName": "IDX_price_list_rule_rule_type_id", "primary": false, "unique": false }, { - "columnNames": [ - "price_list_id" - ], + "columnNames": ["price_list_id"], "composite": false, "keyName": "IDX_price_list_rule_price_list_id", "primary": false, @@ -967,19 +863,14 @@ }, { "keyName": "IDX_price_list_rule_rule_type_id_price_list_id_unique", - "columnNames": [ - "price_list_id", - "rule_type_id" - ], + "columnNames": ["price_list_id", "rule_type_id"], "composite": true, "primary": false, "unique": true }, { "keyName": "price_list_rule_pkey", - "columnNames": [ - "id" - ], + "columnNames": ["id"], "composite": false, "primary": true, "unique": true @@ -989,25 +880,17 @@ "foreignKeys": { "price_list_rule_rule_type_id_foreign": { "constraintName": "price_list_rule_rule_type_id_foreign", - "columnNames": [ - "rule_type_id" - ], + "columnNames": ["rule_type_id"], "localTableName": "public.price_list_rule", - "referencedColumnNames": [ - "id" - ], + "referencedColumnNames": ["id"], "referencedTableName": "public.rule_type", "updateRule": "cascade" }, "price_list_rule_price_list_id_foreign": { "constraintName": "price_list_rule_price_list_id_foreign", - "columnNames": [ - "price_list_id" - ], + "columnNames": ["price_list_id"], "localTableName": "public.price_list_rule", - "referencedColumnNames": [ - "id" - ], + "referencedColumnNames": ["id"], "referencedTableName": "public.price_list", "updateRule": "cascade" } @@ -1047,9 +930,7 @@ "schema": "public", "indexes": [ { - "columnNames": [ - "price_list_rule_id" - ], + "columnNames": ["price_list_rule_id"], "composite": false, "keyName": "IDX_price_list_rule_price_list_rule_value_id", "primary": false, @@ -1057,9 +938,7 @@ }, { "keyName": "price_list_rule_value_pkey", - "columnNames": [ - "id" - ], + "columnNames": ["id"], "composite": false, "primary": true, "unique": true @@ -1069,13 +948,9 @@ "foreignKeys": { "price_list_rule_value_price_list_rule_id_foreign": { "constraintName": "price_list_rule_value_price_list_rule_id_foreign", - "columnNames": [ - "price_list_rule_id" - ], + "columnNames": ["price_list_rule_id"], "localTableName": "public.price_list_rule_value", - "referencedColumnNames": [ - "id" - ], + "referencedColumnNames": ["id"], "referencedTableName": "public.price_list_rule", "deleteRule": "cascade", "updateRule": "cascade" diff --git a/packages/pricing/src/migrations/Migration20230929122253.ts b/packages/pricing/src/migrations/Migration20230929122253.ts index d0a29286c3..2a3fad2ae7 100644 --- a/packages/pricing/src/migrations/Migration20230929122253.ts +++ b/packages/pricing/src/migrations/Migration20230929122253.ts @@ -18,7 +18,7 @@ export class Migration20230929122253 extends Migration { ) this.addSql( - 'create table "price_set_money_amount" ("id" text not null, "title" text not null, "price_set_id" text not null, "money_amount_id" text not null, "number_rules" integer not null default 0, constraint "price_set_money_amount_pkey" primary key ("id"));' + 'create table "price_set_money_amount" ("id" text not null, "title" text not null, "price_set_id" text not null, "money_amount_id" text not null, "rules_count" integer not null default 0, constraint "price_set_money_amount_pkey" primary key ("id"));' ) this.addSql( 'create index "IDX_price_set_money_amount_price_set_id" on "price_set_money_amount" ("price_set_id");' @@ -103,7 +103,7 @@ export class Migration20230929122253 extends Migration { ) this.addSql( - 'create table if not exists "price_list" ("id" text not null, "status" text check ("status" in (\'active\', \'draft\')) not null default \'draft\', "starts_at" timestamptz null, "ends_at" timestamptz null, "number_rules" integer not null default 0, constraint "price_list_pkey" primary key ("id"));' + 'create table if not exists "price_list" ("id" text not null, "status" text check ("status" in (\'active\', \'draft\')) not null default \'draft\', "starts_at" timestamptz null, "ends_at" timestamptz null, "rules_count" integer not null default 0, constraint "price_list_pkey" primary key ("id"));' ) this.addSql( diff --git a/packages/pricing/src/migrations/Migration20231101232834.ts b/packages/pricing/src/migrations/Migration20231101232834.ts index e51c5471c9..5b812d57d3 100644 --- a/packages/pricing/src/migrations/Migration20231101232834.ts +++ b/packages/pricing/src/migrations/Migration20231101232834.ts @@ -15,7 +15,7 @@ export class Migration20231101232834 extends Migration { this.addSql( `ALTER TABLE price_list - ADD COLUMN IF NOT EXISTS number_rules integer not null default 0` + ADD COLUMN IF NOT EXISTS rules_count integer not null default 0` ) this.addSql( @@ -65,7 +65,7 @@ export class Migration20231101232834 extends Migration { async down(): Promise { this.addSql('drop table if exists "price_list_rule_value" cascade;') - this.addSql(`ALTER TABLE price_list DROP COLUMN IF EXISTS number_rules`) + this.addSql(`ALTER TABLE price_list DROP COLUMN IF EXISTS rules_count`) this.addSql('alter table "price_list" drop column if exists "title";') diff --git a/packages/pricing/src/models/price-list.ts b/packages/pricing/src/models/price-list.ts index fb8f0dfd90..ca6ba90812 100644 --- a/packages/pricing/src/models/price-list.ts +++ b/packages/pricing/src/models/price-list.ts @@ -21,7 +21,7 @@ import RuleType from "./rule-type" type OptionalFields = | "status" | "type" - | "number_rules" + | "rules_count" | "starts_at" | "ends_at" | "created_at" @@ -82,7 +82,7 @@ export default class PriceList { rule_types = new Collection(this) @Property({ columnType: "integer", default: 0 }) - number_rules?: number + rules_count?: number @Property({ onCreate: () => new Date(), diff --git a/packages/pricing/src/models/price-set-money-amount.ts b/packages/pricing/src/models/price-set-money-amount.ts index 729f4db96e..0c6479d22d 100644 --- a/packages/pricing/src/models/price-set-money-amount.ts +++ b/packages/pricing/src/models/price-set-money-amount.ts @@ -38,7 +38,7 @@ export default class PriceSetMoneyAmount { money_amount?: MoneyAmount @Property({ columnType: "integer", default: 0 }) - number_rules?: number + rules_count?: number @OneToMany({ entity: () => PriceRule, diff --git a/packages/pricing/src/repositories/pricing.ts b/packages/pricing/src/repositories/pricing.ts index 9e12f4a491..a721e8c1df 100644 --- a/packages/pricing/src/repositories/pricing.ts +++ b/packages/pricing/src/repositories/pricing.ts @@ -5,6 +5,7 @@ import { PricingFilters, } from "@medusajs/types" import { MedusaError, MikroOrmBase } from "@medusajs/utils" + import { SqlEntityManager } from "@mikro-orm/postgresql" import { PricingRepositoryService } from "../types" @@ -67,9 +68,9 @@ export class PricingRepository id: "psma1.id", price_set_id: "psma1.price_set_id", money_amount_id: "psma1.money_amount_id", - number_rules: "psma1.number_rules", + rules_count: "psma1.rules_count", price_list_id: "psma1.price_list_id", - pl_number_rules: "pl.number_rules", + pl_rules_count: "pl.rules_count", pl_type: "pl.type", has_price_list: knex.raw( "case when psma1.price_list_id IS NULL then False else True end" @@ -86,23 +87,22 @@ export class PricingRepository ) .leftJoin("rule_type as plrt", "plrt.id", "plr.rule_type_id") .leftJoin("rule_type as rt", "rt.id", "pr.rule_type_id") - .orderBy("pl.number_rules", "desc") - .orderBy("number_rules", "desc") .orderBy([ - { column: "number_rules", order: "desc" }, - { column: "pl.number_rules", order: "desc" }, + { column: "rules_count", order: "desc" }, + { column: "pl.rules_count", order: "desc" }, ]) .groupBy("psma1.id", "pl.id") .having( knex.raw( - "count(DISTINCT rt.rule_attribute) = psma1.number_rules AND psma1.price_list_id IS NULL" + "count(DISTINCT rt.rule_attribute) = psma1.rules_count AND psma1.price_list_id IS NULL" ) ) .orHaving( knex.raw( - "count(DISTINCT plrt.rule_attribute) = pl.number_rules AND psma1.price_list_id IS NOT NULL" + "count(DISTINCT plrt.rule_attribute) = pl.rules_count AND psma1.price_list_id IS NOT NULL" ) ) + psmaSubQueryKnex.orWhere((q) => { for (const [key, value] of Object.entries(context)) { q.orWhere({ @@ -110,8 +110,7 @@ export class PricingRepository "pr.value": value, }) } - - q.orWhere("psma1.number_rules", "=", 0) + q.orWhere("psma1.rules_count", "=", 0) q.whereNull("psma1.price_list_id") }) @@ -124,14 +123,29 @@ export class PricingRepository this.whereNull("pl.ends_at").orWhere("pl.ends_at", ">=", date) }) .andWhere(function () { - for (const [key, value] of Object.entries(context)) { - this.orWhere({ - "plrt.rule_attribute": key, - }) - this.whereIn("plrv.value", [value]) - } + this.andWhere(function () { + for (const [key, value] of Object.entries(context)) { + this.orWhere({ + "plrt.rule_attribute": key, + }) + this.whereIn("plrv.value", [value]) + } - this.orWhere("pl.number_rules", "=", 0) + this.orWhere("pl.rules_count", "=", 0) + }) + + this.andWhere(function () { + this.andWhere(function () { + for (const [key, value] of Object.entries(context)) { + this.orWhere({ + "rt.rule_attribute": key, + "pr.value": value, + }) + } + this.andWhere("psma1.rules_count", ">", 0) + }) + this.orWhere("psma1.rules_count", "=", 0) + }) }) }) @@ -146,8 +160,8 @@ export class PricingRepository max_quantity: "ma.max_quantity", currency_code: "ma.currency_code", default_priority: "rt.default_priority", - number_rules: "psma.number_rules", - pl_number_rules: "psma.pl_number_rules", + rules_count: "psma.rules_count", + pl_rules_count: "psma.pl_rules_count", price_list_type: "psma.pl_type", price_list_id: "psma.price_list_id", }) @@ -160,9 +174,9 @@ export class PricingRepository .orderBy([ { column: "psma.has_price_list", order: "asc" }, - { column: "number_rules", order: "desc" }, - { column: "default_priority", order: "desc" }, { column: "amount", order: "asc" }, + { column: "rules_count", order: "desc" }, + { column: "default_priority", order: "desc" }, ]) if (quantity) { diff --git a/packages/pricing/src/services/price-set-money-amount.ts b/packages/pricing/src/services/price-set-money-amount.ts index b660c72385..02aaff4691 100644 --- a/packages/pricing/src/services/price-set-money-amount.ts +++ b/packages/pricing/src/services/price-set-money-amount.ts @@ -1,6 +1,5 @@ import { Context, DAL, FindConfig, PricingTypes } from "@medusajs/types" import { - doNotForceTransaction, InjectManager, InjectTransactionManager, MedusaContext, diff --git a/packages/pricing/src/services/pricing-module.ts b/packages/pricing/src/services/pricing-module.ts index aaa5066a7c..20ab8ba240 100644 --- a/packages/pricing/src/services/pricing-module.ts +++ b/packages/pricing/src/services/pricing-module.ts @@ -14,12 +14,14 @@ import { RuleTypeDTO, } from "@medusajs/types" import { - groupBy, InjectManager, InjectTransactionManager, MedusaContext, MedusaError, PriceListType, + arrayDifference, + deduplicate, + groupBy, removeNullish, } from "@medusajs/utils" @@ -153,7 +155,7 @@ export default class PricingModuleService< pricingFilters.id.map( (priceSetId: string): PricingTypes.CalculatedPriceSet => { // This is where we select prices, for now we just do a first match based on the database results - // which is prioritized by number_rules first for exact match and then deafult_priority of the rule_type + // which is prioritized by rules_count first for exact match and then deafult_priority of the rule_type // inject custom price selection here const prices = pricesSetPricesMap.get(priceSetId) || [] const priceListPrice = prices.find((p) => p.price_list_id) @@ -288,7 +290,6 @@ export default class PricingModuleService< { id: priceSets.filter((p) => !!p).map((p) => p!.id) }, { relations: ["rule_types", "money_amounts", "price_rules"], - take: null, }, sharedContext ) @@ -332,7 +333,9 @@ export default class PricingModuleService< } const invalidMoneyAmountRule = data - .map((d) => d.prices?.map((ma) => Object.keys(ma.rules)).flat() ?? []) + .map( + (d) => d.prices?.map((ma) => Object.keys(ma?.rules ?? {})).flat() ?? [] + ) .flat() .filter((r) => !ruleTypeMap.has(r)) @@ -360,6 +363,7 @@ export default class PricingModuleService< price_set: createdPriceSets[index], })) || [] ) + if (ruleTypeData.length > 0) { await this.priceSetRuleTypeService_.create( ruleTypeData as unknown as PricingTypes.CreatePriceSetRuleTypeDTO[], @@ -387,7 +391,7 @@ export default class PricingModuleService< price_set: createdPriceSets[index], money_amount: createdMoneyAmounts[moneyAmountIndex++], title: "test", // TODO: accept title - number_rules: numberOfRules, + rules_count: numberOfRules, } priceSetMoneyAmountData.push(priceSetMoneyAmount) @@ -412,7 +416,7 @@ export default class PricingModuleService< // Update price set money amount references for (let i = 0, j = 0; i < priceSetMoneyAmountData.length; i++) { - const rulesCount = (priceSetMoneyAmountData[i] as any).number_rules + const rulesCount = (priceSetMoneyAmountData[i] as any).rules_count for (let k = 0; k < rulesCount; k++, j++) { ;(priceRulesData[j] as any).price_set_money_amount = createdPriceSetMoneyAmounts[i] @@ -449,19 +453,22 @@ export default class PricingModuleService< const priceSets = await this.addRules_(inputs, sharedContext) - return (Array.isArray(data) ? priceSets : priceSets[0]) as unknown as - | PricingTypes.PriceSetDTO[] - | PricingTypes.PriceSetDTO + return await this.list( + { id: priceSets.map(({ id }) => id) }, + { + relations: ["rule_types"], + } + ) } @InjectTransactionManager("baseRepository_") protected async addRules_( inputs: PricingTypes.AddRulesDTO[], @MedusaContext() sharedContext: Context = {} - ): Promise { + ): Promise { const priceSets = await this.priceSetService_.list( { id: inputs.map((d) => d.priceSetId) }, - { relations: ["rule_types"], take: null }, + { relations: ["rule_types"] }, sharedContext ) @@ -537,12 +544,7 @@ export default class PricingModuleService< sharedContext ) - return this.baseRepository_.serialize( - priceSets, - { - populate: true, - } - ) + return priceSets } async addPrices( @@ -566,7 +568,7 @@ export default class PricingModuleService< return (await this.list( { id: input.map((d) => d.priceSetId) }, - { relations: ["money_amounts"], take: null }, + { relations: ["money_amounts"] }, sharedContext )) as unknown as PricingTypes.PriceSetDTO[] | PricingTypes.PriceSetDTO } @@ -578,7 +580,7 @@ export default class PricingModuleService< ) { const priceSets = await this.list( { id: input.map((d) => d.priceSetId) }, - { relations: ["rule_types"], take: null }, + { relations: ["rule_types"] }, sharedContext ) @@ -640,7 +642,7 @@ export default class PricingModuleService< price_set: priceSetId, money_amount: ma, title: "test", // TODO: accept title - number_rules: numberOfRules, + rules_count: numberOfRules, } }) ) @@ -684,7 +686,7 @@ export default class PricingModuleService< { id: data.map((d) => d.id), }, - { take: null }, + {}, sharedContext ) const priceSetIds = priceSets.map((ps) => ps.id) @@ -1386,61 +1388,71 @@ export default class PricingModuleService< data: PricingTypes.CreatePriceListDTO[], @MedusaContext() sharedContext: Context = {} ) { - const createdPriceLists: PricingTypes.PriceListDTO[] = [] - const ruleAttributes = data - .map((priceListData) => Object.keys(priceListData.rules || {})) - .flat() + const ruleTypeAttributes: string[] = [] + + for (const priceListData of data) { + const { prices = [], rules: priceListRules = {} } = priceListData + + ruleTypeAttributes.push(...Object.keys(priceListRules)) + + for (const price of prices) { + const { rules: priceListPriceRules = {} } = price + + ruleTypeAttributes.push(...Object.keys(priceListPriceRules)) + } + } const ruleTypes = await this.listRuleTypes( - { - rule_attribute: ruleAttributes, - }, + { rule_attribute: ruleTypeAttributes }, { take: null } ) + const invalidRuleTypes = arrayDifference( + deduplicate(ruleTypeAttributes), + ruleTypes.map((ruleType) => ruleType.rule_attribute) + ) + + if (invalidRuleTypes.length) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + `Cannot find RuleTypes with rule_attribute - ${invalidRuleTypes.join( + ", " + )}` + ) + } + const ruleTypeMap: Map = new Map( ruleTypes.map((rt) => [rt.rule_attribute, rt]) ) + const priceListsToCreate: PricingTypes.CreatePriceListDTO[] = [] + for (const priceListData of data) { - const { rules = {}, prices = [], ...priceListOnlyData } = priceListData + const { rules = {}, ...priceListOnlyData } = priceListData - const [createdPriceList] = (await this.priceListService_.create( - [ - { - ...priceListOnlyData, - number_rules: Object.keys(rules).length, - }, - ], - sharedContext - )) as unknown as PricingTypes.PriceListDTO[] + priceListsToCreate.push({ + ...priceListOnlyData, + rules_count: Object.keys(rules).length, + }) + } - createdPriceLists.push(createdPriceList) + const priceLists = (await this.priceListService_.create( + priceListsToCreate + )) as unknown as PricingTypes.PriceListDTO[] + + for (var i = 0; i < data.length; i++) { + const { rules = {}, prices = [] } = data[i] + const priceList = priceLists[i] for (const [ruleAttribute, ruleValues = []] of Object.entries(rules)) { - // Find or create rule type - let ruleType = ruleTypeMap.get(ruleAttribute) - - if (!ruleType) { - ;[ruleType] = await this.createRuleTypes( - [ - { - name: ruleAttribute, - rule_attribute: ruleAttribute, - }, - ], - sharedContext - ) - - ruleTypeMap.set(ruleAttribute, ruleType) - } + let ruleType = ruleTypeMap.get(ruleAttribute)! // Create the rule const [priceListRule] = await this.priceListRuleService_.create( [ { - price_list: createdPriceList, - rule_type: ruleType?.id || ruleType, + price_list: priceList, + rule_type: ruleType.id, }, ], sharedContext @@ -1461,29 +1473,48 @@ export default class PricingModuleService< } for (const price of prices) { - const { price_set_id: priceSetId, ...moneyAmountData } = price + const { + price_set_id: priceSetId, + rules: priceRules = {}, + ...moneyAmountData + } = price const [moneyAmount] = await this.moneyAmountService_.create( [moneyAmountData], sharedContext ) - await this.priceSetMoneyAmountService_.create( - [ - { - price_set: priceSetId, - price_list: createdPriceList, - money_amount: moneyAmount, - title: "test", - number_rules: 0, - }, - ] as unknown as PricingTypes.CreatePriceSetMoneyAmountDTO[], + const [priceSetMoneyAmount] = + await this.priceSetMoneyAmountService_.create( + [ + { + price_set: priceSetId, + price_list: priceList, + money_amount: moneyAmount, + title: "test", + rules_count: Object.keys(priceRules).length, + }, + ] as unknown as PricingTypes.CreatePriceSetMoneyAmountDTO[], + sharedContext + ) + + await this.createPriceRules( + Object.entries(priceRules).map(([ruleAttribute, ruleValue]) => { + return { + price_set_id: priceSetId, + rule_type: + ruleTypeMap.get(ruleAttribute)!?.id || + ruleTypeMap.get(ruleAttribute)!, + value: ruleValue, + price_set_money_amount: priceSetMoneyAmount as any, + } + }), sharedContext ) } } - return createdPriceLists + return priceLists } @InjectTransactionManager("baseRepository_") @@ -1519,7 +1550,7 @@ export default class PricingModuleService< const existingPriceLists = await this.listPriceLists( { id: priceListIds }, - { relations: ["price_list_rules"], take: null }, + { relations: ["price_list_rules"] }, sharedContext ) @@ -1531,7 +1562,7 @@ export default class PricingModuleService< { id: priceListRuleIds, }, - { take: null }, + {}, sharedContext ) @@ -1561,7 +1592,7 @@ export default class PricingModuleService< } if (typeof rules === "object") { - updatePriceListData.number_rules = Object.keys(rules).length + updatePriceListData.rules_count = Object.keys(rules).length } const [updatedPriceList] = (await this.priceListService_.update( @@ -1750,11 +1781,78 @@ export default class PricingModuleService< data: PricingTypes.AddPriceListPricesDTO[], sharedContext: Context = {} ): Promise { - const priceLists = await this.listPriceLists( - { id: data.map((d) => d.priceListId) }, - { - take: null, + const ruleTypeAttributes: string[] = [] + const priceListIds: string[] = [] + const priceSetIds: string[] = [] + + for (const priceListData of data) { + priceListIds.push(priceListData.priceListId) + + for (const price of priceListData.prices) { + ruleTypeAttributes.push(...Object.keys(price.rules || {})) + priceSetIds.push(price.price_set_id) + } + } + + const ruleTypes = await this.listRuleTypes( + { rule_attribute: ruleTypeAttributes }, + { take: null }, + sharedContext + ) + + const priceSets = await this.list( + { id: priceSetIds }, + { relations: ["rule_types"] }, + sharedContext + ) + + const priceSetRuleTypeMap: Map> = priceSets.reduce( + (acc, curr) => { + const priceSetRuleAttributeSet: Set = + 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 rule_attribute of Object.keys(price.rules ?? {})) { + if ( + !priceSetRuleTypeMap.get(price.price_set_id)?.has(rule_attribute) + ) { + ruleTypeErrors.push( + `rule_attribute "${rule_attribute}" 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 ruleTypeMap: Map = new Map( + ruleTypes.map((rt) => [rt.rule_attribute, rt]) + ) + + const priceLists = await this.listPriceLists( + { id: priceListIds }, + {}, sharedContext ) @@ -1772,23 +1870,41 @@ export default class PricingModuleService< await Promise.all( prices.map(async (price) => { + const priceRules = price.rules || {} + const noOfRules = Object.keys(priceRules).length + const [moneyAmount] = await this.moneyAmountService_.create( [price] as unknown as CreateMoneyAmountDTO[], sharedContext ) - const psma = await this.priceSetMoneyAmountService_.create( + const [psma] = await this.priceSetMoneyAmountService_.create( [ { price_set: price.price_set_id, money_amount: moneyAmount.id, title: "test", price_list: priceList.id, + rules_count: noOfRules, }, ], sharedContext ) + await this.createPriceRules( + Object.entries(priceRules).map(([ruleAttribute, ruleValue]) => { + return { + price_set_id: price.price_set_id, + rule_type: + ruleTypeMap.get(ruleAttribute)!?.id || + ruleTypeMap.get(ruleAttribute)!, + value: ruleValue, + price_set_money_amount: psma as any, + } + }), + sharedContext + ) + return psma }) ) @@ -1816,7 +1932,6 @@ export default class PricingModuleService< { id: data.map((d) => d.priceListId) }, { relations: ["price_list_rules", "price_list_rules.rule_type"], - take: null, }, sharedContext ) @@ -1956,7 +2071,6 @@ export default class PricingModuleService< { id: data.map((d) => d.priceListId) }, { relations: ["price_list_rules", "price_list_rules.rule_type"], - take: null, }, sharedContext ) diff --git a/packages/pricing/src/types/repositories/price-list.ts b/packages/pricing/src/types/repositories/price-list.ts index ca8993dd21..10e8e24c20 100644 --- a/packages/pricing/src/types/repositories/price-list.ts +++ b/packages/pricing/src/types/repositories/price-list.ts @@ -7,5 +7,5 @@ export interface CreatePriceListDTO { ends_at?: string status?: PriceListStatus type?: PriceListType - number_rules?: number + rules_count?: number } diff --git a/packages/types/src/pricing/common/price-list.ts b/packages/types/src/pricing/common/price-list.ts index a256ca379b..6f41c01ea7 100644 --- a/packages/types/src/pricing/common/price-list.ts +++ b/packages/types/src/pricing/common/price-list.ts @@ -65,7 +65,7 @@ export interface PriceListDTO { /** * The number of rules associated with this price list. */ - number_rules?: number + rules_count?: number /** * The associated price set money amounts. * @@ -111,8 +111,22 @@ export interface PriceListPriceDTO 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 } +/** + * @interface + * + * The price rules to be set for each price in the price set. + * + * Each key of the object is a rule type's `rule_attribute`, and its value + * is the values of the rule. + */ +export interface CreatePriceSetPriceRules extends Record {} + /** * @interface * @@ -154,7 +168,7 @@ export interface CreatePriceListDTO { /** * The number of rules associated with the price list. */ - number_rules?: number + rules_count?: number /** * The rules to be created and associated with the price list. */ @@ -194,7 +208,7 @@ export interface UpdatePriceListDTO { /** * The number of rules associated with the price list. */ - number_rules?: number + rules_count?: number /** * The rules to be created and associated with the price list. */ @@ -227,7 +241,7 @@ export interface FilterablePriceListProps /** * The number of rules to filter price lists by. */ - number_rules?: number[] + rules_count?: number[] } /** diff --git a/packages/types/src/pricing/common/price-rule.ts b/packages/types/src/pricing/common/price-rule.ts index 738d4b3d88..61ff8176c1 100644 --- a/packages/types/src/pricing/common/price-rule.ts +++ b/packages/types/src/pricing/common/price-rule.ts @@ -1,5 +1,6 @@ import { BaseFilterable } from "../../dal" import { PriceSetDTO } from "./price-set" +import { PriceSetMoneyAmountDTO } from "./price-set-money-amount" import { RuleTypeDTO } from "./rule-type" /** @@ -56,24 +57,38 @@ export interface PriceRuleDTO { * A price rule to create. */ export interface CreatePriceRuleDTO { - /** - * The ID of the price rule. - */ - id: string /** * 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. */ - 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. */ value: string + /** + * The priority of the price rule in comparison to other applicable price rules. + */ priority?: number - price_set_money_amount_id: string + /** + * The ID of the associated price set money amount. + */ + price_set_money_amount_id?: string + /** + * The ID or object of the associated price set money amount. + */ + price_set_money_amount?: string | PriceSetMoneyAmountDTO } /** diff --git a/packages/types/src/pricing/common/price-set-money-amount.ts b/packages/types/src/pricing/common/price-set-money-amount.ts index 7cc4118178..c207f04bcf 100644 --- a/packages/types/src/pricing/common/price-set-money-amount.ts +++ b/packages/types/src/pricing/common/price-set-money-amount.ts @@ -20,13 +20,13 @@ export interface PriceSetMoneyAmountDTO { title?: string /** * The price set associated with the price set money amount. - * + * * @expandable */ price_set?: PriceSetDTO /** * The price list associated with the price set money amount. - * + * * @expandable */ price_list?: PriceListDTO @@ -36,13 +36,13 @@ export interface PriceSetMoneyAmountDTO { price_set_id?: string /** * The price rules associated with the price set money amount. - * + * * @expandable */ price_rules?: PriceRuleDTO[] /** * The money amount associated with the price set money amount. - * + * * @expandable */ money_amount?: MoneyAmountDTO @@ -60,6 +60,7 @@ export interface CreatePriceSetMoneyAmountDTO { price_set?: PriceSetDTO | string price_list?: PriceListDTO | string money_amount?: MoneyAmountDTO | string + rules_count?: number } /** diff --git a/packages/types/src/pricing/common/price-set.ts b/packages/types/src/pricing/common/price-set.ts index 8e4b023572..651c4a810f 100644 --- a/packages/types/src/pricing/common/price-set.ts +++ b/packages/types/src/pricing/common/price-set.ts @@ -1,6 +1,7 @@ import { BaseFilterable } from "../../dal"; import { CreateMoneyAmountDTO, FilterableMoneyAmountProps, MoneyAmountDTO } from "./money-amount"; import { RuleTypeDTO } from "./rule-type"; +import { CreatePriceSetPriceRules } from "./price-list"; /** * @interface @@ -52,7 +53,7 @@ export interface PriceSetDTO { * @interface * * A calculated price set's data. - * + * * @privateRemarks * Do we still need this type? Shouldn't we use CalculatedPriceSet instead? */ @@ -93,7 +94,7 @@ export interface CalculatedPriceSetDTO { /** * @interface - * + * * The calculated price for a specific price set and context. */ export interface CalculatedPriceSet { @@ -102,7 +103,7 @@ export interface CalculatedPriceSet { */ id: string /** - * Whether the calculated price is associated with a price list. During the calculation process, if no valid price list is found, + * Whether the calculated price is associated with a price list. During the calculation process, if no valid price list is found, * the calculated price is set to the original price, which doesn't belong to a price list. In that case, the value of this property is `false`. */ is_calculated_price_price_list?: boolean @@ -112,7 +113,7 @@ export interface CalculatedPriceSet { calculated_amount: number | null /** - * Whether the original price is associated with a price list. During the calculation process, if the price list of the calculated price is of type override, + * Whether the original price is associated with a price list. During the calculation process, if the price list of the calculated price is of type override, * the original price will be the same as the calculated price. In that case, the value of this property is `true`. */ is_original_price_price_list?: boolean @@ -192,7 +193,7 @@ export interface AddRulesDTO { /** * The rules to add to a price set. */ - rules: { + rules: { /** * The value of the rule's `rule_attribute` attribute. */ @@ -209,7 +210,7 @@ export interface CreatePricesDTO extends CreateMoneyAmountDTO { /** * 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: Record + rules?: CreatePriceSetPriceRules } /** @@ -253,7 +254,7 @@ export interface CreatePriceSetDTO { /** * The rules to associate with the price set. */ - rules?: { + rules?: { /** * the value of the rule's `rule_attribute` attribute. */ diff --git a/packages/types/src/workflow/price-list/create-price-list.ts b/packages/types/src/workflow/price-list/create-price-list.ts index 024a58ddb1..a96165cded 100644 --- a/packages/types/src/workflow/price-list/create-price-list.ts +++ b/packages/types/src/workflow/price-list/create-price-list.ts @@ -8,7 +8,7 @@ export interface CreatePriceListDTO { starts_at?: string ends_at?: string status?: PriceListStatus - number_rules?: number + rules_count?: number rules?: PriceListRuleDTO[] prices?: { amount: number @@ -63,7 +63,7 @@ export interface CreatePriceListWorkflowDTO { starts_at?: string ends_at?: string status?: PriceListStatus - number_rules?: number + rules_count?: number prices: InputPrice[] rules?: CreatePriceListRules }