@medusajs/pricing 0.1.13-snapshot-20240718083016 → 0.1.13-snapshot-20240719080828

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. package/dist/index.d.ts +6 -6
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +5 -9
  4. package/dist/joiner-config.d.ts +2 -10
  5. package/dist/joiner-config.d.ts.map +1 -0
  6. package/dist/joiner-config.js +4 -52
  7. package/dist/migrations/Migration20230929122253.d.ts +1 -0
  8. package/dist/migrations/Migration20230929122253.d.ts.map +1 -0
  9. package/dist/migrations/Migration20240322094407.d.ts +1 -0
  10. package/dist/migrations/Migration20240322094407.d.ts.map +1 -0
  11. package/dist/migrations/Migration20240322113359.d.ts +1 -0
  12. package/dist/migrations/Migration20240322113359.d.ts.map +1 -0
  13. package/dist/migrations/Migration20240322120125.d.ts +1 -0
  14. package/dist/migrations/Migration20240322120125.d.ts.map +1 -0
  15. package/dist/migrations/Migration20240626133555.d.ts +5 -0
  16. package/dist/migrations/Migration20240626133555.d.ts.map +1 -0
  17. package/dist/migrations/Migration20240626133555.js +33 -0
  18. package/dist/migrations/Migration20240704094505.d.ts +6 -0
  19. package/dist/migrations/Migration20240704094505.d.ts.map +1 -0
  20. package/dist/migrations/Migration20240704094505.js +15 -0
  21. package/dist/models/index.d.ts +2 -3
  22. package/dist/models/index.d.ts.map +1 -0
  23. package/dist/models/index.js +3 -7
  24. package/dist/models/price-list-rule.d.ts +6 -8
  25. package/dist/models/price-list-rule.d.ts.map +1 -0
  26. package/dist/models/price-list-rule.js +8 -29
  27. package/dist/models/price-list.d.ts +2 -3
  28. package/dist/models/price-list.d.ts.map +1 -0
  29. package/dist/models/price-list.js +0 -9
  30. package/dist/models/price-preference.d.ts +13 -0
  31. package/dist/models/price-preference.d.ts.map +1 -0
  32. package/dist/models/{rule-type.js → price-preference.js} +35 -40
  33. package/dist/models/price-rule.d.ts +5 -9
  34. package/dist/models/price-rule.d.ts.map +1 -0
  35. package/dist/models/price-rule.js +6 -45
  36. package/dist/models/price-set.d.ts +1 -4
  37. package/dist/models/price-set.d.ts.map +1 -0
  38. package/dist/models/price-set.js +0 -19
  39. package/dist/models/price.d.ts +5 -4
  40. package/dist/models/price.d.ts.map +1 -0
  41. package/dist/models/price.js +5 -5
  42. package/dist/repositories/index.d.ts +1 -0
  43. package/dist/repositories/index.d.ts.map +1 -0
  44. package/dist/repositories/pricing.d.ts +1 -0
  45. package/dist/repositories/pricing.d.ts.map +1 -0
  46. package/dist/repositories/pricing.js +29 -36
  47. package/dist/schema/index.d.ts +1 -0
  48. package/dist/schema/index.d.ts.map +1 -0
  49. package/dist/services/index.d.ts +1 -2
  50. package/dist/services/index.d.ts.map +1 -0
  51. package/dist/services/index.js +1 -5
  52. package/dist/services/pricing-module.d.ts +66 -53
  53. package/dist/services/pricing-module.d.ts.map +1 -0
  54. package/dist/services/pricing-module.js +594 -605
  55. package/dist/types/index.d.ts +1 -0
  56. package/dist/types/index.d.ts.map +1 -0
  57. package/dist/types/services/index.d.ts +30 -2
  58. package/dist/types/services/index.d.ts.map +1 -0
  59. package/dist/types/services/index.js +0 -16
  60. package/dist/utils/events.d.ts +63 -0
  61. package/dist/utils/events.d.ts.map +1 -0
  62. package/dist/utils/events.js +66 -0
  63. package/dist/utils/index.d.ts +2 -0
  64. package/dist/utils/index.d.ts.map +1 -0
  65. package/dist/utils/index.js +1 -0
  66. package/dist/utils/validate-price-list-dates.d.ts +1 -0
  67. package/dist/utils/validate-price-list-dates.d.ts.map +1 -0
  68. package/package.json +8 -13
  69. package/dist/initialize/index.d.ts +0 -4
  70. package/dist/initialize/index.js +0 -17
  71. package/dist/loaders/connection.d.ts +0 -4
  72. package/dist/loaders/connection.js +0 -40
  73. package/dist/loaders/container.d.ts +0 -2
  74. package/dist/loaders/container.js +0 -34
  75. package/dist/loaders/index.d.ts +0 -2
  76. package/dist/loaders/index.js +0 -18
  77. package/dist/models/price-list-rule-value.d.ts +0 -17
  78. package/dist/models/price-list-rule-value.js +0 -102
  79. package/dist/models/price-set-rule-type.d.ts +0 -10
  80. package/dist/models/price-set-rule-type.js +0 -108
  81. package/dist/models/rule-type.d.ts +0 -17
  82. package/dist/module-definition.d.ts +0 -4
  83. package/dist/module-definition.js +0 -50
  84. package/dist/scripts/bin/run-seed.d.ts +0 -3
  85. package/dist/scripts/bin/run-seed.js +0 -38
  86. package/dist/scripts/seed.d.ts +0 -4
  87. package/dist/scripts/seed.js +0 -67
  88. package/dist/services/price-list.d.ts +0 -16
  89. package/dist/services/price-list.js +0 -34
  90. package/dist/services/rule-type.d.ts +0 -15
  91. package/dist/services/rule-type.js +0 -53
  92. package/dist/types/services/price-list.d.ts +0 -18
  93. package/dist/types/services/price-list.js +0 -2
  94. package/dist/types/services/price-set.d.ts +0 -4
  95. package/dist/types/services/price-set.js +0 -2
@@ -17,33 +17,27 @@ const utils_1 = require("@medusajs/utils");
17
17
  const _models_1 = require("../models");
18
18
  const _utils_1 = require("../utils");
19
19
  const joiner_config_1 = require("../joiner-config");
