tango-app-api-analysis-traffic 3.8.7-vms.2 → 3.8.7-vms.4

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-traffic",
3
- "version": "3.8.7-vms.2",
3
+ "version": "3.8.7-vms.4",
4
4
  "description": "Traffic Analysis",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -306,12 +306,19 @@ export async function storeProcessedData( req, res ) {
306
306
  },
307
307
  },
308
308
  size: 1,
309
- _source: [ 'status' ],
309
+ _source: [ 'status', 'mappingInfo' ],
310
310
  };
311
311
  try {
312
312
  const footfallDirRes = await getOpenSearchData( openSearch.footfallDirectory, footfallDirQuery );
313
313
  const hit = footfallDirRes?.body?.hits?.hits?.[0];
314
- ticketStatus = hit?._source?.status || null;
314
+ if ( hit?._source?.mappingInfo && Array.isArray( hit._source.mappingInfo ) ) {
315
+ for ( let i = 0; i < hit._source.mappingInfo.length; i++ ) {
316
+ if ( hit._source.mappingInfo[i].type === 'tagging' ) {
317
+ ticketStatus = hit._source.mappingInfo[i].status;
318
+ break;
319
+ }
320
+ }
321
+ }
315
322
  } catch ( err ) {
316
323
  logger.warn( { message: 'Could not get ticket status from footfallDirectory', error: err } );
317
324
  }
@@ -335,7 +342,27 @@ export async function storeProcessedData( req, res ) {
335
342
  downtime: processedData?.down_time || 0,
336
343
  ticketStatus,
337
344
  raisedStatusEnabled,
345
+
338
346
  } );
347
+
348
+ if ( raisedStatusEnabled === 'block' ) {
349
+ // Calculate the number of days from currentDate + 1 to the end of the month
350
+ // Assume currentDate is in format 'YYYY-MM-DD'
351
+ const currentDateObj = new Date( currentDate );
352
+ // Move to next day
353
+ const nextDay = new Date( currentDateObj );
354
+ nextDay.setDate( currentDateObj.getDate() + 1 );
355
+
356
+ // Get the last date of the current month
357
+ const endOfMonth = new Date( currentDateObj.getFullYear(), currentDateObj.getMonth() + 1, 0 );
358
+
359
+ // Calculate number of days (inclusive of end date, exclusive of nextDay)
360
+ let noOfBlockedDays = Math.floor( ( endOfMonth - nextDay ) / ( 1000 * 60 * 60 * 24 ) ) + 1;
361
+ if ( noOfBlockedDays < 0 ) noOfBlockedDays = 0;
362
+
363
+ // Add to response
364
+ responseArray[responseArray.length - 1].noOfBlockedDays = noOfBlockedDays;
365
+ }
339
366
  }
340
367
 
341
368
  return res.sendSuccess( responseArray );
@@ -379,40 +406,112 @@ export async function footFallImages( req, res ) {
379
406
  ],
380
407
  },
381
408
  },
382
- // '_source': [ 'dateString', 'storeId', 'duplicateCount', 'footfallCount', 'employeeCount', 'houseKeepingCount', 'junkCount', 'status', 'ticketId', 'comments', 'userName', 'role', 'createdAt', 'email', 'houseKeepingACCount', 'duplicateACCount', 'employeeACCount', 'junkACCount', 'approverEmail', 'approverRole', 'approverUserName' ],
409
+ '_source': [ 'dateString', 'storeId', 'mappingInfo', 'revicedFootfall', 'revicedPerc', 'createdAt', 'updatedAt', 'footfallCount' ],
383
410
 
384
411
  };
385
412
 
386
413
  const getData = await getOpenSearchData( opensearch.footfallDirectory, query );
387
414
  const ticketDetails = getData?.body?.hits?.hits[0];
388
415
  let temp = [];
