tango-app-api-payment-subscription 3.0.34-dev → 3.0.36-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
|
@@ -375,7 +375,7 @@ export const updateSubscriptionOLD = async ( req, res ) => {
|
|
|
375
375
|
|
|
376
376
|
let result = await paymentService.updateOne( { clientId: req.params.clientId }, details );
|
|
377
377
|
let storeProduct = products.map( ( item ) => item.productName );
|
|
378
|
-
await storeService.updateMany( { clientId: req.params.clientId
|
|
378
|
+
await storeService.updateMany( { clientId: req.params.clientId }, { product: storeProduct } );
|
|
379
379
|
|
|
380
380
|
if ( result.modifiedCount ) {
|
|
381
381
|
return res.sendSuccess( { message: 'Subscription Updated Successfully' } );
|
|
@@ -391,6 +391,7 @@ export const updateSubscriptionOLD = async ( req, res ) => {
|
|
|
391
391
|
export const updateSubscription = async ( req, res ) => {
|
|
392
392
|
try {
|
|
393
393
|
let requestBody = req.body;
|
|
394
|
+
let subscriptionCount = 0;
|
|
394
395
|
if ( !requestBody?.products?.length ) {
|
|
395
396
|
return res.sendError( 'product is required', 400 );
|
|
396
397
|
}
|
|
@@ -438,6 +439,7 @@ export const updateSubscription = async ( req, res ) => {
|
|
|
438
439
|
clientProducts[existsIndex].status = 'live';
|
|
439
440
|
clientProducts[existsIndex].subscribedDate = new Date();
|
|
440
441
|
}
|
|
442
|
+
subscriptionCount = subscriptionCount + 1;
|
|
441
443
|
}
|
|
442
444
|
}
|
|
443
445
|
|
|
@@ -458,10 +460,30 @@ export const updateSubscription = async ( req, res ) => {
|
|
|
458
460
|
'currencyType': 'rupees',
|
|
459
461
|
};
|
|
460
462
|
let pricingDetails = await calculatePricing( req, res );
|
|
463
|
+
if ( subscriptionCount ) {
|
|
464
|
+
let userDetails= await userService.findOne( { clientId: requestBody.clientId, role: 'superadmin' } );
|
|
465
|
+
if ( userDetails ) {
|
|
466
|
+
let data = {
|
|
467
|
+
username: userDetails.userName,
|
|
468
|
+
};
|
|
469
|
+
const templateHtml = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/trialSubscriptionEmail.hbs', 'utf8' );
|
|
470
|
+
const template = Handlebars.compile( templateHtml );
|
|
471
|
+
const html = template( { data: data } );
|
|
472
|
+
let params = {
|
|
473
|
+
toEmail: userDetails.email,
|
|
474
|
+
mailSubject: 'Subscribe - Tango Eye',
|
|
475
|
+
htmlBody: html,
|
|
476
|
+
attachment: '',
|
|
477
|
+
sourceEmail: appConfig.cloud.aws.ses.adminEmail,
|
|
478
|
+
};
|
|
479
|
+
sendEmailWithSES( params.toEmail, params.mailSubject, params.htmlBody, params.attachment, params.sourceEmail );
|
|
480
|
+
}
|
|
481
|
+
}
|
|
461
482
|
let data = {
|
|
462
483
|
planDetails: details,
|
|
463
484
|
price: pricingDetails.price,
|
|
464
485
|
priceType: requestBody.priceType,
|
|
486
|
+
|
|
465
487
|
};
|
|
466
488
|
|
|
467
489
|
let result = await paymentService.updateOne( { clientId: req.params.clientId }, data );
|
|
@@ -477,7 +499,7 @@ export const updateSubscription = async ( req, res ) => {
|
|
|
477
499
|
};
|
|
478
500
|
insertOpenSearchData( 'tango-retail-activity-logs', logObj );
|
|
479
501
|
let storeProduct = clientProducts.map( ( item ) => item.productName );
|
|
480
|
-
await storeService.updateMany( { clientId: req.params.clientId
|
|
502
|
+
await storeService.updateMany( { clientId: req.params.clientId }, { product: storeProduct } );
|
|
481
503
|
|
|
482
504
|
if ( result.modifiedCount ) {
|
|
483
505
|
req.body.clientId = req.params.clientId;
|
|
@@ -816,7 +838,7 @@ export const trialApproval = async ( req, res ) => {
|
|
|
816
838
|
} );
|
|
817
839
|
}
|
|
818
840
|
clientProducts.save();
|
|
819
|
-
await storeService.addremoveElement( { clientId: requestData.clientId
|
|
841
|
+
await storeService.addremoveElement( { clientId: requestData.clientId }, { $push: { product: requestData.name } } );
|
|
820
842
|
req.body.clientId = requestData.clientId;
|
|
821
843
|
updatePricing( req, res, true );
|
|
822
844
|
let userDetails= await userService.findOne( { clientId: requestData.clientId, role: 'superadmin' } );
|
|
@@ -927,6 +949,7 @@ export const productSubscribe = async ( req, res ) => {
|
|
|
927
949
|
try {
|
|
928
950
|
let data = req.body.product;
|
|
929
951
|
req.body.product = [];
|
|
952
|
+
let subscriptionCount = 0;
|
|
930
953
|
data.forEach( ( item ) => {
|
|
931
954
|
if ( item.type != 'cancel' ) {
|
|
932
955
|
let arr = item.name.split( ',' );
|
|
@@ -967,8 +990,9 @@ export const productSubscribe = async ( req, res ) => {
|
|
|
967
990
|
subscribedDate: new Date(),
|
|
968
991
|
status: 'live',
|
|
969
992
|
} );
|
|
993
|
+
subscriptionCount = subscriptionCount + 1;
|
|
970
994
|
}
|
|
971
|
-
await storeService.addremoveElement( { clientId: clientInfo.clientId
|
|
995
|
+
await storeService.addremoveElement( { clientId: clientInfo.clientId }, { $push: { product: item.name } } );
|
|
972
996
|
} else {
|
|
973
997
|
let productIndex = product.findIndex( ( ele ) => ele.productName == item.name );
|
|
974
998
|
if ( productIndex != -1 ) {
|
|
@@ -976,6 +1000,7 @@ export const productSubscribe = async ( req, res ) => {
|
|
|
976
1000
|
product[productIndex].subscribedDate = new Date();
|
|
977
1001
|
product[productIndex].status = 'live';
|
|
978
1002
|
}
|
|
1003
|
+
subscriptionCount = subscriptionCount + 1;
|
|
979
1004
|
}
|
|
980
1005
|
}
|
|
981
1006
|
}
|
|
@@ -992,9 +1017,7 @@ export const productSubscribe = async ( req, res ) => {
|
|
|
992
1017
|
if ( product.length > 1 ) {
|
|
993
1018
|
clientInfo.planDetails.subscriptionType = 'premium';
|
|
994
1019
|
}
|
|
995
|
-
|
|
996
|
-
clientInfo.save().then( async () => {
|
|
997
|
-
updatePricing( req, res, true );
|
|
1020
|
+
if ( subscriptionCount ) {
|
|
998
1021
|
let userDetails= await userService.findOne( { clientId: clientInfo.clientId, role: 'superadmin' } );
|
|
999
1022
|
if ( userDetails ) {
|
|
1000
1023
|
let data = {
|
|
@@ -1012,6 +1035,27 @@ export const productSubscribe = async ( req, res ) => {
|
|
|
1012
1035
|
};
|
|
1013
1036
|
sendEmailWithSES( params.toEmail, params.mailSubject, params.htmlBody, params.attachment, params.sourceEmail );
|
|
1014
1037
|
}
|
|
1038
|
+
}
|
|
1039
|
+
clientInfo.planDetails.product = product;
|
|
1040
|
+
clientInfo.save().then( async () => {
|
|
1041
|
+
updatePricing( req, res, true );
|
|
1042
|
+
// let userDetails= await userService.findOne( { clientId: clientInfo.clientId, role: 'superadmin' } );
|
|
1043
|
+
// if ( userDetails ) {
|
|
1044
|
+
// let data = {
|
|
1045
|
+
// username: userDetails.userName,
|
|
1046
|
+
// };
|
|
1047
|
+
// const templateHtml = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/trialSubscriptionEmail.hbs', 'utf8' );
|
|
1048
|
+
// const template = Handlebars.compile( templateHtml );
|
|
1049
|
+
// const html = template( { data: data } );
|
|
1050
|
+
// let params = {
|
|
1051
|
+
// toEmail: userDetails.email,
|
|
1052
|
+
// mailSubject: 'Subscribe - Tango Eye',
|
|
1053
|
+
// htmlBody: html,
|
|
1054
|
+
// attachment: '',
|
|
1055
|
+
// sourceEmail: appConfig.cloud.aws.ses.adminEmail,
|
|
1056
|
+
// };
|
|
1057
|
+
// sendEmailWithSES( params.toEmail, params.mailSubject, params.htmlBody, params.attachment, params.sourceEmail );
|
|
1058
|
+
// }
|
|
1015
1059
|
} );
|
|
1016
1060
|
const logObj = {
|
|
1017
1061
|
clientId: req.body.clientId,
|
|
@@ -1247,7 +1291,7 @@ export const storeViewList = async ( req, res ) => {
|
|
|
1247
1291
|
export const storeLocationList = async ( req, res ) => {
|
|
1248
1292
|
try {
|
|
1249
1293
|
let storeDetails;
|
|
1250
|
-
storeDetails = await storeService.find( { clientId: req.query.clientId
|
|
1294
|
+
storeDetails = await storeService.find( { clientId: req.query.clientId }, { 'storeId': 1, 'storeName': 1, 'storeProfile.city': 1 } );
|
|
1251
1295
|
let store = [];
|
|
1252
1296
|
let location = [];
|
|
1253
1297
|
if ( storeDetails.length ) {
|
|
@@ -1291,6 +1335,7 @@ export const addStoreProduct = async ( req, res ) => {
|
|
|
1291
1335
|
let clientProduct = [];
|
|
1292
1336
|
let storeProduct = [];
|
|
1293
1337
|
let removedProduct = [];
|
|
1338
|
+
let subscriptionCount = 0;
|
|
1294
1339
|
clientProduct = clientInfo.planDetails.product;
|
|
1295
1340
|
req.body.product.forEach( ( item ) => {
|
|
1296
1341
|
if ( item.type != 'unsubscribe' ) {
|
|
@@ -1333,11 +1378,31 @@ export const addStoreProduct = async ( req, res ) => {
|
|
|
1333
1378
|
subscribedDate: new Date(),
|
|
1334
1379
|
status: 'live',
|
|
1335
1380
|
} );
|
|
1381
|
+
subscriptionCount = subscriptionCount + 1;
|
|
1336
1382
|
}
|
|
1337
1383
|
}
|
|
1338
1384
|
}
|
|
1339
1385
|
},
|
|
1340
1386
|
);
|
|
1387
|
+
if ( subscriptionCount ) {
|
|
1388
|
+
let userDetails= await userService.findOne( { clientId: req.body.clientId, role: 'superadmin' } );
|
|
1389
|
+
if ( userDetails ) {
|
|
1390
|
+
let data = {
|
|
1391
|
+
username: userDetails.userName,
|
|
1392
|
+
};
|
|
1393
|
+
const templateHtml = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/trialSubscriptionEmail.hbs', 'utf8' );
|
|
1394
|
+
const template = Handlebars.compile( templateHtml );
|
|
1395
|
+
const html = template( { data: data } );
|
|
1396
|
+
let params = {
|
|
1397
|
+
toEmail: userDetails.email,
|
|
1398
|
+
mailSubject: 'Subscribe - Tango Eye',
|
|
1399
|
+
htmlBody: html,
|
|
1400
|
+
attachment: '',
|
|
1401
|
+
sourceEmail: appConfig.cloud.aws.ses.adminEmail,
|
|
1402
|
+
};
|
|
1403
|
+
sendEmailWithSES( params.toEmail, params.mailSubject, params.htmlBody, params.attachment, params.sourceEmail );
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1341
1406
|
clientInfo.planDetails.product = clientProduct;
|
|
1342
1407
|
clientInfo.save();
|
|
1343
1408
|
storeDetails.forEach( async ( item ) => {
|
|
@@ -1461,6 +1526,9 @@ export const invoiceList = async ( req, res ) => {
|
|
|
1461
1526
|
if ( item.products?.length>0 ) {
|
|
1462
1527
|
let newProducts = [];
|
|
1463
1528
|
for ( let productIndex = 0; productIndex < item.products.length; productIndex++ ) {
|
|
1529
|
+
let [ firstWord, secondWord ] = item.products[productIndex]?.product?.product.replace( /([a-z])([A-Z])/g, '$1 $2' ).split( ' ' );
|
|
1530
|
+
firstWord = firstWord.charAt( 0 ).toUpperCase() + firstWord.slice( 1 );
|
|
1531
|
+
item.products[productIndex].product.product = firstWord + ' ' + secondWord;
|
|
1464
1532
|
newProducts.push( item.products[productIndex]?.product?.product );
|
|
1465
1533
|
}
|
|
1466
1534
|
item.productList = newProducts;
|
|
@@ -1632,6 +1700,9 @@ export const pricingListUpdate = async ( req, res ) => {
|
|
|
1632
1700
|
productList = JSON.parse( JSON.stringify( req.body ) );
|
|
1633
1701
|
let amount =0;
|
|
1634
1702
|
productList.products.forEach( ( item ) => {
|
|
1703
|
+
let [ firstWord, secondWord ] = item.productName.replace( /([a-z])([A-Z])/g, '$1 $2' ).split( ' ' );
|
|
1704
|
+
firstWord = firstWord.charAt( 0 ).toUpperCase() + firstWord.slice( 1 );
|
|
1705
|
+
item.productName = firstWord + ' ' + secondWord;
|
|
1635
1706
|
if ( req.body.client.paymentInvoice.currencyType == 'dollar' ) {
|
|
1636
1707
|
item.basePrice = convertINRtoUSD( item.basePrice );
|
|
1637
1708
|
item.price = convertINRtoUSD( item.price );
|
|
@@ -1719,6 +1790,7 @@ async function updatePricing( req, res, update ) {
|
|
|
1719
1790
|
let clientDetails = await paymentService.findOne( { clientId: req.body.clientId } );
|
|
1720
1791
|
if ( clientDetails ) {
|
|
1721
1792
|
let products = clientDetails.planDetails.product.map( ( item ) => item.productName );
|
|
1793
|
+
let subscriptionCount = clientDetails.planDetails.product.map( ( item ) => item.status == 'live' );
|
|
1722
1794
|
let standardList = [];
|
|
1723
1795
|
let stepList = [];
|
|
1724
1796
|
products.forEach( ( product ) => {
|
|
@@ -1775,9 +1847,18 @@ async function updatePricing( req, res, update ) {
|
|
|
1775
1847
|
'currencyType': 'rupees',
|
|
1776
1848
|
};
|
|
1777
1849
|
let pricingDetails = await calculatePricing( req, res );
|
|
1850
|
+
let paymentStatus = clientDetails?.subscriptionType == 'free' ? 'free' : 'trial';
|
|
1851
|
+
if ( subscriptionCount ) {
|
|
1852
|
+
let invoiceCount = await invoiceService.count( { clientId: req.params.clientId, status: 'pending' } );
|
|
1853
|
+
if ( invoiceCount ) {
|
|
1854
|
+
paymentStatus ='due';
|
|
1855
|
+
} else {
|
|
1856
|
+
paymentStatus ='unbilled';
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1778
1859
|
let details = {
|
|
1779
1860
|
'priceType': 'standard',
|
|
1780
|
-
'planDetails.paymentStatus': clientDetails?.subscriptionType == 'free' ? 'free' :
|
|
1861
|
+
'planDetails.paymentStatus': clientDetails?.subscriptionType == 'free' ? 'free' : paymentStatus,
|
|
1781
1862
|
'planDetails.product': product,
|
|
1782
1863
|
'price': pricingDetails.price,
|
|
1783
1864
|
};
|
|
@@ -1801,6 +1882,13 @@ export const updatedRevisedPrice = async ( req, res ) => {
|
|
|
1801
1882
|
let clientDetails = await paymentService.findOne( { clientId: invoiceDetails.clientId } );
|
|
1802
1883
|
let amount = 0;
|
|
1803
1884
|
invoiceDetails.products.forEach( ( item ) => {
|
|
1885
|
+
let [ firstWord, secondWord ] = item.product.product.replace( /([a-z])([A-Z])/g, '$1 $2' ).split( ' ' );
|
|
1886
|
+
firstWord = firstWord.charAt( 0 ).toUpperCase() + firstWord.slice( 1 );
|
|
1887
|
+
item.product.product = firstWord + ' ' + secondWord;
|
|
1888
|
+
if ( clientDetails?.paymentInvoice?.currencyType == 'dollar' ) {
|
|
1889
|
+
item.basePrice = convertINRtoUSD( item.basePrice );
|
|
1890
|
+
item.price = convertINRtoUSD( item.price );
|
|
1891
|
+
}
|
|
1804
1892
|
if ( clientDetails.priceType == 'step' ) {
|
|
1805
1893
|
item.count = item.product.storeRange;
|
|
1806
1894
|
}
|
|
@@ -1814,7 +1902,8 @@ export const updatedRevisedPrice = async ( req, res ) => {
|
|
|
1814
1902
|
clientName: clientDetails.clientName,
|
|
1815
1903
|
extendDays: clientDetails.paymentInvoice.extendPaymentPeriodDays,
|
|
1816
1904
|
address: clientDetails.billingDetails.billingAddress,
|
|
1817
|
-
amount: amount,
|
|
1905
|
+
amount: amount.toFixed( 2 ),
|
|
1906
|
+
currencyType: clientDetails.paymentInvoice.currencyType == 'dollar' ? '$' : '₹',
|
|
1818
1907
|
discount: req.body.discount,
|
|
1819
1908
|
total: req.body.revisedAmount.toFixed( 2 ),
|
|
1820
1909
|
invoiceDate,
|
|
@@ -1870,9 +1959,9 @@ export const getStoreProducts = async ( req, res ) => {
|
|
|
1870
1959
|
try {
|
|
1871
1960
|
let storeProductDetails;
|
|
1872
1961
|
if ( !req.body.store.length ) {
|
|
1873
|
-
storeProductDetails = await storeService.find( { clientId: req.body.clientId
|
|
1962
|
+
storeProductDetails = await storeService.find( { clientId: req.body.clientId } );
|
|
1874
1963
|
} else {
|
|
1875
|
-
storeProductDetails = await storeService.find( { storeId: { $in: req.body.store }, clientId: req.body.clientId
|
|
1964
|
+
storeProductDetails = await storeService.find( { storeId: { $in: req.body.store }, clientId: req.body.clientId } );
|
|
1876
1965
|
}
|
|
1877
1966
|
|
|
1878
1967
|
let product = new Set();
|
|
@@ -1899,15 +1988,18 @@ export const getRemindClients = async ( req, res ) => {
|
|
|
1899
1988
|
clientDetails.forEach( async ( client ) => {
|
|
1900
1989
|
if ( client.planDetails?.product && client.planDetails?.product.length ) {
|
|
1901
1990
|
client.planDetails.product.forEach( async ( item ) => {
|
|
1902
|
-
if ( item.status == 'trial' ) {
|
|
1903
|
-
let
|
|
1904
|
-
let
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1991
|
+
if ( item.status == 'trial' && item?.trialEndDate ) {
|
|
1992
|
+
let endDate = dayjs( item.trialEndDate ).startOf( 'day' );
|
|
1993
|
+
let date = dayjs().startOf( 'day' );
|
|
1994
|
+
let leftDays = endDate.diff( date, 'day' );
|
|
1995
|
+
// let date = new Date();
|
|
1996
|
+
// let userTimezoneOffset = item.trialEndDate.getTimezoneOffset() / 60000;
|
|
1997
|
+
// item.trialEndDate = new Date( item.trialEndDate.getTime() - userTimezoneOffset );
|
|
1998
|
+
// item.trialEndDate.setUTCHours( 0, 0, 0, 0 );
|
|
1999
|
+
// const diffTime = parseInt( ( item.trialEndDate - date ) / ( 1000 * 60 * 60 * 24 ), 10 ) + 1;
|
|
1908
2000
|
let userDetails= await userService.findOne( { clientId: client.clientId, role: 'superadmin' } );
|
|
1909
2001
|
if ( userDetails ) {
|
|
1910
|
-
if (
|
|
2002
|
+
if ( leftDays == 3 ) {
|
|
1911
2003
|
let [ firstWord, secondWord ] = item.productName.replace( /([a-z])([A-Z])/g, '$1 $2' ).split( ' ' );
|
|
1912
2004
|
firstWord = firstWord.charAt( 0 ).toUpperCase() + firstWord.slice( 1 );
|
|
1913
2005
|
let data = {
|
|
@@ -1939,7 +2031,7 @@ export const getRemindClients = async ( req, res ) => {
|
|
|
1939
2031
|
};
|
|
1940
2032
|
|
|
1941
2033
|
|
|
1942
|
-
export const
|
|
2034
|
+
export const getExpiredClientsOld = async ( req, res ) => {
|
|
1943
2035
|
try {
|
|
1944
2036
|
let start = new Date();
|
|
1945
2037
|
let userTimezoneOffset = start.getTimezoneOffset() * 60000;
|
|
@@ -1958,7 +2050,6 @@ export const getExpiredClients = async ( req, res ) => {
|
|
|
1958
2050
|
{
|
|
1959
2051
|
$match: {
|
|
1960
2052
|
'planDetails.product.status': 'trial',
|
|
1961
|
-
'planDetails.product.trialEndDate': { $gt: end },
|
|
1962
2053
|
},
|
|
1963
2054
|
},
|
|
1964
2055
|
];
|
|
@@ -1974,7 +2065,7 @@ export const getExpiredClients = async ( req, res ) => {
|
|
|
1974
2065
|
let [ firstWord, secondWord ] = item.productName.replace( /([a-z])([A-Z])/g, '$1 $2' ).split( ' ' );
|
|
1975
2066
|
firstWord = firstWord.charAt( 0 ).toUpperCase() + firstWord.slice( 1 );
|
|
1976
2067
|
let data = {
|
|
1977
|
-
|
|
2068
|
+
userName: userDetails.userName,
|
|
1978
2069
|
product: firstWord +' '+secondWord,
|
|
1979
2070
|
};
|
|
1980
2071
|
const templateHtml = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/trialExpiredEmail.hbs', 'utf8' );
|
|
@@ -1997,6 +2088,56 @@ export const getExpiredClients = async ( req, res ) => {
|
|
|
1997
2088
|
return res.sendError( e, 500 );
|
|
1998
2089
|
}
|
|
1999
2090
|
};
|
|
2091
|
+
export const getExpiredClients = async ( req, res ) => {
|
|
2092
|
+
try {
|
|
2093
|
+
let clientDetails = await paymentService.find( { status: 'active' } );
|
|
2094
|
+
if ( !clientDetails.length ) {
|
|
2095
|
+
return res.sendError( 'no data found', 204 );
|
|
2096
|
+
}
|
|
2097
|
+
clientDetails.forEach( async ( client ) => {
|
|
2098
|
+
if ( client.planDetails?.product && client.planDetails?.product.length ) {
|
|
2099
|
+
client.planDetails.product.forEach( async ( item ) => {
|
|
2100
|
+
if ( item.status == 'trial' && item?.trialEndDate ) {
|
|
2101
|
+
let endDate = dayjs( item.trialEndDate ).startOf( 'day' );
|
|
2102
|
+
let date = dayjs().startOf( 'day' );
|
|
2103
|
+
let leftDays = endDate.diff( date, 'day' );
|
|
2104
|
+
// let date = new Date();
|
|
2105
|
+
// let userTimezoneOffset = item.trialEndDate.getTimezoneOffset() / 60000;
|
|
2106
|
+
// item.trialEndDate = new Date( item.trialEndDate.getTime() - userTimezoneOffset );
|
|
2107
|
+
// item.trialEndDate.setUTCHours( 0, 0, 0, 0 );
|
|
2108
|
+
// const diffTime = parseInt( ( item.trialEndDate - date ) / ( 1000 * 60 * 60 * 24 ), 10 ) + 1;
|
|
2109
|
+
let userDetails= await userService.findOne( { clientId: client.clientId, role: 'superadmin' } );
|
|
2110
|
+
if ( userDetails ) {
|
|
2111
|
+
if ( leftDays == -1 ) {
|
|
2112
|
+
let [ firstWord, secondWord ] = item.productName.replace( /([a-z])([A-Z])/g, '$1 $2' ).split( ' ' );
|
|
2113
|
+
firstWord = firstWord.charAt( 0 ).toUpperCase() + firstWord.slice( 1 );
|
|
2114
|
+
let data = {
|
|
2115
|
+
userName: userDetails.userName,
|
|
2116
|
+
product: firstWord + ' ' + secondWord,
|
|
2117
|
+
};
|
|
2118
|
+
const templateHtml = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/trialExpiredEmail.hbs', 'utf8' );
|
|
2119
|
+
const template = Handlebars.compile( templateHtml );
|
|
2120
|
+
const html = template( { data: data } );
|
|
2121
|
+
let params = {
|
|
2122
|
+
toEmail: userDetails.email,
|
|
2123
|
+
mailSubject: 'TangoEye | Trial Expired - Upgrade to Continue',
|
|
2124
|
+
htmlBody: html,
|
|
2125
|
+
attachment: '',
|
|
2126
|
+
sourceEmail: appConfig.cloud.aws.ses.adminEmail,
|
|
2127
|
+
};
|
|
2128
|
+
await sendEmailWithSES( params.toEmail, params.mailSubject, params.htmlBody, params.attachment, params.sourceEmail );
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
} );
|
|
2133
|
+
}
|
|
2134
|
+
} );
|
|
2135
|
+
return res.sendSuccess();
|
|
2136
|
+
} catch ( e ) {
|
|
2137
|
+
logger.error( { error: e, function: 'getExpiredClients' } );
|
|
2138
|
+
return res.sendError( e, 500 );
|
|
2139
|
+
}
|
|
2140
|
+
};
|
|
2000
2141
|
|
|
2001
2142
|
export const invoiceDownload = async ( req, res ) => {
|
|
2002
2143
|
try {
|
|
@@ -2006,6 +2147,9 @@ export const invoiceDownload = async ( req, res ) => {
|
|
|
2006
2147
|
let clientDetails = await paymentService.findOne( { clientId: invoiceInfo.clientId } );
|
|
2007
2148
|
let amount = 0;
|
|
2008
2149
|
invoiceInfo.products.forEach( ( item ) => {
|
|
2150
|
+
let [ firstWord, secondWord ] = item.product.product.replace( /([a-z])([A-Z])/g, '$1 $2' ).split( ' ' );
|
|
2151
|
+
firstWord = firstWord.charAt( 0 ).toUpperCase() + firstWord.slice( 1 );
|
|
2152
|
+
item.product.product = firstWord + ' ' + secondWord;
|
|
2009
2153
|
if ( clientDetails.paymentInvoice.currencyType == 'dollar' ) {
|
|
2010
2154
|
item.basePrice = convertINRtoUSD( item.basePrice );
|
|
2011
2155
|
item.price = convertINRtoUSD( item.price );
|
|
@@ -2307,7 +2451,7 @@ export const invoiceGenerate = async ( req, res ) => {
|
|
|
2307
2451
|
};
|
|
2308
2452
|
let storeCount = await storeService.count( storeQuery );
|
|
2309
2453
|
let data = {
|
|
2310
|
-
invoice: `invoice#${requestClient[clientIndex]}-${
|
|
2454
|
+
invoice: `invoice#${requestClient[clientIndex]}-${new Date().getTime()}`,
|
|
2311
2455
|
products: invoiceDetails,
|
|
2312
2456
|
status: 'pending',
|
|
2313
2457
|
amount: amount,
|
|
@@ -2353,6 +2497,9 @@ export const invoiceRevised = async ( req, res ) => {
|
|
|
2353
2497
|
let days = clientDetails?.paymentInvoice?.extendPaymentPeriodDays || 10;
|
|
2354
2498
|
let dueDate = invoiceDetails?.dueDate ? dayjs( invoiceDetails?.dueDate ).format( 'DD MMM, YYYY' ) : dayjs().add( days, 'days' ).format( 'DD MMM, YYYY' );
|
|
2355
2499
|
invoiceDetails.products.forEach( ( item ) => {
|
|
2500
|
+
let [ firstWord, secondWord ] = item.product.product.replace( /([a-z])([A-Z])/g, '$1 $2' ).split( ' ' );
|
|
2501
|
+
firstWord = firstWord.charAt( 0 ).toUpperCase() + firstWord.slice( 1 );
|
|
2502
|
+
item.product.product = firstWord + ' ' + secondWord;
|
|
2356
2503
|
if ( clientDetails?.paymentInvoice?.currencyType == 'dollar' ) {
|
|
2357
2504
|
item.basePrice = convertINRtoUSD( item.basePrice );
|
|
2358
2505
|
item.price = convertINRtoUSD( item.price );
|
|
@@ -80,6 +80,31 @@
|
|
|
80
80
|
border: 0;
|
|
81
81
|
outline: none;
|
|
82
82
|
}
|
|
83
|
+
|
|
84
|
+
.invoicedescription {
|
|
85
|
+
/* width:300px;
|
|
86
|
+
padding-left:30px; */
|
|
87
|
+
color: #667085 !important
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.productstext {
|
|
91
|
+
font-size: 16px !important;
|
|
92
|
+
font-weight: 500 !important;
|
|
93
|
+
text-align: left;
|
|
94
|
+
color: #475467 !important;
|
|
95
|
+
/* border-bottom:1px solid #f0ecea !important; */
|
|
96
|
+
line-height: 24px !important;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.invoicesub {
|
|
100
|
+
/* font-family: 'Inter'; */
|
|
101
|
+
color: #667085 !important;
|
|
102
|
+
font-size: 16px;
|
|
103
|
+
font-weight: 600;
|
|
104
|
+
line-height: 24px;
|
|
105
|
+
text-align: left;
|
|
106
|
+
|
|
107
|
+
}
|
|
83
108
|
</style>
|
|
84
109
|
|
|
85
110
|
</head>
|
|
@@ -133,7 +158,7 @@
|
|
|
133
158
|
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 680px;">
|
|
134
159
|
<tr>
|
|
135
160
|
<td align="left" bgcolor="#ffffff"
|
|
136
|
-
style="padding-left: 30px;padding-right: 24px;padding-top:10px; font-size: 16px; line-height: 24px;font-weight:400;color:#384860">
|
|
161
|
+
style="padding-left: 30px;padding-right: 24px;padding-top:10px; font-size: 16px; line-height: 24px;font-weight:400;color:#384860; padding-bottom: 20px;">
|
|
137
162
|
<p style="margin: 0;">"Notice:Subscription price revised.Please review updated pricing
|
|
138
163
|
details.we <br />
|
|
139
164
|
appreciated your continued
|
|
@@ -148,68 +173,70 @@
|
|
|
148
173
|
<td align="center" bgcolor="#dbe5ea" style="padding:0 10px 0 10px">
|
|
149
174
|
<table align="center" bgcolor="#ffffff" border="0" cellpadding="0" cellspacing="0" width="100%"
|
|
150
175
|
style="max-width: 680px;">
|
|
151
|
-
<tr bgcolor="#
|
|
152
|
-
style="border:
|
|
153
|
-
<th style="width:300px;padding-left:30px;">Description</th>
|
|
154
|
-
<th style="width:120px;">Price</th>
|
|
155
|
-
<th style="width:120px;">Stores</th>
|
|
156
|
-
<th style="width:120px;">Total Amount</th>
|
|
176
|
+
<tr bgcolor="#F9FAFB"
|
|
177
|
+
style="border-bottom:1px solid #f0ecea;height:40px;margin-top:10px;text-align:left">
|
|
178
|
+
<th class="invoicedescription" style="width:300px;padding-left:30px;">Description</th>
|
|
179
|
+
<th class="invoicedescription" style="width:120px;">Price</th>
|
|
180
|
+
<th class="invoicedescription" style="width:120px;">Stores</th>
|
|
181
|
+
<th class="invoicedescription" style="width:120px;">Total Amount</th>
|
|
182
|
+
</tr>
|
|
183
|
+
<tr style="border:none;">
|
|
184
|
+
<td colspan="4" align="left" bgcolor="#ffffff" style="padding-left: 30px;padding-right: 24px; font-size: 14px; line-height: 24px;">
|
|
185
|
+
<p class="" style="border: 0px solid #EAECF0;">
|
|
186
|
+
</p>
|
|
187
|
+
</td>
|
|
157
188
|
</tr>
|
|
158
189
|
{{#each data.products}}
|
|
159
190
|
<tr bgcolor="#ffffff" style="border:none;margin-top:10px;">
|
|
160
|
-
<td style="padding-left:30px;">{{productName}}</td>
|
|
161
|
-
<td>{{../data.currencyType}} {{basePrice}}</td>
|
|
162
|
-
<td>{{storeCount}}</td>
|
|
163
|
-
<td>{{../data.currencyType}} {{price}}</td>
|
|
191
|
+
<td class="productstext" style="padding-left:30px;">{{productName}}</td>
|
|
192
|
+
<td class="productstext">{{../data.currencyType}} {{basePrice}}</td>
|
|
193
|
+
<td class="productstext">{{storeCount}}</td>
|
|
194
|
+
<td class="productstext">{{../data.currencyType}} {{price}}</td>
|
|
164
195
|
</tr>
|
|
165
196
|
{{/each}}
|
|
166
197
|
<tr>
|
|
167
|
-
<td align="left" bgcolor="#ffffff"
|
|
198
|
+
<td colspan="4" align="left" bgcolor="#ffffff"
|
|
168
199
|
style="padding-left: 30px;padding-right: 24px; font-size: 14px; line-height: 24px;">
|
|
169
|
-
<p class="
|
|
170
|
-
style="width: 624px;height: 0px;border: 1px solid #CBD5E1;flex: none;order: 1;flex-grow: 0;">
|
|
200
|
+
<p class="" style="border: 1px solid #EAECF0;">
|
|
171
201
|
</p>
|
|
172
202
|
</td>
|
|
173
203
|
</tr>
|
|
174
|
-
<tr bgcolor="#ffffff"
|
|
175
|
-
style="
|
|
176
|
-
<td style="padding-left:30px;">Sub Total</td>
|
|
204
|
+
<tr bgcolor="#ffffff" style="border:none;margin-top:0px;">
|
|
205
|
+
<td class="invoicesub" style="padding-left:30px; line-height: 24px;">Sub Total</td>
|
|
177
206
|
<td></td>
|
|
178
207
|
<td></td>
|
|
179
|
-
<td>{{data.currencyType}} {{data.amount}}</td>
|
|
208
|
+
<td class="invoicesub">{{data.currencyType}} {{data.amount}}</td>
|
|
180
209
|
</tr>
|
|
181
210
|
<tr bgcolor="#ffffff" style="border:none;margin-top:0px;">
|
|
182
|
-
<td style="padding-left:30px;">IGST</td>
|
|
211
|
+
<td class="invoicesub" style="padding-left:30px; line-height: 24px;">IGST</td>
|
|
183
212
|
<td></td>
|
|
184
213
|
<td></td>
|
|
185
|
-
<td>0%</td>
|
|
214
|
+
<td class="invoicesub">0%</td>
|
|
186
215
|
</tr>
|
|
187
216
|
<tr bgcolor="#ffffff" style="border:none;margin-top:0px;">
|
|
188
|
-
<td style="padding-left:30px;">Total</td>
|
|
217
|
+
<td class="invoicesub" style="padding-left:30px; line-height: 24px;">Total</td>
|
|
189
218
|
<td></td>
|
|
190
219
|
<td></td>
|
|
191
|
-
<td>{{data.currencyType}}
|
|
220
|
+
<td class="invoicesub">{{data.currencyType}} {{data.total}}</td>
|
|
192
221
|
</tr>
|
|
193
222
|
<tr bgcolor="#ffffff" style="border:none;margin-top:0px;">
|
|
194
|
-
<td style="padding-left:30px;">Discount</td>
|
|
223
|
+
<td class="invoicesub" style="padding-left:30px; line-height: 24px;">Discount</td>
|
|
195
224
|
<td></td>
|
|
196
225
|
<td></td>
|
|
197
|
-
<td>{{data.discount}}%</td>
|
|
226
|
+
<td class="invoicesub">{{data.discount}}%</td>
|
|
198
227
|
</tr>
|
|
199
228
|
<tr>
|
|
200
|
-
<td align="left" bgcolor="#ffffff"
|
|
229
|
+
<td colspan="4" align="left" bgcolor="#ffffff"
|
|
201
230
|
style="padding-left: 30px;padding-right: 24px; font-size: 14px; line-height: 24px;">
|
|
202
|
-
<p class="
|
|
203
|
-
style="width: 624px;height: 0px;border: 1px solid #CBD5E1;flex: none;order: 1;flex-grow: 0;">
|
|
231
|
+
<p class="" style="border: 1px solid #EAECF0;">
|
|
204
232
|
</p>
|
|
205
233
|
</td>
|
|
206
234
|
</tr>
|
|
207
|
-
<tr bgcolor="#ffffff"
|
|
208
|
-
style="
|
|
209
|
-
<td style="padding-left:30px;">Final Value</td>
|
|
235
|
+
<tr bgcolor="#ffffff" style="border:none;margin-top:10px;">
|
|
236
|
+
<td class="invoicesub" style="padding-left:30px; ">Final Value</td>
|
|
210
237
|
<td></td>
|
|
211
238
|
<td></td>
|
|
212
|
-
<td>{{data.currencyType}} {{data.total}}</td>
|
|
239
|
+
<td class="invoicesub">{{data.currencyType}} {{data.total}}</td>
|
|
213
240
|
</tr>
|
|
214
241
|
</table>
|
|
215
242
|
</td>
|
|
@@ -385,6 +385,30 @@
|
|
|
385
385
|
transform-origin: 0 0;
|
|
386
386
|
transform: rotate(0deg) scale(1, 1);
|
|
387
387
|
}
|
|
388
|
+
.invoicedescription {
|
|
389
|
+
/* width:300px;
|
|
390
|
+
padding-left:30px; */
|
|
391
|
+
color: #667085 !important
|
|
392
|
+
}
|
|
393
|
+
.productstext {
|
|
394
|
+
font-size: 16px !important;
|
|
395
|
+
font-weight: 500 !important;
|
|
396
|
+
text-align: left;
|
|
397
|
+
color: #475467 !important;
|
|
398
|
+
/* border-bottom:1px solid #f0ecea !important; */
|
|
399
|
+
line-height: 24px !important;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.invoicesub {
|
|
403
|
+
/* font-family: 'Inter'; */
|
|
404
|
+
color: #667085 !important;
|
|
405
|
+
font-size: 16px;
|
|
406
|
+
font-weight: 600;
|
|
407
|
+
line-height: 24px;
|
|
408
|
+
text-align: left;
|
|
409
|
+
|
|
410
|
+
}
|
|
411
|
+
|
|
388
412
|
</style>
|
|
389
413
|
|
|
390
414
|
</head>
|
|
@@ -441,7 +465,7 @@
|
|
|
441
465
|
</tr> -->
|
|
442
466
|
<tr>
|
|
443
467
|
<td align="left" bgcolor="#ffffff"
|
|
444
|
-
style="padding-left: 27px;padding-right: 24px;padding-top:10px; font-size: 16px; line-height: 24px;font-weight:400;color:#384860">
|
|
468
|
+
style="padding-left: 27px;padding-right: 24px;padding-top:10px; font-size: 16px; line-height: 24px;font-weight:400;color:#384860; padding-bottom: 20px;">
|
|
445
469
|
<p style="margin: 0;">"Notice: Subscription price revised. Please review updated
|
|
446
470
|
pricing details. We appreciate your continued support. Thank you for
|
|
447
471
|
understanding."
|
|
@@ -452,61 +476,70 @@
|
|
|
452
476
|
<td class="o_bg-white o_px-md o_py-xl o_xs-py-md"
|
|
453
477
|
style="background-color: #ffffff;padding-left: 30px;padding-right: 24px;padding-bottom: 10px;">
|
|
454
478
|
<table style="max-width: 600px;border:none" border="0" cellpadding="0" cellspacing="0" width="100%">
|
|
455
|
-
<tr style="border:
|
|
456
|
-
<th style="width:300px;">Description</th>
|
|
457
|
-
<th style="width:120px;">Price</th>
|
|
458
|
-
<th style="width:120px;">Stores</th>
|
|
459
|
-
<th style="width:120px;">Total Amount</th>
|
|
479
|
+
<tr bgcolor="#F9FAFB" style="border-bottom:1px solid #f0ecea;height:40px;;margin-top:10px;text-align:left">
|
|
480
|
+
<th class="invoicedescription" style="width:300px;">Description</th>
|
|
481
|
+
<th class="invoicedescription" style="width:120px;">Price</th>
|
|
482
|
+
<th class="invoicedescription" style="width:120px;">Stores</th>
|
|
483
|
+
<th class="invoicedescription" style="width:120px;">Total Amount</th>
|
|
484
|
+
</tr>
|
|
485
|
+
<tr style="border:none;">
|
|
486
|
+
<td colspan="4" align="left" bgcolor="#ffffff" style="font-size: 14px; line-height: 24px;">
|
|
487
|
+
<p class="" style="border: 0px solid #EAECF0;">
|
|
488
|
+
</p>
|
|
489
|
+
</td>
|
|
460
490
|
</tr>
|
|
461
491
|
{{#each data.products}}
|
|
462
492
|
<tr style="border:none;margin-top:10px;">
|
|
463
|
-
<td>{{product.product}}</td>
|
|
464
|
-
<td
|
|
465
|
-
<td>{{count}}</td>
|
|
466
|
-
<td
|
|
493
|
+
<td class="productstext">{{product.product}}</td>
|
|
494
|
+
<td class="productstext">{{../data.currencyType}} {{basePrice}}</td>
|
|
495
|
+
<td class="productstext">{{count}}</td>
|
|
496
|
+
<td class="productstext">{{../data.currencyType}} {{price}}</td>
|
|
467
497
|
</tr>
|
|
468
498
|
{{/each}}
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
<td
|
|
472
|
-
|
|
473
|
-
|
|
499
|
+
|
|
500
|
+
<tr>
|
|
501
|
+
<td colspan="4" align="left" bgcolor="#ffffff"
|
|
502
|
+
style="font-size: 14px; line-height: 24px;">
|
|
503
|
+
<p class="" style="border: 1px solid #EAECF0;">
|
|
504
|
+
</p>
|
|
505
|
+
</td>
|
|
474
506
|
</tr>
|
|
475
|
-
<tr style="border:none;
|
|
476
|
-
<td>Sub Total</td>
|
|
507
|
+
<tr style="border:none;margin-top:10px;">
|
|
508
|
+
<td class="invoicesub">Sub Total</td>
|
|
477
509
|
<td></td>
|
|
478
510
|
<td></td>
|
|
479
|
-
<td
|
|
511
|
+
<td class="invoicesub">{{data.currencyType}} {{data.amount}}</td>
|
|
480
512
|
</tr>
|
|
481
513
|
<tr style="border:none;margin-top:10px;">
|
|
482
|
-
<td>IGST</td>
|
|
514
|
+
<td class="invoicesub">IGST</td>
|
|
483
515
|
<td></td>
|
|
484
516
|
<td></td>
|
|
485
|
-
<td>0%</td>
|
|
517
|
+
<td class="invoicesub">0%</td>
|
|
486
518
|
</tr>
|
|
487
519
|
<tr style="border:none;margin-top:10px;">
|
|
488
|
-
<td>Total</td>
|
|
520
|
+
<td class="invoicesub">Total</td>
|
|
489
521
|
<td></td>
|
|
490
522
|
<td></td>
|
|
491
|
-
<td
|
|
523
|
+
<td class="invoicesub">{{data.currencyType}} {{data.total}}</td>
|
|
492
524
|
</tr>
|
|
493
525
|
<tr style="border:none;margin-top:10px;">
|
|
494
|
-
<td>Discount</td>
|
|
526
|
+
<td class="invoicesub">Discount</td>
|
|
495
527
|
<td></td>
|
|
496
528
|
<td></td>
|
|
497
|
-
<td>{{data.discount}}</td>
|
|
529
|
+
<td class="invoicesub">{{data.discount}}</td>
|
|
498
530
|
</tr>
|
|
499
|
-
<tr
|
|
500
|
-
<td
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
531
|
+
<tr>
|
|
532
|
+
<td colspan="4" align="left" bgcolor="#ffffff"
|
|
533
|
+
style="font-size: 14px; line-height: 24px;">
|
|
534
|
+
<p class="" style="border: 1px solid #EAECF0;">
|
|
535
|
+
</p>
|
|
536
|
+
</td>
|
|
504
537
|
</tr>
|
|
505
|
-
<tr style="border:none;
|
|
506
|
-
<td>Final Value</td>
|
|
538
|
+
<tr style="border:none;margin-top:10px;">
|
|
539
|
+
<td class="invoicesub">Final Value</td>
|
|
507
540
|
<td></td>
|
|
508
541
|
<td></td>
|
|
509
|
-
<td
|
|
542
|
+
<td class="invoicesub">{{data.currencyType}} {{data.total}}</td>
|
|
510
543
|
</tr>
|
|
511
544
|
</table>
|
|
512
545
|
</td>
|
|
@@ -514,41 +547,43 @@
|
|
|
514
547
|
</table>
|
|
515
548
|
</td>
|
|
516
549
|
</tr>
|
|
517
|
-
</table>
|
|
518
|
-
</td>
|
|
519
|
-
</tr>
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
<tr>
|
|
523
|
-
<td align="center" bgcolor="#dbe5ea" style="padding: 0px 15px 32px 15px;">
|
|
524
|
-
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 648px;">
|
|
525
|
-
<tr>
|
|
526
|
-
<td class="o_bg-white o_px-md o_py-xl o_xs-py-md"
|
|
527
|
-
style="background-color: #ffffff;padding-left: 35px;padding-right: 24px;padding-top:10px">
|
|
528
|
-
<div class="o_col-6s o_sans o_text-md o_text-light o_center"
|
|
529
|
-
style="margin-top: 35px;margin-bottom: 0px;font-size: 12px;color: #202B3C;font-style: normal;font-weight: 400;font-size: 12px;line-height: 150%;">
|
|
530
|
-
<p>
|
|
531
|
-
If you'd rather not receive this kind of email, Don’t want any more emails from
|
|
532
|
-
TangoEye? <a
|
|
533
|
-
style="color: var(--Primary-Base, #00A3FF); text-decoration-line: underline; letter-spacing: 0.2px;">Unsubscribe.</a>
|
|
534
|
-
</p>
|
|
535
|
-
</div>
|
|
536
|
-
</td>
|
|
537
|
-
</tr>
|
|
538
550
|
<tr>
|
|
539
|
-
<td
|
|
540
|
-
style="
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
551
|
+
<td align="center" bgcolor="#dbe5ea" style="padding:0 0px 32px 0px;">
|
|
552
|
+
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 648px;">
|
|
553
|
+
<tr>
|
|
554
|
+
<td class="o_bg-white o_px-md o_py-xl o_xs-py-md"
|
|
555
|
+
style="background-color: #ffffff;padding-left: 35px;padding-right: 24px;padding-top:10px">
|
|
556
|
+
<div class="o_col-6s o_sans o_text-md o_text-light o_center"
|
|
557
|
+
style="margin-top: 35px;margin-bottom: 0px;font-size: 12px;color: #202B3C;font-style: normal;font-weight: 400;font-size: 12px;line-height: 150%;">
|
|
558
|
+
<p>
|
|
559
|
+
If you'd rather not receive this kind of email, Don’t want any more emails from
|
|
560
|
+
TangoEye? <a
|
|
561
|
+
style="color: var(--Primary-Base, #00A3FF); text-decoration-line: underline; letter-spacing: 0.2px;">Unsubscribe.</a>
|
|
562
|
+
</p>
|
|
563
|
+
</div>
|
|
564
|
+
</td>
|
|
565
|
+
</tr>
|
|
566
|
+
<tr>
|
|
567
|
+
<td class="o_bg-white o_px-md o_py-xl o_xs-py-md"
|
|
568
|
+
style="background-color: #ffffff;padding:0px 24px 15px 27px">
|
|
569
|
+
<div class="o_col-6s o_sans o_text-md o_text-light o_center"
|
|
570
|
+
style="margin-top: 0px;margin-bottom: 0px;font-size: 12px;color: #202B3C;font-style: normal;font-weight: 400;font-size: 12px;line-height: 150%; padding-left: 7px;">
|
|
571
|
+
<p>
|
|
572
|
+
© Tango Eye. All rights reserved.</p>
|
|
573
|
+
</div>
|
|
574
|
+
</td>
|
|
575
|
+
</tr>
|
|
576
|
+
</table>
|
|
546
577
|
</td>
|
|
547
578
|
</tr>
|
|
548
579
|
</table>
|
|
549
580
|
</td>
|
|
581
|
+
|
|
550
582
|
</tr>
|
|
551
583
|
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
|
|
552
587
|
</table>
|
|
553
588
|
|
|
554
589
|
</body>
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
style="margin-top: 0px;margin-bottom: 0px;font-size: 24px;line-height: 28px;color: #82899a;">
|
|
122
122
|
<span class="o_heading o_text-dark o_mb-xxs"
|
|
123
123
|
style="font-weight: 700;margin-top: 0px;margin-bottom: 4px;color: #121A26;line-height: 39px;">
|
|
124
|
-
Unlock Premium Features - Your
|
|
124
|
+
Unlock Premium Features - Your {{data.product}} Trial Has Ended</span>
|
|
125
125
|
</div>
|
|
126
126
|
</td>
|
|
127
127
|
</tr>
|