tango-app-api-payment-subscription 3.0.3 → 3.0.5

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": "tango-app-api-payment-subscription",
3
- "version": "3.0.3",
3
+ "version": "3.0.5",
4
4
  "description": "paymentSubscription",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -14,12 +14,13 @@
14
14
  "license": "ISC",
15
15
  "dependencies": {
16
16
  "aws-sdk": "^2.1572.0",
17
+ "dayjs": "^1.11.10",
17
18
  "dotenv": "^16.4.5",
18
19
  "express": "^4.18.3",
19
20
  "handlebars": "^4.7.8",
20
21
  "mongodb": "^6.4.0",
21
22
  "nodemon": "^3.1.0",
22
- "tango-api-schema": "^2.0.4",
23
+ "tango-api-schema": "^2.0.41",
23
24
  "tango-app-api-middleware": "^1.0.15",
24
25
  "winston": "^3.12.0",
25
26
  "winston-daily-rotate-file": "^5.0.0"
@@ -1,20 +1,20 @@
1
1
  import { logger } from 'tango-app-api-middleware';
2
- import paymentService from '../services/paymentSubscription.services.js';
3
- // import mongoose from 'mongoose';
4
- // const ObjectId = mongoose.Types.ObjectId;
2
+ import * as paymentService from '../services/clientPayment.services.js';
3
+ import * as storeService from '../services/store.service.js';
4
+ import * as basePricingService from '../services/basePrice.service.js';
5
+ import * as clientRequestService from '../services/clientRequest.service.js';
6
+ import mongoose from 'mongoose';
7
+ import dayjs from 'dayjs';
8
+ const ObjectId = mongoose.Types.ObjectId;
5
9
 
6
10
 
7
11
  export const addBilling = async ( req, res ) => {
8
12
  try {
9
- let details = await paymentService.findOne( { _id: req.body.client }, { _id: 1 } );
10
- if ( !details ) {
11
- return res.sendNoContent( 'client Not Found' );
12
- }
13
13
  let params = {
14
14
  'billingDetails.gstNumber': req.body.gstNo,
15
15
  'billingDetails.billingAddress': req.body.billingAddress,
16
16
  };
17
- let result = await paymentService.updateOne( { _id: req.body.client }, params );
17
+ let result = await paymentService.updateOne( { _id: req.body.clientId }, params );
18
18
  if ( result.modifiedCount ) {
19
19
  logger.info( 'Billing Details Added Successfully' );
20
20
  return res.sendSuccess( { message: 'Bank Details Added Successfully' } );
@@ -32,27 +32,41 @@ export const addBilling = async ( req, res ) => {
32
32
 
33
33
  export const billingInfo = async ( req, res, next ) => {
34
34
  try {
35
- let clientInfo;
36
- clientInfo = await paymentService.findOne( { _id: req.params.clientId } );
35
+ let query = [
36
+ {
37
+ $match: {
38
+ _id: new ObjectId( req.params.clientId ),
39
+ status: 'active',
40
+ },
41
+ },
42
+ {
43
+ $project: {
44
+ clientName: 1,
45
+ _id: 1,
46
+ planDetails: 1,
47
+ billingDetails: 1,
48
+ price: 1,
49
+ priceType: 1,
50
+ virtualAccount: 1,
51
+ },
52
+ },
53
+ {
54
+ $project: {
55
+ 'planDetails.product._id': 0,
56
+ },
57
+ },
58
+ ];
59
+ let clientInfo = await paymentService.aggregate( query );
37
60
  if ( !clientInfo ) {
38
61
  return res.sendNoContent( 'Client is not Found' );
39
62
  }
40
- let storeCount = await paymentService.storeCount( { clientId: clientInfo.clientId } );
63
+ let storeCount = await storeService.count( { clientId: clientInfo.clientId } );
41
64
 
42
- let virtualBankInfo = await paymentService.VirtualAccFind( {}, { _id: 0, createdAt: 0, updatedAt: 0 } );
43
- let description;
44
- if ( clientInfo?.planDetails?.subscriptionType && clientInfo?.planDetails?.subscriptionType == 'free' ) {
45
- description = 'You will not be billed during your free subscription. To explore other products, upgrade to a paid subscription.';
46
- } else if ( clientInfo?.planDetails?.subscriptionType && clientInfo.planDetails.subscriptionType == 'premium' ) {
47
- description = 'You will not be billed during your free trial.To keep your dashboard running after the trial end, upgrade to a paid subscription.';
48
- } else if ( clientInfo?.planDetails?.subscriptionType && clientInfo.planDetails.subscriptionType == 'enterprice' ) {
49
- description = 'You will not be billed during your free trial.To keep your dashboard running after the trial end, upgrade to a paid subscription.';
50
- }
51
65
  let data = {
52
- clientDetails: clientInfo,
53
- bankDetails: virtualBankInfo,
54
- storeCount: storeCount,
55
- description: description,
66
+ _id: clientInfo[0]._id,
67
+ currentPlanInfo: { ...clientInfo[0].planDetails, storeCount: storeCount, price: clientInfo[0].price, priceType: clientInfo[0].priceType },
68
+ billingDetails: { ...clientInfo[0].billingDetails, nextBillingDate: '--' },
69
+ BankDetails: clientInfo[0].virtualAccount,
56
70
  };
57
71
 
58
72
  return res.sendSuccess( data );
@@ -65,7 +79,7 @@ export const billingInfo = async ( req, res, next ) => {
65
79
 
66
80
  export const getStoreList = async ( req, res ) => {
67
81
  try {
68
- let storeList = await paymentService.storeFind( { clientId: req.query.clientId, status: 'active' }, { _id: 1, storeId: 1, storeName: 1 } );
82
+ let storeList = await storeService.find( { clientId: req.query.clientId, status: 'active' }, { _id: 1, storeId: 1, storeName: 1 } );
69
83
 
70
84
  if ( !storeList.length ) {
71
85
  return res.sendNoContent( 'No Stores Found' );
@@ -80,7 +94,7 @@ export const getStoreList = async ( req, res ) => {
80
94
 
81
95
  export const getClientList = async ( req, res ) => {
82
96
  try {
83
- let storeList = await paymentService.find( {}, { clientId: 1, _id: 1, clientName: 1 } );
97
+ let storeList = await paymentService.find( { status: 'active' }, { clientId: 1, _id: 1, clientName: 1 } );
84
98
 
85
99
  if ( !storeList.length ) {
86
100
  return res.sendNoContent( 'No Stores Found' );
@@ -114,10 +128,11 @@ export const pricingInfo = async ( req, res ) => {
114
128
  },
115
129
  },
116
130
  ];
117
- let pricingDetails = await paymentService.getprice( query );
131
+ let pricingDetails = await basePricingService.aggregate( query );
118
132
 
119
133
  return res.sendSuccess( { price: pricingDetails } );
120
134
  } catch ( e ) {
135
+ console.log( 'pricingInfo=>', e );
121
136
  logger.error( e );
122
137
  return res.sendError( e, 500 );
123
138
  }
@@ -125,22 +140,28 @@ export const pricingInfo = async ( req, res ) => {
125
140
 
126
141
  export const updateSubscription = async ( req, res ) => {
127
142
  try {
128
- let clientDetails = await paymentService.findOne( { _id: req.params.clientId }, { _id: 1 } );
129
- if ( !clientDetails ) {
130
- return res.sendNoContent( 'No Content' );
131
- }
132
- let features = req.body.clientDetails.planDetails.subscribedFeatures;
133
- for ( const key in features ) {
134
- if ( features[key].active ) {
135
- features[key].status = 'live';
136
- features[key].subscribedDate = new Date();
143
+ let price = req.body.currentPlanInfo.price;
144
+ let priceType = req.body.currentPlanInfo.priceType;
145
+ delete req.body.currentPlanInfo.price;
146
+ delete req.body.currentPlanInfo.priceType;
147
+ delete req.body.currentPlanInfo.storeCount;
148
+ let products = req.body.currentPlanInfo.product;
149
+ products.forEach( ( element, index ) => {
150
+ if ( !element.subscribedDate || element.subscribedDate != null ) {
151
+ req.body.currentPlanInfo.product[index].subscribedDate = new Date();
152
+ req.body.currentPlanInfo.product[index].status = 'live';
153
+ req.body.currentPlanInfo.product[index].trialStartDate = element?.trialStartDate || '';
154
+ req.body.currentPlanInfo.product[index].trialEndDate = element?.trialEndDate || '';
137
155
  }
138
- }
139
- req.body.clientDetails.planDetails.subscribedFeatures = features;
140
- let input = req.body.clientDetails;
156
+ } );
157
+ let details = {
158
+ planDetails: req.body.currentPlanInfo,
159
+ price: price,
160
+ priceType: priceType,
161
+ };
141
162
 
142
- let result = await paymentService.updateOne( { _id: req.params.clientId }, input );
143
- console.log( input );
163
+ let result = await paymentService.updateOne( { _id: req.params.clientId }, details );
164
+ console.log( details );
144
165
 
145
166
  if ( result.modifiedCount ) {
146
167
  return res.sendSuccess( { message: 'Subscription Updated Successfully' } );
@@ -153,3 +174,455 @@ export const updateSubscription = async ( req, res ) => {
153
174
  return res.sendError( e, 500 );
154
175
  }
155
176
  };
177
+
178
+ export const trailProductList = async ( req, res ) => {
179
+ try {
180
+ let date = new Date();
181
+ let getClientInfo = await paymentService.findOne( { '_id': req.query.clientId, 'status': 'active', 'planDetails.product.status': 'trail' }, { 'planDetails.product': 1 } );
182
+
183
+ if ( !getClientInfo ) {
184
+ return res.sendNoContent();
185
+ }
186
+ let products;
187
+ if ( getClientInfo.planDetails.product.length ) {
188
+ products = getClientInfo.planDetails.product.filter( ( item ) => item.trialEndDate >= date ).map( ( item ) => item.productName );
189
+ }
190
+ return res.sendSuccess( products );
191
+ } catch ( e ) {
192
+ console.log( 'trialRequest =>', e );
193
+ logger.error( e );
194
+ return res.sendError( e, 500 );
195
+ }
196
+ };
197
+
198
+ export const unsubscribeProduct = async ( req, res ) => {
199
+ try {
200
+ let checkExistRequest = await clientRequestService.findOne( { client: req.body.clientId, status: 'pending' } );
201
+ if ( checkExistRequest ) {
202
+ return res.sendSuccess( 'Request is Already initiated waiting for admin approval' );
203
+ }
204
+ let params = {
205
+ user: '65e966e12b1991393cf8ce30', // need to login user id here
206
+ client: req.body.client._id,
207
+ clientId: req.body.client.clientId,
208
+ reason: req.body.reason,
209
+ description: req.body.description,
210
+ category: 'Request for unsubscribe',
211
+ status: 'pending',
212
+ };
213
+ await clientRequestService.insert( params );
214
+
215
+ return res.sendSuccess( 'Request Send Successfully' );
216
+ } catch ( e ) {
217
+ console.log( 'unsubscribeProduct =>', e );
218
+ logger.error( e );
219
+ return res.sendError( e, 500 );
220
+ }
221
+ };
222
+
223
+ export const trialExtendRequest = async ( req, res ) => {
224
+ try {
225
+ let checkExistRequest = await clientRequestService.findOne( { client: req.body.clientId, status: 'pending' } );
226
+ if ( checkExistRequest ) {
227
+ return res.sendSuccess( 'Request is Already initiated waiting for admin approval' );
228
+ }
229
+ let params = {
230
+ user: '65e966e12b1991393cf8ce30', // need to login user id here
231
+ client: req.body.client._id,
232
+ clientId: req.body.client.clientId,
233
+ name: req.body.product,
234
+ description: 'Request for extend Trail',
235
+ category: 'TrailExtend',
236
+ status: 'pending',
237
+ };
238
+ await clientRequestService.insert( params );
239
+
240
+ return res.sendSuccess( 'Request Send Successfully' );
241
+ } catch ( e ) {
242
+ console.log( 'trialExtendRequest =>', e );
243
+ logger.error( e );
244
+ return res.sendError( e, 500 );
245
+ }
246
+ };
247
+
248
+
249
+ export const trialRequest = async ( req, res ) => {
250
+ try {
251
+ let checkExistRequest = await clientRequestService.findOne( { client: req.body.clientId, status: 'pending' } );
252
+ if ( checkExistRequest ) {
253
+ return res.sendSuccess( 'Request is Already initiated waiting for admin approval' );
254
+ }
255
+ let params = {
256
+ user: '65e966e12b1991393cf8ce30', // need to login user id here
257
+ client: req.body.client._id,
258
+ clientId: req.body.client.clientId,
259
+ name: req.body.product,
260
+ description: 'Request for Trail',
261
+ category: 'Trail',
262
+ status: 'pending',
263
+ };
264
+ await clientRequestService.insert( params );
265
+
266
+ return res.sendSuccess( 'Request Send Successfully' );
267
+ } catch ( e ) {
268
+ console.log( 'trialExtendRequest =>', e );
269
+ logger.error( e );
270
+ return res.sendError( e, 500 );
271
+ }
272
+ };
273
+
274
+ export const invoiceDetails = async ( req, res ) => {
275
+ try {
276
+ let clientInvoiceDetails = await paymentService.findOne( { _id: req.params.clientId, status: 'active' }, { paymentInvoice: 1 } );
277
+ if ( !clientInvoiceDetails ) {
278
+ return res.sendNoContent( 'No client Found' );
279
+ }
280
+ let data = {
281
+ proRate: clientInvoiceDetails?.paymentInvoice?.proRate || '',
282
+ paymenttype: clientInvoiceDetails?.paymentInvoice?.paymentType || '',
283
+ paymentCycle: clientInvoiceDetails?.paymentInvoice?.paymentCycle || '',
284
+ currencyType: clientInvoiceDetails?.paymentInvoice?.currencyType || '',
285
+ invoiceTo: clientInvoiceDetails?.paymentInvoice?.invoiceTo || [],
286
+ paymentAgreementTo: clientInvoiceDetails?.paymentInvoice?.paymentAgreementTo || [],
287
+ invoiceOn: clientInvoiceDetails?.paymentInvoice?.invoiceOn || '',
288
+ extendPaymentPeriodDays: clientInvoiceDetails?.paymentInvoice?.extendPaymentPeriodDays || '',
289
+ };
290
+ return res.sendSuccess( data );
291
+ } catch ( e ) {
292
+ console.log( 'invoiceDetails =>', e );
293
+ logger.error( e );
294
+ return res.sendError( e, 500 );
295
+ }
296
+ };
297
+
298
+
299
+ export const updateInvoiceDetails = async ( req, res ) => {
300
+ try {
301
+ let clientInvoiceDetails = await paymentService.findOne( { _id: req.params.clientId, status: 'active' }, { paymentInvoice: 1 } );
302
+ if ( !clientInvoiceDetails ) {
303
+ return res.sendNoContent( 'No client Found' );
304
+ }
305
+ let data = req.body;
306
+ clientInvoiceDetails.paymentInvoice.proRate = data.proRate;
307
+ clientInvoiceDetails.paymentInvoice.paymentType = data.paymenttype;
308
+ clientInvoiceDetails.paymentInvoice.paymentCycle = data.paymentCycle;
309
+ clientInvoiceDetails.paymentInvoice.currencyType = data.currencyType;
310
+ clientInvoiceDetails.paymentInvoice.invoiceTo = data.invoiceTo;
311
+ clientInvoiceDetails.paymentInvoice.paymentAgreementTo = data.paymentAgreementTo;
312
+ clientInvoiceDetails.paymentInvoice.invoiceOn = data.invoiceOn;
313
+ clientInvoiceDetails.paymentInvoice.extendPaymentPeriodDays = data.extendPaymentPeriodDays;
314
+ clientInvoiceDetails.save().then( () => {
315
+ return res.sendSuccess( 'Invoice Updated Successfully' );
316
+ } ).catch( ( e ) => {
317
+ return res.sendError( e );
318
+ } );
319
+ } catch ( e ) {
320
+ console.log( 'invoiceDetails =>', e );
321
+ logger.error( e );
322
+ return res.sendError( e, 500 );
323
+ }
324
+ };
325
+
326
+
327
+ export const notificationList = async ( req, res ) => {
328
+ try {
329
+ let query = {};
330
+ query.status = 'pending';
331
+ if ( req?.query?.clientId ) {
332
+ query.client = req?.query?.clientId;
333
+ }
334
+ let notificationList = await clientRequestService.find( query, { createdAt: 0, updatedAt: 0 } );
335
+ if ( !notificationList.length ) {
336
+ return res.sendNoContent( 'no list found' );
337
+ }
338
+ return res.sendSuccess( notificationList );
339
+ } catch ( e ) {
340
+ console.log( 'approvalList =>', e );
341
+ logger.error( e );
342
+ return res.sendError( e, 500 );
343
+ }
344
+ };
345
+
346
+
347
+ export const trialApproval = async ( req, res ) => {
348
+ try {
349
+ let requestData = await clientRequestService.findOne( { _id: req.body.id } );
350
+ if ( !requestData ) {
351
+ return res.sendNoContent();
352
+ }
353
+ requestData.status = 'complete';
354
+ requestData.save().then( async () => {
355
+ if ( req.body.type == 'approve' ) {
356
+ let clientProducts = await paymentService.findOne( { _id: requestData.client, status: 'active' }, { planDetails: 1 } );
357
+ if ( !clientProducts ) {
358
+ return res.sendNoContent( 'No client Found' );
359
+ }
360
+ let productIndex = clientProducts.planDetails.product.findIndex( ( item ) => item.productName == requestData.name );
361
+ if ( productIndex != -1 ) {
362
+ clientProducts.planDetails.product[productIndex].status =
363
+ clientProducts.planDetails.product[productIndex].status = 'trail';
364
+ clientProducts.planDetails.product[productIndex].trialStartDate = new Date();
365
+ clientProducts.planDetails.product[productIndex].trialEndDate = new Date( dayjs().add( 13, 'days' ).format( 'YYYY-MM-DD' ) );
366
+ } else {
367
+ clientProducts.planDetails.product.push( {
368
+ productName: requestData.name,
369
+ status: 'trail',
370
+ trialStartDate: new Date(),
371
+ trialEndDate: new Date( dayjs().add( 13, 'days' ).format( 'YYYY-MM-DD' ) ),
372
+ } );
373
+ }
374
+ clientProducts.save();
375
+ }
376
+ return res.sendSuccess( 'updated Successfully' );
377
+ } );
378
+ } catch ( e ) {
379
+ console.log( 'approvalList =>', e );
380
+ logger.error( e );
381
+ return res.sendError( e, 500 );
382
+ }
383
+ };
384
+
385
+
386
+ export const trialExtendRequestApproval = async ( req, res ) => {
387
+ try {
388
+ let clientDetails = await paymentService.findOne( { _id: req.body.client, status: 'active' }, { planDetails: 1 } );
389
+ if ( !clientDetails ) {
390
+ return res.sendNoContent();
391
+ }
392
+ clientDetails.planDetails.product.forEach( ( item ) => {
393
+ if ( item.productName == req.body.product && item.status == 'trail' ) {
394
+ item.trialEndDate = new Date( dayjs( item.trialEndDate ).add( req.body.days, 'days' ).format( 'YYYY-MM-DD' ) );
395
+ }
396
+ } );
397
+ clientDetails.save().then( async () => {
398
+ let requestData = await clientRequestService.findOne( { client: req.body.client, status: 'pending', name: req.body.product, category: 'TrailExtend' } );
399
+ if ( requestData ) {
400
+ requestData.status = 'complete';
401
+ requestData.save();
402
+ }
403
+ return res.sendSuccess( 'Trial Extended Successfully' );
404
+ } ).catch( ( e ) => {
405
+ return res.sendError( e, 500 );
406
+ } );
407
+ } catch ( e ) {
408
+ console.log( 'trialExtendRequestApproval =>', e );
409
+ logger.error( e );
410
+ return res.sendError( e );
411
+ }
412
+ };
413
+
414
+ export const productSubscribe = async ( req, res ) => {
415
+ try {
416
+ let clientinfo = await paymentService.findOne( { _id: req.body.clientId, status: 'active' }, { planDetails: 1 } );
417
+ if ( !clientinfo ) {
418
+ return res.sendNoContent();
419
+ }
420
+ let productIndex = clientinfo.planDetails.product.findIndex( ( item ) => item.productName == req.body.product );
421
+ if ( productIndex != -1 ) {
422
+ clientinfo.planDetails.product[productIndex].status = 'live',
423
+ clientinfo.planDetails.product[productIndex].subscribedDate = new Date();
424
+ } else {
425
+ clientinfo.planDetails.product.push(
426
+ {
427
+ productName: req.body.product,
428
+ status: 'live',
429
+ subscribedDate: new Date(),
430
+ },
431
+ );
432
+ }
433
+
434
+ clientinfo.save().then( async () => {
435
+ return res.sendSuccess( 'Product Subscribed Successfully' );
436
+ } );
437
+ } catch ( e ) {
438
+ console.log( 'updateProductSubscribe =>', e );
439
+ logger.error( e );
440
+ return res.sendError( e, 500 );
441
+ }
442
+ };
443
+
444
+ export const unsubscribeApproval = async ( req, res ) => {
445
+ try {
446
+ let requestData = await clientRequestService.findOne( { _id: req.body.id, status: 'pending' } );
447
+ if ( !requestData ) {
448
+ return res.sendNoContent();
449
+ }
450
+ requestData.status = 'complete';
451
+ requestData.save().then( async () => {
452
+ if ( req.body.type == 'unsubscribe' ) {
453
+ let clientProducts = await paymentService.findOne( { _id: requestData.client, status: 'active' }, { status: 1 } );
454
+ if ( !clientProducts ) {
455
+ return res.sendNoContent( 'No client Found' );
456
+ }
457
+ clientProducts.status = 'deactive';
458
+ clientProducts.save();
459
+ }
460
+ return res.sendSuccess( 'updated Successfully' );
461
+ } );
462
+ } catch ( e ) {
463
+ console.log( 'subscribeApproval =>', e );
464
+ logger.error( e );
465
+ return res.sendError( e, 500 );
466
+ }
467
+ };
468
+
469
+ export const productViewList = async ( req, res ) => {
470
+ try {
471
+ let query = [
472
+ {
473
+ $match: {
474
+ clientId: req.body.client.clientId,
475
+ status: 'active',
476
+ },
477
+ },
478
+ { $unwind: '$product' },
479
+ {
480
+ $group: {
481
+ '_id': '$product',
482
+ 'count': { $sum: 1 },
483
+ },
484
+ },
485
+ {
486
+ $project: {
487
+ _id: 0,
488
+ product: '$_id',
489
+ storeCount: '$count',
490
+ },
491
+ },
492
+ ];
493
+ let storeProductCount = await storeService.aggregate( query );
494
+ if ( !storeProductCount.length ) {
495
+ return res.sendNoContent();
496
+ }
497
+ let productPrice = await basePricingService.find();
498
+ storeProductCount.forEach( ( item ) => {
499
+ let productBasePrice = productPrice.find( ( product ) => product.product_name == item.product );
500
+ if ( productBasePrice ) {
501
+ item.basePrice = productBasePrice.base_price;
502
+ }
503
+ } );
504
+ return res.sendSuccess( storeProductCount );
505
+ } catch ( e ) {
506
+ console.log( 'productViewList =>', e );
507
+ logger.error( e );
508
+ return res.sendError( e, 500 );
509
+ }
510
+ };
511
+
512
+ export const storeViewList = async ( req, res ) => {
513
+ try {
514
+ let limit = req.body?.limit || 10;
515
+ let offset = req.body.offset || 0;
516
+ let skip = offset * limit;
517
+ let query = [
518
+ {
519
+ $match: {
520
+ clientId: req.body.client.clientId,
521
+ status: 'active',
522
+ },
523
+ },
524
+ ];
525
+
526
+ if ( req.body?.searchValue && req.body.searchValue != '' ) {
527
+ query.push(
528
+ {
529
+ $match: {
530
+ $or: [
531
+ { storeName: { $regex: req.body?.searchValue } },
532
+ { storeId: { $regex: req.body?.searchValue } },
533
+ ],
534
+ },
535
+ },
536
+ );
537
+ }
538
+
539
+ if ( req.body?.product && req.body.product.length ) {
540
+ query.push(
541
+ {
542
+ $match: {
543
+ product: { $in: req.body?.product },
544
+ },
545
+ },
546
+ );
547
+ }
548
+
549
+ if ( req.body?.store && req.body.store.length ) {
550
+ query.push(
551
+ {
552
+ $match: {
553
+ storeName: { $in: req.body?.store },
554
+ },
555
+ },
556
+ );
557
+ }
558
+
559
+ if ( req.body?.location && req.body.location.length ) {
560
+ query.push(
561
+ {
562
+ $match: {
563
+ 'storeProfile.city': req.body.location,
564
+ },
565
+ },
566
+ );
567
+ }
568
+
569
+ if ( req.body?.sortColumn && req.body.sortColumn != '' && req.body.sortBy != '' ) {
570
+ query.push( { $sort: { [req.body.sortColumn]: req.body.sortBy } } );
571
+ }
572
+ let storeCount = await storeService.aggregate( query );
573
+
574
+ query.push( { $skip: skip }, { $limit: limit } );
575
+
576
+ let storeDetails = await storeService.aggregate( query );
577
+
578
+ if ( !storeDetails.length ) {
579
+ return res.sendNoContent();
580
+ }
581
+ let data = {
582
+ count: storeCount.length,
583
+ data: storeDetails,
584
+ };
585
+
586
+ return res.sendSuccess( data );
587
+ } catch ( e ) {
588
+ console.log( 'storeViewList =>', e );
589
+ logger.error( e );
590
+ return res.sendError( e, 500 );
591
+ }
592
+ };
593
+
594
+ export const storeLocationList = async ( req, res ) => {
595
+ try {
596
+ let storeDetails = await storeService.find( { clientId: req.body.client.clientId, status: 'active' }, { 'storeId': 1, 'storeName': 1, 'storeProfile.city': 1 } );
597
+ if ( !storeDetails.length ) {
598
+ return res.sendNoContent();
599
+ }
600
+ let store = storeDetails.map( ( item ) => {
601
+ return { id: item.id, storeId: item.storeId, storeName: item.storeName };
602
+ } );
603
+ let location = storeDetails.filter( ( item ) => item.storeProfile.city != '' && item.storeProfile.city != null && typeof ( item.storeProfile.city ) != undefined ).map( ( item ) => item.storeProfile.city );
604
+ let productDetails = await basePricingService.find( {}, { product_name: 1, _id: 0 } );
605
+ let product = productDetails.map( ( item ) => item.product_name );
606
+ return res.sendSuccess( { store, location, product } );
607
+ } catch ( e ) {
608
+ console.log( 'storeLocationList =>', e );
609
+ logger.error( e );
610
+ return res.sendError( e, 500 );
611
+ }
612
+ };
613
+
614
+
615
+ export const addStoreProduct = async ( req, res ) => {
616
+ try {
617
+ let storeDetails = await storeService.find( { storeName: { $in: req.body.store }, clientId: req.body.client.clientId } );
618
+ if ( !storeDetails.length ) {
619
+ return res.sendNoContent();
620
+ }
621
+ await storeService.updateProduct( { storeName: { $in: req.body.store }, clientId: req.body.client.clientId }, req.body.product );
622
+ return res.sendSuccess( 'product updated Successfully' );
623
+ } catch ( e ) {
624
+ console.log( 'addStoreProduct => ', e );
625
+ logger.error( e );
626
+ return res.sendError( e, 500 );
627
+ }
628
+ };
@@ -2,7 +2,7 @@ import joi from 'joi';
2
2
 
3
3
  export const validateBillingParams = {
4
4
  body: joi.object( {
5
- client: joi.string().required(),
5
+ clientId: joi.string().required(),
6
6
  gstNo: joi.string().required(),
7
7
  billingAddress: joi.string().required(),
8
8
  } ),
@@ -20,9 +20,8 @@ export const validateStoreParams = {
20
20
  } ),
21
21
  };
22
22
 
23
-
24
23
  export const validateProducts = {
25
- post: joi.object( {
24
+ body: joi.object( {
26
25
  camara_per_sqft: joi.string().required(),
27
26
  currency_type: joi.string().required(),
28
27
  plan_name: joi.string().required(),
@@ -30,3 +29,58 @@ export const validateProducts = {
30
29
  stores_count: joi.string().required(),
31
30
  } ),
32
31
  };
32
+
33
+ export const validateunsubscribeParams = {
34
+ body: joi.object( {
35
+ reason: joi.string().required(),
36
+ description: joi.string().required(),
37
+ clientId: joi.string().required(),
38
+ } ),
39
+ };
40
+
41
+ export const validateTrailExtendandSubscibeParams = {
42
+ body: joi.object( {
43
+ product: joi.string().required(),
44
+ clientId: joi.string().required(),
45
+ } ),
46
+ };
47
+
48
+ export const validateTrailandUnsubscribeParams = {
49
+ body: joi.object( {
50
+ id: joi.string().required(),
51
+ type: joi.string().required(),
52
+ } ),
53
+ };
54
+
55
+
56
+ export const validateTrailExtendRequestParams = {
57
+ body: joi.object( {
58
+ client: joi.string().required(),
59
+ days: joi.string().required(),
60
+ product: joi.string().required(),
61
+ } ),
62
+ };
63
+
64
+
65
+ export const validateStoreViewParams = {
66
+ body: joi.object( {
67
+ limit: joi.number().required(),
68
+ offset: joi.number().required(),
69
+ clientId: joi.string().required(),
70
+ sortColumn: joi.string().optional(),
71
+ sortBy: joi.number().optional(),
72
+ searchValue: joi.string().optional(),
73
+ product: joi.array().optional(),
74
+ store: joi.array().optional(),
75
+ location: joi.array().optional(),
76
+ } ),
77
+ };
78
+
79
+ export const validateAddStoreProductParams = {
80
+ body: joi.object( {
81
+ clientId: joi.string().required(),
82
+ store: joi.array().required(),
83
+ product: joi.array().required(),
84
+ } ),
85
+ };
86
+
@@ -1,17 +1,31 @@
1
1
 
2
2
  import express from 'express';
3
- import { addBilling, billingInfo, getStoreList, getClientList, pricingInfo, updateSubscription } from '../controllers/paymentSubscription.controllers.js';
3
+ import * as paymentController from '../controllers/paymentSubscription.controllers.js';
4
4
  import { validate } from 'tango-app-api-middleware';
5
- import { validateBillingParams, validateBrandParams, validateStoreParams, validateProducts } from '../dtos/validation.dtos.js';
6
-
5
+ import * as validationDtos from '../dtos/validation.dtos.js';
6
+ import { validateClient } from '../utils/validations/client.validation.js';
7
7
  export const paymentSubscriptionRouter = express.Router();
8
8
 
9
- paymentSubscriptionRouter.post( '/addBilling', validate( validateBillingParams ), addBilling );
10
- paymentSubscriptionRouter.get( '/clientBillingInfo/:clientId', validate( validateBrandParams ), billingInfo );
11
- paymentSubscriptionRouter.get( '/storeList', validate( validateStoreParams ), getStoreList );
12
- paymentSubscriptionRouter.get( '/clientList', getClientList );
13
- paymentSubscriptionRouter.post( '/basePricing', validate( validateProducts ), pricingInfo );
14
- paymentSubscriptionRouter.put( '/update/subscription/:clientId', validate( validateBrandParams ), updateSubscription );
15
- paymentSubscriptionRouter.put( '/startTrail/', validate( validateBrandParams ), updateSubscription );
9
+ paymentSubscriptionRouter.post( '/addBilling', validate( validationDtos.validateBillingParams ), validateClient, paymentController.addBilling );
10
+ paymentSubscriptionRouter.get( '/clientBillingInfo/:clientId', validate( validationDtos.validateBrandParams ), paymentController.billingInfo );
11
+ paymentSubscriptionRouter.get( '/storeList', validate( validationDtos.validateStoreParams ), paymentController.getStoreList );
12
+ paymentSubscriptionRouter.get( '/clientList', paymentController.getClientList );
13
+ paymentSubscriptionRouter.post( '/basePricing', validate( validationDtos.validateProducts ), paymentController.pricingInfo );
14
+ paymentSubscriptionRouter.put( '/update/subscription/:clientId', validate( validationDtos.validateBrandParams ), validateClient, paymentController.updateSubscription );
15
+ paymentSubscriptionRouter.get( '/getTrailProducts', validate( validationDtos.validateStoreParams ), paymentController.trailProductList );
16
+ paymentSubscriptionRouter.post( '/unsubscribe', validate( validationDtos.validateunsubscribeParams ), validateClient, paymentController.unsubscribeProduct );
17
+ paymentSubscriptionRouter.post( '/trialExtendRequest', validate( validationDtos.validateTrailExtendandSubscibeParams ), validateClient, paymentController.trialExtendRequest );
18
+ paymentSubscriptionRouter.post( '/trialRequest', validate( validationDtos.validateTrailExtendandSubscibeParams ), validateClient, paymentController.trialRequest );
19
+ paymentSubscriptionRouter.get( '/InvoiceDetails/:clientId', validate( validationDtos.validateBrandParams ), paymentController.invoiceDetails );
20
+ paymentSubscriptionRouter.put( '/update/InvoiceDetails/:clientId', validate( validationDtos.validateBrandParams ), paymentController.updateInvoiceDetails );
21
+ paymentSubscriptionRouter.get( '/admin/notificationList', paymentController.notificationList );
22
+ paymentSubscriptionRouter.post( '/admin/trialApproval', validate( validationDtos.validateTrailandUnsubscribeParams ), paymentController.trialApproval );
23
+ paymentSubscriptionRouter.post( '/admin/trialExtendApproval', validate( validationDtos.validateTrailExtendRequestParams ), paymentController.trialExtendRequestApproval );
24
+ paymentSubscriptionRouter.post( '/admin/subscribeproduct', validate( validationDtos.validateTrailExtendandSubscibeParams ), paymentController.productSubscribe );
25
+ paymentSubscriptionRouter.post( '/admin/unsubscribeApproval', validate( validationDtos.validateTrailandUnsubscribeParams ), paymentController.unsubscribeApproval );
26
+ paymentSubscriptionRouter.get( '/admin/getProductViewList', validate( validationDtos.validateStoreParams ), validateClient, paymentController.productViewList );
27
+ paymentSubscriptionRouter.post( '/admin/getstoreViewList', validate( validationDtos.validateStoreViewParams ), validateClient, paymentController.storeViewList );
28
+ paymentSubscriptionRouter.get( '/admin/getStoreLocationList', validate( validationDtos.validateStoreParams ), validateClient, paymentController.storeLocationList );
29
+ paymentSubscriptionRouter.post( '/admin/addStoreProduct', validate( validationDtos.validateAddStoreProductParams ), validateClient, paymentController.addStoreProduct );
16
30
 
17
31
 
@@ -0,0 +1,9 @@
1
+ import model from 'tango-api-schema';
2
+
3
+ export const aggregate = ( query = {} ) => {
4
+ return model.basePricingModel.aggregate( query );
5
+ };
6
+
7
+ export const find = ( query = {}, record = {} ) => {
8
+ return model.basePricingModel.find( query, record );
9
+ };
@@ -0,0 +1,19 @@
1
+ import model from 'tango-api-schema';
2
+
3
+ export const find = ( query = {}, record = {} ) => {
4
+ return model.clientModel.find( query, record );
5
+ };
6
+
7
+ export const findOne = ( query = {}, record = {} ) => {
8
+ return model.clientModel.findOne( query, record ).sort( { updatedAt: -1 } );
9
+ };
10
+
11
+ export const updateOne = ( query = {}, record = {} ) => {
12
+ return model.clientModel.updateOne( query, { $set: record } );
13
+ };
14
+
15
+ export const aggregate = ( query = [] ) => {
16
+ return model.clientModel.aggregate( query );
17
+ };
18
+
19
+
@@ -0,0 +1,18 @@
1
+ import model from 'tango-api-schema';
2
+
3
+
4
+ export const insert = async ( record ) => {
5
+ return await model.clientRequestModel.create( record );
6
+ };
7
+
8
+ export const findOne = async ( query = {}, record = {} ) => {
9
+ return await model.clientRequestModel.findOne( query, record );
10
+ };
11
+
12
+ export const find = async ( query ={}, record={} ) => {
13
+ return await model.clientRequestModel.find( query, record );
14
+ };
15
+
16
+ export const updateone = async ( query = {}, record ={} ) => {
17
+ return await model.clientRequestModel.updateOne( query, { $set: record } );
18
+ };
@@ -0,0 +1,17 @@
1
+ import model from 'tango-api-schema';
2
+
3
+ export const find = ( query = {}, record = {} ) => {
4
+ return model.storeModel.find( query, record );
5
+ };
6
+
7
+ export const count = ( query = {} ) => {
8
+ return model.storeModel.count( query );
9
+ };
10
+
11
+ export const aggregate = ( query = {} ) => {
12
+ return model.storeModel.aggregate( query );
13
+ };
14
+
15
+ export const updateProduct = ( query = {}, record = {} ) => {
16
+ return model.storeModel.updateMany( query, { $push: { product: { $each: record } } } );
17
+ };
@@ -0,0 +1,28 @@
1
+ import * as clientPayment from '../../services/clientPayment.services.js';
2
+
3
+
4
+ export const validateClient = async ( req, res, next ) => {
5
+ try {
6
+ let data;
7
+ if ( req?.body?.clientId ) {
8
+ data = req.body.clientId;
9
+ }
10
+ if ( req?.query?.clientId ) {
11
+ data = req.query.clientId;
12
+ }
13
+ if ( req?.params?.clientId ) {
14
+ data = req.params.clientId;
15
+ }
16
+
17
+ let clientExists = await clientPayment.findOne( { _id: data, status: 'active' }, { _id: 1, clientId: 1 } );
18
+ if ( !clientExists ) {
19
+ return res.sendNoContent();
20
+ }
21
+ req.body.client = clientExists;
22
+ next();
23
+ } catch ( e ) {
24
+ console.log( 'validateClient =>', e );
25
+ logger.error( e );
26
+ res.sendError( e, 500 );
27
+ }
28
+ };
@@ -1,46 +0,0 @@
1
- import model from 'tango-api-schema';
2
-
3
-
4
- const findOne = ( query = {}, record = {} ) => {
5
- return model.clientModel.findOne( query, record ).sort( { updatedAt: -1 } );
6
- };
7
-
8
- const updateOne = ( query = {}, record = {} ) => {
9
- return model.clientModel.updateOne( query, { $set: record } );
10
- };
11
-
12
- const VirtualAccFind = ( query = {}, record ={} ) => {
13
- return model.virtualAccountModel.findOne( query, record );
14
- };
15
-
16
- const storeFind = ( query = {}, record = {} ) => {
17
- return model.storeModel.find( query, record );
18
- };
19
-
20
- const aggregate = ( query = [] ) => {
21
- return model.clientModel.aggregate( query );
22
- };
23
-
24
- const find = ( query = {}, record = {} ) => {
25
- return model.clientModel.find( query, record );
26
- };
27
-
28
- const storeCount = ( query= {} ) => {
29
- return model.storeModel.count( query );
30
- };
31
-
32
- const getprice = ( query= {} ) => {
33
- return model.basePricingModel.aggregate( query );
34
- };
35
-
36
-
37
- export default {
38
- findOne,
39
- updateOne,
40
- VirtualAccFind,
41
- storeFind,
42
- aggregate,
43
- find,
44
- storeCount,
45
- getprice,
46
- };