From fc1ef29ed935e192f0943a2bf4b8fbb05ce6890d Mon Sep 17 00:00:00 2001 From: Riqwan Thamir Date: Fri, 24 Nov 2023 14:54:23 +0100 Subject: [PATCH] fix(medusa,pricing,types): rules only gets updated/deleted upon passing an explicit object (#5711) --- .changeset/olive-penguins-cross.md | 7 +++ .../admin/update-price-list.spec.ts | 55 +++++++++++++++++ .../admin/price-lists/update-price-list.ts | 22 +++---- .../pricing/src/services/pricing-module.ts | 33 ++++++---- .../types/src/pricing/common/price-list.ts | 60 +++++++++---------- 5 files changed, 124 insertions(+), 53 deletions(-) create mode 100644 .changeset/olive-penguins-cross.md diff --git a/.changeset/olive-penguins-cross.md b/.changeset/olive-penguins-cross.md new file mode 100644 index 0000000000..d2720cb732 --- /dev/null +++ b/.changeset/olive-penguins-cross.md @@ -0,0 +1,7 @@ +--- +"@medusajs/pricing": patch +"@medusajs/medusa": patch +"@medusajs/types": patch +--- + +fix(medusa,pricing,types): rules only gets updated/deleted upon passing an explicit object 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 20dfecf877..72b3fe55bf 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 @@ -223,4 +223,59 @@ describe("POST /admin/price-lists/: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 api = useApi() as any + 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, + }, + ], + }) + ) + }) }) diff --git a/packages/medusa/src/api/routes/admin/price-lists/update-price-list.ts b/packages/medusa/src/api/routes/admin/price-lists/update-price-list.ts index b00b582659..e6f869c374 100644 --- a/packages/medusa/src/api/routes/admin/price-lists/update-price-list.ts +++ b/packages/medusa/src/api/routes/admin/price-lists/update-price-list.ts @@ -99,22 +99,22 @@ export default async (req, res) => { if (featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) { const updateVariantsWorkflow = updatePriceLists(req.scope) - const rules: PricingTypes.CreatePriceListRules = {} - const customerGroups = validated.customer_groups || [] + const customerGroups = validated.customer_groups delete validated.customer_groups - if (customerGroups.length) { - rules["customer_group_id"] = customerGroups.map((group) => group.id) + 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: [ - { - id, - ...validated, - rules, - }, - ], + price_lists: [updatePriceListInput], } as WorkflowTypes.PriceListWorkflow.UpdatePriceListWorkflowInputDTO await updateVariantsWorkflow.run({ diff --git a/packages/pricing/src/services/pricing-module.ts b/packages/pricing/src/services/pricing-module.ts index ce623d79ac..021201aa33 100644 --- a/packages/pricing/src/services/pricing-module.ts +++ b/packages/pricing/src/services/pricing-module.ts @@ -1499,10 +1499,15 @@ export default class PricingModuleService< @MedusaContext() sharedContext: Context = {} ) { const updatedPriceLists: PricingTypes.PriceListDTO[] = [] - const priceListIds = data.map((d) => d.id) - const ruleAttributes = data - .map((priceListData) => Object.keys(priceListData.rules || {})) - .flat() + const ruleAttributes: string[] = [] + const priceListIds: string[] = [] + + for (const priceListData of data) { + if (typeof priceListData.rules === "object") { + ruleAttributes.push(...Object.keys(priceListData.rules)) + priceListIds.push(priceListData.id) + } + } const existingPriceLists = await this.listPriceLists( { id: priceListIds }, @@ -1542,21 +1547,25 @@ export default class PricingModuleService< ) for (const priceListData of data) { - const { rules = {}, ...priceListOnlyData } = priceListData + const { rules, ...priceListOnlyData } = priceListData + const updatePriceListData = { + ...priceListOnlyData, + } + + if (typeof rules === "object") { + updatePriceListData.number_rules = Object.keys(rules).length + } const [updatedPriceList] = (await this.priceListService_.update( - [ - { - ...priceListOnlyData, - number_rules: Object.keys(rules).length, - }, - ], + [updatePriceListData], sharedContext )) as unknown as PricingTypes.PriceListDTO[] updatedPriceLists.push(updatedPriceList) - for (const [ruleAttribute, ruleValues = []] of Object.entries(rules)) { + for (const [ruleAttribute, ruleValues = []] of Object.entries( + rules || {} + )) { let ruleType = ruleTypeMap.get(ruleAttribute) if (!ruleType) { diff --git a/packages/types/src/pricing/common/price-list.ts b/packages/types/src/pricing/common/price-list.ts index 25d7ea58bc..42e2a6fd4c 100644 --- a/packages/types/src/pricing/common/price-list.ts +++ b/packages/types/src/pricing/common/price-list.ts @@ -6,7 +6,7 @@ import { RuleTypeDTO } from "./rule-type" /** * @enum - * + * * The price list's status. */ export enum PriceListStatus { @@ -22,7 +22,7 @@ export enum PriceListStatus { /** * @enum - * + * * The price list's type. */ export enum PriceListType { @@ -38,7 +38,7 @@ export enum PriceListType { /** * @interface - * + * * A price list's details. */ export interface PriceListDTO { @@ -68,34 +68,34 @@ export interface PriceListDTO { number_rules?: number /** * The associated price set money amounts. - * + * * @expandable */ price_set_money_amounts?: PriceSetMoneyAmountDTO[] /** * The associated money amounts. - * + * * @expandable */ money_amounts?: MoneyAmountDTO[] /** * The associated rule types. - * + * * @expandable */ rule_types?: RuleTypeDTO[] /** * The price set's rules. - * + * * @expandable */ rules?: PriceListRuleDTO[] /** * The price set's rules. - * + * * @privateRemarks * Do we need both this and `rules`? - * + * * @expandable */ price_list_rules?: PriceListRuleDTO[] @@ -103,7 +103,7 @@ export interface PriceListDTO { /** * @interface - * + * * The prices associated with a price list. */ export interface PriceListPriceDTO extends CreateMoneyAmountDTO { @@ -115,15 +115,15 @@ export interface PriceListPriceDTO extends CreateMoneyAmountDTO { /** * @interface - * + * * The price list's rules to be set. Each key of the object is a rule type's `rule_attribute`, and its value - * is the values of the rule. + * is the values of the rule. */ export interface CreatePriceListRules extends Record {} /** * @interface - * + * * The price list to create. */ export interface CreatePriceListDTO { @@ -167,7 +167,7 @@ export interface CreatePriceListDTO { /** * @interface - * + * * The attributes to update in a price list. */ export interface UpdatePriceListDTO { @@ -182,11 +182,11 @@ export interface UpdatePriceListDTO { /** * The price list is enabled starting from this date. */ - starts_at?: string + starts_at?: string | null /** * The price list expires after this date. */ - ends_at?: string + ends_at?: string | null /** * The price list's status. */ @@ -203,7 +203,7 @@ export interface UpdatePriceListDTO { /** * @inteface - * + * * Filters to apply on price lists. */ export interface FilterablePriceListProps @@ -232,7 +232,7 @@ export interface FilterablePriceListProps /** * @interface - * + * * Filters to apply on price list rules. */ export interface FilterablePriceListRuleProps @@ -264,7 +264,7 @@ export interface FilterablePriceListRuleValueProps /** * @interface - * + * * The price list rule's details. */ export interface PriceListRuleDTO { @@ -274,26 +274,26 @@ export interface PriceListRuleDTO { id: string /** * The value of the rule. - * + * * @privateRemarks * Shouldn't this be in PriceListRuleValueDTO only? */ value: string /** * The associated rule type. - * + * * @expandable */ rule_type: RuleTypeDTO /** * The associated price list. - * + * * @expandable */ price_list: PriceListDTO /** * The associated rule values. - * + * * @expandable */ price_list_rule_values?: PriceListRuleValueDTO[] @@ -301,7 +301,7 @@ export interface PriceListRuleDTO { /** * @interface - * + * * The price list rule to create. */ export interface CreatePriceListRuleDTO { @@ -325,7 +325,7 @@ export interface CreatePriceListRuleDTO { /** * @interface - * + * * The attributes to update in a price list rule. */ export interface UpdatePriceListRuleDTO { @@ -353,7 +353,7 @@ export interface UpdatePriceListRuleDTO { /** * @interface - * + * * The price list rule value's details. */ export interface PriceListRuleValueDTO { @@ -367,7 +367,7 @@ export interface PriceListRuleValueDTO { value: string /** * The associated price list rule. - * + * * @expandable */ price_list_rule: PriceListRuleDTO @@ -387,7 +387,7 @@ export interface UpdatePriceListRuleValueDTO { /** * @interface - * + * * The prices to be added to a price list. */ export interface AddPriceListPricesDTO { @@ -403,7 +403,7 @@ export interface AddPriceListPricesDTO { /** * @interface - * + * * The rules to add to a price list. */ export interface SetPriceListRulesDTO { @@ -420,7 +420,7 @@ export interface SetPriceListRulesDTO { /** * @interface - * + * * The rules to remove from a price list. */ export interface RemovePriceListRulesDTO {