@ordergroove/offers 2.30.2-alpha-PR-715-5.3 → 2.30.3

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.
@@ -114,6 +114,7 @@
114
114
  <option>upsell</option>
115
115
  <option>subscribed</option>
116
116
  <option>not-subscribed</option>
117
+ <option>prepaid</option>
117
118
  </select>
118
119
 
119
120
  <div id="the-offer">
package/examples/index.js CHANGED
@@ -8,24 +8,24 @@ import { getMarkup, getStyles } from '@ordergroove/offers-templates';
8
8
  window.og_settings = {
9
9
  // object were key is product id and value is an array of plan discount
10
10
  product_discounts: {
11
- UD729: {
11
+ UD728: {
12
12
  '3_1': ['30.00', '10%', '$27.00'],
13
13
  '1_2': ['30.00', '20%', '$24.00']
14
14
  },
15
- UD728: [
15
+ UD729: [
16
16
  {
17
- frequency: '1_2',
18
- prepaidShipments: '3',
17
+ frequency: '1_3',
18
+ prepaidShipments: null,
19
19
  regularPrice: '$15.00',
20
20
  subscriptionPrice: '$13.50',
21
21
  discountRate: '10%'
22
22
  },
23
23
  {
24
- frequency: '3_1',
24
+ frequency: '2_3',
25
25
  prepaidShipments: null,
26
26
  regularPrice: '$15.00',
27
- subscriptionPrice: '$12.00',
28
- discountRate: '20%'
27
+ subscriptionPrice: '$13.50',
28
+ discountRate: '10%'
29
29
  }
30
30
  ]
31
31
  }
@@ -179,7 +179,8 @@ const offersExamples = [
179
179
  },
180
180
  {
181
181
  name: 'Prepaid',
182
- selector: 'og-offer[location="initial"]',
182
+ defaultPreviewMode: 'prepaid',
183
+ selector: 'og-offer[location="prepaid-pdp"]',
183
184
  config: {
184
185
  settings: {
185
186
  ...settings,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ordergroove/offers",
3
- "version": "2.30.2-alpha-PR-715-5.3+1cc1ca11",
3
+ "version": "2.30.3",
4
4
  "description": "offer state component",
5
5
  "author": "Eugenio Lattanzio <eugenio63@gmail.com>",
6
6
  "homepage": "https://github.com/ordergroove/plush-toys#readme",
@@ -45,7 +45,7 @@
45
45
  "throttle-debounce": "^2.1.0"
46
46
  },
47
47
  "devDependencies": {
48
- "@ordergroove/offers-templates": "^0.5.1"
48
+ "@ordergroove/offers-templates": "^0.5.2"
49
49
  },
50
- "gitHead": "1cc1ca119c0d7aaaf8552855075f89a62dbd3049"
50
+ "gitHead": "8133777abaeacaf6acdac2bef33ee1b2aa5b72c7"
51
51
  }
@@ -64,6 +64,7 @@ export class Offer extends TemplateElement {
64
64
  if (preview === 'preview-standard-offer') this.preview = 'regular';
65
65
  else if (preview === 'preview-upsell-offer') this.preview = 'upsell';
66
66
  else if (preview === 'preview-subscribed-offer') this.preview = 'subscribed';
67
+ else if (preview === 'preview-prepaid-offer') this.preview = 'prepaid';
67
68
  }
68
69
 
69
70
  static get styles() {
@@ -25,7 +25,7 @@ export class Price extends withProduct(TemplateElement) {
25
25
  const plans = this.productPlans[realProductId] || [];
26
26
 
27
27
  if (this.payAsYouGo) {
28
- const payAsYouGoPlan = plans.find(plan => plan.prepaidShipments === null);
28
+ const payAsYouGoPlan = plans.find(plan => plan.prepaidShipments === null || plan.prepaidShipments === undefined);
29
29
  if (!payAsYouGoPlan) return '';
30
30
  return payAsYouGoPlan.subscriptionPrice;
31
31
  }
@@ -72,6 +72,75 @@ describe('Price', () => {
72
72
  expect(insideText).toBe('10%');
73
73
  });
74
74
 
75
+ it('should render payAsYouGo price with undefined prepaidShipments', async () => {
76
+ const template = html`
77
+ <og-some-price pay-as-you-go product="yum id"> </og-some-price>
78
+ `;
79
+ const priceDivUndefinedPrepaid = await renderPriceTemplate(template, {
80
+ frequency: '1_3',
81
+ productPlans: {
82
+ 'yum id': [
83
+ {
84
+ frequency: '1_3',
85
+ regularPrice: '$1.00',
86
+ discountRate: '10%',
87
+ subscriptionPrice: '$1.00',
88
+ prepaidShipments: 3
89
+ },
90
+ {
91
+ frequency: '1_3',
92
+ regularPrice: '$1.00',
93
+ discountRate: '10%',
94
+ subscriptionPrice: '$2.00'
95
+ },
96
+ {
97
+ frequency: '1_3',
98
+ regularPrice: '$1.00',
99
+ discountRate: '10%',
100
+ subscriptionPrice: '$1.00',
101
+ prepaidShipments: 6
102
+ }
103
+ ]
104
+ }
105
+ });
106
+ });
107
+
108
+ it('should render payAsYouGo price with nullish prepaidShipments', async () => {
109
+ const template = html`
110
+ <og-some-price pay-as-you-go product="yum id"> </og-some-price>
111
+ `;
112
+ const priceDivNullPrepaid = await renderPriceTemplate(template, {
113
+ frequency: '1_3',
114
+ productPlans: {
115
+ 'yum id': [
116
+ {
117
+ frequency: '1_3',
118
+ regularPrice: '$1.00',
119
+ discountRate: '10%',
120
+ subscriptionPrice: '$1.00',
121
+ prepaidShipments: 3
122
+ },
123
+ {
124
+ frequency: '1_3',
125
+ regularPrice: '$1.00',
126
+ discountRate: '10%',
127
+ subscriptionPrice: '$4.50',
128
+ prepaidShipments: null
129
+ },
130
+ {
131
+ frequency: '1_3',
132
+ regularPrice: '$1.00',
133
+ discountRate: '10%',
134
+ subscriptionPrice: '$1.00',
135
+ prepaidShipments: 6
136
+ }
137
+ ]
138
+ }
139
+ });
140
+ const ogPriceNullPrepaid = priceDivNullPrepaid.shadowRoot.innerHTML;
141
+ expect(ogPriceNullPrepaid).toContain('$4.50');
142
+ });
143
+
75
144
  it('should render empty price when subscription is equal to regular', async () => {
76
145
  const template = html`
77
146
  <og-some-price discount product="yum id"> </og-some-price>
@@ -0,0 +1,187 @@
1
+ import { mergeProductPlansToState } from '../actions-preview';
2
+
3
+ describe('actions preview', () => {
4
+ describe('mergeProductPlansToState', () => {
5
+ it('Should merge productPlans to state correctly', () => {
6
+ const payAsYouGoPlan = [
7
+ {
8
+ frequency: '3_1',
9
+ prepaidShipments: null,
10
+ regularPrice: '30.00',
11
+ subscriptionPrice: '$27.00',
12
+ discountRate: '10%'
13
+ },
14
+ {
15
+ frequency: '1_2',
16
+ prepaidShipments: null,
17
+ regularPrice: '30.00',
18
+ subscriptionPrice: '$24.00',
19
+ discountRate: '20%'
20
+ }
21
+ ];
22
+
23
+ const payAsYouGoThat2 = [
24
+ {
25
+ frequency: '1_3',
26
+ prepaidShipments: null,
27
+ regularPrice: '$15.00',
28
+ subscriptionPrice: '$13.50',
29
+ discountRate: '10%'
30
+ },
31
+ {
32
+ frequency: '2_3',
33
+ prepaidShipments: null,
34
+ regularPrice: '$15.00',
35
+ subscriptionPrice: '$13.50',
36
+ discountRate: '10%'
37
+ }
38
+ ];
39
+
40
+ const prepaidPlansToBeAdded = [
41
+ {
42
+ frequency: '1_3',
43
+ regularPrice: '$15.00',
44
+ subscriptionPrice: '$12.00',
45
+ discountRate: '25%',
46
+ prepaidShipments: 3,
47
+ regularPrepaidPrice: '$36.00',
48
+ prepaidSavingsPerShipment: '$3.00',
49
+ prepaidSavingsTotal: '$9.00',
50
+ prepaidExtraSavingsPercentage: '10%'
51
+ },
52
+ {
53
+ frequency: '1_3',
54
+ regularPrice: '$15.00',
55
+ subscriptionPrice: '$12.00',
56
+ discountRate: '20%',
57
+ prepaidShipments: 6,
58
+ regularPrepaidPrice: '$72.00',
59
+ prepaidSavingsPerShipment: '$3.00',
60
+ prepaidSavingsTotal: '$18.00',
61
+ prepaidExtraSavingsPercentage: '10%'
62
+ },
63
+ {
64
+ frequency: '1_3',
65
+ regularPrice: '$15.00',
66
+ subscriptionPrice: '$12.00',
67
+ discountRate: '20%',
68
+ prepaidShipments: 12,
69
+ regularPrepaidPrice: '$144.00',
70
+ prepaidSavingsPerShipment: '$3.00',
71
+ prepaidSavingsTotal: '$36.00',
72
+ prepaidExtraSavingsPercentage: '10%'
73
+ }
74
+ ];
75
+
76
+ const state = {
77
+ UD728: payAsYouGoPlan,
78
+ UD729: payAsYouGoThat2,
79
+ UD730: [
80
+ {
81
+ frequency: '1_2',
82
+ prepaidShipments: null,
83
+ regularPrice: '30.00',
84
+ subscriptionPrice: '$24.00',
85
+ discountRate: '20%'
86
+ }
87
+ ]
88
+ };
89
+
90
+ const repeatedProductPlan = {
91
+ frequency: '3_1',
92
+ prepaidShipments: null,
93
+ regularPrice: '30.00',
94
+ subscriptionPrice: '$27.00',
95
+ discountRate: '10%'
96
+ };
97
+
98
+ const differentProductPlan = {
99
+ frequency: '1_2',
100
+ prepaidShipments: null,
101
+ regularPrice: '30.00',
102
+ subscriptionPrice: '$24.00',
103
+ discountRate: '21%'
104
+ };
105
+
106
+ const productPlans = {
107
+ UD728: [repeatedProductPlan],
108
+ UD729: prepaidPlansToBeAdded,
109
+ UD730: [differentProductPlan]
110
+ };
111
+
112
+ const expected = {
113
+ UD728: [...payAsYouGoPlan],
114
+ UD729: [...payAsYouGoThat2, ...prepaidPlansToBeAdded],
115
+ UD730: [
116
+ {
117
+ frequency: '1_2',
118
+ prepaidShipments: null,
119
+ regularPrice: '30.00',
120
+ subscriptionPrice: '$24.00',
121
+ discountRate: '20%'
122
+ },
123
+ {
124
+ frequency: '1_2',
125
+ prepaidShipments: null,
126
+ regularPrice: '30.00',
127
+ subscriptionPrice: '$24.00',
128
+ discountRate: '21%'
129
+ }
130
+ ]
131
+ };
132
+
133
+ expect(mergeProductPlansToState(state, productPlans)).toEqual(expected);
134
+ });
135
+
136
+ it('Should not add anything if productPlans are equal to state', () => {
137
+ const prepaidPlans = [
138
+ {
139
+ frequency: '1_3',
140
+ regularPrice: '$15.00',
141
+ subscriptionPrice: '$12.00',
142
+ discountRate: '25%',
143
+ prepaidShipments: 3,
144
+ regularPrepaidPrice: '$36.00',
145
+ prepaidSavingsPerShipment: '$3.00',
146
+ prepaidSavingsTotal: '$9.00',
147
+ prepaidExtraSavingsPercentage: '10%'
148
+ },
149
+ {
150
+ frequency: '1_3',
151
+ regularPrice: '$15.00',
152
+ subscriptionPrice: '$12.00',
153
+ discountRate: '20%',
154
+ prepaidShipments: 6,
155
+ regularPrepaidPrice: '$72.00',
156
+ prepaidSavingsPerShipment: '$3.00',
157
+ prepaidSavingsTotal: '$18.00',
158
+ prepaidExtraSavingsPercentage: '10%'
159
+ },
160
+ {
161
+ frequency: '1_3',
162
+ regularPrice: '$15.00',
163
+ subscriptionPrice: '$12.00',
164
+ discountRate: '20%',
165
+ prepaidShipments: 12,
166
+ regularPrepaidPrice: '$144.00',
167
+ prepaidSavingsPerShipment: '$3.00',
168
+ prepaidSavingsTotal: '$36.00',
169
+ prepaidExtraSavingsPercentage: '10%'
170
+ }
171
+ ];
172
+ const state = {
173
+ UD729: prepaidPlans
174
+ };
175
+
176
+ const productPlans = {
177
+ UD729: prepaidPlans
178
+ };
179
+
180
+ const expected = {
181
+ UD729: prepaidPlans
182
+ };
183
+
184
+ expect(mergeProductPlansToState(state, productPlans)).toEqual(expected);
185
+ });
186
+ });
187
+ });
@@ -1,4 +1,5 @@
1
- import { receiveOffer, receiveOrders, authorize, unauthorized, optinProduct, optoutProduct } from './actions';
1
+ import { receiveOffer, receiveOrders, authorize, unauthorized, optinProduct } from './actions';
2
+ import { getObjectStructuredProductPlans } from './adapters';
2
3
  import * as constants from './constants';
3
4
 
4
5
  export const setPreviewStandardOffer = (isPreview, productId, offer) =>
@@ -62,6 +63,19 @@ export const setPreviewStandardOffer = (isPreview, productId, offer) =>
62
63
  );
63
64
  };
64
65
 
66
+ export const mergeProductPlansToState = (state, newProductPlans) => {
67
+ Object.entries(newProductPlans).forEach(([key, value]) => {
68
+ if (Object.prototype.hasOwnProperty.call(state, key)) {
69
+ const mergedArray = state[key].concat(value);
70
+ const uniqueArray = [...new Set(mergedArray.map(item => JSON.stringify(item)))];
71
+ state[key] = uniqueArray.map(item => JSON.parse(item));
72
+ } else {
73
+ state[key] = value;
74
+ }
75
+ });
76
+ return state;
77
+ };
78
+
65
79
  export const setPreviewUpsellOffer = (isPreview, productId, offer) =>
66
80
  async function setPreviewUpsellOfferThunk(dispatch, getState) {
67
81
  await dispatch({ type: constants.SET_PREVIEW_UPSELL_OFFER, payload: isPreview });
@@ -122,6 +136,133 @@ export const setPreviewUpsellOffer = (isPreview, productId, offer) =>
122
136
  }
123
137
  };
124
138
 
139
+ export const setPreviewPrepaid = (isPreview, productId, offer) =>
140
+ async function setPreviewPrepaidThunk(dispatch, getState) {
141
+ const existingProductPlans = getState().productPlans;
142
+
143
+ await dispatch({
144
+ type: constants.SET_PREVIEW_PREPAID_OFFER,
145
+ payload: isPreview
146
+ });
147
+ await dispatch({
148
+ type: constants.UNAUTHORIZED
149
+ });
150
+ await dispatch(
151
+ receiveOffer(
152
+ {
153
+ in_stock: { [productId]: true },
154
+ eligibility_groups: { [productId]: ['subscription', 'upsell', 'prepaid'] },
155
+ result: 'success',
156
+ autoship: { [productId]: true },
157
+ autoship_by_default: { [productId]: false },
158
+ modifiers: {},
159
+ module_view: { regular: '096135e6650111e9a444bc764e106cf4' },
160
+ incentives_display: {
161
+ '47c01e9aacbe40389b5c7325d79091aa': {
162
+ field: 'sub_total',
163
+ object: 'order',
164
+ type: 'Discount Percent',
165
+ value: 5
166
+ },
167
+ e6534b9d877f41e586c37b7d8abc3a58: {
168
+ field: 'total_price',
169
+ object: 'item',
170
+ type: 'Discount Percent',
171
+ value: 10
172
+ },
173
+ f35e842710b24929922db4a529eecd40: {
174
+ field: 'total_price',
175
+ object: 'item',
176
+ type: 'Discount Percent',
177
+ value: 10
178
+ },
179
+ '5be321d7c17f4e18a757212b9a20bfcc': {
180
+ field: 'total_price',
181
+ object: 'item',
182
+ type: 'Discount Percent',
183
+ value: 1
184
+ }
185
+ },
186
+ incentives: {
187
+ [productId]: {
188
+ initial: ['5be321d7c17f4e18a757212b9a20bfcc'],
189
+ ongoing: [
190
+ 'e6534b9d877f41e586c37b7d8abc3a58',
191
+ '47c01e9aacbe40389b5c7325d79091aa',
192
+ 'f35e842710b24929922db4a529eecd40'
193
+ ]
194
+ }
195
+ }
196
+ },
197
+ offer
198
+ )
199
+ );
200
+ await dispatch({
201
+ type: constants.RECEIVE_PRODUCT_PLANS,
202
+ payload: mergeProductPlansToState(
203
+ existingProductPlans,
204
+ getObjectStructuredProductPlans({
205
+ [productId]: [
206
+ {
207
+ frequency: '1_3',
208
+ regularPrice: '$15.00',
209
+ subscriptionPrice: '$12.00',
210
+ discountRate: '25%',
211
+ prepaidShipments: 3,
212
+ regularPrepaidPrice: '$36.00',
213
+ prepaidSavingsPerShipment: '$3.00',
214
+ prepaidSavingsTotal: '$9.00',
215
+ prepaidExtraSavingsPercentage: '10%'
216
+ },
217
+ {
218
+ frequency: '1_3',
219
+ regularPrice: '$15.00',
220
+ subscriptionPrice: '$12.00',
221
+ discountRate: '20%',
222
+ prepaidShipments: 6,
223
+ regularPrepaidPrice: '$72.00',
224
+ prepaidSavingsPerShipment: '$3.00',
225
+ prepaidSavingsTotal: '$18.00',
226
+ prepaidExtraSavingsPercentage: '10%'
227
+ },
228
+ {
229
+ frequency: '1_3',
230
+ regularPrice: '$15.00',
231
+ subscriptionPrice: '$12.00',
232
+ discountRate: '20%',
233
+ prepaidShipments: 12,
234
+ regularPrepaidPrice: '$144.00',
235
+ prepaidSavingsPerShipment: '$3.00',
236
+ prepaidSavingsTotal: '$36.00',
237
+ prepaidExtraSavingsPercentage: '10%'
238
+ }
239
+ ]
240
+ })
241
+ )
242
+ });
243
+ await dispatch({
244
+ type: constants.SET_CONFIG,
245
+ payload: {
246
+ prepaidSellingPlans: {
247
+ [productId]: [
248
+ {
249
+ numberShipments: 3,
250
+ sellingPlan: '1_3'
251
+ },
252
+ {
253
+ numberShipments: 6,
254
+ sellingPlan: '1_3'
255
+ },
256
+ {
257
+ numberShipments: 12,
258
+ sellingPlan: '1_3'
259
+ }
260
+ ]
261
+ }
262
+ }
263
+ });
264
+ };
265
+
125
266
  export const setPreview = (value, oldValue, offer) =>
126
267
  async function(dispatch, getState) {
127
268
  await dispatch({ type: constants.LOCAL_STORAGE_CLEAR });
@@ -145,6 +286,11 @@ export const setPreview = (value, oldValue, offer) =>
145
286
  dispatch(setPreviewStandardOffer(true, offer.product.id, offer));
146
287
  dispatch(optinProduct(offer.product, '2_2'));
147
288
  break;
289
+ case 'prepaid':
290
+ dispatch(setPreviewPrepaid(true, offer.product.id, offer));
291
+ // Prepaid needs to be subscribed to appear
292
+ dispatch(optinProduct(offer.product, '1_3'));
293
+ break;
148
294
  default:
149
295
  }
150
296
  };
@@ -31,6 +31,7 @@ export const SET_LOCALE = 'SET_LOCALE';
31
31
  export const SET_CONFIG = 'SET_CONFIG';
32
32
  export const SET_PREVIEW_STANDARD_OFFER = 'SET_PREVIEW_STANDARD_OFFER';
33
33
  export const SET_PREVIEW_UPSELL_OFFER = 'SET_PREVIEW_UPSELL_OFFER';
34
+ export const SET_PREVIEW_PREPAID_OFFER = 'SET_PREVIEW_PREPAID_OFFER';
34
35
  export const ADD_TEMPLATE = 'ADD_TEMPLATE';
35
36
  export const SET_TEMPLATES = 'SET_TEMPLATES';
36
37
  export const LOCAL_STORAGE_CHANGE = 'LOCAL_STORAGE_CHANGE';
@@ -420,6 +420,15 @@ export const previewUpsellOffer = (state = false, action) => {
420
420
  }
421
421
  };
422
422
 
423
+ export const previewPrepaidOffer = (state = false, action) => {
424
+ switch (action.type) {
425
+ case constants.SET_PREVIEW_PREPAID_OFFER:
426
+ return action.payload;
427
+ default:
428
+ return state;
429
+ }
430
+ };
431
+
423
432
  export const autoshipByDefault = (state = [], action) => {
424
433
  switch (action.type) {
425
434
  case constants.RECEIVE_OFFER:
@@ -236,6 +236,50 @@ describe('Shopify productPlan Reducer', () => {
236
236
 
237
237
  expect(newProductPlan).toEqual(expectedProductPlan);
238
238
  });
239
+
240
+ it('should deal with dividing integers and not add decimals to prices/discounts that are added', () => {
241
+ const allocation = {
242
+ price: 4798,
243
+ compare_at_price: 1999,
244
+ selling_plan: {
245
+ options: [
246
+ {
247
+ name: 'Delivery every',
248
+ position: 1,
249
+ value: 'PREPAID-1 month'
250
+ },
251
+ {
252
+ name: 'Shipment amount',
253
+ position: 2,
254
+ value: '3 shipments'
255
+ }
256
+ ]
257
+ }
258
+ };
259
+
260
+ const productPlan = {
261
+ frequency: '688412852500',
262
+ regularPrice: '19.99',
263
+ subscriptionPrice: '$15.99',
264
+ discountRate: '20%',
265
+ prepaidShipments: 3
266
+ };
267
+
268
+ const expectedProductPlan = {
269
+ frequency: '688412852500',
270
+ regularPrice: '19.99',
271
+ subscriptionPrice: '$15.99',
272
+ discountRate: '20%',
273
+ prepaidShipments: 3,
274
+ regularPrepaidPrice: '$47.98',
275
+ prepaidSavingsPerShipment: '$4.00',
276
+ prepaidSavingsTotal: '$11.99'
277
+ };
278
+
279
+ const newProductPlan = addPrepaidPriceAndSavings(allocation, productPlan);
280
+
281
+ expect(newProductPlan).toEqual(expectedProductPlan);
282
+ });
239
283
  });
240
284
 
241
285
  describe('mapSellingPlanToDiscount', () => {