tango-app-api-audit 3.4.0-alpha.9 → 3.4.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.
@@ -1,4 +1,4 @@
1
- import { checkFileExist, download, getDate, getDateWithCustomizeTime, getUTC, insertOpenSearchData, listFileByPath, logger, signedUrl, sqsReceive } from 'tango-app-api-middleware';
1
+ import { checkFileExist, chunkArray, download, getDate, getDateWithCustomizeTime, getUTC, insertOpenSearchData, listFileByPath, logger, signedUrl, sqsReceive } from 'tango-app-api-middleware';
2
2
  import { aggregateBinaryAudit, createBinaryAudit, updateOneBinaryAuditModel } from '../service/binaryAudit.service.js';
3
3
  import { countDocumentsStore, findOneStore } from '../service/store.service.js';
4
4
  import { findOneUser } from '../service/user.service.js';
@@ -18,7 +18,8 @@ export async function getDetectionAuditFile( req, res ) {
18
18
  const bucket = JSON.parse( process.env.BUCKET );
19
19
  const openSearch = JSON.parse( process.env.OPENSEARCH );
20
20
  const inputData = req.query;
21
- const data = await getDate( new Date(), new Date() );
21
+ const previousDate = new Date( new Date() - 1 );
22
+ const data = await getDate( previousDate, new Date() );
22
23
  logger.info( { data: data, function: 'data', newDate: new Date() } );
23
24
  logger.info( { userId: req.user._id, queueName: inputData.queueName, moduleType: inputData.moduleType } );
24
25
  const start = data.start;
@@ -471,10 +472,9 @@ export async function workSpace( req, res ) {
471
472
  const filter =[
472
473
  { status: { $in: [ 'active', 'hold' ] } },
473
474
  { 'auditConfigs.audit': { $eq: true } },
475
+ { clientId: { $in: inputData.clientId } },
474
476
  ];
475
- if ( inputData?.clientId?.length > 0 ) {
476
- filter.push( { clientId: { $in: inputData.clientId } } );
477
- }
477
+
478
478
  const temp = [];
479
479
  const clientQuery = [
480
480
  {
@@ -619,6 +619,48 @@ export async function workSpace( req, res ) {
619
619
  },
620
620
  ];
621
621
 
622
+ const binarCompletedStores = [
623
+ {
624
+ $match: {
625
+ $and: [
626
+ { clientId: { $in: clientList } },
627
+ { fileDate: { $eq: latestDate } },
628
+ { moduleType: { $eq: inputData.moduleType } },
629
+ ],
630
+ },
631
+ },
632
+ {
633
+ $project: {
634
+ clientId: 1,
635
+ completed: {
636
+ $cond: [ { $eq: [ '$auditStatus', 'completed' ] }, 1, 0 ],
637
+ },
638
+ },
639
+ },
640
+ // {
641
+ // $group: {
642
+ // _id: { clientId: '$clientId', storeId: '$storeId' },
643
+ // clientId: { $first: '$clientId' },
644
+ // completedStoresCount: { $sum: '$completed' },
645
+ // },
646
+ // },
647
+ {
648
+ $group: {
649
+ _id: '$clientId',
650
+ clientId: { $first: '$clientId' },
651
+ // completedStoresCount: { $first: '$completedStoresCount' },
652
+ completedStoresCount: { $sum: '$completed' },
653
+ },
654
+ },
655
+ {
656
+ $project: {
657
+ _id: 0,
658
+ clientId: 1,
659
+ completedStoresCount: 1,
660
+ },
661
+ },
662
+ ];
663
+
622
664
  const auditFiles = [
623
665
  {
624
666
  $match: {
@@ -754,7 +796,7 @@ export async function workSpace( req, res ) {
754
796
  const auditUserCount = inputData.moduleType.includes( [ 'uniform-detection', 'mobile-detection' ] )?await aggregateUserEmpDetection( auditFiles ) : await aggregateBinaryAudit( auditFiles );
755
797
  const userIncompleteFilesCount = inputData.moduleType.includes( [ 'uniform-detection', 'mobile-detection' ] )?await aggregateUserEmpDetection( userIncompleteFiles ) : await aggregateBinaryAudit( userIncompleteFiles );
756
798
  const userAsignAuditCount = await aggregateAssignAudit( userAsignAudit );
757
- const completedStoresCount = inputData.moduleType.includes( [ 'uniform-detection', 'mobile-detection' ] )? await aggregateStoreEmpDetection( completedStores ) : await aggregateBinaryAudit( completedStores );
799
+ const completedStoresCount = inputData.moduleType.includes( [ 'uniform-detection', 'mobile-detection' ] )? await aggregateStoreEmpDetection( completedStores ) : await aggregateBinaryAudit( binarCompletedStores );
758
800
  const clientAssignedCount = await aggregateAssignAudit( clientAssign );
759
801
  const auditStoreData = await aggregateTraxAuditData(
760
802
  auditStoreDataQuery,
@@ -861,7 +903,8 @@ export async function getAuditFile( req, res ) {
861
903
  try {
862
904
  const inputData = req.query;
863
905
  const openSearch = JSON.parse( process.env.OPENSEARCH );
864
- const data = await getDate( new Date(), new Date() );
906
+ const previousDate = new Date( new Date() - 1 );
907
+ const data = await getDate( previousDate, new Date() );
865
908
  const start = data.start;
866
909
  const end = data.end;
867
910
  let msg = {};
@@ -908,18 +951,55 @@ export async function getAuditFile( req, res ) {
908
951
  break;
909
952
 
910
953
  case 'inprogress':
911
-
912
- msg ={
913
- storeId: userDetails[0].storeId,
914
- fileDate: userDetails[0].fileDate,
915
- moduleType: userDetails[0].moduleType,
916
- tempId: userDetails[0].tempId,
917
- question: userDetails[0].question,
918
- fileDetails: userDetails[0].fileDetails,
919
- inputBucketName: userDetails[0].inputBucketName,
920
- questionType: userDetails[0].questionType,
921
- streamName: userDetails[0].streamName,
922
- };
954
+ let query = {};
955
+ switch ( inputData.moduleType ) {
956
+ case 'unattended-customer':
957
+ query ={
958
+ storeId: userDetails[0].storeId,
959
+ fileDate: userDetails[0].fileDate,
960
+ tempId: userDetails[0].tempId,
961
+ moduleType: userDetails[0].moduleType,
962
+ };
963
+ break;
964
+ case 'left-in-middle':
965
+ query ={
966
+ storeId: userDetails[0].storeId,
967
+ fileDate: userDetails[0].fileDate,
968
+ question: userDetails[0].question,
969
+ moduleType: userDetails[0].moduleType,
970
+ };
971
+ break;
972
+ case 'uniform-detection':
973
+ query ={
974
+ storeId: userDetails[0].storeId,
975
+ fileDate: userDetails[0].fileDate,
976
+ moduleType: userDetails[0].moduleType,
977
+ };
978
+ break;
979
+ case 'mobile-detection':
980
+ query ={
981
+ storeId: userDetails[0].storeId,
982
+ fileDate: userDetails[0].fileDate,
983
+ moduleType: userDetails[0].moduleType,
984
+ };
985
+ break;
986
+ case 'camera-angle-change':
987
+ query ={
988
+ storeId: userDetails[0].storeId,
989
+ fileDate: userDetails[0].fileDate,
990
+ streamName: userDetails[0].streamName,
991
+ moduleType: userDetails[0].moduleType,
992
+ };
993
+ break;
994
+ default:
995
+ return res.sendError( 'Please give valid modueType', 400 );
996
+ }
997
+ logger.info( { query: query } );
998
+ const traxInfo = await findOneTraxAuditData( query );
999
+ if ( !traxInfo ) {
1000
+ return res.sendError( 'The sorce record not found', 400 );
1001
+ }
1002
+ msg =traxInfo?.sqs?.Body;
923
1003
  break;
924
1004
 
925
1005
  default:
@@ -1144,6 +1224,175 @@ export async function getAuditFile( req, res ) {
1144
1224
  }
1145
1225
  }
1146
1226
 
1227
+ export async function getUpdatedFile( req, res ) {
1228
+ try {
1229
+ const openSearch = JSON.parse( process.env.OPENSEARCH );
1230
+ const inputData = req.body;
1231
+ const msg = req?.TraxData?.sqs?.Body;
1232
+ logger.info( { msg: msg } );
1233
+ let result =[];
1234
+ switch ( inputData.moduleType ) {
1235
+ case 'camera-angle-change':
1236
+ const actualParams ={
1237
+ Bucket: msg.inputBucketName,
1238
+ Key: msg.actual,
1239
+ };
1240
+ const changedParams ={
1241
+ Bucket: msg.inputBucketName,
1242
+ Key: msg.changed,
1243
+ };
1244
+
1245
+ const [ isActualExists, isChangedExists ] = await Promise.all( [ checkFileExist( actualParams ), checkFileExist( changedParams ) ] );
1246
+ result =[
1247
+ {
1248
+ actualCameraImage: isActualExists? await signedUrl( { Bucket: msg.inputBucketName,
1249
+ file_path: msg.actual } ) :'',
1250
+ },
1251
+ {
1252
+ changedCameraImage: isChangedExists? await signedUrl( { Bucket: msg.inputBucketName,
1253
+ file_path: msg.changed } ) : '',
1254
+ },
1255
+ ];
1256
+ break;
1257
+ case 'unattended-customer':
1258
+ for ( let i =0; i< msg.fileDetails.length; i++ ) {
1259
+ const files = [];
1260
+ const params ={
1261
+ Bucket: msg.inputBucketName,
1262
+ file_path: msg?.fileDetails[i]?.folderPath,
1263
+ MaxKeys: 1000,
1264
+ };
1265
+ const list = await listFileByPath( params );
1266
+ const folderPath = list.data;
1267
+ logger.info( { folderPath: list, params: params, list: list } );
1268
+ if ( folderPath?.length ) {
1269
+ for ( let i = 0; i < folderPath.length; i++ ) {
1270
+ // const img = folderPath[i].Key.split( '/' );
1271
+ // const image = img[3].split( '.' );
1272
+ // const indexes = image[0].split( '_' );
1273
+ const signedParams ={
1274
+ Bucket: msg.inputBucketName,
1275
+ file_path: folderPath[i].Key,
1276
+ };
1277
+ const data = await signedUrl( signedParams );
1278
+
1279
+ files.push(
1280
+ data,
1281
+ );
1282
+ }
1283
+ } else {
1284
+ logger.error( {
1285
+ error: { folderPath: folderPath },
1286
+ function: `getAuditFile - ${inputData.moduleType}`,
1287
+ message: 'Bucket image data not availale',
1288
+ } );
1289
+ return res.sendError( 'Bucket is Empty', 204 );
1290
+ }
1291
+ result.push( {
1292
+ type: msg.fileDetails[i].type,
1293
+ file: files,
1294
+ } );
1295
+ }
1296
+ break;
1297
+ case 'left-in-middle':
1298
+ for ( let i =0; i< msg.fileDetails.length; i++ ) {
1299
+ const files = [];
1300
+ const params ={
1301
+ Bucket: msg.inputBucketName,
1302
+ file_path: msg?.fileDetails[i]?.folderPath,
1303
+ MaxKeys: 1000,
1304
+ };
1305
+ const list = await listFileByPath( params );
1306
+ const folderPath = list.data;
1307
+ logger.info( { folderPath: list, params: params, list: list } );
1308
+ if ( folderPath?.length ) {
1309
+ for ( let i = 0; i < folderPath.length; i++ ) {
1310
+ // const img = folderPath[i].Key.split( '/' );
1311
+ // const image = img[3].split( '.' );
1312
+ // const indexes = image[0].split( '_' );
1313
+ const signedParams ={
1314
+ Bucket: msg.inputBucketName,
1315
+ file_path: folderPath[i].Key,
1316
+ };
1317
+ const data = await signedUrl( signedParams );
1318
+
1319
+ files.push(
1320
+ data,
1321
+ );
1322
+ }
1323
+ } else {
1324
+ logger.error( {
1325
+ error: { folderPath: folderPath },
1326
+ function: `getAuditFile - ${inputData.moduleType}`,
1327
+ message: 'Bucket image data not availale',
1328
+ } );
1329
+ return res.sendError( 'Bucket is Empty', 204 );
1330
+ }
1331
+ result.push( {
1332
+ type: msg.fileDetails[i].type,
1333
+ file: files,
1334
+ } );
1335
+ }
1336
+ break;
1337
+ default:
1338
+ return res.sendError( 'Please given valid moduleType', 400 );
1339
+ }
1340
+
1341
+ const userdata = await findOneUser( { _id: req.user._id } );
1342
+ const storeQuery = {
1343
+ storeId: inputData.storeId,
1344
+ };
1345
+ const storeFields = {
1346
+ 'storeName': 1,
1347
+ 'storeProfile.address': 1,
1348
+ 'clientId': 1,
1349
+ };
1350
+ const storeInfo = await findOneStore( storeQuery, storeFields );
1351
+
1352
+ const logData = {
1353
+ userId: req.user._id,
1354
+ userName: userdata.name,
1355
+ logType: 'audit',
1356
+ logSubType: 'auditStart',
1357
+ data: {
1358
+ fileDate: msg.fileDate,
1359
+ storeId: msg.storeId,
1360
+ clientId: storeInfo?.clientId,
1361
+ tempId: msg.tempId,
1362
+ value: msg.value,
1363
+ fileDetails: msg.fileDetails,
1364
+ moduleType: inputData.moduleType,
1365
+ question: msg.question,
1366
+ questionType: msg.questionType,
1367
+ streamName: msg.streamName,
1368
+ actaulImage: msg.actual,
1369
+ changedImage: msg.changed,
1370
+ },
1371
+ createdAt: new Date(),
1372
+ };
1373
+ await insertOpenSearchData( openSearch.auditLog, logData );
1374
+
1375
+ return res.sendSuccess( {
1376
+ result: result,
1377
+ storeId: msg.storeId,
1378
+ storeName: storeInfo?.storeName,
1379
+ address: storeInfo?.address,
1380
+ customerId: msg.tempId,
1381
+ moduleType: inputData.moduleType,
1382
+ value: inputData.moduleType == 'left-in-middle'? 'Employee Left in Middle ' : ( inputData.moduleType ).split( '-' ).join( ' ' ),
1383
+ fileDate: msg.fileDate,
1384
+ question: msg.question,
1385
+ questionType: msg.questionType,
1386
+ streamName: msg.streamName,
1387
+ auditId: inputData.auditId,
1388
+ } );
1389
+ } catch ( error ) {
1390
+ const err = error.message || 'Internal Server Error';
1391
+ logger.error( { error: error, data: req.body, function: 'getUpdatedFile' } );
1392
+ return res.sendError( err, 500 );
1393
+ }
1394
+ }
1395
+
1147
1396
  export async function saveBinary( req, res ) {
1148
1397
  try {
1149
1398
  const inputData = req.body;
@@ -1151,6 +1400,7 @@ export async function saveBinary( req, res ) {
1151
1400
  const currentTime = dayjs();
1152
1401
  const isoDateTime = dayjs( isoDate );
1153
1402
  const timeDifferenceInMinutes = currentTime.diff( isoDateTime, 'seconds' );
1403
+ const value = inputData.moduleType? inputData.moduleType.replace( /-/g, ' ' ) : '';
1154
1404
  switch ( inputData.moduleType ) {
1155
1405
  case 'unattended-customer':
1156
1406
  let unattendedquery ={
@@ -1170,10 +1420,10 @@ export async function saveBinary( req, res ) {
1170
1420
  };
1171
1421
  let updatDataunattended= await updateOneBinaryAuditModel( unattendedquery, update );
1172
1422
  if ( updatDataunattended.modifiedCount==0 ) {
1173
- return res.sendError( updatDataunattended, 204 );
1423
+ return res.sendError( 'Update failed, it may be invalid request', 400 );
1174
1424
  }
1175
1425
  logger.info( 'update in binary data', { query: unattendedquery, update: update } );
1176
- res.sendSuccess( `Successfully update in ${inputData.moduleType} ` );
1426
+ return res.sendSuccess( `Successfully updated in ${value}` );
1177
1427
 
1178
1428
  break;
1179
1429
 
@@ -1194,10 +1444,10 @@ export async function saveBinary( req, res ) {
1194
1444
  };
1195
1445
  let updatDataleft= await updateOneBinaryAuditModel( leftquery, leftupdate );
1196
1446
  if ( updatDataleft.modifiedCount==0 ) {
1197
- return res.sendError( updatDataleft, 204 );
1447
+ return res.sendError( 'Update failed, it may be invalid request', 400 );
1198
1448
  }
1199
1449
  logger.info( 'update in binary data', { query: leftquery, update: leftupdate } );
1200
- res.sendSuccess( `Successfully update in ${inputData.moduleType} ` );
1450
+ return res.sendSuccess( `Successfully updated in ${value}` );
1201
1451
 
1202
1452
  break;
1203
1453
 
@@ -1218,17 +1468,16 @@ export async function saveBinary( req, res ) {
1218
1468
  };
1219
1469
  let updatDatacamera= await updateOneBinaryAuditModel( cameraquery, cameraupdate );
1220
1470
  if ( updatDatacamera.modifiedCount==0 ) {
1221
- return res.sendError( updatDatacamera, 204 );
1471
+ return res.sendError( 'Update failed, it may be invalid request', 400 );
1222
1472
  }
1223
1473
  logger.info( 'update in binary data', { query: cameraquery, update: cameraupdate } );
1224
- res.sendSuccess( `Successfully update in ${inputData.moduleType} ` );
1474
+ return res.sendSuccess( `Successfully updated in ${value}` );
1225
1475
 
1226
1476
  break;
1227
1477
 
1228
1478
  default:
1229
1479
  res.sendError( 'no data', 204 );
1230
- break
1231
- ;
1480
+ break;
1232
1481
  }
1233
1482
  } catch ( error ) {
1234
1483
  const err = error.mesage || 'Internal Server Error';
@@ -1248,6 +1497,7 @@ export async function userAuditHistory( req, res ) {
1248
1497
  let filter = [
1249
1498
  { userId: { $eq: userId } },
1250
1499
  { moduleType: { $eq: inputData.moduleType } },
1500
+ { clientId: { $in: inputData.clientId } },
1251
1501
  ];
1252
1502
 
1253
1503
  if ( inputData.dateType == 'fileDate' ) {
@@ -1280,9 +1530,7 @@ export async function userAuditHistory( req, res ) {
1280
1530
  auditStatus: { $in: inputData.filterByStatus },
1281
1531
  } );
1282
1532
  }
1283
- if ( inputData?.clientId?.length > 0 ) {
1284
- filter.push( { clientId: { $in: inputData.clientId } } );
1285
- }
1533
+
1286
1534
  const query = [
1287
1535
  {
1288
1536
  $match: {
@@ -1476,16 +1724,16 @@ export async function userAuditHistory( req, res ) {
1476
1724
  switch ( inputData.moduleType ) {
1477
1725
  case 'camera-angle-change':
1478
1726
  temp['stream Name'] = element.streamName;
1479
- temp['User Comments'] = element.userCommands;
1727
+ temp['User Comments'] = element.userComments;
1480
1728
  break;
1481
1729
  case 'unattended-customer':
1482
1730
  temp['Customer ID'] = element.tempId;
1483
1731
  temp['Question'] = element.question;
1484
- temp['User Comments'] = element.userCommands;
1732
+ temp['User Comments'] = element.userComments;
1485
1733
  break;
1486
1734
  case 'left-in-middle':
1487
1735
  temp['Question'] = element.question;
1488
- temp['User Comments'] = element.userCommands;
1736
+ temp['User Comments'] = element.userComments;
1489
1737
  break;
1490
1738
  case 'uniform-detection':
1491
1739
  temp['Before Count'] = element.beforeCount;
@@ -1757,11 +2005,9 @@ export async function storeMetrics( req, res ) {
1757
2005
  { fileDateISO: { $gte: dateRange.start } },
1758
2006
  { fileDateISO: { $lte: dateRange.end } },
1759
2007
  { moduleType: { $eq: inputData.moduleType } },
2008
+ { clientId: { $in: inputData.filterByClientId } },
1760
2009
 
1761
2010
  ];
1762
- if ( inputData.filterByClientId && inputData.filterByClientId?.length > 0 ) {
1763
- filter.push( { clientId: { $in: inputData.filterByClientId } } );
1764
- }
1765
2011
 
1766
2012
  if ( inputData.filterByStoreId && inputData.filterByStoreId?.length > 0 ) {
1767
2013
  filter.push( { storeId: { $in: inputData.filterByStoreId } } );
@@ -1825,6 +2071,7 @@ export async function storeMetrics( req, res ) {
1825
2071
  },
1826
2072
  tempId: 1,
1827
2073
  streamName: 1,
2074
+ userComments: 1,
1828
2075
  question: 1,
1829
2076
  questionType: 1,
1830
2077
  answer: 1,
@@ -1915,6 +2162,7 @@ export async function storeMetrics( req, res ) {
1915
2162
  streamName: 1,
1916
2163
  question: 1,
1917
2164
  questionType: 1,
2165
+ userComments: 1,
1918
2166
  answer: 1,
1919
2167
  moduleType: 1,
1920
2168
  value: 1,
@@ -1959,6 +2207,191 @@ export async function storeMetrics( req, res ) {
1959
2207
 
1960
2208
  ];
1961
2209
 
2210
+ const binaryQuery = [
2211
+ {
2212
+ $match: {
2213
+ $and: filter,
2214
+ },
2215
+ },
2216
+
2217
+ {
2218
+ $lookup: {
2219
+ from: 'stores',
2220
+ let: { storeId: '$storeId' },
2221
+ pipeline: [
2222
+ {
2223
+ $match: {
2224
+ $expr: {
2225
+ $eq: [ '$storeId', '$$storeId' ],
2226
+ },
2227
+ },
2228
+ },
2229
+ {
2230
+ $project: {
2231
+ _id: 0,
2232
+ storeName: 1,
2233
+ },
2234
+ },
2235
+ ], as: 'stores',
2236
+ },
2237
+ },
2238
+ {
2239
+ $unwind: {
2240
+ path: '$stores',
2241
+ preserveNullAndEmptyArrays: true,
2242
+ },
2243
+ },
2244
+ {
2245
+ $project: {
2246
+ auditId: '$_id',
2247
+ _id: 0,
2248
+ fileDate: 1,
2249
+ storeId: 1,
2250
+ storeName: '$stores.storeName',
2251
+ clientName: '',
2252
+ clientId: 1,
2253
+ moduleType: 1,
2254
+ value: {
2255
+ $replaceAll: { input: '$moduleType', find: '-', replacement: ' ' },
2256
+ },
2257
+ tempId: 1,
2258
+ streamName: 1,
2259
+ question: 1,
2260
+ questionType: 1,
2261
+ userComments: 1,
2262
+ answer: 1,
2263
+ // userId: {
2264
+ // $arrayElemAt: [ '$userId', { $subtract: [ { $size: '$userId' }, 1 ] } ], //need to check if no data
2265
+ // },
2266
+ userId: 1,
2267
+ auditType: 1,
2268
+ beforeCount: 1,
2269
+ afterCount: { $ifNull: [ '$afterCount', null ] },
2270
+ accuracy: { $cond: [ { $eq: [ '$auditStatus', 'completed' ] }, { $round: [
2271
+ {
2272
+ $multiply: [ { $divide: [ '$afterCount', '$beforeCount' ] }, 100 ],
2273
+ }, 1,
2274
+ ],
2275
+ }, null ] },
2276
+ timeSpent: 1,
2277
+ status: 1,
2278
+ auditStatus: 1,
2279
+ },
2280
+ },
2281
+ {
2282
+ $lookup: {
2283
+ from: 'users',
2284
+ let: { userId: '$userId' },
2285
+ pipeline: [
2286
+ {
2287
+ $match: {
2288
+ $expr: {
2289
+ $eq: [ '$_id', '$$userId' ],
2290
+ },
2291
+ },
2292
+ },
2293
+ {
2294
+ $project: {
2295
+ _id: 0,
2296
+ userName: 1,
2297
+ userEmail: '$email',
2298
+ },
2299
+ },
2300
+ ], as: 'users',
2301
+ },
2302
+ },
2303
+ {
2304
+ $unwind: {
2305
+ path: '$users',
2306
+ preserveNullAndEmptyArrays: true,
2307
+ },
2308
+ },
2309
+ {
2310
+ $lookup: {
2311
+ from: 'clients',
2312
+ let: { clientId: '$clientId' },
2313
+ pipeline: [
2314
+ {
2315
+ $match: {
2316
+ $expr: {
2317
+ $eq: [ '$clientId', '$$clientId' ],
2318
+ },
2319
+ },
2320
+ },
2321
+ {
2322
+ $project: {
2323
+ _id: 0,
2324
+ clientName: 1,
2325
+ },
2326
+ },
2327
+ ], as: 'client',
2328
+ },
2329
+ },
2330
+ {
2331
+ $unwind: {
2332
+ path: '$client',
2333
+ preserveNullAndEmptyArrays: true,
2334
+ },
2335
+ },
2336
+ {
2337
+ $project: {
2338
+ auditId: 1,
2339
+ fileDate: 1,
2340
+ storeId: 1,
2341
+ storeName: 1,
2342
+ userName: '$users.userName',
2343
+ userEmail: '$users.userEmail',
2344
+ clientId: 1,
2345
+ clientName: '$client.clientName',
2346
+ tempId: 1,
2347
+ streamName: 1,
2348
+ question: 1,
2349
+ questionType: 1,
2350
+ userComments: 1,
2351
+ answer: 1,
2352
+ moduleType: 1,
2353
+ value: 1,
2354
+ auditType: 1,
2355
+ beforeCount: 1,
2356
+ afterCount: { $ifNull: [ '$afterCount', null ] },
2357
+ accuracy: { $cond: [ { $eq: [ '$auditStatus', 'completed' ] }, { $round: [
2358
+ {
2359
+ $multiply: [ { $divide: [ '$afterCount', '$beforeCount' ] }, 100 ],
2360
+ }, 1,
2361
+ ],
2362
+ }, null ] },
2363
+ timeSpent: {
2364
+
2365
+ $cond: [
2366
+ { $lt: [ '$timeSpent', 60 ] }, // Case 1: If less than 60 seconds
2367
+ { $concat: [ { $toString: '$timeSpent' }, ' sec' ] },
2368
+ {
2369
+ $cond: [
2370
+ { $lt: [ '$timeSpent', 3600 ] }, // Case 2: If less than 60 minutes (3600 seconds)
2371
+ {
2372
+ $concat: [
2373
+ { $toString: { $round: [ { $divide: [ '$timeSpent', 60 ] }, 1 ] } }, // Convert to minutes
2374
+ ' min',
2375
+ ],
2376
+ },
2377
+ {
2378
+ $concat: [
2379
+ { $toString: { $round: [ { $divide: [ '$timeSpent', 3600 ] }, 1 ] } }, // Convert to hours
2380
+ ' hr',
2381
+ ],
2382
+ },
2383
+ ],
2384
+ },
2385
+ ],
2386
+
2387
+ },
2388
+ status: 1,
2389
+ auditStatus: 1,
2390
+ },
2391
+ },
2392
+
2393
+ ];
2394
+
1962
2395
  if ( inputData.searchValue && inputData.searchValue !== '' ) {
1963
2396
  query.push( {
1964
2397
  $match: {
@@ -1975,6 +2408,7 @@ export async function storeMetrics( req, res ) {
1975
2408
  { question: { $regex: inputData.searchValue, $options: 'i' } },
1976
2409
  { answer: { $regex: inputData.searchValue, $options: 'i' } },
1977
2410
  { auditStatus: { $regex: inputData.searchValue, $options: 'i' } },
2411
+ { userComments: { $regex: inputData.searchValue, $options: 'i' } },
1978
2412
  ],
1979
2413
  },
1980
2414
  } );
@@ -1988,7 +2422,7 @@ export async function storeMetrics( req, res ) {
1988
2422
  },
1989
2423
  );
1990
2424
  }
1991
- const count = inputData.moduleType.includes( [ 'uniform-detection', 'mobile-detection' ] )?await aggregateStoreEmpDetection( query ) : await aggregateBinaryAudit( query );
2425
+ const count = inputData.moduleType.includes( [ 'uniform-detection', 'mobile-detection' ] )?await aggregateStoreEmpDetection( query ) : await aggregateBinaryAudit( binaryQuery );
1992
2426
 
1993
2427
  if ( count.length == 0 ) {
1994
2428
  return res.sendError( 'No data Found', 204 );
@@ -2022,16 +2456,16 @@ export async function storeMetrics( req, res ) {
2022
2456
  switch ( inputData.moduleType ) {
2023
2457
  case 'camera-angle-change':
2024
2458
  temp['stream Name'] = element.streamName;
2025
- temp['User Comments'] = element.auditStatus;
2459
+ temp['User Comments'] = element.userComments;
2026
2460
  break;
2027
2461
  case 'unattended-customer':
2028
2462
  temp['Customer ID'] = element.tempId;
2029
2463
  temp['Question'] = element.question;
2030
- temp['User Comments'] = element.auditStatus;
2464
+ temp['User Comments'] = element.userComments;
2031
2465
  break;
2032
2466
  case 'left-in-middle':
2033
2467
  temp['Question'] = element.question;
2034
- temp['User Comments'] = element.userCommands;
2468
+ temp['User Comments'] = element.userComments;
2035
2469
  temp['Status'] = element.auditStatus;
2036
2470
  break;
2037
2471
  case 'mobile-detection':
@@ -2107,11 +2541,10 @@ export async function userMetrics( req, res ) {
2107
2541
  userId: 1,
2108
2542
  fileDate: 1,
2109
2543
  startTime: 1,
2544
+ endTime: 1,
2110
2545
  beforeCount: 1,
2111
2546
  moduleType: 1,
2112
2547
  afterCount: 1,
2113
- checkIntime: 1,
2114
- checkOutTime: 1,
2115
2548
  totalCompletedFiles: { $cond: [ { $eq: [ '$auditStatus', 'completed' ] }, 1, 0 ] },
2116
2549
  beforeCount: 1,
2117
2550
  afterCount: { $cond: [ { $eq: [ '$auditStatus', 'completed' ] }, '$afterCount', 0 ] },
@@ -2379,13 +2812,10 @@ export async function pendingSummaryTable( req, res ) {
2379
2812
  { fileDateISO: { $lte: dateRange.end } },
2380
2813
  { auditStatus: { $ne: 'completed' } },
2381
2814
  { moduleType: { $eq: inputData.moduleType } },
2815
+ { clientId: { $in: inputData.clientId } },
2382
2816
 
2383
2817
  ];
2384
2818
 
2385
- if ( inputData.clientId.length > 0 ) {
2386
- filters.push( { clientId: { $in: inputData.clientId } } );
2387
- }
2388
-
2389
2819
  if ( inputData.filterByAuditType.length > 0 ) {
2390
2820
  filters.push( { auditType: { $in: inputData.filterByAuditType } } );
2391
2821
  }
@@ -2524,8 +2954,6 @@ export async function pendingSummaryTable( req, res ) {
2524
2954
  result.forEach( ( element ) => {
2525
2955
  const temp = {
2526
2956
  'Store ID': element.storeId,
2527
- 'Result': element.answer,
2528
- 'userComments': element.userComments,
2529
2957
  'File Date': element.fileDate,
2530
2958
  'Product Type': element.value,
2531
2959
  'Audit Type': element.auditType,
@@ -2537,16 +2965,13 @@ export async function pendingSummaryTable( req, res ) {
2537
2965
  switch ( inputData.moduleType ) {
2538
2966
  case 'camera-angle-change':
2539
2967
  temp['stream Name'] = element.streamName;
2540
- temp['User Comments'] = element.userCommands;
2541
2968
  break;
2542
2969
  case 'unattended-customer':
2543
2970
  temp['Customer ID'] = element.tempId;
2544
2971
  temp['Question'] = element.question;
2545
- temp['User Comments'] = element.userCommands;
2546
2972
  break;
2547
2973
  case 'left-in-middle':
2548
2974
  temp['Question'] = element.question;
2549
- temp['User Comments'] = element.userCommands;
2550
2975
  break;
2551
2976
  case 'mobile-detection':
2552
2977
  temp['Before Count'] = element.beforeCount;
@@ -2589,12 +3014,10 @@ export async function overAllAuditSummary( req, res ) {
2589
3014
  let filters =[
2590
3015
  { fileDateISO: { $gte: dateRange.start } },
2591
3016
  { fileDateISO: { $lte: dateRange.end } },
2592
- { moduleType: { $eq: inputData.moduleType },
2593
- },
3017
+ { moduleType: { $eq: inputData.moduleType } },
3018
+ { clientId: { $in: inputData.clientId } },
2594
3019
  ];
2595
- if ( inputData.clientId.length > 0 ) {
2596
- filters.push( { clientId: { $in: inputData.clientId } } );
2597
- }
3020
+
2598
3021
  const storeQuery = inputData.clientId.length? { 'edge.firstFile': true, 'clientId': { $in: inputData. clientId } } : { 'edge.firstFile': true };
2599
3022
  temp.installedStores = await countDocumentsStore( storeQuery );
2600
3023
  const auditClientDataQuery =[
@@ -2669,7 +3092,57 @@ export async function overAllAuditSummary( req, res ) {
2669
3092
  },
2670
3093
  },
2671
3094
  ];
2672
- const storeAudit = inputData.moduleType.includes( [ 'uniform-detection', 'mobile-detection' ] )?await aggregateStoreEmpDetection( storeAuditQuery ) : await aggregateBinaryAudit( storeAuditQuery );
3095
+
3096
+ const binaryAuditQuery =[
3097
+ {
3098
+ $match: {
3099
+ $and: filters,
3100
+ },
3101
+
3102
+ },
3103
+ {
3104
+ $project: {
3105
+ completedStores: { $cond: [ { $eq: [ '$auditStatus', 'completed' ] }, 1, 0 ] },
3106
+ auditInprogress: { $cond: [ { $and: [ { $in: [ '$auditStatus', [ 'inprogress' ] ] }, { $eq: [ '$auditType', 'Audit' ] } ] }, 1, 0 ] },
3107
+ reAuditInprogress: { $cond: [ { $and: [ { $in: [ '$auditStatus', [ 'inprogress' ] ] }, { $eq: [ '$auditType', 'ReAudit' ] } ] }, 1, 0 ] },
3108
+ draft: { $cond: [ { $eq: [ '$auditStatus', 'drafted' ] }, 1, 0 ] },
3109
+ assigned: { $cond: [ { $eq: [ '$auditStatus', 'assigned' ] }, 1, 0 ] },
3110
+ exceptNoAssigned: { $cond: { if: { $not: { $in: [ '$auditStatus', [ 'skipped', 'not_assign' ] ] } }, then: 1, else: 0 } },
3111
+ auditCompleted: { $cond: [ { $and: [ { $in: [ '$auditStatus', [ 'completed' ] ] }, { $eq: [ '$auditType', 'Audit' ] } ] }, 1, 0 ] },
3112
+ reAuditCompleted: { $cond: [ { $and: [ { $in: [ '$auditStatus', [ 'completed' ] ] }, { $eq: [ '$auditType', 'ReAudit' ] } ] }, 1, 0 ] },
3113
+
3114
+
3115
+ },
3116
+ },
3117
+ {
3118
+ $group: {
3119
+ _id: null,
3120
+ completedStores: { $sum: '$completedStores' },
3121
+ auditInprogress: { $sum: '$auditInprogress' },
3122
+ reAuditInprogress: { $sum: '$reAuditInprogress' },
3123
+ draft: { $sum: '$draft' },
3124
+ assigned: { $sum: '$assigned' },
3125
+ exceptNoAssigned: { $sum: '$exceptNoAssigned' },
3126
+ auditCompleted: { $sum: '$auditCompleted' },
3127
+ reAuditCompleted: { $sum: '$reAuditCompleted' },
3128
+ },
3129
+ },
3130
+ {
3131
+ $project: {
3132
+ completedStores: 1,
3133
+ inprogressStores: { $subtract: [ temp.auditStores, '$completedStores' ] },
3134
+ auditInprogress: 1,
3135
+ reAuditInprogress: 1,
3136
+ draft: 1,
3137
+ assigned: 1,
3138
+ exceptNoAssigned: { $subtract: [ temp.auditStores, '$exceptNoAssigned' ] },
3139
+ auditCompleted: 1,
3140
+ reAuditCompleted: 1,
3141
+ },
3142
+ },
3143
+ ];
3144
+
3145
+ const storeAudit = inputData.moduleType.includes( [ 'uniform-detection', 'mobile-detection' ] )?await aggregateStoreEmpDetection( storeAuditQuery ) : await aggregateBinaryAudit( binaryAuditQuery );
2673
3146
  if ( storeAudit.length > 0 ) {
2674
3147
  temp.inprogressStores= storeAudit[0].inprogressStores;
2675
3148
  temp.completedStores = storeAudit[0].completedStores;
@@ -2708,10 +3181,9 @@ export async function summarySplit( req, res ) {
2708
3181
  { fileDateISO: { $gte: dateRange.start } },
2709
3182
  { fileDateISO: { $lte: dateRange.end } },
2710
3183
  { moduleType: { $eq: inputData.moduleType } },
3184
+ { clientId: { $in: inputData.clientId } },
2711
3185
  ];
2712
- if ( inputData.clientId.length > 0 ) {
2713
- filters.push( { clientId: { $in: inputData.clientId } } );
2714
- }
3186
+
2715
3187
  const query =[
2716
3188
  {
2717
3189
  $match: {
@@ -2822,13 +3294,10 @@ export async function overviewTable( req, res ) {
2822
3294
  { fileDateISO: { $gte: dateRange.start } },
2823
3295
  { fileDateISO: { $lte: dateRange.end } },
2824
3296
  { moduleType: { $eq: inputData.moduleType } },
3297
+ { clientId: { $in: inputData.clientId } },
2825
3298
 
2826
3299
  ];
2827
3300
 
2828
- if ( inputData.clientId.length > 0 ) {
2829
- filters.push( { clientId: { $in: inputData.clientId } } );
2830
- }
2831
-
2832
3301
  if ( inputData.filterByAuditType.length > 0 ) {
2833
3302
  filters.push( { auditType: { $in: inputData.filterByAuditType } } );
2834
3303
  }
@@ -2986,16 +3455,16 @@ export async function overviewTable( req, res ) {
2986
3455
  switch ( inputData.moduleType ) {
2987
3456
  case 'camera-angle-change':
2988
3457
  temp['stream Name'] = element.streamName;
2989
- temp['User Comments'] = element.userCommands;
3458
+ temp['User Comments'] = element.userComments;
2990
3459
  break;
2991
3460
  case 'unattended-customer':
2992
3461
  temp['Customer ID'] = element.tempId;
2993
3462
  temp['Question'] = element.question;
2994
- temp['User Comments'] = element.userCommands;
3463
+ temp['User Comments'] = element.userComments;
2995
3464
  break;
2996
3465
  case 'left-in-middle':
2997
3466
  temp['Question'] = element.question;
2998
- temp['User Comments'] = element.userCommands;
3467
+ temp['User Comments'] = element.userComments;
2999
3468
  break;
3000
3469
  case 'mobile-detection':
3001
3470
  temp['Before Count'] = element.beforeCount;