tango-app-api-analysis-zone 3.4.0 → 3.7.1-alpha.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tango-app-api-analysis-zone",
3
- "version": "3.4.0",
3
+ "version": "3.7.1-alpha.1",
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.1.45",
24
+ "tango-app-api-middleware": "^3.1.77",
25
25
  "winston": "^3.13.1",
26
26
  "winston-daily-rotate-file": "^5.0.0"
27
27
  },
@@ -1,4 +1,4 @@
1
- import { logger, download } from 'tango-app-api-middleware';
1
+ import { logger, download, convertSecondstoTimeFormat } from 'tango-app-api-middleware';
2
2
  import { findOneUserAssignedStore } from '../services/userAssignedStore.service.js';
3
3
 
4
4
  // Lamda Service Call //
@@ -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
  }
@@ -298,26 +298,28 @@ export const zoneInteractionTable430 = async ( req, res ) => {
298
298
  let resultData = await LamdaServiceCall( LamdaURL, reqestData );
299
299
  if ( resultData ) {
300
300
  if ( resultData.status_code == '200' ) {
301
- if ( reqestData.export ) {
302
- if ( resultData.data.length>0 ) {
303
- const exportdata = [];
304
- resultData.data.forEach( ( element ) => {
305
- exportdata.push( {
306
- 'Passer By': element.passer_by || '--',
307
- 'Footfall': element.footfall || '--',
308
- 'Drop In Rate': element.drop_in_rate +'%',
309
- 'Customer Attended ': element.customer_attended || '--',
310
- 'Interation Rate ': element.interaction_rate +'%',
311
- 'Billing Conversion': element.footfall_overamin_inzone || '--',
312
- 'Billing Conversion Rate': element.billing_conversion_rate +'%',
313
- 'Greetings Count': element.greeting_count || '--',
314
- } );
315
- } );
316
- return await download( exportdata, res );
317
- } else {
318
- return res.sendError( 'No Content', 204 );
319
- }
320
- }
301
+ resultData.data[0].assist_time_string = await convertSecondstoTimeFormat( resultData.data[0].assist_time );
302
+ resultData.data[0].avg_interaction_time_string = await convertSecondstoTimeFormat( resultData.data[0].avg_interaction_time );
303
+ // if ( reqestData.export ) {
304
+ // if ( resultData.data.length>0 ) {
305
+ // const exportdata = [];
306
+ // resultData.data.forEach( ( element ) => {
307
+ // exportdata.push( {
308
+ // 'Passer By': element.passer_by || '--',
309
+ // 'Footfall': element.footfall || '--',
310
+ // 'Drop In Rate': element.drop_in_rate +'%',
311
+ // 'Customer Attended ': element.customer_attended || '--',
312
+ // 'Interation Rate ': element.interaction_rate +'%',
313
+ // 'Billing Conversion': element.footfall_overamin_inzone ?? '--',
314
+ // 'Billing Conversion Rate': element.billing_conversion_rate +'%',
315
+ // 'Greetings Count': element.greeting_count ?? '--',
316
+ // } );
317
+ // } );
318
+ // return await download( exportdata, res );
319
+ // } else {
320
+ // return res.sendError( 'No Content', 204 );
321
+ // }
322
+ // }
321
323
  return res.sendSuccess( resultData );
322
324
  } else {
323
325
  return res.sendError( 'No Content', 204 );
@@ -420,7 +422,7 @@ export const zoneInteractionTableExport430 = async ( req, res ) => {
420
422
  exportdata.push( {
421
423
  'Store Id': element.store_id || '--',
422
424
  'Date': element.date || '--',
423
- 'Customer spent more than 10 mins': element.customer_count_over10min || '--',
425
+ 'Customer spent more than 10 mins': element.customer_count_over10min ?? '--',
424
426
  'Billing Conversion': element.billing_conversion || '--',
425
427
  } );
426
428
  } );
@@ -455,7 +457,7 @@ export const zoneConcentrationTableExport = async ( req, res ) => {
455
457
  exportdata.push( {
456
458
  'Date': element.Date,
457
459
  'Zone Name': element.zoneName,
458
- 'Footfall(Actuals)': element.footfallCount || '--',
460
+ 'Footfall(Actuals)': element.footfallCount ?? '--',
459
461
  'DwellTime(Average)': element.avgDwellTime || '--',
460
462
  'Concentration': element.concentrationRate +'%',
461
463
  } );
@@ -492,7 +494,7 @@ export const zoneSegmentationV1Export = async ( req, res ) => {
492
494
  const exportItem = {
493
495
  'Date': element.date,
494
496
  'Entrance': element.category,
495
- 'Entrance wise footfall': element.value,
497
+ 'Entrance wise footfall': element.value ?? '--',
496
498
  };
497
499
  if ( clientId === '463' ) {
498
500
  exportItem['Concentration Rate'] = element?.concentrationRate ? element?.concentrationRate + '%' : '--';
@@ -526,21 +528,24 @@ export const zoneInteractionTable430Export = async ( req, res ) => {
526
528
  if ( reqestData.export ) {
527
529
  if ( resultData.data.length>0 ) {
528
530
  const exportdata = [];
529
- resultData.data.forEach( ( element ) => {
531
+ for ( let element of resultData.data ) {
532
+ element.assist_time_string = await convertSecondstoTimeFormat( element.assist_time );
533
+ element.avg_interaction_time_string = await convertSecondstoTimeFormat( element.avg_interaction_time );
530
534
  exportdata.push( {
531
535
  'Date': element.date || '--',
532
536
  'Passer By': element.passer_by || '--',
533
537
  'Footfall': element.footfall || '--',
534
538
  'Drop In Rate': element.drop_in_rate +'%',
535
- 'Greetings Count': element.greeting_count || '--',
539
+ 'Greetings Count': element.greeting_count ?? '--',
536
540
  'Greetings Rate': ( ( element.greeting_count / element.footfall ) * 100 ).toFixed( 1 ) + '%' || '--',
537
541
  'Customer Interacted': element.customer_attended || '--',
538
542
  'Interation Rate ': element.interaction_rate +'%',
539
- 'Avg Time To Interact': element.avg_interaction_time || '--',
540
- 'Billing Conversion': element.footfall_overamin_inzone || '--',
543
+ 'Avg Time Taken to Assist a Customer': element.avg_interaction_time_string ?? '--',
544
+ 'Avg Time Spent with Customer': element.assist_time_string ?? '--',
545
+ 'Billing Conversion': element.footfall_overamin_inzone ?? '--',
541
546
  'Billing Conversion Rate': element.billing_conversion_rate +'%',
542
547
  } );
543
- } );
548
+ }
544
549
  return await download( exportdata, res );
545
550
  } else {
546
551
  return res.sendError( 'No Content', 204 );
@@ -554,6 +559,7 @@ export const zoneInteractionTable430Export = async ( req, res ) => {
554
559
  return res.sendError( 'No Content', 204 );
555
560
  }
556
561
  } catch ( error ) {
562
+ // console.log( 'error', error );
557
563
  logger.error( { error: error, message: req.query, function: 'zoneInteractionTable430Export' } );
558
564
  return res.sendError( { error: error }, 500 );
559
565
  }
@@ -591,7 +597,7 @@ export const zoneSegmentationTableExport = async ( req, res ) => {
591
597
  resultData.zoneConcentrationData.forEach( ( element ) => {
592
598
  exportdata.push( {
593
599
  'Zone Name': element?.zoneName || '--',
594
- 'Footfall': element?.footfallCount || '--',
600
+ 'Footfall': element?.footfallCount ?? '--',
595
601
  'Avg.Dwell Time (Mins)': element?.avgDwellTime || '--',
596
602
  'Trolley': element?.Trolley ? element?.Trolley: 0,
597
603
  'Basket': element?.Basket ? element?.Basket : 0,
@@ -652,7 +658,7 @@ export const zonePasserByTable430Export = async ( req, res ) => {
652
658
  exportdata.push( {
653
659
  'Date': element?.date_string || '--',
654
660
  'Camera Name': element?.streamName || '--',
655
- 'Passer-by Count': element?.passerby_count || '--',
661
+ 'Passer-by Count': element?.passerby_count ?? '--',
656
662
  } );
657
663
  } );
658
664
  return await download( exportdata, res );
@@ -676,7 +682,7 @@ export const zonePasserByTable430Export = async ( req, res ) => {
676
682
  export const interactionTableV1 = async ( req, res ) => {
677
683
  try {
678
684
  let reqestData = req.body;
679
- let LamdaURL = 'https://ciwoce4ore3iyx5x5eicp2lpii0yutva.lambda-url.ap-south-1.on.aws/';
685
+ let LamdaURL = 'https://x5rjtf6uylkgie62dwmp2dpjra0txbve.lambda-url.ap-south-1.on.aws/';
680
686
  let resultData = await LamdaServiceCall( LamdaURL, reqestData );
681
687
  if ( resultData ) {
682
688
  if ( resultData.status_code == '200' ) {
@@ -692,4 +698,115 @@ export const interactionTableV1 = async ( req, res ) => {
692
698
  return res.sendError( { error: error }, 500 );
693
699
  }
694
700
  };
701
+ export const interactionTable430Export = async ( req, res ) => {
702
+ try {
703
+ let reqestData = req.body;
704
+ if ( reqestData.export ) {
705
+ reqestData.limit = 10000;
706
+ }
707
+ let LamdaURL = 'https://x5rjtf6uylkgie62dwmp2dpjra0txbve.lambda-url.ap-south-1.on.aws/';
708
+ let resultData = await LamdaServiceCall( LamdaURL, reqestData );
709
+ if ( resultData ) {
710
+ if ( resultData.status_code == '200' ) {
711
+ if ( reqestData.export ) {
712
+ if ( resultData.data.length > 0 ) {
713
+ const exportdata = [];
714
+ resultData.data.forEach( ( element ) => {
715
+ exportdata.push( {
716
+ 'Date': element?.storeDate || '--',
717
+ 'Category': element?.category || '--',
718
+ 'Value': element?.value ?? '--',
719
+ } );
720
+ } );
721
+ return await download( exportdata, res );
722
+ } else {
723
+ return res.sendError( 'No Content', 204 );
724
+ }
725
+ }
726
+ return res.sendSuccess( resultData );
727
+ } else {
728
+ return res.sendError( 'No Content', 204 );
729
+ }
730
+ } else {
731
+ return res.sendError( 'No Content', 204 );
732
+ }
733
+ } catch ( error ) {
734
+ logger.error( { error: error, message: req.query, function: 'interactionTable430Export' } );
735
+ return res.sendError( { error: error }, 500 );
736
+ }
737
+ };
738
+ export const ZonewiseCustomerFunnelV1 = async ( req, res ) => {
739
+ try {
740
+ let reqestData = req.body;
741
+ let LamdaURL = 'https://7q6v4wppeubi5kgdffwm37az2e0bfkak.lambda-url.ap-south-1.on.aws/';
742
+ let resultData = await LamdaServiceCall( LamdaURL, reqestData );
743
+ if ( resultData ) {
744
+ if ( resultData.status_code == '200' ) {
745
+ resultData.data[0].assist_time_string = await convertSecondstoTimeFormat( resultData.data[0].assist_time );
746
+ resultData.data[0].avg_interaction_time_string = await convertSecondstoTimeFormat( resultData.data[0].avg_interaction_time );
747
+ return res.sendSuccess( resultData );
748
+ } else {
749
+ return res.sendError( 'No Content', 204 );
750
+ }
751
+ } else {
752
+ return res.sendError( 'No Content', 204 );
753
+ }
754
+ } catch ( error ) {
755
+ logger.error( { error: error, message: req.query, function: 'ZonewiseCustomerFunnelV1' } );
756
+ return res.sendError( { error: error }, 500 );
757
+ }
758
+ };
759
+
760
+ export const ZonewiseCustomerFunnelExport = async ( req, res ) => {
761
+ try {
762
+ let reqestData = req.body;
763
+ let LamdaURL = 'https://7q6v4wppeubi5kgdffwm37az2e0bfkak.lambda-url.ap-south-1.on.aws/';
764
+ let resultData = await LamdaServiceCall( LamdaURL, reqestData );
765
+ if ( resultData ) {
766
+ if ( resultData.status_code == '200' ) {
767
+ // resultData.data[0].assist_time_string = await convertSecondstoTimeFormat( resultData.data[0].assist_time );
768
+ // resultData.data[0].avg_interaction_time_string = await convertSecondstoTimeFormat( resultData.data[0].avg_interaction_time );
769
+ if ( reqestData.export ) {
770
+ if ( resultData.data.length > 0 ) {
771
+ const exportdata = [];
772
+ for ( let element of resultData.data ) {
773
+ element.assist_time_string = await convertSecondstoTimeFormat( element.assist_time );
774
+ element.avg_interaction_time_string = await convertSecondstoTimeFormat( element.avg_interaction_time );
775
+ const row = {
776
+ 'Date': element.date || '--',
777
+ 'Footfall': element.footfall ?? '--',
778
+ 'Greetings Count': element.greeting_count ?? '--',
779
+ 'Greetings Rate': ( element.greeting_count && element.footfall ) ? ( ( element.greeting_count / element.footfall ) * 100 ).toFixed( 1 ) + '%': '--',
780
+ 'Customer Interacted': element.customer_attended ?? '--',
781
+ 'Interation Rate ': element.interaction_rate != null ? element.interaction_rate + '%' : '--',
782
+ 'Avg Time Taken to Assist a Customer': element.avg_interaction_time_string ?? '--',
783
+ 'Avg Time Spent with Customer': element.assist_time_string ?? '--',
784
+ };
785
+ if ( element.footfall_overamin_inzone != null ) {
786
+ row['Billing Conversion'] = element.footfall_overamin_inzone;
787
+ }
788
+ if ( element.billing_conversion_rate != null ) {
789
+ row['Billing Conversion Rate'] = element.billing_conversion_rate + '%';
790
+ }
791
+
792
+ exportdata.push( row );
793
+ };
794
+ return await download( exportdata, res );
795
+ } else {
796
+ return res.sendError( 'No Content', 204 );
797
+ }
798
+ }
799
+ return res.sendSuccess( resultData );
800
+ } else {
801
+ return res.sendError( 'No Content', 204 );
802
+ }
803
+ } else {
804
+ return res.sendError( 'No Content', 204 );
805
+ }
806
+ } catch ( error ) {
807
+ // console.log( 'error', error );
808
+ logger.error( { error: error, message: req.query, function: 'ZonewiseCustomerFunnelExport' } );
809
+ return res.sendError( { error: error }, 500 );
810
+ }
811
+ };
695
812
 
@@ -314,19 +314,19 @@ 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.export ) {
318
- if ( resultData.customerJourneyTableData.length>0 ) {
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
- return await download( exportdata, res );
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
+ return await download( resultData.customerJourneyTableData, res );
330
330
  } else {
331
331
  return res.sendError( 'No Content', 204 );
332
332
  }
@@ -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,9 @@ import {
36
36
  zonePasserByTableV1,
37
37
  zonePasserByTable430Export,
38
38
  interactionTableV1,
39
+ interactionTable430Export,
40
+ ZonewiseCustomerFunnelV1,
41
+ ZonewiseCustomerFunnelExport,
39
42
  } from '../controllers/analysisZoneV1.controllers.js';
40
43
 
41
44
  analysisZoneRouter
@@ -141,5 +144,21 @@ analysisZoneRouter
141
144
  userType: [ 'tango', 'client' ], access: [
142
145
  { featureName: 'TangoEye', name: 'ZoneTag', permissions: [] },
143
146
  ],
144
- } ), validate( validationDtos.validatezoneSegmaentationTableParams ), interactionTableV1 );
147
+ } ), validate( validationDtos.validatezoneSegmaentationTableParams ), interactionTableV1 )
148
+ .post( '/interactionTable_430Export', isAllowedSessionHandler, isAllowedClient, accessVerification( {
149
+ userType: [ 'tango', 'client' ], access: [
150
+ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [] },
151
+ ],
152
+ } ), validate( validationDtos.validatezoneSegmaentationTableParams ), interactionTable430Export )
153
+ .post( '/ZonewiseCustomerFunnel_v1', isAllowedSessionHandler, isAllowedClient, accessVerification( {
154
+ userType: [ 'tango', 'client' ], access: [
155
+ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [] },
156
+ ],
157
+ } ), validate( validationDtos.validatezoneSegmaentationTableParams ), ZonewiseCustomerFunnelV1 )
158
+ .post( '/ZonewiseCustomerFunnel_Export', isAllowedSessionHandler, isAllowedClient, accessVerification( {
159
+ userType: [ 'tango', 'client' ], access: [
160
+ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [] },
161
+ ],
162
+ } ), validate( validationDtos.validatezoneInteractionTable430ExportParams ), ZonewiseCustomerFunnelExport );
163
+
145
164
  export default analysisZoneRouter;