tango-app-api-payment-subscription 3.1.12 → 3.1.13
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 +2 -2
- package/src/controllers/billing.controllers.js +241 -1
- package/src/controllers/invoice.controller.js +32 -4
- package/src/controllers/payment.controller.js +18 -0
- package/src/controllers/paymentSubscription.controllers.js +78 -15
- package/src/dtos/validation.dtos.js +23 -0
- package/src/routes/billing.routes.js +14 -2
- package/src/routes/payment.routes.js +11 -0
- package/src/routes/paymentSubscription.routes.js +3 -0
- package/src/services/billing.service.js +4 -0
- package/src/services/paymentAccount.service.js +7 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tango-app-api-payment-subscription",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.13",
|
|
4
4
|
"description": "paymentSubscription",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"nodemon": "^3.1.0",
|
|
27
27
|
"swagger-ui-express": "^5.0.0",
|
|
28
28
|
"tango-api-schema": "^2.0.131",
|
|
29
|
-
"tango-app-api-middleware": "^3.1.
|
|
29
|
+
"tango-app-api-middleware": "^3.1.26",
|
|
30
30
|
"winston": "^3.12.0",
|
|
31
31
|
"winston-daily-rotate-file": "^5.0.0"
|
|
32
32
|
},
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { download, logger } from 'tango-app-api-middleware';
|
|
2
2
|
import { aggregate } from '../services/store.service.js';
|
|
3
|
-
import
|
|
3
|
+
import * as invoice from '../services/invoice.service.js';
|
|
4
|
+
import { aggregatebilling, countDocuments, create, deleteOne, find, findOne, updateMany, updateOne } from '../services/billing.service.js';
|
|
4
5
|
import mongoose from 'mongoose';
|
|
6
|
+
import { findOneAccount } from '../services/paymentAccount.service.js';
|
|
7
|
+
import dayjs from 'dayjs';
|
|
5
8
|
|
|
6
9
|
|
|
7
10
|
export const subscribedStoreList = async ( req, res ) => {
|
|
@@ -308,6 +311,8 @@ export const deleteBillingGroup = async ( req, res ) => {
|
|
|
308
311
|
|
|
309
312
|
export const getBillingGroups = async ( req, res ) => {
|
|
310
313
|
try {
|
|
314
|
+
const allGroups = await countDocuments( { clientId: req.body.clientId } );
|
|
315
|
+
|
|
311
316
|
const matchStage = {
|
|
312
317
|
$match: {
|
|
313
318
|
clientId: req.body.clientId,
|
|
@@ -434,6 +439,7 @@ export const getBillingGroups = async ( req, res ) => {
|
|
|
434
439
|
await download( exportResult, res );
|
|
435
440
|
return;
|
|
436
441
|
}
|
|
442
|
+
groupList[0].pageInfo['total'] = allGroups;
|
|
437
443
|
|
|
438
444
|
return res.sendSuccess( groupList[0] );
|
|
439
445
|
} catch ( error ) {
|
|
@@ -442,4 +448,238 @@ export const getBillingGroups = async ( req, res ) => {
|
|
|
442
448
|
}
|
|
443
449
|
};
|
|
444
450
|
|
|
451
|
+
export const getVirtualAccount = async ( req, res ) => {
|
|
452
|
+
try {
|
|
453
|
+
const account = await findOneAccount( { clientId: req.query.clientId }, { accountNumber: 1, ifsc: 1, branch: 1, paymentType: 1, _id: 0 } );
|
|
454
|
+
|
|
455
|
+
if ( !account ) {
|
|
456
|
+
return res.sendError( 'No data found', 204 );
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
return res.sendSuccess( account );
|
|
460
|
+
} catch ( error ) {
|
|
461
|
+
logger.error( { error: error, function: 'getVirtualAccount' } );
|
|
462
|
+
return res.sendError( error, 500 );
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
export const getInvoices = async ( req, res ) => {
|
|
468
|
+
try {
|
|
469
|
+
const allInvoices = await invoice.count( { clientId: req.body.clientId } );
|
|
470
|
+
|
|
471
|
+
const matchStage = {
|
|
472
|
+
$match: {
|
|
473
|
+
clientId: req.body.clientId,
|
|
474
|
+
},
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
let filterStartDate = '';
|
|
478
|
+
let filterEndDate = '';
|
|
479
|
+
|
|
480
|
+
if ( req.body?.filter && req.body.filter == 'current' ) {
|
|
481
|
+
filterStartDate = new Date( dayjs().startOf( 'month' ).format( 'YYYY-MM-DD' ) );
|
|
482
|
+
filterEndDate = new Date( dayjs().endOf( 'month' ).format( 'YYYY-MM-DD' ) );
|
|
483
|
+
}
|
|
484
|
+
if ( req.body?.filter && req.body.filter == 'prev' ) {
|
|
485
|
+
filterStartDate = new Date( dayjs().subtract( 1, 'month' ).startOf( 'month' ).format( 'YYYY-MM-DD' ) );
|
|
486
|
+
filterEndDate = new Date( dayjs().subtract( 1, 'month' ).endOf( 'month' ).format( 'YYYY-MM-DD' ) );
|
|
487
|
+
}
|
|
488
|
+
if ( req.body?.filter && req.body.filter == 'last' ) {
|
|
489
|
+
filterStartDate = new Date( dayjs().subtract( 2, 'month' ).startOf( 'month' ).format( 'YYYY-MM-DD' ) );
|
|
490
|
+
filterEndDate = new Date( dayjs().endOf( 'month' ).format( 'YYYY-MM-DD' ) );
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if ( req.body?.filter ) {
|
|
494
|
+
matchStage.$match['$and'] = [
|
|
495
|
+
{ billingDate: { $gte: filterStartDate } },
|
|
496
|
+
{ billingDate: { $lte: filterEndDate } },
|
|
497
|
+
];
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
if ( req.body.searchValue ) {
|
|
501
|
+
matchStage.$match.$or = [
|
|
502
|
+
{
|
|
503
|
+
invoice: {
|
|
504
|
+
$regex: req.body.searchValue,
|
|
505
|
+
$options: 'i',
|
|
506
|
+
},
|
|
507
|
+
},
|
|
508
|
+
];
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
const pipeline = [
|
|
513
|
+
matchStage,
|
|
514
|
+
{
|
|
515
|
+
$project: {
|
|
516
|
+
'_id': 1,
|
|
517
|
+
'invoice': 1,
|
|
518
|
+
'billingDate': 1,
|
|
519
|
+
'totalAmount': 1,
|
|
520
|
+
'stores': 1,
|
|
521
|
+
'paymentStatus': 1,
|
|
522
|
+
'paymentTerm': 1,
|
|
523
|
+
'products.productName': 1,
|
|
524
|
+
},
|
|
525
|
+
},
|
|
526
|
+
];
|
|
527
|
+
|
|
528
|
+
if ( req.body?.sortColumn && req.body?.sortBy ) {
|
|
529
|
+
pipeline.push(
|
|
530
|
+
{
|
|
531
|
+
$addFields: {
|
|
532
|
+
sortField: {
|
|
533
|
+
$toLower: `$${req.body.sortColumn}`,
|
|
534
|
+
},
|
|
535
|
+
},
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
$sort: {
|
|
539
|
+
[req.body.sortColumn]: req.body.sortBy,
|
|
540
|
+
},
|
|
541
|
+
},
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
pipeline.push(
|
|
546
|
+
{
|
|
547
|
+
$project: {
|
|
548
|
+
sortField: 0,
|
|
549
|
+
},
|
|
550
|
+
},
|
|
551
|
+
|
|
552
|
+
);
|
|
553
|
+
|
|
554
|
+
const facetStage = {
|
|
555
|
+
$facet: {
|
|
556
|
+
data: [
|
|
557
|
+
{
|
|
558
|
+
$skip: ( ( req.body.offset - 1 ) * req.body.limit ),
|
|
559
|
+
},
|
|
560
|
+
{
|
|
561
|
+
$limit: ( req.body.limit ),
|
|
562
|
+
},
|
|
563
|
+
],
|
|
564
|
+
pageInfo: [
|
|
565
|
+
{
|
|
566
|
+
$count: 'count',
|
|
567
|
+
},
|
|
568
|
+
],
|
|
569
|
+
},
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
if ( req.body?.isExport ) {
|
|
573
|
+
facetStage.$facet.data = [];
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
pipeline.push( facetStage );
|
|
577
|
+
|
|
578
|
+
pipeline.push( {
|
|
579
|
+
$unwind: {
|
|
580
|
+
path: '$pageInfo',
|
|
581
|
+
},
|
|
582
|
+
} );
|
|
583
|
+
|
|
584
|
+
const invoiceList = await invoice.aggregate( pipeline );
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
if ( !invoiceList[0] ) {
|
|
588
|
+
return res.sendError( 'No data found', 204 );
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
function transformData( data ) {
|
|
592
|
+
const result = [];
|
|
593
|
+
const groups = {};
|
|
594
|
+
|
|
595
|
+
data.forEach( ( invoiceData ) => {
|
|
596
|
+
if ( invoiceData.paymentStatus === 'unpaid' ) {
|
|
597
|
+
const currentDate = dayjs();
|
|
598
|
+
const givenDate = dayjs( invoiceData.billingDate );
|
|
599
|
+
const daysDifference = currentDate.diff( givenDate, 'day' );
|
|
600
|
+
if ( daysDifference <= invoiceData.paymentTerm && daysDifference >= 0 ) {
|
|
601
|
+
invoiceData.paymentStatus = 'due';
|
|
602
|
+
} else {
|
|
603
|
+
invoiceData.paymentStatus = 'unpaid';
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
invoiceData.products = invoiceData.products.map( ( product ) => product.productName );
|
|
607
|
+
const tempProduct = new Set();
|
|
608
|
+
invoiceData.products.forEach( ( product ) => {
|
|
609
|
+
tempProduct.add( product );
|
|
610
|
+
} );
|
|
611
|
+
invoiceData.products = Array.from( tempProduct );
|
|
612
|
+
|
|
613
|
+
const billingDate = invoiceData.billingDate;
|
|
614
|
+
|
|
615
|
+
if ( !groups[billingDate] ) {
|
|
616
|
+
groups[billingDate] = {
|
|
617
|
+
summary: `Summary - ${dayjs( billingDate ).format( 'MMM YYYY' )}`,
|
|
618
|
+
products: new Set(),
|
|
619
|
+
stores: 0,
|
|
620
|
+
totalAmount: 0,
|
|
621
|
+
billingDate: billingDate,
|
|
622
|
+
invoices: [],
|
|
623
|
+
paymentStatus: invoiceData.paymentStatus,
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
groups[billingDate].invoices.push( invoiceData );
|
|
628
|
+
groups[billingDate].stores += invoiceData.stores;
|
|
629
|
+
groups[billingDate].totalAmount += invoiceData.totalAmount;
|
|
630
|
+
|
|
631
|
+
if ( invoiceData.paymentStatus === 'unpaid' ) {
|
|
632
|
+
const currentDate = dayjs();
|
|
633
|
+
const givenDate = dayjs( invoiceData.billingDate );
|
|
634
|
+
const daysDifference = currentDate.diff( givenDate, 'day' );
|
|
635
|
+
if ( daysDifference <= invoiceData.paymentTerm && daysDifference >= 0 ) {
|
|
636
|
+
groups[billingDate].paymentStatus = 'due';
|
|
637
|
+
} else {
|
|
638
|
+
groups[billingDate].paymentStatus = 'unpaid';
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
invoiceData.products.forEach( ( product ) => {
|
|
643
|
+
groups[billingDate].products.add( product );
|
|
644
|
+
} );
|
|
645
|
+
} );
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
// eslint-disable-next-line guard-for-in
|
|
649
|
+
for ( const billingDate in groups ) {
|
|
650
|
+
const group = groups[billingDate];
|
|
651
|
+
group.products = Array.from( group.products );
|
|
652
|
+
result.push( group );
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
return result;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
invoiceList[0].data = transformData( invoiceList[0].data );
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
if ( req.body.isExport ) {
|
|
662
|
+
const exportResult = [];
|
|
663
|
+
for ( let invoice of invoiceList[0].data ) {
|
|
664
|
+
exportResult.push( {
|
|
665
|
+
'Invoice': invoice.invoice||'',
|
|
666
|
+
'Billing date': invoice.billingDate||'',
|
|
667
|
+
'Total amount': invoice.totalAmount||'',
|
|
668
|
+
'Store count': invoice.stores || '',
|
|
669
|
+
'Status': invoice.paymentStatus||'',
|
|
670
|
+
'Products': invoice.products.length ? invoice.products.join( ', ' ) : '',
|
|
671
|
+
} );
|
|
672
|
+
}
|
|
673
|
+
await download( exportResult, res );
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
invoiceList[0].pageInfo['total'] = allInvoices;
|
|
677
|
+
|
|
678
|
+
return res.sendSuccess( invoiceList[0] );
|
|
679
|
+
} catch ( error ) {
|
|
680
|
+
logger.error( { error: error, function: 'subscribedStoreList' } );
|
|
681
|
+
return res.sendError( error, 500 );
|
|
682
|
+
}
|
|
683
|
+
};
|
|
684
|
+
|
|
445
685
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { aggregatebilling } from '../services/billing.service.js';
|
|
2
1
|
import * as invoiceService from '../services/invoice.service.js';
|
|
3
2
|
import * as dailyPricingService from '../services/dailyPrice.service.js';
|
|
4
3
|
import * as clientService from '../services/clientPayment.services.js';
|
|
5
|
-
|
|
4
|
+
import * as billingService from '../services/billing.service.js';
|
|
6
5
|
import dayjs from 'dayjs';
|
|
7
6
|
|
|
8
7
|
|
|
@@ -14,7 +13,7 @@ import htmlpdf from 'html-pdf-node';
|
|
|
14
13
|
export async function createInvoice( req, res ) {
|
|
15
14
|
try {
|
|
16
15
|
for ( let client of req.body.clientList ) {
|
|
17
|
-
let invoiceGroup = await aggregatebilling( [
|
|
16
|
+
let invoiceGroup = await billingService.aggregatebilling( [
|
|
18
17
|
{
|
|
19
18
|
$match: {
|
|
20
19
|
clientId: client,
|
|
@@ -32,7 +31,6 @@ export async function createInvoice( req, res ) {
|
|
|
32
31
|
|
|
33
32
|
let address = group.addressLineOne + group.addressLineTwo + group.city + ',' + group.state + ',' + group.country + ' -' + group.pinCode;
|
|
34
33
|
|
|
35
|
-
|
|
36
34
|
const currentMonthDays = dayjs().daysInMonth();
|
|
37
35
|
let products = await dailyPricingService.aggregate( [
|
|
38
36
|
{
|
|
@@ -44,6 +42,17 @@ export async function createInvoice( req, res ) {
|
|
|
44
42
|
$sort: { dateISO: -1 },
|
|
45
43
|
},
|
|
46
44
|
{ $limit: 1 },
|
|
45
|
+
{
|
|
46
|
+
$project: {
|
|
47
|
+
stores: {
|
|
48
|
+
$filter: {
|
|
49
|
+
input: '$stores',
|
|
50
|
+
as: 'item',
|
|
51
|
+
cond: { $in: [ '$$item.storeId', group.stores ] },
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
47
56
|
{
|
|
48
57
|
$unwind: {
|
|
49
58
|
path: '$stores',
|
|
@@ -63,6 +72,11 @@ export async function createInvoice( req, res ) {
|
|
|
63
72
|
workingDays: '$stores.products.workingdays',
|
|
64
73
|
},
|
|
65
74
|
},
|
|
75
|
+
{
|
|
76
|
+
$match: {
|
|
77
|
+
workingDays: { $gt: 0 },
|
|
78
|
+
},
|
|
79
|
+
},
|
|
66
80
|
{
|
|
67
81
|
$group: {
|
|
68
82
|
_id: {
|
|
@@ -244,6 +258,8 @@ export async function createInvoice( req, res ) {
|
|
|
244
258
|
);
|
|
245
259
|
}
|
|
246
260
|
let data = {
|
|
261
|
+
groupName: group.groupName,
|
|
262
|
+
groupId: group._id,
|
|
247
263
|
invoice: `INV-${Finacialyear}-${invoiceNo}`,
|
|
248
264
|
products: products,
|
|
249
265
|
status: 'pending',
|
|
@@ -332,6 +348,7 @@ export async function invoiceDownload( req, res ) {
|
|
|
332
348
|
dueDate,
|
|
333
349
|
};
|
|
334
350
|
const currentMonthDays = dayjs().daysInMonth();
|
|
351
|
+
let getgroup = await billingService.findOne( { _id: invoiceInfo.groupId } );
|
|
335
352
|
let annuxureData = await dailyPricingService.aggregate( [
|
|
336
353
|
{
|
|
337
354
|
$match: {
|
|
@@ -342,6 +359,17 @@ export async function invoiceDownload( req, res ) {
|
|
|
342
359
|
$sort: { dateISO: -1 },
|
|
343
360
|
},
|
|
344
361
|
{ $limit: 1 },
|
|
362
|
+
{
|
|
363
|
+
$project: {
|
|
364
|
+
stores: {
|
|
365
|
+
$filter: {
|
|
366
|
+
input: '$stores',
|
|
367
|
+
as: 'item',
|
|
368
|
+
cond: { $in: [ '$$item.storeId', getgroup.stores ] },
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
},
|
|
345
373
|
{
|
|
346
374
|
$unwind: {
|
|
347
375
|
path: '$stores',
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
import { createOrder } from 'tango-app-api-middleware';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export const generateOrder = async ( req, res ) => {
|
|
6
|
+
try {
|
|
7
|
+
const order = await createOrder( { amount: req.body.amount, currency: req.body.currency } );
|
|
8
|
+
|
|
9
|
+
if ( !order ) {
|
|
10
|
+
return res.sendError( 'Failed to generate order id', 500 );
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return res.sendSuccess( order );
|
|
14
|
+
} catch ( error ) {
|
|
15
|
+
logger.error( { error: error, function: 'getVirtualAccount' } );
|
|
16
|
+
return res.sendError( error, 500 );
|
|
17
|
+
}
|
|
18
|
+
};
|
|
@@ -10,6 +10,8 @@ import * as invoiceService from '../services/invoice.service.js';
|
|
|
10
10
|
import * as userService from '../services/user.service.js';
|
|
11
11
|
import * as dailyPriceService from '../services/dailyPrice.service.js';
|
|
12
12
|
import * as cameraService from '../services/camera.service.js';
|
|
13
|
+
import * as billingService from '../services/billing.service.js';
|
|
14
|
+
|
|
13
15
|
import dayjs from 'dayjs';
|
|
14
16
|
import Handlebars from 'handlebars';
|
|
15
17
|
import fs from 'fs';
|
|
@@ -2014,18 +2016,18 @@ export const invoiceList = async ( req, res ) => {
|
|
|
2014
2016
|
item.billingDate = dayjs( item.billingDate ).format( 'DD MMM, YYYY' );
|
|
2015
2017
|
if ( item.products?.length > 0 ) {
|
|
2016
2018
|
let newProducts = [];
|
|
2017
|
-
// for ( let productIndex = 0; productIndex < item.products.length; productIndex++ ) {
|
|
2018
|
-
// let [ firstWord, secondWord ] = item.products[productIndex]?.productName.replace( /([a-z])([A-Z])/g, '$1 $2' ).split( ' ' );
|
|
2019
|
-
// firstWord = firstWord.charAt( 0 ).toUpperCase() + firstWord.slice( 1 );
|
|
2020
|
-
// item.products[productIndex].productName = firstWord + ' ' + secondWord;
|
|
2021
|
-
// newProducts.push( item.products[productIndex]?.productName );
|
|
2022
|
-
// }
|
|
2023
2019
|
for ( let productIndex = 0; productIndex < item.products.length; productIndex++ ) {
|
|
2024
|
-
let [ firstWord, secondWord ] = item.products[productIndex]?.
|
|
2020
|
+
let [ firstWord, secondWord ] = item.products[productIndex]?.productName.replace( /([a-z])([A-Z])/g, '$1 $2' ).split( ' ' );
|
|
2025
2021
|
firstWord = firstWord.charAt( 0 ).toUpperCase() + firstWord.slice( 1 );
|
|
2026
|
-
item.products[productIndex].
|
|
2027
|
-
newProducts.push( item.products[productIndex]?.
|
|
2022
|
+
item.products[productIndex].productName = firstWord + ' ' + secondWord;
|
|
2023
|
+
newProducts.push( item.products[productIndex]?.productName );
|
|
2028
2024
|
}
|
|
2025
|
+
// for ( let productIndex = 0; productIndex < item.products.length; productIndex++ ) {
|
|
2026
|
+
// let [ firstWord, secondWord ] = item.products[productIndex]?.product?.product.replace( /([a-z])([A-Z])/g, '$1 $2' ).split( ' ' );
|
|
2027
|
+
// firstWord = firstWord.charAt( 0 ).toUpperCase() + firstWord.slice( 1 );
|
|
2028
|
+
// item.products[productIndex].product.product = firstWord + ' ' + secondWord;
|
|
2029
|
+
// newProducts.push( item.products[productIndex]?.product?.product );
|
|
2030
|
+
// }
|
|
2029
2031
|
item.productList = newProducts;
|
|
2030
2032
|
}
|
|
2031
2033
|
} );
|
|
@@ -3060,7 +3062,7 @@ export const dailyPricingInsert = async ( req, res ) => {
|
|
|
3060
3062
|
let query = [
|
|
3061
3063
|
{
|
|
3062
3064
|
$match: {
|
|
3063
|
-
clientId:
|
|
3065
|
+
clientId: getClient.clientId,
|
|
3064
3066
|
},
|
|
3065
3067
|
},
|
|
3066
3068
|
{ $unwind: '$stores' },
|
|
@@ -3085,7 +3087,21 @@ export const dailyPricingInsert = async ( req, res ) => {
|
|
|
3085
3087
|
let dailyData = await dailyPriceService.aggregate( query );
|
|
3086
3088
|
let cameraDetails = await cameraService.find( { storeId: getStore[storeIndex].storeId, clientId: requestClient[clientIndex], isActivated: true, isUp: true }, { streamName: 1 } );
|
|
3087
3089
|
let firstDate = dayjs( getStore[storeIndex]?.edge?.firstFileDate ).format( 'YYYY-MM-DD' );
|
|
3088
|
-
let workingdays
|
|
3090
|
+
let workingdays;
|
|
3091
|
+
if ( firstDate < requestData.date && getStore[storeIndex]?.status == 'active' &&
|
|
3092
|
+
dailyData[0]?.dateString != dayjs( requestData.date, 'YYYY-MM-DD' ).format( 'YYYY-MM-DD' ) ) {
|
|
3093
|
+
if ( dailyData.length && dailyData[0]?.stores?.daysDifference ) {
|
|
3094
|
+
workingdays = dailyData[0]?.stores?.daysDifference + 1;
|
|
3095
|
+
} else {
|
|
3096
|
+
workingdays = 1;
|
|
3097
|
+
}
|
|
3098
|
+
} else {
|
|
3099
|
+
if ( dailyData[0]?.stores?.daysDifference ) {
|
|
3100
|
+
workingdays = dailyData[0]?.stores?.daysDifference;
|
|
3101
|
+
} else {
|
|
3102
|
+
workingdays = 0;
|
|
3103
|
+
}
|
|
3104
|
+
}
|
|
3089
3105
|
let priceDetails = getClient.priceType == 'standard' ? getBaseprice.standard : getBaseprice.step;
|
|
3090
3106
|
for ( let storeProductIndex = 0; storeProductIndex < getStore[storeIndex].product.length; storeProductIndex++ ) {
|
|
3091
3107
|
let productDetails;
|
|
@@ -3189,6 +3205,7 @@ export const dailyPricingInsertV1 = async ( req, res ) => {
|
|
|
3189
3205
|
for ( let i=1; i<requestData.days; i++ ) {
|
|
3190
3206
|
dayList.push( dayjs( requestData.date ).add( i, 'day' ).format( 'YYYY-MM-DD' ) );
|
|
3191
3207
|
}
|
|
3208
|
+
|
|
3192
3209
|
if ( requestData && requestClient.length > 0 ) {
|
|
3193
3210
|
for ( let i=0; i<dayList.length; i++ ) {
|
|
3194
3211
|
requestData.date = dayList[i];
|
|
@@ -3202,12 +3219,12 @@ export const dailyPricingInsertV1 = async ( req, res ) => {
|
|
|
3202
3219
|
for ( let storeIndex = 0; storeIndex < getStore.length; storeIndex++ ) {
|
|
3203
3220
|
let productList = [];
|
|
3204
3221
|
if ( getBaseprice ) {
|
|
3205
|
-
await axios.get(
|
|
3222
|
+
await axios.get( `https://api.tangoeye.in/v1/processedDayData/getDailyData?clientId=${requestClient[clientIndex]}&storeId=${getStore[storeIndex].storeId}&date=${requestData.date}`, { headers: { Authorization: 'Bearer d47433f8-9a33-47c7-ba43-1a0fbac28f66' } } ).then( async ( response ) => {
|
|
3206
3223
|
let processedFileDate = response.data?.data?.firstFileDate || null;
|
|
3207
3224
|
let query = [
|
|
3208
3225
|
{
|
|
3209
3226
|
$match: {
|
|
3210
|
-
clientId:
|
|
3227
|
+
clientId: getClient.clientId,
|
|
3211
3228
|
},
|
|
3212
3229
|
},
|
|
3213
3230
|
{ $unwind: '$stores' },
|
|
@@ -3232,7 +3249,21 @@ export const dailyPricingInsertV1 = async ( req, res ) => {
|
|
|
3232
3249
|
let dailyData = await dailyPriceService.aggregate( query );
|
|
3233
3250
|
let cameraDetails = await cameraService.find( { storeId: getStore[storeIndex].storeId, clientId: requestClient[clientIndex], isActivated: true, isUp: true }, { streamName: 1 } );
|
|
3234
3251
|
let firstDate = dayjs( getStore[storeIndex]?.edge?.firstFileDate ).format( 'YYYY-MM-DD' );
|
|
3235
|
-
let workingdays
|
|
3252
|
+
let workingdays;
|
|
3253
|
+
if ( firstDate < requestData.date && getStore[storeIndex]?.status == 'active' &&
|
|
3254
|
+
dailyData[0]?.dateString != dayjs( requestData.date, 'YYYY-MM-DD' ).format( 'YYYY-MM-DD' ) ) {
|
|
3255
|
+
if ( dailyData.length && dailyData[0]?.stores?.daysDifference ) {
|
|
3256
|
+
workingdays = dailyData[0]?.stores?.daysDifference + 1;
|
|
3257
|
+
} else {
|
|
3258
|
+
workingdays = 1;
|
|
3259
|
+
}
|
|
3260
|
+
} else {
|
|
3261
|
+
if ( dailyData[0]?.stores?.daysDifference ) {
|
|
3262
|
+
workingdays = dailyData[0]?.stores?.daysDifference;
|
|
3263
|
+
} else {
|
|
3264
|
+
workingdays = 0;
|
|
3265
|
+
}
|
|
3266
|
+
}
|
|
3236
3267
|
let priceDetails = getClient.priceType == 'standard' ? getBaseprice.standard : getBaseprice.step;
|
|
3237
3268
|
for ( let storeProductIndex = 0; storeProductIndex < getStore[storeIndex].product.length; storeProductIndex++ ) {
|
|
3238
3269
|
let productDetails;
|
|
@@ -3276,13 +3307,14 @@ export const dailyPricingInsertV1 = async ( req, res ) => {
|
|
|
3276
3307
|
},
|
|
3277
3308
|
);
|
|
3278
3309
|
if ( storeIndex == getStore.length - 1 ) {
|
|
3310
|
+
let activestores = storeList.filter( ( store ) => store.status=='active' );
|
|
3279
3311
|
let params = {
|
|
3280
3312
|
clientId: requestClient[clientIndex],
|
|
3281
3313
|
stores: storeList,
|
|
3282
3314
|
dateISO: new Date( requestData.date ),
|
|
3283
3315
|
accountType: getClient?.planDetails?.subscriptionType,
|
|
3284
3316
|
status: getClient?.status,
|
|
3285
|
-
activeStores:
|
|
3317
|
+
activeStores: activestores?.length,
|
|
3286
3318
|
brandName: getClient?.clientName,
|
|
3287
3319
|
proRate: getClient?.paymentInvoice?.proRate,
|
|
3288
3320
|
dateString: dayjs( requestData.date, 'YYYY-MM-DD' ).format( 'YYYY-MM-DD' ),
|
|
@@ -3676,3 +3708,34 @@ function convertTitleCase( data ) {
|
|
|
3676
3708
|
}
|
|
3677
3709
|
|
|
3678
3710
|
|
|
3711
|
+
export async function createDefaultbillings( req, res ) {
|
|
3712
|
+
let clientlist = await paymentService.find( { 'status': 'active' } );
|
|
3713
|
+
|
|
3714
|
+
for ( let client of clientlist ) {
|
|
3715
|
+
let storeslist = await storeService.find( { clientId: client.clientId }, { storeId: 1 } );
|
|
3716
|
+
storeslist = storeslist.map( ( a ) => a.storeId );
|
|
3717
|
+
let payload = {
|
|
3718
|
+
clientId: client.clientId,
|
|
3719
|
+
registeredCompanyName: client.billingDetails.companyName,
|
|
3720
|
+
gst: client.billingDetails.gstNumber,
|
|
3721
|
+
addressLineOne: client.billingDetails.billingAddress,
|
|
3722
|
+
placeOfSupply: client.billingDetails.PlaceOfSupply,
|
|
3723
|
+
stores: storeslist,
|
|
3724
|
+
currency: client.paymentInvoice.currencyType,
|
|
3725
|
+
generateInvoiceTo: [ ...client.paymentInvoice.invoiceCC, ...client.paymentInvoice.invoiceCC.invoiceTo?client.paymentInvoice.invoiceCC.invoiceTo:[] ],
|
|
3726
|
+
isPrimary: true,
|
|
3727
|
+
|
|
3728
|
+
};
|
|
3729
|
+
await billingService.create( payload );
|
|
3730
|
+
}
|
|
3731
|
+
}
|
|
3732
|
+
|
|
3733
|
+
|
|
3734
|
+
export async function planDetails( req, res ) {
|
|
3735
|
+
try {
|
|
3736
|
+
|
|
3737
|
+
} catch ( error ) {
|
|
3738
|
+
logger.error( { error: error, function: 'planDetails' } );
|
|
3739
|
+
return res.sendError( error, 500 );
|
|
3740
|
+
}
|
|
3741
|
+
}
|
|
@@ -378,3 +378,26 @@ export const billingGroupBody = joi.object( {
|
|
|
378
378
|
export const billingGroupSchema = {
|
|
379
379
|
body: billingGroupBody,
|
|
380
380
|
};
|
|
381
|
+
|
|
382
|
+
export const getVirtualAccountQuery = {
|
|
383
|
+
clientId: joi.string().required(),
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
export const getVirtualAccountSchema = {
|
|
387
|
+
query: getVirtualAccountQuery,
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
export const getInvoiceBody = joi.object( {
|
|
391
|
+
limit: joi.number().required(),
|
|
392
|
+
offset: joi.number().required(),
|
|
393
|
+
clientId: joi.string().required(),
|
|
394
|
+
sortColumn: joi.string().optional(),
|
|
395
|
+
sortBy: joi.number().optional(),
|
|
396
|
+
searchValue: joi.string().optional(),
|
|
397
|
+
isExport: joi.boolean().optional(),
|
|
398
|
+
filter: joi.string().optional(),
|
|
399
|
+
} );
|
|
400
|
+
|
|
401
|
+
export const getInvoiceSchema = {
|
|
402
|
+
body: getInvoiceBody,
|
|
403
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
2
|
export const billingRouter = express.Router();
|
|
3
3
|
import { authorize, isAllowedSessionHandler, validate } from 'tango-app-api-middleware';
|
|
4
|
-
import { createBillingGroup, deleteBillingGroup, getAllBillingGroups, getBillingGroups, subscribedStoreList, updateBillingGroup } from '../controllers/billing.controllers.js';
|
|
5
|
-
import { billingGroupSchema, createBillingGroupsSchema, deleteBillingGroupsSchema, getBillingGroupsSchema, subscribedStoreListSchema, updateBillingGroupsSchema } from '../dtos/validation.dtos.js';
|
|
4
|
+
import { createBillingGroup, deleteBillingGroup, getAllBillingGroups, getBillingGroups, getInvoices, getVirtualAccount, subscribedStoreList, updateBillingGroup } from '../controllers/billing.controllers.js';
|
|
5
|
+
import { billingGroupSchema, createBillingGroupsSchema, deleteBillingGroupsSchema, getBillingGroupsSchema, getInvoiceSchema, getVirtualAccountSchema, subscribedStoreListSchema, updateBillingGroupsSchema } from '../dtos/validation.dtos.js';
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
billingRouter.post( '/get-subscribed-store-list', isAllowedSessionHandler, authorize( {
|
|
@@ -41,3 +41,15 @@ billingRouter.post( '/get-billing-groups', isAllowedSessionHandler, authorize( {
|
|
|
41
41
|
],
|
|
42
42
|
} ), validate( billingGroupSchema ), getBillingGroups );
|
|
43
43
|
|
|
44
|
+
billingRouter.get( '/get-virtual-account', isAllowedSessionHandler, authorize( {
|
|
45
|
+
userType: [ 'tango' ], access: [
|
|
46
|
+
{ featureName: 'settings', name: 'paymentSubscriptions', permissions: [ 'isView' ] },
|
|
47
|
+
],
|
|
48
|
+
} ), validate( getVirtualAccountSchema ), getVirtualAccount );
|
|
49
|
+
|
|
50
|
+
billingRouter.post( '/get-invoices', isAllowedSessionHandler, authorize( {
|
|
51
|
+
userType: [ 'tango' ], access: [
|
|
52
|
+
{ featureName: 'settings', name: 'paymentSubscriptions', permissions: [ 'isView' ] },
|
|
53
|
+
],
|
|
54
|
+
} ), validate( getInvoiceSchema ), getInvoices );
|
|
55
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
export const paymentRouter = express.Router();
|
|
3
|
+
import { authorize, isAllowedSessionHandler } from 'tango-app-api-middleware';
|
|
4
|
+
import { generateOrder } from '../controllers/payment.controller.js';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
paymentRouter.post( '/generate-order', isAllowedSessionHandler, authorize( {
|
|
8
|
+
userType: [ 'tango' ], access: [
|
|
9
|
+
{ featureName: 'settings', name: 'paymentSubscriptions', permissions: [ 'isView' ] },
|
|
10
|
+
],
|
|
11
|
+
} ), generateOrder );
|
|
@@ -165,4 +165,7 @@ paymentSubscriptionRouter.get( '/notificationList', isAllowedSessionHandler, val
|
|
|
165
165
|
paymentSubscriptionRouter.put( '/notification/update/:notificationId', isAllowedSessionHandler, validate( validationDtos.validateId ), paymentController.updateNotification );
|
|
166
166
|
paymentSubscriptionRouter.put( '/pushNotification/update/:notificationId', isAllowedSessionHandler, validate( validationDtos.validateId ), paymentController.updatePushNotification );
|
|
167
167
|
paymentSubscriptionRouter.post( '/updateRemind/:notificationId', isAllowedSessionHandler, validate( validationDtos.validateId ), paymentController.updateRemind );
|
|
168
|
+
paymentSubscriptionRouter.post( '/createDefaultbillings', paymentController.createDefaultbillings );
|
|
169
|
+
paymentSubscriptionRouter.post( '/planDetails', isAllowedSessionHandler, paymentController.planDetails );
|
|
170
|
+
|
|
168
171
|
|