tango-app-api-infra 3.1.13 → 3.1.14

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-infra",
3
- "version": "3.1.13",
3
+ "version": "3.1.14",
4
4
  "description": "infra",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -26,8 +26,8 @@
26
26
  "mongodb": "^6.4.0",
27
27
  "nodemon": "^3.1.0",
28
28
  "swagger-ui-express": "^5.0.0",
29
- "tango-api-schema": "^2.0.103",
30
- "tango-app-api-middleware": "^3.1.10",
29
+ "tango-api-schema": "^2.0.104",
30
+ "tango-app-api-middleware": "^3.1.11",
31
31
  "winston": "^3.12.0",
32
32
  "winston-daily-rotate-file": "^5.0.0"
33
33
  },
@@ -1,16 +1,16 @@
1
1
 
2
- import { aggregateStore, countDocumentsStore } from '../services/store.service.js';
2
+ import { countDocumentsStore } from '../services/store.service.js';
3
3
  import { logger, download, getUTC } from 'tango-app-api-middleware';
4
4
  import { aggregateTangoTicket } from '../services/tangoTicket.service.js';
5
5
  import { findinfraReason } from '../services/infraReason.service.js';
6
- import { aggregateClient } from '../services/client.service.js';
6
+ import { aggregateClient, findClient } from '../services/client.service.js';
7
7
  import dayjs from 'dayjs';
8
8
  import { getOpenSearchData } from 'tango-app-api-middleware';
9
9
 
