tango-app-api-analysis-zone 3.4.0 → 3.7.1-alpha.10
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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tango-app-api-analysis-zone",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.1-alpha.10",
|
|
4
4
|
"description": "zone Analysis",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"mongodb": "^6.8.0",
|
|
22
22
|
"nodemon": "^3.1.4",
|
|
23
23
|
"tango-api-schema": "^2.2.21",
|
|
24
|
-
"tango-app-api-middleware": "^3.
|
|
24
|
+
"tango-app-api-middleware": "^3.6.8",
|
|
25
25
|
"winston": "^3.13.1",
|
|
26
26
|
"winston-daily-rotate-file": "^5.0.0"
|
|
27
27
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { logger, download } from 'tango-app-api-middleware';
|
|
1
|
+
import { logger, download, downloadint, convertSecondstoTimeFormat } from 'tango-app-api-middleware';
|
|
2
2
|
import { findOneUserAssignedStore } from '../services/userAssignedStore.service.js';
|
|
3
|
-
|
|
3
|
+
import * as clientService from '../services/clients.services.js';
|
|
4
4
|
// Lamda Service Call //
|
|
5
5
|
async function LamdaServiceCall( url, data ) {
|
|
6
6
|
try {
|
|
@@ -19,7 +19,7 @@ async function LamdaServiceCall( url, data ) {
|
|
|
19
19
|
const json = await response.json();
|
|
20
20
|
return json;
|
|
21
21
|
} catch ( error ) {
|
|
22
|
-
console.log( 'error =>', error );
|
|
22
|
+
// console.log( 'error =>', error );
|
|
23
23
|
logger.error( { error: error, message: data, function: 'LamdaServiceCall' } );
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -108,7 +108,7 @@ export const zoneSummaryTableV1 = async ( req, res ) => {
|
|
|
108
108
|
try {
|
|
109
109
|
let reqestData = req.body;
|
|
110
110
|
if ( reqestData.export ) {
|
|
111
|
-
reqestData.limit =
|
|
111
|
+
reqestData.limit = 10000;
|
|
112
112
|
}
|
|
113
113
|
let LamdaURL = 'https://hxpnn5weq3lm4nqouk4pjm3chy0jmqdb.lambda-url.ap-south-1.on.aws/';
|
|
114
114
|
let resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
@@ -123,6 +123,8 @@ export const zoneSummaryTableV1 = async ( req, res ) => {
|
|
|
123
123
|
'Zone Name': element.zoneName,
|
|
124
124
|
'Store Name': element.storeName,
|
|
125
125
|
'Store ID': element.storeId,
|
|
126
|
+
...( element.storefootfallCount !== undefined && { 'Store FF': element.storefootfallCount } ),
|
|
127
|
+
...( element.nob !== undefined && { 'Zone Wise NoB': element.nob } ),
|
|
126
128
|
'Zone Conc.Rate': element.concentrationRate,
|
|
127
129
|
'Avg Dwell Time (Mins)': element.avgDwellTime,
|
|
128
130
|
'Zone FF': element.footfallCount,
|
|
@@ -138,7 +140,7 @@ export const zoneSummaryTableV1 = async ( req, res ) => {
|
|
|
138
140
|
'Female': element.femaleCount,
|
|
139
141
|
} );
|
|
140
142
|
} );
|
|
141
|
-
return await
|
|
143
|
+
return await downloadint( exportdata, res );
|
|
142
144
|
} else {
|
|
143
145
|
return res.sendError( 'No Content', 204 );
|
|
144
146
|
}
|
|
@@ -298,26 +300,28 @@ export const zoneInteractionTable430 = async ( req, res ) => {
|
|
|
298
300
|
let resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
299
301
|
if ( resultData ) {
|
|
300
302
|
if ( resultData.status_code == '200' ) {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
303
|
+
resultData.data[0].assist_time_string = await convertSecondstoTimeFormat( resultData.data[0].assist_time );
|
|
304
|
+
resultData.data[0].avg_interaction_time_string = await convertSecondstoTimeFormat( resultData.data[0].avg_interaction_time );
|
|
305
|
+
// if ( reqestData.export ) {
|
|
306
|
+
// if ( resultData.data.length>0 ) {
|
|
307
|
+
// const exportdata = [];
|
|
308
|
+
// resultData.data.forEach( ( element ) => {
|
|
309
|
+
// exportdata.push( {
|
|
310
|
+
// 'Passer By': element.passer_by || '--',
|
|
311
|
+
// 'Footfall': element.footfall || '--',
|
|
312
|
+
// 'Drop In Rate': element.drop_in_rate +'%',
|
|
313
|
+
// 'Customer Attended ': element.customer_attended || '--',
|
|
314
|
+
// 'Interation Rate ': element.interaction_rate +'%',
|
|
315
|
+
// 'Billing Conversion': element.footfall_overamin_inzone ?? '--',
|
|
316
|
+
// 'Billing Conversion Rate': element.billing_conversion_rate +'%',
|
|
317
|
+
// 'Greetings Count': element.greeting_count ?? '--',
|
|
318
|
+
// } );
|
|
319
|
+
// } );
|
|
320
|
+
// return await download( exportdata, res );
|
|
321
|
+
// } else {
|
|
322
|
+
// return res.sendError( 'No Content', 204 );
|
|
323
|
+
// }
|
|
324
|
+
// }
|
|
321
325
|
return res.sendSuccess( resultData );
|
|
322
326
|
} else {
|
|
323
327
|
return res.sendError( 'No Content', 204 );
|
|
@@ -420,7 +424,7 @@ export const zoneInteractionTableExport430 = async ( req, res ) => {
|
|
|
420
424
|
exportdata.push( {
|
|
421
425
|
'Store Id': element.store_id || '--',
|
|
422
426
|
'Date': element.date || '--',
|
|
423
|
-
'Customer spent more than 10 mins': element.customer_count_over10min
|
|
427
|
+
'Customer spent more than 10 mins': element.customer_count_over10min ?? '--',
|
|
424
428
|
'Billing Conversion': element.billing_conversion || '--',
|
|
425
429
|
} );
|
|
426
430
|
} );
|
|
@@ -455,7 +459,7 @@ export const zoneConcentrationTableExport = async ( req, res ) => {
|
|
|
455
459
|
exportdata.push( {
|
|
456
460
|
'Date': element.Date,
|
|
457
461
|
'Zone Name': element.zoneName,
|
|
458
|
-
'Footfall(Actuals)': element.footfallCount
|
|
462
|
+
'Footfall(Actuals)': element.footfallCount ?? '--',
|
|
459
463
|
'DwellTime(Average)': element.avgDwellTime || '--',
|
|
460
464
|
'Concentration': element.concentrationRate +'%',
|
|
461
465
|
} );
|
|
@@ -492,7 +496,7 @@ export const zoneSegmentationV1Export = async ( req, res ) => {
|
|
|
492
496
|
const exportItem = {
|
|
493
497
|
'Date': element.date,
|
|
494
498
|
'Entrance': element.category,
|
|
495
|
-
'Entrance wise footfall': element.value,
|
|
499
|
+
'Entrance wise footfall': element.value ?? '--',
|
|
496
500
|
};
|
|
497
501
|
if ( clientId === '463' ) {
|
|
498
502
|
exportItem['Concentration Rate'] = element?.concentrationRate ? element?.concentrationRate + '%' : '--';
|
|
@@ -526,21 +530,24 @@ export const zoneInteractionTable430Export = async ( req, res ) => {
|
|
|
526
530
|
if ( reqestData.export ) {
|
|
527
531
|
if ( resultData.data.length>0 ) {
|
|
528
532
|
const exportdata = [];
|
|
529
|
-
|
|
533
|
+
for ( let element of resultData.data ) {
|
|
534
|
+
element.assist_time_string = await convertSecondstoTimeFormat( element.assist_time );
|
|
535
|
+
element.avg_interaction_time_string = await convertSecondstoTimeFormat( element.avg_interaction_time );
|
|
530
536
|
exportdata.push( {
|
|
531
537
|
'Date': element.date || '--',
|
|
532
538
|
'Passer By': element.passer_by || '--',
|
|
533
539
|
'Footfall': element.footfall || '--',
|
|
534
540
|
'Drop In Rate': element.drop_in_rate +'%',
|
|
535
|
-
'Greetings Count': element.greeting_count
|
|
541
|
+
'Greetings Count': element.greeting_count ?? '--',
|
|
536
542
|
'Greetings Rate': ( ( element.greeting_count / element.footfall ) * 100 ).toFixed( 1 ) + '%' || '--',
|
|
537
543
|
'Customer Interacted': element.customer_attended || '--',
|
|
538
544
|
'Interation Rate ': element.interaction_rate +'%',
|
|
539
|
-
'Avg Time
|
|
540
|
-
'
|
|
545
|
+
'Avg Time Taken to Assist a Customer': element.avg_interaction_time_string ?? '--',
|
|
546
|
+
'Avg Time Spent with Customer': element.assist_time_string ?? '--',
|
|
547
|
+
'Billing Conversion': element.footfall_overamin_inzone ?? '--',
|
|
541
548
|
'Billing Conversion Rate': element.billing_conversion_rate +'%',
|
|
542
549
|
} );
|
|
543
|
-
}
|
|
550
|
+
}
|
|
544
551
|
return await download( exportdata, res );
|
|
545
552
|
} else {
|
|
546
553
|
return res.sendError( 'No Content', 204 );
|
|
@@ -554,6 +561,7 @@ export const zoneInteractionTable430Export = async ( req, res ) => {
|
|
|
554
561
|
return res.sendError( 'No Content', 204 );
|
|
555
562
|
}
|
|
556
563
|
} catch ( error ) {
|
|
564
|
+
// console.log( 'error', error );
|
|
557
565
|
logger.error( { error: error, message: req.query, function: 'zoneInteractionTable430Export' } );
|
|
558
566
|
return res.sendError( { error: error }, 500 );
|
|
559
567
|
}
|
|
@@ -591,7 +599,7 @@ export const zoneSegmentationTableExport = async ( req, res ) => {
|
|
|
591
599
|
resultData.zoneConcentrationData.forEach( ( element ) => {
|
|
592
600
|
exportdata.push( {
|
|
593
601
|
'Zone Name': element?.zoneName || '--',
|
|
594
|
-
'Footfall': element?.footfallCount
|
|
602
|
+
'Footfall': element?.footfallCount ?? '--',
|
|
595
603
|
'Avg.Dwell Time (Mins)': element?.avgDwellTime || '--',
|
|
596
604
|
'Trolley': element?.Trolley ? element?.Trolley: 0,
|
|
597
605
|
'Basket': element?.Basket ? element?.Basket : 0,
|
|
@@ -652,7 +660,7 @@ export const zonePasserByTable430Export = async ( req, res ) => {
|
|
|
652
660
|
exportdata.push( {
|
|
653
661
|
'Date': element?.date_string || '--',
|
|
654
662
|
'Camera Name': element?.streamName || '--',
|
|
655
|
-
'Passer-by Count': element?.passerby_count
|
|
663
|
+
'Passer-by Count': element?.passerby_count ?? '--',
|
|
656
664
|
} );
|
|
657
665
|
} );
|
|
658
666
|
return await download( exportdata, res );
|
|
@@ -676,7 +684,7 @@ export const zonePasserByTable430Export = async ( req, res ) => {
|
|
|
676
684
|
export const interactionTableV1 = async ( req, res ) => {
|
|
677
685
|
try {
|
|
678
686
|
let reqestData = req.body;
|
|
679
|
-
let LamdaURL = 'https://
|
|
687
|
+
let LamdaURL = 'https://x5rjtf6uylkgie62dwmp2dpjra0txbve.lambda-url.ap-south-1.on.aws/';
|
|
680
688
|
let resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
681
689
|
if ( resultData ) {
|
|
682
690
|
if ( resultData.status_code == '200' ) {
|
|
@@ -692,4 +700,363 @@ export const interactionTableV1 = async ( req, res ) => {
|
|
|
692
700
|
return res.sendError( { error: error }, 500 );
|
|
693
701
|
}
|
|
694
702
|
};
|
|
703
|
+
export const interactionTable430Export = async ( req, res ) => {
|
|
704
|
+
try {
|
|
705
|
+
let reqestData = req.body;
|
|
706
|
+
if ( reqestData.export ) {
|
|
707
|
+
reqestData.limit = 10000;
|
|
708
|
+
}
|
|
709
|
+
let LamdaURL = 'https://x5rjtf6uylkgie62dwmp2dpjra0txbve.lambda-url.ap-south-1.on.aws/';
|
|
710
|
+
let resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
711
|
+
if ( resultData ) {
|
|
712
|
+
if ( resultData.status_code == '200' ) {
|
|
713
|
+
if ( reqestData.export ) {
|
|
714
|
+
if ( resultData.data.length > 0 ) {
|
|
715
|
+
const exportdata = [];
|
|
716
|
+
resultData.data.forEach( ( element ) => {
|
|
717
|
+
exportdata.push( {
|
|
718
|
+
'Date': element?.storeDate || '--',
|
|
719
|
+
'Category': element?.category || '--',
|
|
720
|
+
'Value': element?.value ?? '--',
|
|
721
|
+
} );
|
|
722
|
+
} );
|
|
723
|
+
return await download( exportdata, res );
|
|
724
|
+
} else {
|
|
725
|
+
return res.sendError( 'No Content', 204 );
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
return res.sendSuccess( resultData );
|
|
729
|
+
} else {
|
|
730
|
+
return res.sendError( 'No Content', 204 );
|
|
731
|
+
}
|
|
732
|
+
} else {
|
|
733
|
+
return res.sendError( 'No Content', 204 );
|
|
734
|
+
}
|
|
735
|
+
} catch ( error ) {
|
|
736
|
+
logger.error( { error: error, message: req.query, function: 'interactionTable430Export' } );
|
|
737
|
+
return res.sendError( { error: error }, 500 );
|
|
738
|
+
}
|
|
739
|
+
};
|
|
740
|
+
export const ZonewiseCustomerFunnelV1 = async ( req, res ) => {
|
|
741
|
+
try {
|
|
742
|
+
let reqestData = req.body;
|
|
743
|
+
let LamdaURL = 'https://7q6v4wppeubi5kgdffwm37az2e0bfkak.lambda-url.ap-south-1.on.aws/';
|
|
744
|
+
let resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
745
|
+
if ( resultData ) {
|
|
746
|
+
if ( resultData.status_code == '200' ) {
|
|
747
|
+
resultData.data[0].assist_time_string = await convertSecondstoTimeFormat( resultData.data[0].assist_time );
|
|
748
|
+
resultData.data[0].avg_interaction_time_string = await convertSecondstoTimeFormat( resultData.data[0].avg_interaction_time );
|
|
749
|
+
return res.sendSuccess( resultData );
|
|
750
|
+
} else {
|
|
751
|
+
return res.sendError( 'No Content', 204 );
|
|
752
|
+
}
|
|
753
|
+
} else {
|
|
754
|
+
return res.sendError( 'No Content', 204 );
|
|
755
|
+
}
|
|
756
|
+
} catch ( error ) {
|
|
757
|
+
logger.error( { error: error, message: req.query, function: 'ZonewiseCustomerFunnelV1' } );
|
|
758
|
+
return res.sendError( { error: error }, 500 );
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
|
|
762
|
+
export const ZonewiseCustomerFunnelExport = async ( req, res ) => {
|
|
763
|
+
try {
|
|
764
|
+
let reqestData = req.body;
|
|
765
|
+
let LamdaURL = 'https://7q6v4wppeubi5kgdffwm37az2e0bfkak.lambda-url.ap-south-1.on.aws/';
|
|
766
|
+
let resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
767
|
+
if ( resultData ) {
|
|
768
|
+
if ( resultData.status_code == '200' ) {
|
|
769
|
+
// resultData.data[0].assist_time_string = await convertSecondstoTimeFormat( resultData.data[0].assist_time );
|
|
770
|
+
// resultData.data[0].avg_interaction_time_string = await convertSecondstoTimeFormat( resultData.data[0].avg_interaction_time );
|
|
771
|
+
if ( reqestData.export ) {
|
|
772
|
+
if ( resultData.data.length > 0 ) {
|
|
773
|
+
const exportdata = [];
|
|
774
|
+
for ( let element of resultData.data ) {
|
|
775
|
+
element.assist_time_string = await convertSecondstoTimeFormat( element.assist_time );
|
|
776
|
+
element.avg_interaction_time_string = await convertSecondstoTimeFormat( element.avg_interaction_time );
|
|
777
|
+
const row = {
|
|
778
|
+
'Date': element.date || '--',
|
|
779
|
+
'Footfall': element.footfall ?? '--',
|
|
780
|
+
'Greetings Count': element.greeting_count ?? '--',
|
|
781
|
+
'Greetings Rate': ( element.greeting_count && element.footfall ) ? ( ( element.greeting_count / element.footfall ) * 100 ).toFixed( 1 ) + '%': '--',
|
|
782
|
+
'Customer Interacted': element.customer_attended ?? '--',
|
|
783
|
+
'Interation Rate ': element.interaction_rate != null ? element.interaction_rate + '%' : '--',
|
|
784
|
+
'Avg Time Taken to Assist a Customer': element.avg_interaction_time_string ?? '--',
|
|
785
|
+
'Avg Time Spent with Customer': element.assist_time_string ?? '--',
|
|
786
|
+
};
|
|
787
|
+
if ( element.footfall_overamin_inzone != null ) {
|
|
788
|
+
row['Billing Conversion'] = element.footfall_overamin_inzone;
|
|
789
|
+
}
|
|
790
|
+
if ( element.billing_conversion_rate != null ) {
|
|
791
|
+
row['Billing Conversion Rate'] = element.billing_conversion_rate + '%';
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
exportdata.push( row );
|
|
795
|
+
};
|
|
796
|
+
return await download( exportdata, res );
|
|
797
|
+
} else {
|
|
798
|
+
return res.sendError( 'No Content', 204 );
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
return res.sendSuccess( resultData );
|
|
802
|
+
} else {
|
|
803
|
+
return res.sendError( 'No Content', 204 );
|
|
804
|
+
}
|
|
805
|
+
} else {
|
|
806
|
+
return res.sendError( 'No Content', 204 );
|
|
807
|
+
}
|
|
808
|
+
} catch ( error ) {
|
|
809
|
+
// console.log( 'error', error );
|
|
810
|
+
logger.error( { error: error, message: req.query, function: 'ZonewiseCustomerFunnelExport' } );
|
|
811
|
+
return res.sendError( { error: error }, 500 );
|
|
812
|
+
}
|
|
813
|
+
};
|
|
814
|
+
|
|
815
|
+
|
|
816
|
+
// new Pantprojects api for Zone FF V2
|
|
817
|
+
export const getZoneAPIFFV2 = async ( req, res ) => {
|
|
818
|
+
try {
|
|
819
|
+
let reqestData = req.body;
|
|
820
|
+
let LamdaURL = 'https://kxz75vd4lsgpf4ykytgmyllmoa0xwixt.lambda-url.ap-south-1.on.aws/';
|
|
821
|
+
let resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
822
|
+
if ( resultData ) {
|
|
823
|
+
return res.sendSuccess( resultData );
|
|
824
|
+
} else {
|
|
825
|
+
return res.sendError( 'No Content', 204 );
|
|
826
|
+
}
|
|
827
|
+
} catch ( error ) {
|
|
828
|
+
logger.error( { error: error, message: req.query, function: 'getZoneAPIFFV2' } );
|
|
829
|
+
return res.sendError( { error: error }, 500 );
|
|
830
|
+
}
|
|
831
|
+
};
|
|
832
|
+
|
|
833
|
+
export const getNewZoneFFV2 = async ( req, res ) => {
|
|
834
|
+
try {
|
|
835
|
+
let reqestData = req.body;
|
|
836
|
+
let LamdaURL = 'https://gcizlv6zpfhvwyrqzgpjsxneoi0rfnuc.lambda-url.ap-south-1.on.aws/';
|
|
837
|
+
let resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
838
|
+
if ( resultData ) {
|
|
839
|
+
if ( resultData.status_code == '200' ) {
|
|
840
|
+
return res.sendSuccess( resultData );
|
|
841
|
+
} else {
|
|
842
|
+
return res.sendError( 'No Content', 204 );
|
|
843
|
+
}
|
|
844
|
+
} else {
|
|
845
|
+
return res.sendError( 'No Content', 204 );
|
|
846
|
+
}
|
|
847
|
+
} catch ( error ) {
|
|
848
|
+
logger.error( { error: error, message: req.query, function: 'getNewZoneFFV2' } );
|
|
849
|
+
return res.sendError( { error: error }, 500 );
|
|
850
|
+
}
|
|
851
|
+
};
|
|
852
|
+
export const getSelectedZoneFFV2 = async ( req, res ) => {
|
|
853
|
+
try {
|
|
854
|
+
let reqestData = req.body;
|
|
855
|
+
let LamdaURL = 'https://6adocjaelheviyminlomqqncmi0japrn.lambda-url.ap-south-1.on.aws/';
|
|
856
|
+
let resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
857
|
+
if ( resultData ) {
|
|
858
|
+
if ( resultData.status_code == '200' ) {
|
|
859
|
+
if ( reqestData.export ) {
|
|
860
|
+
const exportdata = [];
|
|
861
|
+
const element = resultData.data;
|
|
862
|
+
const row = {
|
|
863
|
+
'Store Name': element.storeName || '--',
|
|
864
|
+
'Overall FF': ( element.zone1FF ?? element.zone2FF ?? element.zone3FF ) != null ?
|
|
865
|
+
element.overallFootfall ?? '--' :
|
|
866
|
+
'--',
|
|
867
|
+
'NOB': element.noB ?? '--',
|
|
868
|
+
};
|
|
869
|
+
|
|
870
|
+
// Conditionally add zone values if present
|
|
871
|
+
if ( element.zone1FF !== undefined && element.zone1FF !== null ) {
|
|
872
|
+
row['Zone 1 FF'] = element.zone1FF;
|
|
873
|
+
}
|
|
874
|
+
if ( element.zone2FF !== undefined && element.zone2FF !== null ) {
|
|
875
|
+
row['Zone 2 FF'] = element.zone2FF;
|
|
876
|
+
}
|
|
877
|
+
if ( element.zone3FF !== undefined && element.zone3FF !== null ) {
|
|
878
|
+
row['Zone 3 FF'] = element.zone3FF;
|
|
879
|
+
}
|
|
880
|
+
if ( element.zone1Percentage !== undefined && element.zone1Percentage !== null ) {
|
|
881
|
+
row['Zone 1 Conc %'] = element.zone1Percentage !== undefined ?`${element.zone1Percentage}%` : '--';
|
|
882
|
+
}
|
|
883
|
+
if ( element.zone2Percentage !== undefined && element.zone2Percentage !== null ) {
|
|
884
|
+
row['Zone 2 Conc %'] = element.zone2Percentage !== undefined ? `${element.zone2Percentage}%` : '--';
|
|
885
|
+
}
|
|
886
|
+
if ( element.zone3Percentage !== undefined && element.zone3Percentage !== null ) {
|
|
887
|
+
row['Zone 3 Conc %'] = element.zone3Percentage !== undefined ? `${element.zone3Percentage}%` : '--';
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
|
|
891
|
+
exportdata.push( row );
|
|
892
|
+
|
|
893
|
+
return await downloadint( exportdata, res );
|
|
894
|
+
}
|
|
895
|
+
return res.sendSuccess( resultData );
|
|
896
|
+
} else {
|
|
897
|
+
return res.sendError( 'No Content', 204 );
|
|
898
|
+
}
|
|
899
|
+
} else {
|
|
900
|
+
return res.sendError( 'No Content', 204 );
|
|
901
|
+
}
|
|
902
|
+
} catch ( error ) {
|
|
903
|
+
logger.error( { error: error, message: req.query, function: 'getSelectedZoneFFV2' } );
|
|
904
|
+
return res.sendError( { error: error }, 500 );
|
|
905
|
+
}
|
|
906
|
+
};
|
|
907
|
+
|
|
908
|
+
// end v2 API's for pantprojects//
|
|
909
|
+
// pant New Api start date 19-12-2025
|
|
910
|
+
|
|
911
|
+
|
|
912
|
+
export const getNewHoTColdZoneV1 = async ( req, res ) => {
|
|
913
|
+
try {
|
|
914
|
+
let reqestData = req.body;
|
|
915
|
+
let LamdaURL = 'https://j7e5uxgkna6qnuu4vip57kl2wu0pqxza.lambda-url.ap-south-1.on.aws/';
|
|
916
|
+
let resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
917
|
+
if ( resultData ) {
|
|
918
|
+
return res.sendSuccess( resultData );
|
|
919
|
+
} else {
|
|
920
|
+
return res.sendError( 'No Content', 204 );
|
|
921
|
+
}
|
|
922
|
+
} catch ( error ) {
|
|
923
|
+
logger.error( { error: error, message: req.query, function: 'getNewHoTColdZoneV1' } );
|
|
924
|
+
return res.sendError( { error: error }, 500 );
|
|
925
|
+
}
|
|
926
|
+
};
|
|
927
|
+
|
|
928
|
+
export const getNewZoneShopperAnalysisV1 = async ( req, res ) => {
|
|
929
|
+
try {
|
|
930
|
+
const reqestData = req.body;
|
|
931
|
+
|
|
932
|
+
const getClientData = await getClientConfig( reqestData.clientId );
|
|
933
|
+
if ( !getClientData ) {
|
|
934
|
+
return res.sendError( 'Invalid Client Id', 400 );
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
reqestData.featureConfigs = getClientData.featureConfigs;
|
|
938
|
+
|
|
939
|
+
const LamdaURL =
|
|
940
|
+
'https://sekueyolczfjl2ggy4hadzxxxu0zqcmt.lambda-url.ap-south-1.on.aws/';
|
|
941
|
+
|
|
942
|
+
const resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
943
|
+
|
|
944
|
+
if ( !resultData || resultData.status_code !== '200' ) {
|
|
945
|
+
return res.sendError( 'No Content', 204 );
|
|
946
|
+
}
|
|
947
|
+
if ( reqestData.export && resultData.shopperJourneyExportData?.length ) {
|
|
948
|
+
const finalRow = {
|
|
949
|
+
'Overall FF': resultData['Overall FF'] ?? 0,
|
|
950
|
+
'NOB': resultData.NoB ?? 0,
|
|
951
|
+
};
|
|
952
|
+
|
|
953
|
+
resultData.shopperJourneyExportData.forEach( ( zoneObj ) => {
|
|
954
|
+
Object.entries( zoneObj ).forEach( ( [ key, value ] ) => {
|
|
955
|
+
finalRow[key] = value ?? 0;
|
|
956
|
+
} );
|
|
957
|
+
} );
|
|
958
|
+
|
|
959
|
+
return await downloadint( [ finalRow ], res );
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
return res.sendSuccess( resultData );
|
|
963
|
+
} catch ( error ) {
|
|
964
|
+
logger.error( {
|
|
965
|
+
error,
|
|
966
|
+
message: req.query,
|
|
967
|
+
function: 'getNewZoneShopperAnalysisV1',
|
|
968
|
+
} );
|
|
969
|
+
return res.sendError( { error }, 500 );
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+
export const getNewZoneShopperBubbleChartV1 = async ( req, res ) => {
|
|
975
|
+
try {
|
|
976
|
+
let reqestData = req.body;
|
|
977
|
+
let LamdaURL = 'https://iqh6vcxtdxeszpfgdenhsrnvwq0rseou.lambda-url.ap-south-1.on.aws/';
|
|
978
|
+
let resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
979
|
+
if ( resultData ) {
|
|
980
|
+
if ( resultData.status_code == '200' ) {
|
|
981
|
+
return res.sendSuccess( resultData );
|
|
982
|
+
} else {
|
|
983
|
+
return res.sendError( 'No Content', 204 );
|
|
984
|
+
}
|
|
985
|
+
} else {
|
|
986
|
+
return res.sendError( 'No Content', 204 );
|
|
987
|
+
}
|
|
988
|
+
} catch ( error ) {
|
|
989
|
+
logger.error( { error: error, message: req.query, function: 'getNewZoneShopperBubbleChartV1' } );
|
|
990
|
+
return res.sendError( { error: error }, 500 );
|
|
991
|
+
}
|
|
992
|
+
};
|
|
993
|
+
|
|
994
|
+
export const getNewCustomerTravelZoneV1 = async ( req, res ) => {
|
|
995
|
+
try {
|
|
996
|
+
let reqestData = req.body;
|
|
997
|
+
let LamdaURL = 'https://id7qgpex6qbft4kcnloqdrby2q0hyldr.lambda-url.ap-south-1.on.aws/';
|
|
998
|
+
let resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
999
|
+
if ( resultData ) {
|
|
1000
|
+
if ( resultData.status_code == '200' ) {
|
|
1001
|
+
return res.sendSuccess( resultData );
|
|
1002
|
+
} else {
|
|
1003
|
+
return res.sendError( 'No Content', 204 );
|
|
1004
|
+
}
|
|
1005
|
+
} else {
|
|
1006
|
+
return res.sendError( 'No Content', 204 );
|
|
1007
|
+
}
|
|
1008
|
+
} catch ( error ) {
|
|
1009
|
+
logger.error( { error: error, message: req.query, function: 'getNewCustomerTravelZoneV1' } );
|
|
1010
|
+
return res.sendError( { error: error }, 500 );
|
|
1011
|
+
}
|
|
1012
|
+
};
|
|
1013
|
+
|
|
1014
|
+
export const getNewAnalysisZoneV1 = async ( req, res ) => {
|
|
1015
|
+
try {
|
|
1016
|
+
let reqestData = req.body;
|
|
1017
|
+
let LamdaURL = 'https://udcada6kh2bpchpgmigky4bxee0drhwb.lambda-url.ap-south-1.on.aws/';
|
|
1018
|
+
let resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
1019
|
+
if ( resultData ) {
|
|
1020
|
+
return res.sendSuccess( resultData );
|
|
1021
|
+
} else {
|
|
1022
|
+
return res.sendError( 'No Content', 204 );
|
|
1023
|
+
}
|
|
1024
|
+
} catch ( error ) {
|
|
1025
|
+
logger.error( { error: error, message: req.query, function: 'getNewAnalysisZoneV1' } );
|
|
1026
|
+
return res.sendError( { error: error }, 500 );
|
|
1027
|
+
}
|
|
1028
|
+
};
|
|
1029
|
+
|
|
1030
|
+
export const getOverallStoreCardsV1 = async ( req, res ) => {
|
|
1031
|
+
try {
|
|
1032
|
+
let reqestData = req.body;
|
|
1033
|
+
let LamdaURL = 'https://fdeqsx2kouac3n4wodmczoxyke0xpikn.lambda-url.ap-south-1.on.aws/';
|
|
1034
|
+
let resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
1035
|
+
if ( resultData ) {
|
|
1036
|
+
if ( resultData.status_code == '200' ) {
|
|
1037
|
+
return res.sendSuccess( resultData );
|
|
1038
|
+
} else {
|
|
1039
|
+
return res.sendError( 'No Content', 204 );
|
|
1040
|
+
}
|
|
1041
|
+
} else {
|
|
1042
|
+
return res.sendError( 'No Content', 204 );
|
|
1043
|
+
}
|
|
1044
|
+
} catch ( error ) {
|
|
1045
|
+
logger.error( { error: error, message: req.query, function: 'getOverallStoreCardsV1' } );
|
|
1046
|
+
return res.sendError( { error: error }, 500 );
|
|
1047
|
+
}
|
|
1048
|
+
};
|
|
1049
|
+
|
|
1050
|
+
async function getClientConfig( clientId ) {
|
|
1051
|
+
try {
|
|
1052
|
+
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, 'clientName': 1 } );
|
|
1053
|
+
if ( !getClientData ) {
|
|
1054
|
+
return false;
|
|
1055
|
+
}
|
|
1056
|
+
return getClientData;
|
|
1057
|
+
} catch ( error ) {
|
|
1058
|
+
logger.error( { error: error, message: data, function: 'getClientConfig' } );
|
|
1059
|
+
return false;
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
695
1062
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { logger,
|
|
1
|
+
import { logger, downloadint } from 'tango-app-api-middleware';
|
|
2
2
|
import { findOneUserAssignedStore } from '../services/userAssignedStore.service.js';
|
|
3
3
|
|
|
4
4
|
// Lamda Service Call //
|
|
@@ -89,7 +89,7 @@ export const zoneSummaryTableV2 = async ( req, res ) => {
|
|
|
89
89
|
try {
|
|
90
90
|
let reqestData = req.body;
|
|
91
91
|
if ( reqestData.export ) {
|
|
92
|
-
reqestData.limit =
|
|
92
|
+
reqestData.limit = 10000;
|
|
93
93
|
}
|
|
94
94
|
let LamdaURL = 'https://obtvnopiiuwlsrjygprlvjp2p40wokyd.lambda-url.ap-south-1.on.aws/';
|
|
95
95
|
let resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
@@ -104,7 +104,7 @@ export const zoneSummaryTableV2 = async ( req, res ) => {
|
|
|
104
104
|
'StoreId': element.storeId,
|
|
105
105
|
'Date': element.date,
|
|
106
106
|
'Zone Name': element.zoneName,
|
|
107
|
-
'
|
|
107
|
+
'Impression Rate': element.impressionRate,
|
|
108
108
|
'Avg Dwell Time': element.avgDwellTime,
|
|
109
109
|
'Zone FF': element.footfallCount,
|
|
110
110
|
'Zone Bounced': element.bouncedCount,
|
|
@@ -119,7 +119,7 @@ export const zoneSummaryTableV2 = async ( req, res ) => {
|
|
|
119
119
|
'Female': element.femaleCount,
|
|
120
120
|
} );
|
|
121
121
|
} );
|
|
122
|
-
return await
|
|
122
|
+
return await downloadint( exportdata, res );
|
|
123
123
|
} else {
|
|
124
124
|
return res.sendError( 'No Content', 204 );
|
|
125
125
|
}
|
|
@@ -314,19 +314,20 @@ export const customerJourneyTableV2 = async ( req, res ) => {
|
|
|
314
314
|
let resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
315
315
|
if ( resultData ) {
|
|
316
316
|
if ( resultData.status_code == '200' ) {
|
|
317
|
-
if ( reqestData
|
|
318
|
-
if ( resultData
|
|
319
|
-
const exportdata = [];
|
|
320
|
-
resultData.customerJourneyTableData.forEach( ( element ) => {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
} );
|
|
329
|
-
|
|
317
|
+
if ( reqestData?.export ) {
|
|
318
|
+
if ( resultData?.customerJourneyTableData.length ) {
|
|
319
|
+
// const exportdata = [];
|
|
320
|
+
// resultData.customerJourneyTableData.forEach( ( element ) => {
|
|
321
|
+
// exportdata.push( {
|
|
322
|
+
// 'Zone Name': element.zoneName,
|
|
323
|
+
// 'No of Stores': element.noOfStores,
|
|
324
|
+
// 'Zone FF': element.zoneFF,
|
|
325
|
+
// 'Impressions': element.impressions,
|
|
326
|
+
// 'Avg Dwell Time': element.AvgDwellTime,
|
|
327
|
+
// } );
|
|
328
|
+
// } );
|
|
329
|
+
resultData.customerJourneyTableData = [ Object.fromEntries( resultData.customerJourneyTableData ) ];
|
|
330
|
+
return await download( resultData.customerJourneyTableData, res );
|
|
330
331
|
} else {
|
|
331
332
|
return res.sendError( 'No Content', 204 );
|
|
332
333
|
}
|
|
@@ -11,6 +11,7 @@ const baseSchema = {
|
|
|
11
11
|
// Schema for Card Funnel
|
|
12
12
|
export const validateCardsAgeAnalysisSchema = joi.object( {
|
|
13
13
|
...baseSchema,
|
|
14
|
+
zoneName: joi.string().optional().allow( '' ),
|
|
14
15
|
} );
|
|
15
16
|
|
|
16
17
|
export const validateCardsAgeAnalysisParams = {
|
|
@@ -258,6 +259,7 @@ export const validateZoneSegmentationExportParams = {
|
|
|
258
259
|
export const validatezoneInteractionTable430ExportSchema = joi.object( {
|
|
259
260
|
...baseSchema,
|
|
260
261
|
export: joi.boolean().optional().allow( '' ),
|
|
262
|
+
zoneName: joi.string().optional().allow( '' ),
|
|
261
263
|
} );
|
|
262
264
|
|
|
263
265
|
export const validatezoneInteractionTable430ExportParams = {
|
|
@@ -36,6 +36,18 @@ import {
|
|
|
36
36
|
zonePasserByTableV1,
|
|
37
37
|
zonePasserByTable430Export,
|
|
38
38
|
interactionTableV1,
|
|
39
|
+
interactionTable430Export,
|
|
40
|
+
ZonewiseCustomerFunnelV1,
|
|
41
|
+
ZonewiseCustomerFunnelExport,
|
|
42
|
+
getNewZoneFFV2,
|
|
43
|
+
getSelectedZoneFFV2,
|
|
44
|
+
getZoneAPIFFV2,
|
|
45
|
+
getNewHoTColdZoneV1,
|
|
46
|
+
getNewZoneShopperAnalysisV1,
|
|
47
|
+
getNewZoneShopperBubbleChartV1,
|
|
48
|
+
getNewCustomerTravelZoneV1,
|
|
49
|
+
getNewAnalysisZoneV1,
|
|
50
|
+
getOverallStoreCardsV1,
|
|
39
51
|
} from '../controllers/analysisZoneV1.controllers.js';
|
|
40
52
|
|
|
41
53
|
analysisZoneRouter
|
|
@@ -141,5 +153,31 @@ analysisZoneRouter
|
|
|
141
153
|
userType: [ 'tango', 'client' ], access: [
|
|
142
154
|
{ featureName: 'TangoEye', name: 'ZoneTag', permissions: [] },
|
|
143
155
|
],
|
|
144
|
-
} ), validate( validationDtos.validatezoneSegmaentationTableParams ), interactionTableV1 )
|
|
156
|
+
} ), validate( validationDtos.validatezoneSegmaentationTableParams ), interactionTableV1 )
|
|
157
|
+
.post( '/interactionTable_430Export', isAllowedSessionHandler, isAllowedClient, accessVerification( {
|
|
158
|
+
userType: [ 'tango', 'client' ], access: [
|
|
159
|
+
{ featureName: 'TangoEye', name: 'ZoneTag', permissions: [] },
|
|
160
|
+
],
|
|
161
|
+
} ), validate( validationDtos.validatezoneSegmaentationTableParams ), interactionTable430Export )
|
|
162
|
+
.post( '/ZonewiseCustomerFunnel_v1', isAllowedSessionHandler, isAllowedClient, accessVerification( {
|
|
163
|
+
userType: [ 'tango', 'client' ], access: [
|
|
164
|
+
{ featureName: 'TangoEye', name: 'ZoneTag', permissions: [] },
|
|
165
|
+
],
|
|
166
|
+
} ), validate( validationDtos.validatezoneSegmaentationTableParams ), ZonewiseCustomerFunnelV1 )
|
|
167
|
+
.post( '/ZonewiseCustomerFunnel_Export', isAllowedSessionHandler, isAllowedClient, accessVerification( {
|
|
168
|
+
userType: [ 'tango', 'client' ], access: [
|
|
169
|
+
{ featureName: 'TangoEye', name: 'ZoneTag', permissions: [] },
|
|
170
|
+
],
|
|
171
|
+
} ), validate( validationDtos.validatezoneInteractionTable430ExportParams ), ZonewiseCustomerFunnelExport )
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
.post( '/getNewZoneFF_v2', getNewZoneFFV2 )
|
|
175
|
+
.post( '/getSelectedZoneFF_v2', getSelectedZoneFFV2 )
|
|
176
|
+
.post( '/getZoneAPI_v2', getZoneAPIFFV2 )
|
|
177
|
+
.post( '/getNewHoTColdZone_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateTopPerformingZonesSchema ), getNewHoTColdZoneV1 )
|
|
178
|
+
.post( '/getNewZoneShopperAnalysis_v1', getNewZoneShopperAnalysisV1 )
|
|
179
|
+
.post( '/getNewZoneShopperBubbleChart_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateTopPerformingZonesSchema ), getNewZoneShopperBubbleChartV1 )
|
|
180
|
+
.post( '/getNewCustomerTravelZone_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateTopPerformingZonesSchema ), getNewCustomerTravelZoneV1 )
|
|
181
|
+
.post( '/getNewAnalysisZone_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateTopPerformingZonesSchema ), getNewAnalysisZoneV1 )
|
|
182
|
+
.post( '/getOverallStoreCards_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateTopPerformingZonesSchema ), getOverallStoreCardsV1 );
|
|
145
183
|
export default analysisZoneRouter;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import model from 'tango-api-schema';
|
|
2
|
+
|
|
3
|
+
export const find = ( query = {}, record = {} ) => {
|
|
4
|
+
return model.clientModel.find( query, record );
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const findOne = ( query = {}, record = {} ) => {
|
|
8
|
+
return model.clientModel.findOne( query, record ).sort( { updatedAt: -1 } );
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const updateOne = ( query = {}, record = {} ) => {
|
|
12
|
+
return model.clientModel.updateOne( query, { $set: record } );
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const aggregate = ( query = [] ) => {
|
|
16
|
+
return model.clientModel.aggregate( query );
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const getClientCount = ( query = {} ) => {
|
|
20
|
+
return model.clientModel.count( query );
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
|