tango-app-api-trax 3.9.32 → 3.9.33

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.
Files changed (53) hide show
  1. package/index.js +1 -2
  2. package/package.json +2 -2
  3. package/src/controllers/gallery.controller.js +0 -2
  4. package/src/controllers/internalTrax.controller.js +78 -117
  5. package/src/controllers/mobileTrax.controller.js +29 -69
  6. package/src/controllers/teaxFlag.controller.js +5 -5
  7. package/src/controllers/trax.controller.js +3 -4
  8. package/src/controllers/traxDashboard.controllers.js +54 -63
  9. package/src/hbs/flag.hbs +1 -1
  10. package/src/hbs/login-otp.hbs +943 -943
  11. package/src/hbs/template.hbs +0 -7
  12. package/src/hbs/visit-checklist.hbs +1 -51
  13. package/src/services/app.service.js +14 -20
  14. package/src/services/approver.service.js +20 -28
  15. package/src/services/authentication.service.js +6 -12
  16. package/src/services/camera.service.js +18 -24
  17. package/src/services/checklist.service.js +31 -36
  18. package/src/services/checklistAssign.service.js +39 -44
  19. package/src/services/checklistQuestion.service.js +35 -40
  20. package/src/services/checklistlog.service.js +35 -40
  21. package/src/services/clientRequest.service.js +5 -12
  22. package/src/services/clients.services.js +18 -23
  23. package/src/services/cluster.service.js +28 -36
  24. package/src/services/domain.service.js +28 -33
  25. package/src/services/download.services.js +38 -48
  26. package/src/services/group.service.js +22 -28
  27. package/src/services/lenskartEmployeeMapping.service.js +15 -20
  28. package/src/services/locus.service.js +34 -41
  29. package/src/services/notification.service.js +31 -40
  30. package/src/services/otp.service.js +17 -24
  31. package/src/services/planogram.service.js +5 -12
  32. package/src/services/processedTaskConfig.service.js +32 -40
  33. package/src/services/processedTaskList.service.js +30 -36
  34. package/src/services/processedchecklist.services.js +48 -56
  35. package/src/services/processedchecklistconfig.services.js +35 -40
  36. package/src/services/recurringFlagTracker.service.js +33 -40
  37. package/src/services/runAIFeatures.services.js +31 -36
  38. package/src/services/runAIRequest.services.js +39 -44
  39. package/src/services/store.service.js +31 -36
  40. package/src/services/tagging.service.js +5 -12
  41. package/src/services/taskConfig.service.js +32 -40
  42. package/src/services/teams.service.js +30 -41
  43. package/src/services/ticket.service.js +15 -20
  44. package/src/services/user.service.js +25 -32
  45. package/src/services/userAssignedstores.service.js +10 -17
  46. package/src/utils/visitChecklistPdf.utils.js +11 -114
  47. package/src/logging/activityLogFlusher.js +0 -59
  48. package/src/logging/activityLogMiddleware.js +0 -45
  49. package/src/logging/activityLogStore.js +0 -91
  50. package/src/logging/compressBatches.js +0 -83
  51. package/src/logging/config.js +0 -24
  52. package/src/logging/createLoggableService.js +0 -46
  53. package/src/logging/logExternalCall.js +0 -37
package/index.js CHANGED
@@ -9,6 +9,5 @@ import { mobileRouter } from './src/routes/mobileTrax.routes.js';
9
9
  import { internalTraxRouter } from './src/routes/internalTraxApi.router.js';
10
10
  import { locusOrderRouter } from './src/routes/locus.router.js';
11
11
  import { traxActivityLogRouter } from './src/routes/activityLog.router.js';
12
- import traxActivityLogMiddleware from './src/logging/activityLogMiddleware.js';
13
12
 
14
- export { traxDashboardRouter, traxFlagRouter, traxRouter, galleryRouter, downloadRouter, mobileRouter, internalTraxRouter, locusOrderRouter, traxActivityLogRouter, traxActivityLogMiddleware };
13
+ export { traxDashboardRouter, traxFlagRouter, traxRouter, galleryRouter, downloadRouter, mobileRouter, internalTraxRouter, locusOrderRouter, traxActivityLogRouter };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tango-app-api-trax",
3
- "version": "3.9.32",
3
+ "version": "3.9.33",
4
4
  "description": "Trax",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -30,7 +30,7 @@
30
30
  "path": "^0.12.7",
31
31
  "puppeteer": "^24.39.1",
32
32
  "swagger-ui-express": "^5.0.1",
33
- "tango-api-schema": "^2.6.15",
33
+ "tango-api-schema": "^2.6.17",
34
34
  "tango-app-api-middleware": "^3.5.2",
35
35
  "url": "^0.11.4",
36
36
  "winston": "^3.13.1",
