tango-app-api-infra 3.1.12 → 3.1.13

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/index.js CHANGED
@@ -6,9 +6,10 @@ import { userInfraRouter } from './src/routes/userInfra.routes.js';
6
6
  import { storeInfraRouter } from './src/routes/storeInfra.routes.js';
7
7
  import { clientInfraRouter } from './src/routes/clientInfra.routes.js';
8
8
  import { employeeTrainigRouter } from './src/routes/employeetrainig.routes.js';
9
- import { dataMismatchRouter } from './src/routes/dataMismatch.routes.js';
9
+ import { dataMismatchTicketRouter } from './src/routes/dataMismatch.routes.js';
10
+ import { infraDocs } from './src/docs/infra.docs.js';
10
11
 
11
12
 
12
- export { infraRouter, internalInfraRouter, userInfraRouter, storeInfraRouter, dataMismatchRouter, clientInfraRouter, employeeTrainigRouter };
13
+ export { infraRouter, internalInfraRouter, userInfraRouter, storeInfraRouter, dataMismatchTicketRouter, clientInfraRouter, employeeTrainigRouter, infraDocs };
13
14
 
14
15
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tango-app-api-infra",
3
- "version": "3.1.12",
3
+ "version": "3.1.13",
4
4
  "description": "infra",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -22,10 +22,12 @@
22
22
  "express-fileupload": "^1.5.0",
23
23
  "handlebars": "^4.7.8",
24
24
  "html-pdf-node": "^1.0.8",
25
+ "joi-to-swagger": "^6.2.0",
25
26
  "mongodb": "^6.4.0",
26
27
  "nodemon": "^3.1.0",
27
- "tango-api-schema": "^2.0.94",
28
- "tango-app-api-middleware": "^3.1.7",
28
+ "swagger-ui-express": "^5.0.0",
29
+ "tango-api-schema": "^2.0.103",
30
+ "tango-app-api-middleware": "^3.1.10",
29
31
  "winston": "^3.12.0",
30
32
  "winston-daily-rotate-file": "^5.0.0"
31
33
  },
@@ -1,6 +1,8 @@
1
1
 
