tango-app-api-audit 3.3.2 → 3.4.0-alpha.1

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
@@ -1,8 +1,10 @@
1
1
 
2
2
 
3
3
  import { auditRouter } from './src/routes/audit.routes.js';
4
+ import { traxAuditRouter } from './src/routes/traxAudit.routes.js';
4
5
  import { auditDocs } from './src/docs/audit.docs.js';
6
+ import { traxAuditDocs } from './src/docs/traxAudit.docs.js';
5
7
 
6
- export { auditRouter, auditDocs };
8
+ export { auditRouter, auditDocs, traxAuditRouter, traxAuditDocs };
7
9
 
8
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tango-app-api-audit",
3
- "version": "3.3.2",
3
+ "version": "3.4.0-alpha.1",
4
4
  "description": "audit & audit metrics apis",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -24,7 +24,7 @@
24
24
  "mongodb": "^6.7.0",
25
25
  "nodemon": "^3.1.3",
26
26
  "swagger-ui-express": "^5.0.1",
27
- "tango-api-schema": "^2.0.159",
27
+ "tango-api-schema": "^2.1.5",
28
28
  "tango-app-api-middleware": "^3.1.33",
29
29
  "winston": "^3.13.0",
30
30
  "winston-daily-rotate-file": "^5.0.0"
