tango-app-api-audit 3.4.68-beta.9 → 3.4.69-beta.0

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.
@@ -12,11 +12,14 @@ dayjs.extend( timezone );
12
12
  export async function getList( req, res ) {
13
13
  try {
14
14
  const inputData = req.body;
15
+ if ( inputData.clientId !== '11' ) {
16
+ return res.sendError( 'No data found', 204 );
17
+ }
15
18
  const openSearch = JSON.parse( process.env.OPENSEARCH );
16
19
  const limit = inputData.limit || 10;
17
20
  const offset = inputData.offset ? ( inputData.offset - 1 ) * limit : 0;
18
21
 
19
- const sortBy = inputData?.sortBy ? `${inputData.sortBy}.keyword` : 'storeName.keyword';
22
+ const sortBy = inputData?.sortBy ? inputData.sortBy === 'coveredStepsAI'||inputData.sortBy==='updatedAt' ? inputData.sortBy :`${inputData.sortBy}.keyword` : 'storeName.keyword';
20
23
  const order = inputData?.sortOrder || -1;
21
24
  let filter= [
22
25
  {
@@ -31,13 +34,13 @@ export async function getList( req, res ) {
31
34
  ];
32
35
 
33
36
 
34
- // if ( inputData.demographics && inputData.demographics.length > 0 ) {
35
- // filter.push( {
36
- // 'terms': {
37
- // 'visitorsType.keyword': inputData.demographics,
38
- // },
39
- // } );
40
- // }
37
+ if ( inputData.demographics && inputData.demographics.length > 0 ) {
38
+ filter.push( {
39
+ 'terms': {
40
+ 'visitorsType.keyword': inputData.demographics,
41
+ },
42
+ } );
43
+ }
41
44
  if ( inputData.type && inputData.type!='' ) {
42
45
  filter.push( {
43
46
  'term': {
@@ -54,67 +57,108 @@ export async function getList( req, res ) {
54
57
  },
55
58
 
56
59
  } );
60
+ } else {
61
+ return res.sendError( 'No data found', 204 );
57
62
  }
58
63
  let search ={
59
64
  'must': filter,
60
65
  };
61
66
 
62
67
  if ( inputData.searchValue && inputData.searchValue !== '' ) {
63
- search ={
64
- 'must': filter,
65
- 'should': [
66
- {
67
- 'wildcard': {
68
- 'storeName.keyword': {
69
- 'value': `*${inputData.searchValue}*`,
68
+ if ( inputData.type&&inputData.type==='remote' ) {
69
+ search ={
70
+ 'must': filter,
71
+ 'should': [
72
+ {
73
+ 'wildcard': {
74
+ 'storeName.keyword': {
75
+ 'value': `*${inputData.searchValue}*`,
76
+ },
70
77
  },
71
78
  },
72
- },
73
- {
74
- 'wildcard': {
75
- 'storeId.keyword': {
76
- 'value': `*${inputData.searchValue}*`,
79
+ {
80
+ 'wildcard': {
81
+ 'storeId.keyword': {
82
+ 'value': `*${inputData.searchValue}*`,
83
+ },
77
84
  },
78
85
  },
79
- },
80
- {
81
- 'wildcard': {
82
- 'engagementId.keyword': {
83
- 'value': `*${inputData.searchValue}*`,
86
+ {
87
+ 'wildcard': {
88
+ 'engagementId.keyword': {
89
+ 'value': `*${inputData.searchValue}*`,
90
+ },
84
91
  },
85
92
  },
86
- },
87
- {
88
- 'wildcard': {
89
- 'queueId.keyword': {
90
- 'value': `*${inputData.searchValue}*`,
93
+
94
+ {
95
+ 'wildcard': {
96
+ 'auditStatus.keyword': {
97
+ 'value': `*${inputData.searchValue}*`,
98
+ },
91
99
  },
92
100
  },
93
- },
94
- {
95
- 'wildcard': {
96
- 'optumId.keyword': {
97
- 'value': `*${inputData.engagementId}*`,
101
+ ],
102
+ 'minimum_should_match': 1,
103
+ };
104
+ } else {
105
+ search ={
106
+ 'must': filter,
107
+ 'should': [
108
+ {
109
+ 'wildcard': {
110
+ 'storeName.keyword': {
111
+ 'value': `*${inputData.searchValue}*`,
112
+ },
98
113
  },
99
114
  },
100
- },
101
- {
102
- 'wildcard': {
103
- 'visitorsType.keyword': {
104
- 'value': `*${inputData.searchValue}*`,
115
+ {
116
+ 'wildcard': {
117
+ 'storeId.keyword': {
118
+ 'value': `*${inputData.searchValue}*`,
119
+ },
105
120
  },
106
121
  },
107
- },
108
- {
109
- 'wildcard': {
110
- 'auditStatus.keyword': {
111
- 'value': `*${inputData.searchValue}*`,
122
+ {
123
+ 'wildcard': {
124
+ 'engagementId.keyword': {
125
+ 'value': `*${inputData.searchValue}*`,
126
+ },
112
127
  },
113
128
  },
114
- },
115
- ],
116
- 'minimum_should_match': 1,
117
- };
129
+ {
130
+ 'wildcard': {
131
+ 'queueId.keyword': {
132
+ 'value': `*${inputData.searchValue}*`,
133
+ },
134
+ },
135
+ },
136
+ {
137
+ 'wildcard': {
138
+ 'optumId.keyword': {
139
+ 'value': `*${inputData.searchValue}*`,
140
+ },
141
+ },
142
+ },
143
+ {
144
+ 'wildcard': {
145
+ 'visitorsType.keyword': {
146
+ 'value': `*${inputData.searchValue}*`,
147
+ },
148
+ },
149
+ },
150
+
151
+ {
152
+ 'wildcard': {
153
+ 'auditStatus.keyword': {
154
+ 'value': `*${inputData.searchValue}*`,
155
+ },
156
+ },
157
+ },
158
+ ],
159
+ 'minimum_should_match': 1,
160
+ };
161
+ }
118
162
  }
119
163
  let searchQuery={
120
164
  'from': offset,
@@ -171,16 +215,19 @@ export async function getList( req, res ) {
171
215
  const minutes1 =minutes> 1? `${minutes} mins` : `${minutes} min`;
172
216
  const seconds1 = seconds > 1? `${minutes} secs`: seconds == 1? `${minutes} sec` : '';
173
217
  const duration =`${minutes1} ${seconds1}`;
174
- const userName = await findOneUser( { _id: element?._source?.userId }, { _id: 0, userName: 1 } );
218
+ let userName = '';
219
+ if ( element?._source?.userId&&element?._source?.userId!='' ) {
220
+ userName = await findOneUser( { _id: element?._source?.userId }, { _id: 0, userName: 1 } );
221
+ }
175
222
  if ( element?._source?.type == 'physical' ) {
176
223
  exportData.push( {
177
- 'Date': dayjs( element?._source?.date ).format( 'YYYY,MMM D' ),
224
+ 'Date': dayjs( element?._source?.date ).format( 'D MMM, YYYY' ),
178
225
  'Store Name': element?._source?.storeName,
179
226
  'Store ID': element?._source?.storeId || 'Un Assigned',
180
227
  'Store Name': element?._source?.storeName ||'Un Assigned',
181
228
  'Optum ID': element?._source?.optumId,
182
229
  'Queue ID': element?._source?.queueId,
183
- 'Compliance Score': element?._source?.complianceScore || 0,
230
+ 'Compliance Score': element?._source?.totalSteps>0 ? Math.round( ( element?._source?.coveredStepsAI/ element?._source?.totalSteps )*100 ): 0,
184
231
  'Steps Covered By AI': element?._source?.coveredStepsAI || 0,
185
232
  'Visitor Type': element?._source?.visitorsType,
186
233
  'Test Duration': duration || '',
@@ -190,14 +237,13 @@ export async function getList( req, res ) {
190
237
  } );
191
238
  } else {
192
239
  exportData.push( {
193
- 'Date': dayjs( element?._source?.date ).format( 'YYYY,MMM D' ),
240
+ 'Date': dayjs( element?._source?.date ).format( 'D MMM, YYYY' ),
194
241
  'Store Name': element?._source?.storeName,
195
242
  'Store ID': element?._source?.storeId || 'Un Assigned',
196
243
  'Store Name': element?._source?.storeName ||'Un Assigned',
197
244
  'Engagement ID': element?._source?.engagementId,
198
245
  'Compliance Score': element?._source?.complianceScore || 0,
199
246
  'Steps Covered By AI': element?._source?.coveredStepsAI || 0,
200
- 'Visitor Type': element?._source?.visitorsType,
201
247
  'Test Duration': duration || '',
202
248
  'Audit Status': element?._source?.auditStatus || '',
203
249
  'Audited By': userName?.userName || '',
@@ -213,14 +259,18 @@ export async function getList( req, res ) {
213
259
  return;
214
260
  } else {
215
261
  for ( const [ i, item ] of searchValue.entries() ) {
216
- const userName = await findOneUser( { _id: item?._source?.userId }, { _id: 0, userName: 1 } );
262
+ let userName='';
263
+ if ( item?._source?.userId&&item?._source?.userId!='' ) {
264
+ userName = await findOneUser( { _id: item?._source?.userId }, { _id: 0, userName: 1 } );
265
+ }
217
266
  const testDuration = searchValue[i]?._source?.testDuration;
218
267
  const minutes = Math.floor( testDuration / 60 );
219
268
  const seconds = testDuration % 60;
220
-
269
+ searchValue[i]._source.complianceScore = searchValue[i]?._source?.totalSteps>0 ? Math.round( ( searchValue[i]?._source?.coveredStepsAI/ searchValue[i]?._source?.totalSteps )*100 ): 0;
221
270
  searchValue[i]._source.min = minutes;
222
271
  searchValue[i]._source.sec = seconds;
223
272
  searchValue[i]._source.auditedBy = userName?.userName || '';
273
+ searchValue[i]._source.date = dayjs( searchValue[i]?._source?.date ).format( 'D MMM, YYYY' );
224
274
  }
225
275
  }
226
276
 
@@ -257,7 +307,11 @@ export async function viewFile( req, res ) {
257
307
  'term': {
258
308
  'type.keyword': getData?.type,
259
309
  },
260
-
310
+ },
311
+ {
312
+ 'terms': {
313
+ 'auditStatus.keyword': [ 'Audited', 'Re-Audited' ],
314
+ },
261
315
  },
262
316
  ];
263
317
  if ( getData?.type == 'remote' ) {
@@ -272,7 +326,11 @@ export async function viewFile( req, res ) {
272
326
  'term': {
273
327
  'type.keyword': getData?.type,
274
328
  },
275
-
329
+ },
330
+ {
331
+ 'terms': {
332
+ 'auditStatus.keyword': [ 'Audited', 'Re-Audited' ],
333
+ },
276
334
  },
277
335
  ];
278
336
  }
@@ -290,6 +348,7 @@ export async function viewFile( req, res ) {
290
348
  };
291
349
 
292
350
  const searchRes= await getOpenSearchData( openSearch.EyeTestOutput, searchQuery );
351
+
293
352
  const temp = searchRes?.body?.hits?.hits?.length > 0? searchRes?.body?.hits?.hits[0] : [];
294
353
 
295
354
  const getUserName = await findOneUser( { _id: new mongoose.Types.ObjectId( temp?._source?.userId ) }, { userName: 1 } );
@@ -321,7 +380,9 @@ export async function viewFile( req, res ) {
321
380
  break;
322
381
  case 'Audited':
323
382
  response['steps']= temp._source?.steps;
383
+ isEnable=true;
324
384
  case 'Re-Audited':
385
+ response['steps']= temp._source?.steps;
325
386
  isEnable=true;
326
387
  }
327
388
 
@@ -432,7 +493,7 @@ export async function getFile( req, res ) {
432
493
  if ( !searchData ) {
433
494
  const data1 = await insertOpenSearchData( openSearch.EyeTestOutput, record );
434
495
  logger.info( { data1: data1 } );
435
- await updateOpenSearchData( openSearch.EyeTestInput, inputData.id, { doc: { auditStatus: 'In-Progress', auditType: 'Audit', userId: req?.user?._id } } );
496
+ await updateOpenSearchData( openSearch.EyeTestInput, inputData.id, { doc: { 'auditStatus': 'In-Progress', 'auditType': 'Audit', 'userId': req?.user?._id, 'updatedAt': dayjs().tz( 'Asia/Kolkata' ) } } );
436
497
  }
437
498
 
438
499
  break;
@@ -480,7 +541,7 @@ export async function getFile( req, res ) {
480
541
 
481
542
  };
482
543
  await insertOpenSearchData( openSearch.EyeTestOutput, newRecord );
483
- await updateOpenSearchData( openSearch.EyeTestInput, inputData.id, { doc: { auditStatus: 'In-Progress', auditType: 'Re-Audit' } } );
544
+ await updateOpenSearchData( openSearch.EyeTestInput, inputData.id, { doc: { auditStatus: 'In-Progress', auditType: 'Re-Audit', userId: req?.user?._id } } );
484
545
 
485
546
  break;
486
547
  default:
@@ -512,7 +573,11 @@ export async function save( req, res ) {
512
573
  },
513
574
 
514
575
  },
515
-
576
+ {
577
+ 'term': {
578
+ 'userId.keyword': req?.user?._id,
579
+ },
580
+ },
516
581
  {
517
582
  'term': {
518
583
  'auditStatus.keyword': 'In-Progress',
@@ -558,26 +623,27 @@ export async function save( req, res ) {
558
623
  logger.info( { getOutput: getOutput } );
559
624
  const output = getOutput?.body?.hits?.hits?.length > 0 ? getOutput?.body?.hits?.hits[0] : null;
560
625
  if ( !output ) {
561
- return res.sendError( 'No saved records found', 400 );
626
+ return res.sendError( 'This file is currently being audited by another user. Any actions you perform will not be saved.', 400 );
562
627
  }
563
628
  const record ={
564
- steps: inputData?.steps,
565
- auditStatus: inputData?.auditStatus,
566
- auditedSteps: inputData?.auditedSteps,
567
- overRides: inputData?.overRides,
568
- trustScore: Math.round( 100-( ( inputData?.overRides / inputData?.steps?.length ) * 100 ) ),
569
- spokenLanguage: inputData?.spokenLanguage,
570
- endTime: dayjs().tz( 'Asia/Kolkata' ),
571
-
629
+ 'steps': inputData?.steps,
630
+ 'auditStatus': inputData?.auditStatus,
631
+ 'auditedSteps': inputData?.auditedSteps,
632
+ 'overRides': inputData?.overRides,
633
+ 'trustScore': Math.round( 100-( ( inputData?.overRides / inputData?.steps?.length ) * 100 ) ),
634
+ 'spokenLanguage': inputData?.spokenLanguage,
635
+ 'endTime': dayjs().tz( 'Asia/Kolkata' ),
636
+ 'updatedAt': dayjs().tz( 'Asia/Kolkata' ),
572
637
  };
573
638
  const inputrecord ={
574
639
 
575
- auditStatus: inputData?.auditStatus,
576
- auditedSteps: inputData?.auditedSteps,
577
- overRides: inputData?.overRides,
578
- trustScore: Math.round( 100-( ( inputData?.overRides / inputData?.steps?.length ) * 100 ) ),
579
- spokenLanguage: inputData?.spokenLanguage,
580
- endTime: dayjs().tz( 'Asia/Kolkata' ),
640
+ 'auditStatus': inputData?.auditStatus,
641
+ 'auditedSteps': inputData?.auditedSteps,
642
+ 'overRides': inputData?.overRides,
643
+ 'trustScore': Math.round( 100-( ( inputData?.overRides / inputData?.steps?.length ) * 100 ) ),
644
+ 'spokenLanguage': inputData?.spokenLanguage,
645
+ 'endTime': dayjs().tz( 'Asia/Kolkata' ),
646
+ 'updatedAt': dayjs().tz( 'Asia/Kolkata' ),
581
647
 
582
648
  };
583
649
  await updateOpenSearchData( openSearch.EyeTestOutput, output?._id, { doc: record } );
@@ -594,7 +660,20 @@ export async function cancel( req, res ) {
594
660
  try {
595
661
  const inputData = req.body;
596
662
  const openSearch = JSON.parse( process.env.OPENSEARCH );
663
+ let searchFilterhistory=[
664
+ {
665
+ 'term': {
666
+ 'queueId.keyword': inputData?.fileId,
667
+ },
668
+
669
+ },
670
+ {
671
+ 'term': {
672
+ 'type.keyword': inputData?.type,
673
+ },
597
674
 
675
+ },
676
+ ];
598
677
  let searchFilter =[
599
678
  {
600
679
  'term': {
@@ -608,7 +687,11 @@ export async function cancel( req, res ) {
608
687
  },
609
688
 
610
689
  },
611
-
690
+ {
691
+ 'term': {
692
+ 'userId.keyword': req?.user?._id,
693
+ },
694
+ },
612
695
  {
613
696
  'term': {
614
697
  'auditStatus.keyword': 'In-Progress',
@@ -640,6 +723,20 @@ export async function cancel( req, res ) {
640
723
  },
641
724
  },
642
725
  ];
726
+ searchFilterhistory=[
727
+ {
728
+ 'term': {
729
+ 'engagementId.keyword': inputData?.fileId,
730
+ },
731
+
732
+ },
733
+ {
734
+ 'term': {
735
+ 'type.keyword': inputData?.type,
736
+ },
737
+
738
+ },
739
+ ];
643
740
  }
644
741
 
645
742
  let searchQuery={
@@ -650,23 +747,38 @@ export async function cancel( req, res ) {
650
747
  },
651
748
  },
652
749
  };
750
+ let searchQueryHistory={
751
+ 'size': 100,
752
+ 'query': {
753
+ 'bool': {
754
+ 'must': searchFilterhistory,
755
+ },
756
+ },
757
+ };
653
758
  const getOutput = await getOpenSearchData( openSearch.EyeTestOutput, searchQuery );
759
+ const getOutputHistory = await getOpenSearchData( openSearch.EyeTestOutput, searchQueryHistory );
654
760
  logger.info( { getOutput: getOutput } );
655
761
  const output = getOutput?.body?.hits?.hits?.length > 0 ? getOutput?.body?.hits?.hits[0] : null;
762
+ let checkReaudited = getOutput?.body?.hits?.hits?.length > 0 ? getOutputHistory?.body?.hits?.hits.filter( ( data ) => data._source.auditType==='Re-Audit'&&data._source.auditStatus==='Re-Audited' ).length:0;
763
+ let checkReauditedData = getOutput?.body?.hits?.hits?.length > 0 ? getOutputHistory?.body?.hits?.hits.filter( ( data ) => data._source.auditType==='Re-Audit'&&data._source.auditStatus==='Re-Audited' ):[];
764
+ let checkaudited = getOutput?.body?.hits?.hits?.length > 0 ? getOutputHistory?.body?.hits?.hits.filter( ( data ) => data._source.auditType==='Audit'&&data._source.auditStatus==='Audited' ).length:0;
765
+ let checkauditedData = getOutput?.body?.hits?.hits?.length > 0 ? getOutputHistory?.body?.hits?.hits.filter( ( data ) => data._source.auditType==='Audit'&&data._source.auditStatus==='Audited' ):[];
766
+
656
767
  if ( !output ) {
657
768
  return res.sendError( 'No saved records found', 400 );
658
769
  }
659
770
  const record1 ={
660
771
 
661
772
  auditStatus: 'Skipped',
773
+ auditType: checkReaudited>0?'Re-Audit':'Audit',
662
774
  endTime: dayjs().tz( 'Asia/Kolkata' ),
663
775
 
664
776
  };
665
777
  const record2 ={
666
-
667
- auditStatus: 'Yet-to-Audit',
778
+ auditStatus: checkReaudited>0?'Re-Audited':checkaudited>0?'Audited':'Yet-to-Audit',
779
+ auditType: checkReaudited>0?'Re-Audit':'Audit',
668
780
  endTime: dayjs().tz( 'Asia/Kolkata' ),
669
-
781
+ userId: checkaudited>0?checkauditedData[0]?._source?.userId:checkReaudited>0?checkReauditedData[0]?._source?.userId:'',
670
782
  };
671
783
  await updateOpenSearchData( openSearch.EyeTestOutput, output?._id, { doc: record1 } );
672
784
  await updateOpenSearchData( openSearch.EyeTestInput, inputData.id, { doc: record2 } );
@@ -702,6 +814,9 @@ export async function getFileHistory( req, res ) {
702
814
  ],
703
815
  },
704
816
  },
817
+ 'sort': [
818
+ { updatedAt: { order: 'desc' } },
819
+ ],
705
820
  };
706
821
  } else {
707
822
  Query = {
@@ -722,6 +837,9 @@ export async function getFileHistory( req, res ) {
722
837
  ],
723
838
  },
724
839
  },
840
+ 'sort': [
841
+ { updatedAt: { order: 'desc' } },
842
+ ],
725
843
  };
726
844
  };
727
845
 
@@ -730,7 +848,6 @@ export async function getFileHistory( req, res ) {
730
848
  let sourcesArray = resposnse.body.hits.hits.map( ( hit ) => hit );
731
849
  let outputData=[];
732
850
  for ( let data of sourcesArray ) {
733
- // console.log( data._source.endTime );
734
851
  let findUser= await findOneUser( { _id: new mongoose.Types.ObjectId( data._source.userId ) } );
735
852
  outputData.push( {
736
853
  _id: data._id,
@@ -2,10 +2,23 @@ import joi from 'joi';
2
2
 
3
3
  export const getListSchema = joi.object(
4
4
  {
5
- fromDate: joi.string().required(),
6
- toDate: joi.string().required(),
7
- type: joi.string().required(),
5
+ fromDate: joi.string().required().messages( {
6
+ 'any.required': 'From Date is required',
7
+ 'string.empty': 'From Date cannot be empty',
8
+ } ),
9
+ toDate: joi.string().required().messages( {
10
+ 'any.required': 'To Date is required',
11
+ 'string.empty': 'To Date cannot be empty',
12
+ } ),
13
+ type: joi.string().required().messages( {
14
+ 'any.required': 'Type is required',
15
+ 'string.empty': 'Type cannot be empty',
16
+ } ),
8
17
  demographics: joi.array().optional(),
18
+ clientId: joi.string().required().messages( {
19
+ 'any.required': 'Client ID is required',
20
+ 'string.empty': 'Client ID cannot be empty',
21
+ } ),
9
22
  storeId: joi.array().optional(),
10
23
  limit: joi.number().optional(),
11
24
  offset: joi.number().optional(),