2
- import { findOneTangoTicket, createTangoTicket } from '../services/tangoTicket.service.js';
3
- import { logger } from 'tango-app-api-middleware';
2
+ import { findOneTangoTicket, createTangoTicket, updateOneTangoTicket, aggregateTangoTicket, countDocumentsTangoTicket } from '../services/tangoTicket.service.js';
3
+ import { logger, getUTC, appConfig, fileUpload, signedUrl, sendMessageToQueue } from 'tango-app-api-middleware';
4
+ import dayjs from 'dayjs';
5
+
4
6
  export async function createTicket( req, res ) {
5
7
  try {
6
8
  let ticketExist = await findOneTangoTicket( { 'issueType': req.body.issueType, 'issueDate': ( new Date( req.body.Date ) ), 'basicDetails.storeId': req.body.storeId } );
@@ -8,11 +10,58 @@ export async function createTicket( req, res ) {
8
10
  if ( ticketExist ) {
9
11
  return res.sendSuccess( 'MAT Ticket Already Exists for the store' );
10
12
  }
13
+ let actionBy = '';
14
+ if ( req.user.userType == 'tango' ) {
15
+ actionBy = 'Tango';
16
+ } else if ( req.user.userType == 'client' ) {
17
+ actionBy = 'User';
18
+ }
11
19
  req.body.ticketDetails = {};
12
- req.body.ticketDetails.dataMismatch = req.body.dataMismatch;
20
+ req.body.dataMismatch ={
21
+ actualCount: req.body.actualCount,
22
+ expectedCount: req.body.expectedCount,
23
+ contactEmail: req.body.contactEmail,
24
+ };
13
25
  req.body.issueDate = new Date( req.body.Date );
14
26
  req.body.ticketId = 'TE_DM_' + new Date().valueOf();
15
27
  let create = await createTangoTicket( req.body );
28
+ let getObject = {};
29
+ if ( req.files ) {
30
+ let params = {
31
+ Bucket: appConfig.cloud.aws.bucket.ticket,
32
+ Key: create.ticketId + '/',
33
+ ContentType: 'multipart/form-data',
34
+ body: req.files.img.data,
35
+ fileName: req.files.img.name,
36
+ };
37
+ let upload = await fileUpload( params );
38
+ if ( upload ) {
39
+ getObject = {
40
+ fileName: req.files.img.name,
41
+ filePath: create.ticketId + '/' + req.files.img.name,
42
+ };
43
+ }
44
+ }
45
+ req.body.ticketActivity = [ {
46
+ actionType: 'Created',
47
+ timeStamp: new Date(),
48
+ actionBy: actionBy,
49
+ IdentifiedBy: req.user.userName,
50
+ description: req.body.description,
51
+ attachments: [ getObject ],
52
+ } ];
53
+ await updateOneTangoTicket( { ticketId: create.ticketId }, { ticketActivity: req.body.ticketActivity } );
54
+
55
+ const ticket = await findOneTangoTicket( { ticketId: req.body.ticketId }, { 'issueDate': 1, 'basicDetails': 1, 'issueType': 1, 'dataMismatch.contactEmail': 1, '_id': 0 } );
56
+
57
+ const obj = {
58
+ storeId: ticket.basicDetails.storeId,
59
+ issueDate: dayjs( ticket.issueDate ).format( 'DD-MM-YYYY' ),
60
+ };
61
+
62
+ if ( req.body.issueType === 'highcount' ) {
63
+ await sendMessageToQueue( `${appConfig.cloud.aws.sqs.url}${appConfig.cloud.aws.sqs.highcountTopic}`, JSON.stringify( obj ) );
64
+ }
16
65
  if ( create ) {
17
66
  res.sendSuccess( 'Ticket Created Successfully' );
18
67
  }
@@ -21,3 +70,165 @@ export async function createTicket( req, res ) {
21
70
  return res.sendError( error, 500 );
22
71
  }
23
72
  }
73
+
74
+ export async function updateMat( req, res ) {
75
+ try {
76
+ let updateValue = {};
77
+ if ( req.body.actionType && req.body.actionType != '' ) {
78
+ let actionBy = '';
79
+ if ( req.user.userType == 'tango' ) {
80
+ actionBy = 'Tango';
81
+ } else if ( req.user.userType == 'client' ) {
82
+ actionBy = 'User';
83
+ }
84
+ req.body.ticketActivity.push( {
85
+ actionType: req.body.actionType,
86
+ actionBy: actionBy,
87
+ timeStamp: new Date(),
88
+ IdentifiedBy: req.user.userName,
89
+ description: req.body.description,
90
+ attachments: req.body.attachments,
91
+ } );
92
+ updateValue = { ticketActivity: req.body.ticketActivity };
93
+ }
94
+
95
+ let updateTicket = await updateOneTangoTicket( { ticketId: req.body.ticketId }, updateValue );
96
+ if ( updateTicket ) {
97
+ res.sendSuccess( 'Ticket Updated Successfully' );
98
+ }
99
+ } catch ( error ) {
100
+ logger.error( { error: error, function: 'updateMat' } );
101
+ return res.sendError( error, 500 );
102
+ }
103
+ }
104
+
105
+
106
+ export async function activityList( req, res ) {
107
+ try {
108
+ let date = await getUTC( new Date( req.body.fromDate ), new Date( req.body.toDate ) );
109
+ let query = [ {
110
+ $match: {
111
+ $and: [
112
+ { 'basicDetails.storeId': req.body.storeId },
113
+ { issueType: { $in: [ 'lowcount', 'highcount' ] } },
114
+ { createdAt: { $gte: date.start } },
115
+ { createdAt: { $lte: date.end } },
116
+ ],
117
+ },
118
+ },
119
+ {
120
+ $project: {
121
+ storeId: '$basicDetails.storeId',
122
+ status: 1,
123
+ issueDate: '$issueDate',
124
+ Date: { $dateToString: { format: '%d-%m-%Y', date: '$createdAt' } },
125
+ issueClosedDate: 1,
126
+ ticketId: 1,
127
+ issueType: 1,
128
+ ticketActivity: 1,
129
+ comments: { $size: '$ticketActivity' },
130
+ },
131
+ },
132
+ {
133
+ $unwind: {
134
+ path: '$ticketActivity', preserveNullAndEmptyArrays: true,
135
+ },
136
+ },
137
+ {
138
+ $group: {
139
+ _id: '$ticketId',
140
+ storeId: { $first: '$storeId' },
141
+ Date: { $first: '$Date' },
142
+ issueClosedDate: { $first: '$issueClosedDate' },
143
+ status: { $first: '$status' },
144
+ issueDate: { $first: '$issueDate' },
145
+ ticketId: { $first: '$ticketId' },
146
+ issueType: { $first: '$issueType' },
147
+ comments: { $first: '$comments' },
148
+ description: { $last: '$ticketActivity.description' },
149
+ },
150
+ },
151
+ {
152
+ $sort: {
153
+ issueDate: -1,
154
+ },
155
+ },
156
+ ];
157
+
158
+ if ( req.body.filter && req.body.filter !== '' ) {
159
+ query.push( {
160
+ $match: {
161
+ issueType: req.body.filter,
162
+ },
163
+ } );
164
+ }
165
+ let ticketList = await aggregateTangoTicket( query );
166
+ if ( req.body.export && ticketList.length > 0 ) {
167
+ const exportdata = [];
168
+ ticketList.forEach( ( element ) => {
169
+ exportdata.push( {
170
+ 'STORE ID': element.storeId,
171
+ 'TICKET ID': element.ticketId,
172
+ 'DATE': element.Date,
173
+ 'ISSUE CLOSED DATE': element.issueClosedDate,
174
+ 'STATUS': element.status,
175
+ 'COMMENT': element.description,
176
+ } );
177
+ } );
178
+ await download( exportdata, res );
179
+ return;
180
+ }
181
+ if ( ticketList.length ) {
182
+ let highCount = await countDocumentsTangoTicket( {
183
+ $and: [
184
+ { 'basicDetails.storeId': req.body.storeId },
185
+ { issueType: 'highcount' },
186
+ { createdAt: { $gte: date.start } },
187
+ { createdAt: { $lte: date.end } },
188
+ ],
189
+ } );
190
+ let lowCount = await countDocumentsTangoTicket( {
191
+ $and: [
192
+ { 'basicDetails.storeId': req.body.storeId },
193
+ { issueType: 'lowcount' },
194
+ { createdAt: { $gte: date.start } },
195
+ { createdAt: { $lte: date.end } },
196
+ ],
197
+ } );
198
+
199
+ res.sendSuccess( {
200
+ count: ticketList.length,
201
+ data: ticketList,
202
+ highCount: highCount,
203
+ lowCount: lowCount,
204
+ } );
205
+ } else {
206
+ return res.sendError( 'NO data', 204 );
207
+ }
208
+ } catch ( error ) {
209
+ logger.error( { error: error, function: 'activityList' } );
210
+ return res.sendError( error, 500 );
211
+ }
212
+ }
213
+
214
+
215
+ export async function showActivity( req, res ) {
216
+ try {
217
+ for ( let activity of req.body.ticketActivity ) {
218
+ if ( activity.attachments&&activity.attachments.length>0 ) {
219
+ for ( let attchment of activity.attachments ) {
220
+ let params = {
221
+ Bucket: appConfig.cloud.aws.bucket.ticket,
222
+ file_path: attchment.filePath,
223
+ };
224
+ let attachments = await signedUrl( params );
225
+ attchment.signedUrl = attachments;
226
+ }
227
+ }
228
+ }
229
+ res.sendSuccess( req.body );
230
+ } catch ( error ) {
231
+ logger.error( { error: error, function: 'showActivity' } );
232
+ return res.sendError( error, 500 );
233
+ }
234
+ }
@@ -48,3 +48,16 @@ export async function activityLog( req, res ) {
48
48
  return res.sendError( error, 500 );
49
49
  }
50
50
  }
51
+
52
+
53
+ export async function updateMatStatus( req, res ) {
54
+ try {
55
+ let update = await updateOneTangoTicket( { ticketId: req.body.ticketId }, { 'ticketDetails.matStatus': req.body.matStatus } );
56
+ if ( update ) {
57
+ res.sendSuccess( 'Updated Successfully' );
58
+ }
59
+ } catch ( error ) {
60
+ logger.error( { error: error, function: 'updateMatStatus' } );
61
+ return res.sendError( error, 500 );
62
+ }
63
+ }
@@ -13,10 +13,11 @@ import handlebars from 'handlebars';
13
13
  import { findOneGroup } from '../services/group.service.js';
14
14
  import htmlpdf from 'html-pdf-node';
15
15
  import mongoose from 'mongoose';
16
+ import _ from 'lodash';
17
+ import { aggregateCamera } from '../services/camera.service.js';
16
18
  export async function createTicket( req, res ) {
17
19
  try {
18
20
  req.body.issueDate = new Date( req.body.Date );
19
- req.body.ticketDetails.filesCount = req.body.filesCount;
20
21
  if ( req.body.issueType == 'infra' ) {
21
22
  req.body.ticketId = 'TE_INF_' + new Date().valueOf();
22
23
  req.body.ticketActivity = [ {
@@ -125,33 +126,28 @@ export async function bulkcreateTicket( req, res ) {
125
126
 
126
127
  export async function updateStatus( req, res ) {
127
128
  try {
128
- console.log( req.user.userType );
129
129
  if ( req.user.userType == 'tango' ) {
130
- if ( req.body.status == 'inprogress' ) {
131
- req.body.ticketActivity.push( {
132
- actionType: 'statusChange',
133
- timeStamp: new Date(),
134
- actionBy: 'Tango',
135
- IdentifiedBy: req.user.userName,
136
- } );
137
- req.body.status ='inprogress';
138
- }
130
+ req.body.ticketActivity.push( {
131
+ actionType: 'statusChange',
132
+ timeStamp: new Date(),
133
+ actionBy: 'Tango',
134
+ IdentifiedBy: req.user.userName,
135
+ } );
136
+ req.body.status = 'inprogress';
139
137
  req.body.ticketDetails.addressingUser = req.user._id;
140
- console.log( req.body );
141
138
  let updateTicket = await updateOneTangoTicket( { ticketId: req.body.ticketId }, req.body );
142
139
  if ( updateTicket ) {
143
140
  res.sendSuccess( 'Ticket Updated Successfully' );
144
141
  }
145
142
  } else if ( req.user.userType == 'client' ) {
146
- if ( req.body.status == 'inprogress' ) {
147
- req.body.ticketActivity.push( {
148
- actionType: 'statusChange',
149
- timeStamp: new Date(),
150
- actionBy: 'User',
151
- IdentifiedBy: req.user.userName,
152
- } );
153
- req.body.status ='inprogress';
154
- }
143
+ req.body.ticketActivity.push( {
144
+ actionType: 'statusChange',
145
+ timeStamp: new Date(),
146
+ actionBy: 'User',
147
+ IdentifiedBy: req.user.userName,
148
+ } );
149
+ req.body.status = 'inprogress';
150
+
155
151
  req.body.ticketDetails.addressingClient = req.user._id;
156
152
  let updateTicket = await updateOneTangoTicket( { ticketId: req.body.ticketId }, req.body );
157
153
  if ( updateTicket ) {
@@ -611,6 +607,217 @@ export async function invoice( req, res ) {
611
607
  } );
612
608
  }
613
609
 
610
+ export async function getInfraIssues( req, res ) {
611
+ try {
612
+ const inputData = req.body;
613
+ const query=[
614
+ {
615
+ $match: {
616
+ $and: [
617
+ {
618
+ 'issueType': { $eq: 'infra' },
619
+
620
+ },
621
+ {
622
+ 'basicDetails.storeId': { $eq: inputData.storeId },
623
+
624
+ },
625
+ {
626
+ 'issueDate': { $gte: new Date( inputData.fromDate ) },
627
+
628
+ },
629
+ {
630
+ 'issueDate': { $lte: new Date( inputData.toDate ) },
631
+
632
+ },
633
+ {
634
+ 'ticketDetails.issueStatus': { $eq: 'identified' },
635
+
636
+ },
637
+
638
+ ],
639
+ },
640
+ },
641
+ {
642
+ $project: {
643
+ issueType: 1,
644
+ issueDate: { $dateToString: { format: '%Y-%m-%d', date: '$issueDate' } },
645
+ ticketActivity: {
646
+ $filter: {
647
+ input: '$ticketActivity',
648
+ as: 'item',
649
+ cond: { $eq: [ '$$item.actionType', 'issueUpdate' ] },
650
+ },
651
+ },
652
+ },
653
+ },
654
+
655
+ {
656
+ $unwind: {
657
+ path: '$ticketActivity', preserveNullAndEmptyArrays: true,
658
+ },
659
+ },
660
+ {
661
+ $unwind: {
662
+ path: '$ticketActivity.reasons', preserveNullAndEmptyArrays: true,
663
+ },
664
+ },
665
+ {
666
+ $group: {
667
+ _id: { reason: '$ticketActivity.reasons', issueDate: '$issueDate' },
668
+ issueDate: { $first: '$issueDate' },
669
+ primaryIssue: { $last: '$ticketActivity.reasons.primaryIssue' },
670
+ secondaryIssue: { $last: '$ticketActivity.reasons.secondaryIssue' },
671
+
672
+ },
673
+ },
674
+ {
675
+ $unwind: {
676
+ path: '$secondaryIssue', preserveNullAndEmptyArrays: true,
677
+ },
678
+ },
679
+ {
680
+ $group: {
681
+ _id: { issue: '$primaryIssue', issueDate: '$issueDate' },
682
+ issueDate: { $first: '$issueDate' },
683
+ primaryIssue: { $last: '$primaryIssue' },
684
+ secondaryReason: { $push: '$secondaryIssue.name' },
685
+
686
+ },
687
+ },
688
+ {
689
+ $project: {
690
+ _id: 0,
691
+ issueDate: 1,
692
+ primaryIssue: 1,
693
+ secondaryReason: 1,
694
+ downTime: { $ifNull: [ 0, 0 ] },
695
+ speedTest: { $ifNull: [ 0.5, 0.5 ] },
696
+ },
697
+
698
+ },
699
+ ];
700
+
701
+
702
+ let retVal = [];
703
+ let current = new Date( inputData.fromDate );
704
+ let end = new Date( inputData.toDate );
705
+
706
+ while ( current <= end ) {
707
+ retVal.push( { issueDate: dayjs( current ).format( 'YYYY-MM-DD' ), downTime: 0, speedTest: 0.6 } );
708
+ current.setDate( current.getDate() + 1 );
709
+ }
710
+
711
+ const result = await aggregateTangoTicket( query );
712
+
713
+ const mergeValue =_.values(
714
+ _.merge(
715
+ _.keyBy( retVal, 'issueDate' ),
716
+ _.keyBy( result, 'issueDate' ),
717
+ ),
718
+ );
719
+ logger.info( { message: mergeValue, value1: result } );
720
+
721
+ if ( mergeValue.length == 0 ) {
722
+ return res.sendError( 'NO Data Found', 204 );
723
+ }
724
+ for ( let i =0; i< mergeValue.length; i++ ) {
725
+ const downTime = await getOpenSearchData( 'live_downtime_hourly',
726
+ {
727
+ 'size': 100,
728
+ 'query': {
729
+ 'bool': {
730
+ 'must': [
731
+ {
732
+ 'term': {
733
+ 'doc.date.keyword': dayjs( mergeValue[i].issueDate ).format( 'DD-MM-YYYY' ),
734
+ },
735
+ },
736
+ {
737
+ 'term': {
738
+ 'doc.store_id.keyword': inputData.storeId,
739
+ },
740
+ },
741
+
742
+ ],
743
+
744
+ },
745
+ },
746
+
747
+ } );
748
+ let streamwiseDowntime = [];
749
+ logger.info( { streamwiseDowntime: downTime.body.hits.hits.length } );
750
+ 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 ) => {
753
+ return accumulator + currentValue.down_time;
754
+ }, 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 );
758
+ }
759
+ }
760
+ }
761
+ const camQuery = [
762
+ {
763
+ $match: {
764
+ $and: [
765
+ { isUp: { $eq: true } },
766
+ { isActivated: { $eq: true } },
767
+ { storeId: inputData.storeId },
768
+ ],
769
+ },
770
+ },
771
+ {
772
+ $project: {
773
+ _id: 0,
774
+ streamName: 1,
775
+ cameraNumber: 1,
776
+ thumbnailImage: await signedUrl( { Bucket: appConfig.cloud.aws.bucket.baseImage, file_path: '$thumbnailImage' } ),
777
+ },
778
+ },
779
+ ];
780
+
781
+ const highCountQuery =[
782
+ {
783
+ $match: {
784
+ $and: [
785
+ { 'basicDetails.storeId': inputData.storeId },
786
+ { issueType: { $in: [ 'highcount', 'lowcount' ] } },
787
+
788
+ ],
789
+ },
790
+ },
791
+ {
792
+ $group: {
793
+ _id: null,
794
+ total: { $sum: 1 },
795
+ successRate: { $avg: '$dataMismatch.successPercentage' },
796
+ },
797
+ },
798
+ {
799
+ $project: {
800
+ _id: 0,
801
+ total: 1,
802
+ successRate: 1,
803
+ },
804
+ },
805
+ ];
806
+ const defaultValue= {
807
+ total: 0,
808
+ successRate: 0,
809
+ };
810
+ const getHighCountTicket = await aggregateTangoTicket( highCountQuery );
811
+ logger.info( { getHighCountTicket: getHighCountTicket } );
812
+ const camera = await aggregateCamera( camQuery );
813
+ logger.info( { message: camera } );
814
+ return res.sendSuccess( { result: mergeValue, streams: camera, highCountTicketDetails: getHighCountTicket[0] || defaultValue } );
815
+ } catch ( error ) {
816
+ logger.error( { error: error, function: 'getInfraIssues' } );
817
+ return res.sendError( error, 500 );
818
+ }
819
+ }
820
+
614
821
 
615
822
  function inWords( num ) {
616
823
  let a = [ '', 'one ', 'two ', 'three ', 'four ', 'five ', 'six ', 'seven ', 'eight ', 'nine ', 'ten ', 'eleven ', 'twelve ', 'thirteen ', 'fourteen ', 'fifteen ', 'sixteen ', 'seventeen ', 'eighteen ', 'nineteen ' ]; let b = [ '', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety' ];
@@ -1237,14 +1444,14 @@ export async function matTable( req, res ) {
1237
1444
  result.forEach( ( element ) => {
1238
1445
  exportdata.push( {
1239
1446
  'ticketId': element.ticketId,
1240
- 'issueDate': dayjs( element.issueDate ).format( 'DD-MM-YYYY' ),
1447
+ 'Date': dayjs( element.issueDate ).format( 'DD-MM-YYYY' ),
1241
1448
  'storeId': element.storeId,
1242
1449
  'storeName': element.storeName,
1243
1450
  'clientId': element.clientId,
1244
1451
  'clientName': element.clientName,
1245
1452
  'userName': element.userName,
1246
1453
  'userEmail': element.userEmail,
1247
- 'Status': element.installationStatus,
1454
+ 'Status': element.status,
1248
1455
  } );
1249
1456
  } );
1250
1457
  await download( exportdata, res );
@@ -1276,18 +1483,25 @@ export async function assignTicket( req, res ) {
1276
1483
  }
1277
1484
  export async function storeFilter( req, res ) {
1278
1485
  try {
1279
- let stores = await findTangoTicket( { 'issueType': req.body.issueType, 'basicDetails.clientId': req.body.clientId, 'basicDetails.storeId': { $exists: true } }, { 'basicDetails.storeId': 1 } );
1486
+ const inputData = req.body;
1487
+ let query = { 'issueType': inputData.issueType, 'basicDetails.clientId': inputData.clientId, 'basicDetails.storeId': { $exists: true } };
1488
+ if ( inputData.issueType == 'dataMismatch' ) {
1489
+ query ={
1490
+ 'issueType': { '$in': [ 'highcount', 'lowcount' ] }, 'basicDetails.clientId': inputData.clientId, 'basicDetails.storeId': { $exists: true },
1491
+ };
1492
+ }
1493
+ let stores = await findTangoTicket( query, { 'basicDetails.storeId': 1 } );
1280
1494
  const uniqueStoreIds = [ ...new Set( stores.map( ( store ) => store.basicDetails.storeId ) ) ];
1281
1495
  const uniqueStoreObjects = uniqueStoreIds.map( ( storeId ) => ( { 'storeId': storeId } ) );
1282
1496
 
1283
- if ( uniqueStoreObjects.length>0 ) {
1497
+ if ( uniqueStoreObjects.length > 0 ) {
1284
1498
  res.sendSuccess( { count: uniqueStoreObjects.length, data: uniqueStoreObjects } );
1285
1499
  } else {
1286
1500
  res.sendError( 'No data', 204 );
1287
1501
  }
1288
1502
  } catch ( error ) {
1289
- // console.log( error );
1290
1503
  logger.error( { error: error, function: 'storeFilter' } );
1291
1504
  return res.sendError( error, 500 );
1292
1505
  }
1293
1506
  }
1507
+
@@ -445,11 +445,10 @@ export async function emailUserList( req, res ) {
445
445
  }
446
446
  export async function infraReportSent( req, res ) {
447
447
  try {
448
- let date;
449
448
  // if ( req.body.type == 'start' ) {
450
449
  // date = dayjs().subtract( 1, 'day' ).format( 'YYYY-MM-DD' );
451
450
  // } else if ( req.body.type == 'end' ) {
452
- date = dayjs().format( 'YYYY-MM-DD' );
451
+ let date = dayjs( ).format( 'YYYY-MM-DD' );
453
452
  // };
454
453
  let query = [ {
455
454
  $match: {
@@ -468,6 +467,13 @@ export async function infraReportSent( req, res ) {
468
467
  status: 1,
469
468
  ticketDetails: 1,
470
469
  issueClosedDate: 1,
470
+ otherscomment: {
471
+ $filter: {
472
+ input: '$ticketActivity',
473
+ as: 'item',
474
+ cond: { $eq: [ '$$item.actionType', 'comment' ] },
475
+ },
476
+ },
471
477
  primaryIssue: {
472
478
  $filter: {
473
479
  input: '$ticketActivity',
@@ -477,6 +483,11 @@ export async function infraReportSent( req, res ) {
477
483
  },
478
484
  },
479
485
  },
486
+ {
487
+ $unwind: {
488
+ path: '$otherscomment', preserveNullAndEmptyArrays: true,
489
+ },
490
+ },
480
491
  {
481
492
  $unwind: {
482
493
  path: '$primaryIssue', preserveNullAndEmptyArrays: true,
@@ -500,6 +511,8 @@ export async function infraReportSent( req, res ) {
500
511
  status: 1,
501
512
  ticketDetails: 1,
502
513
  issueClosedDate: 1,
514
+ ommentText: { $ifNull: [ '$primaryIssue.comment', '-' ] },
515
+ otherscomment: { $ifNull: [ '$otherscomment.comment', '-' ] },
503
516
  primaryIssue: { $ifNull: [ '$primaryIssue.reasons.primaryIssue', '-' ] },
504
517
  secondaryIssue: { $ifNull: [ '$primaryIssue.reasons.secondaryIssue.name', '-' ] },
505
518
  },
@@ -510,11 +523,12 @@ export async function infraReportSent( req, res ) {
510
523
  ticketDetails: { $first: '$ticketDetails' },
511
524
  issueClosedDate: { $first: '$issueClosedDate' },
512
525
  basicDetails: { $first: '$basicDetails' },
526
+ commentText: { $last: '$commentText' },
513
527
  primaryIssue: { $last: '$primaryIssue' },
514
528
  secondaryIssue: { $last: '$secondaryIssue' },
529
+ otherscomment: { $last: '$otherscomment' },
515
530
  createdAt: { $first: '$createdAt' },
516
531
  status: { $last: '$status' },
517
-
518
532
  },
519
533
  },
520
534
  ];
@@ -527,7 +541,7 @@ export async function infraReportSent( req, res ) {
527
541
  exportdata.push( {
528
542
  'Client ID': element.basicDetails.clientId,
529
543
  'Client Name': element.basicDetails.clientName,
530
- 'Ticket Created Date & Time': dayjs( element.createdAt ).format( 'YYYY-MM-DD HH:mm A' ),
544
+ 'Ticket Created Date & Time': dayjs( element.createdAt ).tz( 'Asia/Kolkata' ).format( 'YYYY-MM-DD HH:mm A' ),
531
545
  'Store ID': element.basicDetails.storeId,
532
546
  'Store Name': element.basicDetails.storeName,
533
547
  'Issue ': element.primaryIssue,
@@ -535,9 +549,12 @@ export async function infraReportSent( req, res ) {
535
549
  'Status ': element.status,
536
550
  'Responded By': clientuser && clientuser.userName ? clientuser.userName : '-',
537
551
  'Resolved By': tangouser && tangouser.userName ? tangouser.userName : '-',
538
- 'Ticket Closed Date & Time': element.issueClosedDate ? dayjs( element.issueClosedDate ).format( 'YYYY-MM-DD HH:mm A' ) : '-',
539
- 'Latest Comment': '',
540
- 'Activity Log': `${appConfig.url.domain+'/manage/stores/infra-ticket?storeId='+element.basicDetails.storeId}`,
552
+ '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,
554
+ 'Activity Log': {
555
+ label: 'Link',
556
+ url: `${appConfig.url.domain+'/manage/stores/infra-ticket?storeId='+element.basicDetails.storeId}`,
557
+ },
541
558
  } );
542
559
  }
543
560
 
@@ -572,40 +589,23 @@ export async function infraReportSent( req, res ) {
572
589
  count: 0,
573
590
  } ) );
574
591
  }
575
- let reportdate = dayjs().format( 'YYYY-MM-DD' );
592
+
576
593
  let attachments = null;
577
- if ( exportdata.length > 0 ) {
578
- const wb = new xl.Workbook();
579
- const ws = wb.addWorksheet( 'Daily report' );
580
- const headers = Object.keys( exportdata[0] );
594
+ let buffer = await download( exportdata );
595
+ attachments = {
596
+ filename: `dailyInfraReport- ${date}.xlsx`,
597
+ content: buffer,
598
+ contentType: 'application/xlsx', // e.g., 'application/pdf'
599
+ };
581
600
 
582
- for ( let i = 0; i < headers.length; i++ ) {
583
- ws.cell( 1, i + 1 ).string( headers[i] );
584
- };
585
- for ( let i = 0; i < exportdata.length; i++ ) {
586
- const dataRow = exportdata[i];
587
- for ( let j = 0; j < headers.length; j++ ) {
588
- const header = headers[j];
589
- const value = dataRow[header];
590
- ws.cell( i + 2, j + 1 ).string( value?.toString() );
591
- }
592
- }
593
- let buffer = await wb.writeToBuffer();
594
601
 
595
- attachments = {
596
- filename: `dailyInfraReport- ${reportdate}.xlsx`,
597
- content: buffer,
598
- contentType: 'application/xlsx', // e.g., 'application/pdf'
599
- };
600
- }
601
-
602
- const subject = `Daily Digest - Infra Downtime Report - ${reportdate}`;
602
+ const subject = `Daily Digest - Infra Downtime Report - ${date}`;
603
603
  const fileContent = readFileSync( join() + '/src/hbs/dailyInfraReport.hbs', 'utf8' );
604
604
  const htmlContent = handlebars.compile( fileContent );
605
605
  let Uidomain = `${appConfig.url.domain}`;
606
606
 
607
607
 
608
- const html = htmlContent( { ...req.body, Uidomain: Uidomain, issueCount: issueCount, avgDownTime: avgDownTime, reportdate: reportdate, content: response, date: date, domain: appConfig.url.apiDomain } );
608
+ const html = htmlContent( { ...req.body, Uidomain: Uidomain, issueCount: issueCount, avgDownTime: avgDownTime, reportdate: date, content: response, date: date, domain: appConfig.url.apiDomain } );
609
609
  if ( isValidEmail( req.body.email ) ) {
610
610
  const result = await sendEmailWithSES( req.body.email, subject, html, attachments, appConfig.cloud.aws.ses.adminEmail );
611
611
  res.sendSuccess( result );
@@ -724,8 +724,7 @@ export async function download( data ) {
724
724
  for ( let j = 0; j < headers.length; j++ ) {
725
725
  const header = headers[j];
726
726
  const value = dataRow[header];
727
-
728
- if ( typeof value === 'object' && value.hasOwnProperty( 'label' ) && value.hasOwnProperty( 'url' ) ) {
727
+ if ( value&& typeof value === 'object' && value.hasOwnProperty( 'label' ) && value.hasOwnProperty( 'url' ) ) {
729
728
  ws.cell( i + 2, j + 1 ).link( value.url );
730
729
  ws.cell( i + 2, j + 1 ).string( value.label );
731
730
  } else {
@@ -884,11 +883,9 @@ export async function edgeApplogsCheck( req, res ) {
884
883
  let findissueEdgeApp = {};
885
884
  if ( result.length>0 ) {
886
885
  for ( let findissue of result ) {
887
- // console.log( ticket.ticketId );
888
886
  const istTimestamp = dayjs.utc( ticket.createdAt ).tz( 'Asia/Kolkata' ).format( 'HH:mm:ss' );
889
887
 
890
888
  if ( findissue.code == '1003' ) {
891
- // Compare the times
892
889
  const occurringTimeParsed = dayjs( `${req.body.date} ${findissue.edgelog.occuringTime}` );
893
890
  const ticketCreatedParsed = dayjs( `${req.body.date} ${istTimestamp}` );
894
891
  const isOccurringTimeEarlier = occurringTimeParsed.isBefore( ticketCreatedParsed );
@@ -902,7 +899,6 @@ export async function edgeApplogsCheck( req, res ) {
902
899
  };
903
900
  updateIssue( findissueEdgeApp );
904
901
  finalresult.push( findissueEdgeApp );
905
- // console.log( findissueEdgeApp );
906
902
  }
907
903
  } else if ( findissue.code == '1024' ) {
908
904
  const occurringTimeParsed = dayjs( `${req.body.date} ${findissue.edgelog.data.occuringTime}` );
@@ -938,7 +934,6 @@ export async function edgeApplogsCheck( req, res ) {
938
934
  };
939
935
  updateIssue( findissueEdgeApp );
940
936
  finalresult.push( findissueEdgeApp );
941
- // console.log( findissueEdgeApp );
942
937
  }
943
938
  } else if ( findissue.code ==='1005' ) {
944
939
  const occurringTimeParsed = dayjs( `${req.body.date} ${findissue.edgelog.occuringTime}` );
@@ -954,7 +949,6 @@ export async function edgeApplogsCheck( req, res ) {
954
949
  };
955
950
  updateIssue( findissueEdgeApp );
956
951
  finalresult.push( findissueEdgeApp );
957
- // console.log( findissueEdgeApp );
958
952
  }
959
953
  }
960
954
  }
@@ -1054,7 +1048,6 @@ export async function updateIssue( data ) {
1054
1048
  'status': 'inprogress',
1055
1049
  };
1056
1050
  await updateOneTangoTicket( { ticketId: data.ticketId }, query );
1057
- // console.log( data );
1058
1051
  } catch ( error ) {
1059
1052
  logger.error( { error: error, function: 'updateAutomaticIssue' } );
1060
1053
  res.sendError( error, 500 );
@@ -28,7 +28,20 @@ export async function storeTicketList( req, res ) {
28
28
  ticketId: 1,
29
29
  issueStatus: '$ticketDetails.issueStatus',
30
30
  ticketType: '$ticketDetails.ticketType',
31
- comments: { $size: '$ticketActivity' },
31
+ otherscomment: {
32
+ $filter: {
33
+ input: '$ticketActivity',
34
+ as: 'item',
35
+ cond: { $eq: [ '$$item.actionType', 'comment' ] },
36
+ },
37
+ },
38
+ comments: {
39
+ $filter: {
40
+ input: '$ticketActivity',
41
+ as: 'item',
42
+ cond: { $ne: [ '$$item.actionType', 'statusChange' ] },
43
+ },
44
+ },
32
45
  primaryIssue: {
33
46
  $filter: {
34
47
  input: '$ticketActivity',
@@ -43,11 +56,21 @@ export async function storeTicketList( req, res ) {
43
56
  path: '$primaryIssue', preserveNullAndEmptyArrays: true,
44
57
  },
45
58
  },
59
+ {
60
+ $unwind: {
61
+ path: '$otherscomment', preserveNullAndEmptyArrays: true,
62
+ },
63
+ },
46
64
  {
47
65
  $unwind: {
48
66
  path: '$primaryIssue.reasons', preserveNullAndEmptyArrays: true,
49
67
  },
50
68
  },
69
+ {
70
+ $unwind: {
71
+ path: '$primaryIssue.reasons.secondaryIssue', preserveNullAndEmptyArrays: true,
72
+ },
73
+ },
51
74
  {
52
75
  $project: {
53
76
  storeId: 1,
@@ -57,10 +80,12 @@ export async function storeTicketList( req, res ) {
57
80
  ticketId: 1,
58
81
  issueStatus: 1,
59
82
  ticketType: 1,
60
- comments: 1,
83
+ comments: { $size: '$comments' },
61
84
  issueDate: 1,
85
+ commentText: '$primaryIssue.comment',
62
86
  primaryIssue: '$primaryIssue.reasons.primaryIssue',
63
- secondaryIssue: '$primaryIssue.reasons.secondaryIssue',
87
+ secondaryIssue: '$primaryIssue.reasons.secondaryIssue.name',
88
+ otherscomment: '$otherscomment.comment',
64
89
  },
65
90
  },
66
91
  {
@@ -75,8 +100,11 @@ export async function storeTicketList( req, res ) {
75
100
  issueStatus: { $first: '$issueStatus' },
76
101
  ticketType: { $first: '$ticketType' },
77
102
  comments: { $first: '$comments' },
103
+ commentText: { $last: '$commentText' },
78
104
  primaryIssue: { $last: '$primaryIssue' },
79
105
  secondaryIssue: { $last: '$secondaryIssue' },
106
+ otherscomment: { $last: '$otherscomment' },
107
+
80
108
  },
81
109
  },
82
110
  {
@@ -102,8 +130,10 @@ export async function storeTicketList( req, res ) {
102
130
  'TICKET ID': element.ticketId,
103
131
  'DATE': element.Date,
104
132
  'ISSUE CLOSED DATE': element.issueClosedDate,
105
- 'ISSUE': element.primaryIssue,
133
+ 'PRIMARY ISSUE': element.primaryIssue,
134
+ 'SECONDARY ISSUE': element.secondaryIssue,
106
135
  'STATUS': element.status,
136
+ 'COMMENT': element.otherscomment?element.otherscomment:element.commentText,
107
137
  } );
108
138
  } );
109
139
  await download( exportdata, res );
@@ -330,7 +360,6 @@ export async function edgeAppLogTable( req, res ) {
330
360
  };
331
361
  const downtime = await getOpenSearchData( 'live_downtime_hourly', downTimeQuery );
332
362
  let streamwiseDowntime = downtime.body.hits.hits.length > 0 ? downtime.body.hits.hits[0]._source.doc.streamwise_downtime : [];
333
- // console.log( obj.hour, streamwiseDowntime );
334
363
  if ( streamwiseDowntime.length > 0 ) {
335
364
  const sum = streamwiseDowntime.reduce( ( accumulator, currentValue ) => {
336
365
  return accumulator + currentValue.down_time;
@@ -92,7 +92,7 @@ export async function userTakeTicket( req, res ) {
92
92
  }
93
93
  userTicket = await findOneTangoTicket( query );
94
94
  }
95
- if ( userTicket ) {
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' );
@@ -113,6 +113,7 @@ export async function userTicketList( req, res ) {
113
113
  query.push( {
114
114
  $match: {
115
115
  $and: [
116
+ { 'basicDetails.clientId': { $in: req.body.clientId } },
116
117
  { issueType: req.body.issueType },
117
118
  { 'ticketDetails.addressingUser': new mongoose.Types.ObjectId( req.body.userId ) },
118
119
  ],
@@ -122,6 +123,7 @@ export async function userTicketList( req, res ) {
122
123
  query.push( {
123
124
  $match: {
124
125
  $and: [
126
+ { 'basicDetails.clientId': { $in: req.body.clientId } },
125
127
  { issueType: { $in: [ 'highcount', 'lowcount' ] } },
126
128
  { 'ticketDetails.addressingUser': new mongoose.Types.ObjectId( req.body.userId ) },
127
129
  ],
@@ -163,6 +165,7 @@ export async function userTicketList( req, res ) {
163
165
  issueStatus: '$ticketDetails.issueStatus',
164
166
  ticketType: '$ticketDetails.ticketType',
165
167
  installationStatus: '$ticketDetails.installationStatus',
168
+ matStatus: '$ticketDetails.matStatus',
166
169
  primaryIssue: {
167
170
  $filter: {
168
171
  input: '$ticketActivity',
@@ -194,6 +197,7 @@ export async function userTicketList( req, res ) {
194
197
  status: 1,
195
198
  issueType: 1,
196
199
  installationStatus: 1,
200
+ matStatus: 1,
197
201
  infraIssue: '$primaryIssue.reasons.primaryIssue',
198
202
  },
199
203
  },
@@ -208,6 +212,7 @@ export async function userTicketList( req, res ) {
208
212
  issueType: { $first: '$issueType' },
209
213
  status: { $first: '$status' },
210
214
  installationStatus: { $first: '$installationStatus' },
215
+ matStatus: { $first: '$matStatus' },
211
216
  issueStatus: { $first: '$issueStatus' },
212
217
  ticketType: { $first: '$ticketType' },
213
218
  infraIssue: { $last: '$infraIssue' },
@@ -232,6 +237,7 @@ export async function userTicketList( req, res ) {
232
237
  $or: [
233
238
  { issueStatus: req.body.filter },
234
239
  { infraIssue: req.body.filter },
240
+ { issueType: req.body.filter },
235
241
  ],
236
242
  },
237
243
  } );
@@ -240,13 +246,23 @@ export async function userTicketList( req, res ) {
240
246
  if ( req.body.export ) {
241
247
  const exportdata = [];
242
248
  ticketList.forEach( ( element ) => {
243
- exportdata.push( {
249
+ let data = {
244
250
  'DATE': element.Date,
245
251
  'TICKET ID': element.ticketId,
246
252
  'STORE ID': element.storeId,
247
- 'ISSUE': element.issueStatus,
253
+ 'STORE NAME': element.storeName,
248
254
  'STATUS': element.status,
249
- } );
255
+ };
256
+ if ( req.body.issueType ==='infra' ) {
257
+ data = { ...data, ...{ 'ISSUE': element.issueStatus } };
258
+ }
259
+ if ( req.body.issueType ==='installation' ) {
260
+ data = { ...data, ...{ 'ISSUE': element.issueStatus } };
261
+ }
262
+ if ( req.body.issueType ==='dataMismatch' ) {
263
+ data = { ...data, ...{ 'ISSUE TYPE': element.issueType } };
264
+ }
265
+ exportdata.push( data );
250
266
  } );
251
267
  await download( exportdata, res );
252
268
  return;
@@ -334,6 +350,7 @@ export async function workHistory( req, res ) {
334
350
  query.push( {
335
351
  $match: {
336
352
  $and: [
353
+ { 'basicDetails.clientId': { $in: req.body.clientId } },
337
354
  { 'status': 'closed' },
338
355
  { issueType: req.body.issueType },
339
356
  { 'ticketDetails.addressingUser': new mongoose.Types.ObjectId( req.body.userId ) },
@@ -344,6 +361,7 @@ export async function workHistory( req, res ) {
344
361
  query.push( {
345
362
  $match: {
346
363
  $and: [
364
+ { 'basicDetails.clientId': { $in: req.body.clientId } },
347
365
  { 'status': 'closed' },
348
366
  { issueType: { $in: [ 'highcount', 'lowcount' ] } },
349
367
  { 'ticketDetails.addressingUser': new mongoose.Types.ObjectId( req.body.userId ) },
@@ -373,6 +391,18 @@ export async function workHistory( req, res ) {
373
391
  { 'issueClosedDate': { $lte: date.end } },
374
392
  ],
375
393
 
394
+ },
395
+ },
396
+ );
397
+ } else if ( req.body.dateFilter === 'issueDate' ) {
398
+ query.push(
399
+ {
400
+ $match: {
401
+ $and: [
402
+ { 'issueDate': { $gte: date.start } },
403
+ { 'issueDate': { $lte: date.end } },
404
+ ],
405
+
376
406
  },
377
407
  },
378
408
  );
@@ -407,6 +437,7 @@ export async function workHistory( req, res ) {
407
437
  storeName: '$basicDetails.storeName',
408
438
  clientId: '$basicDetails.clientId',
409
439
  clientName: '$basicDetails.clientName',
440
+ issueType: 1,
410
441
  issueDate: { $dateToString: { format: '%Y-%m-%d', date: '$createdAt' } },
411
442
  issueClosedDate: { $dateToString: { format: '%Y-%m-%d', date: '$issueClosedDate' } },
412
443
  issueIdentifiedDate: { $dateToString: { format: '%Y-%m-%d', date: '$ticketDetails.issueIdentifiedDate' } },
@@ -436,6 +467,7 @@ export async function workHistory( req, res ) {
436
467
  $project: {
437
468
  storeId: 1,
438
469
  storeName: 1,
470
+ issueType: 1,
439
471
  clientId: 1,
440
472
  clientName: 1,
441
473
  issueDate: 1,
@@ -443,17 +475,25 @@ export async function workHistory( req, res ) {
443
475
  issueClosedDate: 1,
444
476
  ticketId: 1,
445
477
  issueStatus: 1,
478
+ status: 1,
446
479
  ticketType: 1,
447
480
  infraIssue: { $ifNull: [ '$primaryIssue.reasons.primaryIssue', '' ] },
448
481
  },
449
482
  } );
450
- if ( req.body.issueFilter && req.body.issueFilter.length>0 ) {
483
+ if ( req.body.issueFilter && req.body.issueFilter.length>0&&req.body.issueType!='dataMismatch' ) {
451
484
  query.push( {
452
485
  $match: {
453
486
  infraIssue: { $in: req.body.issueFilter },
454
487
  },
455
488
  } );
456
489
  }
490
+ if ( req.body.issueFilter && req.body.issueFilter.length>0&&req.body.issueType==='dataMismatch' ) {
491
+ query.push( {
492
+ $match: {
493
+ issueType: { $in: req.body.issueFilter },
494
+ },
495
+ } );
496
+ }
457
497
  if ( req.body.searchValue && req.body.searchValue !== '' ) {
458
498
  query.push( {
459
499
  $match: {
@@ -484,19 +524,25 @@ export async function workHistory( req, res ) {
484
524
  if ( req.body.export ) {
485
525
  const exportdata = [];
486
526
  result.forEach( ( element ) => {
487
- exportdata.push( {
527
+ let data ={
488
528
  'CREATED ON': dayjs( element.issueDate ).format( 'DD-MM-YYYY' ),
489
529
  'TICKET ID': element.ticketId,
490
530
  'STORE ID': element.storeId,
491
531
  'STORE NAME': element.storeName,
492
532
  'CLIENT ID': element.clientId,
493
533
  'CLIENT NAME': element.clientName,
494
- 'ISSUE IDENTIFIED DATE': element.issueIdentifiedDate,
495
534
  'CLOSED ON': element.issueClosedDate,
496
- 'ISSUE': element.infraIssue?element.infraIssue:'-',
497
535
  'STATUS': element.status,
498
- } );
536
+ };
537
+ if ( req.body.issueType==='infra'||req.body.issueType==='installation' ) {
538
+ data = { ...data, ...{ 'ISSUE': element.infraIssue?element.infraIssue:'-', 'ISSUE IDENTIFIED DATE': element.issueIdentifiedDate } };
539
+ }
540
+ if ( req.body.issueType==='dataMismatch' ) {
541
+ data = { ...data, ...{ 'issueType': element.issueType?element.issueType:'-' } };
542
+ }
543
+ exportdata.push( data );
499
544
  } );
545
+
500
546
  await download( exportdata, res );
501
547
  return;
502
548
  }
@@ -0,0 +1,28 @@
1
+ import j2s from 'joi-to-swagger';
2
+ import { getInfraIssueSchema } from '../dtos/infra.dtos.js';
3
+
4
+ export const infraDocs = {
5
+
6
+ '/v3/infra/get-infra-issues': {
7
+ post: {
8
+ tags: [ 'infra' ],
9
+ description: `Get infra issues against store`,
10
+ operationId: 'get-infra-issues',
11
+ parameters: {},
12
+ requestBody: {
13
+ content: {
14
+ 'application/json': {
15
+ schema: j2s( getInfraIssueSchema ).swagger,
16
+ },
17
+ },
18
+ },
19
+ responses: {
20
+ 200: { description: 'Group has been created successfully' },
21
+ 401: { description: 'Unauthorized User' },
22
+ 422: { description: 'Field Error' },
23
+ 500: { description: 'Server Error' },
24
+ 204: { description: 'Not Found' },
25
+ },
26
+ },
27
+ },
28
+ };
@@ -0,0 +1,12 @@
1
+ import Joi from 'joi';
2
+
3
+ export const getInfraIssueSchema = Joi.object().keys( {
4
+ fromDate: Joi.string().required(),
5
+ toDate: Joi.string().required(),
6
+ storeId: Joi.string().required(),
7
+
8
+ } );
9
+
10
+ export const getInfraIssueValid = {
11
+ body: getInfraIssueSchema,
12
+ };
@@ -1,10 +1,22 @@
1
1
  import express from 'express';
2
2
  import { isAllowedSessionHandler, authorize } from 'tango-app-api-middleware';
3
- import { createTicket } from '../controllers/dataMismatch.controller.js';
4
- import { validateDetails } from '../validations/infra.validation.js';
5
- export const dataMismatchRouter = express.Router();
3
+ import { createTicket, updateMat, activityList, showActivity } from '../controllers/dataMismatch.controller.js';
4
+ import { ticketExists, validateDetails } from '../validations/infra.validation.js';
5
+ export const dataMismatchTicketRouter = express.Router();
6
6
 
7
- dataMismatchRouter.post( '/createTicket', isAllowedSessionHandler, authorize( {
7
+ dataMismatchTicketRouter.post( '/createTicket', isAllowedSessionHandler, authorize( {
8
8
  userType: [ 'client', 'tango' ], access: [
9
9
  { featureName: 'manage', name: 'tickets', permissions: [ 'isView', 'isEdit' ] } ],
10
10
  } ), validateDetails, createTicket );
11
+ dataMismatchTicketRouter.post( '/updateMat', isAllowedSessionHandler, authorize( {
12
+ userType: [ 'client', 'tango' ], access: [
13
+ { featureName: 'manage', name: 'tickets', permissions: [ 'isView' ] } ],
14
+ } ), ticketExists, updateMat );
15
+ dataMismatchTicketRouter.post( '/activityList', isAllowedSessionHandler, authorize( {
16
+ userType: [ 'client', 'tango' ], access: [
17
+ { featureName: 'manage', name: 'tickets', permissions: [ 'isView' ] } ],
18
+ } ), activityList );
19
+ dataMismatchTicketRouter.post( '/showActivity', isAllowedSessionHandler, authorize( {
20
+ userType: [ 'client', 'tango' ], access: [
21
+ { featureName: 'manage', name: 'tickets', permissions: [ 'isView' ] } ],
22
+ } ), ticketExists, showActivity );
@@ -1,4 +1,4 @@
1
- import { createTicket, updatecomment, activityLog } from '../controllers/employeeTraning.controller.js';
1
+ import { createTicket, updatecomment, activityLog, updateMatStatus } from '../controllers/employeeTraning.controller.js';
2
2
  import { ticketExists, validateDetails } from '../validations/infra.validation.js';
3
3
  import express from 'express';
4
4
  import { isAllowedSessionHandler, authorize } from 'tango-app-api-middleware';
@@ -15,3 +15,7 @@ employeeTrainigRouter.post( '/activityLog', isAllowedSessionHandler, authorize(
15
15
  userType: [ 'tango' ], access: [
16
16
  { featureName: 'manage', name: 'tickets', permissions: [ 'isView' ] } ],
17
17
  } ), ticketExists, activityLog );
18
+ employeeTrainigRouter.post( '/updateMatStatus', isAllowedSessionHandler, authorize( {
19
+ userType: [ 'tango' ], access: [
20
+ { featureName: 'manage', name: 'tickets', permissions: [ 'isView' ] } ],
21
+ } ), ticketExists, updateMatStatus );
@@ -1,10 +1,11 @@
1
1
 
2
2
  import express from 'express';
3
- import { isAllowedSessionHandler, authorize } from 'tango-app-api-middleware';
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
5
  import { createTicket, bulkcreateTicket, updateStatus, createReason, PrimaryReasons, matTable,
6
- secondaryReason, updateTicketIssue, viewTicket, AlertTicketReply, uploadAttachments,
6
+ secondaryReason, updateTicketIssue, viewTicket, AlertTicketReply, uploadAttachments, getInfraIssues,
7
7
  updateInstallationTicket, emailUserList, saveInfraEmailConfig, invoice, infraTable, storeFilter, assignTicket, installationTable } from '../controllers/infra.controllers.js';
8
+ import { getInfraIssueValid } from '../dtos/infra.dtos.js';
8
9
 
9
10
 
10
11
  export const infraRouter = express.Router();
@@ -75,3 +76,8 @@ infraRouter.post( '/storeFilter', isAllowedSessionHandler, authorize( {
75
76
  userType: [ 'client', 'tango' ], access: [
76
77
  { featureName: 'manage', name: 'tickets', permissions: [ 'isView' ] } ],
77
78
  } ), storeFilter );
79
+ infraRouter.post( '/get-infra-issues', isAllowedSessionHandler, authorize( {
80
+ userType: [ 'client', 'tango' ], access: [
81
+ { featureName: 'manage', name: 'tickets', permissions: [ 'isView' ] } ],
82
+ } ), validate( getInfraIssueValid ), getInfraIssues );
83
+
@@ -0,0 +1,5 @@
1
+ import cameraModel from 'tango-api-schema/schema/camera.model.js';
2
+
3
+ export async function aggregateCamera( query ) {
4
+ return await cameraModel.aggregate( query );
5
+ }
@@ -9,11 +9,11 @@ export async function validateDetails( req, res, next ) {
9
9
  try {
10
10
  let store = await findOneStore( { storeId: req.body.storeId } );
11
11
  if ( !store ) {
12
- return res.sendError( 'Store Not Available' );
12
+ return res.sendError( 'Store Not Available', 500 );
13
13
  }
14
14
  let client = await findOneClient( { clientId: store.clientId } );
15
15
  if ( !client ) {
16
- return res.sendError( 'Client Not Available' );
16
+ return res.sendError( 'Client Not Available', 500 );
17
17
  }
18
18
 
19
19
  if ( store.spocDetails && store.spocDetails.length > 0 ) {
@@ -186,7 +186,7 @@ export async function ticketExists( req, res, next ) {
186
186
  req.body.ticketActivity = Ticket.ticketActivity;
187
187
  req.body.status = Ticket.status;
188
188
  req.body.issueDate = Ticket.issueDate;
189
-
189
+ req.body.dataMismatch = Ticket.dataMismatch;
190
190
 
191
191
  next();
192
192
  } catch ( error ) {
@@ -202,8 +202,6 @@ export async function validateTicketstatus( req, res, next ) {
202
202
  if ( req.body.status == 'closed' ) {
203
203
  return res.sendSuccess( 'Ticket already closed' );
204
204
  }
205
- console.log( req.body.ticketDetails );
206
-
207
205
  if ( req.body.ticketDetails.ticketType==='firsttimeticket'&&req.body.ticketDetails.issueStatus==='identified' ) {
208
206
  return res.sendSuccess( 'Ticket already Addressed' );
209
207
  }