20
- const price_list_1 = require("../models/price-list");
21
- const price_set_1 = require("../models/price-set");
22
- const generateMethodForModels = [
23
- _models_1.PriceList,
24
- _models_1.PriceListRule,
25
- _models_1.PriceListRuleValue,
26
- _models_1.PriceRule,
27
- _models_1.Price,
28
- _models_1.PriceSetRuleType,
29
- _models_1.RuleType,
30
- ];
31
- class PricingModuleService extends utils_1.ModulesSdkUtils.abstractModuleServiceFactory(_models_1.PriceSet, generateMethodForModels, joiner_config_1.entityNameToLinkableKeysMap) {
32
- constructor({ baseRepository, pricingRepository, ruleTypeService, priceSetService, priceRuleService, priceSetRuleTypeService, priceService, priceListService, priceListRuleService, priceListRuleValueService, }, moduleDeclaration) {
20
+ const generateMethodForModels = {
21
+ PriceSet: _models_1.PriceSet,
22
+ PriceList: _models_1.PriceList,
23
+ PriceListRule: _models_1.PriceListRule,
24
+ PriceRule: _models_1.PriceRule,
25
+ Price: _models_1.Price,
26
+ PricePreference: _models_1.PricePreference,
27
+ };
28
+ class PricingModuleService extends utils_1.ModulesSdkUtils.MedusaService(generateMethodForModels) {
29
+ constructor({ baseRepository, pricingRepository, priceSetService, priceRuleService, priceService, pricePreferenceService, priceListService, priceListRuleService, }, moduleDeclaration) {
33
30
  // @ts-ignore
34
31
  super(...arguments);
35
32
  this.moduleDeclaration = moduleDeclaration;
36
33
  this.baseRepository_ = baseRepository;
37
34
  this.pricingRepository_ = pricingRepository;
38
- this.ruleTypeService_ = ruleTypeService;
39
35
  this.priceSetService_ = priceSetService;
40
- this.ruleTypeService_ = ruleTypeService;
41
36
  this.priceRuleService_ = priceRuleService;
42
- this.priceSetRuleTypeService_ = priceSetRuleTypeService;
43
37
  this.priceService_ = priceService;
38
+ this.pricePreferenceService_ = pricePreferenceService;
44
39
  this.priceListService_ = priceListService;
45
40
  this.priceListRuleService_ = priceListRuleService;
46
- this.priceListRuleValueService_ = priceListRuleValueService;
47
41
  }
48
42
  __joinerConfig() {
49
43
  return joiner_config_1.joinerConfig;
@@ -51,61 +45,69 @@ class PricingModuleService extends utils_1.ModulesSdkUtils.abstractModuleService
51
45
  setupCalculatedPriceConfig_(filters, config) {
52
46
  const fieldIdx = config.relations?.indexOf("calculated_price");
53
47
  const shouldCalculatePrice = fieldIdx > -1;
48
+ const pricingContext = filters.context ?? {};
49
+ delete filters.context;
54
50
  if (!shouldCalculatePrice) {
55
51
  return;
56
52
  }
57
- let pricingContext = filters.context ?? {};
58
53
  // cleanup virtual field "calculated_price"
59
54
  config.relations?.splice(fieldIdx, 1);
60
- delete filters.context;
61
55
  return pricingContext;
62
56
  }
63
- async list(filters = {}, config = {}, sharedContext = {}) {
64
- const pricingContext = this.setupCalculatedPriceConfig_(filters, config);
65
- const priceSets = await super.list(filters, config, sharedContext);
66
- if (pricingContext && priceSets.length) {
67
- const priceSetIds = [];
68
- const priceSetMap = new Map();
69
- for (const priceSet of priceSets) {
70
- priceSetIds.push(priceSet.id);
71
- priceSetMap.set(priceSet.id, priceSet);
72
- }
73
- const calculatedPrices = await this.calculatePrices({ id: priceSets.map((p) => p.id) }, { context: pricingContext }, sharedContext);
74
- for (const calculatedPrice of calculatedPrices) {
75
- const priceSet = priceSetMap.get(calculatedPrice.id);
76
- priceSet.calculated_price = calculatedPrice;
77
- }
57
+ // @ts-expect-error
58
+ async retrievePriceSet(id, config, sharedContext) {
59
+ const priceSet = await this.priceSetService_.retrieve(id, this.normalizePriceSetConfig(config), sharedContext);
60
+ return await this.baseRepository_.serialize(priceSet);
61
+ }
62
+ // @ts-expect-error
63
+ async listPriceSets(filters = {}, config = {}, sharedContext = {}) {
64
+ const normalizedConfig = this.normalizePriceSetConfig(config);
65
+ const pricingContext = this.setupCalculatedPriceConfig_(filters, normalizedConfig);
66
+ const priceSets = await super.listPriceSets(filters, normalizedConfig, sharedContext);
67
+ if (!pricingContext || !priceSets.length) {
68
+ return priceSets;
69
+ }
70
+ const calculatedPrices = await this.calculatePrices({ id: priceSets.map((p) => p.id) }, { context: pricingContext }, sharedContext);
71
+ const calculatedPricesMap = new Map();
72
+ for (const calculatedPrice of calculatedPrices) {
73
+ calculatedPricesMap.set(calculatedPrice.id, calculatedPrice);
74
+ }
75
+ for (const priceSet of priceSets) {
76
+ const calculatedPrice = calculatedPricesMap.get(priceSet.id);
77
+ priceSet.calculated_price = calculatedPrice ?? null;
78
78
  }
79
79
  return priceSets;
80
80
  }
81
- async listAndCount(filters = {}, config = {}, sharedContext = {}) {
82
- const pricingContext = this.setupCalculatedPriceConfig_(filters, config);
83
- const [priceSets, count] = await super.listAndCount(filters, config, sharedContext);
84
- if (pricingContext && priceSets.length) {
85
- const priceSetIds = [];
86
- const priceSetMap = new Map();
87
- for (const priceSet of priceSets) {
88
- priceSetIds.push(priceSet.id);
89
- priceSetMap.set(priceSet.id, priceSet);
90
- }
91
- const calculatedPrices = await this.calculatePrices({ id: priceSets.map((p) => p.id) }, { context: pricingContext }, sharedContext);
92
- for (const calculatedPrice of calculatedPrices) {
93
- const priceSet = priceSetMap.get(calculatedPrice.id);
94
- priceSet.calculated_price = calculatedPrice;
95
- }
81
+ // @ts-expect-error
82
+ async listAndCountPriceSets(filters = {}, config = {}, sharedContext = {}) {
83
+ const normalizedConfig = this.normalizePriceSetConfig(config);
84
+ const pricingContext = this.setupCalculatedPriceConfig_(filters, normalizedConfig);
85
+ const [priceSets, count] = await super.listAndCountPriceSets(filters, normalizedConfig, sharedContext);
86
+ if (!pricingContext || !priceSets.length) {
87
+ return [priceSets, count];
88
+ }
89
+ const calculatedPrices = await this.calculatePrices({ id: priceSets.map((p) => p.id) }, { context: pricingContext }, sharedContext);
90
+ const calculatedPricesMap = new Map();
91
+ for (const calculatedPrice of calculatedPrices) {
92
+ calculatedPricesMap.set(calculatedPrice.id, calculatedPrice);
93
+ }
94
+ for (const priceSet of priceSets) {
95
+ const calculatedPrice = calculatedPricesMap.get(priceSet.id);
96
+ priceSet.calculated_price = calculatedPrice ?? null;
96
97
  }
97
98
  return [priceSets, count];
98
99
  }
99
100
  async calculatePrices(pricingFilters, pricingContext = { context: {} }, sharedContext = {}) {
100
101
  const results = await this.pricingRepository_.calculatePrices(pricingFilters, pricingContext, sharedContext);
101
102
  const pricesSetPricesMap = (0, utils_1.groupBy)(results, "price_set_id");
102
- const calculatedPrices = pricingFilters.id.map((priceSetId) => {
103
- // This is where we select prices, for now we just do a first match based on the database results
104
- // which is prioritized by rules_count first for exact match and then deafult_priority of the rule_type
105
- // TODO: inject custom price selection here
106
- const prices = pricesSetPricesMap.get(priceSetId) || [];
103
+ const priceIds = [];
104
+ pricesSetPricesMap.forEach((prices, key) => {
107
105
  const priceListPrice = prices.find((p) => p.price_list_id);
108
106
  const defaultPrice = prices?.find((p) => !p.price_list_id);
107
+ if (!prices.length || (!priceListPrice && !defaultPrice)) {
108
+ pricesSetPricesMap.delete(key);
109
+ return;
110
+ }
109
111
  let calculatedPrice = defaultPrice;
110
112
  let originalPrice = defaultPrice;
111
113
  if (priceListPrice) {
@@ -114,12 +116,43 @@ class PricingModuleService extends utils_1.ModulesSdkUtils.abstractModuleService
114
116
  originalPrice = priceListPrice;
115
117
  }
116
118
  }
119
+ pricesSetPricesMap.set(key, { calculatedPrice, originalPrice });
120
+ priceIds.push(...(0, utils_1.deduplicate)([calculatedPrice?.id, originalPrice?.id].filter(Boolean)));
121
+ });
122
+ // We use the price rules to get the right preferences for the price
123
+ const priceRulesForPrices = await this.priceRuleService_.list({ price_id: priceIds }, { take: null });
124
+ const priceRulesPriceMap = (0, utils_1.groupBy)(priceRulesForPrices, "price_id");
125
+ // Note: For now the preferences are intentionally kept very simple and explicit - they use either the region or currency,
126
+ // so we hard-code those as the possible filters here. This can be made more flexible if needed later on.
127
+ const pricingPreferences = await this.pricePreferenceService_.list({
128
+ $or: Object.entries(pricingContext)
129
+ .filter(([key, val]) => {
130
+ return key === "region_id" || key === "currency_code";
131
+ })
132
+ .map(([key, val]) => ({
133
+ attribute: key,
134
+ value: val,
135
+ })),
136
+ }, {}, sharedContext);
137
+ const calculatedPrices = pricingFilters.id
138
+ .map((priceSetId) => {
139
+ const prices = pricesSetPricesMap.get(priceSetId);
140
+ if (!prices) {
141
+ return null;
142
+ }
143
+ const { calculatedPrice, originalPrice, } = prices;
117
144
  return {
118
145
  id: priceSetId,
119
146
  is_calculated_price_price_list: !!calculatedPrice?.price_list_id,
120
- calculated_amount: parseInt(calculatedPrice?.amount || "") || null,
147
+ is_calculated_price_tax_inclusive: isTaxInclusive(priceRulesPriceMap.get(calculatedPrice.id), pricingPreferences, calculatedPrice.currency_code, pricingContext.context?.region_id),
148
+ calculated_amount: parseFloat(calculatedPrice?.amount || "") || null,
149
+ raw_calculated_amount: calculatedPrice?.raw_amount || null,
121
150
  is_original_price_price_list: !!originalPrice?.price_list_id,
122
- original_amount: parseInt(originalPrice?.amount || "") || null,
151
+ is_original_price_tax_inclusive: originalPrice?.id
152
+ ? isTaxInclusive(priceRulesPriceMap.get(originalPrice.id), pricingPreferences, originalPrice.currency_code || calculatedPrice.currency_code, pricingContext.context?.region_id)
153
+ : false,
154
+ original_amount: parseFloat(originalPrice?.amount || "") || null,
155
+ raw_original_amount: originalPrice?.raw_amount || null,
123
156
  currency_code: calculatedPrice?.currency_code || null,
124
157
  calculated_price: {
125
158
  id: calculatedPrice?.id || null,
@@ -136,35 +169,38 @@ class PricingModuleService extends utils_1.ModulesSdkUtils.abstractModuleService
136
169
  max_quantity: parseInt(originalPrice?.max_quantity || "") || null,
137
170
  },
138
171
  };
139
- });
172
+ })
173
+ .filter(Boolean);
140
174
  return JSON.parse(JSON.stringify(calculatedPrices));
141
175
  }
142
- async create(data, sharedContext = {}) {
176
+ async createPriceSets(data, sharedContext = {}) {
143
177
  const input = Array.isArray(data) ? data : [data];
144
- const priceSets = await this.create_(input, sharedContext);
178
+ const priceSets = await this.createPriceSets_(input, sharedContext);
145
179
  // TODO: Remove the need to refetch the data here
146
- const dbPriceSets = await this.list({ id: priceSets.map((p) => p.id) }, { relations: ["rule_types", "prices", "price_rules"] }, sharedContext);
180
+ const dbPriceSets = await this.listPriceSets({ id: priceSets.map((p) => p.id) }, this.normalizePriceSetConfig({
181
+ relations: ["prices", "prices.price_rules"],
182
+ }), sharedContext);
147
183
  // Ensure the output to be in the same order as the input
148
184
  const results = priceSets.map((priceSet) => {
149
185
  return dbPriceSets.find((p) => p.id === priceSet.id);
150
186
  });
151
187
  return await this.baseRepository_.serialize(Array.isArray(data) ? results : results[0]);
152
188
  }
153
- async upsert(data, sharedContext = {}) {
189
+ async upsertPriceSets(data, sharedContext = {}) {
154
190
  const input = Array.isArray(data) ? data : [data];
155
191
  const forUpdate = input.filter((priceSet) => !!priceSet.id);
156
192
  const forCreate = input.filter((priceSet) => !priceSet.id);
157
193
  const operations = [];
158
194
  if (forCreate.length) {
159
- operations.push(this.create_(forCreate, sharedContext));
195
+ operations.push(this.createPriceSets_(forCreate, sharedContext));
160
196
  }
161
197
  if (forUpdate.length) {
162
- operations.push(this.update_(forUpdate, sharedContext));
198
+ operations.push(this.updatePriceSets_(forUpdate, sharedContext));
163
199
  }
164
200
  const result = (await (0, utils_1.promiseAll)(operations)).flat();
165
201
  return await this.baseRepository_.serialize(Array.isArray(data) ? result : result[0]);
166
202
  }
167
- async update(idOrSelector, data, sharedContext = {}) {
203
+ async updatePriceSets(idOrSelector, data, sharedContext = {}) {
168
204
  let normalizedInput = [];
169
205
  if ((0, utils_1.isString)(idOrSelector)) {
170
206
  // Check if the ID exists, it will throw if not.
@@ -178,53 +214,16 @@ class PricingModuleService extends utils_1.ModulesSdkUtils.abstractModuleService
178
214
  ...data,
179
215
  }));
180
216
  }
181
- const updateResult = await this.update_(normalizedInput, sharedContext);
217
+ const updateResult = await this.updatePriceSets_(normalizedInput, sharedContext);
182
218
  const priceSets = await this.baseRepository_.serialize(updateResult);
183
219
  return (0, utils_1.isString)(idOrSelector) ? priceSets[0] : priceSets;
184
220
  }
185
- async normalizeUpdateData(data, sharedContext) {
186
- const ruleAttributes = data
187
- .map((d) => d.prices?.map((p) => Object.keys(p.rules ?? [])) ?? [])
188
- .flat(Infinity)
189
- .filter(Boolean);
190
- const ruleTypes = await this.ruleTypeService_.list({ rule_attribute: ruleAttributes }, { take: null }, sharedContext);
191
- const ruleTypeMap = ruleTypes.reduce((acc, curr) => {
192
- acc.set(curr.rule_attribute, curr);
193
- return acc;
194
- }, new Map());
195
- return data.map((priceSet) => {
196
- const prices = priceSet.prices?.map((price) => {
197
- const rules = Object.entries(price.rules ?? {}).map(([attribute, value]) => {
198
- return {
199
- price_set_id: priceSet.id,
200
- rule_type_id: ruleTypeMap.get(attribute).id,
201
- value,
202
- };
203
- });
204
- const hasRulesInput = (0, utils_1.isPresent)(price.rules);
205
- delete price.rules;
206
- return {
207
- ...price,
208
- price_set_id: priceSet.id,
209
- price_rules: hasRulesInput ? rules : undefined,
210
- rules_count: hasRulesInput ? rules.length : undefined,
211
- };
212
- });
213
- return {
214
- ...priceSet,
215
- prices,
216
- };
217
- });
218
- }
219
- async update_(data, sharedContext = {}) {
220
- // TODO: We are not handling rule types, rules, etc. here, add support after data models are finalized
221
+ async updatePriceSets_(data, sharedContext = {}) {
221
222
  // TODO: Since money IDs are rarely passed, this will delete all previous data and insert new entries.
222
223
  // We can make the `insert` inside upsertWithReplace do an `upsert` instead to avoid this
223
- const normalizedData = await this.normalizeUpdateData(data, sharedContext);
224
+ const normalizedData = await this.normalizeUpdateData(data);
224
225
  const prices = normalizedData.flatMap((priceSet) => priceSet.prices || []);
225
- const upsertedPrices = await this.priceService_.upsertWithReplace(prices, {
226
- relations: ["price_rules"],
227
- }, sharedContext);
226
+ const { entities: upsertedPrices } = await this.priceService_.upsertWithReplace(prices, { relations: ["price_rules"] }, sharedContext);
228
227
  const priceSetsToUpsert = normalizedData.map((priceSet) => {
229
228
  const { prices, ...rest } = priceSet;
230
229
  return {
@@ -238,61 +237,71 @@ class PricingModuleService extends utils_1.ModulesSdkUtils.abstractModuleService
238
237
  }),
239
238
  };
240
239
  });
241
- return await this.priceSetService_.upsertWithReplace(priceSetsToUpsert, { relations: ["prices"] }, sharedContext);
240
+ const { entities: priceSets } = await this.priceSetService_.upsertWithReplace(priceSetsToUpsert, { relations: ["prices"] }, sharedContext);
241
+ return priceSets;
242
242
  }
243
- async addRules(data, sharedContext = {}) {
244
- const inputs = Array.isArray(data) ? data : [data];
245
- const priceSets = await this.addRules_(inputs, sharedContext);
246
- const dbPriceSets = await this.list({ id: priceSets.map(({ id }) => id) }, { relations: ["rule_types"] });
247
- const orderedPriceSets = priceSets.map((priceSet) => {
248
- return dbPriceSets.find((p) => p.id === priceSet.id);
243
+ async normalizeUpdateData(data) {
244
+ return data.map((priceSet) => {
245
+ return {
246
+ ...priceSet,
247
+ prices: this.normalizePrices(priceSet.prices?.map((p) => ({ ...p, price_set_id: priceSet.id })), []),
248
+ };
249
249
  });
250
- return Array.isArray(data) ? orderedPriceSets : orderedPriceSets[0];
250
+ }
251
+ normalizePrices(data, existingPrices, priceListId) {
252
+ const pricesToUpsert = new Map();
253
+ const existingPricesMap = new Map();
254
+ existingPrices?.forEach((price) => {
255
+ existingPricesMap.set(hashPrice(price), price);
256
+ });
257
+ data?.forEach((price) => {
258
+ const cleanRules = price.rules ? (0, utils_1.removeNullish)(price.rules) : {};
259
+ const ruleEntries = Object.entries(cleanRules);
260
+ const rules = ruleEntries.map(([attribute, value]) => {
261
+ return {
262
+ attribute,
263
+ value,
264
+ };
265
+ });
266
+ const hasRulesInput = (0, utils_1.isPresent)(price.rules);
267
+ const entry = {
268
+ ...price,
269
+ price_list_id: priceListId,
270
+ price_rules: hasRulesInput ? rules : undefined,
271
+ rules_count: hasRulesInput ? ruleEntries.length : undefined,
272
+ };
273
+ delete entry.rules;
274
+ const entryHash = hashPrice(entry);
275
+ // We want to keep the existing rules as they might already have ids, but any other data should come from the updated input
276
+ const existing = existingPricesMap.get(entryHash);
277
+ pricesToUpsert.set(entryHash, {
278
+ ...entry,
279
+ id: existing?.id ?? entry.id,
280
+ price_rules: existing?.price_rules ?? entry.price_rules,
281
+ });
282
+ return entry;
283
+ });
284
+ return Array.from(pricesToUpsert.values());
251
285
  }
252
286
  async addPrices(data, sharedContext = {}) {
253
287
  const input = Array.isArray(data) ? data : [data];
254
288
  await this.addPrices_(input, sharedContext);
255
- const dbPrices = await this.list({ id: input.map((d) => d.priceSetId) }, { relations: ["prices"] }, sharedContext);
289
+ const dbPrices = await this.listPriceSets({ id: input.map((d) => d.priceSetId) }, { relations: ["prices"] }, sharedContext);
256
290
  const orderedPriceSets = input.map((inputItem) => {
257
291
  return dbPrices.find((p) => p.id === inputItem.priceSetId);
258
292
  });
259
293
  return Array.isArray(data) ? orderedPriceSets : orderedPriceSets[0];
260
294
  }
261
- async removeRules(data, sharedContext = {}) {
262
- const priceSets = await this.priceSetService_.list({ id: data.map((d) => d.id) }, {}, sharedContext);
263
- const priceSetIds = priceSets.map((ps) => ps.id);
264
- const ruleTypes = await this.ruleTypeService_.list({
265
- rule_attribute: data.map((d) => d.rules || []).flat(),
266
- }, { take: null }, sharedContext);
267
- const ruleTypeIds = ruleTypes.map((rt) => rt.id);
268
- const priceSetRuleTypes = await this.priceSetRuleTypeService_.list({ price_set_id: priceSetIds, rule_type_id: ruleTypeIds }, { take: null }, sharedContext);
269
- const priceRules = await this.priceRuleService_.list({ price_set_id: priceSetIds, rule_type_id: ruleTypeIds }, { select: ["price"], take: null }, sharedContext);
270
- await this.priceSetRuleTypeService_.delete(priceSetRuleTypes.map((psrt) => psrt.id), sharedContext);
271
- await this.priceService_.delete(priceRules.map((pr) => pr.price.id), sharedContext);
272
- }
295
+ // @ts-ignore
273
296
  async createPriceLists(data, sharedContext = {}) {
274
297
  const priceLists = await this.createPriceLists_(data, sharedContext);
275
298
  return await this.baseRepository_.serialize(priceLists);
276
299
  }
300
+ // @ts-ignore
277
301
  async updatePriceLists(data, sharedContext = {}) {
278
302
  const priceLists = await this.updatePriceLists_(data, sharedContext);
279
303
  return await this.baseRepository_.serialize(priceLists);
280
304
  }
281
- async createPriceListRules(data, sharedContext = {}) {
282
- const priceLists = await this.createPriceListRules_(data, sharedContext);
283
- return await this.baseRepository_.serialize(priceLists, {
284
- populate: true,
285
- });
286
- }
287
- async createPriceListRules_(data, sharedContext = {}) {
288
- return await this.priceListRuleService_.create(data, sharedContext);
289
- }
290
- async updatePriceListRules(data, sharedContext = {}) {
291
- const priceLists = await this.priceListRuleService_.update(data, sharedContext);
292
- return await this.baseRepository_.serialize(priceLists, {
293
- populate: true,
294
- });
295
- }
296
305
  async updatePriceListPrices(data, sharedContext = {}) {
297
306
  const prices = await this.updatePriceListPrices_(data, sharedContext);
298
307
  return await this.baseRepository_.serialize(prices);
@@ -312,505 +321,455 @@ class PricingModuleService extends utils_1.ModulesSdkUtils.abstractModuleService
312
321
  const [priceList] = await this.removePriceListRules_([data], sharedContext);
313
322
  return await this.baseRepository_.serialize(priceList);
314
323
  }
315
- async create_(data, sharedContext = {}) {
324
+ async createPricePreferences(data, sharedContext = {}) {
325
+ const normalized = Array.isArray(data) ? data : [data];
326
+ const preferences = await this.createPricePreferences_(normalized, sharedContext);
327
+ const serialized = await this.baseRepository_.serialize(preferences);
328
+ return Array.isArray(data) ? serialized : serialized[0];
329
+ }
330
+ async upsertPricePreferences(data, sharedContext = {}) {
316
331
  const input = Array.isArray(data) ? data : [data];
317
- const ruleAttributes = data
318
- .map((d) => d.rules?.map((r) => r.rule_attribute) ?? [])
319
- .flat();
320
- const ruleTypes = await this.ruleTypeService_.list({ rule_attribute: ruleAttributes }, { take: null }, sharedContext);
321
- const ruleTypeMap = ruleTypes.reduce((acc, curr) => {
322
- acc.set(curr.rule_attribute, curr);
323
- return acc;
324
- }, new Map());
325
- const invalidRuleAttributes = ruleAttributes.filter((r) => !ruleTypeMap.has(r));
326
- if (invalidRuleAttributes.length > 0) {
327
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, `Rule types don't exist for: ${invalidRuleAttributes.join(", ")}`);
332
+ const forUpdate = input.filter((pricePreference) => !!pricePreference.id);
333
+ const forCreate = input.filter((pricePreference) => !pricePreference.id);
334
+ const operations = [];
335
+ if (forCreate.length) {
336
+ operations.push(this.createPricePreferences_(forCreate, sharedContext));
328
337
  }
329
- const invalidMoneyAmountRule = data
330
- .map((d) => d.prices?.map((ma) => Object.keys(ma?.rules ?? {})).flat() ?? [])
331
- .flat()
332
- .filter((r) => !ruleTypeMap.has(r));
333
- if (invalidMoneyAmountRule.length > 0) {
334
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Rule types don't exist for money amounts with rule attribute: ${invalidMoneyAmountRule.join(", ")}`);
338
+ if (forUpdate.length) {
339
+ operations.push(this.updatePricePreferences_(forUpdate, sharedContext));
335
340
  }
336
- const ruleSetRuleTypeToCreateMap = new Map();
341
+ const result = (await (0, utils_1.promiseAll)(operations)).flat();
342
+ return await this.baseRepository_.serialize(Array.isArray(data) ? result : result[0]);
343
+ }
344
+ async updatePricePreferences(idOrSelector, data, sharedContext = {}) {
345
+ let normalizedInput = [];
346
+ if ((0, utils_1.isString)(idOrSelector)) {
347
+ // Check if the ID exists, it will throw if not.
348
+ await this.pricePreferenceService_.retrieve(idOrSelector, {}, sharedContext);
349
+ normalizedInput = [{ id: idOrSelector, ...data }];
350
+ }
351
+ else {
352
+ const pricePreferences = await this.pricePreferenceService_.list(idOrSelector, {}, sharedContext);
353
+ normalizedInput = pricePreferences.map((pricePreference) => ({
354
+ id: pricePreference.id,
355
+ ...data,
356
+ }));
357
+ }
358
+ const updateResult = await this.updatePricePreferences_(normalizedInput, sharedContext);
359
+ const pricePreferences = await this.baseRepository_.serialize(updateResult);
360
+ return (0, utils_1.isString)(idOrSelector) ? pricePreferences[0] : pricePreferences;
361
+ }
362
+ async createPricePreferences_(data, sharedContext = {}) {
363
+ const preferences = await this.pricePreferenceService_.create(data.map((d) => ({
364
+ ...d,
365
+ is_tax_inclusive: d.is_tax_inclusive ?? false,
366
+ })), sharedContext);
367
+ return preferences;
368
+ }
369
+ async updatePricePreferences_(data, sharedContext = {}) {
370
+ const preferences = await this.pricePreferenceService_.update(data, sharedContext);
371
+ return preferences;
372
+ }
373
+ async createPriceSets_(data, sharedContext = {}) {
374
+ const input = Array.isArray(data) ? data : [data];
337
375
  const toCreate = input.map((inputData) => {
338
- const id = (0, utils_1.generateEntityId)(inputData.id, price_set_1.PriceSetIdPrefix);
339
- const { prices, rules = [], ...rest } = inputData;
340
- let pricesData = [];
341
- rules.forEach((rule) => {
342
- const priceSetRuleType = {
343
- rule_type_id: ruleTypeMap.get(rule.rule_attribute).id,
344
- price_set_id: id,
345
- };
346
- ruleSetRuleTypeToCreateMap.set(JSON.stringify(priceSetRuleType), priceSetRuleType);
347
- });
348
- if (inputData.prices) {
349
- pricesData = inputData.prices.map((price) => {
350
- let { rules: priceRules = {}, ...rest } = price;
351
- const cleanRules = priceRules ? (0, utils_1.removeNullish)(priceRules) : {};
352
- const numberOfRules = Object.keys(cleanRules).length;
353
- const rulesDataMap = new Map();
354
- Object.entries(priceRules).map(([attribute, value]) => {
355
- const rule = {
356
- price_set_id: id,
357
- rule_type_id: ruleTypeMap.get(attribute).id,
358
- value,
359
- };
360
- rulesDataMap.set(JSON.stringify(rule), rule);
361
- const priceSetRuleType = {
362
- rule_type_id: ruleTypeMap.get(attribute).id,
363
- price_set_id: id,
364
- };
365
- ruleSetRuleTypeToCreateMap.set(JSON.stringify(priceSetRuleType), priceSetRuleType);
366
- });
367
- return {
368
- ...rest,
369
- title: "",
370
- rules_count: numberOfRules,
371
- price_rules: Array.from(rulesDataMap.values()),
372
- };
373
- });
374
- }
375
- return {
376
- ...rest,
377
- id,
378
- prices: pricesData,
376
+ const entry = {
377
+ ...inputData,
378
+ prices: this.normalizePrices(inputData.prices, []),
379
379
  };
380
+ return entry;
380
381
  });
381
382
  // Bulk create price sets
382
383
  const createdPriceSets = await this.priceSetService_.create(toCreate, sharedContext);
383
- if (ruleSetRuleTypeToCreateMap.size) {
384
- await this.priceSetRuleTypeService_.create(Array.from(ruleSetRuleTypeToCreateMap.values()), sharedContext);
385
- }
386
- return createdPriceSets;
387
- }
388
- async addRules_(inputs, sharedContext = {}) {
389
- const priceSets = await this.priceSetService_.list({ id: inputs.map((d) => d.priceSetId) }, { relations: ["rule_types"] }, sharedContext);
390
- const priceSetRuleTypeMap = new Map(priceSets.map((priceSet) => [
391
- priceSet.id,
392
- new Map([...priceSet.rule_types].map((rt) => [rt.rule_attribute, rt])),
393
- ]));
394
- const priceSetMap = new Map(priceSets.map((p) => [p.id, p]));
395
- const invalidPriceSetInputs = inputs.filter((d) => !priceSetMap.has(d.priceSetId));
396
- if (invalidPriceSetInputs.length) {
397
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `PriceSets with ids: ${invalidPriceSetInputs
398
- .map((d) => d.priceSetId)
399
- .join(", ")} was not found`);
400
- }
401
- const ruleTypes = await this.ruleTypeService_.list({
402
- rule_attribute: inputs
403
- .map((data) => data.rules.map((r) => r.attribute))
404
- .flat(),
405
- }, { take: null }, sharedContext);
406
- const ruleTypeMap = new Map(ruleTypes.map((rt) => [rt.rule_attribute, rt]));
407
- const invalidRuleAttributeInputs = inputs
408
- .map((d) => d.rules.map((r) => r.attribute))
409
- .flat()
410
- .filter((r) => !ruleTypeMap.has(r));
411
- if (invalidRuleAttributeInputs.length) {
412
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Rule types don't exist for attributes: ${[
413
- ...new Set(invalidRuleAttributeInputs),
414
- ].join(", ")}`);
415
- }
416
- const priceSetRuleTypesCreate = [];
417
- inputs.forEach((data) => {
418
- for (const rule of data.rules) {
419
- if (priceSetRuleTypeMap.get(data.priceSetId).has(rule.attribute)) {
420
- continue;
421
- }
422
- priceSetRuleTypesCreate.push({
423
- rule_type_id: ruleTypeMap.get(rule.attribute).id,
424
- price_set_id: priceSetMap.get(data.priceSetId).id,
384
+ const eventsData = createdPriceSets.reduce((eventsData, priceSet) => {
385
+ eventsData.priceSets.push({
386
+ id: priceSet.id,
387
+ });
388
+ priceSet.prices.map((price) => {
389
+ eventsData.prices.push({
390
+ id: price.id,
425
391
  });
426
- }
392
+ price.price_rules.map((priceRule) => {
393
+ eventsData.priceRules.push({
394
+ id: priceRule.id,
395
+ });
396
+ });
397
+ });
398
+ return eventsData;
399
+ }, {
400
+ priceSets: [],
401
+ priceRules: [],
402
+ prices: [],
427
403
  });
428
- await this.priceSetRuleTypeService_.create(priceSetRuleTypesCreate, sharedContext);
429
- return priceSets;
404
+ _utils_1.eventBuilders.createdPriceSet({
405
+ data: eventsData.priceSets,
406
+ sharedContext,
407
+ });
408
+ _utils_1.eventBuilders.createdPrice({
409
+ data: eventsData.prices,
410
+ sharedContext,
411
+ });
412
+ _utils_1.eventBuilders.createdPriceRule({
413
+ data: eventsData.priceRules,
414
+ sharedContext,
415
+ });
416
+ return createdPriceSets;
430
417
  }
431
418
  async addPrices_(input, sharedContext = {}) {
432
- const priceSets = await this.list({ id: input.map((d) => d.priceSetId) }, { relations: ["rule_types"] }, sharedContext);
419
+ const priceSets = await this.listPriceSets({ id: input.map((d) => d.priceSetId) }, { take: null, relations: ["prices", "prices.price_rules"] }, sharedContext);
420
+ const existingPrices = priceSets
421
+ .map((p) => p.prices)
422
+ .flat();
423
+ const pricesToUpsert = input
424
+ .map((addPrice) => this.normalizePrices(addPrice.prices?.map((p) => ({
425
+ ...p,
426
+ price_set_id: addPrice.priceSetId,
427
+ })), existingPrices))
428
+ .filter(Boolean)
429
+ .flat();
433
430
  const priceSetMap = new Map(priceSets.map((p) => [p.id, p]));
434
- const ruleTypeMap = new Map(priceSets.map((priceSet) => [
435
- priceSet.id,
436
- new Map(priceSet.rule_types?.map((rt) => [rt.rule_attribute, rt]) ?? []),
437
- ]));
438
- input.forEach(({ priceSetId, prices }) => {
439
- const priceSet = priceSetMap.get(priceSetId);
431
+ pricesToUpsert.forEach((price) => {
432
+ const priceSet = priceSetMap.get(price.price_set_id);
440
433
  if (!priceSet) {
441
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Price set with id: ${priceSetId} not found`);
442
- }
443
- const ruleAttributes = prices
444
- .map((d) => (d.rules ? Object.keys(d.rules) : []))
445
- .flat();
446
- const invalidRuleAttributes = ruleAttributes.filter((r) => !ruleTypeMap.get(priceSetId).has(r));
447
- if (invalidRuleAttributes.length > 0) {
448
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, `Rule types don't exist for: ${invalidRuleAttributes.join(", ")}`);
434
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Price set with id: ${price.price_set_id} not found`);
449
435
  }
450
436
  });
451
- const pricesToCreate = input.flatMap(({ priceSetId, prices }) => prices.map((price) => {
452
- const numberOfRules = Object.entries(price?.rules ?? {}).length;
453
- const priceRules = Object.entries(price.rules ?? {}).map(([attribute, value]) => ({
454
- rule_type_id: ruleTypeMap.get(priceSetId).get(attribute).id,
455
- price_set_id: priceSetId,
456
- value,
457
- }));
458
- return {
459
- ...price,
460
- price_set_id: priceSetId,
461
- title: "test",
462
- rules_count: numberOfRules,
463
- priceRules,
464
- };
465
- }));
466
- await this.priceService_.create(pricesToCreate, sharedContext);
437
+ const { entities, performedActions } = await this.priceService_.upsertWithReplace(pricesToUpsert, { relations: ["price_rules"] }, sharedContext);
438
+ _utils_1.eventBuilders.createdPrice({
439
+ data: performedActions.created[_models_1.Price.name] ?? [],
440
+ sharedContext,
441
+ });
442
+ _utils_1.eventBuilders.updatedPrice({
443
+ data: performedActions.updated[_models_1.Price.name] ?? [],
444
+ sharedContext,
445
+ });
446
+ _utils_1.eventBuilders.deletedPrice({
447
+ data: performedActions.deleted[_models_1.Price.name] ?? [],
448
+ sharedContext,
449
+ });
450
+ _utils_1.eventBuilders.createdPriceRule({
451
+ data: performedActions.created[_models_1.PriceRule.name] ?? [],
452
+ sharedContext,
453
+ });
454
+ _utils_1.eventBuilders.updatedPriceRule({
455
+ data: performedActions.updated[_models_1.PriceRule.name] ?? [],
456
+ sharedContext,
457
+ });
458
+ _utils_1.eventBuilders.deletedPriceRule({
459
+ data: performedActions.deleted[_models_1.PriceRule.name] ?? [],
460
+ sharedContext,
461
+ });
462
+ return entities;
467
463
  }
468
464
  async createPriceLists_(data, sharedContext = {}) {
469
- const ruleTypeAttributes = [];
470
- for (const priceListData of data) {
471
- const { prices = [], rules: priceListRules = {} } = priceListData;
472
- ruleTypeAttributes.push(...Object.keys(priceListRules));
473
- for (const price of prices) {
474
- const { rules: priceListPriceRules = {} } = price;
475
- ruleTypeAttributes.push(...Object.keys(priceListPriceRules));
465
+ const normalized = this.normalizePriceListDate(data);
466
+ const priceListsToCreate = normalized.map((priceListData) => {
467
+ const entry = {
468
+ ...priceListData,
469
+ rules: undefined,
470
+ };
471
+ if (priceListData.prices) {
472
+ entry.prices = this.normalizePrices(priceListData.prices, []);
476
473
  }
477
- }
478
- const ruleTypes = await this.listRuleTypes({ rule_attribute: ruleTypeAttributes }, { take: null }, sharedContext);
479
- const invalidRuleTypes = (0, utils_1.arrayDifference)((0, utils_1.deduplicate)(ruleTypeAttributes), ruleTypes.map((ruleType) => ruleType.rule_attribute));
480
- if (invalidRuleTypes.length) {
481
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Cannot find RuleTypes with rule_attribute - ${invalidRuleTypes.join(", ")}`);
482
- }
483
- const ruleTypeMap = new Map(ruleTypes.map((rt) => [rt.rule_attribute, rt]));
484
- const priceListsToCreate = data.map((priceListData) => {
485
- const id = (0, utils_1.generateEntityId)(priceListData.id, price_list_1.PriceListIdPrefix);
486
- const { prices = [], rules = {}, ...rest } = priceListData;
487
- (0, _utils_1.validatePriceListDates)(priceListData);
488
- const priceListRules = Object.entries(rules).map(([attribute, value]) => {
489
- const ruleType = ruleTypeMap.get(attribute);
490
- return {
491
- price_list_id: id,
492
- rule_type_id: ruleType.id,
493
- price_list_rule_values: value.map((v) => ({ value: v })),
494
- };
495
- });
496
- const pricesData = prices.map((price) => {
497
- const priceRules = Object.entries(price.rules ?? {}).map(([ruleAttribute, ruleValue]) => {
498
- return {
499
- price_set_id: price.price_set_id,
500
- rule_type_id: ruleTypeMap.get(ruleAttribute)?.id,
501
- value: ruleValue,
474
+ if (priceListData.rules) {
475
+ const cleanRules = priceListData.rules
476
+ ? (0, utils_1.removeNullish)(priceListData.rules)
477
+ : {};
478
+ const rules = Object.entries(cleanRules);
479
+ const numberOfRules = rules.length;
480
+ const rulesDataMap = new Map();
481
+ rules.map(([attribute, value]) => {
482
+ const rule = {
483
+ attribute,
484
+ value,
502
485
  };
486
+ rulesDataMap.set(JSON.stringify(rule), rule);
503
487
  });
504
- return {
505
- price_list_id: id,
506
- title: "test",
507
- rules_count: Object.keys(price.rules ?? {}).length,
508
- price_rules: priceRules,
509
- ...price,
510
- };
488
+ entry.price_list_rules = Array.from(rulesDataMap.values());
489
+ entry.rules_count = numberOfRules;
490
+ }
491
+ return entry;
492
+ });
493
+ const priceLists = await this.priceListService_.create(priceListsToCreate, sharedContext);
494
+ /**
495
+ * Preparing data for emitting events
496
+ */
497
+ const eventsData = priceLists.reduce((eventsData, priceList) => {
498
+ eventsData.priceList.push({
499
+ id: priceList.id,
511
500
  });
512
- return {
513
- id,
514
- ...rest,
515
- rules_count: Object.keys(rules).length,
516
- price_list_rules: priceListRules,
517
- prices: pricesData,
518
- };
501
+ priceList.price_list_rules.map((listRule) => {
502
+ eventsData.priceListRules.push({
503
+ id: listRule.id,
504
+ });
505
+ });
506
+ priceList.prices.map((price) => {
507
+ eventsData.prices.push({
508
+ id: price.id,
509
+ });
510
+ price.price_rules.map((priceRule) => {
511
+ eventsData.priceRules.push({
512
+ id: priceRule.id,
513
+ });
514
+ });
515
+ });
516
+ return eventsData;
517
+ }, {
518
+ priceList: [],
519
+ priceListRules: [],
520
+ priceRules: [],
521
+ prices: [],
522
+ });
523
+ /**
524
+ * Emitting events for all created entities
525
+ */
526
+ _utils_1.eventBuilders.createdPriceList({
527
+ data: eventsData.priceList,
528
+ sharedContext,
529
+ });
530
+ _utils_1.eventBuilders.createdPriceListRule({
531
+ data: eventsData.priceListRules,
532
+ sharedContext,
519
533
  });
520
- return await this.priceListService_.create(priceListsToCreate, sharedContext);
534
+ _utils_1.eventBuilders.createdPrice({
535
+ data: eventsData.prices,
536
+ sharedContext,
537
+ });
538
+ _utils_1.eventBuilders.createdPriceRule({
539
+ data: eventsData.priceRules,
540
+ sharedContext,
541
+ });
542
+ return priceLists;
521
543
  }
522
544
  async updatePriceLists_(data, sharedContext = {}) {
523
- const updatedPriceLists = [];
524
- const ruleAttributes = [];
525
- const priceListIds = [];
526
- for (const priceListData of data) {
527
- if (typeof priceListData.rules === "object") {
528
- ruleAttributes.push(...Object.keys(priceListData.rules));
529
- priceListIds.push(priceListData.id);
530
- }
545
+ const existingPriceLists = await this.priceListService_.list({ id: data.map((d) => d.id) }, {}, sharedContext);
546
+ if (existingPriceLists.length !== data.length) {
547
+ const diff = (0, utils_1.arrayDifference)(data.map((d) => d.id), existingPriceLists.map((p) => p.id));
548
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Price lists with ids: '${diff.join(", ")}' not found`);
531
549
  }
532
- const existingPriceLists = await this.listPriceLists({ id: priceListIds }, { relations: ["price_list_rules"] }, sharedContext);
533
- const priceListRuleIds = existingPriceLists
534
- .map((pl) => (pl.price_list_rules || []).map((plr) => plr.id))
535
- .flat();
536
- const existingPriceListRules = await this.listPriceListRules({ id: priceListRuleIds }, {}, sharedContext);
537
- if (existingPriceListRules.length) {
538
- await this.deletePriceListRules(existingPriceListRules.map((plr) => plr.id), sharedContext);
539
- }
540
- const ruleTypes = await this.listRuleTypes({ rule_attribute: ruleAttributes }, { take: null }, sharedContext);
541
- const ruleTypeMap = new Map(ruleTypes.map((rt) => [rt.rule_attribute, rt]));
542
- for (const priceListData of data) {
543
- const { rules, ...priceListOnlyData } = priceListData;
544
- const updatePriceListData = {
545
- ...priceListOnlyData,
550
+ const normalizedData = this.normalizePriceListDate(data).map((priceList) => {
551
+ const entry = {
552
+ ...priceList,
553
+ rules: undefined,
554
+ price_list_rules: undefined,
546
555
  };
547
- (0, _utils_1.validatePriceListDates)(updatePriceListData);
548
- if (typeof rules === "object") {
549
- updatePriceListData.rules_count = Object.keys(rules).length;
550
- }
551
- const [updatedPriceList] = (await this.priceListService_.update([updatePriceListData], sharedContext));
552
- updatedPriceLists.push(updatedPriceList);
553
- for (const [ruleAttribute, ruleValues = []] of Object.entries(rules || {})) {
554
- let ruleType = ruleTypeMap.get(ruleAttribute);
555
- if (!ruleType) {
556
- ;
557
- [ruleType] = await this.createRuleTypes([{ name: ruleAttribute, rule_attribute: ruleAttribute }], sharedContext);
558
- ruleTypeMap.set(ruleAttribute, ruleType);
559
- }
560
- const [priceListRule] = await this.priceListRuleService_.create([
561
- {
562
- price_list_id: updatedPriceList.id,
563
- rule_type_id: ruleType?.id,
564
- },
565
- ], sharedContext);
566
- for (const ruleValue of ruleValues) {
567
- await this.priceListRuleValueService_.create([{ price_list_rule_id: priceListRule.id, value: ruleValue }], sharedContext);
568
- }
556
+ if (typeof priceList.rules === "object") {
557
+ const cleanRules = priceList.rules
558
+ ? (0, utils_1.removeNullish)(priceList.rules)
559
+ : {};
560
+ const rules = Object.entries(cleanRules);
561
+ const numberOfRules = rules.length;
562
+ const rulesDataMap = new Map();
563
+ rules.map(([attribute, value]) => {
564
+ const rule = {
565
+ attribute,
566
+ value,
567
+ };
568
+ rulesDataMap.set(JSON.stringify(rule), rule);
569
+ });
570
+ entry.price_list_rules = Array.from(rulesDataMap.values());
571
+ entry.rules_count = numberOfRules;
569
572
  }
570
- }
571
- return updatedPriceLists;
573
+ return entry;
574
+ });
575
+ const { entities } = await this.priceListService_.upsertWithReplace(normalizedData, {
576
+ relations: ["price_list_rules"],
577
+ });
578
+ return entities;
572
579
  }
573
580
  async updatePriceListPrices_(data, sharedContext = {}) {
574
- const ruleTypeAttributes = [];
575
- const priceListIds = [];
576
- const priceIds = [];
577
- const priceSetIds = data
578
- .map((d) => d.prices.map((price) => price.price_set_id))
581
+ const priceLists = await this.listPriceLists({ id: data.map((p) => p.price_list_id) }, { take: null, relations: ["prices", "prices.price_rules"] }, sharedContext);
582
+ const existingPrices = priceLists
583
+ .map((p) => p.prices ?? [])
584
+ .flat();
585
+ const pricesToUpsert = data
586
+ .map((addPrice) => this.normalizePrices(addPrice.prices, existingPrices, addPrice.price_list_id))
587
+ .filter(Boolean)
579
588
  .flat();
580
- for (const priceListData of data) {
581
- priceListIds.push(priceListData.price_list_id);
582
- for (const price of priceListData.prices) {
583
- priceIds.push(price.id);
584
- ruleTypeAttributes.push(...Object.keys(price.rules || {}));
585
- }
586
- }
587
- const prices = await this.listPrices({ id: priceIds }, { take: null, relations: ["price_rules"] }, sharedContext);
588
- const priceMap = new Map(prices.map((price) => [price.id, price]));
589
- const ruleTypes = await this.listRuleTypes({ rule_attribute: ruleTypeAttributes }, { take: null }, sharedContext);
590
- const ruleTypeMap = new Map(ruleTypes.map((rt) => [rt.rule_attribute, rt]));
591
- const priceSets = await this.list({ id: priceSetIds }, { relations: ["rule_types"] }, sharedContext);
592
- const priceSetRuleTypeMap = priceSets.reduce((acc, curr) => {
593
- const priceSetRuleAttributeSet = acc.get(curr.id) || new Set();
594
- for (const rt of curr.rule_types ?? []) {
595
- priceSetRuleAttributeSet.add(rt.rule_attribute);
596
- }
597
- acc.set(curr.id, priceSetRuleAttributeSet);
598
- return acc;
599
- }, new Map());
600
- const ruleTypeErrors = [];
601
- for (const priceListData of data) {
602
- for (const price of priceListData.prices) {
603
- for (const ruleAttribute of Object.keys(price.rules ?? {})) {
604
- if (!priceSetRuleTypeMap.get(price.price_set_id)?.has(ruleAttribute)) {
605
- ruleTypeErrors.push(`rule_attribute "${ruleAttribute}" in price set ${price.price_set_id}`);
606
- }
607
- }
608
- }
609
- }
610
- if (ruleTypeErrors.length) {
611
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Invalid rule type configuration: Price set rules doesn't exist for ${ruleTypeErrors.join(", ")}`);
612
- }
613
- const priceLists = await this.listPriceLists({ id: priceListIds }, { take: null }, sharedContext);
614
589
  const priceListMap = new Map(priceLists.map((p) => [p.id, p]));
615
- const pricesToUpdate = [];
616
- const priceRuleIdsToDelete = [];
617
- const priceRulesToCreate = [];
618
590
  for (const { price_list_id: priceListId, prices } of data) {
619
591
  const priceList = priceListMap.get(priceListId);
620
592
  if (!priceList) {
621
593
  throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Price list with id: ${priceListId} not found`);
622
594
  }
623
- for (const priceData of prices) {
624
- const { rules = {}, price_set_id, ...rest } = priceData;
625
- const price = priceMap.get(rest.id);
626
- const priceRules = price.price_rules;
627
- priceRulesToCreate.push(...Object.entries(rules).map(([ruleAttribute, ruleValue]) => ({
628
- price_set_id,
629
- rule_type_id: ruleTypeMap.get(ruleAttribute).id,
630
- value: ruleValue,
631
- price_id: price.id,
632
- })));
633
- pricesToUpdate.push({
634
- ...rest,
635
- rules_count: Object.keys(rules).length,
636
- });
637
- priceRuleIdsToDelete.push(...priceRules.map((pr) => pr.id));
638
- }
639
595
  }
640
- const [_deletedPriceRule, _createdPriceRule, updatedPrices] = await (0, utils_1.promiseAll)([
641
- this.priceRuleService_.delete(priceRuleIdsToDelete),
642
- this.priceRuleService_.create(priceRulesToCreate),
643
- this.priceService_.update(pricesToUpdate),
644
- ]);
645
- return updatedPrices;
596
+ const { entities } = await this.priceService_.upsertWithReplace(pricesToUpsert, { relations: ["price_rules"] }, sharedContext);
597
+ return entities;
646
598
  }
647
599
  async removePrices_(ids, sharedContext = {}) {
648
600
  await this.priceService_.delete(ids, sharedContext);
649
601
  }
650
602
  async addPriceListPrices_(data, sharedContext = {}) {
651
- const ruleTypeAttributes = [];
652
- const priceListIds = [];
653
- const priceSetIds = [];
654
- for (const priceListData of data) {
655
- priceListIds.push(priceListData.price_list_id);
656
- for (const price of priceListData.prices) {
657
- ruleTypeAttributes.push(...Object.keys(price.rules || {}));
658
- priceSetIds.push(price.price_set_id);
659
- }
660
- }
661
- const ruleTypes = await this.listRuleTypes({ rule_attribute: ruleTypeAttributes }, { take: null }, sharedContext);
662
- const priceSets = await this.list({ id: priceSetIds }, { relations: ["rule_types"] }, sharedContext);
663
- const priceSetRuleTypeMap = priceSets.reduce((acc, curr) => {
664
- const priceSetRuleAttributeSet = acc.get(curr.id) || new Set();
665
- for (const rt of curr.rule_types ?? []) {
666
- priceSetRuleAttributeSet.add(rt.rule_attribute);
667
- }
668
- acc.set(curr.id, priceSetRuleAttributeSet);
669
- return acc;
670
- }, new Map());
671
- const ruleTypeErrors = [];
672
- for (const priceListData of data) {
673
- for (const price of priceListData.prices) {
674
- for (const rule_attribute of Object.keys(price.rules ?? {})) {
675
- if (!priceSetRuleTypeMap.get(price.price_set_id)?.has(rule_attribute)) {
676
- ruleTypeErrors.push(`rule_attribute "${rule_attribute}" in price set ${price.price_set_id}`);
677
- }
678
- }
679
- }
680
- }
681
- if (ruleTypeErrors.length) {
682
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Invalid rule type configuration: Price set rules doesn't exist for ${ruleTypeErrors.join(", ")}`);
683
- }
684
- const ruleTypeMap = new Map(ruleTypes.map((rt) => [rt.rule_attribute, rt]));
685
- const priceLists = await this.listPriceLists({ id: priceListIds }, {}, sharedContext);
603
+ const priceLists = await this.listPriceLists({ id: data.map((p) => p.price_list_id) }, { take: null, relations: ["prices", "prices.price_rules"] }, sharedContext);
604
+ const existingPrices = priceLists
605
+ .map((p) => p.prices ?? [])
606
+ .flat();
607
+ const pricesToUpsert = data
608
+ .map((addPrice) => this.normalizePrices(addPrice.prices, existingPrices, addPrice.price_list_id))
609
+ .filter(Boolean)
610
+ .flat();
686
611
  const priceListMap = new Map(priceLists.map((p) => [p.id, p]));
687
- const pricesToCreate = [];
688
- for (const { price_list_id: priceListId, prices } of data) {
689
- const priceList = priceListMap.get(priceListId);
612
+ pricesToUpsert.forEach((price) => {
613
+ const priceList = priceListMap.get(price.price_list_id);
690
614
  if (!priceList) {
691
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Price list with id: ${priceListId} not found`);
615
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Price list with id: ${price.price_list_id} not found`);
692
616
  }
693
- const priceListPricesToCreate = prices.map((priceData) => {
694
- const priceRules = priceData.rules || {};
695
- const noOfRules = Object.keys(priceRules).length;
696
- const priceRulesToCreate = Object.entries(priceRules).map(([ruleAttribute, ruleValue]) => {
697
- return {
698
- price_set_id: priceData.price_set_id,
699
- rule_type_id: ruleTypeMap.get(ruleAttribute)?.id,
700
- value: ruleValue,
701
- };
702
- });
703
- return {
704
- ...priceData,
705
- price_set_id: priceData.price_set_id,
706
- title: "test",
707
- price_list_id: priceList.id,
708
- rules_count: noOfRules,
709
- price_rules: priceRulesToCreate,
710
- };
711
- });
712
- pricesToCreate.push(...priceListPricesToCreate);
713
- }
714
- return await this.priceService_.create(pricesToCreate, sharedContext);
617
+ });
618
+ const { entities, performedActions } = await this.priceService_.upsertWithReplace(pricesToUpsert, { relations: ["price_rules"] }, sharedContext);
619
+ _utils_1.eventBuilders.createdPrice({
620
+ data: performedActions.created[_models_1.Price.name] ?? [],
621
+ sharedContext,
622
+ });
623
+ _utils_1.eventBuilders.updatedPrice({
624
+ data: performedActions.updated[_models_1.Price.name] ?? [],
625
+ sharedContext,
626
+ });
627
+ _utils_1.eventBuilders.deletedPrice({
628
+ data: performedActions.deleted[_models_1.Price.name] ?? [],
629
+ sharedContext,
630
+ });
631
+ _utils_1.eventBuilders.createdPriceRule({
632
+ data: performedActions.created[_models_1.PriceRule.name] ?? [],
633
+ sharedContext,
634
+ });
635
+ _utils_1.eventBuilders.updatedPriceRule({
636
+ data: performedActions.updated[_models_1.PriceRule.name] ?? [],
637
+ sharedContext,
638
+ });
639
+ _utils_1.eventBuilders.deletedPriceRule({
640
+ data: performedActions.deleted[_models_1.PriceRule.name] ?? [],
641
+ sharedContext,
642
+ });
643
+ return entities;
715
644
  }
716
645
  async setPriceListRules_(data, sharedContext = {}) {
717
646
  // TODO: re think this method
718
- const priceLists = await this.priceListService_.list({ id: data.map((d) => d.price_list_id) }, { relations: ["price_list_rules", "price_list_rules.rule_type"] }, sharedContext);
719
- const priceListMap = new Map(priceLists.map((p) => [p.id, p]));
720
- const ruleTypes = await this.listRuleTypes({ rule_attribute: data.map((d) => Object.keys(d.rules)).flat() }, { take: null });
721
- const ruleTypeMap = new Map(ruleTypes.map((rt) => [rt.rule_attribute, rt]));
722
- const ruleIdsToUpdate = [];
723
- const rulesToCreate = [];
724
- const priceRuleValues = new Map();
725
- for (const { price_list_id: priceListId, rules } of data) {
726
- const priceList = priceListMap.get(priceListId);
727
- if (!priceList) {
728
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Price list with id: ${priceListId} not found`);
647
+ const priceLists = await this.priceListService_.list({ id: data.map((d) => d.price_list_id) }, {
648
+ relations: ["price_list_rules"],
649
+ }, sharedContext);
650
+ const rulesMap = new Map();
651
+ data.forEach((rule) => {
652
+ if (!rulesMap.has(rule.price_list_id)) {
653
+ rulesMap.set(rule.price_list_id, []);
729
654
  }
730
- const priceListRulesMap = new Map(priceList.price_list_rules.map((p) => [p.rule_type.rule_attribute, p]));
731
- const priceListRuleValues = new Map();
732
- Object.entries(rules).map(async ([key, value]) => {
733
- const ruleType = ruleTypeMap.get(key);
734
- if (!ruleType) {
735
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Rule type with attribute: ${key} not found`);
736
- }
737
- const rule = priceListRulesMap.get(key);
738
- priceListRuleValues.set(ruleType.id, Array.isArray(value) ? value : [value]);
739
- if (!rule) {
740
- rulesToCreate.push({
741
- rule_type_id: ruleType.id,
742
- price_list_id: priceListId,
743
- });
744
- }
745
- else {
746
- ruleIdsToUpdate.push(rule.id);
747
- }
655
+ Object.entries(rule.rules).forEach(([key, value]) => {
656
+ rulesMap.get(rule.price_list_id).push([key, value]);
748
657
  });
749
- priceRuleValues.set(priceListId, priceListRuleValues);
750
- }
751
- const [createdRules, priceListValuesToDelete] = await (0, utils_1.promiseAll)([
752
- this.priceListRuleService_.create(rulesToCreate),
753
- this.priceListRuleValueService_.list({ price_list_rule_id: ruleIdsToUpdate }, { take: null }),
754
- ]);
755
- const priceListRuleValuesToCreate = [];
756
- for (const { id, price_list_id, rule_type_id } of createdRules) {
757
- const ruleValues = priceRuleValues.get(price_list_id);
758
- if (!ruleValues) {
759
- continue;
760
- }
761
- const values = ruleValues.get(rule_type_id);
762
- if (!values) {
763
- continue;
658
+ });
659
+ const priceListsUpsert = priceLists
660
+ .map((priceList) => {
661
+ const allRules = new Map(priceList.price_list_rules
662
+ .toArray()
663
+ .map((r) => [r.attribute, r.value]));
664
+ const rules = rulesMap.get(priceList.id);
665
+ if (!rules?.length) {
666
+ return;
764
667
  }
765
- values.forEach((v) => {
766
- priceListRuleValuesToCreate.push({
767
- price_list_rule_id: id,
768
- value: v,
769
- });
668
+ rules.forEach(([key, value]) => {
669
+ allRules.set(key, value);
770
670
  });
771
- }
772
- await (0, utils_1.promiseAll)([
773
- this.priceListRuleValueService_.delete(priceListValuesToDelete.map((p) => p.id), sharedContext),
774
- this.priceListRuleValueService_.create(priceListRuleValuesToCreate, sharedContext),
775
- ]);
776
- return priceLists;
671
+ return {
672
+ ...priceList,
673
+ rules_count: allRules.size,
674
+ price_list_rules: Array.from(allRules).map(([attribute, value]) => ({
675
+ attribute,
676
+ value,
677
+ })),
678
+ };
679
+ })
680
+ .filter(Boolean);
681
+ const { entities } = await this.priceListService_.upsertWithReplace(priceListsUpsert, { relations: ["price_list_rules"] }, sharedContext);
682
+ return entities;
777
683
  }
778
684
  async removePriceListRules_(data, sharedContext = {}) {
779
- const priceLists = await this.priceListService_.list({ id: data.map((d) => d.price_list_id) }, { relations: ["price_list_rules", "price_list_rules.rule_type"] }, sharedContext);
780
- const priceListMap = new Map(priceLists.map((p) => [p.id, p]));
781
- const idsToDelete = [];
782
- for (const { price_list_id: priceListId, rules } of data) {
783
- const priceList = priceListMap.get(priceListId);
784
- if (!priceList) {
785
- throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Price list with id: ${priceListId} not found`);
685
+ // TODO: re think this method
686
+ const priceLists = await this.priceListService_.list({ id: data.map((d) => d.price_list_id) }, {
687
+ relations: ["price_list_rules"],
688
+ }, sharedContext);
689
+ const rulesMap = new Map();
690
+ data.forEach((rule) => {
691
+ if (!rulesMap.has(rule.price_list_id)) {
692
+ rulesMap.set(rule.price_list_id, []);
786
693
  }
787
- const priceListRulesMap = new Map(priceList.price_list_rules.map((p) => [p.rule_type.rule_attribute, p]));
788
- rules.map(async (rule_attribute) => {
789
- const rule = priceListRulesMap.get(rule_attribute);
790
- if (rule) {
791
- idsToDelete.push(rule.id);
792
- }
694
+ rule.rules.forEach((key) => {
695
+ rulesMap.get(rule.price_list_id).push([key, undefined]);
793
696
  });
794
- }
795
- await this.priceListRuleService_.delete(idsToDelete);
796
- return priceLists;
697
+ });
698
+ const priceListsUpsert = priceLists
699
+ .map((priceList) => {
700
+ const allRules = new Map(priceList.price_list_rules
701
+ .toArray()
702
+ .map((r) => [r.attribute, r.value]));
703
+ const rules = rulesMap.get(priceList.id);
704
+ if (!rules?.length) {
705
+ return;
706
+ }
707
+ rules.forEach(([key, value]) => {
708
+ allRules.set(key, value);
709
+ });
710
+ return {
711
+ ...priceList,
712
+ rules_count: allRules.size,
713
+ price_list_rules: Array.from(allRules)
714
+ .map(([attribute, value]) => ({
715
+ attribute,
716
+ value,
717
+ }))
718
+ .filter((r) => !!r.value),
719
+ };
720
+ })
721
+ .filter(Boolean);
722
+ const { entities } = await this.priceListService_.upsertWithReplace(priceListsUpsert, { relations: ["price_list_rules"] }, sharedContext);
723
+ return entities;
724
+ }
725
+ normalizePriceListDate(data) {
726
+ return data.map((priceListData) => {
727
+ (0, _utils_1.validatePriceListDates)(priceListData);
728
+ if (!!priceListData.starts_at) {
729
+ priceListData.starts_at = (0, utils_1.GetIsoStringFromDate)(priceListData.starts_at);
730
+ }
731
+ if (!!priceListData.ends_at) {
732
+ priceListData.ends_at = (0, utils_1.GetIsoStringFromDate)(priceListData.ends_at);
733
+ }
734
+ return priceListData;
735
+ });
736
+ }
737
+ normalizePriceSetConfig(config) {
738
+ return {
739
+ options: {
740
+ populateWhere: { prices: { price_list_id: null } },
741
+ },
742
+ ...config,
743
+ };
797
744
  }
798
745
  }
799
746
  exports.default = PricingModuleService;
800
747
  __decorate([
801
- (0, utils_1.InjectManager)("baseRepository_"),
748
+ (0, utils_1.InjectManager)("baseRepository_")
749
+ // @ts-expect-error
750
+ ,
751
+ __metadata("design:type", Function),
752
+ __metadata("design:paramtypes", [String, Object, Object]),
753
+ __metadata("design:returntype", Promise)
754
+ ], PricingModuleService.prototype, "retrievePriceSet", null);
755
+ __decorate([
756
+ (0, utils_1.InjectManager)("baseRepository_")
757
+ // @ts-expect-error
758
+ ,
802
759
  __param(2, (0, utils_1.MedusaContext)()),
803
760
  __metadata("design:type", Function),
804
761
  __metadata("design:paramtypes", [Object, Object, Object]),
805
762
  __metadata("design:returntype", Promise)
806
- ], PricingModuleService.prototype, "list", null);
763
+ ], PricingModuleService.prototype, "listPriceSets", null);
807
764
  __decorate([
808
- (0, utils_1.InjectManager)("baseRepository_"),
765
+ (0, utils_1.InjectManager)("baseRepository_")
766
+ // @ts-expect-error
767
+ ,
809
768
  __param(2, (0, utils_1.MedusaContext)()),
810
769
  __metadata("design:type", Function),
811
770
  __metadata("design:paramtypes", [Object, Object, Object]),
812
771
  __metadata("design:returntype", Promise)
813
- ], PricingModuleService.prototype, "listAndCount", null);
772
+ ], PricingModuleService.prototype, "listAndCountPriceSets", null);
814
773
  __decorate([
815
774
  (0, utils_1.InjectManager)("baseRepository_"),
816
775
  __param(2, (0, utils_1.MedusaContext)()),
@@ -820,62 +779,55 @@ __decorate([
820
779
  ], PricingModuleService.prototype, "calculatePrices", null);
821
780
  __decorate([
822
781
  (0, utils_1.InjectManager)("baseRepository_"),
782
+ (0, utils_1.EmitEvents)(),
823
783
  __param(1, (0, utils_1.MedusaContext)()),
824
784
  __metadata("design:type", Function),
825
785
  __metadata("design:paramtypes", [Object, Object]),
826
786
  __metadata("design:returntype", Promise)
827
- ], PricingModuleService.prototype, "create", null);
787
+ ], PricingModuleService.prototype, "createPriceSets", null);
828
788
  __decorate([
829
789
  (0, utils_1.InjectManager)("baseRepository_"),
830
790
  __param(1, (0, utils_1.MedusaContext)()),
831
791
  __metadata("design:type", Function),
832
792
  __metadata("design:paramtypes", [Object, Object]),
833
793
  __metadata("design:returntype", Promise)
834
- ], PricingModuleService.prototype, "upsert", null);
794
+ ], PricingModuleService.prototype, "upsertPriceSets", null);
835
795
  __decorate([
836
796
  (0, utils_1.InjectManager)("baseRepository_"),
837
797
  __param(2, (0, utils_1.MedusaContext)()),
838
798
  __metadata("design:type", Function),
839
799
  __metadata("design:paramtypes", [Object, Object, Object]),
840
800
  __metadata("design:returntype", Promise)
841
- ], PricingModuleService.prototype, "update", null);
801
+ ], PricingModuleService.prototype, "updatePriceSets", null);
842
802
  __decorate([
843
803
  (0, utils_1.InjectTransactionManager)("baseRepository_"),
844
804
  __param(1, (0, utils_1.MedusaContext)()),
845
805
  __metadata("design:type", Function),
846
806
  __metadata("design:paramtypes", [Array, Object]),
847
807
  __metadata("design:returntype", Promise)
848
- ], PricingModuleService.prototype, "update_", null);
849
- __decorate([
850
- (0, utils_1.InjectManager)("baseRepository_"),
851
- __param(1, (0, utils_1.MedusaContext)()),
852
- __metadata("design:type", Function),
853
- __metadata("design:paramtypes", [Object, Object]),
854
- __metadata("design:returntype", Promise)
855
- ], PricingModuleService.prototype, "addRules", null);
808
+ ], PricingModuleService.prototype, "updatePriceSets_", null);
856
809
  __decorate([
857
810
  (0, utils_1.InjectManager)("baseRepository_"),
811
+ (0, utils_1.EmitEvents)(),
858
812
  __param(1, (0, utils_1.MedusaContext)()),
859
813
  __metadata("design:type", Function),
860
814
  __metadata("design:paramtypes", [Object, Object]),
861
815
  __metadata("design:returntype", Promise)
862
816
  ], PricingModuleService.prototype, "addPrices", null);
863
- __decorate([
864
- (0, utils_1.InjectTransactionManager)("baseRepository_"),
865
- __param(1, (0, utils_1.MedusaContext)()),
866
- __metadata("design:type", Function),
867
- __metadata("design:paramtypes", [Array, Object]),
868
- __metadata("design:returntype", Promise)
869
- ], PricingModuleService.prototype, "removeRules", null);
870
817
  __decorate([
871
818
  (0, utils_1.InjectManager)("baseRepository_"),
819
+ (0, utils_1.EmitEvents)()
820
+ // @ts-ignore
821
+ ,
872
822
  __param(1, (0, utils_1.MedusaContext)()),
873
823
  __metadata("design:type", Function),
874
824
  __metadata("design:paramtypes", [Array, Object]),
875
825
  __metadata("design:returntype", Promise)
876
826
  ], PricingModuleService.prototype, "createPriceLists", null);
877
827
  __decorate([
878
- (0, utils_1.InjectTransactionManager)("baseRepository_"),
828
+ (0, utils_1.InjectTransactionManager)("baseRepository_")
829
+ // @ts-ignore
830
+ ,
879
831
  __param(1, (0, utils_1.MedusaContext)()),
880
832
  __metadata("design:type", Function),
881
833
  __metadata("design:paramtypes", [Array, Object]),
@@ -887,70 +839,79 @@ __decorate([
887
839
  __metadata("design:type", Function),
888
840
  __metadata("design:paramtypes", [Array, Object]),
889
841
  __metadata("design:returntype", Promise)
890
- ], PricingModuleService.prototype, "createPriceListRules", null);
842
+ ], PricingModuleService.prototype, "updatePriceListPrices", null);
891
843
  __decorate([
892
- (0, utils_1.InjectTransactionManager)("baseRepository_"),
844
+ (0, utils_1.InjectManager)("baseRepository_"),
893
845
  __param(1, (0, utils_1.MedusaContext)()),
894
846
  __metadata("design:type", Function),
895
847
  __metadata("design:paramtypes", [Array, Object]),
896
848
  __metadata("design:returntype", Promise)
897
- ], PricingModuleService.prototype, "createPriceListRules_", null);
849
+ ], PricingModuleService.prototype, "removePrices", null);
898
850
  __decorate([
899
- (0, utils_1.InjectTransactionManager)("baseRepository_"),
851
+ (0, utils_1.InjectManager)("baseRepository_"),
852
+ (0, utils_1.EmitEvents)(),
900
853
  __param(1, (0, utils_1.MedusaContext)()),
901
854
  __metadata("design:type", Function),
902
855
  __metadata("design:paramtypes", [Array, Object]),
903
856
  __metadata("design:returntype", Promise)
904
- ], PricingModuleService.prototype, "updatePriceListRules", null);
857
+ ], PricingModuleService.prototype, "addPriceListPrices", null);
905
858
  __decorate([
906
859
  (0, utils_1.InjectManager)("baseRepository_"),
907
860
  __param(1, (0, utils_1.MedusaContext)()),
908
861
  __metadata("design:type", Function),
909
- __metadata("design:paramtypes", [Array, Object]),
862
+ __metadata("design:paramtypes", [Object, Object]),
910
863
  __metadata("design:returntype", Promise)
911
- ], PricingModuleService.prototype, "updatePriceListPrices", null);
864
+ ], PricingModuleService.prototype, "setPriceListRules", null);
912
865
  __decorate([
913
866
  (0, utils_1.InjectManager)("baseRepository_"),
914
867
  __param(1, (0, utils_1.MedusaContext)()),
915
868
  __metadata("design:type", Function),
916
- __metadata("design:paramtypes", [Array, Object]),
869
+ __metadata("design:paramtypes", [Object, Object]),
917
870
  __metadata("design:returntype", Promise)
918
- ], PricingModuleService.prototype, "removePrices", null);
871
+ ], PricingModuleService.prototype, "removePriceListRules", null);
919
872
  __decorate([
920
873
  (0, utils_1.InjectManager)("baseRepository_"),
874
+ (0, utils_1.EmitEvents)(),
921
875
  __param(1, (0, utils_1.MedusaContext)()),
922
876
  __metadata("design:type", Function),
923
- __metadata("design:paramtypes", [Array, Object]),
877
+ __metadata("design:paramtypes", [Object, Object]),
924
878
  __metadata("design:returntype", Promise)
925
- ], PricingModuleService.prototype, "addPriceListPrices", null);
879
+ ], PricingModuleService.prototype, "createPricePreferences", null);
926
880
  __decorate([
927
881
  (0, utils_1.InjectManager)("baseRepository_"),
928
882
  __param(1, (0, utils_1.MedusaContext)()),
929
883
  __metadata("design:type", Function),
930
884
  __metadata("design:paramtypes", [Object, Object]),
931
885
  __metadata("design:returntype", Promise)
932
- ], PricingModuleService.prototype, "setPriceListRules", null);
886
+ ], PricingModuleService.prototype, "upsertPricePreferences", null);
933
887
  __decorate([
934
888
  (0, utils_1.InjectManager)("baseRepository_"),
889
+ __param(2, (0, utils_1.MedusaContext)()),
890
+ __metadata("design:type", Function),
891
+ __metadata("design:paramtypes", [Object, Object, Object]),
892
+ __metadata("design:returntype", Promise)
893
+ ], PricingModuleService.prototype, "updatePricePreferences", null);
894
+ __decorate([
895
+ (0, utils_1.InjectTransactionManager)("baseRepository_"),
935
896
  __param(1, (0, utils_1.MedusaContext)()),
936
897
  __metadata("design:type", Function),
937
- __metadata("design:paramtypes", [Object, Object]),
898
+ __metadata("design:paramtypes", [Array, Object]),
938
899
  __metadata("design:returntype", Promise)
939
- ], PricingModuleService.prototype, "removePriceListRules", null);
900
+ ], PricingModuleService.prototype, "createPricePreferences_", null);
940
901
  __decorate([
941
902
  (0, utils_1.InjectTransactionManager)("baseRepository_"),
942
903
  __param(1, (0, utils_1.MedusaContext)()),
943
904
  __metadata("design:type", Function),
944
905
  __metadata("design:paramtypes", [Array, Object]),
945
906
  __metadata("design:returntype", Promise)
946
- ], PricingModuleService.prototype, "create_", null);
907
+ ], PricingModuleService.prototype, "updatePricePreferences_", null);
947
908
  __decorate([
948
909
  (0, utils_1.InjectTransactionManager)("baseRepository_"),
949
910
  __param(1, (0, utils_1.MedusaContext)()),
950
911
  __metadata("design:type", Function),
951
912
  __metadata("design:paramtypes", [Array, Object]),
952
913
  __metadata("design:returntype", Promise)
953
- ], PricingModuleService.prototype, "addRules_", null);
914
+ ], PricingModuleService.prototype, "createPriceSets_", null);
954
915
  __decorate([
955
916
  (0, utils_1.InjectTransactionManager)("baseRepository_"),
956
917
  __param(1, (0, utils_1.MedusaContext)()),
@@ -1002,3 +963,31 @@ __decorate([
1002
963
  __metadata("design:paramtypes", [Array, Object]),
1003
964
  __metadata("design:returntype", Promise)
1004
965
  ], PricingModuleService.prototype, "removePriceListRules_", null);
966
+ const isTaxInclusive = (priceRules, preferences, currencyCode, regionId) => {
967
+ const regionRule = priceRules?.find((rule) => rule.attribute === "region_id" && rule.value === regionId);
968
+ const regionPreference = preferences.find((p) => p.attribute === "region_id" && p.value === regionId);
969
+ const currencyPreference = preferences.find((p) => p.attribute === "currency_code" && p.value === currencyCode);
970
+ if (regionRule && regionPreference) {
971
+ return regionPreference.is_tax_inclusive;
972
+ }
973
+ if (currencyPreference) {
974
+ return currencyPreference.is_tax_inclusive;
975
+ }
976
+ return false;
977
+ };
978
+ const hashPrice = (price) => {
979
+ const data = Object.entries({
980
+ currency_code: price.currency_code,
981
+ price_set_id: "price_set_id" in price ? price.price_set_id ?? null : null,
982
+ price_list_id: "price_list_id" in price ? price.price_list_id ?? null : null,
983
+ min_quantity: price.min_quantity ? price.min_quantity.toString() : null,
984
+ max_quantity: price.max_quantity ? price.max_quantity.toString() : null,
985
+ ...("price_rules" in price
986
+ ? price.price_rules?.reduce((agg, pr) => {
987
+ agg[pr.attribute] = pr.value;
988
+ return agg;
989
+ }, {})
990
+ : {}),
991
+ }).sort(([a], [b]) => a.localeCompare(b));
992
+ return (0, utils_1.simpleHash)(JSON.stringify(data));
993
+ };