tango-app-api-analysis-traffic 3.1.0-alpha.8 → 3.3.1-alpha-1-1
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/index.js +1 -2
- package/package.json +2 -5
- package/src/controllers/tangoTrafficV1.controllers.js +29 -1
- package/src/controllers/tangoTrafficV3.controllers.js +83 -25
- package/src/dtos/nob.dtos.js +9 -4
- package/src/dtos/validation.dtos.js +3 -20
- package/src/routes/traffic.routes.js +3 -1
- package/src/controllers/emailers.controllers.js +0 -1728
- package/src/controllers/handlebars.js +0 -23
- package/src/hbs/dailyMailerMultiple.hbs +0 -1104
- package/src/hbs/dailyMailerSingle.hbs +0 -1026
- package/src/hbs/weeklyMailerMultiple.hbs +0 -1018
- package/src/hbs/weeklyMailerSingle.hbs +0 -871
- package/src/routes/emailers.js +0 -20
- package/src/services/user.service.js +0 -67
package/index.js
CHANGED
|
@@ -4,7 +4,6 @@ import { analysisTrafficRouter } from './src/routes/traffic.routes.js';
|
|
|
4
4
|
import { mobileTrafficAnalysisRouter } from './src/routes/mobileTraffic.routes.js';
|
|
5
5
|
import { nobDocs } from './src/docs/nob.docs.js';
|
|
6
6
|
import nobRouter from './src/routes/nob.routes.js';
|
|
7
|
-
import emailersRouter from './src/routes/emailers.js';
|
|
8
7
|
|
|
9
|
-
export { analysisTrafficRouter, mobileTrafficAnalysisRouter, nobDocs, nobRouter
|
|
8
|
+
export { analysisTrafficRouter, mobileTrafficAnalysisRouter, nobDocs, nobRouter };
|
|
10
9
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tango-app-api-analysis-traffic",
|
|
3
|
-
"version": "3.1
|
|
3
|
+
"version": "3.3.1-alpha-1-1",
|
|
4
4
|
"description": "Traffic Analysis",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -18,16 +18,13 @@
|
|
|
18
18
|
"dotenv": "^16.4.5",
|
|
19
19
|
"express": "^4.19.2",
|
|
20
20
|
"handlebars": "^4.7.8",
|
|
21
|
-
"html-pdf": "^3.0.1",
|
|
22
|
-
"html-pdf-node": "^1.0.8",
|
|
23
21
|
"joi-to-swagger": "^6.2.0",
|
|
24
22
|
"lodash": "^4.17.21",
|
|
25
23
|
"mongodb": "^6.8.0",
|
|
26
24
|
"nodemon": "^3.1.4",
|
|
27
|
-
"puppeteer": "^23.11.1",
|
|
28
25
|
"swagger-ui-express": "^5.0.1",
|
|
29
26
|
"tango-api-schema": "^2.2.7",
|
|
30
|
-
"tango-app-api-middleware": "^3.1.
|
|
27
|
+
"tango-app-api-middleware": "^3.1.55",
|
|
31
28
|
"winston": "^3.13.1",
|
|
32
29
|
"winston-daily-rotate-file": "^5.0.0"
|
|
33
30
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { logger, download, signedUrl } from 'tango-app-api-middleware';
|
|
1
|
+
import { logger, download, signedUrl, getChecklistUsers } from 'tango-app-api-middleware';
|
|
2
2
|
import * as clientService from '../services/clients.services.js';
|
|
3
3
|
import {
|
|
4
4
|
aggregateStore,
|
|
@@ -1070,6 +1070,8 @@ export const headerStoresV2 = async ( req, res ) => {
|
|
|
1070
1070
|
{ storeId: { $in: totalStores } },
|
|
1071
1071
|
{ storeId: { $in: unqueCityStores } },
|
|
1072
1072
|
{ storeId: { $in: unqueGroupStores } },
|
|
1073
|
+
{ 'edge.firstFile': true },
|
|
1074
|
+
{ status: { $eq: 'active' } },
|
|
1073
1075
|
],
|
|
1074
1076
|
},
|
|
1075
1077
|
},
|
|
@@ -1089,6 +1091,8 @@ export const headerStoresV2 = async ( req, res ) => {
|
|
|
1089
1091
|
$and: [
|
|
1090
1092
|
{ storeId: { $in: totalStores } },
|
|
1091
1093
|
{ storeId: { $in: uniqueCityStores } },
|
|
1094
|
+
{ 'edge.firstFile': true },
|
|
1095
|
+
{ status: { $eq: 'active' } },
|
|
1092
1096
|
],
|
|
1093
1097
|
},
|
|
1094
1098
|
},
|
|
@@ -1108,6 +1112,8 @@ export const headerStoresV2 = async ( req, res ) => {
|
|
|
1108
1112
|
$and: [
|
|
1109
1113
|
{ storeId: { $in: totalStores } },
|
|
1110
1114
|
{ storeId: { $in: uniqueclusterStores } },
|
|
1115
|
+
{ 'edge.firstFile': true },
|
|
1116
|
+
{ status: { $eq: 'active' } },
|
|
1111
1117
|
],
|
|
1112
1118
|
},
|
|
1113
1119
|
},
|
|
@@ -1126,6 +1132,8 @@ export const headerStoresV2 = async ( req, res ) => {
|
|
|
1126
1132
|
$match: {
|
|
1127
1133
|
$and: [
|
|
1128
1134
|
{ storeId: { $in: totalStores } },
|
|
1135
|
+
{ 'edge.firstFile': true },
|
|
1136
|
+
{ status: { $eq: 'active' } },
|
|
1129
1137
|
],
|
|
1130
1138
|
},
|
|
1131
1139
|
},
|
|
@@ -1360,6 +1368,7 @@ async function getAssignedAllStores( userClientId ) {
|
|
|
1360
1368
|
$and: [
|
|
1361
1369
|
{ clientId: { $eq: userClientId } },
|
|
1362
1370
|
{ status: { $eq: 'active' } },
|
|
1371
|
+
{ 'edge.firstFile': true },
|
|
1363
1372
|
],
|
|
1364
1373
|
},
|
|
1365
1374
|
},
|
|
@@ -1489,6 +1498,7 @@ async function getLocationStores( userClientId, cityList, req ) {
|
|
|
1489
1498
|
if ( req.body.assignedStores&&req.body.assignedStores.length>0 ) {
|
|
1490
1499
|
filter.push( { storeId: { $in: req.body.assignedStores } } );
|
|
1491
1500
|
}
|
|
1501
|
+
filter.push( { 'edge.firstFile': true }, { status: { $eq: 'active' } } );
|
|
1492
1502
|
|
|
1493
1503
|
let storeQuery = [
|
|
1494
1504
|
{
|
|
@@ -1928,3 +1938,21 @@ export const getStoreMapData = async ( req, res ) => {
|
|
|
1928
1938
|
// }
|
|
1929
1939
|
// let getGEO = await getGeocodedAddress( 12.900260100404893, 80.23384232089138 );
|
|
1930
1940
|
// console.log( 'getGEO =>', getGEO );
|
|
1941
|
+
|
|
1942
|
+
export async function getUserEmails( req, res ) {
|
|
1943
|
+
try {
|
|
1944
|
+
let requestData = req.body;
|
|
1945
|
+
// Get User Based Checklist //
|
|
1946
|
+
let loginUser = { clientId: requestData.clientId, role: req.user.role, userType: req.user.userType, userEmail: req.user.email };
|
|
1947
|
+
let getUserEmails = await getChecklistUsers( loginUser );
|
|
1948
|
+
// End: Get User Based Checklist////
|
|
1949
|
+
if ( !getUserEmails.length ) {
|
|
1950
|
+
return res.sendError( { error: 'No Users Found' }, 204 );
|
|
1951
|
+
} else {
|
|
1952
|
+
return res.sendSuccess( { userEmailData: getUserEmails } );
|
|
1953
|
+
}
|
|
1954
|
+
} catch ( e ) {
|
|
1955
|
+
logger.error( { function: 'getUserEmails', error: e, message: req.body } );
|
|
1956
|
+
return res.sendError( e, 500 );
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
@@ -588,6 +588,19 @@ export const summaryTableV3 = async ( req, res ) => {
|
|
|
588
588
|
try {
|
|
589
589
|
let reqestData = req.body;
|
|
590
590
|
let getClientData = await getClientConfig( reqestData.clientId );
|
|
591
|
+
let featureConfigs = getClientData?.featureConfigs || {};
|
|
592
|
+
const engagersLabel = featureConfigs?.bouncedLimit?.value ?
|
|
593
|
+
`More than ${featureConfigs.bouncedLimit.value} mins` :
|
|
594
|
+
'Engagers';
|
|
595
|
+
const bouncedLabel = featureConfigs?.bouncedLimit?.value ?
|
|
596
|
+
`Less than ${featureConfigs.bouncedLimit.value} mins Footfall` :
|
|
597
|
+
'Bounced Footfall';
|
|
598
|
+
const conversionLabel = featureConfigs?.conversion?.value ?
|
|
599
|
+
`More than ${featureConfigs.conversion.value} mins Rate` :
|
|
600
|
+
'Conversion Rate';
|
|
601
|
+
const missedlabel = featureConfigs?.bouncedLimit?.value && featureConfigs?.conversion?.value ?
|
|
602
|
+
`${featureConfigs.bouncedLimit.value} - ${featureConfigs.conversion.value} mins` :
|
|
603
|
+
'Missed Opportunity';
|
|
591
604
|
if ( !getClientData ) {
|
|
592
605
|
return res.sendError( 'Invalid Client Id', 400 );
|
|
593
606
|
}
|
|
@@ -619,7 +632,7 @@ export const summaryTableV3 = async ( req, res ) => {
|
|
|
619
632
|
if ( resultData ) {
|
|
620
633
|
if ( resultData.status_code == '200' ) {
|
|
621
634
|
if ( reqestData.export ) {
|
|
622
|
-
if ( resultData.summaryData.length>0 ) {
|
|
635
|
+
if ( resultData.summaryData.length > 0 ) {
|
|
623
636
|
const exportdata = [];
|
|
624
637
|
resultData.summaryData.forEach( ( element ) => {
|
|
625
638
|
if ( reqestData.clientId === '193' ) {
|
|
@@ -628,14 +641,14 @@ export const summaryTableV3 = async ( req, res ) => {
|
|
|
628
641
|
'Store ID': element.storeId,
|
|
629
642
|
...( req.body.storeId.length ==1 ) ? { Date: element['date'] }:{},
|
|
630
643
|
'Footfall': element.footfallCount,
|
|
631
|
-
'Bounced
|
|
644
|
+
'Bounced Footfall': element.bouncedCount,
|
|
632
645
|
'Engagers': element.engagersCount,
|
|
633
|
-
'
|
|
646
|
+
'Missed Opportunity': element.missedOpportunityCount,
|
|
634
647
|
'Potential Buyers': element.potentialBuyersCount,
|
|
635
|
-
'Conversion Rate': element.conversionRate,
|
|
636
648
|
'NOB Count': element.NOBCount,
|
|
637
649
|
'Avg.Dwell Time': element.avgDwellTime,
|
|
638
650
|
'Avg.Infra DownTime': element.avgInfraDowntime,
|
|
651
|
+
...( element.passerBy_count !== undefined ? { 'Passer By': element.passerBy_count } : {} ),
|
|
639
652
|
'Below12': element.below12,
|
|
640
653
|
'13-19': element['13-19'],
|
|
641
654
|
'20-30': element['20-30'],
|
|
@@ -646,20 +659,44 @@ export const summaryTableV3 = async ( req, res ) => {
|
|
|
646
659
|
'Male': element.male,
|
|
647
660
|
'Female': element.female,
|
|
648
661
|
} );
|
|
662
|
+
} else if ( reqestData.clientId === '452' ) {
|
|
663
|
+
exportdata.push( {
|
|
664
|
+
'Store Name': element.storeName,
|
|
665
|
+
'Store ID': element.storeId,
|
|
666
|
+
...( req.body.storeId.length ==1 ) ? { Date: element['date'] }:{},
|
|
667
|
+
'Footfall': element.footfallCount,
|
|
668
|
+
...( bouncedLabel ? { [bouncedLabel]: element.bouncedCount } : {} ),
|
|
669
|
+
...( engagersLabel ? { [engagersLabel]: element.engagersCount } : {} ),
|
|
670
|
+
...( missedlabel ? { [missedlabel]: element.missedOpportunityCount } : {} ),
|
|
671
|
+
...( conversionLabel ? { [conversionLabel]: element.conversionRate } : {} ),
|
|
672
|
+
'NOB Count': element.NOBCount,
|
|
673
|
+
'Avg.Dwell Time': element.avgDwellTime,
|
|
674
|
+
'Avg.Infra DownTime': element.avgInfraDowntime,
|
|
675
|
+
...( element.passerBy_count !== undefined ? { 'Passer By': element.passerBy_count } : {} ),
|
|
676
|
+
'Below12': element.below12,
|
|
677
|
+
'13-19': element['13-19'],
|
|
678
|
+
'20-30': element['20-30'],
|
|
679
|
+
'31-45': element['31-45'],
|
|
680
|
+
'46-59': element['46-59'],
|
|
681
|
+
'60 above': element['60 above'],
|
|
682
|
+
'Male': element.male,
|
|
683
|
+
'Female': element.female,
|
|
684
|
+
} );
|
|
649
685
|
} else {
|
|
650
686
|
exportdata.push( {
|
|
651
687
|
'Store Name': element.storeName,
|
|
652
688
|
'Store ID': element.storeId,
|
|
653
689
|
...( req.body.storeId.length ==1 ) ? { Date: element['date'] }:{},
|
|
654
690
|
'Footfall': element.footfallCount,
|
|
655
|
-
'Bounced
|
|
691
|
+
'Bounced Footfall': element.bouncedCount,
|
|
656
692
|
'Engagers': element.engagersCount,
|
|
657
|
-
'
|
|
693
|
+
'Missed Opportunity': element.missedOpportunityCount,
|
|
658
694
|
'Potential Buyers': element.potentialBuyersCount,
|
|
659
695
|
'Conversion Rate': element.conversionRate,
|
|
660
696
|
'NOB Count': element.NOBCount,
|
|
661
697
|
'Avg.Dwell Time': element.avgDwellTime,
|
|
662
698
|
'Avg.Infra DownTime': element.avgInfraDowntime,
|
|
699
|
+
...( element.passerBy_count !== undefined ? { 'Passer By': element.passerBy_count } : {} ),
|
|
663
700
|
'Below12': element.below12,
|
|
664
701
|
'13-19': element['13-19'],
|
|
665
702
|
'20-30': element['20-30'],
|
|
@@ -753,27 +790,48 @@ export const performanceMatrixV3 = async ( req, res ) => {
|
|
|
753
790
|
if ( resultData ) {
|
|
754
791
|
if ( resultData.status_code == '200' ) {
|
|
755
792
|
let data = [];
|
|
756
|
-
resultData.performanceData.
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
item.left = data[findprevIndex].left + 5;
|
|
793
|
+
let performanceData = resultData.performanceData.reduce( ( acc, ele ) => {
|
|
794
|
+
if ( !acc[ele.position] ) {
|
|
795
|
+
console.log( ele );
|
|
796
|
+
acc[ele.position] = [ ele ];
|
|
761
797
|
} else {
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
798
|
+
acc[ele.position].push( ele );
|
|
799
|
+
}
|
|
800
|
+
return acc;
|
|
801
|
+
}, {} );
|
|
802
|
+
|
|
803
|
+
Object.keys( performanceData ).forEach( ( key ) => {
|
|
804
|
+
performanceData[key].forEach( ( item, index ) => {
|
|
805
|
+
let findprevIndex = data.findIndex( ( ele ) => ele.position == item.position );
|
|
806
|
+
let findLastIndex = data.findLastIndex( ( ele ) => ele.position == item.position );
|
|
807
|
+
if ( findprevIndex != -1 ) {
|
|
808
|
+
let num = index < 5 ? 0 : index < 10 ? 10 : 20;
|
|
809
|
+
let left = data[findLastIndex].left;
|
|
810
|
+
let leftNum = 8;
|
|
811
|
+
if ( [ 0, 5, 10 ].includes( index ) ) {
|
|
812
|
+
left = data[findprevIndex].left;
|
|
813
|
+
leftNum = 0;
|
|
814
|
+
}
|
|
815
|
+
console.log( leftNum );
|
|
816
|
+
item.top = data[findprevIndex].top + num;
|
|
817
|
+
item.left = left + leftNum;
|
|
771
818
|
} else {
|
|
772
|
-
item.
|
|
773
|
-
|
|
819
|
+
if ( item.position == 'High_Low' ) {
|
|
820
|
+
item.left = 3;
|
|
821
|
+
item.top = 10;
|
|
822
|
+
} else if ( item.position == 'High_High' ) {
|
|
823
|
+
item.left = 55;
|
|
824
|
+
item.top = 10;
|
|
825
|
+
} else if ( item.position == 'Low_Low' ) {
|
|
826
|
+
item.left = 3;
|
|
827
|
+
item.top = 55;
|
|
828
|
+
} else {
|
|
829
|
+
item.left = 55;
|
|
830
|
+
item.top = 55;
|
|
831
|
+
}
|
|
774
832
|
}
|
|
775
|
-
|
|
776
|
-
|
|
833
|
+
data.push( item );
|
|
834
|
+
} );
|
|
777
835
|
} );
|
|
778
836
|
resultData.performanceData = data;
|
|
779
837
|
return res.sendSuccess( resultData );
|
|
@@ -2005,7 +2063,7 @@ async function getGroupStoresIds( userClientId, storeIds, getRole, getUserType,
|
|
|
2005
2063
|
|
|
2006
2064
|
async function getClientConfig( clientId ) {
|
|
2007
2065
|
try {
|
|
2008
|
-
let getClientData = await clientService.findOne( { clientId: clientId }, { 'paymentInvoice.currencyType': 1, 'averageTransactionValue': 1, 'featureConfigs.billableCalculation': 1, 'featureConfigs.missedOpportunityCalculation': 1, 'featureConfigs.conversionCalculation': 1, 'featureConfigs.open': 1, 'featureConfigs.close': 1, 'isFootfallAuditStores': 1 } );
|
|
2066
|
+
let getClientData = await clientService.findOne( { clientId: clientId }, { 'paymentInvoice.currencyType': 1, 'averageTransactionValue': 1, 'featureConfigs.billableCalculation': 1, 'featureConfigs.missedOpportunityCalculation': 1, 'featureConfigs.conversionCalculation': 1, 'featureConfigs.open': 1, 'featureConfigs.close': 1, 'isFootfallAuditStores': 1, 'featureConfigs.bouncedLimit': 1, 'featureConfigs.conversion': 1 } );
|
|
2009
2067
|
if ( !getClientData ) {
|
|
2010
2068
|
return false;
|
|
2011
2069
|
}
|
package/src/dtos/nob.dtos.js
CHANGED
|
@@ -8,10 +8,15 @@ export const addBillsSchema = joi.object( {
|
|
|
8
8
|
'string.empty': 'Please enter a valid Store ID',
|
|
9
9
|
'any.required': 'Store ID is required',
|
|
10
10
|
} ).allow( null ),
|
|
11
|
-
nobDate: joi.string()
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
nobDate: joi.string()
|
|
12
|
+
.pattern( /^\d{4}-\d{2}-\d{2}$/ ) // Ensures format YYYY-MM-DD
|
|
13
|
+
.required()
|
|
14
|
+
.messages( {
|
|
15
|
+
'string.pattern.base': 'NOB Date must be in YYYY-MM-DD format',
|
|
16
|
+
'string.empty': 'Please enter a valid NOB Date',
|
|
17
|
+
'any.required': 'NOB Date is required',
|
|
18
|
+
} )
|
|
19
|
+
.allow( null ),
|
|
15
20
|
nobCount: joi.number().required().messages( {
|
|
16
21
|
'string.empty': 'Please enter a valid NOB Count',
|
|
17
22
|
'any.required': 'NOB Count is required',
|
|
@@ -10,6 +10,7 @@ const baseSchema = {
|
|
|
10
10
|
nob: joi.boolean().optional().allow( '' ),
|
|
11
11
|
dateType: joi.string().optional().allow( '' ),
|
|
12
12
|
normalize: joi.boolean().optional().allow( '' ),
|
|
13
|
+
conversiontype: joi.string().optional().allow( '' ),
|
|
13
14
|
};
|
|
14
15
|
|
|
15
16
|
// Schema for Card Funnel
|
|
@@ -37,6 +38,7 @@ export const validateRecapVideoSchema = joi.object( {
|
|
|
37
38
|
recapVideoDate: joi.string().required(),
|
|
38
39
|
valueType: joi.string().optional().allow( '' ),
|
|
39
40
|
nob: joi.boolean().optional().allow( '' ),
|
|
41
|
+
conversiontype: joi.string().optional().allow( '' ),
|
|
40
42
|
} );
|
|
41
43
|
|
|
42
44
|
export const validateRecapVideoParams = {
|
|
@@ -192,6 +194,7 @@ export const validateperformanceMatrixSchema = joi.object( {
|
|
|
192
194
|
...baseSchema,
|
|
193
195
|
processtype1: joi.string().required(),
|
|
194
196
|
processtype2: joi.string().required(),
|
|
197
|
+
topStores: joi.number().optional().allow( '' ),
|
|
195
198
|
} );
|
|
196
199
|
|
|
197
200
|
export const validateperformanceMatrixParams = {
|
|
@@ -233,23 +236,3 @@ export const getStoreCameraImageSchema = joi.object( {
|
|
|
233
236
|
export const getStoreCameraImageParams = {
|
|
234
237
|
body: getStoreCameraImageSchema,
|
|
235
238
|
};
|
|
236
|
-
|
|
237
|
-
export const createEmailersSchema = joi.object( {
|
|
238
|
-
clientId: joi.string().required(),
|
|
239
|
-
fromDate: joi.string().required(),
|
|
240
|
-
toDate: joi.string().required(),
|
|
241
|
-
templateType: joi.string().required(),
|
|
242
|
-
} );
|
|
243
|
-
|
|
244
|
-
export const createEmailersParams = {
|
|
245
|
-
body: createEmailersSchema,
|
|
246
|
-
};
|
|
247
|
-
|
|
248
|
-
export const sendEmailersSchema = joi.object( {
|
|
249
|
-
_id: joi.string().required(),
|
|
250
|
-
} );
|
|
251
|
-
|
|
252
|
-
export const sendEmailersParams = {
|
|
253
|
-
body: sendEmailersSchema,
|
|
254
|
-
};
|
|
255
|
-
|
|
@@ -57,6 +57,7 @@ import {
|
|
|
57
57
|
headerStoresV2,
|
|
58
58
|
headerClustersV2,
|
|
59
59
|
headerLocationsV2,
|
|
60
|
+
getUserEmails,
|
|
60
61
|
} from '../controllers/tangoTrafficV1.controllers.js';
|
|
61
62
|
|
|
62
63
|
import {
|
|
@@ -165,6 +166,7 @@ analysisTrafficRouter
|
|
|
165
166
|
.post( '/storeOperation_v3', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateStoreOperationParams ), storeOperationV3 )
|
|
166
167
|
.post( '/performanceMatrix_v3', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateperformanceMatrixParams ), performanceMatrixV3 )
|
|
167
168
|
.post( '/zoneDwellTimeSplit_v3', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateStoreOperationParams ), zoneDwellTimeSplitV3 )
|
|
168
|
-
.post( '/storesMap_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateStoresMapParams ), storesMapV1 )
|
|
169
|
+
.post( '/storesMap_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateStoresMapParams ), storesMapV1 )
|
|
170
|
+
.post( '/headerUserEmails_v2', isAllowedSessionHandler, getUserEmails );
|
|
169
171
|
|
|
170
172
|
export default analysisTrafficRouter;
|