10
10
  export async function infraCard( req, res ) {
11
11
  try {
12
12
  let date = await getUTC( new Date( req.body.fromDate ), new Date( req.body.toDate ) );
13
- let storeCount = await countDocumentsStore( { 'clientId': { $in: req.body.clientId }, 'edge.firstFile': true, 'status': 'active' } );
13
+ let storeCount = await countDocumentsStore( { 'clientId': { $in: req.body.clientId }, 'createdAt': { $lte: date.end }, 'edge.firstFile': true, 'status': 'active' } );
14
14
  let infraStoreCount = await aggregateTangoTicket( [
15
15
  {
16
16
  $match: {
@@ -18,7 +18,7 @@ export async function infraCard( req, res ) {
18
18
  { issueType: 'infra' },
19
19
  { status: { $ne: 'closed' } },
20
20
  { 'basicDetails.clientId': { $in: req.body.clientId } },
21
- { createdAt: { $gte: date.start } },
21
+ // { createdAt: { $gte: date.start } },
22
22
  { createdAt: { $lte: date.end } },
23
23
  ],
24
24
  },
@@ -54,7 +54,7 @@ export async function infraCard( req, res ) {
54
54
  { status: { $ne: 'closed' } },
55
55
  { 'ticketDetails.issueStatus': 'identified' },
56
56
  { 'basicDetails.clientId': { $in: req.body.clientId } },
57
- { createdAt: { $gte: date.start } },
57
+ // { createdAt: { $gte: date.start } },
58
58
  { createdAt: { $lte: date.end } },
59
59
  ],
60
60
  },
@@ -134,6 +134,14 @@ export async function infraCard( req, res ) {
134
134
  count: 0,
135
135
  } ) );
136
136
  }
137
+ response.unshift( {
138
+ name: 'All Issues',
139
+ count: infraStoreCount.length > 0 ? infraStoreCount[0].identifiedcount : 0,
140
+ } );
141
+ response.push( {
142
+ name: 'Issues Not Identified',
143
+ count: infraStoreCount.length > 0 ? infraStoreCount[0].infraCount - infraStoreCount[0].identifiedcount : 0,
144
+ } );
137
145
  res.sendSuccess( {
138
146
  total: storeCount,
139
147
  liveStoreCount: infraStoreCount.length > 0 ? storeCount - infraStoreCount[0].infraCount : 0,
@@ -149,15 +157,21 @@ export async function infraCard( req, res ) {
149
157
  }
150
158
  export async function installationCard( req, res ) {
151
159
  try {
160
+ let date = await getUTC( new Date( req.body.fromDate ), new Date( req.body.toDate ) );
152
161
  let onboardedCount = await countDocumentsStore( {
153
162
  '$and': [
154
163
  { 'clientId': { $in: req.body.clientId } },
164
+ { 'createdAt': { $lte: date.end } },
155
165
  ],
156
166
  } );
157
- let installedCount = await countDocumentsStore( { 'clientId': { $in: req.body.clientId },
158
- 'edge.firstFile': true, 'status': 'active' } );
159
- let deactiveCount = await countDocumentsStore( { 'clientId': { $in: req.body.clientId },
160
- 'status': 'deactive' } );
167
+ let installedCount = await countDocumentsStore( {
168
+ 'clientId': { $in: req.body.clientId },
169
+ 'edge.firstFile': true, 'status': 'active', 'createdAt': { $lte: date.end },
170
+ } );
171
+ let deactiveCount = await countDocumentsStore( {
172
+ 'clientId': { $in: req.body.clientId },
173
+ 'status': 'deactive',
174
+ } );
161
175
  let yettoInstallCount = await aggregateTangoTicket( [
162
176
  {
163
177
  $match: {
@@ -166,7 +180,7 @@ export async function installationCard( req, res ) {
166
180
  { 'status': { $ne: 'closed' } },
167
181
  { 'ticketDetails.issueStatus': 'notidentified' },
168
182
  { 'basicDetails.clientId': { $in: req.body.clientId } },
169
- { createdAt: { $gte: new Date( req.body.fromDate ) } },
183
+ { createdAt: { $lte: new Date( req.body.toDate ) } },
170
184
  ],
171
185
  },
172
186
  },
@@ -178,7 +192,7 @@ export async function installationCard( req, res ) {
178
192
  { 'status': { $ne: 'closed' } },
179
193
  { 'basicDetails.clientId': { $in: req.body.clientId } },
180
194
  { 'ticketDetails.issueStatus': 'identified' },
181
- { createdAt: { $gte: new Date( req.body.fromDate ) } },
195
+ { createdAt: { $lte: new Date( req.body.toDate ) } },
182
196
  ],
183
197
  },
184
198
  },
@@ -265,14 +279,18 @@ export async function installationCard( req, res ) {
265
279
  export async function infraIssuesTable( req, res ) {
266
280
  try {
267
281
  let date = await getUTC( new Date( req.body.fromDate ), new Date( req.body.toDate ) );
282
+ let issueStatus = 'identified';
283
+ if ( req.body.filterIssue == 'Issues Not Identified' ) {
284
+ issueStatus = 'notidentified';
285
+ };
268
286
  let query = [ {
269
287
  $match: {
270
288
  $and: [
271
289
  { issueType: 'infra' },
272
290
  { status: { $ne: 'closed' } },
273
291
  { 'basicDetails.clientId': { $in: req.body.clientId } },
274
- { 'ticketDetails.issueStatus': 'identified' },
275
- { createdAt: { $gte: date.start } },
292
+ { 'ticketDetails.issueStatus': issueStatus },
293
+ // { createdAt: { $gte: date.start } },
276
294
  { createdAt: { $lte: date.end } },
277
295
  ],
278
296
  },
@@ -343,7 +361,7 @@ export async function infraIssuesTable( req, res ) {
343
361
  },
344
362
  },
345
363
  ];
346
- if ( req.body.filterIssue && req.body.filterIssue != '' ) {
364
+ if ( req.body.filterIssue && req.body.filterIssue != '' && req.body.filterIssue != 'All Issues' && req.body.filterIssue != 'Issues Not Identified' ) {
347
365
  query.push( {
348
366
  $match: {
349
367
  primaryIssue: req.body.filterIssue,
@@ -418,9 +436,10 @@ export async function InstallationIssuesTable( req, res ) {
418
436
  $match: {
419
437
  $and: [
420
438
  { issueType: 'installation' },
439
+ { 'status': { $ne: 'closed' } },
421
440
  { 'basicDetails.clientId': { $in: req.body.clientId } },
422
- { createdAt: { $gte: new Date( req.body.fromDate ) } },
423
- // { createdAt: { $lte: new Date( req.body.toDate ) } },
441
+ // { createdAt: { $gte: new Date( req.body.fromDate ) } },
442
+ { createdAt: { $lte: new Date( req.body.toDate ) } },
424
443
  ],
425
444
  },
426
445
  },
@@ -537,11 +556,15 @@ export async function InstallationIssuesTable( req, res ) {
537
556
  export async function hourWiseDownClients( req, res ) {
538
557
  try {
539
558
  let inputData = req.body;
540
-
559
+ let clientList = await findClient( { clientId: { $in: req.body.clientId }, status: 'active' } );
560
+ let activeClient = [];
561
+ for ( let client of clientList ) {
562
+ activeClient.push( client.clientId );
563
+ }
541
564
  let query = [
542
565
  {
543
566
  $match: {
544
- clientId: { $in: req.body.clientId },
567
+ clientId: { $in: activeClient },
545
568
  },
546
569
  },
547
570
  {
@@ -685,22 +708,55 @@ function generateTimeSlots( startHour, endHour, interval, time ) {
685
708
  export async function hourWiseDownstores( req, res ) {
686
709
  try {
687
710
  let inputData = req.body;
688
- inputData.Date = dayjs().format( 'YYYY-MM-DD' );
711
+ inputData.Date = dayjs( req.body.toDate ).format( 'YYYY-MM-DD' );
689
712
 
690
713
  let query = [ {
691
714
  $match: {
692
- clientId: req.body.clientId,
693
- status: 'active',
715
+ $and: [
716
+ { 'basicDetails.clientId': req.body.clientId },
717
+ { 'status': { $ne: 'closed' } },
718
+ { 'issueDate': { $lte: new Date( req.body.toDate ) } },
719
+ ],
720
+ },
721
+ },
722
+ {
723
+ $project: {
724
+ storeId: '$basicDetails.storeId',
725
+ storeName: '$basicDetails.storeName',
726
+ primaryIssue: {
727
+ $filter: {
728
+ input: '$ticketActivity',
729
+ as: 'item',
730
+ cond: { $eq: [ '$$item.actionType', 'issueUpdate' ] },
731
+ },
732
+ },
733
+ },
734
+ },
735
+ {
736
+ $unwind: {
737
+ path: '$primaryIssue', preserveNullAndEmptyArrays: true,
738
+ },
739
+ },
740
+ {
741
+ $unwind: {
742
+ path: '$primaryIssue.reasons', preserveNullAndEmptyArrays: true,
694
743
  },
695
744
  },
696
745
  {
697
746
  $project: {
698
747
  storeId: 1,
699
748
  storeName: 1,
700
- storeProfile: 1,
749
+ primaryIssue: { $ifNull: [ '$primaryIssue.reasons.primaryIssue', 'NotIdentified' ] },
750
+ },
751
+ },
752
+ {
753
+ $group: {
754
+ _id: '$storeId',
755
+ storeId: { $first: '$storeId' },
756
+ storeName: { $first: '$storeName' },
757
+ primaryIssue: { $last: '$primaryIssue' },
701
758
  },
702
759
  },
703
-
704
760
  ];
705
761
  if ( req.body.searchValue && req.body.searchValue !== '' ) {
706
762
  query.push( {
@@ -717,14 +773,21 @@ export async function hourWiseDownstores( req, res ) {
717
773
  $sort: { [req.body.sortColumName]: req.body.sortBy },
718
774
  } );
719
775
  }
720
- let count = await aggregateStore( query );
776
+ if ( req.body.filterIssue && req.body.filterIssue != '' && req.body.filterIssue != 'All Issues' && req.body.filterIssue != 'Issues Not Identified' ) {
777
+ query.push( {
778
+ $match: {
779
+ primaryIssue: req.body.filterIssue,
780
+ },
781
+ } );
782
+ }
783
+ let count = await aggregateTangoTicket( query );
721
784
  if ( req.body.limit && req.body.offset && !req.body.export ) {
722
785
  query.push(
723
786
  { $skip: ( req.body.offset - 1 ) * req.body.limit },
724
787
  { $limit: Number( req.body.limit ) },
725
788
  );
726
789
  }
727
- let storeslist = await aggregateStore( query );
790
+ let storeslist = await aggregateTangoTicket( query );
728
791
  if ( storeslist.length == 0 ) {
729
792
  return res.sendError( 'no data', 204 );
730
793
  }
@@ -733,6 +796,7 @@ export async function hourWiseDownstores( req, res ) {
733
796
  for ( const store of storeslist ) {
734
797
  data.storeId = store.storeId;
735
798
  data.storeName = store.storeName;
799
+ data.primaryIssue = store.primaryIssue;
736
800
  let storedata = await downStoresCheck( data, inputData );
737
801
  result.push( storedata[0] );
738
802
  }
@@ -801,7 +865,7 @@ function downStoresCheck( data, inputData ) {
801
865
  const mergedData = {
802
866
  storeName: data.storeName,
803
867
  storeId: data.storeId,
804
-
868
+ PrimaryIssue: data.primaryIssue,
805
869
  };
806
870
  timewise.forEach( ( obj ) => {
807
871
  for ( const key in obj ) {
@@ -5,7 +5,7 @@ export async function createTicket( req, res ) {
5
5
  try {
6
6
  let ticketExist = await findOneTangoTicket( { 'issueType': req.body.issueType, 'basicDetails.storeId': req.body.storeId } );
7
7
  if ( ticketExist ) {
8
- return res.sendSuccess( 'MAT Ticket Already Exists for the store' );
8
+ return res.status( 409 ).send( 'DataMismatch Ticket Already Exists for the store' );
9
9
  }
10
10
 
11
11
  req.body.issueDate = new Date( req.body.Date );
@@ -26,6 +26,10 @@ export async function createTicket( req, res ) {
26
26
  actionBy: 'Tango',
27
27
  IdentifiedBy: 'Tango',
28
28
  } ];
29
+ let ticketExists= await findOneTangoTicket( { ticketId: req.body.ticketId } );
30
+ if ( ticketExists ) {
31
+ res.status( 200 ).send( { storeId: req.body.storeId } );
32
+ }
29
33
  }
30
34
  if ( req.body.issueType == 'installation' ) {
31
35
  req.body.ticketId = 'TE_INS_' + new Date().valueOf();
@@ -332,6 +336,17 @@ export async function AlertTicketReply( req, res ) {
332
336
  return res.sendError( error, 500 );
333
337
  }
334
338
  }
339
+ export async function removeAttachment( req, res ) {
340
+ try {
341
+ let updateTicket = await updateOneTangoTicket( { ticketId: req.params.ticketId }, { attachments: req.body.attachments } );
342
+ if ( updateTicket ) {
343
+ res.sendSuccess( 'Removed successfully' );
344
+ }
345
+ } catch ( error ) {
346
+ logger.error( { error: error, function: 'uploadAttachments' } );
347
+ return res.sendError( error, 500 );
348
+ }
349
+ }
335
350
  export async function uploadAttachments( req, res ) {
336
351
  try {
337
352
  if ( req.files.img && req.files.img.length > 0 ) {
@@ -692,7 +707,7 @@ export async function getInfraIssues( req, res ) {
692
707
  primaryIssue: 1,
693
708
  secondaryReason: 1,
694
709
  downTime: { $ifNull: [ 0, 0 ] },
695
- speedTest: { $ifNull: [ 0.5, 0.5 ] },
710
+ speedTest: null,
696
711
  },
697
712
 
698
713
  },
@@ -704,7 +719,7 @@ export async function getInfraIssues( req, res ) {
704
719
  let end = new Date( inputData.toDate );
705
720
 
706
721
  while ( current <= end ) {
707
- retVal.push( { issueDate: dayjs( current ).format( 'YYYY-MM-DD' ), downTime: 0, speedTest: 0.6 } );
722
+ retVal.push( { issueDate: dayjs( current ).format( 'YYYY-MM-DD' ), downTime: 0, speedTest: null } );
708
723
  current.setDate( current.getDate() + 1 );
709
724
  }
710
725
 
@@ -716,7 +731,6 @@ export async function getInfraIssues( req, res ) {
716
731
  _.keyBy( result, 'issueDate' ),
717
732
  ),
718
733
  );
719
- logger.info( { message: mergeValue, value1: result } );
720
734
 
721
735
  if ( mergeValue.length == 0 ) {
722
736
  return res.sendError( 'NO Data Found', 204 );
@@ -745,17 +759,65 @@ export async function getInfraIssues( req, res ) {
745
759
  },
746
760
 
747
761
  } );
748
- let streamwiseDowntime = [];
749
- logger.info( { streamwiseDowntime: downTime.body.hits.hits.length } );
762
+
763
+ const speedTest = await getOpenSearchData( 'edgeapp_systemlogs',
764
+ {
765
+ 'size': 1,
766
+ 'query': {
767
+ 'bool': {
768
+ 'must': [
769
+ {
770
+ 'term': {
771
+ 'store_date.keyword': dayjs( mergeValue[i].issueDate ).format( 'DD-MM-YYYY' ),
772
+ },
773
+ },
774
+ {
775
+ 'term': {
776
+ 'storeId.keyword': inputData.storeId,
777
+ },
778
+ },
779
+ {
780
+ 'term': {
781
+ 'log_subtype.keyword': 'Speed_Test',
782
+ },
783
+ },
784
+
785
+ ],
786
+
787
+ },
788
+ },
789
+
790
+ 'sort': [
791
+ {
792
+ 'timestamp': {
793
+ 'order': 'desc',
794
+ },
795
+ },
796
+ ],
797
+
798
+ } );
799
+ let streamwiseDowntime = downTime.body.hits.hits;
800
+
750
801
  if ( downTime.body.hits.hits.length > 0 ) {
751
- for ( let i = 0; i< downTime.body.hits.hits.length; i++ ) {
752
- const sum = streamwiseDowntime.reduce( ( accumulator, currentValue ) => {
802
+ let down = 0;
803
+ for ( let j = 0; j< downTime.body.hits.hits.length; j++ ) {
804
+ const sum = streamwiseDowntime[j]?._source?.doc?.streamwise_downtime?.reduce( ( accumulator, currentValue ) => {
753
805
  return accumulator + currentValue.down_time;
754
806
  }, 0 );
755
- const average = sum / streamwiseDowntime.length;
756
- mergeValue.downTime = Math.round( average );
757
- // streamwiseDowntime.push( ...downTime.body.hits.hits[i]._source.doc.streamwise_downtime );
807
+ if ( streamwiseDowntime[j]?._source?.doc?.streamwise_downtime?.length > 0 ) {
808
+ const average = sum / streamwiseDowntime[j]?._source?.doc?.streamwise_downtime?.length;
809
+
810
+ down = down + Math.round( average );
811
+ logger.info( { down: down, downTine: mergeValue[i].downTime, streamwiseData: streamwiseDowntime[j]?._source?.doc?.streamwise_downtime } );
812
+ }
758
813
  }
814
+ mergeValue[i].downTime = down;
815
+ }
816
+
817
+ if ( speedTest.body.hits.hits.length > 0 ) {
818
+ const uploadspeed =Number( speedTest.body.hits.hits[0]?._source?.data?.upload_Speed.split( ' ' )[0] );
819
+ const converToMb = ( uploadspeed/ 1048576 ).toFixed( 1 );
820
+ mergeValue[i].speedTest = Number( converToMb );
759
821
  }
760
822
  }
761
823
  const camQuery = [
@@ -773,7 +835,7 @@ export async function getInfraIssues( req, res ) {
773
835
  _id: 0,
774
836
  streamName: 1,
775
837
  cameraNumber: 1,
776
- thumbnailImage: await signedUrl( { Bucket: appConfig.cloud.aws.bucket.baseImage, file_path: '$thumbnailImage' } ),
838
+ thumbnailImage: '$thumbnailImage',
777
839
  },
778
840
  },
779
841
  ];
@@ -808,8 +870,12 @@ export async function getInfraIssues( req, res ) {
808
870
  successRate: 0,
809
871
  };
810
872
  const getHighCountTicket = await aggregateTangoTicket( highCountQuery );
811
- logger.info( { getHighCountTicket: getHighCountTicket } );
812
873
  const camera = await aggregateCamera( camQuery );
874
+ for ( let index = 0; index < camera.length; index++ ) {
875
+ if ( camera?.[index]?.thumbnailImage ) {
876
+ camera[index].thumbnailImage = await signedUrl( { Bucket: appConfig.cloud.aws.bucket.baseImage, file_path: camera[index].thumbnailImage } );
877
+ }
878
+ }
813
879
  logger.info( { message: camera } );
814
880
  return res.sendSuccess( { result: mergeValue, streams: camera, highCountTicketDetails: getHighCountTicket[0] || defaultValue } );
815
881
  } catch ( error ) {
@@ -861,6 +927,7 @@ export async function infraTable( req, res ) {
861
927
  ticketId: 1,
862
928
  storeName: '$basicDetails.storeName',
863
929
  clientName: '$basicDetails.clientName',
930
+ ticketStatus: '$ticketDetails.issueStatus',
864
931
  status: 1,
865
932
  createdAt: 1,
866
933
  issueDate: 1,
@@ -872,6 +939,20 @@ export async function infraTable( req, res ) {
872
939
  cond: { $eq: [ '$$item.actionType', 'issueUpdate' ] },
873
940
  },
874
941
  },
942
+ otherscomment: {
943
+ $filter: {
944
+ input: '$ticketActivity',
945
+ as: 'item',
946
+ cond: { $eq: [ '$$item.actionType', 'comment' ] },
947
+ },
948
+ },
949
+ comments: {
950
+ $filter: {
951
+ input: '$ticketActivity',
952
+ as: 'item',
953
+ cond: { $ne: [ '$$item.actionType', 'statusChange' ] },
954
+ },
955
+ },
875
956
  },
876
957
  },
877
958
  {
@@ -884,6 +965,11 @@ export async function infraTable( req, res ) {
884
965
  path: '$primaryIssue.reasons', preserveNullAndEmptyArrays: true,
885
966
  },
886
967
  },
968
+ {
969
+ $unwind: {
970
+ path: '$otherscomment', preserveNullAndEmptyArrays: true,
971
+ },
972
+ },
887
973
  {
888
974
  $unwind: {
889
975
  path: '$primaryIssue.reasons.secondaryIssue', preserveNullAndEmptyArrays: true,
@@ -897,9 +983,12 @@ export async function infraTable( req, res ) {
897
983
  clientName: 1,
898
984
  createdAt: 1,
899
985
  addressingUser: 1,
986
+ ticketStatus: 1,
900
987
  ticketId: 1,
901
988
  issueDate: { $ifNull: [ '$issueDate', '' ] },
902
989
  status: 1,
990
+ commentText: '$primaryIssue.comment',
991
+ otherscomment: '$otherscomment.comment',
903
992
  primaryIssue: { $ifNull: [ '$primaryIssue.reasons.primaryIssue', '-' ] },
904
993
  secondaryIssue: { $ifNull: [ '$primaryIssue.reasons.secondaryIssue.name', '-' ] },
905
994
  },
@@ -941,12 +1030,15 @@ export async function infraTable( req, res ) {
941
1030
  clientId: { $first: '$clientId' },
942
1031
  ticketId: { $first: '$ticketId' },
943
1032
  storeName: { $first: '$storeName' },
1033
+ ticketStatus: { $first: '$ticketStatus' },
944
1034
  userName: { $first: { $ifNull: [ '$user.userName', '-' ] } },
945
1035
  userEmail: { $first: { $ifNull: [ '$user.email', '-' ] } },
946
1036
  clientName: { $first: '$clientName' },
947
1037
  createdAt: { $first: '$createdAt' },
948
1038
  issueDate: { $last: '$issueDate' },
949
1039
  status: { $last: '$status' },
1040
+ commentText: { $last: '$commentText' },
1041
+ otherscomment: { $last: '$otherscomment' },
950
1042
  primaryIssue: { $last: '$primaryIssue' },
951
1043
  secondaryIssue: { $last: '$secondaryIssue' },
952
1044
  },
@@ -1006,19 +1098,48 @@ export async function infraTable( req, res ) {
1006
1098
  count: 0,
1007
1099
  } ) );
1008
1100
  }
1101
+
1009
1102
  response.push( {
1010
1103
  'name': 'total',
1011
1104
  'count': ticketList.length,
1012
-
1013
1105
  } );
1014
- if ( req.body.filterIssue && req.body.filterIssue != '' && req.body.filterIssue != 'total' ) {
1106
+ let notIdentifiedCount = ticketList.reduce( ( count, ticket ) => {
1107
+ return ticket.ticketStatus === 'notidentified'&&ticket.status!='closed' ? count + 1 : count;
1108
+ }, 0 );
1109
+ let AutoClosedCount = ticketList.reduce( ( count, ticket ) => {
1110
+ return ticket.ticketStatus === 'notidentified'&&ticket.status=='closed' ? count + 1 : count;
1111
+ }, 0 );
1112
+ response.unshift( {
1113
+ 'name': 'Yet to Address',
1114
+ 'count': notIdentifiedCount,
1115
+ } );
1116
+ response.unshift( {
1117
+ 'name': 'Auto Closed',
1118
+ 'count': AutoClosedCount,
1119
+ } );
1120
+ if ( req.body.filterIssue && req.body.filterIssue != '' && req.body.filterIssue != 'total'&&req.body.filterIssue != 'Yet to Address'&&req.body.filterIssue != 'Auto Closed' ) {
1015
1121
  query.push( {
1016
1122
  $match: {
1017
1123
  primaryIssue: req.body.filterIssue,
1018
1124
  },
1019
1125
  } );
1020
1126
  }
1021
-
1127
+ if ( req.body.filterIssue == 'Yet to Address' ) {
1128
+ query.push( {
1129
+ $match: {
1130
+ ticketStatus: 'notidentified',
1131
+ status: { $ne: 'closed' },
1132
+ },
1133
+ } );
1134
+ }
1135
+ if ( req.body.filterIssue == 'Auto Closed' ) {
1136
+ query.push( {
1137
+ $match: {
1138
+ ticketStatus: 'notidentified',
1139
+ status: 'closed',
1140
+ },
1141
+ } );
1142
+ }
1022
1143
  if ( req.body.searchValue && req.body.searchValue != '' ) {
1023
1144
  query.push( {
1024
1145
  $match: {
@@ -1053,6 +1174,7 @@ export async function infraTable( req, res ) {
1053
1174
  'Status': element.status,
1054
1175
  'StatusDetails': element.primaryIssue,
1055
1176
  'SubIssue': element.secondaryIssue,
1177
+ 'Comment': element.otherscomment ? element.otherscomment : ( element.commentText?element.commentText:'-' ),
1056
1178
  } );
1057
1179
  } );
1058
1180
  await download( exportdata, res );
@@ -1096,6 +1218,7 @@ export async function installationTable( req, res ) {
1096
1218
  ticketId: 1,
1097
1219
  storeName: '$basicDetails.storeName',
1098
1220
  clientName: '$basicDetails.clientName',
1221
+ ticketStatus: '$ticketDetails.issueStatus',
1099
1222
  status: 1,
1100
1223
  createdAt: 1,
1101
1224
  addressingUser: '$ticketDetails.addressingUser',
@@ -1133,6 +1256,7 @@ export async function installationTable( req, res ) {
1133
1256
  clientName: 1,
1134
1257
  createdAt: 1,
1135
1258
  ticketId: 1,
1259
+ ticketStatus: 1,
1136
1260
  addressingUser: 1,
1137
1261
  installationStatus: { $ifNull: [ '$installationStatus', '-' ] },
1138
1262
  issueDate: { $ifNull: [ '$issueDate', '' ] },
@@ -1178,6 +1302,7 @@ export async function installationTable( req, res ) {
1178
1302
  clientId: { $first: '$clientId' },
1179
1303
  ticketId: { $first: '$ticketId' },
1180
1304
  storeName: { $first: '$storeName' },
1305
+ ticketStatus: { $first: '$ticketStatus' },
1181
1306
  userName: { $first: { $ifNull: [ '$user.userName', '-' ] } },
1182
1307
  userEmail: { $first: { $ifNull: [ '$user.email', '-' ] } },
1183
1308
  clientName: { $first: '$clientName' },
@@ -1227,11 +1352,13 @@ export async function installationTable( req, res ) {
1227
1352
  let response;
1228
1353
  if ( ticketList.length > 0 ) {
1229
1354
  ticketList.forEach( ( item ) => {
1230
- const categoryName = item.primaryIssue;
1231
- if ( categoryCounts[categoryName] ) {
1232
- categoryCounts[categoryName]++;
1233
- } else {
1234
- categoryCounts[categoryName] = 1;
1355
+ if ( item.installationStatus!='deployed' ) {
1356
+ const categoryName = item.primaryIssue;
1357
+ if ( categoryCounts[categoryName] ) {
1358
+ categoryCounts[categoryName]++;
1359
+ } else {
1360
+ categoryCounts[categoryName] = 1;
1361
+ }
1235
1362
  }
1236
1363
  } );
1237
1364
  response = issueList.map( ( category ) => ( {
@@ -1247,15 +1374,54 @@ export async function installationTable( req, res ) {
1247
1374
  response.push( {
1248
1375
  'name': 'total',
1249
1376
  'count': ticketList.length,
1250
-
1251
1377
  } );
1252
- if ( req.body.filterIssue && req.body.filterIssue != '' && req.body.filterIssue != 'total' ) {
1378
+ let notIdentifiedCount = ticketList.reduce( ( count, ticket ) => {
1379
+ return ticket.ticketStatus === 'notidentified'&&( ticket.installationStatus=='onboarded'||ticket.installationStatus=='paired' ) ? count + 1 : count;
1380
+ }, 0 );
1381
+ let AutoClosedCount = ticketList.reduce( ( count, ticket ) => {
1382
+ return ticket.installationStatus === 'deployed' ? count + 1 : count;
1383
+ }, 0 );
1384
+ response.unshift( {
1385
+ 'name': 'Yet to Address',
1386
+ 'count': notIdentifiedCount,
1387
+ } );
1388
+ response.unshift( {
1389
+ 'name': 'Deployed',
1390
+ 'count': AutoClosedCount,
1391
+ } );
1392
+ if ( req.body.filterIssue && req.body.filterIssue != '' && req.body.filterIssue != 'total'&&req.body.filterIssue != 'Yet to Address'&&req.body.filterIssue != 'Deployed' ) {
1253
1393
  query.push( {
1254
1394
  $match: {
1255
1395
  primaryIssue: req.body.filterIssue,
1256
1396
  },
1257
1397
  } );
1258
1398
  }
1399
+ if ( req.body.filterIssue == 'Yet to Address' ) {
1400
+ query.push( {
1401
+ $match: {
1402
+ $and: [
1403
+ {
1404
+ $or: [
1405
+ { installationStatus: 'onboarded' },
1406
+ { installationStatus: 'paired' },
1407
+ ],
1408
+ },
1409
+ {
1410
+ ticketStatus: 'notidentified',
1411
+ },
1412
+ ],
1413
+
1414
+
1415
+ },
1416
+ } );
1417
+ }
1418
+ if ( req.body.filterIssue == 'Deployed' ) {
1419
+ query.push( {
1420
+ $match: {
1421
+ installationStatus: 'deployed',
1422
+ },
1423
+ } );
1424
+ }
1259
1425
  if ( req.body.searchValue && req.body.searchValue != '' ) {
1260
1426
  query.push( {
1261
1427
  $match: {
@@ -12,7 +12,7 @@ dayjs.extend( timezone );
12
12
  import { sendEmailWithSES, signedUrl } from 'tango-app-api-middleware';
13
13
  import { createClient, findClient, aggregateClient, findOneClient } from '../services/client.service.js';
14
14
  import { createStore, findStore, updateOneStore, findOneStore } from '../services/store.service.js';
15
- import { findTangoTicket, findOneTangoTicket, countDocumentsTangoTicket, aggregateTangoTicket, updateOneTangoTicket } from '../services/tangoTicket.service.js';
15
+ import { findTangoTicket, findOneTangoTicket, countDocumentsTangoTicket, updateOneTangoTicketunset, aggregateTangoTicket, updateOneTangoTicket } from '../services/tangoTicket.service.js';
16
16
  import { findOneGroup } from '../services/group.service.js';
17
17
  import { findinfraReason } from '../services/infraReason.service.js';
18
18
  import { findOneUser } from '../services/user.service.js';
@@ -74,9 +74,9 @@ export async function migrateStores() {
74
74
  }
75
75
  export async function clientList( req, res ) {
76
76
  try {
77
- let storeList = await findClient( { status: 'active' },
77
+ let clientList = await findClient( { status: { $in: [ 'active', 'hold' ] } },
78
78
  { 'clientName': 1, 'clientId': 1, 'ticketConfigs': 1 } );
79
- res.sendSuccess( storeList );
79
+ res.sendSuccess( clientList );
80
80
  } catch ( error ) {
81
81
  logger.error( { error: error, function: 'basicList' } );
82
82
  res.sendError( error, 500 );
@@ -85,7 +85,12 @@ export async function clientList( req, res ) {
85
85
 
86
86
  export async function basicList( req, res ) {
87
87
  try {
88
- let storeList = await findStore( { status: 'active' },
88
+ let clientList = await findClient( { status: { $in: [ 'active', 'hold' ] } }, { 'clientId': 1 } );
89
+ let clients = [];
90
+ for ( let client of clientList ) {
91
+ clients.push( client.clientId );
92
+ }
93
+ let storeList = await findStore( { 'clientId': { $in: clients }, 'status': 'active', 'edge.firstFile': true },
89
94
  { 'storeName': 1, 'storeId': 1, 'ticketConfigs': 1, 'clientId': 1, 'storeProfile.open': 1, 'storeProfile.close': 1, 'storeProfile.timeZone': 1 } );
90
95
  res.sendSuccess( storeList );
91
96
  } catch ( error ) {
@@ -152,6 +157,7 @@ export async function updateRefreshTicket( req, res ) {
152
157
  for ( let ticket of req.body.TicketList ) {
153
158
  let getTicket = await findOneTangoTicket( { ticketId: ticket.ticketId } );
154
159
  await updateOneTangoTicket( { ticketId: ticket.ticketId }, { 'ticketDetails.ticketType': 'refreshticket' } );
160
+ await updateOneTangoTicketunset( { ticketId: ticket.ticketId }, { 'ticketDetails.addressingUser': 1 } );
155
161
  let downTimeQuery = {
156
162
  'size': 1,
157
163
  'query': {
@@ -448,12 +454,12 @@ export async function infraReportSent( req, res ) {
448
454
  // if ( req.body.type == 'start' ) {
449
455
  // date = dayjs().subtract( 1, 'day' ).format( 'YYYY-MM-DD' );
450
456
  // } else if ( req.body.type == 'end' ) {
451
- let date = dayjs( ).format( 'YYYY-MM-DD' );
457
+ let date = dayjs().format( 'YYYY-MM-DD' );
452
458
  // };
453
459
  let query = [ {
454
460
  $match: {
455
461
  $and: [
456
- { issueDate: new Date( date ) },
462
+ { issueDate: { $lte: new Date( date ) } },
457
463
  { 'basicDetails.storeId': { $in: req.body.storeList } },
458
464
  { issueType: 'infra' },
459
465
  ],
@@ -550,10 +556,10 @@ export async function infraReportSent( req, res ) {
550
556
  'Responded By': clientuser && clientuser.userName ? clientuser.userName : '-',
551
557
  'Resolved By': tangouser && tangouser.userName ? tangouser.userName : '-',
552
558
  'Ticket Closed Date & Time': element.issueClosedDate ? dayjs( element.issueClosedDate ).tz( 'Asia/Kolkata' ).format( 'YYYY-MM-DD HH:mm A' ) : '-',
553
- 'Latest Comment': element.otherscomment?element.otherscomment:element.commentText,
559
+ 'Latest Comment': element.otherscomment ? element.otherscomment : element.commentText,
554
560
  'Activity Log': {
555
561
  label: 'Link',
556
- url: `${appConfig.url.domain+'/manage/stores/infra-ticket?storeId='+element.basicDetails.storeId}`,
562
+ url: `${appConfig.url.domain + '/manage/stores/infra-ticket?storeId=' + element.basicDetails.storeId}`,
557
563
  },
558
564
  } );
559
565
  }
@@ -724,7 +730,7 @@ export async function download( data ) {
724
730
  for ( let j = 0; j < headers.length; j++ ) {
725
731
  const header = headers[j];
726
732
  const value = dataRow[header];
727
- if ( value&& typeof value === 'object' && value.hasOwnProperty( 'label' ) && value.hasOwnProperty( 'url' ) ) {
733
+ if ( value && typeof value === 'object' && value.hasOwnProperty( 'label' ) && value.hasOwnProperty( 'url' ) ) {
728
734
  ws.cell( i + 2, j + 1 ).link( value.url );
729
735
  ws.cell( i + 2, j + 1 ).string( value.label );
730
736
  } else {
@@ -736,7 +742,7 @@ export async function download( data ) {
736
742
  }
737
743
  export async function edgeApplogsCheck( req, res ) {
738
744
  try {
739
- let finalresult= [];
745
+ let finalresult = [];
740
746
  let ticketList = await findTangoTicket( { 'issueDate': new Date( req.body.issueDate ), 'status': { $ne: 'closed' }, 'ticketDetails.issueStatus': 'notidentified', 'issueType': 'infra' } );
741
747
  for ( let ticket of ticketList ) {
742
748
  req.body.date = dayjs( ticket.createdAt ).format( 'YYYY-MM-DD' );
@@ -881,7 +887,7 @@ export async function edgeApplogsCheck( req, res ) {
881
887
  }
882
888
  }
883
889
  let findissueEdgeApp = {};
884
- if ( result.length>0 ) {
890
+ if ( result.length > 0 ) {
885
891
  for ( let findissue of result ) {
886
892
  const istTimestamp = dayjs.utc( ticket.createdAt ).tz( 'Asia/Kolkata' ).format( 'HH:mm:ss' );
887
893
 
@@ -908,7 +914,7 @@ export async function edgeApplogsCheck( req, res ) {
908
914
  const existsInArray = finalresult.some( ( item ) =>
909
915
  item.ticketId === ticket.ticketId,
910
916
  );
911
- if ( isOccurringTimeEarlier&&!existsInArray ) {
917
+ if ( isOccurringTimeEarlier && !existsInArray ) {
912
918
  findissueEdgeApp = {
913
919
  ticketId: ticket.ticketId,
914
920
  storeId: ticket.basicDetails.storeId,
@@ -935,7 +941,7 @@ export async function edgeApplogsCheck( req, res ) {
935
941
  updateIssue( findissueEdgeApp );
936
942
  finalresult.push( findissueEdgeApp );
937
943
  }
938
- } else if ( findissue.code ==='1005' ) {
944
+ } else if ( findissue.code === '1005' ) {
939
945
  const occurringTimeParsed = dayjs( `${req.body.date} ${findissue.edgelog.occuringTime}` );
940
946
  const ticketCreatedParsed = dayjs( `${req.body.date} ${istTimestamp}` );
941
947
  const isOccurringTimeEarlier = occurringTimeParsed.isBefore( ticketCreatedParsed );
@@ -8,12 +8,35 @@ import { signedUrl, appConfig } from 'tango-app-api-middleware';
8
8
  export async function storeTicketList( req, res ) {
9
9
  try {
10
10
  let date = await getUTC( new Date( req.body.fromDate ), new Date( req.body.toDate ) );
11
- let query = [ {
11
+ let query = [];
12
+ if ( req.body.fromDate == req.body.toDate ) {
13
+ query.push( {
14
+ $match: {
15
+ $and: [
16
+ { 'basicDetails.storeId': req.body.storeId },
17
+ { issueType: 'infra' },
18
+ { createdAt: { $lte: date.end } },
19
+ ],
20
+ },
21
+ } );
22
+ } else {
23
+ query.push( {
24
+ $match: {
25
+ $and: [
26
+ { 'basicDetails.storeId': req.body.storeId },
27
+ { issueType: 'infra' },
28
+ { createdAt: { $gte: date.start } },
29
+ { createdAt: { $lte: date.end } },
30
+ ],
31
+ },
32
+ } );
33
+ }
34
+ query.push( {
12
35
  $match: {
13
36
  $and: [
14
37
  { 'basicDetails.storeId': req.body.storeId },
15
38
  { issueType: 'infra' },
16
- { createdAt: { $gte: date.start } },
39
+ // { createdAt: { $gte: date.start } },
17
40
  { createdAt: { $lte: date.end } },
18
41
  ],
19
42
  },
@@ -112,7 +135,7 @@ export async function storeTicketList( req, res ) {
112
135
  issueDate: -1,
113
136
  },
114
137
  },
115
- ];
138
+ );
116
139
 
117
140
  if ( req.body.filter && req.body.filter !== '' ) {
118
141
  query.push( {
@@ -133,7 +156,7 @@ export async function storeTicketList( req, res ) {
133
156
  'PRIMARY ISSUE': element.primaryIssue,
134
157
  'SECONDARY ISSUE': element.secondaryIssue,
135
158
  'STATUS': element.status,
136
- 'COMMENT': element.otherscomment?element.otherscomment:element.commentText,
159
+ 'COMMENT': element.otherscomment ? element.otherscomment : element.commentText,
137
160
  } );
138
161
  } );
139
162
  await download( exportdata, res );
@@ -156,58 +179,74 @@ export async function storeTicketList( req, res ) {
156
179
  export async function storeTicketcard( req, res ) {
157
180
  try {
158
181
  let date = await getUTC( new Date( req.body.fromDate ), new Date( req.body.toDate ) );
159
- let query = [ {
160
- $match: {
161
- $and: [
162
- { 'basicDetails.storeId': req.body.storeId },
163
- { 'ticketDetails.issueStatus': 'identified' },
164
- { issueType: 'infra' },
165
- { createdAt: { $gte: date.start } },
166
- { createdAt: { $lte: date.end } },
167
- ],
182
+ let query = [];
183
+ if ( req.body.fromDate == req.body.toDate ) {
184
+ query.push( {
185
+ $match: {
186
+ $and: [
187
+ { 'basicDetails.storeId': req.body.storeId },
188
+ { 'ticketDetails.issueStatus': 'identified' },
189
+ { issueType: 'infra' },
190
+ { createdAt: { $lte: date.end } },
191
+ ],
192
+ },
193
+ } );
194
+ } else {
195
+ query.push( {
196
+ $match: {
197
+ $and: [
198
+ { 'basicDetails.storeId': req.body.storeId },
199
+ { 'ticketDetails.issueStatus': 'identified' },
200
+ { issueType: 'infra' },
201
+ { createdAt: { $gte: date.start } },
202
+ { createdAt: { $lte: date.end } },
203
+ ],
204
+ },
205
+ } );
206
+ }
168
207
 
169
- },
170
- },
171
- {
172
- $project: {
173
- ticketId: 1,
174
- issueStatus: '$ticketDetails.issueStatus',
175
- primaryIssue: {
176
- $filter: {
177
- input: '$ticketActivity',
178
- as: 'item',
179
- cond: { $eq: [ '$$item.actionType', 'issueUpdate' ] },
208
+
209
+ query.push(
210
+ {
211
+ $project: {
212
+ ticketId: 1,
213
+ issueStatus: '$ticketDetails.issueStatus',
214
+ primaryIssue: {
215
+ $filter: {
216
+ input: '$ticketActivity',
217
+ as: 'item',
218
+ cond: { $eq: [ '$$item.actionType', 'issueUpdate' ] },
219
+ },
220
+ },
180
221
  },
181
222
  },
182
- },
183
- },
184
- {
185
- $unwind: {
186
- path: '$primaryIssue', preserveNullAndEmptyArrays: true,
187
- },
188
- },
189
- {
190
- $unwind: {
191
- path: '$primaryIssue.reasons', preserveNullAndEmptyArrays: true,
192
- },
193
- },
194
- {
195
- $project: {
196
- ticketId: 1,
197
- issueStatus: 1,
198
- ticketType: 1,
199
- primaryIssue: '$primaryIssue.reasons.primaryIssue',
200
- },
201
- }, {
202
- $group: {
203
- _id: '$ticketId',
204
- ticketId: { $first: '$ticketId' },
205
- issueStatus: { $first: '$issueStatus' },
206
- ticketType: { $first: '$ticketType' },
207
- primaryIssue: { $last: '$primaryIssue' },
208
- },
209
- },
210
- ];
223
+ {
224
+ $unwind: {
225
+ path: '$primaryIssue', preserveNullAndEmptyArrays: true,
226
+ },
227
+ },
228
+ {
229
+ $unwind: {
230
+ path: '$primaryIssue.reasons', preserveNullAndEmptyArrays: true,
231
+ },
232
+ },
233
+ {
234
+ $project: {
235
+ ticketId: 1,
236
+ issueStatus: 1,
237
+ ticketType: 1,
238
+ primaryIssue: '$primaryIssue.reasons.primaryIssue',
239
+ },
240
+ }, {
241
+ $group: {
242
+ _id: '$ticketId',
243
+ ticketId: { $first: '$ticketId' },
244
+ issueStatus: { $first: '$issueStatus' },
245
+ ticketType: { $first: '$ticketType' },
246
+ primaryIssue: { $last: '$primaryIssue' },
247
+ },
248
+ } );
249
+
211
250
  let ticketList = await aggregateTangoTicket( query );
212
251
  let issueList = await findinfraReason( { parentId: { '$exists': false } } );
213
252
  const categoryCounts = {};
@@ -367,7 +406,7 @@ export async function edgeAppLogTable( req, res ) {
367
406
  const average = sum / streamwiseDowntime.length;
368
407
  obj.downtime = Math.round( average );
369
408
  } else {
370
- obj.downtime ='';
409
+ obj.downtime = '';
371
410
  }
372
411
  let appStatusQuery = {
373
412
  'size': 1,
@@ -440,7 +479,7 @@ function generateTimeSlots( startHour, endHour, interval, req ) {
440
479
  return timeSlots;
441
480
  } catch ( error ) {
442
481
  logger.error( { error: error, function: 'generateTimeSlots' } );
443
- return res.sendError( error, 500 );
482
+ return error;
444
483
  }
445
484
  };
446
485
 
@@ -854,3 +893,122 @@ export async function cameraAngleChange( req, res ) {
854
893
  return res.sendError( error, 500 );
855
894
  }
856
895
  }
896
+ function getDatesArray( fromDate, toDate ) {
897
+ let dates = [];
898
+ let currentDate = new Date( fromDate );
899
+ let endDate = new Date( toDate );
900
+
901
+ while ( currentDate <= endDate ) {
902
+ dates.push( currentDate.toISOString().split( 'T' )[0] ); // Convert Date to string format YYYY-MM-DD
903
+ currentDate.setDate( currentDate.getDate() + 1 );
904
+ }
905
+
906
+ return dates;
907
+ }
908
+
909
+ function paginateArray( array, offset, limit ) {
910
+ return array.slice( ( offset - 1 ) * limit, offset*limit );
911
+ }
912
+ export async function datewiseDowntime( req, res ) {
913
+ try {
914
+ const store = await findOneStore( { storeId: req.body.storeId } );
915
+ if ( !store ) {
916
+ return res.sendError( 'Stores Not fond', 204 );
917
+ }
918
+ let startHour = store.storeProfile.open.split( ':' )[0];
919
+ let endHour = store.storeProfile.close.split( ':' )[0];
920
+
921
+ let datesArray = getDatesArray( req.body.fromDate, req.body.toDate );
922
+ let paginatedDates = paginateArray( datesArray, req.body.offset, req.body.limit );
923
+ let result = [];
924
+ for ( const singleDate of paginatedDates ) {
925
+ let inputData = {
926
+ start: startHour,
927
+ end: endHour,
928
+ interval: 60,
929
+ };
930
+ req.body.Date= singleDate;
931
+ let storedata = await livecountCheck( inputData, req );
932
+ result.push( storedata[0] );
933
+ }
934
+ res.sendSuccess( {
935
+ count: datesArray.length,
936
+ data: result,
937
+ } );
938
+ } catch ( error ) {
939
+ logger.error( { error: error, function: 'cameraAngleChange' } );
940
+ return res.sendError( error, 500 );
941
+ }
942
+ }
943
+
944
+
945
+ export async function livecountCheck( inputData, req ) {
946
+ return new Promise( async ( Resolve, Reject ) => {
947
+ try {
948
+ let TimeSlots = generateTimeSlots( inputData.start, inputData.end, inputData.interval, req );
949
+ let timewise = [];
950
+ for ( const obj of TimeSlots ) {
951
+ obj.startTime = dayjs( obj.from ).format( 'hh:mm A' );
952
+ obj.endTime = dayjs( obj.to ).format( 'hh:mm A' );
953
+ let downTimeQuery = {
954
+ 'size': 1,
955
+ 'query': {
956
+ 'bool': {
957
+ 'must': [
958
+ {
959
+ 'term': {
960
+ 'doc.date.keyword': dayjs( obj.from ).format( 'DD-MM-YYYY' ),
961
+ },
962
+ },
963
+ {
964
+ 'term': {
965
+ 'doc.store_id.keyword': req.body.storeId,
966
+ },
967
+ },
968
+ {
969
+ 'terms': {
970
+ 'doc.hour.keyword': [ obj.hour ],
971
+ },
972
+ },
973
+ ],
974
+
975
+ },
976
+ },
977
+ };
978
+ const downtime = await getOpenSearchData( 'live_downtime_hourly', downTimeQuery );
979
+ let streamwiseDowntime = downtime.body.hits.hits.length > 0 ? downtime.body.hits.hits[0]._source.doc.streamwise_downtime : [];
980
+ if ( streamwiseDowntime.length > 0 ) {
981
+ const sum = streamwiseDowntime.reduce( ( accumulator, currentValue ) => {
982
+ return accumulator + currentValue.down_time;
983
+ }, 0 );
984
+ const average = sum / streamwiseDowntime.length;
985
+ obj[obj.startTime + '-' + obj.endTime] = Math.round( average );
986
+ } else {
987
+ obj[obj.startTime + '-' + obj.endTime] = '';
988
+ }
989
+
990
+ timewise.push( obj );
991
+ }
992
+ const mergedData = {
993
+ Date: dayjs( req.body.Date ).format( 'YYYY-MM-DD' ),
994
+ };
995
+ timewise.forEach( ( obj ) => {
996
+ for ( const key in obj ) {
997
+ if ( key !== 'hour' && key !== 'from' && key !== 'to' && key !== 'startTime' && key !== 'endTime' && key !== 'clientId' ) {
998
+ if ( mergedData[key] ) {
999
+ mergedData[key] += obj[key];
1000
+ } else {
1001
+ mergedData[key] = obj[key];
1002
+ }
1003
+ }
1004
+ }
1005
+ } );
1006
+
1007
+ // Create an array with the merged data.
1008
+ const mergedArray = [ mergedData ];
1009
+ Resolve( mergedArray );
1010
+ } catch ( err ) {
1011
+ Reject( err );
1012
+ }
1013
+ } );
1014
+ }
@@ -30,7 +30,7 @@ export async function userTakeTicket( req, res ) {
30
30
  'ticketDetails.addressingClient': { $exists: false },
31
31
  };
32
32
  if ( assignedClients.length > 0 ) {
33
- query =( { ...query, ...{ 'basicDetails.clientId': { $in: assignedClients } } } );
33
+ query = ( { ...query, ...{ 'basicDetails.clientId': { $in: assignedClients } } } );
34
34
  }
35
35
  userTicket = await findOneTangoTicket( query );
36
36
 
@@ -43,7 +43,7 @@ export async function userTakeTicket( req, res ) {
43
43
  'ticketDetails.refreshTicketStatus': 'notidentified',
44
44
  };
45
45
  if ( assignedClients.length > 0 ) {
46
- query =( { ...query, ...{ 'basicDetails.clientId': { $in: assignedClients } } } );
46
+ query = ( { ...query, ...{ 'basicDetails.clientId': { $in: assignedClients } } } );
47
47
  }
48
48
  userTicket = await findOneTangoTicket( query );
49
49
  }
@@ -56,7 +56,7 @@ export async function userTakeTicket( req, res ) {
56
56
  'ticketDetails.addressingClient': { $exists: false },
57
57
  };
58
58
  if ( assignedClients.length > 0 ) {
59
- query =( { ...query, ...{ 'basicDetails.clientId': { $in: assignedClients } } } );
59
+ query = ( { ...query, ...{ 'basicDetails.clientId': { $in: assignedClients } } } );
60
60
  }
61
61
  userTicket = await findOneTangoTicket( query );
62
62
  if ( !userTicket ) {
@@ -67,7 +67,7 @@ export async function userTakeTicket( req, res ) {
67
67
  'ticketDetails.refreshTicketStatus': 'notidentified',
68
68
  };
69
69
  if ( assignedClients.length > 0 ) {
70
- query =( { ...query, ...{ 'basicDetails.clientId': { $in: assignedClients } } } );
70
+ query = ( { ...query, ...{ 'basicDetails.clientId': { $in: assignedClients } } } );
71
71
  }
72
72
  userTicket = await findOneTangoTicket( query );
73
73
  }
@@ -78,7 +78,7 @@ export async function userTakeTicket( req, res ) {
78
78
  'ticketDetails.addressingUser': { $exists: false },
79
79
  };
80
80
  if ( assignedClients.length > 0 ) {
81
- query =( { ...query, ...{ 'basicDetails.clientId': { $in: assignedClients } } } );
81
+ query = ( { ...query, ...{ 'basicDetails.clientId': { $in: assignedClients } } } );
82
82
  }
83
83
  userTicket = await findOneTangoTicket( query );
84
84
  } else if ( req.body.issueType == 'dataMismatch' ) {
@@ -88,11 +88,11 @@ export async function userTakeTicket( req, res ) {
88
88
  'ticketDetails.addressingUser': { $exists: false },
89
89
  };
90
90
  if ( assignedClients.length > 0 ) {
91
- query =( { ...query, ...{ 'basicDetails.clientId': { $in: assignedClients } } } );
91
+ query = ( { ...query, ...{ 'basicDetails.clientId': { $in: assignedClients } } } );
92
92
  }
93
93
  userTicket = await findOneTangoTicket( query );
94
94
  }
95
- if ( userTicket&&userTicket.ticketId ) {
95
+ if ( userTicket && userTicket.ticketId ) {
96
96
  let assignTicket = await updateOneTangoTicket( { ticketId: userTicket.ticketId }, { 'ticketDetails.addressingUser': req.body.userId } );
97
97
  if ( assignTicket ) {
98
98
  res.sendSuccess( 'Ticket Assigned Successfully' );
@@ -109,7 +109,7 @@ export async function userTicketList( req, res ) {
109
109
  try {
110
110
  let date = await getUTC( new Date( req.body.fromDate ), new Date( req.body.toDate ) );
111
111
  let query = [];
112
- if ( req.body.issueType!='dataMismatch' ) {
112
+ if ( req.body.issueType != 'dataMismatch' ) {
113
113
  query.push( {
114
114
  $match: {
115
115
  $and: [
@@ -253,13 +253,13 @@ export async function userTicketList( req, res ) {
253
253
  'STORE NAME': element.storeName,
254
254
  'STATUS': element.status,
255
255
  };
256
- if ( req.body.issueType ==='infra' ) {
256
+ if ( req.body.issueType === 'infra' ) {
257
257
  data = { ...data, ...{ 'ISSUE': element.issueStatus } };
258
258
  }
259
- if ( req.body.issueType ==='installation' ) {
259
+ if ( req.body.issueType === 'installation' ) {
260
260
  data = { ...data, ...{ 'ISSUE': element.issueStatus } };
261
261
  }
262
- if ( req.body.issueType ==='dataMismatch' ) {
262
+ if ( req.body.issueType === 'dataMismatch' ) {
263
263
  data = { ...data, ...{ 'ISSUE TYPE': element.issueType } };
264
264
  }
265
265
  exportdata.push( data );
@@ -326,15 +326,17 @@ export async function basicDetails( req, res ) {
326
326
  }
327
327
  let infraCount = await countDocumentsTangoTicket( { 'ticketDetails.addressingUser': new mongoose.Types.ObjectId( req.body.userId ), 'issueType': 'infra' } );
328
328
  let installationCount = await countDocumentsTangoTicket( { 'ticketDetails.addressingUser': new mongoose.Types.ObjectId( req.body.userId ), 'issueType': 'installation' } );
329
+ let dataMismatchCount = await countDocumentsTangoTicket( { 'ticketDetails.addressingUser': new mongoose.Types.ObjectId( req.body.userId ), 'issueType': { $in: [ 'highcount', 'lowcount' ] } } );
330
+ let employeeTrainingCount = await countDocumentsTangoTicket( { 'ticketDetails.addressingUser': new mongoose.Types.ObjectId( req.body.userId ), 'issueType': 'mat' } );
329
331
  res.sendSuccess( {
330
332
  userName: user.userName,
331
333
  userType: user.userType,
332
- total: infraCount + installationCount,
334
+ total: infraCount + installationCount + dataMismatchCount + employeeTrainingCount,
333
335
  infraCount: infraCount,
334
336
  installationCount: installationCount,
335
- dataMismatchCount: 0,
337
+ dataMismatchCount: dataMismatchCount,
336
338
  auditCount: 0,
337
- employeeTrainingCount: 0,
339
+ employeeTrainingCount: employeeTrainingCount,
338
340
  } );
339
341
  } catch ( error ) {
340
342
  logger.error( { error: error, function: 'userTakeTicket' } );
@@ -345,8 +347,8 @@ export async function basicDetails( req, res ) {
345
347
  export async function workHistory( req, res ) {
346
348
  try {
347
349
  let date = await getUTC( new Date( req.body.fromDate ), new Date( req.body.toDate ) );
348
- let query = [ ];
349
- if ( req.body.issueType!='dataMismatch' ) {
350
+ let query = [];
351
+ if ( req.body.issueType != 'dataMismatch' ) {
350
352
  query.push( {
351
353
  $match: {
352
354
  $and: [
@@ -480,14 +482,14 @@ export async function workHistory( req, res ) {
480
482
  infraIssue: { $ifNull: [ '$primaryIssue.reasons.primaryIssue', '' ] },
481
483
  },
482
484
  } );
483
- if ( req.body.issueFilter && req.body.issueFilter.length>0&&req.body.issueType!='dataMismatch' ) {
485
+ if ( req.body.issueFilter && req.body.issueFilter.length > 0 && req.body.issueType != 'dataMismatch' ) {
484
486
  query.push( {
485
487
  $match: {
486
488
  infraIssue: { $in: req.body.issueFilter },
487
489
  },
488
490
  } );
489
491
  }
490
- if ( req.body.issueFilter && req.body.issueFilter.length>0&&req.body.issueType==='dataMismatch' ) {
492
+ if ( req.body.issueFilter && req.body.issueFilter.length > 0 && req.body.issueType === 'dataMismatch' ) {
491
493
  query.push( {
492
494
  $match: {
493
495
  issueType: { $in: req.body.issueFilter },
@@ -524,8 +526,8 @@ export async function workHistory( req, res ) {
524
526
  if ( req.body.export ) {
525
527
  const exportdata = [];
526
528
  result.forEach( ( element ) => {
527
- let data ={
528
- 'CREATED ON': dayjs( element.issueDate ).format( 'DD-MM-YYYY' ),
529
+ let data = {
530
+ 'CREATED ON': dayjs( element.createdAt ).format( 'DD-MM-YYYY' ),
529
531
  'TICKET ID': element.ticketId,
530
532
  'STORE ID': element.storeId,
531
533
  'STORE NAME': element.storeName,
@@ -534,11 +536,11 @@ export async function workHistory( req, res ) {
534
536
  'CLOSED ON': element.issueClosedDate,
535
537
  'STATUS': element.status,
536
538
  };
537
- if ( req.body.issueType==='infra'||req.body.issueType==='installation' ) {
538
- data = { ...data, ...{ 'ISSUE': element.infraIssue?element.infraIssue:'-', 'ISSUE IDENTIFIED DATE': element.issueIdentifiedDate } };
539
+ if ( req.body.issueType === 'infra' || req.body.issueType === 'installation' ) {
540
+ data = { ...data, ...{ 'ISSUE': element.infraIssue ? element.infraIssue : '-', 'ISSUE IDENTIFIED DATE': element.issueIdentifiedDate } };
539
541
  }
540
- if ( req.body.issueType==='dataMismatch' ) {
541
- data = { ...data, ...{ 'issueType': element.issueType?element.issueType:'-' } };
542
+ if ( req.body.issueType === 'dataMismatch' ) {
543
+ data = { ...data, ...{ 'issueType': element.issueType ? element.issueType : '-', 'ISSUE DATE': dayjs( element.issueDate ).format( 'DD-MM-YYYY' ) } };
542
544
  }
543
545
  exportdata.push( data );
544
546
  } );
@@ -2,7 +2,7 @@
2
2
  import express from 'express';
3
3
  import { isAllowedSessionHandler, authorize, validate } from 'tango-app-api-middleware';
4
4
  import { validateDetails, bulkvalidateDetails, validateTicket, bulkvalidateTicket, validateTicketstatus, ticketExists, infraReasonExists, InfrastepstoResolve, InfraAlert } from '../validations/infra.validation.js';
5
- import { createTicket, bulkcreateTicket, updateStatus, createReason, PrimaryReasons, matTable,
5
+ import { createTicket, bulkcreateTicket, updateStatus, createReason, PrimaryReasons, matTable, removeAttachment,
6
6
  secondaryReason, updateTicketIssue, viewTicket, AlertTicketReply, uploadAttachments, getInfraIssues,
7
7
  updateInstallationTicket, emailUserList, saveInfraEmailConfig, invoice, infraTable, storeFilter, assignTicket, installationTable } from '../controllers/infra.controllers.js';
8
8
  import { getInfraIssueValid } from '../dtos/infra.dtos.js';
@@ -43,6 +43,10 @@ infraRouter.put( '/uploadAttachments/:ticketId', isAllowedSessionHandler, author
43
43
  userType: [ 'client', 'tango' ], access: [
44
44
  { featureName: 'manage', name: 'tickets', permissions: [ 'isEdit', 'isView' ] } ],
45
45
  } ), ticketExists, uploadAttachments );
46
+ infraRouter.put( '/removeAttachment/:ticketId', isAllowedSessionHandler, authorize( {
47
+ userType: [ 'client', 'tango' ], access: [
48
+ { featureName: 'manage', name: 'tickets', permissions: [ 'isEdit', 'isView' ] } ],
49
+ } ), ticketExists, removeAttachment );
46
50
  infraRouter.post( '/updateInstallationTicket', isAllowedSessionHandler, authorize( {
47
51
  userType: [ 'client', 'tango' ], access: [
48
52
  { featureName: 'manage', name: 'tickets', permissions: [ 'isEdit', 'isView' ] } ],
@@ -1,7 +1,7 @@
1
1
 
2
2
  import express from 'express';
3
3
  import { isAllowedSessionHandler, authorize } from 'tango-app-api-middleware';
4
- import { storeTicketList, storeTicketcard, edgeAppLogTable, viewedgeAppLog, cameraAngleChange } from '../controllers/storeInfra.controlller.js';
4
+ import { storeTicketList, storeTicketcard, edgeAppLogTable, viewedgeAppLog, cameraAngleChange, datewiseDowntime } from '../controllers/storeInfra.controlller.js';
5
5
  export const storeInfraRouter = express.Router();
6
6
 
7
7
  storeInfraRouter.post( '/storeTicketList', isAllowedSessionHandler, authorize( {
@@ -25,3 +25,7 @@ storeInfraRouter.post( '/cameraAngleChange', isAllowedSessionHandler, authorize(
25
25
  { featureName: 'manage', name: 'tickets', permissions: [ 'isView' ] } ],
26
26
  } ), cameraAngleChange );
27
27
 
28
+ storeInfraRouter.post( '/datewiseDowntime', isAllowedSessionHandler, authorize( {
29
+ userType: [ 'client', 'tango' ], access: [
30
+ { featureName: 'manage', name: 'tickets', permissions: [ 'isView' ] } ],
31
+ } ), datewiseDowntime );
@@ -13,6 +13,9 @@ export async function findOneTangoTicket( query, project ) {
13
13
  export async function updateOneTangoTicket( query, data ) {
14
14
  return await dataModel.tangoTicketModel.updateOne( query, { $set: data } );
15
15
  }
16
+ export async function updateOneTangoTicketunset( query, data ) {
17
+ return await dataModel.tangoTicketModel.updateOne( query, { $unset: data } );
18
+ }
16
19
  export async function updateManyTangoTicket( query, data ) {
17
20
  return await dataModel.tangoTicketModel.updateMany( query, { $set: data } );
18
21
  }