@@ -271,7 +271,6 @@ export const checklistDropdown = async ( req, res ) => {
271
271
  if ( !getTotalCount.length ) {
272
272
  return res.sendError( { error: 'No Data Found' }, 204 );
273
273
  }
274
-
275
274
  if ( requestData.sortColumnName && requestData.sortColumnName != '' && requestData.sortBy && requestData.sortBy != '' ) {
276
275
  findQuery.push( { $sort: { [requestData.sortColumnName]: requestData.sortBy } } );
277
276
  } else {
@@ -279,7 +278,6 @@ export const checklistDropdown = async ( req, res ) => {
279
278
  }
280
279
 
281
280
  let getChecklistData = await processedchecklistconfigService.aggregate( findQuery );
282
-
283
281
  let AiCheklist = getChecklistData.filter( ( data ) => data.checkListType != 'custom' );
284
282
  let CustomCheklist = getChecklistData.filter( ( data ) => data.checkListType == 'custom' );
285
283
 
@@ -624,7 +624,6 @@ export async function PCLconfigCreation( req, res ) {
624
624
  element4.rawImageUpload = getCLconfig?.rawImageUpload || false;
625
625
  element4.rawVideoUpload = getCLconfig?.rawVideoUpload || false;
626
626
  element4.videoUploadTimeLimit = getCLconfig?.videoUploadTimeLimit || 0;
627
- element4.userVerification = getCLconfig?.userVerification;
628
627
  }
629
628
  if ( userIdList.length ) {
630
629
  allQuestion = allQuestion.filter( ( item ) => typeof item._id == 'undefined' );
@@ -931,7 +930,7 @@ async function insertData( requestData ) {
931
930
  },
932
931
  } );
933
932
  let getSections = await CLquestions.aggregate( sectionQuery );
934
- if ( getSections.length || [ 'storeopenandclose', 'mobileusagedetection', 'uniformdetection', 'customerunattended', 'staffleftinthemiddle', 'eyetest', 'remoteoptometrist', 'storehygienemonitoring', 'cleaning', 'scrum', 'suspiciousactivity', 'suspiciousfootfall', 'drinking', 'bagdetection', 'inventorycount', 'carsattended', 'numberplateinfo', 'vehicle_check_in', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'unattendeddetection' ].includes( getCLconfig.checkListType ) ) {
933
+ if ( getSections.length || [ 'storeopenandclose', 'mobileusagedetection', 'uniformdetection', 'customerunattended', 'staffleftinthemiddle', 'eyetest', 'remoteoptometrist', 'storehygienemonitoring', 'cleaning', 'scrum', 'suspiciousactivity', 'suspiciousfootfall', 'drinking', 'bagdetection', 'inventorycount', 'carsattended', 'numberplateinfo', 'vehicle_check_in', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'unattendeddetection', 'employeemonitoring' ].includes( getCLconfig.checkListType ) ) {
935
934
  if ( getSections.length ) {
936
935
  for ( let element3 of getSections ) {
937
936
  let collectQuestions = {};
@@ -1226,11 +1225,11 @@ async function insertData( requestData ) {
1226
1225
  // }
1227
1226
  }
1228
1227
  } else {
1229
- if ( [ 'storeopenandclose', 'mobileusagedetection', 'uniformdetection', 'customerunattended', 'staffleftinthemiddle', 'eyetest', 'remoteoptometrist', 'storehygienemonitoring', 'cleaning', 'scrum', 'suspiciousactivity', 'suspiciousfootfall', 'drinking', 'bagdetection', 'inventorycount', 'carsattended', 'numberplateinfo', 'vehicle_check_in', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'unattendeddetection' ].includes( getCLconfig.checkListType ) ) {
1228
+ if ( [ 'storeopenandclose', 'mobileusagedetection', 'uniformdetection', 'customerunattended', 'staffleftinthemiddle', 'eyetest', 'remoteoptometrist', 'storehygienemonitoring', 'cleaning', 'scrum', 'suspiciousactivity', 'suspiciousfootfall', 'drinking', 'bagdetection', 'inventorycount', 'carsattended', 'numberplateinfo', 'vehicle_check_in', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'unattendeddetection', 'employeemonitoring' ].includes( getCLconfig.checkListType ) ) {
1230
1229
  let storeNameList = allQuestion.map( ( item ) => item.store_id );
1231
- let storeDetails = await storeService.find( { clientId: getCLconfig.client_id, status: 'active', ...( [ 'storeopenandclose', 'mobileusagedetection', 'uniformdetection', 'customerunattended', 'staffleftinthemiddle', 'scrum', 'cleaning', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'unattendeddetection' ].includes( getCLconfig.checkListType ) ) ? { storeId: { $in: storeNameList } } : {} }, { storeId: 1 } );
1230
+ let storeDetails = await storeService.find( { clientId: getCLconfig.client_id, status: 'active', ...( [ 'storeopenandclose', 'mobileusagedetection', 'uniformdetection', 'customerunattended', 'staffleftinthemiddle', 'scrum', 'cleaning', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'unattendeddetection', 'employeemonitoring' ].includes( getCLconfig.checkListType ) ) ? { storeId: { $in: storeNameList } } : {} }, { storeId: 1 } );
1232
1231
  let storeList = storeDetails.map( ( store ) => store.storeId );
1233
- if ( [ 'storeopenandclose', 'mobileusagedetection', 'uniformdetection', 'customerunattended', 'staffleftinthemiddle', 'scrum', 'cleaning', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'unattendeddetection' ].includes( getCLconfig.checkListType ) ) {
1232
+ if ( [ 'storeopenandclose', 'mobileusagedetection', 'uniformdetection', 'customerunattended', 'staffleftinthemiddle', 'scrum', 'cleaning', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'unattendeddetection', 'employeemonitoring' ].includes( getCLconfig.checkListType ) ) {
1234
1233
  allQuestion = allQuestion.filter( ( ele ) => storeList.includes( ele?.store_id ) );
1235
1234
  } else {
1236
1235
  allQuestion = storeDetails.map( ( item ) => {
@@ -1264,7 +1263,7 @@ async function insertData( requestData ) {
1264
1263
  client_id: getCLconfig.client_id,
1265
1264
  aiStoreList: allQuestion.length ? allQuestion.map( ( store ) => store.store_id ) : [],
1266
1265
  };
1267
- if ( [ 'storeopenandclose', 'mobileusagedetection', 'uniformdetection', 'customerunattended', 'staffleftinthemiddle', 'scrum', 'cleaning', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'unattendeddetection' ].includes( getCLconfig.checkListType ) ) {
1266
+ if ( [ 'storeopenandclose', 'mobileusagedetection', 'uniformdetection', 'customerunattended', 'staffleftinthemiddle', 'scrum', 'cleaning', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'unattendeddetection', 'employeemonitoring' ].includes( getCLconfig.checkListType ) ) {
1268
1267
  let processData = {
1269
1268
  aiStoreList: allQuestion.length ? allQuestion.map( ( store ) => {
1270
1269
  return { storeName: store.storeName, storeId: store.store_id, events: store.events };
@@ -1384,40 +1383,40 @@ export async function insertTimeDelayFlags( req, res ) {
1384
1383
  let updatedDetails = await processedchecklist.updateMany( { _id: { $in: checklistId } }, { timeFlag: 1 } );
1385
1384
 
1386
1385
 
1387
- // let notifyStores = await processedchecklist.find( { _id: { $in: checklistId }, notify: { $exists: false } } );
1388
-
1389
- // if ( notifyStores.length ) {
1390
- // Promise.all( notifyStores.map( async ( store ) => {
1391
- // let checklistDetails = await CLconfig.findOne( { _id: store.sourceCheckList_id }, { notifyFlags: 1, approver: 1 } );
1392
- // if ( checklistDetails?.notifyFlags?.notifyType?.length ) {
1393
- // let emailList = checklistDetails?.notifyFlags?.notifyType.includes( 'approver' ) ? checklistDetails.approver.map( ( ele ) => ele?.value ): [];
1394
- // emailList = [ ...emailList, ...checklistDetails?.notifyFlags?.users?.map( ( ele ) => ele?.value ) ];
1395
- // let data = {
1396
- // storeName: store.storeName,
1397
- // flagCount: 1,
1398
- // checklistName: store.checkListName?.trim(),
1399
- // submittedBy: '--',
1400
- // time: '--',
1401
- // domain: `${JSON.parse( process.env.URL ).domain}/manage/trax/flags?date=${dayjs().format( 'YYYY-MM-DD' )}`,
1402
- // type: 'delay',
1403
- // };
1404
- // const fileContent = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/flag.hbs', 'utf8' );
1405
- // const htmlContent = handlebars.compile( fileContent );
1406
- // const html = htmlContent( { data: data } );
1407
- // emailList.forEach( ( email ) => {
1408
- // let params = {
1409
- // toEmail: email,
1410
- // mailSubject: 'TangoEye | Checklist Flag',
1411
- // htmlBody: html,
1412
- // attachment: '',
1413
- // sourceEmail: JSON.parse( process.env.SES ).adminEmail,
1414
- // };
1415
- // sendEmailWithSES( params.toEmail, params.mailSubject, params.htmlBody, params.attachment, params.sourceEmail );
1416
- // } );
1417
- // }
1418
- // await processedchecklist.updateOne( { _id: store._id }, { notify: true } );
1419
- // } ) );
1420
- // }
1386
+ let notifyStores = await processedchecklist.find( { _id: { $in: checklistId }, notify: { $exists: false } } );
1387
+
1388
+ if ( notifyStores.length ) {
1389
+ Promise.all( notifyStores.map( async ( store ) => {
1390
+ let checklistDetails = await CLconfig.findOne( { _id: store.sourceCheckList_id }, { notifyFlags: 1, approver: 1 } );
1391
+ if ( checklistDetails?.notifyFlags?.notifyType?.length ) {
1392
+ let emailList = checklistDetails?.notifyFlags?.notifyType.includes( 'approver' ) ? checklistDetails.approver.map( ( ele ) => ele?.value ): [];
1393
+ emailList = [ ...emailList, ...checklistDetails?.notifyFlags?.users?.map( ( ele ) => ele?.value ) ];
1394
+ let data = {
1395
+ storeName: store.storeName,
1396
+ flagCount: 1,
1397
+ checklistName: store.checkListName?.trim(),
1398
+ submittedBy: '--',
1399
+ time: '--',
1400
+ domain: `${JSON.parse( process.env.URL ).domain}/manage/trax/flags?date=${dayjs().format( 'YYYY-MM-DD' )}`,
1401
+ type: 'delay',
1402
+ };
1403
+ const fileContent = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/flag.hbs', 'utf8' );
1404
+ const htmlContent = handlebars.compile( fileContent );
1405
+ const html = htmlContent( { data: data } );
1406
+ emailList.forEach( ( email ) => {
1407
+ let params = {
1408
+ toEmail: email,
1409
+ mailSubject: 'TangoEye | Checklist Flag',
1410
+ htmlBody: html,
1411
+ attachment: '',
1412
+ sourceEmail: JSON.parse( process.env.SES ).adminEmail,
1413
+ };
1414
+ sendEmailWithSES( params.toEmail, params.mailSubject, params.htmlBody, params.attachment, params.sourceEmail );
1415
+ } );
1416
+ }
1417
+ await processedchecklist.updateOne( { _id: store._id }, { notify: true } );
1418
+ } ) );
1419
+ }
1421
1420
 
1422
1421
  if ( updatedDetails ) {
1423
1422
  return res.sendSuccess( { message: 'Time Delay Updated Successfully' } );
@@ -2701,57 +2700,10 @@ export async function countUpdateRunAI( req, res ) {
2701
2700
  runAIFlag: req.body.runAICount,
2702
2701
  };
2703
2702
 
2704
- // complianceCount is already populated for the other answer types; add the image/video scores on top.
2705
- let complianceCount = getDetails.userComplianceCount || 0;
2706
-
2707
- // Pull every "Matched/Not Matched" verdict out of a runAIData array, tolerating both shapes we store:
2708
- // 1) [ { answerImage, results: [ { featureName, value } ] } ] (verdict nested under results)
2709
- // 2) [ { featureName, value } ] (flat verdict)
2710
- const extractMatchValues = ( runAIData ) => {
2711
- if ( !Array.isArray( runAIData ) ) return [];
2712
- const values = [];
2713
- runAIData.forEach( ( entry ) => {
2714
- const results = Array.isArray( entry?.results ) ? entry.results : [ entry ];
2715
- results.forEach( ( r ) => {
2716
- if ( r?.featureName === 'Matched/Not Matched' ) values.push( r?.value );
2717
- } );
2718
- } );
2719
- return values;
2720
- };
2721
-
2722
- getDetails.questionAnswers.forEach( ( section ) => {
2723
- section.questions.forEach( ( question ) => {
2724
- if ( question.compliance && [ 'image', 'image/video' ].includes( question.answerType ) ) {
2725
- // For 'image/video' each userAnswer carries its own answerType and runAIData only lives on
2726
- // the image entries; a pure 'image' question keeps runAIData directly on every userAnswer.
2727
- const aiAnswers = question.answerType === 'image/video' ?
2728
- ( question.userAnswer || [] ).filter( ( ua ) => ua?.answerType === 'image' ) :
2729
- ( question.userAnswer || [] );
2730
-
2731
- // Compliance comes from the first configured answer: every "Matched/Not Matched" verdict
2732
- // across the image answers must be True to count as matched, otherwise it's not matched.
2733
- const matchValues = aiAnswers.flatMap( ( ua ) => extractMatchValues( ua?.runAIData ) );
2734
- const allMatched = matchValues.length > 0 && matchValues.every( ( v ) => v === 'True' || v === true );
2735
- const score = allMatched ?
2736
- ( question.answers?.[0]?.matchedCount ?? 0 ) :
2737
- ( question.answers?.[0]?.notMatchedCount ?? 0 );
2738
-
2739
- // Persist the derived score back onto each userAnswer so PDF/dashboard reads stay consistent.
2740
- ( question.userAnswer || [] ).forEach( ( ua ) => {
2741
- ua.complianceScore = score;
2742
- } );
2743
-
2744
- complianceCount += score;
2745
- }
2746
- } );
2747
- } );
2748
-
2749
- updateData.complianceCount = complianceCount;
2750
-
2751
2703
  await processedchecklist.updateOne( { _id: req.body.id }, updateData );
2752
2704
  return res.sendSuccess( 'RunAI Count updated successfully' );
2753
2705
  } catch ( e ) {
2754
- logger.error( { functionName: 'countUpdateRunAI', error: e } );
2706
+ logger.error( { functionName: 'updateRunAI', error: e } );
2755
2707
  return res.sendError( e, 500 );
2756
2708
  }
2757
2709
  }
@@ -3588,38 +3540,47 @@ export async function runAIFlag( req, res ) {
3588
3540
  ],
3589
3541
  },
3590
3542
  }, { _id: 1, notifyFlags: 1, approver: 1 } );
3591
- let date = dayjs().format( 'YYYY-MM-DD' );
3543
+ let date = dayjs().subtract( 1, 'day' ).format( 'YYYY-MM-DD' );
3592
3544
  if ( checklistDetails.length ) {
3593
3545
  await Promise.all( checklistDetails.map( async ( ele ) => {
3594
- let submitDetails = await processedchecklist.find( { sourceCheckList_id: ele._id, date_string: date, $or: [ { timeFlag: { $gt: 0 } }, { questionFlag: { $gt: 0 } }, { runAIFlag: { $gt: 0 } } ] }, { storeName: 1, checkListName: 1, userName: 1, submitTime_string: 1, runAIFlag: 1, questionFlag: 1, checklistStatus: 1 } );
3595
- let emailList = ele?.notifyFlags?.notifyType.includes( 'approver' ) ? ele.approver.map( ( approver ) => approver?.value ): [];
3596
- emailList = [ ...emailList, ...ele?.notifyFlags?.users?.map( ( user ) => user?.value ) ];
3546
+ let submitDetails = await processedchecklist.find( { sourceCheckList_id: ele._id, checklistStatus: 'submit', date_string: date }, { storeName: 1, checkListName: 1, questionAnswers: 1 } );
3597
3547
  await Promise.all( submitDetails.map( ( store ) => {
3598
- let data = {
3599
- storeName: store.storeName,
3600
- flagCount: store.timeFlag ? 1 : store?.runAIFlag + store?.questionFlag,
3601
- runAIFlag: store?.runAIFlag,
3602
- questionFlag: store?.questionFlag,
3603
- checklistName: store.checkListName?.trim(),
3604
- submittedBy: store?.userName,
3605
- time: store?.submitTime_string ?? '--',
3606
- domain: `${JSON.parse( process.env.URL ).domain}/manage/trax/flags?date=${dayjs().format( 'YYYY-MM-DD' )}`,
3607
- status: store.checklistStatus,
3608
- };
3609
- const fileContent = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/flag.hbs', 'utf8' );
3610
- const htmlContent = handlebars.compile( fileContent );
3611
- const html = htmlContent( { data: data } );
3612
- emailList.forEach( ( email ) => {
3613
- console.log( email );
3614
- let params = {
3615
- toEmail: email,
3616
- mailSubject: 'TangoEye | Checklist Flag',
3617
- htmlBody: html,
3618
- attachment: '',
3619
- sourceEmail: JSON.parse( process.env.SES ).adminEmail,
3620
- };
3621
- sendEmailWithSES( params.toEmail, params.mailSubject, params.htmlBody, params.attachment, params.sourceEmail );
3622
- } );
3548
+ if ( store.questionAnswers.length ) {
3549
+ let runAIFlag = 0;
3550
+ store.questionAnswers.forEach( ( section ) => {
3551
+ section.questions.forEach( ( question ) => {
3552
+ if ( question.answerType == 'image' && ( question?.userAnswer?.[0]?.runAIData?.value == 'False' || !question?.userAnswer?.[0]?.runAIData?.value ) ) {
3553
+ runAIFlag++;
3554
+ }
3555
+ } );
3556
+ } );
3557
+ if ( runAIFlag ) {
3558
+ let emailList = ele?.notifyFlags?.notifyType.includes( 'approver' ) ? ele.approver.map( ( approver ) => approver?.value ): [];
3559
+ emailList = [ ...emailList, ...ele?.notifyFlags?.users?.map( ( user ) => user?.value ) ];
3560
+ let data = {
3561
+ storeName: store.storeName,
3562
+ flagCount: 1,
3563
+ checklistName: store.checkListName?.trim(),
3564
+ submittedBy: '--',
3565
+ time: '--',
3566
+ domain: `${JSON.parse( process.env.URL ).domain}/manage/trax/flags?date=${dayjs().format( 'YYYY-MM-DD' )}`,
3567
+ type: 'delay',
3568
+ };
3569
+ const fileContent = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/flag.hbs', 'utf8' );
3570
+ const htmlContent = handlebars.compile( fileContent );
3571
+ const html = htmlContent( { data: data } );
3572
+ emailList.forEach( ( email ) => {
3573
+ let params = {
3574
+ toEmail: email,
3575
+ mailSubject: 'TangoEye | Checklist Flag',
3576
+ htmlBody: html,
3577
+ attachment: '',
3578
+ sourceEmail: JSON.parse( process.env.SES ).adminEmail,
3579
+ };
3580
+ sendEmailWithSES( params.toEmail, params.mailSubject, params.htmlBody, params.attachment, params.sourceEmail );
3581
+ } );
3582
+ }
3583
+ }
3623
3584
  } ) );
3624
3585
  } ) );
3625
3586
  }
@@ -1765,7 +1765,6 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
1765
1765
  } else {
1766
1766
  if ( qaans[k].validationType == 'Capture Multiple Image with description' ) {
1767
1767
  qaans[k]['validationImage']=[];
1768
- qaans[k]['validationVideo']=[];
1769
1768
  if ( requestSection[i].validationImage.length ) {
1770
1769
  for ( let image of requestSection[i].validationImage ) {
1771
1770
  let validationAnswer = decodeURIComponent( image.split( '?' )[0] );
@@ -1778,18 +1777,6 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
1778
1777
  };
1779
1778
  }
1780
1779
  }
1781
- if ( requestSection[i]?.validationVideo?.length ) {
1782
- for ( let video of requestSection[i].validationVideo ) {
1783
- let validationAnswer = decodeURIComponent( video.split( '?' )[0] );
1784
- if ( validationAnswer.length ) {
1785
- let splitImgUrl = validationAnswer.split( '/' );
1786
- if ( splitImgUrl.length > 1 ) {
1787
- splitImgUrl.splice( 0, 3 );
1788
- qaans[k].validationVideo.push( splitImgUrl.join( '/' ) || '' );
1789
- }
1790
- };
1791
- }
1792
- }
1793
1780
  }
1794
1781
  // qaans[k].descriptivetype = qaAnswers[j].descriptivetype || '';
1795
1782
  qaans[k].validationAnswer = requestSection[i].validationAnswer || '';
@@ -2140,18 +2127,12 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
2140
2127
  logger.error( { message: requestData.questionAnswers, error: 'QuestionanswersPayload' } );
2141
2128
 
2142
2129
  if ( requestData.submittype == 'submit' ) {
2143
- requestData.userComplianceCount = 0;
2144
2130
  for ( let section of sectionFormat ) {
2145
2131
  for ( let question of section.questions ) {
2146
2132
  let mustValidate = !question.linkType || ( question.linkType && question.linkquestionenabled );
2147
2133
  if ( mustValidate && ( !question.userAnswer || !question.userAnswer.length ) ) {
2148
2134
  return res.sendError( 'Please Fill All Fields', 400 );
2149
2135
  }
2150
- if ( question.compliance ) {
2151
- const scores = ( question.userAnswer || [] ).map( ( ua ) => ua?.complianceScore ?? 0 );
2152
- let score = scores.length ? Math.max( ...scores ) : 0;
2153
- requestData.userComplianceCount += score;
2154
- }
2155
2136
  }
2156
2137
  }
2157
2138
  }
@@ -2795,15 +2776,6 @@ export async function submitChecklist( req, res ) {
2795
2776
  updateData.checklistStatus = 'submit';
2796
2777
  updateData.updatedAt = dayjs.utc( currentDateTime.format( 'hh:mm:ss A, DD MMM YYYY' ), 'hh:mm:ss A, DD MMM YYYY' ).format();
2797
2778
  updateData.submitMobileTime = requestData?.currentTime;
2798
- updateData.userComplianceCount = requestData?.userComplianceCount;
2799
- updateData.userSignature = requestData?.userSignature;
2800
- if ( requestData?.userImage ) {
2801
- let splitImgUrl = requestData?.userImage.split( '/' );
2802
- if ( splitImgUrl.length > 1 ) {
2803
- splitImgUrl.splice( 0, 3 );
2804
- updateData.userImage = splitImgUrl.join( '/' ) || '';
2805
- }
2806
- }
2807
2779
  }
2808
2780
  // updateData.questionAnswers.forEach( ( section ) => {
2809
2781
  // section.questions.forEach( ( question ) => {
@@ -2904,34 +2876,34 @@ export async function submitChecklist( req, res ) {
2904
2876
  userType: req.user.userType,
2905
2877
  };
2906
2878
  insertOpenSearchData( openSearch.traxActivityLog, inserttraxlogs );
2907
- // if ( updateData.questionFlag ) {
2908
- // let checklistDetails = await checklistService.findOne( { _id: getchecklist[0].sourceCheckList_id }, { notifyFlags: 1, approver: 1 } );
2909
- // if ( checklistDetails?.notifyFlags?.notifyType?.length ) {
2910
- // let emailList = checklistDetails?.notifyFlags?.notifyType.includes( 'approver' ) ? checklistDetails.approver.map( ( ele ) => ele?.value ): [];
2911
- // emailList = [ ...emailList, ...checklistDetails?.notifyFlags?.users?.map( ( ele ) => ele?.value ) ];
2912
- // let data = {
2913
- // storeName: getchecklist[0].storeName,
2914
- // flagCount: updateData.questionFlag,
2915
- // checklistName: getchecklist[0].checkListName,
2916
- // submittedBy: getchecklist[0].userName,
2917
- // time: updateData.submitTime_string,
2918
- // domain: `${JSON.parse( process.env.URL ).domain}/manage/trax/flags?date=${dayjs().format( 'YYYY-MM-DD' )}`,
2919
- // };
2920
- // const fileContent = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/flag.hbs', 'utf8' );
2921
- // const htmlContent = handlebars.compile( fileContent );
2922
- // const html = htmlContent( { data: data } );
2923
- // emailList.forEach( ( email ) => {
2924
- // let params = {
2925
- // toEmail: email,
2926
- // mailSubject: 'TangoEye | Checklist Flag',
2927
- // htmlBody: html,
2928
- // attachment: '',
2929
- // sourceEmail: JSON.parse( process.env.SES ).adminEmail,
2930
- // };
2931
- // sendEmailWithSES( params.toEmail, params.mailSubject, params.htmlBody, params.attachment, params.sourceEmail );
2932
- // } );
2933
- // }
2934
- // }
2879
+ if ( updateData.questionFlag ) {
2880
+ let checklistDetails = await checklistService.findOne( { _id: getchecklist[0].sourceCheckList_id }, { notifyFlags: 1, approver: 1 } );
2881
+ if ( checklistDetails?.notifyFlags?.notifyType?.length ) {
2882
+ let emailList = checklistDetails?.notifyFlags?.notifyType.includes( 'approver' ) ? checklistDetails.approver.map( ( ele ) => ele?.value ): [];
2883
+ emailList = [ ...emailList, ...checklistDetails?.notifyFlags?.users?.map( ( ele ) => ele?.value ) ];
2884
+ let data = {
2885
+ storeName: getchecklist[0].storeName,
2886
+ flagCount: updateData.questionFlag,
2887
+ checklistName: getchecklist[0].checkListName,
2888
+ submittedBy: getchecklist[0].userName,
2889
+ time: updateData.submitTime_string,
2890
+ domain: `${JSON.parse( process.env.URL ).domain}/manage/trax/flags?date=${dayjs().format( 'YYYY-MM-DD' )}`,
2891
+ };
2892
+ const fileContent = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/flag.hbs', 'utf8' );
2893
+ const htmlContent = handlebars.compile( fileContent );
2894
+ const html = htmlContent( { data: data } );
2895
+ emailList.forEach( ( email ) => {
2896
+ let params = {
2897
+ toEmail: email,
2898
+ mailSubject: 'TangoEye | Checklist Flag',
2899
+ htmlBody: html,
2900
+ attachment: '',
2901
+ sourceEmail: JSON.parse( process.env.SES ).adminEmail,
2902
+ };
2903
+ sendEmailWithSES( params.toEmail, params.mailSubject, params.htmlBody, params.attachment, params.sourceEmail );
2904
+ } );
2905
+ }
2906
+ }
2935
2907
  }
2936
2908
  if ( getchecklist?.[0]?.redoEdit?.toString() != requestData?.redoEdit ) {
2937
2909
  return res.sendSuccess( 'New Questions Added So,Checklist moved back to In Progress. Please complete the updated checklist.' );
@@ -4205,9 +4177,6 @@ export async function questionList( req, res ) {
4205
4177
  streamId: { $ifNull: [ '$streamId', '' ] },
4206
4178
  export: { $ifNull: [ '$export', false ] },
4207
4179
  redoEdit: 1,
4208
- userVerification: 1,
4209
- userSignature: 1,
4210
- userImage: 1,
4211
4180
  },
4212
4181
  } );
4213
4182
 
@@ -4218,7 +4187,6 @@ export async function questionList( req, res ) {
4218
4187
  logger.info( `v5 => Checklist Continue => store Name: ${getchecklist[0].storeName}, User Email: ${getchecklist[0].userEmail}, Checklist Name: ${getchecklist[0].checkListName}` );
4219
4188
  // let bucket = JSON.parse( process.env.BUCKET );
4220
4189
  let cdnurl = JSON.parse( process.env.CDNURL );
4221
- getchecklist[0].userImage = `${cdnurl}/${getchecklist[0].userImage}`;
4222
4190
  for ( let [ secIndex, section ] of getchecklist[0].questionAnswers.entries() ) {
4223
4191
  for ( let [ questionIndex, question ] of section.questions.entries() ) {
4224
4192
  let Multianswer = [];
@@ -4274,15 +4242,10 @@ export async function questionList( req, res ) {
4274
4242
  }
4275
4243
  if ( userAns.validationType == 'Capture Multiple Image with description' ) {
4276
4244
  let imageAnswers = userAns.validationImage;
4277
- getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].validationImage = [];
4245
+ userAns.validationImage = [];
4278
4246
  for ( let image of imageAnswers ) {
4279
4247
  getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].validationImage.push( `${cdnurl.TraxAnswerCDN}${image}` );
4280
4248
  }
4281
- let videoAnswer = userAns.validationVideo;
4282
- getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].validationVideo = [];
4283
- for ( let image of videoAnswer ) {
4284
- getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].validationVideo.push( `${cdnurl.TraxAnswerCDN}${image}` );
4285
- }
4286
4249
  }
4287
4250
  if ( [ 'image', 'descriptiveImage', 'video' ].includes( question.answerType ) && userAns.answer != '' ) {
4288
4251
  getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].answer =`${cdnurl.TraxAnswerCDN}${userAns.answer}`;
@@ -5527,9 +5490,6 @@ export async function downloadChecklist( req, res ) {
5527
5490
  if ( [ 'Capture Multiple Image with description' ].includes( answer.validationType ) && answer?.validationImage?.length ) {
5528
5491
  answer.validationImage = answer?.validationImage?.map( ( ele ) => JSON.parse( process.env.CDNURL )?.TraxAnswerCDN+ele );
5529
5492
  }
5530
- if ( [ 'Capture Multiple Image with description' ].includes( answer.validationType ) && answer?.validationVideo?.length ) {
5531
- answer.validationVideo = answer?.validationVideo?.map( ( ele ) => JSON.parse( process.env.CDNURL )?.TraxAnswerCDN+ele );
5532
- }
5533
5493
  if ( answer?.answer?.trim() && [ 'image', 'descriptiveImage', 'multipleImage', 'image/video', 'video' ].includes( question.answerType ) ) {
5534
5494
  answer.answer = JSON.parse( process.env.CDNURL )?.TraxAnswerCDN+answer.answer;
5535
5495
  }
@@ -608,7 +608,7 @@ export const flagCardsV1 = async ( req, res ) => {
608
608
  {
609
609
  client_id: clientId,
610
610
  publish: true,
611
- checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring', 'unattendeddetection' ] },
611
+ checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring', 'unattendeddetection', 'employeemonitoring' ] },
612
612
  },
613
613
  { checkListType: 1 },
614
614
  );
@@ -2747,7 +2747,7 @@ export const checklistDropdownV1 = async ( req, res ) => {
2747
2747
  $or: [
2748
2748
  { questionFlag: { $gte: 1 } },
2749
2749
  { timeFlag: { $gte: 1 } },
2750
- { checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring', 'unattendeddetection', 'vehicle_check_in' ] } },
2750
+ { checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring', 'unattendeddetection', 'vehicle_check_in', 'employeemonitoring' ] } },
2751
2751
  {
2752
2752
  runAIQuestionCount: { $gte: 1 },
2753
2753
  },
@@ -2949,7 +2949,7 @@ export const flagComparisonCardsV2 = async ( req, res ) => {
2949
2949
  {
2950
2950
  client_id: requestData.clientId,
2951
2951
  publish: true,
2952
- checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring', 'unattendeddetection' ] },
2952
+ checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring', 'unattendeddetection', 'employeemonitoring' ] },
2953
2953
  },
2954
2954
  { checkListType: 1 },
2955
2955
  );
@@ -3051,7 +3051,7 @@ export const flagTablesV2 = async ( req, res ) => {
3051
3051
  }
3052
3052
 
3053
3053
  if ( requestData?.filter === 'all' ) {
3054
- findAndQuery.push( { $or: [ { checkListType: { $in: [ 'custom', 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring', 'unattendeddetection', 'vehicle_check_in' ] } } ] } );
3054
+ findAndQuery.push( { $or: [ { checkListType: { $in: [ 'custom', 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring', 'unattendeddetection', 'vehicle_check_in', 'employeemonitoring' ] } } ] } );
3055
3055
  } else if ( requestData?.filter === 'question' ) {
3056
3056
  findAndQuery.push( { checkListType: 'custom' } );
3057
3057
  findAndQuery.push( { questionFlag: { $gte: 1 } } );
@@ -3059,7 +3059,7 @@ export const flagTablesV2 = async ( req, res ) => {
3059
3059
  findAndQuery.push( { checkListType: 'custom' } );
3060
3060
  findAndQuery.push( { timeFlag: { $gte: 1 } } );
3061
3061
  } else if ( requestData?.filter === 'detection' ) {
3062
- findAndQuery.push( { checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring', 'unattendeddetection', 'vehicle_check_in' ] } } );
3062
+ findAndQuery.push( { checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring', 'unattendeddetection', 'vehicle_check_in', 'employeemonitoring' ] } } );
3063
3063
  } else if ( requestData?.filter === 'runAI' ) {
3064
3064
  if ( req.body.runAIChecklistName ) {
3065
3065
  findAndQuery.push( { checkListName: { $in: req.body.runAIChecklistName } } );
@@ -620,7 +620,6 @@ export const zoneList = async ( req, res ) => {
620
620
  const allowedChecklistsStreams = [
621
621
  'Camera Angle Change Compliance',
622
622
  ];
623
- console.log( allowedChecklists.includes( inputBody.checkListName ) );
624
623
 
625
624
  if ( inputBody.checkListName && allowedChecklists.includes( inputBody.checkListName ) ) {
626
625
  console.log( '==================' );
@@ -1915,6 +1914,7 @@ export const updateConfigure = async ( req, res ) => {
1915
1914
 
1916
1915
  export const updateConfigurev1 = async ( req, res ) => {
1917
1916
  try {
1917
+ console.log( '123' );
1918
1918
  let inputBody = req.body;
1919
1919
  let id;
1920
1920
  let checklistDetails;
@@ -3972,7 +3972,6 @@ async function insertPCBulkV4( getCLconfig, checklistId, currentdate, updatedche
3972
3972
  element4.rawVideoUpload = getCLconfig?.rawVideoUpload || false;
3973
3973
  element4.videoUploadTimeLimit = getCLconfig?.videoUploadTimeLimit || 0;
3974
3974
  element4.complianceCount = getCLconfig?.complianceCount || 0;
3975
- element4.userVerification = getCLconfig?.userVerification;
3976
3975
  assignUserList.push( { ...element4 } );
3977
3976
  }
3978
3977
  } ) );
@@ -4137,7 +4136,7 @@ async function updateOpenSearch( user, data ) {
4137
4136
  export const aiChecklist = async ( req, res ) => {
4138
4137
  try {
4139
4138
  let storeDetails = await storeService.count( { clientId: req.query.clientId, status: 'active' } );
4140
- let aiList = [ 'mobileusagedetection', 'storeopenandclose', 'uniformdetection', 'staffleftinthemiddle', 'customerunattended', 'eyetest', 'remoteoptometrist', 'storehygienemonitoring', 'cleaning', 'scrum', 'suspiciousactivity', 'suspiciousfootfall', 'drinking', 'bagdetection', 'inventorycount', 'carsattended', 'numberplateinfo', 'vehicle_check_in', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'unattendeddetection', 'occupancydetection' ];
4139
+ let aiList = [ 'mobileusagedetection', 'storeopenandclose', 'uniformdetection', 'staffleftinthemiddle', 'customerunattended', 'eyetest', 'remoteoptometrist', 'storehygienemonitoring', 'cleaning', 'scrum', 'suspiciousactivity', 'suspiciousfootfall', 'drinking', 'bagdetection', 'inventorycount', 'carsattended', 'numberplateinfo', 'vehicle_check_in', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'unattendeddetection', 'occupancydetection', 'employeemonitoring' ];
4141
4140
  let checklistDetails = [];
4142
4141
  let publishList = [];
4143
4142
  let unpublishList = [];
@@ -4150,7 +4149,7 @@ export const aiChecklist = async ( req, res ) => {
4150
4149
  checklistDetails = [ ...publishList, ...unpublishList ];
4151
4150
 
4152
4151
  checklistDetails.forEach( ( item ) => {
4153
- if ( ![ 'mobileusagedetection', 'storeopenandclose', 'cleaning', 'scrum', 'uniformdetection', 'staffleftinthemiddle', 'customerunattended', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'unattendeddetection', 'storehygienemonitoring' ].includes( item.checkListType ) ) {
4152
+ if ( ![ 'mobileusagedetection', 'storeopenandclose', 'cleaning', 'scrum', 'uniformdetection', 'staffleftinthemiddle', 'customerunattended', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'unattendeddetection', 'storehygienemonitoring', 'employeemonitoring' ].includes( item.checkListType ) ) {
4154
4153
  item.storeCount = storeDetails;
4155
4154
  }
4156
4155
  } );