tango-app-api-payment-subscription 3.0.17-dev → 3.0.19-dev
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
|
@@ -10,6 +10,9 @@ import dayjs from 'dayjs';
|
|
|
10
10
|
import Handlebars from 'handlebars';
|
|
11
11
|
import fs from 'fs';
|
|
12
12
|
import path from 'path';
|
|
13
|
+
import { JSDOM } from 'jsdom';
|
|
14
|
+
import pdfMake from 'pdfmake';
|
|
15
|
+
import htmlToPdfmake from 'html-to-pdfmake';
|
|
13
16
|
|
|
14
17
|
export const addBilling = async ( req, res ) => {
|
|
15
18
|
try {
|
|
@@ -600,6 +603,7 @@ export const notificationList = async ( req, res ) => {
|
|
|
600
603
|
query.status = 'pending';
|
|
601
604
|
if ( req?.query?.clientId ) {
|
|
602
605
|
query.clientId = req?.query?.clientId;
|
|
606
|
+
query.category = { $ne: 'TrialExtend' };
|
|
603
607
|
}
|
|
604
608
|
let notificationList = await clientRequestService.find( query, { createdAt: 0, updatedAt: 0 } );
|
|
605
609
|
query = [
|
|
@@ -629,13 +633,13 @@ export const notificationList = async ( req, res ) => {
|
|
|
629
633
|
if ( item.product?.trialStartDate && item.product?.trialEndDate ) {
|
|
630
634
|
let [ firstWord, secondWord ] = item.product.productName.replace( /([a-z])([A-Z])/g, '$1 $2' ).split( ' ' );
|
|
631
635
|
firstWord = firstWord.charAt( 0 ).toUpperCase() + firstWord.slice( 1 );
|
|
632
|
-
let startDate = dayjs( item.product.trialStartDate );
|
|
633
|
-
let endDate = dayjs( item.product.trialEndDate ).startOf( 'day' );
|
|
636
|
+
let startDate = dayjs( item.product.trialStartDate ).startOf( 'day' );
|
|
637
|
+
let endDate = dayjs( item.product.trialEndDate ).startOf( 'day' ).add( 1, 'days' );
|
|
634
638
|
let date = dayjs().startOf( 'day' );
|
|
635
639
|
let days = date.diff( startDate, 'day' );
|
|
636
640
|
let totalDays = endDate.diff( startDate, 'day' );
|
|
637
641
|
let percentage = Math.round( ( days / totalDays )* 100 );
|
|
638
|
-
let leftDays = endDate.diff( date, 'day' )
|
|
642
|
+
let leftDays = endDate.diff( date, 'day' );
|
|
639
643
|
notificationList.push( {
|
|
640
644
|
product: item.product.productName,
|
|
641
645
|
name: `${firstWord} ${secondWord}`,
|
|
@@ -757,7 +761,7 @@ export const trialExtendRequestApproval = async ( req, res ) => {
|
|
|
757
761
|
days: req.body.days,
|
|
758
762
|
date: trialDate,
|
|
759
763
|
};
|
|
760
|
-
const templateHtml = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/
|
|
764
|
+
const templateHtml = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/trialExtentionEmail.hbs', 'utf8' );
|
|
761
765
|
const template = Handlebars.compile( templateHtml );
|
|
762
766
|
const html = template( { data: data } );
|
|
763
767
|
let params = {
|
|
@@ -771,6 +775,7 @@ export const trialExtendRequestApproval = async ( req, res ) => {
|
|
|
771
775
|
}
|
|
772
776
|
return res.sendSuccess( 'Trial Extended Successfully' );
|
|
773
777
|
} ).catch( ( e ) => {
|
|
778
|
+
logger.error( { error: e, function: 'trialExtendRequestApproval' } );
|
|
774
779
|
return res.sendError( e, 500 );
|
|
775
780
|
} );
|
|
776
781
|
} catch ( e ) {
|
|
@@ -924,6 +929,7 @@ export const productViewList = async ( req, res ) => {
|
|
|
924
929
|
},
|
|
925
930
|
},
|
|
926
931
|
];
|
|
932
|
+
|
|
927
933
|
let storeProductCount = await storeService.aggregate( query );
|
|
928
934
|
let clientProduct = await paymentService.findOne( { clientId: req.query.clientId }, { 'planDetails.product': 1 } );
|
|
929
935
|
|
|
@@ -952,6 +958,11 @@ export const productViewList = async ( req, res ) => {
|
|
|
952
958
|
},
|
|
953
959
|
);
|
|
954
960
|
} );
|
|
961
|
+
if ( req.query.sortBy == -1 ) {
|
|
962
|
+
products.sort( ( a, b ) => b.storeCount - a.storeCount ? -1 : 1 );
|
|
963
|
+
} else {
|
|
964
|
+
products.sort( ( a, b ) => a.storeCount - b.storeCount ? 1 : -1 );
|
|
965
|
+
}
|
|
955
966
|
// storeProductCount.forEach( ( item ) => {
|
|
956
967
|
// let productBasePrice = productPrice.basePricing.find( ( product ) => product.productName == item.product );
|
|
957
968
|
// if ( productBasePrice ) {
|
|
@@ -1222,6 +1233,21 @@ export const invoiceList = async ( req, res ) => {
|
|
|
1222
1233
|
} );
|
|
1223
1234
|
}
|
|
1224
1235
|
|
|
1236
|
+
query.push( {
|
|
1237
|
+
$project: {
|
|
1238
|
+
_id: 1,
|
|
1239
|
+
invoice: 1,
|
|
1240
|
+
billingDate: 1,
|
|
1241
|
+
stores: 1,
|
|
1242
|
+
products: 1,
|
|
1243
|
+
amount: 1,
|
|
1244
|
+
paymentMethod: 1,
|
|
1245
|
+
status: 1,
|
|
1246
|
+
discount: 1,
|
|
1247
|
+
revisedAmount: 1,
|
|
1248
|
+
},
|
|
1249
|
+
} );
|
|
1250
|
+
|
|
1225
1251
|
query.push(
|
|
1226
1252
|
{
|
|
1227
1253
|
$facet: {
|
|
@@ -1241,6 +1267,16 @@ export const invoiceList = async ( req, res ) => {
|
|
|
1241
1267
|
if ( !invoiceDetails[0]?.data.length ) {
|
|
1242
1268
|
return res.sendError( 'no data found', 204 );
|
|
1243
1269
|
}
|
|
1270
|
+
invoiceDetails[0].data.forEach( ( item ) => {
|
|
1271
|
+
item.billingDate = dayjs( item.billingDate ).format( 'DD MMM, YYYY' );
|
|
1272
|
+
} );
|
|
1273
|
+
if ( req.user.userType == 'client' ) {
|
|
1274
|
+
invoiceDetails[0].data.forEach( ( item ) => {
|
|
1275
|
+
delete item.discount;
|
|
1276
|
+
delete item.revisedAmount;
|
|
1277
|
+
delete item.products;
|
|
1278
|
+
} );
|
|
1279
|
+
}
|
|
1244
1280
|
let data = {
|
|
1245
1281
|
data: invoiceDetails[0].data,
|
|
1246
1282
|
count: invoiceDetails[0].count[0].count,
|
|
@@ -1248,7 +1284,25 @@ export const invoiceList = async ( req, res ) => {
|
|
|
1248
1284
|
if ( !req.body.export ) {
|
|
1249
1285
|
return res.sendSuccess( data );
|
|
1250
1286
|
} else {
|
|
1251
|
-
|
|
1287
|
+
let exportData = [];
|
|
1288
|
+
invoiceDetails[0].data.forEach( ( item ) => {
|
|
1289
|
+
if ( item.status == 'trial' ) {
|
|
1290
|
+
item.amount = 'Trial';
|
|
1291
|
+
}
|
|
1292
|
+
if ( item.status == 'free' ) {
|
|
1293
|
+
item.amount = 'Free';
|
|
1294
|
+
}
|
|
1295
|
+
exportData.push( {
|
|
1296
|
+
'Invoice': item.invoice,
|
|
1297
|
+
'Billing Date': item.billingDate,
|
|
1298
|
+
'Stores': item.stores,
|
|
1299
|
+
...( req.user.userType == 'tango' ? { 'Products': item.products } : {} ),
|
|
1300
|
+
'Amount': item.amount,
|
|
1301
|
+
...( req.user.userType == 'client' ? { 'Payment Method': item.paymentMethod } : {} ),
|
|
1302
|
+
'Status': item.status,
|
|
1303
|
+
} );
|
|
1304
|
+
} );
|
|
1305
|
+
await download( exportData, res );
|
|
1252
1306
|
}
|
|
1253
1307
|
} catch ( e ) {
|
|
1254
1308
|
logger.error( { error: e, function: 'invoiceList' } );
|
|
@@ -1344,7 +1398,7 @@ export const priceList = async ( req, res ) => {
|
|
|
1344
1398
|
let result = {
|
|
1345
1399
|
product: data,
|
|
1346
1400
|
totalActualPrice: originalTotalPrice,
|
|
1347
|
-
totalNegotiatePrice: discountTotalPrice,
|
|
1401
|
+
totalNegotiatePrice: discountTotalPrice.toFixed( 2 ),
|
|
1348
1402
|
actualPrice: totalProductPrice,
|
|
1349
1403
|
negotiatePrice: totalnegotiatePrice,
|
|
1350
1404
|
discountPrice: discountPrice,
|
|
@@ -1378,7 +1432,7 @@ export const pricingListUpdate = async ( req, res ) => {
|
|
|
1378
1432
|
productName: product,
|
|
1379
1433
|
discountPercentage: baseDetails.discoutPercentage,
|
|
1380
1434
|
basePrice: baseDetails.basePrice,
|
|
1381
|
-
negotiatePrice:
|
|
1435
|
+
negotiatePrice: discountPrice,
|
|
1382
1436
|
},
|
|
1383
1437
|
);
|
|
1384
1438
|
stepList.push(
|
|
@@ -1386,7 +1440,7 @@ export const pricingListUpdate = async ( req, res ) => {
|
|
|
1386
1440
|
productName: product,
|
|
1387
1441
|
discountPercentage: baseDetails.discoutPercentage,
|
|
1388
1442
|
basePrice: baseDetails.basePrice,
|
|
1389
|
-
negotiatePrice:
|
|
1443
|
+
negotiatePrice: discountPrice,
|
|
1390
1444
|
storeRange: '1-100',
|
|
1391
1445
|
},
|
|
1392
1446
|
);
|
|
@@ -1495,7 +1549,7 @@ export const updatedRevisedPrice = async ( req, res ) => {
|
|
|
1495
1549
|
|
|
1496
1550
|
export const unpaidInvoiceList = async ( req, res ) => {
|
|
1497
1551
|
try {
|
|
1498
|
-
let invoiceDetails = await invoiceService.find( { clientId: req.params.clientId, status: { $
|
|
1552
|
+
let invoiceDetails = await invoiceService.find( { clientId: req.params.clientId, status: { $nin: [ 'paid', 'trial', 'free' ] } }, { invoice: 1, status: 1, amount: 1, revisedAmount: 1, totalAmount: 1, discount: 1 } );
|
|
1499
1553
|
if ( !invoiceDetails.length ) {
|
|
1500
1554
|
return res.sendError( 'no data found', 204 );
|
|
1501
1555
|
}
|
|
@@ -1641,12 +1695,34 @@ export const getExpiredClients = async ( req, res ) => {
|
|
|
1641
1695
|
|
|
1642
1696
|
export const invoiceDownload = async ( req, res ) => {
|
|
1643
1697
|
try {
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1698
|
+
const templateHtml = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/invoicePdf.hbs', 'utf8' );
|
|
1699
|
+
const template = Handlebars.compile( templateHtml );
|
|
1700
|
+
const html = template( { data: '' } );
|
|
1701
|
+
let fonts = {
|
|
1702
|
+
Helvetica: {
|
|
1703
|
+
normal: 'Helvetica',
|
|
1704
|
+
bold: 'Helvetica-Bold',
|
|
1705
|
+
italics: 'Helvetica-Oblique',
|
|
1706
|
+
bolditalics: 'Helvetica-BoldOblique',
|
|
1707
|
+
},
|
|
1708
|
+
};
|
|
1709
|
+
let printer = new pdfMake( fonts );
|
|
1710
|
+
|
|
1711
|
+
let { window } = new JSDOM( '' );
|
|
1712
|
+
const htmlTemplate = htmlToPdfmake( html, { window: window, tableAutoSize: true } );
|
|
1713
|
+
|
|
1714
|
+
const docDefinition = {
|
|
1715
|
+
content: htmlTemplate,
|
|
1716
|
+
defaultStyle: {
|
|
1717
|
+
font: 'Helvetica',
|
|
1718
|
+
},
|
|
1719
|
+
};
|
|
1720
|
+
let pdfDoc = printer.createPdfKitDocument( docDefinition );
|
|
1721
|
+
res.setHeader( 'Content-disposition', `attachment; filename=Report_1.pdf` );
|
|
1722
|
+
res.setHeader( 'Content-Type', 'application/pdf' );
|
|
1723
|
+
pdfDoc.pipe( res );
|
|
1724
|
+
pdfDoc.end();
|
|
1648
1725
|
} catch ( e ) {
|
|
1649
|
-
// console.log( e );
|
|
1650
1726
|
logger.error( { error: e, function: 'invoiceDownload' } );
|
|
1651
1727
|
return res.sendError( e, 500 );
|
|
1652
1728
|
}
|
|
@@ -1661,7 +1737,7 @@ export const updateInvoiceStatus = async ( req, res ) => {
|
|
|
1661
1737
|
if ( !invoiceDetails ) {
|
|
1662
1738
|
return res.sendError( 'no data found', 204 );
|
|
1663
1739
|
}
|
|
1664
|
-
invoiceDetails.status = req.body?.status || '
|
|
1740
|
+
invoiceDetails.status = req.body?.status || 'Payment Received';
|
|
1665
1741
|
invoiceDetails.save().then( async () => {
|
|
1666
1742
|
let clientInfo = await paymentService.findOne( { clientId: invoiceDetails.clientId } );
|
|
1667
1743
|
if ( clientInfo ) {
|
|
@@ -1671,7 +1747,7 @@ export const updateInvoiceStatus = async ( req, res ) => {
|
|
|
1671
1747
|
return res.sendSuccess( 'Invoice updated Successfully' );
|
|
1672
1748
|
} );
|
|
1673
1749
|
} catch ( e ) {
|
|
1674
|
-
logger.error( { error: e, function: '
|
|
1750
|
+
logger.error( { error: e, function: 'updateInvoiceStatus' } );
|
|
1675
1751
|
return res.sendError( e, 500 );
|
|
1676
1752
|
}
|
|
1677
1753
|
};
|
|
@@ -1682,12 +1758,13 @@ export const invoiceCreate = async ( req, res ) => {
|
|
|
1682
1758
|
let products = req.body.client.planDetails.product.map( ( item ) => item.productName );
|
|
1683
1759
|
let storeDetails = await storeService.count( { clientId: req.body.clientId, status: 'active' } );
|
|
1684
1760
|
let data;
|
|
1761
|
+
let clientId = req.body.clientId;
|
|
1685
1762
|
data = {
|
|
1686
1763
|
invoice: `invoice #0${req.body.client.clientId} - ${Math.floor( Math.random() * 100 ) + 1}`,
|
|
1687
1764
|
billingDate: new Date(),
|
|
1688
1765
|
products: products,
|
|
1689
1766
|
stores: storeDetails,
|
|
1690
|
-
status: '',
|
|
1767
|
+
status: 'pending',
|
|
1691
1768
|
clientId: req.body.clientId,
|
|
1692
1769
|
};
|
|
1693
1770
|
req.body = {
|
|
@@ -1700,15 +1777,14 @@ export const invoiceCreate = async ( req, res ) => {
|
|
|
1700
1777
|
let pricingDetails = await calculatePricing( req, res );
|
|
1701
1778
|
data.amount = pricingDetails.price;
|
|
1702
1779
|
await invoiceService.create( data );
|
|
1703
|
-
let clientInfo = await paymentService.findOne( { clientId:
|
|
1780
|
+
let clientInfo = await paymentService.findOne( { clientId: clientId } );
|
|
1704
1781
|
if ( clientInfo ) {
|
|
1705
1782
|
clientInfo.planDetails.paymentStatus = 'due';
|
|
1706
1783
|
clientInfo.save();
|
|
1707
1784
|
}
|
|
1708
1785
|
return res.sendSuccess( 'Invoice Created Successfully' );
|
|
1709
1786
|
} catch ( e ) {
|
|
1710
|
-
|
|
1711
|
-
logger.error( { error: e, function: 'invoiceDownload' } );
|
|
1787
|
+
logger.error( { error: e, function: 'invoiceCreate' } );
|
|
1712
1788
|
return res.sendError( e, 500 );
|
|
1713
1789
|
}
|
|
1714
1790
|
};
|
|
@@ -20,6 +20,14 @@ export const validateStoreParams = {
|
|
|
20
20
|
} ),
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
+
export const validateProductListParams = {
|
|
24
|
+
query: joi.object( {
|
|
25
|
+
clientId: joi.string().required(),
|
|
26
|
+
sortColumn: joi.string().required(),
|
|
27
|
+
sortBy: joi.number().required(),
|
|
28
|
+
} ),
|
|
29
|
+
};
|
|
30
|
+
|
|
23
31
|
export const validateProducts = {
|
|
24
32
|
body: joi.object( {
|
|
25
33
|
camaraPerSqft: joi.string().required(),
|
|
@@ -97,7 +105,7 @@ export const validateInvoiceParams = {
|
|
|
97
105
|
body: joi.object( {
|
|
98
106
|
limit: joi.number().required(),
|
|
99
107
|
offset: joi.number().required(),
|
|
100
|
-
searchValue: joi.string().optional(),
|
|
108
|
+
searchValue: joi.string().optional().empty( '' ),
|
|
101
109
|
filter: joi.string().optional(),
|
|
102
110
|
sortColumn: joi.string().optional(),
|
|
103
111
|
sortBy: joi.number().optional(),
|
|
@@ -96,7 +96,7 @@ paymentSubscriptionRouter.get( '/admin/getProductViewList', isAllowedSessionHand
|
|
|
96
96
|
userType: [ 'tango' ], access: [
|
|
97
97
|
{ featureName: 'settings', name: 'paymentSubscriptions', permissions: [ 'isView' ] },
|
|
98
98
|
],
|
|
99
|
-
} ), validate( validationDtos.
|
|
99
|
+
} ), validate( validationDtos.validateProductListParams ), validateClient, paymentController.productViewList );
|
|
100
100
|
|
|
101
101
|
paymentSubscriptionRouter.post( '/admin/getstoreViewList', isAllowedSessionHandler, authorize( {
|
|
102
102
|
userType: [ 'tango' ], access: [
|
|
@@ -154,7 +154,7 @@ paymentSubscriptionRouter.post( '/admin/getStoreProducts', isAllowedSessionHandl
|
|
|
154
154
|
|
|
155
155
|
paymentSubscriptionRouter.get( '/trialRemaindList', paymentController.getRemindClients );
|
|
156
156
|
paymentSubscriptionRouter.get( '/trialExpiredList', paymentController.getExpiredClients );
|
|
157
|
-
paymentSubscriptionRouter.
|
|
157
|
+
paymentSubscriptionRouter.post( '/invoiceDownload', paymentController.invoiceDownload );
|
|
158
158
|
paymentSubscriptionRouter.post( '/invoiceStatusUpdate/:invoiceId', paymentController.updateInvoiceStatus );
|
|
159
159
|
paymentSubscriptionRouter.post( '/invoice/create', validateClient, paymentController.invoiceCreate );
|
|
160
160
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import model from 'tango-api-schema';
|
|
2
2
|
|
|
3
3
|
export const aggregate = async ( query ={} ) => {
|
|
4
|
-
return await model.invoiceModel.aggregate( query );
|
|
4
|
+
return await model.invoiceModel.aggregate( query, { collation: { locale: 'en_US', numericOrdering: true } } );
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
export const findOne = async ( query ={}, record={} ) => {
|