backend-manager 2.5.74 → 2.5.76

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": "backend-manager",
3
- "version": "2.5.74",
3
+ "version": "2.5.76",
4
4
  "description": "Quick tools for developing Firebase functions",
5
5
  "main": "src/manager/index.js",
6
6
  "bin": {
@@ -16,6 +16,7 @@ SubscriptionResolver.prototype.resolve = function (options) {
16
16
 
17
17
  const resolved = {
18
18
  status: 'cancelled',
19
+ frequency: 'monthly',
19
20
  resource: {
20
21
  id: '',
21
22
  },
@@ -30,20 +31,50 @@ SubscriptionResolver.prototype.resolve = function (options) {
30
31
  timestamp: moment(0),
31
32
  timestampUNIX: moment(0),
32
33
  },
34
+ lastPayment: {
35
+ amount: 0,
36
+ date: {
37
+ timestamp: moment(0),
38
+ timestampUNIX: moment(0),
39
+ }
40
+ },
33
41
  trial: {
34
42
  active: false,
43
+ daysLeft: 0,
35
44
  }
36
45
  }
37
46
 
47
+ // Set
38
48
  const profile = self.profile;
39
49
  const resource = self.resource;
40
50
 
51
+ // Set defaults
52
+ profile.details = profile.details || {};
53
+ profile.details.planFrequency = profile.details.planFrequency || null;
54
+
55
+ // Set
41
56
  options = options || {};
42
57
 
58
+ // Set provider if not set
59
+ if (!profile.processor) {
60
+ if (resource.billing_info) {
61
+ profile.processor = 'paypal';
62
+ } else if (resource.billing_period_unit) {
63
+ profile.processor = 'chargebee';
64
+ } else if (resource.customer) {
65
+ profile.processor = 'stripe';
66
+ } else if (resource.addresses) {
67
+ profile.processor = 'coinbase';
68
+ } else {
69
+ throw new Error('Unable to determine subscription provider');
70
+ }
71
+ }
72
+
73
+ // Log if requested
43
74
  if (options.log) {
44
75
  console.log('profile', profile);
45
76
  console.log('resource', resource);
46
- }
77
+ }
47
78
 
48
79
  // Process differently based on each provider
49
80
  if (profile.processor === 'paypal') {
@@ -75,28 +106,46 @@ SubscriptionResolver.prototype.resolve = function (options) {
75
106
  // Set resource ID
76
107
  resolved.resource.id = resource.id;
77
108
 
109
+ // Set start
110
+ resolved.start.timestamp = moment(
111
+ get(resource, 'start_time', 0)
112
+ )
113
+
114
+ // Set expiration
115
+ resolved.expires.timestamp = moment(
116
+ get(resource, 'billing_info.last_payment.time', 0)
117
+ )
118
+
78
119
  // Get trial
79
- const trialTenure = get(resource, 'billing_info.cycle_executions', []).find((cycle) => cycle.tenure_type === 'TRIAL');
80
- const regularTenure = get(resource, 'billing_info.cycle_executions', []).find((cycle) => cycle.tenure_type === 'REGULAR');
120
+ const trialTenure = get(resource, 'plan.billing_cycles', []).find((cycle) => cycle.tenure_type === 'TRIAL');
121
+ const regularTenure = get(resource, 'plan.billing_cycles', []).find((cycle) => cycle.tenure_type === 'REGULAR');
81
122
 
82
123
  // Resolve trial
83
- if (trialTenure && regularTenure && regularTenure.cycles_completed === 0) {
124
+ if (
125
+ resolved.status === 'active'
126
+ && (trialTenure && regularTenure && regularTenure.total_cycles === 0)
127
+ ) {
84
128
  resolved.trial.active = true;
85
129
 
86
- // Set expiration and start
130
+ // Set expiration
87
131
  resolved.expires.timestamp = moment(
88
132
  get(resource, 'billing_info.next_billing_time', 0)
89
133
  )
90
- } else {
91
- // Set expiration and start
92
- resolved.expires.timestamp = moment(
93
- get(resource, 'billing_info.last_payment.time', 0)
94
- )
95
134
  }
96
135
 
97
- resolved.start.timestamp = moment(
98
- get(resource, 'start_time', 0)
99
- )
136
+ // Resolve frequency
137
+ const unit = regularTenure.frequency.interval_unit;
138
+ if (unit === 'YEAR') {
139
+ resolved.frequency = 'annually';
140
+ } else if (unit === 'MONTH') {
141
+ resolved.frequency = 'monthly';
142
+ } else if (unit === 'WEEK') {
143
+ resolved.frequency = 'weekly';
144
+ } else if (unit === 'DAY') {
145
+ resolved.frequency = 'daily';
146
+ } else {
147
+ throw new Error('Unknown frequency');
148
+ }
100
149
 
101
150
  // Set completed
102
151
  if (resource.plan_id) {
@@ -105,6 +154,12 @@ SubscriptionResolver.prototype.resolve = function (options) {
105
154
  resolved.payment.completed = !['CREATED', 'SAVED', 'APPROVED', 'VOIDED', 'PAYER_ACTION_REQUIRED'].includes(resource.status);
106
155
  }
107
156
 
157
+ // Set last payment
158
+ if (resource.billing_info && resource.billing_info.last_payment) {
159
+ resolved.lastPayment.amount = parseFloat(resource.billing_info.last_payment.amount.value);
160
+ resolved.lastPayment.date.timestamp = moment(resource.billing_info.last_payment.time);
161
+ }
162
+
108
163
  } else if (profile.processor === 'chargebee') {
109
164
  // Set status
110
165
  // subscription: https://apidocs.chargebee.com/docs/api/subscriptions?prod_cat_ver=2#subscription_status
@@ -120,34 +175,55 @@ SubscriptionResolver.prototype.resolve = function (options) {
120
175
  // Set resource ID
121
176
  resolved.resource.id = resource.id;
122
177
 
178
+ // Set start
179
+ resolved.start.timestamp = moment(
180
+ get(resource, 'created_at', 0) * 1000
181
+ )
182
+
183
+ // Set expiration
184
+ resolved.expires.timestamp = moment(
185
+ (
186
+ get(resource, 'current_term_start', 0)
187
+ ) * 1000
188
+ )
189
+
123
190
  // Get trial
124
191
  if (resource.status === 'in_trial') {
125
192
  resolved.trial.active = true;
126
193
 
127
- // Set expiration and start
194
+ // Set expiration
128
195
  resolved.expires.timestamp = moment(
129
196
  (
130
197
  get(resource, 'trial_end', 0)
131
198
  ) * 1000
132
199
  )
133
- } else {
134
- // Set expiration and start
135
- resolved.expires.timestamp = moment(
136
- (
137
- get(resource, 'current_term_start', 0)
138
- ) * 1000
139
- )
140
200
  }
141
201
 
142
- resolved.start.timestamp = moment(
143
- get(resource, 'created_at', 0) * 1000
144
- )
202
+ // Resolve frequency
203
+ const unit = resource.billing_period_unit;
204
+ if (unit === 'year') {
205
+ resolved.frequency = 'annually';
206
+ } else if (unit === 'month') {
207
+ resolved.frequency = 'monthly';
208
+ } else if (unit === 'week') {
209
+ resolved.frequency = 'weekly';
210
+ } else if (unit === 'day') {
211
+ resolved.frequency = 'daily';
212
+ } else {
213
+ throw new Error('Unknown frequency');
214
+ }
145
215
 
146
216
  // Set completed
147
217
  if (true) {
148
218
  resolved.payment.completed = !['future'].includes(resource.status);
149
219
  }
150
220
 
221
+ // Set last payment
222
+ // if (resource.billing_info && resource.billing_info.last_payment) {
223
+ // resolved.lastPayment.amount = parseFloat(resource.billing_info.last_payment.amount.value);
224
+ // resolved.lastPayment.date.timestamp = moment(resource.billing_info.last_payment.time);
225
+ // }
226
+
151
227
  } else if (profile.processor === 'stripe') {
152
228
  // Subscription: https://stripe.com/docs/api/subscriptions/object#subscription_object-status
153
229
  // incomplete, incomplete_expired, trialing, active, past_due, canceled, or unpaid
@@ -157,7 +233,7 @@ SubscriptionResolver.prototype.resolve = function (options) {
157
233
  // Set status
158
234
  if (['trialing', 'active'].includes(resource.status)) {
159
235
  resolved.status = 'active';
160
- } if (['past_due', 'unpaid'].includes(resource.status)) {
236
+ } else if (['past_due', 'unpaid'].includes(resource.status)) {
161
237
  resolved.status = 'suspended';
162
238
  } else {
163
239
  resolved.status = 'cancelled';
@@ -166,26 +242,41 @@ SubscriptionResolver.prototype.resolve = function (options) {
166
242
  // Set resource ID
167
243
  resolved.resource.id = resource.id;
168
244
 
245
+ // Set start
246
+ resolved.start.timestamp = moment(
247
+ get(resource, 'start_date', 0) * 1000
248
+ );
249
+
250
+ // Set expiration
251
+ resolved.expires.timestamp = moment(
252
+ get(resource, 'current_period_start', 0) * 1000
253
+ );
254
+
169
255
  // Get trial
170
256
  if (resource.status === 'trialing') {
171
257
  resolved.trial.active = true;
172
258
 
173
- // Set expiration and start
259
+ // Set expiration
174
260
  resolved.expires.timestamp = moment(
175
261
  (
176
262
  get(resource, 'trial_end', 0)
177
263
  ) * 1000
178
- )
179
- } else {
180
- // Set expiration and start
181
- resolved.expires.timestamp = moment(
182
- get(resource, 'current_period_start', 0) * 1000
183
- );
264
+ )
184
265
  }
185
266
 
186
- resolved.start.timestamp = moment(
187
- get(resource, 'start_date', 0) * 1000
188
- );
267
+ // Resolve frequency @@@
268
+ const unit = resource.plan.interval;
269
+ if (unit === 'year') {
270
+ resolved.frequency = 'annually';
271
+ } else if (unit === 'month') {
272
+ resolved.frequency = 'monthly';
273
+ } else if (unit === 'week') {
274
+ resolved.frequency = 'weekly';
275
+ } else if (unit === 'day') {
276
+ resolved.frequency = 'daily';
277
+ } else {
278
+ throw new Error('Unknown frequency');
279
+ }
189
280
 
190
281
  // Set completed
191
282
  if (resource.object === 'subscription') {
@@ -194,6 +285,14 @@ SubscriptionResolver.prototype.resolve = function (options) {
194
285
  resolved.payment.completed = !['requires_payment_method', 'requires_confirmation', 'requires_action', 'processing', 'requires_capture', 'canceled'].includes(resource.status);
195
286
  }
196
287
 
288
+ // Set last payment
289
+ if (resource.latest_invoice) {
290
+ resolved.lastPayment.amount = resource.latest_invoice.amount_paid / 100;
291
+ resolved.lastPayment.date.timestamp = moment(
292
+ get(resource, 'latest_invoice.created', 0) * 1000
293
+ );
294
+ }
295
+
197
296
  } else if (profile.processor === 'coinbase') {
198
297
  // Set status
199
298
  resolved.status = 'cancelled';
@@ -201,37 +300,64 @@ SubscriptionResolver.prototype.resolve = function (options) {
201
300
  // Set resource ID
202
301
  resolved.resource.id = resource.id;
203
302
 
303
+ // Set start
304
+ resolved.start.timestamp = moment(
305
+ get(resource, 'created_at', 0)
306
+ );
307
+
308
+ // Set expiration
309
+ resolved.expires.timestamp = moment(
310
+ get(resource, 'created_at', 0)
311
+ );
312
+
204
313
  // Get trial
205
314
  if (true) {
206
315
  resolved.trial.active = false;
207
316
  }
208
317
 
209
- // Set expiration and start
210
- resolved.expires.timestamp = moment(
211
- get(resource, 'created_at', 0)
212
- );
213
- resolved.start.timestamp = moment(
214
- get(resource, 'created_at', 0)
215
- );
318
+ // Resolve frequency
319
+ const unit = profile.details.planFrequency;
320
+ if (unit) {
321
+ resolved.frequency = unit;
322
+ } else {
323
+ throw new Error('Unknown frequency');
324
+ }
216
325
 
217
326
  // Set completed
327
+ const lastPayment = resource.payments.find(p => p.status === 'CONFIRMED');
218
328
  if (true) {
219
- resolved.payment.completed = !!resource.payments.find(p => p.status === 'CONFIRMED');
329
+ resolved.payment.completed = !!lastPayment;
220
330
  }
331
+
332
+ // Set last payment
333
+ if (lastPayment) {
334
+ resolved.lastPayment.amount = parseFloat(lastPayment.local.amount);
335
+ resolved.lastPayment.date.timestamp = moment(lastPayment.detected_at);
336
+ }
337
+
338
+ } else {
339
+ throw new Error('Unknown processor');
221
340
  }
222
341
 
223
342
  // Fix expiry by adding time to the date of last payment
224
343
  if (resolved.status === 'active') {
344
+ // Set days left
345
+ if (resolved.trial.active) {
346
+ resolved.trial.daysLeft = resolved.expires.timestamp.diff(moment(), 'days');
347
+ }
348
+
349
+ // Set expiration
225
350
  resolved.expires.timestamp.add(1, 'year').add(30, 'days');
226
351
  } else {
227
352
  // If trial, it's already set to the trial end above
228
353
  if (!resolved.trial.active) {
229
- const freq = profile.details.planFrequency || 'monthly';
230
- if (freq === 'annually') {
354
+ if (resolved.frequency === 'annually') {
231
355
  resolved.expires.timestamp.add(1, 'year');
232
- } else if (freq === 'monthly') {
356
+ } else if (resolved.frequency === 'monthly') {
233
357
  resolved.expires.timestamp.add(1, 'month');
234
- } else if (freq === 'daily') {
358
+ } else if (resolved.frequency === 'weekly') {
359
+ resolved.expires.timestamp.add(1, 'week');
360
+ } else if (resolved.frequency === 'daily') {
235
361
  resolved.expires.timestamp.add(1, 'day');
236
362
  }
237
363
  }
@@ -243,12 +369,20 @@ SubscriptionResolver.prototype.resolve = function (options) {
243
369
  }
244
370
 
245
371
  // Fix timestamps
246
- resolved.expires.timestampUNIX = resolved.expires.timestamp.unix()
247
- resolved.expires.timestamp = resolved.expires.timestamp.toISOString()
372
+ resolved.expires.timestampUNIX = resolved.expires.timestamp.unix();
373
+ resolved.expires.timestamp = resolved.expires.timestamp.toISOString();
248
374
 
249
- resolved.start.timestampUNIX = resolved.start.timestamp.unix()
250
- resolved.start.timestamp = resolved.start.timestamp.toISOString()
375
+ resolved.start.timestampUNIX = resolved.start.timestamp.unix();
376
+ resolved.start.timestamp = resolved.start.timestamp.toISOString();
251
377
 
378
+ // Fix trial days
379
+ resolved.trial.daysLeft = resolved.trial.daysLeft < 0 ? 0 : resolved.trial.daysLeft;
380
+
381
+ // Set last payment
382
+ resolved.lastPayment.date.timestampUNIX = moment(resolved.lastPayment.date.timestamp).unix();
383
+ resolved.lastPayment.date.timestamp = resolved.lastPayment.date.timestamp.toISOString();
384
+
385
+ // Log if needed
252
386
  if (options.log) {
253
387
  console.log('resolved', resolved);
254
388
  }