389
- ticketDetails?._source? temp.push( ticketDetails?._source ) :null;
390
- // temp[0].status = 'open';
391
- if ( ticketDetails?._source?.status == 'closed' ) {
392
- delete temp[0].status;
393
- temp.push( { ...ticketDetails?._source, status: 'closed' } );
394
-
395
- temp[1].userName = getData?.body?.hits?.hits?.[0]?._source?.approverUserName;
396
- temp[1].email = getData?.body?.hits?.hits?.[0]?._source?.approverEmail;
397
- temp[1].role = getData?.body?.hits?.hits?.[0]?._source?.approverRole;
398
- temp[1].employeeCount = getData?.body?.hits?.hits?.[0]?._source?.employeeACCount;
399
- temp[1].houseKeepingCount = getData?.body?.hits?.hits?.[0]?._source?.houseKeepingACCount;
400
- temp[1].duplicateCount = getData?.body?.hits?.hits?.[0]?._source?.duplicateACCount;
401
- temp[1].junkCount = getData?.body?.hits?.hits?.[0]?._source?.junkACCount;
402
- }
403
- const LamdaURL = revop.getImages;
404
- let resultData = await LamdaServiceCall( LamdaURL, inputData );
405
- logger.info( { resultData: resultData } );
406
- if ( resultData ) {
407
- temp.length? temp[0].status = 'open': null;
408
- if ( resultData.status_code == '200' ) {
409
- return res.sendSuccess( { ...resultData, ticketStatus: temp?.length > 0? temp : null, config: req?.store?.footfallDirectoryConfigs } );
410
- } else {
411
- return res.sendError( 'No Content', 204 );
412
- }
413
- } else {
414
- return res.sendError( 'No Content', 204 );
415
- }
416
+ const footfallValue = ticketDetails?._source?.footfallCount ?? 0;
417
+ const mappingInfoArray = ticketDetails?._source?.mappingInfo ?? [];
418
+
419
+ // Helper to get mappingInfo for an actionType
420
+ function getMappingForType( type ) {
421
+ return mappingInfoArray.find( ( m ) => m.type === type ) || {};
422
+ }
423
+
424
+ // List of actionTypes to process in sequence
425
+
426
+ if ( req.user.userType !== 'tango' && req.user.role !== 'superadmin' ) {
427
+ switch ( req.user.role ) {
428
+ case 'user':
429
+ const actionTypesUser = [ 'tagging', 'finalreview' ];
430
+ temp = actionTypesUser.map( ( type ) => {
431
+ const mapping = getMappingForType( type );
432
+
433
+ const revisedFootfall = mapping.revisedFootfall ?? 0;
434
+ // Do not divide by 0
435
+ const revisedPerc =
436
+ footfallValue > 0 ?
437
+ `${Math.round( ( revisedFootfall / footfallValue ) * 100 )}` :
438
+ '0';
439
+
440
+ // Since keys in count can be dynamic, just deep copy the count object or empty object
441
+ const countObj = mapping.count ? { ...mapping.count } : {};
442
+
443
+ return {
444
+ actionType: type,
445
+ footfall: footfallValue,
446
+ revicedFootfall: revisedFootfall,
447
+ revicedPerc: revisedPerc,
448
+ count: countObj,
449
+ };
450
+ } );
451
+ break;
452
+ case 'admin':
453
+ const actionTypesAdmin = [ 'tagging', 'review', 'finalreview' ];
454
+ temp = actionTypesAdmin.map( ( type ) => {
455
+ const mapping = getMappingForType( type );
456
+
457
+ const revisedFootfall = mapping.revisedFootfall ?? 0;
458
+ // Do not divide by 0
459
+ const revisedPerc =
460
+ footfallValue > 0 ?
461
+ `${Math.round( ( revisedFootfall / footfallValue ) * 100 )}` :
462
+ '0';
463
+
464
+ // Since keys in count can be dynamic, just deep copy the count object or empty object
465
+ const countObj = mapping.count ? { ...mapping.count } : {};
466
+
467
+ return {
468
+ actionType: type,
469
+ footfall: footfallValue,
470
+ revicedFootfall: revisedFootfall,
471
+ revicedPerc: revisedPerc,
472
+ count: countObj,
473
+ };
474
+ } );
475
+ break;
476
+ }
477
+ } else {
478
+ const actionTypes = [ 'tagging', 'review', 'approve', 'finalreview' ];
479
+ temp = actionTypes.map( ( type ) => {
480
+ const mapping = getMappingForType( type );
481
+
482
+ const revisedFootfall = mapping.revisedFootfall ?? 0;
483
+ // Do not divide by 0
484
+ const revisedPerc =
485
+ footfallValue > 0 ?
486
+ `${Math.round( ( revisedFootfall / footfallValue ) * 100 )}` :
487
+ '0';
488
+
489
+ // Since keys in count can be dynamic, just deep copy the count object or empty object
490
+ const countObj = mapping.count ? { ...mapping.count } : {};
491
+
492
+ return {
493
+ actionType: type,
494
+ footfall: footfallValue,
495
+ revicedFootfall: revisedFootfall,
496
+ revicedPerc: revisedPerc,
497
+ count: countObj,
498
+ };
499
+ } );
500
+ }
501
+
502
+
503
+ const LamdaURL = revop.getImages;
504
+ let resultData = await LamdaServiceCall( LamdaURL, inputData );
505
+ if ( resultData ) {
506
+ // temp.length? temp[0].status = 'open': null;
507
+ if ( resultData.status_code == '200' ) {
508
+ return res.sendSuccess( { ...resultData, ticketStatus: temp?.length > 0? temp : null, config: req?.store?.footfallDirectoryConfigs } );
509
+ } else {
510
+ return res.sendError( 'No Content', 204 );
511
+ }
512
+ } else {
513
+ return res.sendError( 'No Content', 204 );
514
+ }
416
515
  } catch ( error ) {
417
516
  logger.error( { message: error, data: req.query, function: 'storeProcessedData' } );
418
517
  const err = error.message || 'Internal Server Error';