@cloudcommerce/app-discounts 0.0.126 → 0.0.127

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
1
 
2
- > @cloudcommerce/app-discounts@0.0.125 build /home/leo/code/ecomplus/cloud-commerce/packages/apps/discounts
2
+ > @cloudcommerce/app-discounts@0.0.126 build /home/leo/code/ecomplus/cloud-commerce/packages/apps/discounts
3
3
  > sh ../../../scripts/build-lib.sh
4
4
 
@@ -32,9 +32,11 @@ export default async ({ params, application }) => {
32
32
  return response;
33
33
  };
34
34
 
35
- const addDiscount = (discount, flag, label) => {
35
+ const addDiscount = (discount, flag, label, maxDiscount) => {
36
36
  let value;
37
- const maxDiscount = params.amount[discount.apply_at || 'total'];
37
+ if (typeof maxDiscount !== 'number') {
38
+ maxDiscount = params.amount[discount.apply_at || 'total'];
39
+ }
38
40
  if (maxDiscount) {
39
41
  // update amount discount and total
40
42
  if (discount.type === 'percentage') {
@@ -82,6 +84,11 @@ export default async ({ params, application }) => {
82
84
  }
83
85
  const kitDiscounts = getValidDiscountRules(config.product_kit_discounts, params, params.items)
84
86
  .sort((a, b) => {
87
+ if (!Array.isArray(a.product_ids) || !a.product_ids.length) {
88
+ if (Array.isArray(b.product_ids) && b.product_ids.length) {
89
+ return 1;
90
+ }
91
+ }
85
92
  if (a.min_quantity > b.min_quantity) {
86
93
  return -1;
87
94
  }
@@ -98,6 +105,8 @@ export default async ({ params, application }) => {
98
105
  });
99
106
  // prevent applying duplicated kit discount for same items
100
107
  let discountedItemIds = [];
108
+ // check buy together recommendations
109
+ const buyTogether = [];
101
110
 
102
111
  kitDiscounts.forEach((kitDiscount, index) => {
103
112
  if (kitDiscount) {
@@ -106,39 +115,101 @@ export default async ({ params, application }) => {
106
115
  : [];
107
116
  let kitItems = productIds.length
108
117
  ? params.items.filter((item) => item.quantity && productIds.indexOf(item.product_id) > -1)
109
- : params.items;
110
- kitItems = kitItems.filter((item) => discountedItemIds.indexOf(item._id) === -1);
118
+ : params.items.filter((item) => item.quantity);
119
+ kitItems = kitItems.filter((item) => discountedItemIds.indexOf(item.product_id) === -1);
120
+ if (!kitItems.length) {
121
+ return;
122
+ }
123
+
124
+ const recommendBuyTogether = () => {
125
+ if (
126
+ params.items.length === 1
127
+ && productIds.length <= 4
128
+ && buyTogether.length < 300
129
+ ) {
130
+ const baseProductId = params.items[0].product_id;
131
+ if (productIds.indexOf(baseProductId) === -1) {
132
+ return;
133
+ }
134
+ const baseItemQuantity = params.items[0].quantity || 1;
135
+ const perItemQuantity = kitDiscount.min_quantity > 2
136
+ ? Math.max(kitDiscount.min_quantity / (productIds.length - 1) - baseItemQuantity, 1)
137
+ : 1;
138
+ const buyTogetherProducts = {};
139
+ productIds.forEach((productId) => {
140
+ if (productId !== baseProductId) {
141
+ buyTogetherProducts[productId] = perItemQuantity;
142
+ }
143
+ });
144
+ if (Object.keys(buyTogetherProducts).length) {
145
+ buyTogether.push({
146
+ products: buyTogetherProducts,
147
+ discount: {
148
+ type: kitDiscount.discount.type,
149
+ value: kitDiscount.discount.value,
150
+ },
151
+ });
152
+ }
153
+ }
154
+ };
155
+
156
+ const discount = { ...kitDiscount.discount };
111
157
  if (kitDiscount.min_quantity > 0) {
112
158
  // check total items quantity
113
- let totalQuantity = 0;
114
- kitItems.forEach(({ quantity }) => {
115
- totalQuantity += quantity;
116
- });
117
- if (totalQuantity < kitDiscount.min_quantity) {
118
- return;
119
- }
120
- if (kitDiscount.discount.type === 'fixed' && kitDiscount.cumulative_discount !== false) {
121
- kitDiscount.discount.value *= Math.floor(totalQuantity / kitDiscount.min_quantity);
159
+ if (kitDiscount.same_product_quantity) {
160
+ kitItems = kitItems.filter((item) => item.quantity >= kitDiscount.min_quantity);
161
+ } else {
162
+ let totalQuantity = 0;
163
+ kitItems.forEach(({ quantity }) => {
164
+ totalQuantity += quantity;
165
+ });
166
+ if (totalQuantity < kitDiscount.min_quantity) {
167
+ if (productIds.length > 1 && kitDiscount.check_all_items !== false) {
168
+ recommendBuyTogether();
169
+ return;
170
+ }
171
+ return;
172
+ }
173
+ if (discount.type === 'fixed' && kitDiscount.cumulative_discount !== false) {
174
+ discount.value *= Math.floor(totalQuantity / kitDiscount.min_quantity);
175
+ }
122
176
  }
123
177
  }
124
178
 
125
- if (!params.amount || !(kitDiscount.discount.min_amount > params.amount.total)) {
179
+ if (!params.amount || !(discount.min_amount > params.amount.total)) {
126
180
  if (kitDiscount.check_all_items !== false) {
127
181
  for (let i = 0; i < productIds.length; i++) {
128
182
  const productId = productIds[i];
129
- if (productId
130
- && !kitItems.find((item) => item.quantity && item.product_id === productId)) {
183
+ if (
184
+ productId
185
+ && !kitItems.find((item) => item.quantity && item.product_id === productId)
186
+ ) {
131
187
  // product not on current cart
188
+ recommendBuyTogether();
132
189
  return;
133
190
  }
134
191
  }
135
192
  }
136
193
  // apply cumulative discount \o/
137
- addDiscount(kitDiscount.discount, `KIT-${(index + 1)}`, kitDiscount.label);
194
+ if (kitDiscount.same_product_quantity) {
195
+ kitItems.forEach((item, i) => {
196
+ addDiscount(
197
+ discount,
198
+ `KIT-${(index + 1)}-${i}`,
199
+ kitDiscount.label,
200
+ ecomUtils.price(item) * (item.quantity || 1),
201
+ );
202
+ });
203
+ } else {
204
+ addDiscount(discount, `KIT-${(index + 1)}`, kitDiscount.label);
205
+ }
138
206
  discountedItemIds = discountedItemIds.concat(kitItems.map((item) => item.product_id));
139
207
  }
140
208
  }
141
209
  });
210
+ if (buyTogether.length) {
211
+ response.buy_together = buyTogether;
212
+ }
142
213
 
143
214
  // gift products (freebies) campaings
144
215
  if (Array.isArray(config.freebies_rules)) {
@@ -162,7 +233,7 @@ export default async ({ params, application }) => {
162
233
  // start calculating discount
163
234
  let value = 0;
164
235
  rule.product_ids.forEach((productId) => {
165
- const item = params.items.find((item) => productId === item.product_id);
236
+ const item = params.items.find((_item) => productId === _item.product_id);
166
237
  if (item) {
167
238
  value += ecomUtils.price(item);
168
239
  }
@@ -302,8 +373,11 @@ export default async ({ params, application }) => {
302
373
  // eslint-disable-next-line no-await-in-loop
303
374
  const { data } = await api.get(`${endpoint}${query}`);
304
375
  countOrders = data.result.length;
305
- } catch (e) {
306
- countOrders = max;
376
+ } catch (err) {
377
+ return {
378
+ error: 'CANT_CHECK_USAGE_LIMITS',
379
+ message: err.message,
380
+ };
307
381
  }
308
382
 
309
383
  if (countOrders >= max) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cloudcommerce/app-discounts",
3
3
  "type": "module",
4
- "version": "0.0.126",
4
+ "version": "0.0.127",
5
5
  "description": "E-Com Plus Cloud Commerce app for complex discount rules",
6
6
  "main": "lib/discounts.js",
7
7
  "repository": {
@@ -16,11 +16,11 @@
16
16
  },
17
17
  "homepage": "https://github.com/ecomplus/cloud-commerce/tree/main/packages/apps/discounts#readme",
18
18
  "dependencies": {
19
- "@cloudcommerce/api": "0.0.126",
20
- "@ecomplus/utils": "^1.4.1"
19
+ "@ecomplus/utils": "1.5.0-rc.3",
20
+ "@cloudcommerce/api": "0.0.127"
21
21
  },
22
22
  "devDependencies": {
23
- "@cloudcommerce/types": "0.0.126"
23
+ "@cloudcommerce/types": "0.0.127"
24
24
  },
25
25
  "scripts": {
26
26
  "build": "sh ../../../scripts/build-lib.sh"