tango-app-api-infra 3.1.17 → 3.1.18

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.
@@ -314,21 +314,20 @@ export async function installationCard( req, res ) {
314
314
  export async function infraIssuesTable( req, res ) {
315
315
  try {
316
316
  let date = await getUTC( new Date( req.body.fromDate ), new Date( req.body.toDate ) );
317
- let issueStatus = [ 'identified' ];
317
+ let issueStatus = [ 'notidentified', 'identified' ];
318
+
318
319
  if ( req.body.infrafilterIssue == 'Issues Not Identified' ) {
319
320
  issueStatus = [ 'notidentified' ];
320
321
  };
321
- if ( req.body.infrafilterIssue == 'All Issues' ) {
322
- issueStatus = [ 'notidentified', 'identified' ];
323
- };
324
- if ( req.body.infrafilterIssue == 'Live Stores' ) {
325
- issueStatus = [ 'notidentified', 'identified' ];
322
+ if ( req.body.infrafilterIssue == 'Identified Issues' ) {
323
+ issueStatus = [ 'identified' ];
326
324
  };
325
+
326
+
327
327
  let totalstores = await aggregateStore( [ {
328
328
  $match: {
329
329
  '$and': [
330
330
  { 'clientId': { $in: req.body.clientId } },
331
- { 'edge.firstFile': true },
332
331
  { 'status': 'active' },
333
332
  { 'createdAt': { $lte: date.end } },
334
333
  ],
@@ -338,96 +337,115 @@ export async function infraIssuesTable( req, res ) {
338
337
  for ( let store of totalstores ) {
339
338
  totalnumberstores.push( store.storeId );
340
339
  }
341
- let query = [ {
340
+ let pendingquery = [];
341
+ pendingquery.push( {
342
342
  $match: {
343
343
  $and: [
344
- { issueType: 'infra' },
345
- { status: { $ne: 'closed' } },
344
+ { issueType: 'installation' },
345
+ { 'status': { $ne: 'closed' } },
346
346
  { 'basicDetails.clientId': { $in: req.body.clientId } },
347
- { 'basicDetails.storeId': { $in: totalnumberstores } },
348
- { 'ticketDetails.issueStatus': { $in: issueStatus } },
349
- // { createdAt: { $gte: date.start } },
350
347
  { createdAt: { $lte: date.end } },
351
348
  ],
352
349
  },
353
- },
354
- {
355
- $project: {
356
- storeId: '$basicDetails.storeId',
357
- clientId: '$basicDetails.clientId',
358
- ticketId: 1,
359
- storeName: '$basicDetails.storeName',
360
- clientName: '$basicDetails.clientName',
361
- status: 1,
362
- createdAt: 1,
363
- issueIdentifiedDate: '$ticketDetails.issueIdentifiedDate',
364
- issueClosedDate: '$issueClosedDate',
365
- primaryIssue: {
366
- $filter: {
367
- input: '$ticketActivity',
368
- as: 'item',
369
- cond: { $eq: [ '$$item.actionType', 'issueUpdate' ] },
350
+ } );
351
+ let pendingstorecount = await aggregateTangoTicket( pendingquery );
352
+ let installpendingticket = pendingstorecount.map( ( store ) => store.basicDetails.storeId );
353
+
354
+
355
+ let query = [
356
+ {
357
+ $match: {
358
+ $and: [
359
+ { issueType: 'infra' },
360
+ { status: { $ne: 'closed' } },
361
+ { 'basicDetails.clientId': { $in: req.body.clientId } },
362
+ { 'basicDetails.storeId': { $in: totalnumberstores } },
363
+ { 'ticketDetails.issueStatus': { $in: issueStatus } },
364
+ { createdAt: { $lte: date.end } },
365
+ ],
366
+ },
367
+ },
368
+ {
369
+ $project: {
370
+ storeId: '$basicDetails.storeId',
371
+ clientId: '$basicDetails.clientId',
372
+ ticketId: 1,
373
+ storeName: '$basicDetails.storeName',
374
+ clientName: '$basicDetails.clientName',
375
+ status: 1,
376
+ createdAt: 1,
377
+ issueIdentifiedDate: '$ticketDetails.issueIdentifiedDate',
378
+ issueClosedDate: '$issueClosedDate',
379
+ primaryIssue: {
380
+ $filter: {
381
+ input: '$ticketActivity',
382
+ as: 'item',
383
+ cond: { $eq: [ '$$item.actionType', 'issueUpdate' ] },
384
+ },
370
385
  },
371
386
  },
372
387
  },
373
- },
374
- {
375
- $unwind: {
376
- path: '$primaryIssue', preserveNullAndEmptyArrays: true,
388
+ {
389
+ $unwind: {
390
+ path: '$primaryIssue',
391
+ preserveNullAndEmptyArrays: true,
392
+ },
377
393
  },
378
- },
379
- {
380
- $unwind: {
381
- path: '$primaryIssue.reasons', preserveNullAndEmptyArrays: true,
394
+ {
395
+ $unwind: {
396
+ path: '$primaryIssue.reasons',
397
+ preserveNullAndEmptyArrays: true,
398
+ },
382
399
  },
383
- },
384
- {
385
- $unwind: {
386
- path: '$primaryIssue.reasons.secondaryIssue', preserveNullAndEmptyArrays: true,
400
+ {
401
+ $unwind: {
402
+ path: '$primaryIssue.reasons.secondaryIssue',
403
+ preserveNullAndEmptyArrays: true,
404
+ },
387
405
  },
388
- },
389
- {
390
- $project: {
391
- storeId: 1,
392
- clientId: 1,
393
- storeName: 1,
394
- createdAt: 1,
395
- ticketId: 1,
396
- clientName: 1,
397
- actionBy: '$primaryIssue.actionBy',
398
- issueIdentifiedDate: { $ifNull: [ '$issueIdentifiedDate', '' ] },
399
- issueClosedDate: { $ifNull: [ '$issueClosedDate', '' ] },
400
- status: 1,
401
- primaryIssue: { $ifNull: [ '$primaryIssue.reasons.primaryIssue', '-' ] },
402
- secondaryIssue: { $ifNull: [ '$primaryIssue.reasons.secondaryIssue.name', '-' ] },
406
+ {
407
+ $project: {
408
+ storeId: 1,
409
+ clientId: 1,
410
+ storeName: 1,
411
+ createdAt: 1,
412
+ ticketId: 1,
413
+ clientName: 1,
414
+ actionBy: '$primaryIssue.actionBy',
415
+ issueIdentifiedDate: { $ifNull: [ '$issueIdentifiedDate', '' ] },
416
+ issueClosedDate: { $ifNull: [ '$issueClosedDate', '' ] },
417
+ status: 1,
418
+ primaryIssue: { $ifNull: [ '$primaryIssue.reasons.primaryIssue', '-' ] },
419
+ secondaryIssue: { $ifNull: [ '$primaryIssue.reasons.secondaryIssue.name', '-' ] },
420
+ },
403
421
  },
404
- },
405
- {
406
- $group: {
407
- _id: '$ticketId',
408
- storeId: { $first: '$storeId' },
409
- clientId: { $first: '$clientId' },
410
- ticketId: { $first: '$ticketId' },
411
- actionBy: { $first: '$actionBy' },
412
- storeName: { $first: '$storeName' },
413
- clientName: { $first: '$clientName' },
414
- createdAt: { $first: '$createdAt' },
415
- issueIdentifiedDate: { $last: '$issueIdentifiedDate' },
416
- issueClosedDate: { $last: '$issueClosedDate' },
417
- status: { $last: '$status' },
418
- primaryIssue: { $last: '$primaryIssue' },
419
- secondaryIssue: { $last: '$secondaryIssue' },
422
+ {
423
+ $group: {
424
+ _id: '$ticketId',
425
+ storeId: { $first: '$storeId' },
426
+ clientId: { $first: '$clientId' },
427
+ ticketId: { $first: '$ticketId' },
428
+ actionBy: { $first: '$actionBy' },
429
+ storeName: { $first: '$storeName' },
430
+ clientName: { $first: '$clientName' },
431
+ createdAt: { $first: '$createdAt' },
432
+ issueIdentifiedDate: { $last: '$issueIdentifiedDate' },
433
+ issueClosedDate: { $last: '$issueClosedDate' },
434
+ status: { $last: '$status' },
435
+ primaryIssue: { $last: '$primaryIssue' },
436
+ secondaryIssue: { $last: '$secondaryIssue' },
437
+ },
420
438
  },
421
- },
422
439
  ];
440
+
423
441
  let storesQuery = [];
424
442
  if ( req.body.infrafilterIssue == 'Total Stores' ) {
425
443
  storesQuery.push( {
426
444
  $match: {
427
445
  '$and': [
428
446
  { 'clientId': { $in: req.body.clientId } },
429
- { 'edge.firstFile': true },
430
447
  { 'status': 'active' },
448
+ { 'storeId': { $nin: installpendingticket } },
431
449
  { 'createdAt': { $lte: date.end } },
432
450
  ],
433
451
  },
@@ -436,16 +454,14 @@ export async function infraIssuesTable( req, res ) {
436
454
  }
437
455
  if ( req.body.infrafilterIssue == 'Live Stores' ) {
438
456
  let infrastores = await aggregateTangoTicket( query );
439
- let infraissueStore = [];
440
- for ( let store of infrastores ) {
441
- infraissueStore.push( store.storeId );
442
- }
443
- let result = [];
444
- for ( let data of totalnumberstores ) {
445
- if ( infraissueStore.length > 0 && !infraissueStore.includes( data ) ) {
446
- result.push( data );
447
- }
448
- }
457
+ let infraissueStore = infrastores.map( ( store ) => store.storeId );
458
+
459
+ let result = totalnumberstores.filter( ( data ) =>
460
+ infraissueStore.length > 0 &&
461
+ !infraissueStore.includes( data ) &&
462
+ !installpendingticket.includes( data ),
463
+ );
464
+
449
465
  storesQuery.push(
450
466
  {
451
467
  $match: {
@@ -456,34 +472,29 @@ export async function infraIssuesTable( req, res ) {
456
472
  },
457
473
  );
458
474
  }
459
- if ( req.body.infrafilterIssue && req.body.infrafilterIssue != '' &&
460
- req.body.infrafilterIssue != 'Identified Issues' &&
461
- req.body.infrafilterIssue != 'Issues Not Identified' &&
462
- req.body.infrafilterIssue != 'All Issues' ) {
475
+ const excludedIssues = [ 'Identified Issues', 'Issues Not Identified', 'All Issues' ];
476
+ if ( req.body.infrafilterIssue && !excludedIssues.includes( req.body.infrafilterIssue ) ) {
463
477
  query.push( {
464
478
  $match: {
465
479
  primaryIssue: req.body.infrafilterIssue,
466
480
  },
467
481
  } );
468
482
  }
469
- if ( req.body.searchValue && req.body.searchValue != '' ) {
470
- query.push( {
471
- $match: {
472
- $or: [
473
- { storeId: { $regex: req.body.searchValue, $options: 'i' } },
474
- { storeName: { $regex: req.body.searchValue, $options: 'i' } },
475
- ],
476
- },
477
- } );
478
- storesQuery.push( {
483
+
484
+ if ( req.body.searchValue && req.body.searchValue !== '' ) {
485
+ const searchCondition = {
479
486
  $match: {
480
487
  $or: [
481
488
  { storeId: { $regex: req.body.searchValue, $options: 'i' } },
482
489
  { storeName: { $regex: req.body.searchValue, $options: 'i' } },
483
490
  ],
484
491
  },
485
- } );
492
+ };
493
+
494
+ query.push( searchCondition );
495
+ storesQuery.push( searchCondition );
486
496
  }
497
+
487
498
  if ( req.body.filter && req.body.filter.length > 0 ) {
488
499
  query.push(
489
500
  {
@@ -494,12 +505,13 @@ export async function infraIssuesTable( req, res ) {
494
505
  );
495
506
  }
496
507
  if ( req.body.sortColumName && req.body.sortColumName !== '' && req.body.sortBy ) {
497
- query.push( {
498
- $sort: { [req.body.sortColumName]: req.body.sortBy },
499
- } );
500
- storesQuery.push( {
501
- $sort: { [req.body.sortColumName]: req.body.sortBy },
502
- } );
508
+ const sortOption = { $sort: { [req.body.sortColumName]: req.body.sortBy } };
509
+ query.push( sortOption );
510
+ storesQuery.push( sortOption );
511
+ } else {
512
+ const sortOption = { $sort: { 'storeId': -1 } };
513
+ query.push( sortOption );
514
+ storesQuery.push( sortOption );
503
515
  }
504
516
  let count;
505
517
  if ( req.body.infrafilterIssue == 'Live Stores' || req.body.infrafilterIssue == 'Total Stores' ) {
@@ -508,52 +520,56 @@ export async function infraIssuesTable( req, res ) {
508
520
  count = await aggregateTangoTicket( query );
509
521
  }
510
522
  if ( req.body.limit && req.body.offset && !req.body.export ) {
511
- query.push(
512
- { $skip: ( req.body.offset - 1 ) * req.body.limit },
513
- { $limit: Number( req.body.limit ) },
514
- );
523
+ const skipValue = ( req.body.offset - 1 ) * req.body.limit;
524
+ const limitValue = Number( req.body.limit );
525
+
526
+ const pagination = [
527
+ { $skip: skipValue },
528
+ { $limit: limitValue },
529
+ ];
530
+
531
+ query.push( ...pagination );
515
532
  storesQuery.push(
516
- { $skip: ( req.body.offset - 1 ) * req.body.limit },
517
- { $limit: Number( req.body.limit ) },
518
- );
519
- storesQuery.push( {
520
- $lookup: {
521
- from: 'clients',
522
- let: { clientId: '$clientId' },
523
- pipeline: [
524
- {
525
- $match: {
526
- $expr: {
527
- $and: [
528
- { $eq: [ '$clientId', '$$clientId' ] },
529
- ],
533
+ ...pagination,
534
+ {
535
+ $lookup: {
536
+ from: 'clients',
537
+ let: { clientId: '$clientId' },
538
+ pipeline: [
539
+ {
540
+ $match: {
541
+ $expr: {
542
+ $and: [
543
+ { $eq: [ '$clientId', '$$clientId' ] },
544
+ ],
545
+ },
546
+ },
530
547
  },
531
- },
532
-
548
+ {
549
+ $project: {
550
+ clientName: 1,
551
+ },
552
+ },
553
+ ],
554
+ as: 'client',
533
555
  },
534
- {
535
- $project: {
536
- clientName: 1,
537
- },
556
+ },
557
+ {
558
+ $unwind: { path: '$client', preserveNullAndEmptyArrays: true },
559
+ },
560
+ {
561
+ $project: {
562
+ clientName: '$client.clientName',
563
+ storeId: 1,
564
+ clientId: 1,
565
+ storeName: 1,
566
+ status: 1,
567
+ createdAt: 1,
538
568
  },
539
- ], as: 'client',
540
- },
541
- },
542
- {
543
- $unwind: { path: '$client', preserveNullAndEmptyArrays: true },
544
- },
545
- {
546
- $project: {
547
- clientName: '$client.clientName',
548
- storeId: 1,
549
- clientId: 1,
550
- storeName: 1,
551
- status: 1,
552
- createdAt: 1,
553
- },
554
- },
569
+ },
555
570
  );
556
571
  }
572
+
557
573
  let result;
558
574
  if ( req.body.infrafilterIssue == 'Live Stores' || req.body.infrafilterIssue == 'Total Stores' ) {
559
575
  result = await aggregateStore( storesQuery );
@@ -561,21 +577,30 @@ export async function infraIssuesTable( req, res ) {
561
577
  result = await aggregateTangoTicket( query );
562
578
  }
563
579
  if ( req.body.export && result.length > 0 ) {
564
- const exportdata = [];
565
- result.forEach( ( element ) => {
566
- exportdata.push( {
567
- 'Created On': element.createdAt,
568
- 'StoreID': element.storeId,
569
- 'StoreName': element.storeName,
570
- 'Primary Issue': element.primaryIssue,
571
- 'Sub Issue': element.secondaryIssue,
572
- 'Issue Identified on': element.issueIdentifiedDate? dayjs( element.issueIdentifiedDate ).tz( 'Asia/Kolkata' ).format( 'YYYY-MM-DD HH:mm A' ):'',
573
- 'Status': element.status,
574
- } );
580
+ const exportdata = result.map( ( element ) => {
581
+ if ( req.body.infrafilterIssue === 'Live Stores' || req.body.infrafilterIssue === 'Total Stores' ) {
582
+ return {
583
+ 'Created On': element.createdAt,
584
+ 'StoreID': element.storeId,
585
+ 'StoreName': element.storeName,
586
+ 'Status': element.status,
587
+ };
588
+ } else {
589
+ return {
590
+ 'Created On': element.createdAt,
591
+ 'StoreID': element.storeId,
592
+ 'StoreName': element.storeName,
593
+ 'Primary Issue': element.primaryIssue,
594
+ 'Sub Issue': element.secondaryIssue,
595
+ 'Issue Identified on': element.issueIdentifiedDate ? dayjs( element.issueIdentifiedDate ).tz( 'Asia/Kolkata' ).format( 'YYYY-MM-DD HH:mm A' ) : '',
596
+ 'Status': element.status,
597
+ };
598
+ }
575
599
  } );
576
600
  await download( exportdata, res );
577
601
  return;
578
602
  }
603
+
579
604
  if ( result.length > 0 ) {
580
605
  res.sendSuccess( {
581
606
  count: count.length,
@@ -981,111 +1006,155 @@ function generateTimeSlots( startHour, endHour, interval, time ) {
981
1006
  };
982
1007
  export async function hourWiseDownstores( req, res ) {
983
1008
  try {
984
- let inputData = req.body;
985
- inputData.Date = dayjs( req.body.toDate ).format( 'YYYY-MM-DD' );
986
- let issueStatus = [ 'identified' ];
987
- if ( req.body.filterIssue == 'Issues Not Identified' ) {
1009
+ let date = await getUTC( new Date( req.body.fromDate ), new Date( req.body.toDate ) );
1010
+ let issueStatus = [ 'notidentified', 'identified' ];
1011
+
1012
+ if ( req.body.infrafilterIssue == 'Issues Not Identified' ) {
988
1013
  issueStatus = [ 'notidentified' ];
989
1014
  };
990
- if ( req.body.filterIssue == 'All Issues' ) {
991
- issueStatus = [ 'notidentified', 'identified' ];
992
- };
993
- if ( req.body.filterIssue == 'Live Stores' ) {
994
- issueStatus = [ 'notidentified', 'identified' ];
1015
+ if ( req.body.infrafilterIssue == 'Identified Issues' ) {
1016
+ issueStatus = [ 'identified' ];
995
1017
  };
996
1018
 
1019
+
997
1020
  let totalstores = await aggregateStore( [ {
998
1021
  $match: {
999
1022
  '$and': [
1000
- { 'clientId': req.body.clientId },
1001
- { 'edge.firstFile': true },
1023
+ { 'clientId': { $in: req.body.clientId } },
1002
1024
  { 'status': 'active' },
1003
- { 'createdAt': { $lte: new Date( req.body.toDate ) } },
1025
+ { 'createdAt': { $lte: date.end } },
1004
1026
  ],
1005
1027
  },
1006
1028
  } ] );
1007
-
1008
1029
  let totalnumberstores = [];
1009
1030
  for ( let store of totalstores ) {
1010
1031
  totalnumberstores.push( store.storeId );
1011
1032
  }
1012
- let query = [ {
1033
+ let pendingquery = [];
1034
+ pendingquery.push( {
1013
1035
  $match: {
1014
1036
  $and: [
1015
- { 'basicDetails.clientId': req.body.clientId },
1016
- { 'basicDetails.storeId': { $in: totalnumberstores } },
1037
+ { issueType: 'installation' },
1017
1038
  { 'status': { $ne: 'closed' } },
1018
- { issueType: 'infra' },
1019
- { 'ticketDetails.issueStatus': { $in: issueStatus } },
1020
- { 'issueDate': { $lte: new Date( req.body.toDate ) } },
1039
+ { 'basicDetails.clientId': { $in: req.body.clientId } },
1040
+ { createdAt: { $lte: date.end } },
1021
1041
  ],
1022
1042
  },
1023
- },
1024
- {
1025
- $project: {
1026
- storeId: '$basicDetails.storeId',
1027
- storeName: '$basicDetails.storeName',
1028
- primaryIssue: {
1029
- $filter: {
1030
- input: '$ticketActivity',
1031
- as: 'item',
1032
- cond: { $eq: [ '$$item.actionType', 'issueUpdate' ] },
1043
+ } );
1044
+ let pendingstorecount = await aggregateTangoTicket( pendingquery );
1045
+ let installpendingticket = pendingstorecount.map( ( store ) => store.basicDetails.storeId );
1046
+
1047
+
1048
+ let query = [
1049
+ {
1050
+ $match: {
1051
+ $and: [
1052
+ { issueType: 'infra' },
1053
+ { status: { $ne: 'closed' } },
1054
+ { 'basicDetails.clientId': { $in: req.body.clientId } },
1055
+ { 'basicDetails.storeId': { $in: totalnumberstores } },
1056
+ { 'ticketDetails.issueStatus': { $in: issueStatus } },
1057
+ { createdAt: { $lte: date.end } },
1058
+ ],
1059
+ },
1060
+ },
1061
+ {
1062
+ $project: {
1063
+ storeId: '$basicDetails.storeId',
1064
+ clientId: '$basicDetails.clientId',
1065
+ ticketId: 1,
1066
+ storeName: '$basicDetails.storeName',
1067
+ clientName: '$basicDetails.clientName',
1068
+ status: 1,
1069
+ createdAt: 1,
1070
+ issueIdentifiedDate: '$ticketDetails.issueIdentifiedDate',
1071
+ issueClosedDate: '$issueClosedDate',
1072
+ primaryIssue: {
1073
+ $filter: {
1074
+ input: '$ticketActivity',
1075
+ as: 'item',
1076
+ cond: { $eq: [ '$$item.actionType', 'issueUpdate' ] },
1077
+ },
1033
1078
  },
1034
1079
  },
1035
1080
  },
1036
- },
1037
- {
1038
- $unwind: {
1039
- path: '$primaryIssue', preserveNullAndEmptyArrays: true,
1081
+ {
1082
+ $unwind: {
1083
+ path: '$primaryIssue',
1084
+ preserveNullAndEmptyArrays: true,
1085
+ },
1040
1086
  },
1041
- },
1042
- {
1043
- $unwind: {
1044
- path: '$primaryIssue.reasons', preserveNullAndEmptyArrays: true,
1087
+ {
1088
+ $unwind: {
1089
+ path: '$primaryIssue.reasons',
1090
+ preserveNullAndEmptyArrays: true,
1091
+ },
1045
1092
  },
1046
- },
1047
- {
1048
- $project: {
1049
- storeId: 1,
1050
- storeName: 1,
1051
- primaryIssue: { $ifNull: [ '$primaryIssue.reasons.primaryIssue', 'NotIdentified' ] },
1093
+ {
1094
+ $unwind: {
1095
+ path: '$primaryIssue.reasons.secondaryIssue',
1096
+ preserveNullAndEmptyArrays: true,
1097
+ },
1052
1098
  },
1053
- },
1054
- {
1055
- $group: {
1056
- _id: '$storeId',
1057
- storeId: { $first: '$storeId' },
1058
- storeName: { $first: '$storeName' },
1059
- primaryIssue: { $last: '$primaryIssue' },
1099
+ {
1100
+ $project: {
1101
+ storeId: 1,
1102
+ clientId: 1,
1103
+ storeName: 1,
1104
+ createdAt: 1,
1105
+ ticketId: 1,
1106
+ clientName: 1,
1107
+ actionBy: '$primaryIssue.actionBy',
1108
+ issueIdentifiedDate: { $ifNull: [ '$issueIdentifiedDate', '' ] },
1109
+ issueClosedDate: { $ifNull: [ '$issueClosedDate', '' ] },
1110
+ status: 1,
1111
+ primaryIssue: { $ifNull: [ '$primaryIssue.reasons.primaryIssue', '-' ] },
1112
+ secondaryIssue: { $ifNull: [ '$primaryIssue.reasons.secondaryIssue.name', '-' ] },
1113
+ },
1114
+ },
1115
+ {
1116
+ $group: {
1117
+ _id: '$ticketId',
1118
+ storeId: { $first: '$storeId' },
1119
+ clientId: { $first: '$clientId' },
1120
+ ticketId: { $first: '$ticketId' },
1121
+ actionBy: { $first: '$actionBy' },
1122
+ storeName: { $first: '$storeName' },
1123
+ clientName: { $first: '$clientName' },
1124
+ createdAt: { $first: '$createdAt' },
1125
+ issueIdentifiedDate: { $last: '$issueIdentifiedDate' },
1126
+ issueClosedDate: { $last: '$issueClosedDate' },
1127
+ status: { $last: '$status' },
1128
+ primaryIssue: { $last: '$primaryIssue' },
1129
+ secondaryIssue: { $last: '$secondaryIssue' },
1130
+ },
1060
1131
  },
1061
- },
1062
1132
  ];
1133
+
1063
1134
  let storesQuery = [];
1064
- if ( req.body.filterIssue == 'Total Stores' ) {
1135
+ if ( req.body.infrafilterIssue == 'Total Stores' ) {
1065
1136
  storesQuery.push( {
1066
1137
  $match: {
1067
1138
  '$and': [
1068
- { 'clientId': req.body.clientId },
1069
- { 'edge.firstFile': true },
1139
+ { 'clientId': { $in: req.body.clientId } },
1070
1140
  { 'status': 'active' },
1071
- { 'createdAt': { $lte: new Date( req.body.toDate ) } },
1141
+ { 'storeId': { $nin: installpendingticket } },
1142
+ { 'createdAt': { $lte: date.end } },
1072
1143
  ],
1073
1144
  },
1074
1145
  },
1075
1146
  );
1076
1147
  }
1077
- if ( req.body.filterIssue == 'Live Stores' ) {
1148
+ if ( req.body.infrafilterIssue == 'Live Stores' ) {
1078
1149
  let infrastores = await aggregateTangoTicket( query );
1079
- let infraissueStore = [];
1080
- for ( let store of infrastores ) {
1081
- infraissueStore.push( store.storeId );
1082
- }
1083
- let result = [];
1084
- for ( let data of totalnumberstores ) {
1085
- if ( infraissueStore.length > 0 && !infraissueStore.includes( data ) ) {
1086
- result.push( data );
1087
- }
1088
- }
1150
+ let infraissueStore = infrastores.map( ( store ) => store.storeId );
1151
+
1152
+ let result = totalnumberstores.filter( ( data ) =>
1153
+ infraissueStore.length > 0 &&
1154
+ !infraissueStore.includes( data ) &&
1155
+ !installpendingticket.includes( data ),
1156
+ );
1157
+
1089
1158
  storesQuery.push(
1090
1159
  {
1091
1160
  $match: {
@@ -1096,71 +1165,116 @@ export async function hourWiseDownstores( req, res ) {
1096
1165
  },
1097
1166
  );
1098
1167
  }
1099
- if ( req.body.searchValue && req.body.searchValue !== '' ) {
1168
+ const excludedIssues = [ 'Identified Issues', 'Issues Not Identified', 'All Issues' ];
1169
+ if ( req.body.infrafilterIssue && !excludedIssues.includes( req.body.infrafilterIssue ) ) {
1100
1170
  query.push( {
1101
1171
  $match: {
1102
- $or: [
1103
- { storeName: { $regex: req.body.searchValue, $options: 'i' } },
1104
- { storeId: { $regex: req.body.searchValue, $options: 'i' } },
1105
- ],
1172
+ primaryIssue: req.body.infrafilterIssue,
1106
1173
  },
1107
1174
  } );
1108
- storesQuery.push( {
1175
+ }
1176
+
1177
+ if ( req.body.searchValue && req.body.searchValue !== '' ) {
1178
+ const searchCondition = {
1109
1179
  $match: {
1110
1180
  $or: [
1111
- { storeName: { $regex: req.body.searchValue, $options: 'i' } },
1112
1181
  { storeId: { $regex: req.body.searchValue, $options: 'i' } },
1182
+ { storeName: { $regex: req.body.searchValue, $options: 'i' } },
1113
1183
  ],
1114
1184
  },
1115
- } );
1185
+ };
1186
+
1187
+ query.push( searchCondition );
1188
+ storesQuery.push( searchCondition );
1116
1189
  }
1117
- if ( req.body.sortColumName && req.body.sortColumName != '' && req.body.sortBy && req.body.sortBy != '' ) {
1118
- query.push( {
1119
- $sort: { [req.body.sortColumName]: req.body.sortBy },
1120
- } );
1121
- storesQuery.push( {
1122
- $sort: { [req.body.sortColumName]: req.body.sortBy },
1123
- } );
1190
+
1191
+ if ( req.body.filter && req.body.filter.length > 0 ) {
1192
+ query.push(
1193
+ {
1194
+ $match: {
1195
+ actionBy: { $in: req.body.filter },
1196
+ },
1197
+ },
1198
+ );
1124
1199
  }
1125
- if ( req.body.filterIssue && req.body.filterIssue != '' &&
1126
- req.body.filterIssue != 'Identified Issues' &&
1127
- req.body.filterIssue != 'Issues Not Identified' &&
1128
- req.body.filterIssue != 'All Issues' ) {
1129
- query.push( {
1130
- $match: {
1131
- primaryIssue: req.body.filterIssue,
1132
- },
1133
- } );
1200
+ if ( req.body.sortColumName && req.body.sortColumName !== '' && req.body.sortBy ) {
1201
+ const sortOption = { $sort: { [req.body.sortColumName]: req.body.sortBy } };
1202
+ query.push( sortOption );
1203
+ storesQuery.push( sortOption );
1204
+ } else {
1205
+ const sortOption = { $sort: { 'storeId': -1 } };
1206
+ query.push( sortOption );
1207
+ storesQuery.push( sortOption );
1134
1208
  }
1135
-
1136
1209
  let count;
1137
- if ( req.body.filterIssue == 'Live Stores' || req.body.filterIssue == 'Total Stores' ) {
1210
+ if ( req.body.infrafilterIssue == 'Live Stores' || req.body.infrafilterIssue == 'Total Stores' ) {
1138
1211
  count = await aggregateStore( storesQuery );
1139
1212
  } else {
1140
1213
  count = await aggregateTangoTicket( query );
1141
1214
  }
1142
1215
  if ( req.body.limit && req.body.offset && !req.body.export ) {
1143
- query.push(
1144
- { $skip: ( req.body.offset - 1 ) * req.body.limit },
1145
- { $limit: Number( req.body.limit ) },
1146
- );
1216
+ const skipValue = ( req.body.offset - 1 ) * req.body.limit;
1217
+ const limitValue = Number( req.body.limit );
1218
+
1219
+ const pagination = [
1220
+ { $skip: skipValue },
1221
+ { $limit: limitValue },
1222
+ ];
1223
+
1224
+ query.push( ...pagination );
1147
1225
  storesQuery.push(
1148
- { $skip: ( req.body.offset - 1 ) * req.body.limit },
1149
- { $limit: Number( req.body.limit ) },
1226
+ ...pagination,
1227
+ {
1228
+ $lookup: {
1229
+ from: 'clients',
1230
+ let: { clientId: '$clientId' },
1231
+ pipeline: [
1232
+ {
1233
+ $match: {
1234
+ $expr: {
1235
+ $and: [
1236
+ { $eq: [ '$clientId', '$$clientId' ] },
1237
+ ],
1238
+ },
1239
+ },
1240
+ },
1241
+ {
1242
+ $project: {
1243
+ clientName: 1,
1244
+ },
1245
+ },
1246
+ ],
1247
+ as: 'client',
1248
+ },
1249
+ },
1250
+ {
1251
+ $unwind: { path: '$client', preserveNullAndEmptyArrays: true },
1252
+ },
1253
+ {
1254
+ $project: {
1255
+ clientName: '$client.clientName',
1256
+ storeId: 1,
1257
+ clientId: 1,
1258
+ storeName: 1,
1259
+ status: 1,
1260
+ createdAt: 1,
1261
+ },
1262
+ },
1150
1263
  );
1151
1264
  }
1265
+
1152
1266
  let storesList;
1153
- if ( req.body.filterIssue == 'Live Stores' || req.body.filterIssue == 'Total Stores' ) {
1267
+ if ( req.body.infrafilterIssue == 'Live Stores' || req.body.infrafilterIssue == 'Total Stores' ) {
1154
1268
  storesList = await aggregateStore( storesQuery );
1155
1269
  } else {
1156
1270
  storesList = await aggregateTangoTicket( query );
1157
1271
  }
1158
-
1159
1272
  if ( storesList.length == 0 ) {
1160
1273
  return res.sendError( 'no data', 204 );
1161
1274
  }
1162
1275
  let data = {};
1163
1276
  let result = [];
1277
+ let inputData = req.body;
1164
1278
  for ( const store of storesList ) {
1165
1279
  data.storeId = store.storeId;
1166
1280
  data.storeName = store.storeName;
@@ -1179,82 +1293,64 @@ export async function hourWiseDownstores( req, res ) {
1179
1293
  }
1180
1294
  }
1181
1295
 
1296
+ async function downStoresCheck( data, inputData ) {
1297
+ try {
1298
+ const TimeSlots = generateTimeSlots( 8, 22, 60, inputData.Date );
1299
+ const formattedTimeSlots = TimeSlots.map( ( slot ) => ( {
1300
+ ...slot,
1301
+ startTime: dayjs( slot.from ).format( 'hh:mm A' ),
1302
+ endTime: dayjs( slot.to ).format( 'hh:mm A' ),
1303
+ } ) );
1182
1304
 
1183
- function downStoresCheck( data, inputData ) {
1184
- return new Promise( async ( Resolve, Reject ) => {
1185
- try {
1186
- let TimeSlots = generateTimeSlots( 8, 22, 60, inputData.Date );
1187
- let timewise = [];
1188
- for ( const obj of TimeSlots ) {
1189
- obj.startTime = dayjs( obj.from ).format( 'hh:mm A' );
1190
- obj.endTime = dayjs( obj.to ).format( 'hh:mm A' );
1191
- const downTime = await getOpenSearchData( JSON.parse( process.env.OPENSEARCH ).downTimeHourly,
1192
- {
1193
- 'size': 1,
1194
- 'query': {
1195
- 'bool': {
1196
- 'must': [
1197
- {
1198
- 'term': {
1199
- 'doc.date.keyword': dayjs( inputData.Date ).format( 'DD-MM-YYYY' ),
1200
- },
1201
- },
1202
- {
1203
- 'term': {
1204
- 'doc.store_id.keyword': data.storeId,
1205
- },
1206
- },
1207
- {
1208
- 'terms': {
1209
- 'doc.hour.keyword': [ obj.hour ],
1210
- },
1211
- },
1212
- ],
1213
-
1214
- },
1305
+ const downTimePromises = formattedTimeSlots.map( async ( obj ) => {
1306
+ const downTime = await getOpenSearchData(
1307
+ JSON.parse( process.env.OPENSEARCH ).downTimeHourly,
1308
+ {
1309
+ size: 1,
1310
+ query: {
1311
+ bool: {
1312
+ must: [
1313
+ { term: { 'doc.date.keyword': dayjs( inputData.Date ).format( 'DD-MM-YYYY' ) } },
1314
+ { term: { 'doc.store_id.keyword': data.storeId } },
1315
+ { terms: { 'doc.hour.keyword': [ obj.hour ] } },
1316
+ ],
1215
1317
  },
1318
+ },
1319
+ },
1320
+ );
1216
1321
 
1217
- } );
1218
- let streamwiseDowntime = downTime.body.hits.hits.length > 0 ? downTime.body.hits.hits[0]._source.doc.streamwise_downtime : [];
1219
- if ( streamwiseDowntime.length > 0 ) {
1220
- const sum = streamwiseDowntime.reduce( ( accumulator, currentValue ) => {
1221
- return accumulator + currentValue.down_time;
1222
- }, 0 );
1223
-
1224
- // Calculate the average
1225
- const average = sum / streamwiseDowntime.length;
1226
- obj[obj.startTime + '-' + obj.endTime] = Math.round( average );
1227
- } else {
1228
- obj[obj.startTime + '-' + obj.endTime] = '';
1229
- }
1322
+ const streamwiseDowntime = downTime.body.hits.hits.length > 0 ?
1323
+ downTime.body.hits.hits[0]._source.doc.streamwise_downtime :
1324
+ [];
1230
1325
 
1231
- timewise.push( obj );
1232
- }
1233
- const mergedData = {
1234
- storeName: data.storeName,
1235
- storeId: data.storeId,
1236
- PrimaryIssue: data.primaryIssue,
1237
- };
1238
- timewise.forEach( ( obj ) => {
1239
- for ( const key in obj ) {
1240
- if ( key !== 'hour' && key !== 'from' && key !== 'to' && key !== 'startTime' && key !== 'endTime' && key !== 'clientId' ) {
1241
- if ( mergedData[key] ) {
1242
- mergedData[key] += obj[key];
1243
- } else {
1244
- mergedData[key] = obj[key];
1245
- }
1246
- }
1326
+ const average = streamwiseDowntime.length ?
1327
+ Math.round( streamwiseDowntime.reduce( ( acc, curr ) => acc + curr.down_time, 0 ) / streamwiseDowntime.length ) :
1328
+ '';
1329
+
1330
+ return { ...obj, [`${obj.startTime}-${obj.endTime}`]: average };
1331
+ } );
1332
+
1333
+ const timewise = await Promise.all( downTimePromises );
1334
+
1335
+ const mergedData = timewise.reduce( ( acc, obj ) => {
1336
+ for ( const [ key, value ] of Object.entries( obj ) ) {
1337
+ if ( ![ 'hour', 'from', 'to', 'startTime', 'endTime', 'clientId' ].includes( key ) ) {
1338
+ acc[key] = ( acc[key] || 0 ) + value;
1247
1339
  }
1248
- } );
1340
+ }
1341
+ return acc;
1342
+ }, {
1343
+ storeName: data.storeName,
1344
+ storeId: data.storeId,
1345
+ PrimaryIssue: data.primaryIssue,
1346
+ } );
1249
1347
 
1250
- // Create an array with the merged data.
1251
- const mergedArray = [ mergedData ];
1252
- Resolve( mergedArray );
1253
- } catch ( err ) {
1254
- Reject( err );
1255
- }
1256
- } );
1348
+ return [ mergedData ];
1349
+ } catch ( err ) {
1350
+ throw err;
1351
+ }
1257
1352
  }
1353
+
1258
1354
  export async function ticketCountSplit( req, res ) {
1259
1355
  try {
1260
1356
  const inputData = req.body;