tango-app-api-payment-subscription 3.0.25-dev → 3.0.27-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 +2 -2
- package/src/controllers/paymentSubscription.controllers.js +246 -5
- package/src/docs/payment.docs.js +553 -3
- package/src/dtos/validation.dtos.js +29 -0
- package/src/hbs/invoicePdf.hbs +106 -80
- package/src/hbs/revisedPriceEmail.hbs +1 -1
- package/src/hbs/trialCreditNoteEmail.hbs +1 -1
- package/src/hbs/trialExpiredEmail.hbs +5 -5
- package/src/hbs/trialExtentionEmail.hbs +1 -1
- package/src/hbs/trialInitiateEmail.hbs +5 -5
- package/src/hbs/trialReminderEmail.hbs +5 -5
- package/src/hbs/trialSubscriptionEmail.hbs +1 -1
- package/src/hbs/trialUnsubscribeEmail.hbs +1 -1
- package/src/routes/paymentSubscription.routes.js +5 -5
- package/src/services/dailyPrice.service.js +22 -0
- package/src/utils/validations/client.validation.js +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tango-app-api-payment-subscription",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.27-dev",
|
|
4
4
|
"description": "paymentSubscription",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"nodemon": "^3.1.0",
|
|
26
26
|
"pdfmake": "^0.2.10",
|
|
27
27
|
"swagger-ui-express": "^5.0.0",
|
|
28
|
-
"tango-api-schema": "^2.0.
|
|
28
|
+
"tango-api-schema": "^2.0.78",
|
|
29
29
|
"tango-app-api-middleware": "^1.0.49-dev",
|
|
30
30
|
"winston": "^3.12.0",
|
|
31
31
|
"winston-daily-rotate-file": "^5.0.0"
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
/* eslint-disable new-cap */
|
|
3
3
|
import { logger, download, sendEmailWithSES, appConfig, insertOpenSearchData } from 'tango-app-api-middleware';
|
|
4
4
|
import * as paymentService from '../services/clientPayment.services.js';
|
|
5
|
+
import * as basePriceService from '../services/basePrice.service.js';
|
|
5
6
|
import * as storeService from '../services/store.service.js';
|
|
6
7
|
import * as basePricingService from '../services/basePrice.service.js';
|
|
7
8
|
import * as clientRequestService from '../services/clientRequest.service.js';
|
|
8
9
|
import * as invoiceService from '../services/invoice.service.js';
|
|
9
10
|
import * as userService from '../services/user.service.js';
|
|
11
|
+
import * as dailyPriceService from '../services/dailyPrice.service.js';
|
|
10
12
|
import dayjs from 'dayjs';
|
|
11
13
|
import Handlebars from 'handlebars';
|
|
12
14
|
import fs from 'fs';
|
|
@@ -73,7 +75,7 @@ export const clientBillingSubscriptionInfo = async ( req, res, next ) => {
|
|
|
73
75
|
price: 1,
|
|
74
76
|
priceType: 1,
|
|
75
77
|
virtualAccount: 1,
|
|
76
|
-
|
|
78
|
+
paymentInvoice: 1,
|
|
77
79
|
},
|
|
78
80
|
},
|
|
79
81
|
{
|
|
@@ -199,7 +201,8 @@ export const clientBillingSubscriptionInfo = async ( req, res, next ) => {
|
|
|
199
201
|
currentPlanInfo.expiredProducts = expiredProducts || '--';
|
|
200
202
|
currentPlanInfo.product = activeProducts || '--';
|
|
201
203
|
currentPlanInfo.pendingClientRequest = getPCR;
|
|
202
|
-
|
|
204
|
+
currentPlanInfo.currencyType = clientInfo[0].paymentInvoice.currencyType;
|
|
205
|
+
currentPlanInfo.dollarPrice = await convertINRtoUSD( clientInfo[0].price );
|
|
203
206
|
let data = {
|
|
204
207
|
_id: clientInfo[0]._id,
|
|
205
208
|
clientId: clientInfo[0].clientId,
|
|
@@ -472,6 +475,8 @@ export const updateSubscription = async ( req, res ) => {
|
|
|
472
475
|
await storeService.updateMany( { clientId: req.params.clientId, status: 'active' }, { product: storeProduct } );
|
|
473
476
|
|
|
474
477
|
if ( result.modifiedCount ) {
|
|
478
|
+
req.body.clientId = req.params.clientId;
|
|
479
|
+
updatePricing( req, res, true );
|
|
475
480
|
return res.sendSuccess( { message: 'Subscription Updated Successfully' } );
|
|
476
481
|
} else {
|
|
477
482
|
return res.sendError( 'Something went wrong', 500 );
|
|
@@ -939,6 +944,7 @@ export const productSubscribe = async ( req, res ) => {
|
|
|
939
944
|
if ( productList.includes( item.name ) && item.type =='unsubscribe' ) {
|
|
940
945
|
// let findIndex = product.findIndex( ( product ) => product.productName );
|
|
941
946
|
// product.splice( findIndex, 1 );
|
|
947
|
+
// let requestDetails = await clientRequestService.findOne({});
|
|
942
948
|
await storeService.addremoveElement( { clientId: clientInfo.clientId, status: 'active', product: { $in: item.name } }, { $pull: { product: item.name } } );
|
|
943
949
|
}
|
|
944
950
|
if ( !productList.includes( item.name ) && [ 'trial', 'subscription' ].includes( item.type ) ) {
|
|
@@ -1627,6 +1633,11 @@ export const pricingListUpdate = async ( req, res ) => {
|
|
|
1627
1633
|
getPriceInfo.step = req.body.products;
|
|
1628
1634
|
}
|
|
1629
1635
|
getPriceInfo.save().then( async () => {
|
|
1636
|
+
let clientDetails = await paymentService.findOne( { clientId: req.body.clientId }, { priceType: 1 } );
|
|
1637
|
+
clientDetails.priceType = req.body.type;
|
|
1638
|
+
|
|
1639
|
+
clientDetails.save();
|
|
1640
|
+
|
|
1630
1641
|
let userDetails= await userService.findOne( { clientId: req.body.clientId, role: 'superadmin' } );
|
|
1631
1642
|
if ( userDetails ) {
|
|
1632
1643
|
const templateHtml = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/revisedPriceEmail.hbs', 'utf8' );
|
|
@@ -1670,6 +1681,7 @@ export const pricingListUpdate = async ( req, res ) => {
|
|
|
1670
1681
|
|
|
1671
1682
|
async function updatePricing( req, res, update ) {
|
|
1672
1683
|
let baseProduct = await basePricingService.findOne( { clientId: { $exists: false } }, { basePricing: 1 } );
|
|
1684
|
+
let getPriceInfo = await basePricingService.findOne( { clientId: { $exists: true }, clientId: req.body.clientId }, { standard: 1, step: 1 } );
|
|
1673
1685
|
let clientDetails = await paymentService.findOne( { clientId: req.body.clientId } );
|
|
1674
1686
|
if ( clientDetails ) {
|
|
1675
1687
|
let products = clientDetails.planDetails.product.map( ( item ) => item.productName );
|
|
@@ -1701,7 +1713,7 @@ async function updatePricing( req, res, update ) {
|
|
|
1701
1713
|
step: stepList,
|
|
1702
1714
|
clientId: req.body.clientId,
|
|
1703
1715
|
};
|
|
1704
|
-
if ( !
|
|
1716
|
+
if ( !getPriceInfo ) {
|
|
1705
1717
|
await basePricingService.create( data );
|
|
1706
1718
|
} else {
|
|
1707
1719
|
delete data.clientId;
|
|
@@ -1788,6 +1800,7 @@ export const unpaidInvoiceList = async ( req, res ) => {
|
|
|
1788
1800
|
if ( !invoiceDetails.length ) {
|
|
1789
1801
|
return res.sendError( 'no data found', 204 );
|
|
1790
1802
|
}
|
|
1803
|
+
|
|
1791
1804
|
return res.sendSuccess( invoiceDetails );
|
|
1792
1805
|
} catch ( e ) {
|
|
1793
1806
|
logger.error( { error: e, function: 'unpaidInvoiceList' } );
|
|
@@ -1930,9 +1943,32 @@ export const getExpiredClients = async ( req, res ) => {
|
|
|
1930
1943
|
|
|
1931
1944
|
export const invoiceDownload = async ( req, res ) => {
|
|
1932
1945
|
try {
|
|
1946
|
+
let invoiceDetails;
|
|
1947
|
+
let invoiceInfo = await invoiceService.findOne( { _id: req.params.invoiceId } );
|
|
1948
|
+
if ( invoiceInfo ) {
|
|
1949
|
+
let clientDetails = await paymentService.findOne( { clientId: invoiceInfo.clientId } );
|
|
1950
|
+
let amount = 0;
|
|
1951
|
+
invoiceInfo.products.forEach( ( item ) => {
|
|
1952
|
+
amount = amount + item.price;
|
|
1953
|
+
} );
|
|
1954
|
+
let invoiceDate= dayjs( invoiceInfo.createdAt ).format( 'DD MMM, YYYY' );
|
|
1955
|
+
let days = clientDetails?.paymentInvoice?.extendPaymentPeriodDays || 10;
|
|
1956
|
+
let dueDate = invoiceInfo?.dueDate ? dayjs( invoiceInfo?.dueDate ).format( 'DD MMM, YYYY' ) : dayjs().add( days, 'days' ).format( 'DD MMM, YYYY' );
|
|
1957
|
+
invoiceDetails = {
|
|
1958
|
+
...invoiceInfo._doc,
|
|
1959
|
+
clientName: clientDetails.clientName,
|
|
1960
|
+
extendDays: clientDetails.paymentInvoice.extendPaymentPeriodDays,
|
|
1961
|
+
address: clientDetails.billingDetails.billingAddress,
|
|
1962
|
+
amount: amount,
|
|
1963
|
+
// total: ( amount + ( parseFloat( amount ) * 0.19 ) ).toFixed( 2 ),
|
|
1964
|
+
total: amount.toFixed( 2 ),
|
|
1965
|
+
invoiceDate,
|
|
1966
|
+
dueDate,
|
|
1967
|
+
};
|
|
1968
|
+
}
|
|
1933
1969
|
const templateHtml = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/invoicePdf.hbs', 'utf8' );
|
|
1934
1970
|
const template = Handlebars.compile( templateHtml );
|
|
1935
|
-
const html = template( { data:
|
|
1971
|
+
const html = template( { data: invoiceDetails } );
|
|
1936
1972
|
let fonts = {
|
|
1937
1973
|
Helvetica: {
|
|
1938
1974
|
normal: 'Helvetica',
|
|
@@ -1945,8 +1981,8 @@ export const invoiceDownload = async ( req, res ) => {
|
|
|
1945
1981
|
|
|
1946
1982
|
let { window } = new JSDOM( '' );
|
|
1947
1983
|
const htmlTemplate = htmlToPdfmake( html, { window: window, tableAutoSize: true } );
|
|
1948
|
-
|
|
1949
1984
|
const docDefinition = {
|
|
1985
|
+
pageMargins: [ 40, 0, 40, 40 ],
|
|
1950
1986
|
content: htmlTemplate,
|
|
1951
1987
|
defaultStyle: {
|
|
1952
1988
|
font: 'Helvetica',
|
|
@@ -1973,12 +2009,25 @@ export const updateInvoiceStatus = async ( req, res ) => {
|
|
|
1973
2009
|
return res.sendError( 'no data found', 204 );
|
|
1974
2010
|
}
|
|
1975
2011
|
invoiceDetails.status = req.body?.status || 'Payment Received';
|
|
2012
|
+
invoiceDetails.paymentType = req.body?.paymentType;
|
|
2013
|
+
invoiceDetails.paymentReferenceId = req.body?.paymentReferenceId || '';
|
|
1976
2014
|
invoiceDetails.save().then( async () => {
|
|
1977
2015
|
let clientInfo = await paymentService.findOne( { clientId: invoiceDetails.clientId } );
|
|
1978
2016
|
if ( clientInfo ) {
|
|
1979
2017
|
clientInfo.planDetails.paymentStatus = 'paid';
|
|
1980
2018
|
clientInfo.save();
|
|
1981
2019
|
}
|
|
2020
|
+
const logObj = {
|
|
2021
|
+
clientId: req.body.clientId,
|
|
2022
|
+
userName: req.user?.userName,
|
|
2023
|
+
email: req.user?.email,
|
|
2024
|
+
date: new Date(),
|
|
2025
|
+
logType: 'invoice',
|
|
2026
|
+
logSubType: 'Invoice Status Updated to Paid',
|
|
2027
|
+
changes: [ 'amount', 'paymentType', 'status' ],
|
|
2028
|
+
eventType: 'update',
|
|
2029
|
+
};
|
|
2030
|
+
insertOpenSearchData( 'tango-retail-activity-logs', logObj );
|
|
1982
2031
|
return res.sendSuccess( 'Invoice updated Successfully' );
|
|
1983
2032
|
} );
|
|
1984
2033
|
} catch ( e ) {
|
|
@@ -2023,3 +2072,195 @@ export const invoiceCreate = async ( req, res ) => {
|
|
|
2023
2072
|
return res.sendError( e, 500 );
|
|
2024
2073
|
}
|
|
2025
2074
|
};
|
|
2075
|
+
|
|
2076
|
+
export const dailyPricingInsert = async ( req, res ) => {
|
|
2077
|
+
try {
|
|
2078
|
+
let requestData = req.body;
|
|
2079
|
+
let requestClient = requestData.clientId;
|
|
2080
|
+
if ( requestData.clientId && requestClient.length > 0 ) {
|
|
2081
|
+
for ( let clientIndex = 0; clientIndex < requestClient.length; clientIndex++ ) {
|
|
2082
|
+
let getClient = await paymentService.findOne( { clientId: requestClient[clientIndex], status: 'active' } );
|
|
2083
|
+
if ( getClient ) {
|
|
2084
|
+
let getBaseprice = await basePriceService.findOne( { clientId: requestClient[clientIndex] } );
|
|
2085
|
+
let getStore = await storeService.find( { clientId: requestClient[clientIndex], status: 'active' } );
|
|
2086
|
+
if ( getStore.length ) {
|
|
2087
|
+
let storeList = [];
|
|
2088
|
+
for ( let storeIndex = 0; storeIndex < getStore.length; storeIndex++ ) {
|
|
2089
|
+
let productList = [];
|
|
2090
|
+
let priceDetails = getClient.priceType == 'standard' ? getBaseprice.standard : getBaseprice.step;
|
|
2091
|
+
for ( let storeProductIndex = 0; storeProductIndex < getStore[storeIndex].product.length; storeProductIndex++ ) {
|
|
2092
|
+
let productDetails;
|
|
2093
|
+
if ( getClient.priceType == 'standard' ) {
|
|
2094
|
+
productDetails = priceDetails.find( ( item ) => item.productName == getStore[storeIndex].product[storeProductIndex] );
|
|
2095
|
+
} else {
|
|
2096
|
+
productDetails = priceDetails.find( ( item ) => {
|
|
2097
|
+
let range = item.storeRange.split( '-' );
|
|
2098
|
+
if ( parseInt( range[0] ) <= ( storeIndex + 1 ) && parseInt( range[1] ) >= ( storeIndex + 1 ) ) {
|
|
2099
|
+
return ( item.productName == getStore[storeIndex].product[storeProductIndex] && parseInt( range[0] ) <= ( storeIndex + 1 ) && parseInt( range[1] ) >= ( storeIndex + 1 ) );
|
|
2100
|
+
}
|
|
2101
|
+
} );
|
|
2102
|
+
if ( !productDetails ) {
|
|
2103
|
+
let stepProductDetails = priceDetails.filter( ( item ) => item.productName == getStore[storeIndex].product[storeProductIndex] );
|
|
2104
|
+
productDetails = stepProductDetails[stepProductDetails.length -1];
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
let productStatus = getClient.planDetails.product.find( ( item ) => item.productName == getStore[storeIndex].product[storeProductIndex] );
|
|
2108
|
+
if ( productDetails ) {
|
|
2109
|
+
let newObject = {
|
|
2110
|
+
productName: productDetails.productName,
|
|
2111
|
+
status: productStatus ? productStatus.status : '',
|
|
2112
|
+
price: productStatus ? [ 'trial', 'free' ].includes( productStatus.status ) ? 0 : productDetails.negotiatePrice : 0,
|
|
2113
|
+
featureStoreCount: storeIndex+1,
|
|
2114
|
+
basePrice: productDetails.negotiatePrice,
|
|
2115
|
+
...( getClient.priceType == 'step' ? { storeRange: productDetails.storeRange } : { storeRange: 'standard' } ),
|
|
2116
|
+
};
|
|
2117
|
+
productList.push( newObject );
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
storeList.push(
|
|
2121
|
+
{
|
|
2122
|
+
storeId: getStore[storeIndex].storeId,
|
|
2123
|
+
products: productList,
|
|
2124
|
+
},
|
|
2125
|
+
);
|
|
2126
|
+
if ( storeIndex == getStore.length-1 ) {
|
|
2127
|
+
let params = {
|
|
2128
|
+
clientId: requestClient[clientIndex],
|
|
2129
|
+
stores: storeList,
|
|
2130
|
+
dateISO: new Date( requestData.date ),
|
|
2131
|
+
dateString: dayjs( requestData.date ).format( 'YYYY-MM-DD' ),
|
|
2132
|
+
};
|
|
2133
|
+
await dailyPriceService.create( params );
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
if ( clientIndex == requestClient.length-1 ) {
|
|
2139
|
+
return res.sendSuccess( 'Price Details Inserted Successfully' );
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
} catch ( e ) {
|
|
2144
|
+
logger.error( { error: e, function: 'invoiceCreate' } );
|
|
2145
|
+
return res.sendError( e, 500 );
|
|
2146
|
+
}
|
|
2147
|
+
};
|
|
2148
|
+
|
|
2149
|
+
export const invoiceGenerate = async ( req, res ) => {
|
|
2150
|
+
try {
|
|
2151
|
+
let requestData = req.body;
|
|
2152
|
+
let requestClient = requestData.clientId;
|
|
2153
|
+
let start = new Date( requestData.fromDate );
|
|
2154
|
+
let end = new Date( requestData.toDate );
|
|
2155
|
+
let userTimezoneOffset = end.getTimezoneOffset() * 60000;
|
|
2156
|
+
end = new Date( end.getTime() - userTimezoneOffset );
|
|
2157
|
+
end.setUTCHours( 23, 59, 59, 59 );
|
|
2158
|
+
for ( let clientIndex = 0; clientIndex < requestClient.length; clientIndex++ ) {
|
|
2159
|
+
let getClient = await paymentService.findOne( { clientId: requestClient[clientIndex], status: 'active' } );
|
|
2160
|
+
if ( getClient ) {
|
|
2161
|
+
let query = [
|
|
2162
|
+
{
|
|
2163
|
+
$match: {
|
|
2164
|
+
$and: [
|
|
2165
|
+
{ clientId: requestClient[clientIndex] },
|
|
2166
|
+
{ dateISO: { $gte: start, $lte: end } },
|
|
2167
|
+
],
|
|
2168
|
+
},
|
|
2169
|
+
},
|
|
2170
|
+
{
|
|
2171
|
+
$unwind: '$stores',
|
|
2172
|
+
},
|
|
2173
|
+
{
|
|
2174
|
+
$unwind: '$stores.products',
|
|
2175
|
+
},
|
|
2176
|
+
{
|
|
2177
|
+
$group: {
|
|
2178
|
+
_id: { product: '$stores.products.productName', storeRange: '$stores.products.storeRange' },
|
|
2179
|
+
price: { $sum: '$stores.products.price' },
|
|
2180
|
+
count: { $sum: 1 },
|
|
2181
|
+
basePrice: { $first: '$stores.products.basePrice' },
|
|
2182
|
+
},
|
|
2183
|
+
},
|
|
2184
|
+
{
|
|
2185
|
+
$project: {
|
|
2186
|
+
_id: 0,
|
|
2187
|
+
product: '$_id',
|
|
2188
|
+
price: 1,
|
|
2189
|
+
count: 1,
|
|
2190
|
+
basePrice: 1,
|
|
2191
|
+
},
|
|
2192
|
+
},
|
|
2193
|
+
];
|
|
2194
|
+
// {
|
|
2195
|
+
// $facet: {
|
|
2196
|
+
// data: [
|
|
2197
|
+
// {
|
|
2198
|
+
// $unwind: '$stores',
|
|
2199
|
+
// },
|
|
2200
|
+
// {
|
|
2201
|
+
// $unwind: '$stores.products',
|
|
2202
|
+
// },
|
|
2203
|
+
// {
|
|
2204
|
+
// $group: {
|
|
2205
|
+
// _id: { product: '$stores.products.productName', storeRange: '$stores.products.storeRange' },
|
|
2206
|
+
// price: { $sum: '$stores.products.price' },
|
|
2207
|
+
// },
|
|
2208
|
+
// },
|
|
2209
|
+
// {
|
|
2210
|
+
// $project: {
|
|
2211
|
+
// _id: 0,
|
|
2212
|
+
// product: '$_id',
|
|
2213
|
+
// price: 1,
|
|
2214
|
+
// },
|
|
2215
|
+
// },
|
|
2216
|
+
// ],
|
|
2217
|
+
// count: [
|
|
2218
|
+
// {
|
|
2219
|
+
// $unwind: '$stores',
|
|
2220
|
+
// },
|
|
2221
|
+
// { $sort: { 'stores.products._id': -1 } },
|
|
2222
|
+
// { $project: { lastElement: { $arrayElemAt: [ '$stores.products', -1 ] } } },
|
|
2223
|
+
// { $project: {
|
|
2224
|
+
// count: '$lastElement.featureStoreCount',
|
|
2225
|
+
// },
|
|
2226
|
+
// },
|
|
2227
|
+
// ],
|
|
2228
|
+
// },
|
|
2229
|
+
// },
|
|
2230
|
+
let invoiceDetails = await dailyPriceService.aggregate( query );
|
|
2231
|
+
if ( !invoiceDetails.length ) {
|
|
2232
|
+
return res.sendError( 'no data found', 204 );
|
|
2233
|
+
}
|
|
2234
|
+
let amount = 0;
|
|
2235
|
+
invoiceDetails.forEach( ( item ) => {
|
|
2236
|
+
amount = item.price + amount;
|
|
2237
|
+
} );
|
|
2238
|
+
let data = {
|
|
2239
|
+
invoice: `invoice#${requestClient[clientIndex]}-${dayjs().format( 'MMM YYYY' )}`,
|
|
2240
|
+
products: invoiceDetails,
|
|
2241
|
+
status: 'pending',
|
|
2242
|
+
amount: amount,
|
|
2243
|
+
clientId: requestClient[clientIndex],
|
|
2244
|
+
paymentMethod: getClient?.paymentInvoice?.paymentType || 'online',
|
|
2245
|
+
billingDate: new Date(),
|
|
2246
|
+
};
|
|
2247
|
+
|
|
2248
|
+
await invoiceService.create( data );
|
|
2249
|
+
if ( clientIndex == requestClient.length-1 ) {
|
|
2250
|
+
return res.sendSuccess( 'invocie Generated Succesfully' );
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
} catch ( e ) {
|
|
2255
|
+
logger.error( { error: e, function: 'invoiceCreate' } );
|
|
2256
|
+
return res.sendError( e, 500 );
|
|
2257
|
+
}
|
|
2258
|
+
};
|
|
2259
|
+
|
|
2260
|
+
function convertINRtoUSD( amountINR ) {
|
|
2261
|
+
// Current exchange rate (1 INR = 0.012 USD)
|
|
2262
|
+
const exchangeRate = 0.012;
|
|
2263
|
+
// Convert INR to USD
|
|
2264
|
+
const amountUSD = amountINR * exchangeRate;
|
|
2265
|
+
return amountUSD;
|
|
2266
|
+
}
|