@@ -0,0 +1,737 @@
1
+ import { checkFileExist, getDate, insertOpenSearchData, listFileByPath, logger, signedUrl, sqsReceive } from 'tango-app-api-middleware';
2
+ import { aggregateBinaryAuditModel, createBinaryAudit } from '../service/binaryAudit.service.js';
3
+ import { findOneStore } from '../service/store.service.js';
4
+ import { findOneUser } from '../service/user.service.js';
5
+
6
+
7
+ export async function getDetectionAuditFile( req, res ) {
8
+ try {
9
+ const bucket = JSON.parse( process.env.BUCKET );
10
+ const openSearch = JSON.parse( process.env.OPENSEARCH );
11
+ const inputData = req.query;
12
+ const data = await getDate( new Date(), new Date() );
13
+ logger.info( { data: data, function: 'data', newDate: new Date() } );
14
+ logger.info( { userId: req.user._id, queueName: inputData.queueName, moduleType: inputData.moduleType } );
15
+ const start = data.start;
16
+ const end = data.end;
17
+ const fetchData = {};
18
+ let msg = {};
19
+ const userQuery = [
20
+ {
21
+ $match: {
22
+ $and: [
23
+ { userId: req.user._id },
24
+ { queueName: inputData.queueName },
25
+ { auditStatus: { $nin: [ 'completed', 'skipped' ] } },
26
+ { createdAt: { $gte: start } },
27
+ { createdAt: { $lte: end } },
28
+ { moduleType: inputData.moduleType },
29
+ ],
30
+ },
31
+ },
32
+ {
33
+ $sort: { createdAt: -1 },
34
+ },
35
+ {
36
+ $limit: 1,
37
+ },
38
+ ];
39
+
40
+ const userDetails = await aggregateUserAudit( userQuery );
41
+ logger.info( { userDetails: userDetails, function: 'userDetails' } );
42
+ const auditStatus =
43
+ userDetails && userDetails.length > 0 ? userDetails[0].auditStatus : null;
44
+ switch ( auditStatus ) {
45
+ case null:
46
+ const query = [
47
+ {
48
+ $match: {
49
+ $and: [
50
+ { userId: { $eq: req.user._id } },
51
+ { isCompleted: { $eq: false } },
52
+ { queueName: inputData.queueName },
53
+ { moduleType: inputData.moduleType },
54
+ ],
55
+ },
56
+ },
57
+ ];
58
+ const userAssign = await aggregateAssignAudit( query );
59
+ if ( userAssign.length > 0 ) {
60
+ logger.info( 'Hit in user assign', { inputData } );
61
+ userAssign[0].auditType == 'Audit' ?
62
+ ( msg = {
63
+ store_id: userAssign[0].storeId,
64
+ curr_date: userAssign[0].fileDate,
65
+ total_count: userAssign[0].fileCount,
66
+ zone_id: userAssign[0].zoneName,
67
+ } ) :
68
+ ( msg = {
69
+ store_id: userAssign[0].storeId,
70
+ curr_date: userAssign[0].fileDate,
71
+ audit_type: userAssign[0].auditType,
72
+ total_count: userAssign[0].fileCount,
73
+ zone_id: userAssign[0].zoneName,
74
+ } );
75
+ await updateOneAssignAudit(
76
+ { _id: userAssign[0]._id },
77
+ { isCompleted: true },
78
+ );
79
+ logger.info( 'Hit in auditUserAssignModel updateOne', {
80
+ _id: userAssign[0]._id,
81
+ isCompleted: true,
82
+ } );
83
+ } else {
84
+ logger.info( 'Hit in new file', { inputData } );
85
+ const consumer = await sqsReceive( inputData.queueName );
86
+ if ( !consumer ) {
87
+ logger.error( {
88
+ error: consumer,
89
+ function: 'getAuditFile',
90
+ message: 'SQS Receive queue is empty',
91
+ } );
92
+ return res.sendError( `${inputData.queueName} is Empty`, 204 );
93
+ }
94
+ msg = JSON.parse( consumer );
95
+ }
96
+ break;
97
+
98
+ case 'drafted':
99
+ logger.info( 'userDetails drafted', { inputData } );
100
+ const log = await findOneAuditLog(
101
+ {
102
+ userId: userDetails[0].userId,
103
+ fileDate: userDetails[0].fileDate,
104
+ storeId: userDetails[0].storeId,
105
+ totalCount: userDetails[0].beforeCount,
106
+ moduleType: userDetails[0].moduleType,
107
+ zoneName: userDetails[0].zoneName,
108
+ },
109
+ {},
110
+ { createdAt: -1 },
111
+ );
112
+ if ( !log ) {
113
+ await updateOneUserAudit(
114
+ { _id: userDetails[0]._id },
115
+ { $set: { isDraft: false, auditStatus: 'skipped' } },
116
+ );
117
+ logger.info( 'audit update in drafted', {
118
+ _id: userDetails[0]._id,
119
+ isDraft: false,
120
+ auditStatus: 'skipped',
121
+ } );
122
+ return res.sendError( 'User saved data has been deleted', 204 );
123
+ }
124
+ const file = {
125
+ auditId: userDetails[0]._id,
126
+ store_id: userDetails[0].storeId,
127
+ file_date: userDetails[0].fileDate,
128
+ type: userDetails[0].auditType,
129
+ queueName: log.queueName,
130
+ userId: log.userId,
131
+ moduleType: userDetails[0].moduleType,
132
+ zoneName: userDetails[0].zoneName,
133
+ };
134
+ const result = {
135
+ junk: log.junk,
136
+ junk_count: log.junkCount,
137
+ employee: log.employee,
138
+ employee_count: log.employeeCount,
139
+ customer: log.customer,
140
+ customer_count: log.customerCount,
141
+ retag_image: log.retagImage,
142
+ retag_count: log.retagCount,
143
+ total_count: log.totalCount,
144
+ };
145
+
146
+ const userdata = await findOneUser( { _id: log.userId } );
147
+ if (
148
+ !inputData.nextId ||
149
+ inputData.nextId === '' ||
150
+ inputData.nextId == null
151
+ ) {
152
+ const logData = {
153
+ userId: log.userId,
154
+ userName: userdata.name,
155
+ logType: 'audit',
156
+ logSubType: 'auditStart',
157
+ logData: {
158
+ fileDate: userDetails[0].fileDate,
159
+ auditType: userDetails[0].auditType,
160
+ storeId: userDetails[0].storeId,
161
+ clientName: log.queueName,
162
+ auditId: userDetails[0]._id,
163
+ moduleType: userDetails[0].moduleType,
164
+ zoneName: userDetails[0].zoneName,
165
+ },
166
+ createdAt: new Date(),
167
+ };
168
+ logger.info( { logData: logData } );
169
+ await insertOpenSearchData( openSearch.auditLog, logData );
170
+ }
171
+ const storeQuery = {
172
+ storeId: userDetails[0].storeId,
173
+ };
174
+ const storeFields = {
175
+ storeId: 1,
176
+ storeName: 1,
177
+ address: '$storeProfile.address',
178
+ };
179
+ const storeDetails = await findOneStore( storeQuery, storeFields );
180
+ res.sendSuccess( {
181
+ result: result,
182
+ storeId: storeDetails?.storeId,
183
+ storeName: storeDetails?.storeName,
184
+ address: storeDetails?.address || '',
185
+ count: log.totalCount,
186
+ file: file,
187
+ isDraft: userDetails[0].isDraft,
188
+ } );
189
+ break;
190
+
191
+ default:
192
+ msg = {
193
+ store_id: userDetails[0].storeId,
194
+ curr_date: userDetails[0].fileDate,
195
+ audit_type: userDetails[0].auditType,
196
+ total_count: userDetails[0].beforeCount,
197
+ zone_id: userDetails[0].zoneName,
198
+ };
199
+ break;
200
+ }
201
+ if ( msg.audit_type === 'ReAudit' ) {
202
+ logger.info( 'Hit in user ReAudit', { inputData } );
203
+ let reauditInsert = {};
204
+ const [ filterData, auditImage ] = await Promise.all( [
205
+ getFilterData( msg ),
206
+ getAuditImage( msg ),
207
+ ] );
208
+ if ( filterData.statusCode == 404 || auditImage.statusCode == 404 ) {
209
+ return res.sendError( 'No Data found', 204 );
210
+ }
211
+ const reauditImg = await getReauditImg( filterData, auditImage );
212
+ if ( userDetails.length === 0 ) {
213
+ const [ day, month, year ] = msg.curr_date.split( '-' );
214
+ const temp = `${year}-${month}-${day}`;
215
+ let start = new Date( temp );
216
+ const userTimezoneOffset = start.getTimezoneOffset() * 60000;
217
+ start = new Date( start.getTime() - userTimezoneOffset );
218
+ start.setUTCHours( 0, 0, 0, 0 );
219
+ const record = {
220
+ userId: req.user._id,
221
+ storeId: msg.store_id,
222
+ clientId: msg.store_id.split( '-' )[0],
223
+ auditType: msg.audit_type || 'ReAudit',
224
+ fileDate: msg.curr_date,
225
+ queueName: inputData.queueName,
226
+ beforeCount: reauditImg.length,
227
+ auditStatus: 'inprogress',
228
+ fileDateISO: start,
229
+ timeSpent: 0,
230
+ startTime: new Date(),
231
+ zoneName: msg.zone_id,
232
+ moduleType: inputData.moduleType,
233
+ };
234
+ const query ={
235
+ storeId: msg.store_id,
236
+ zoneName: msg.zone_id,
237
+ fileDate: msg.curr_date,
238
+ moduleType: inputData.moduleType,
239
+ };
240
+ let storeRecord = {
241
+ userId: req.user._id,
242
+ auditType: msg.audit_type || 'ReAudit',
243
+ status: 'inprogress',
244
+ timeSpent: 0,
245
+ };
246
+ reauditInsert = await createUserAudit( record );
247
+
248
+ await updateOneStoreAudit( query, storeRecord );
249
+ } else {
250
+ reauditInsert = userDetails[0];
251
+ }
252
+ const userdata = await findOneUser( { _id: req.user._id } );
253
+ if ( inputData.nextId ) {
254
+ const logData = {
255
+ userId: req.user._id,
256
+ userName: userdata.name,
257
+ logType: 'audit',
258
+ logSubType: 'auditStart',
259
+ logData: {
260
+ fileDate: msg.curr_date,
261
+ auditType: msg.audit_type,
262
+ storeId: msg.store_id,
263
+ clientName: inputData.queueName,
264
+ auditId: reauditInsert._id,
265
+ zoneName: msg.zone_id,
266
+ moduleType: inputData.moduleType,
267
+ },
268
+ createdAt: new Date(),
269
+ };
270
+ await insertOpenSearchData( openSearch.auditLog, logData );
271
+ }
272
+
273
+ const storeQuery = {
274
+ storeId: msg.store_id,
275
+ };
276
+ const storeFields = {
277
+ storeId: 1,
278
+ storeName: 1,
279
+ address: '$storeProfile.address',
280
+ };
281
+ const storeInfo = await findOneStore( storeQuery, storeFields );
282
+ return res.sendSuccess( {
283
+ result: reauditImg,
284
+ count: reauditImg.length,
285
+ storeId: storeInfo?.storeId,
286
+ storeName: storeInfo?.storeName,
287
+ address: storeInfo?.address || '',
288
+ file: {
289
+ store_id: msg.store_id,
290
+ file_date: msg.curr_date,
291
+ type: msg.audit_type || 'ReAudit',
292
+ queueName: inputData.queueName,
293
+ auditId: reauditInsert._id,
294
+ userId: reauditInsert.userId,
295
+ zoneName: msg.zone_id,
296
+ moduleType: inputData.moduleType,
297
+ },
298
+ isDraft: reauditInsert.isDraft,
299
+ } );
300
+ }
301
+ const storeId = msg.store_id;
302
+ const fileDate = msg.curr_date;
303
+
304
+ const files = [];
305
+ let insertData = {};
306
+ fetchData.Bucket = bucket.auditInput; // need to change
307
+ fetchData.file_path = `${fileDate}/${storeId}/${msg.zone_id}/`;
308
+ if ( inputData.limit ) {
309
+ fetchData.MaxKeys = inputData.limit;
310
+ }
311
+ if ( inputData.nextId ) {
312
+ fetchData.ContinuationToken = decodeURIComponent( inputData.nextId );
313
+ }
314
+ const list = await listFileByPath( fetchData );
315
+ const folderPath = list.data;
316
+ const nextQuery = list.pageToken;
317
+ if ( folderPath?.length > 0 ) {
318
+ for ( let i = 0; i < folderPath.length; i++ ) {
319
+ const img = folderPath[i].Key.split( '/' );
320
+ const image = img[3].split( '.' );
321
+ const indexes = image[0].split( '_' );
322
+ fetchData.file_path = folderPath[i].Key;
323
+ const data = await signedUrl( fetchData );
324
+ const mapimg = {
325
+ img_path: data,
326
+ img_name: indexes[1],
327
+ img_id: image[0],
328
+ };
329
+ files.push( {
330
+ img_path: data,
331
+ img_name: indexes[1],
332
+ img_id: image[0],
333
+ selected: false,
334
+ dropped: false,
335
+ count: 1,
336
+ mappedid: [ mapimg ],
337
+ } );
338
+ }
339
+ if ( userDetails.length === 0 ) {
340
+ const [ day, month, year ] = msg.curr_date.split( '-' );
341
+ const temp = `${year}-${month}-${day}`;
342
+ let start = new Date( temp );
343
+ logger.info( { start: start, date: msg.curr_date } );
344
+ const userTimezoneOffset = start.getTimezoneOffset() * 60000;
345
+ start = new Date( start.getTime() - userTimezoneOffset );
346
+ start.setUTCHours( 0, 0, 0, 0 );
347
+ const record = {
348
+ userId: req.user._id,
349
+ storeId: msg.store_id,
350
+ clientId: msg.store_id.split( '-' )[0],
351
+ auditType: 'Audit',
352
+ fileDate: msg.curr_date,
353
+ queueName: inputData.queueName,
354
+ beforeCount: msg.total_count || files.length,
355
+ auditStatus: 'inprogress',
356
+ fileDateISO: start,
357
+ timeSpent: 0,
358
+ startTime: new Date(),
359
+ zoneName: msg.zone_id,
360
+ moduleType: inputData.moduleType,
361
+ };
362
+ const query ={
363
+ storeId: msg.store_id,
364
+ zoneName: msg.zone_id,
365
+ fileDate: msg.curr_date,
366
+ moduleType: inputData.moduleType,
367
+ };
368
+ const storeRecord = {
369
+ userId: req.user._id,
370
+ storeId: msg.store_id,
371
+ clientId: msg.store_id.split( '-' )[0],
372
+ auditType: 'Audit',
373
+ fileDate: msg.curr_date,
374
+ queueName: inputData.queueName,
375
+ beforeCount: msg.total_count || files.length,
376
+ status: 'inprogress',
377
+ fileDateISO: start,
378
+ timeSpent: 0,
379
+ zoneName: msg.zone_id,
380
+ moduleType: inputData.moduleType,
381
+ };
382
+
383
+ insertData = await createUserAudit( record );
384
+ await updateManyStoreAudit( query, storeRecord );
385
+ } else {
386
+ insertData = userDetails[0];
387
+ }
388
+ } else {
389
+ logger.error( {
390
+ error: { folderPath: folderPath, nextQuery: nextQuery },
391
+ function: 'getAuditFile',
392
+ message: 'Bucket image data not availale',
393
+ } );
394
+ return res.sendError( 'Bucket is Empty', 204 );
395
+ }
396
+ const userdata = await findOneUser( { _id: insertData.userId } );
397
+ const storeQuery = {
398
+ storeId: storeId,
399
+ };
400
+ const storeFields = {
401
+ storeName: 1,
402
+ address: '$storeProfile.address',
403
+ };
404
+ const storeInfo = await findOneStore( storeQuery, storeFields );
405
+ if ( inputData.nextId ) {
406
+ const logData = {
407
+ userId: insertData.userId,
408
+ userName: userdata.name,
409
+ logType: 'audit',
410
+ logSubType: 'auditStart',
411
+ logData: {
412
+ fileDate: insertData.fileDate,
413
+ auditType: insertData.auditType,
414
+ storeId: storeId,
415
+ clientName: inputData.queueName,
416
+ auditId: insertData._id,
417
+ zoneName: msg.zone_id,
418
+ moduleType: inputData.moduleType,
419
+ },
420
+ createdAt: new Date(),
421
+ };
422
+ await insertOpenSearchData( openSearch.auditLog, logData );
423
+ }
424
+ logger.info( { storeInfo: storeInfo } );
425
+ return res.sendSuccess( {
426
+ result: files,
427
+ count: msg.total_count,
428
+ storeId: storeId,
429
+ storeName: storeInfo?.storeName,
430
+ address: storeInfo?.address,
431
+ file: {
432
+ queueName: inputData.queueName,
433
+ store_id: storeId,
434
+ file_date: fileDate,
435
+ type: 'Audit',
436
+ auditId: insertData._id,
437
+ userId: insertData.userId,
438
+ zoneName: msg.zone_id,
439
+ moduleType: inputData.moduleType,
440
+ nextToken: nextQuery ? encodeURIComponent( nextQuery ) : null,
441
+ },
442
+ isDraft: insertData.isDraft,
443
+ } );
444
+ } catch ( error ) {
445
+ logger.error( {
446
+ error: error,
447
+ message: req.query,
448
+ function: 'getAuditFile',
449
+ } );
450
+ return res.sendError( error, 500 );
451
+ }
452
+ }
453
+
454
+ export async function getAuditFile( req, res ) {
455
+ try {
456
+ const inputData = req.query;
457
+ const openSearch = JSON.parse( process.env.OPENSEARCH );
458
+ const data = await getDate( new Date(), new Date() );
459
+ const start = data.start;
460
+ const end = data.end;
461
+ let msg = {};
462
+ const userQuery = [
463
+ {
464
+ $match: {
465
+ $and: [
466
+ { userId: req.user._id },
467
+ { queueName: inputData.queueName },
468
+ { auditStatus: { $in: [ 'inprogress' ] } },
469
+ { createdAt: { $gte: start } },
470
+ { createdAt: { $lte: end } },
471
+ { moduleType: inputData.moduleType },
472
+ ],
473
+ },
474
+ },
475
+ {
476
+ $sort: { createdAt: -1 },
477
+ },
478
+ {
479
+ $limit: 1,
480
+ },
481
+ ];
482
+
483
+ const userDetails = await aggregateBinaryAuditModel( userQuery );
484
+ logger.info( { userDetails: userDetails, function: 'userDetails' } );
485
+ const auditStatus = userDetails && userDetails.length > 0 ? userDetails[0].auditStatus : null;
486
+
487
+ switch ( auditStatus ) {
488
+ case null:
489
+
490
+ logger.info( 'Hit in new file', { inputData } );
491
+ const consumer = await sqsReceive( inputData.queueName );
492
+ if ( !consumer ) {
493
+ logger.error( {
494
+ error: consumer,
495
+ function: `get ${inputData.moduleType} File`,
496
+ message: 'SQS Receive queue is empty',
497
+ } );
498
+ return res.sendError( `${inputData.queueName} is Empty`, 204 );
499
+ }
500
+ msg = JSON.parse( consumer );
501
+
502
+ break;
503
+
504
+ case 'inprogress':
505
+
506
+ msg ={
507
+ storeId: userDetails[0].storeId,
508
+ fileDate: userDetails[0].fileDate,
509
+ moduleType: userDetails[0].moduleType,
510
+ tempId: userDetails[0].tempId,
511
+ question: userDetails[0].question,
512
+ fileDetails: userDetails[0].fileDetails,
513
+ inputBucketName: userDetails[0].inputBucketName,
514
+ questionType: userDetails[0].questionType,
515
+ streamName: userDetails[0].streamName,
516
+ };
517
+ break;
518
+
519
+ default:
520
+ logger.info( 'Hit in new file', { inputData } );
521
+ const message = await sqsReceive( inputData.queueName );
522
+ if ( !message ) {
523
+ logger.error( {
524
+ error: message,
525
+ function: `get ${inputData.moduleType} File`,
526
+ message: 'SQS Receive queue is empty',
527
+ } );
528
+ return res.sendError( `${inputData.queueName} is Empty`, 204 );
529
+ }
530
+ msg = JSON.parse( message );
531
+ break;
532
+ }
533
+ let result =[];
534
+ let insertData={};
535
+ switch ( inputData.moduleType ) {
536
+ case 'camera-angle-change':
537
+ const actualParams ={
538
+ Bucket: msg.inputBucketName,
539
+ Key: msg.actual,
540
+ };
541
+ const changedParams ={
542
+ Bucket: msg.inputBucketName,
543
+ Key: msg.changed,
544
+ };
545
+
546
+ const [ isActualExists, isChangedExists ] = await Promise.all( [ checkFileExist( actualParams ), checkFileExist( changedParams ) ] );
547
+ result =[
548
+ {
549
+ actualCameraImage: isActualExists? await signedUrl( { Bucket: msg.inputBucketName,
550
+ file_path: msg.actual } ) :'',
551
+ },
552
+ {
553
+ changedCameraImage: isChangedExists? await signedUrl( { Bucket: msg.inputBucketName,
554
+ file_path: msg.changed } ) : '',
555
+ },
556
+ ];
557
+ break;
558
+ case 'unattended-customer':
559
+ for ( let i =0; i< msg.fileDetails.length; i++ ) {
560
+ const files = [];
561
+ const params ={
562
+ Bucket: msg.inputBucketName,
563
+ file_path: msg?.fileDetails[i]?.folderPath,
564
+ MaxKeys: 1000,
565
+ };
566
+ const list = await listFileByPath( params );
567
+ const folderPath = list.data;
568
+ logger.info( { folderPath: list, params: params, list: list } );
569
+ if ( folderPath?.length ) {
570
+ for ( let i = 0; i < folderPath.length; i++ ) {
571
+ // const img = folderPath[i].Key.split( '/' );
572
+ // const image = img[3].split( '.' );
573
+ // const indexes = image[0].split( '_' );
574
+ const signedParams ={
575
+ Bucket: msg.inputBucketName,
576
+ file_path: folderPath[i].Key,
577
+ };
578
+ const data = await signedUrl( signedParams );
579
+
580
+ files.push(
581
+ data,
582
+ );
583
+ }
584
+ } else {
585
+ logger.error( {
586
+ error: { folderPath: folderPath },
587
+ function: `getAuditFile - ${inputData.moduleType}`,
588
+ message: 'Bucket image data not availale',
589
+ } );
590
+ return res.sendError( 'Bucket is Empty', 204 );
591
+ }
592
+ result.push( {
593
+ type: msg.fileDetails[i].type,
594
+ file: files,
595
+ } );
596
+ }
597
+ break;
598
+ case 'left-in-middle':
599
+ for ( let i =0; i< msg.fileDetails.length; i++ ) {
600
+ const files = [];
601
+ const params ={
602
+ Bucket: msg.inputBucketName,
603
+ file_path: msg?.fileDetails[i]?.folderPath,
604
+ MaxKeys: 1000,
605
+ };
606
+ const list = await listFileByPath( params );
607
+ const folderPath = list.data;
608
+ logger.info( { folderPath: list, params: params, list: list } );
609
+ if ( folderPath?.length ) {
610
+ for ( let i = 0; i < folderPath.length; i++ ) {
611
+ // const img = folderPath[i].Key.split( '/' );
612
+ // const image = img[3].split( '.' );
613
+ // const indexes = image[0].split( '_' );
614
+ const signedParams ={
615
+ Bucket: msg.inputBucketName,
616
+ file_path: folderPath[i].Key,
617
+ };
618
+ const data = await signedUrl( signedParams );
619
+
620
+ files.push(
621
+ data,
622
+ );
623
+ }
624
+ } else {
625
+ logger.error( {
626
+ error: { folderPath: folderPath },
627
+ function: `getAuditFile - ${inputData.moduleType}`,
628
+ message: 'Bucket image data not availale',
629
+ } );
630
+ return res.sendError( 'Bucket is Empty', 204 );
631
+ }
632
+ result.push( {
633
+ type: msg.fileDetails[i].type,
634
+ file: files,
635
+ } );
636
+ }
637
+ break;
638
+ default:
639
+ return res.sendError( 'Please given valid moduleType', 400 );
640
+ }
641
+
642
+
643
+ const storeQuery = {
644
+ storeId: msg.storeId,
645
+ };
646
+ const storeFields = {
647
+ 'storeName': 1,
648
+ 'storeProfile.address': 1,
649
+ 'clientId': 1,
650
+ };
651
+ const storeInfo = await findOneStore( storeQuery, storeFields );
652
+
653
+ if ( userDetails.length === 0 ) {
654
+ const [ day, month, year ] = msg.fileDate.split( '-' );
655
+ const temp = `${year}-${month}-${day}`;
656
+ let start = new Date( temp );
657
+ logger.info( { start: start, date: msg.fileDate } );
658
+ const userTimezoneOffset = start.getTimezoneOffset() * 60000;
659
+ start = new Date( start.getTime() - userTimezoneOffset );
660
+ start.setUTCHours( 0, 0, 0, 0 );
661
+
662
+ const record = {
663
+ userId: req.user._id,
664
+ storeId: msg.storeId,
665
+ clientId: storeInfo?.clientId,
666
+ fileDate: msg.fileDate,
667
+ queueName: inputData.queueName,
668
+ auditStatus: 'inprogress',
669
+ fileDateISO: start,
670
+ timeSpent: 0,
671
+ startTime: new Date(),
672
+ tempId: msg.tempId,
673
+ fileDetails: msg.fileDetails,
674
+ moduleType: inputData.moduleType,
675
+ inputBucketName: msg.inputBucketName,
676
+ question: msg.question,
677
+ questionType: msg.questionType,
678
+ streamName: msg.streamName,
679
+ };
680
+ record.streamName = inputData.moduleType == 'camera-angle-change'? msg.streamName : '';
681
+ record.videoDetails = inputData.moduleType == 'left-in-middle'? {
682
+ 'startHour': msg.startHour,
683
+ 'inspectHour': msg.inspectHour,
684
+ 'endHour': msg.endHour,
685
+ 'startHourCount': msg.startHourCount,
686
+ 'inspectHourCount': msg.inspectHourCount,
687
+ 'endHourCount': msg.inspectHourCount,
688
+ } : {};
689
+ insertData = await createBinaryAudit( record );
690
+ } else {
691
+ insertData = userDetails[0];
692
+ }
693
+
694
+ const userdata = await findOneUser( { _id: insertData.userId } );
695
+
696
+
697
+ const logData = {
698
+ userId: insertData.userId,
699
+ userName: userdata.name,
700
+ logType: 'audit',
701
+ logSubType: 'auditStart',
702
+ data: {
703
+ fileDate: msg.fileDate,
704
+ storeId: msg.storeId,
705
+ clientId: storeInfo?.clientId,
706
+ tempId: msg.tempId,
707
+ value: msg.value,
708
+ auditId: insertData._id,
709
+ fileDetails: msg.fileDetails,
710
+ moduleType: inputData.moduleType,
711
+ question: msg.question,
712
+ questionType: msg.questionType,
713
+ streamName: msg.streamName,
714
+ },
715
+ createdAt: new Date(),
716
+ };
717
+ await insertOpenSearchData( openSearch.auditLog, logData );
718
+
719
+ return res.sendSuccess( {
720
+ result: result,
721
+ storeId: msg.storeId,
722
+ storeName: storeInfo?.storeName,
723
+ address: storeInfo?.address,
724
+ customerId: msg.tempId,
725
+ moduleType: inputData.moduleType,
726
+ value: inputData.moduleType == 'left-in-middle'? 'Employee Left in Middle ' : ( inputData.moduleType ).split( '-' ).join( ' ' ),
727
+ fileDate: msg.fileDate,
728
+ question: msg.question,
729
+ questionType: msg.questionType,
730
+ streamName: msg.streamName,
731
+ } );
732
+ } catch ( error ) {
733
+ const err = error.message || 'Internal Server Error';
734
+ logger.error( { error: error, data: req.query, function: 'getAuditFile' } );
735
+ return res.sendError( err, 500 );
736
+ }
737
+ }
@@ -0,0 +1,46 @@
1
+ import j2s from 'joi-to-swagger';
2
+ import { getFileSchema } from '../dtos/traxAudit.dtos.js';
3
+
4
+ export const traxAuditDocs = {
5
+
6
+ '/v3/trax-audit/get-file': {
7
+ get: {
8
+ tags: [ 'Trax Audit' ],
9
+ description: 'Get a file via queue message',
10
+ operationId: 'get-file',
11
+ parameters: [
12
+ {
13
+ in: 'query',
14
+ name: 'queueName',
15
+ scema: j2s( getFileSchema ).swagger,
16
+ require: true,
17
+ },
18
+ // {
19
+ // in: 'query',
20
+ // name: 'nextId',
21
+ // scema: j2s( getFileSchema ).swagger,
22
+ // require: false,
23
+ // },
24
+ // {
25
+ // in: 'query',
26
+ // name: 'limit',
27
+ // scema: j2s( getFileSchema ).swagger,
28
+ // require: false,
29
+ // },
30
+ {
31
+ in: 'query',
32
+ name: 'moduleType',
33
+ scema: j2s( getFileSchema ).swagger,
34
+ require: true,
35
+ },
36
+ ],
37
+ responses: {
38
+ 200: { description: 'Successful' },
39
+ 401: { description: 'Unauthorized User' },
40
+ 422: { description: 'Field Error' },
41
+ 500: { description: 'Server Error' },
42
+ 204: { description: 'Not Found' },
43
+ },
44
+ },
45
+ },
46
+ };
@@ -0,0 +1,105 @@
1
+ import joi from 'joi';
2
+ /* < -- *** Audit Mapping *** --> */
3
+
4
+ export const getFileSchema = joi.object(
5
+ {
6
+ queueName: joi.string().required(),
7
+ moduleType: joi.string().required(),
8
+ },
9
+ );
10
+
11
+ export const getFileValid = {
12
+ query: getFileSchema,
13
+ };
14
+
15
+ export const getDetectionFileSchema = joi.object( {
16
+ queueName: joi.string().required(),
17
+ nextId: joi.string().optional().allow( '' ),
18
+ limit: joi.number().optional(),
19
+ moduleType: joi.string().required(),
20
+ } );
21
+
22
+ export const getDetectionFileValid = {
23
+ query: getDetectionFileSchema,
24
+ };
25
+
26
+ export const saveDraftSchema = joi.object(
27
+ {
28
+ userCommands: joi.string().optional().allow( '' ),
29
+ storeId: joi.string().required(),
30
+ auditId: joi.string().required(),
31
+ moduleType: joi.string().required(),
32
+ zoneName: joi.string().required(),
33
+ auditType: joi.string().required(),
34
+ fileDate: joi.string().required(),
35
+ queueName: joi.string().required(),
36
+ totalCount: joi.number().required(),
37
+ junkCount: joi.number().optional(),
38
+ junk: joi.array().optional(),
39
+ employeeCount: joi.number().optional(),
40
+ employee: joi.array().optional(),
41
+ customerCount: joi.number().optional(),
42
+ customer: joi.array().optional(),
43
+ retagCount: joi.number().optional(),
44
+ retagImage: joi.array().optional(),
45
+ },
46
+ );
47
+
48
+ export const saveDraftValid = {
49
+ body: saveDraftSchema,
50
+ };
51
+
52
+ export const getDraftedDataSchema = joi.object(
53
+ {
54
+ storeId: joi.string().required(),
55
+ fileDate: joi.string().required(),
56
+ userId: joi.string().optional(),
57
+ moduleType: joi.string().required(),
58
+ zoneName: joi.string().required(),
59
+ },
60
+ );
61
+
62
+ export const getDraftedDataValid = {
63
+ query: getDraftedDataSchema,
64
+ };
65
+
66
+ export const saveSchema = joi.object(
67
+ {
68
+ auditId: joi.string().required(),
69
+ storeId: joi.string().required(),
70
+ fileDate: joi.string().required(),
71
+ auditType: joi.string().required(),
72
+ moduleType: joi.string().required(),
73
+ zoneName: joi.string().required(),
74
+ beforeCount: joi.number().required(),
75
+ junkCount: joi.number().required(),
76
+ junk: joi.array().required(),
77
+ employeeCount: joi.number().required(),
78
+ employee: joi.array().required(),
79
+ customerCount: joi.number().required(),
80
+ customer: joi.array().required(),
81
+ moduleType: joi.string().required(),
82
+ zoneName: joi.string().required(),
83
+ },
84
+ );
85
+
86
+ export const saveValid = {
87
+ body: saveSchema,
88
+ };
89
+
90
+ export const workSpaceSchema = joi.object(
91
+ {
92
+ searchValue: joi.string().optional().allow( '' ),
93
+ moduleType: joi.string().required(),
94
+ clientId: joi.array().optional(),
95
+ offset: joi.number().optional(),
96
+ limit: joi.number().optional(),
97
+ isExport: joi.boolean().optional(),
98
+ sortColumnName: joi.string().optional(),
99
+ sortBy: joi.number().optional(),
100
+ },
101
+ );
102
+
103
+ export const workSpaceValid = {
104
+ body: workSpaceSchema,
105
+ };
@@ -0,0 +1,17 @@
1
+ import { Router } from 'express';
2
+ import { isAllowedSessionHandler, validate } from 'tango-app-api-middleware';
3
+ import { getDetectionFileValid, getFileValid } from '../dtos/traxAudit.dtos.js';
4
+ import { isExistsQueue } from '../validation/audit.validation.js';
5
+ import { getAuditFile, getDetectionAuditFile } from '../controllers/traxAudit.controllers.js';
6
+
7
+ export const traxAuditRouter = Router();
8
+
9
+ // Audit Mapping
10
+ traxAuditRouter.get( '/get-file', isAllowedSessionHandler, validate( getFileValid ), isExistsQueue, getAuditFile );
11
+ traxAuditRouter.get( '/get-file', isAllowedSessionHandler, validate( getDetectionFileValid ), isExistsQueue, getDetectionAuditFile );
12
+ // traxAuditRouter.post( '/save-draft', isAllowedSessionHandler, validate( saveDraftValid ), saveDraft );
13
+ // traxAuditRouter.get( '/get-drafted-data', isAllowedSessionHandler, validate( getDraftedDataValid ), getDraftedData );
14
+ // traxAuditRouter.post( '/save', isAllowedSessionHandler, validate( saveValid ), validateUserAudit, save );
15
+ // traxAuditRouter.post( '/work-space', isAllowedSessionHandler, validate( workSpaceValid ), workSpace );
16
+
17
+ export default traxAuditRouter;
@@ -0,0 +1,10 @@
1
+ import binaryAuditModel from 'tango-api-schema/schema/binaryAudit.model.js';
2
+
3
+
4
+ export function createBinaryAudit( record ) {
5
+ return binaryAuditModel.create( record );
6
+ }
7
+
8
+ export function aggregateBinaryAuditModel( query ) {
9
+ return binaryAuditModel.aggregate( query, { collation: { locale: 'en', strength: 2 } } );
10
+ }
@@ -0,0 +1,6 @@
1
+ import userEmpDetectionModel from 'tango-api-schema/schema/userEmpDetection.model.js';
2
+
3
+
4
+ export function aggregateUserAudit( query ) {
5
+ return userEmpDetectionModel.aggregate( query, { collation: { locale: 'en', strength: 2 } } );
6
+ }