@ordergroove/offers 2.46.1-alpha-PR-1280-4.55 → 2.47.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ordergroove/offers",
3
- "version": "2.46.1-alpha-PR-1280-4.55+fb9521c5",
3
+ "version": "2.47.0",
4
4
  "description": "offer state component",
5
5
  "author": "Eugenio Lattanzio <eugenio63@gmail.com>",
6
6
  "homepage": "https://github.com/ordergroove/plush-toys#readme",
@@ -49,5 +49,5 @@
49
49
  "@ordergroove/offers-templates": "^0.10.0",
50
50
  "@types/lodash.memoize": "^4.1.9"
51
51
  },
52
- "gitHead": "fb9521c55b1918562fb538d5f658c5ba499ebe67"
52
+ "gitHead": "c7c5252a0135bed54846d70a365af5abc681bbf5"
53
53
  }
@@ -2,6 +2,7 @@ import { LitElement, html } from 'lit-element';
2
2
  import { connect } from '../core/connect';
3
3
  import { withProduct } from '../core/resolveProperties';
4
4
  import { safeProductId } from '../core/utils';
5
+ import { INCENTIVE_STANDARD_TYPES } from '../core/constants';
5
6
 
6
7
  export class DiscountAmount {
7
8
  constructor(value) {
@@ -60,12 +61,12 @@ export const getTransformedDiscounts = discounts => {
60
61
  return discounts.map(discount => discountBuilder(discount)).filter(discount => discount !== undefined);
61
62
  };
62
63
 
63
- export function filterIncentives(incentive) {
64
- if (discountBuilder(incentive).className !== this.incentiveClass) {
64
+ function isMatchingIncentive(incentive, { incentiveValue, incentiveClass }) {
65
+ if (discountBuilder(incentive).className !== incentiveClass) {
65
66
  return false;
66
67
  }
67
68
 
68
- if (this.incentiveValue && this.incentiveValue.toString() !== incentive.value.toString()) {
69
+ if (incentiveValue && incentiveValue.toString() !== incentive.value.toString()) {
69
70
  return false;
70
71
  }
71
72
 
@@ -76,6 +77,8 @@ export function replaceText(acc, curr) {
76
77
  return acc.replace(this.textToReplace, discountBuilder(curr));
77
78
  }
78
79
 
80
+ const preferredIncentiveStandards = [INCENTIVE_STANDARD_TYPES.PSI, INCENTIVE_STANDARD_TYPES.PROGRAM_WIDE];
81
+
79
82
  export class IncentiveText extends withProduct(LitElement) {
80
83
  static get properties() {
81
84
  return {
@@ -96,11 +99,26 @@ export class IncentiveText extends withProduct(LitElement) {
96
99
  const incentiveClass = this.from;
97
100
  const incentiveValue = this.value;
98
101
  const incentiveType = this.initial ? 'initial' : 'ongoing';
99
-
100
- const incentive = (this.incentives[incentiveType] || []).find(
101
- filterIncentives.bind({ incentiveClass, incentiveValue })
102
+ /** @type {import('../core/types/reducer').Incentive[]} */
103
+ const incentivesOfType = this.incentives[incentiveType] || [];
104
+
105
+ // prefer to display PSI or program wide incentives, if available
106
+ // since the incentives response may contain other incentives that do not apply, e.g. prepaid, Nth order, customer group, etc.
107
+ const preferredIncentives = incentivesOfType.filter(
108
+ incentive =>
109
+ // we only have criteria if the incentive is standardized
110
+ incentive.criteria &&
111
+ incentive.criteria.node_type === 'PREMISE' &&
112
+ preferredIncentiveStandards.includes(incentive.criteria.standard)
102
113
  );
103
114
 
115
+ const incentive = [
116
+ // put preferred incentives first, so we return one of those if it matches
117
+ ...preferredIncentives,
118
+ // if no preferred incentives matched, try the rest
119
+ ...incentivesOfType.filter(incentive => !preferredIncentives.includes(incentive))
120
+ ].find(incentive => isMatchingIncentive(incentive, { incentiveClass, incentiveValue }));
121
+
104
122
  return html`
105
123
  ${this.label} ${incentive ? discountBuilder(incentive) : this.renderFallback()}
106
124
  `;
@@ -168,6 +168,78 @@ describe('IncentiveText', () => {
168
168
  await appendToBody(el);
169
169
  expect(el.innerText.trim()).toEqual('6%');
170
170
  });
171
+
172
+ it('prefers PSI and program-wide incentives', async () => {
173
+ const el = new IncentiveText();
174
+ el.from = 'DiscountPercent';
175
+ el.incentives = {
176
+ initial: [],
177
+ ongoing: [
178
+ {
179
+ field: 'total_price',
180
+ object: 'item',
181
+ type: 'Discount Percent',
182
+ value: 10,
183
+ criteria: {
184
+ node_type: 'PREMISE',
185
+ standard: 'CUSTOMER_HAS_PRICE_CODE',
186
+ premise_value: ['test']
187
+ }
188
+ },
189
+ {
190
+ field: 'total_price',
191
+ object: 'item',
192
+ type: 'Discount Percent',
193
+ value: 25,
194
+ criteria: {
195
+ node_type: 'PREMISE',
196
+ standard: 'PROGRAM_WIDE'
197
+ }
198
+ }
199
+ ]
200
+ };
201
+ await appendToBody(el);
202
+ expect(el.innerText.trim()).toEqual('25%');
203
+
204
+ el.incentives.ongoing[1].criteria.standard = 'PSI';
205
+ el.incentives.ongoing[1].value = 33;
206
+ el.requestUpdate();
207
+ await el.updateComplete;
208
+ expect(el.innerText.trim()).toEqual('33%');
209
+ });
210
+
211
+ it('returns other matching incentives if no preferred incentives available', async () => {
212
+ const el = new IncentiveText();
213
+ el.from = 'DiscountPercent';
214
+ el.incentives = {
215
+ initial: [],
216
+ ongoing: [
217
+ {
218
+ field: 'total_price',
219
+ object: 'item',
220
+ type: 'Discount Percent',
221
+ value: 10,
222
+ criteria: {
223
+ node_type: 'PREMISE',
224
+ standard: 'CUSTOMER_HAS_PRICE_CODE',
225
+ premise_value: ['test']
226
+ }
227
+ },
228
+ {
229
+ field: 'total_price',
230
+ object: 'item',
231
+ type: 'Discount Amount',
232
+ value: 25,
233
+ criteria: {
234
+ node_type: 'PREMISE',
235
+ standard: 'PROGRAM_WIDE'
236
+ }
237
+ }
238
+ ]
239
+ };
240
+ await appendToBody(el);
241
+ expect(el.innerText.trim()).toEqual('10%');
242
+ });
171
243
  });
172
244
  });
173
245