tango-app-api-trax 3.8.14 → 3.8.15-nike

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 { logger, signedUrl, fileUpload, getOtp, sendEmailWithSES, getUuid, insertOpenSearchData, listFileByPath, getObject, deleteFiles } from 'tango-app-api-middleware';
1
+ import { logger, signedUrl, fileUpload, getOtp, sendEmailWithSES, getUuid, insertOpenSearchData, listFileByPath, getObject, deleteFiles, sendMessageToQueue } from 'tango-app-api-middleware';
2
2
  import * as processedchecklist from '../services/processedchecklist.services.js';
3
3
  import * as processedtask from '../services/processedTaskList.service.js';
4
4
  import * as PCLconfig from '../services/processedchecklistconfig.services.js';
@@ -26,6 +26,7 @@ dayjs.extend( customParseFormat );
26
26
  dayjs.extend( timeZone );
27
27
  import isSameOrBefore from 'dayjs/plugin/isSameOrBefore.js';
28
28
  import * as cameraService from '../services/camera.service.js';
29
+ import * as recurringFlagTracker from '../services/recurringFlagTracker.service.js';
29
30
  dayjs.extend( isSameOrBefore );
30
31
  import puppeteer from 'puppeteer';
31
32
  import handlebars from './handlebar-helper.js';
@@ -233,15 +234,15 @@ export async function startChecklist( req, res ) {
233
234
  },
234
235
  } );
235
236
  let getupdatedchecklist = await processedchecklist.aggregate( findQuery );
236
- let bucket = JSON.parse( process.env.BUCKET );
237
+ // let bucket = JSON.parse( process.env.BUCKET );
237
238
  getupdatedchecklist[0].questionAnswers.forEach( ( section ) => {
238
239
  section.questions.forEach( async ( question ) => {
239
240
  if ( question.questionReferenceImage && question.questionReferenceImage!='' ) {
240
- question.questionReferenceImage = await signedUrl( { Bucket: bucket.sop, file_path: decodeURIComponent( question.questionReferenceImage ) } );
241
+ question.questionReferenceImage = `${cdnurl.TraxAnswerCDN}${question.questionReferenceImage}`;
241
242
  }
242
243
  question.answers.forEach( async ( answer ) => {
243
244
  if ( answer.referenceImage != '' ) {
244
- answer.referenceImage = await signedUrl( { Bucket: bucket.sop, file_path: decodeURIComponent( answer.referenceImage ) } );
245
+ answer.referenceImage = `${cdnurl.TraxAnswerCDN}${answer.referenceImage}`;
245
246
  }
246
247
  } );
247
248
  } );
@@ -466,19 +467,16 @@ export async function startTask( req, res ) {
466
467
  } );
467
468
  const getUpdatedTask = await processedTask.aggregate( findQuery );
468
469
 
469
-
470
+ let cdnurl = JSON.parse( process.env.CDNURL );
470
471
  if ( !( task.checkListFrom && task.checkListFrom == 'api' ) ) {
471
- const bucket = JSON.parse( process.env.BUCKET );
472
+ // const bucket = JSON.parse( process.env.BUCKET );
472
473
  await Promise.all(
473
474
  getUpdatedTask[0].questionAnswers.map( ( section ) =>
474
475
  section.questions.map( async ( question ) => {
475
476
  if ( question.questionReferenceImage.length > 0 ) {
476
477
  question.questionReferenceImage = await Promise.all(
477
478
  question.questionReferenceImage.map( async ( image ) => {
478
- return await signedUrl( {
479
- Bucket: bucket.sop,
480
- file_path: decodeURIComponent( image ),
481
- } );
479
+ return `${cdnurl.TraxAnswerCDN}${image}`;
482
480
  } ),
483
481
  );
484
482
  }
@@ -488,10 +486,7 @@ export async function startTask( req, res ) {
488
486
  if ( answer.referenceImage.length > 0 ) {
489
487
  answer.referenceImage = await Promise.all(
490
488
  answer.referenceImage.map( async ( image ) => {
491
- return await signedUrl( {
492
- Bucket: bucket.sop,
493
- file_path: decodeURIComponent( image ),
494
- } );
489
+ return `${cdnurl.TraxAnswerCDN}${image}`;
495
490
  } ),
496
491
  );
497
492
  }
@@ -1087,12 +1082,15 @@ export async function sopMobilechecklistMultiSectionFormatterv1( req, res, next
1087
1082
  try {
1088
1083
  let requestData = req.body;
1089
1084
  requestData.questionAnswers = typeof requestData.questionAnswers == 'string' ? JSON.parse( requestData.questionAnswers ) : requestData.questionAnswers;
1090
- let getChecklistQA = await processedchecklist.findOne( { _id: new ObjectId( requestData.processedcheckListId ) }, { questionAnswers: 1 } );
1085
+ let getChecklistQA = await processedchecklist.findOne( { _id: new ObjectId( requestData.processedcheckListId ) }, { questionAnswers: 1, redoEdit: 1 } );
1091
1086
  let reqAnswers = requestData.questionAnswers;
1092
1087
  logger.error( { functionName: 'updatedPayload', message: reqAnswers } );
1093
1088
  let CLQAnswers = getChecklistQA.questionAnswers;
1094
1089
 
1095
1090
  if ( requestData.submittype == 'submit' ) {
1091
+ if ( getChecklistQA?.redoEdit ) {
1092
+ requestData.submittype = 'draft';
1093
+ }
1096
1094
  reqAnswers.forEach( ( reqA ) => {
1097
1095
  if ( ![ 'multiplechoicemultiple', 'multipleImage', 'image/video' ].includes( reqA?.answerType ) && ( reqA.answerType == 'dropDown' && !reqA.allowMultiple ) ) {
1098
1096
  if ( ( !reqA.linkType && ( reqA.answer == null || reqA.answer == '' ) ) || ( reqA.linkType && reqA.linkquestionenabled && ( reqA.answer == null || reqA.answer == '' ) ) ) {
@@ -1312,27 +1310,35 @@ export async function sopMobilechecklistMultiSectionFormatterv1( req, res, next
1312
1310
  for ( let k = 0; k < qaans.length; k++ ) {
1313
1311
  let separatedArray = typeof requestSection[i].Multianswer == 'string' ? JSON.parse( requestSection[i].Multianswer ) : requestSection[i].Multianswer;
1314
1312
  for ( let s = 0; s < separatedArray.length; s++ ) {
1315
- if ( separatedArray[s].answer == qaans[k].answer ) {
1316
- if ( qaans[k].validationType == 'Capture Image' || qaans[k].validationType == 'Capture Video' ) {
1317
- if ( separatedArray[s].validationAnswer ) {
1318
- let validationAnswer = decodeURIComponent( separatedArray[s].validationAnswer.split( '?' )[0] );
1319
- if ( validationAnswer.length ) {
1320
- let splitImgUrl = validationAnswer.split( '/' );
1321
- if ( splitImgUrl.length > 1 ) {
1322
- splitImgUrl.splice( 0, 3 );
1323
- qaans[k].validationAnswer = splitImgUrl.join( '/' ) || '';
1313
+ if ( ( separatedArray[s].answer == qaans[k].answer ) ) {
1314
+ if ( ( getChecklistQA?.redoEdit && qaans[k].redo == separatedArray[s].redo ) || !getChecklistQA?.redoEdit ) {
1315
+ if ( qaans[k].validationType == 'Capture Image' || qaans[k].validationType == 'Capture Video' ) {
1316
+ if ( separatedArray[s].validationAnswer ) {
1317
+ let validationAnswer = decodeURIComponent( separatedArray[s].validationAnswer.split( '?' )[0] );
1318
+ if ( validationAnswer.length ) {
1319
+ let splitImgUrl = validationAnswer.split( '/' );
1320
+ if ( splitImgUrl.length > 1 ) {
1321
+ splitImgUrl.splice( 0, 3 );
1322
+ qaans[k].validationAnswer = splitImgUrl.join( '/' ) || '';
1323
+ }
1324
1324
  }
1325
1325
  }
1326
- }
1327
- } else {
1326
+ } else {
1328
1327
  // qaans[k].descriptivetype = qaAnswers[j].descriptivetype || '';
1329
- qaans[k].validationAnswer = separatedArray[s].validationAnswer || '';
1328
+ qaans[k].validationAnswer = separatedArray[s].validationAnswer || '';
1329
+ }
1330
1330
  }
1331
1331
 
1332
1332
  mcmo.push( qaans[k] );
1333
1333
  }
1334
1334
  }
1335
1335
  }
1336
+ qaAnswers[j].answers.forEach( ( ele ) => {
1337
+ if ( typeof ele?.redo === 'boolean' && requestData.submittype === 'submit' ) {
1338
+ ele.redo = false;
1339
+ }
1340
+ } );
1341
+
1336
1342
  let structure = {};
1337
1343
  structure.qno = qaAnswers[j].qno;
1338
1344
  structure.uniqueqno = qaAnswers[j].uniqueqno;
@@ -1443,7 +1449,7 @@ export async function sopMobilechecklistMultiSectionFormatterv1( req, res, next
1443
1449
  let des = [];
1444
1450
  if ( requestSection[i].answer != 'null' && requestSection[i].answer != '' && requestSection[i].answer != null ) {
1445
1451
  let validationAnswer = '';
1446
- if ( requestSection[i].answer.split( '?' ).length > 1 ) {
1452
+ if ( requestSection[i].answer.split( '?' ).length > 1 || requestSection[i].answer.includes( 'https://' ) ) {
1447
1453
  validationAnswer = decodeURIComponent( requestSection[i].answer.split( '?' )[0] );
1448
1454
  }
1449
1455
  if ( validationAnswer.length ) {
@@ -1937,7 +1943,7 @@ export async function sopMobileTaskMultiSectionFormatter( req, res, next ) {
1937
1943
  let des = [];
1938
1944
  if ( requestSection[i].answer != 'null' && requestSection[i].answer != '' && requestSection[i].answer != null ) {
1939
1945
  let validationAnswer = '';
1940
- if ( requestSection[i].answer.split( '?' ).length > 1 ) {
1946
+ if ( requestSection[i].answer.split( '?' ).length > 1 || requestSection[i].answer.includes( 'https://' ) ) {
1941
1947
  validationAnswer = decodeURIComponent( requestSection[i].answer.split( '?' )[0] );
1942
1948
  }
1943
1949
  if ( validationAnswer.length ) {
@@ -2034,6 +2040,102 @@ function QuestionFlag( req, res ) {
2034
2040
  }
2035
2041
  }
2036
2042
 
2043
+ async function updateRecurringFlagTracker( processedChecklist, questionAnswers, currentDateTime ) {
2044
+ try {
2045
+ if ( !processedChecklist?.sourceCheckList_id ) return;
2046
+
2047
+ const isUserBased = processedChecklist?.coverage === 'user';
2048
+ const storeId = isUserBased ? '' : ( processedChecklist?.store_id || '' );
2049
+ const userId = isUserBased ? ( processedChecklist?.userId ? String( processedChecklist.userId ) : ( processedChecklist?.userEmail || '' ) ) : '';
2050
+ if ( !isUserBased && !storeId ) return;
2051
+ if ( isUserBased && !userId ) return;
2052
+
2053
+ const today = currentDateTime ? currentDateTime.format( 'YYYY-MM-DD' ) : dayjs().format( 'YYYY-MM-DD' );
2054
+ const yesterday = dayjs( today, 'YYYY-MM-DD' ).subtract( 1, 'day' ).format( 'YYYY-MM-DD' );
2055
+
2056
+ const trackerKeyBase = {
2057
+ client_id: processedChecklist.client_id,
2058
+ sourceCheckList_id: processedChecklist.sourceCheckList_id,
2059
+ ...( isUserBased ) ? { user_id: userId } : { store_id: storeId },
2060
+ };
2061
+
2062
+ const existingRows = await recurringFlagTracker.find( trackerKeyBase, { section_id: 1, qno: 1, consecutiveCount: 1, lastFlaggedDate: 1 } );
2063
+ const existingMap = new Map();
2064
+ for ( const r of existingRows ) {
2065
+ existingMap.set( `${r.section_id || ''}::${r.qno || ''}`, r );
2066
+ }
2067
+
2068
+ const ops = [];
2069
+
2070
+ ( questionAnswers || [] ).forEach( ( section ) => {
2071
+ ( section?.questions || [] ).forEach( ( question ) => {
2072
+ const sectionId = section?.section_id || '';
2073
+ const qno = question?.qno || '';
2074
+ if ( qno === '' ) return;
2075
+
2076
+ const flaggedNow = Array.isArray( question?.userAnswer ) && question.userAnswer.some( ( a ) => a?.sopFlag === true );
2077
+ const key = `${sectionId}::${qno}`;
2078
+ const existing = existingMap.get( key );
2079
+ console.log( flaggedNow, 'test' );
2080
+ if ( flaggedNow ) {
2081
+ let newCount;
2082
+ if ( !existing ) {
2083
+ newCount = 1;
2084
+ } else if ( existing.lastFlaggedDate === today ) {
2085
+ // Multi-submit on same day: already counted, no-op.
2086
+ return;
2087
+ } else if ( existing.lastFlaggedDate === yesterday ) {
2088
+ newCount = ( existing.consecutiveCount || 0 ) + 1;
2089
+ } else {
2090
+ // Gap broke the streak — fresh start.
2091
+ newCount = 1;
2092
+ }
2093
+
2094
+ ops.push( {
2095
+ updateOne: {
2096
+ filter: { ...trackerKeyBase, section_id: sectionId, qno },
2097
+ update: {
2098
+ $set: {
2099
+ coverage: isUserBased ? 'user' : 'store',
2100
+ checkListName: processedChecklist.checkListName,
2101
+ storeName: isUserBased ? '' : ( processedChecklist.storeName || '' ),
2102
+ userName: processedChecklist.userName || '',
2103
+ userEmail: processedChecklist.userEmail || '',
2104
+ sectionName: section?.sectionName || '',
2105
+ qname: question?.qname || '',
2106
+ consecutiveCount: newCount,
2107
+ lastFlaggedDate: today,
2108
+ lastSubmittedBy: processedChecklist.userName || processedChecklist.userEmail || '--',
2109
+ lastSubmissionDate: currentDateTime ? currentDateTime.format( 'hh:mm A, DD MMM YYYY' ) : today,
2110
+ },
2111
+ },
2112
+ upsert: true,
2113
+ },
2114
+ } );
2115
+ } else if ( existing && ( existing.consecutiveCount || 0 ) > 0 ) {
2116
+ // Question answered correctly today — break the streak.
2117
+ ops.push( {
2118
+ updateOne: {
2119
+ filter: { ...trackerKeyBase, section_id: sectionId, qno },
2120
+ update: { $set: { lastFlaggedDate: today } },
2121
+ },
2122
+ } );
2123
+ }
2124
+ } );
2125
+ } );
2126
+ if ( ops.length ) {
2127
+ try {
2128
+ let data = await recurringFlagTracker.bulkWrite( ops, { ordered: false } );
2129
+ console.log( 'recurringFlagTracker bulkWrite result', data );
2130
+ } catch ( bulkErr ) {
2131
+ logger.error( { function: 'updateRecurringFlagTracker.bulkWrite', code: bulkErr?.code, message: bulkErr?.message, writeErrors: bulkErr?.writeErrors } );
2132
+ }
2133
+ }
2134
+ } catch ( error ) {
2135
+ logger.error( { function: 'updateRecurringFlagTracker', error } );
2136
+ }
2137
+ }
2138
+
2037
2139
  export async function submitChecklist( req, res ) {
2038
2140
  try {
2039
2141
  let requestData = req.body;
@@ -2081,6 +2183,7 @@ export async function submitChecklist( req, res ) {
2081
2183
  let flagCount = QuestionFlag( req, res );
2082
2184
  updateData.questionFlag = flagCount;
2083
2185
  updateData.submitTime_string = currentDateTime.format( 'hh:mm A, DD MMM YYYY' );
2186
+ updateData.redoEdit = false;
2084
2187
  if ( requestData.deviceDetails && requestData.deviceDetails != '' ) {
2085
2188
  updateData.deviceDetails =JSON.parse( requestData.deviceDetails );
2086
2189
  }
@@ -2169,6 +2272,10 @@ export async function submitChecklist( req, res ) {
2169
2272
  // };
2170
2273
  // await detectionService.create( detectionData );
2171
2274
  if ( requestData.submittype == 'submit' ) {
2275
+ console.log( checklistDetails?.recurringFlag?.notifyType?.length );
2276
+ if ( checklistDetails?.recurringFlag?.notifyType?.length ) {
2277
+ updateRecurringFlagTracker( getchecklist[0], requestData.questionAnswers, currentDateTime );
2278
+ }
2172
2279
  updateOpenSearch( req.user, requestData );
2173
2280
  let openSearch = JSON.parse( process.env.OPENSEARCH );
2174
2281
  // console.log( 'openSearch', openSearch );
@@ -2340,8 +2447,17 @@ export async function submitTask( req, res ) {
2340
2447
  insertOpenSearchData( openSearch.traxActivityLog, inserttraxlogs );
2341
2448
  if ( submittype === 'submit' ) {
2342
2449
  const excludedChecklists = [ 'Store Hygiene Check' ];
2343
- if ( checklist.checkListName.includes( 'Store Hygiene' ) ) {
2344
-
2450
+ if ( checklist.checkListName.includes( 'Store Hygiene' ) && checklist?.streamId ) {
2451
+ let sqsData = {
2452
+ 'storeId': checklist.store_id,
2453
+ 'streamID': checklist.streamId,
2454
+ 'detectionTime': checklist?.questionAnswers?.[0]?.questions?.[0]?.answers?.[0]?.detectionTime,
2455
+ 'date': checklist.date_string,
2456
+ 'storeResponseTime': currentDateTime.format( 'HH:mm:ss - MMM DD, YYYY' ),
2457
+ 'message_mode': 'retriggered',
2458
+ };
2459
+ let sqsResponse = await sendMessageToQueue( `${JSON.parse( process.env.SQS ).url}${JSON.parse( process.env.SQS ).storeHygiene}`, JSON.stringify( sqsData ) );
2460
+ console.log( sqsResponse );
2345
2461
  }
2346
2462
  if ( !excludedChecklists.includes( checklist.checkListName ) ) {
2347
2463
  const query1 = [
@@ -3486,7 +3602,7 @@ export async function questionList( req, res ) {
3486
3602
  return res.sendError( 'Check List Got Edited Please Fill Again', 422 );
3487
3603
  } else {
3488
3604
  logger.info( `v5 => Checklist Continue => store Name: ${getchecklist[0].storeName}, User Email: ${getchecklist[0].userEmail}, Checklist Name: ${getchecklist[0].checkListName}` );
3489
- let bucket = JSON.parse( process.env.BUCKET );
3605
+ // let bucket = JSON.parse( process.env.BUCKET );
3490
3606
  let cdnurl = JSON.parse( process.env.CDNURL );
3491
3607
  for ( let [ secIndex, section ] of getchecklist[0].questionAnswers.entries() ) {
3492
3608
  for ( let [ questionIndex, question ] of section.questions.entries() ) {
@@ -3512,12 +3628,12 @@ export async function questionList( req, res ) {
3512
3628
  let checkvalidation = null;
3513
3629
  if ( answer.validationAnswer && answer.validationAnswer !='' ) {
3514
3630
  if ( answer.validationType != 'Descriptive Answer' ) {
3515
- checkvalidation = await signedUrl( { file_path: decodeURIComponent( answer.validationAnswer ), Bucket: bucket.sop } );
3631
+ checkvalidation = `${cdnurl.TraxAnswerCDN}${answer.validationAnswer}`;
3516
3632
  } else {
3517
3633
  checkvalidation = answer.validationAnswer;
3518
3634
  }
3519
3635
  }
3520
- Multianswer.push( { 'answer': answer.answer, 'no': ansIndex, 'validationAnswer': checkvalidation } );
3636
+ Multianswer.push( { 'answer': answer.answer, 'no': ansIndex, 'validationAnswer': checkvalidation, ...( answer.redo && { redo: answer.redo } ) } );
3521
3637
  getchecklist[0].questionAnswers[secIndex].questions[questionIndex].answers[ansIndex].index = ansIndex;
3522
3638
  }
3523
3639
 
@@ -3533,23 +3649,23 @@ export async function questionList( req, res ) {
3533
3649
  answer.referenceImage= `${cdnurl.TraxAnswerCDN}${answer.referenceImage}`;
3534
3650
  }
3535
3651
  if ( ( answer.validationType == 'Capture Image' || answer.validationType == 'Capture Video' ) && answer.validationAnswer && answer.validationAnswer != '' ) {
3536
- getchecklist[0].questionAnswers[secIndex].questions[questionIndex].answers[ansIndex].validationAnswer = await signedUrl( { file_path: decodeURIComponent( answer.validationAnswer ), Bucket: bucket.sop } );
3652
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].answers[ansIndex].validationAnswer = `${cdnurl.TraxAnswerCDN}${answer.validationAnswer}`;
3537
3653
  }
3538
3654
  }
3539
3655
  if ( question?.userAnswer ) {
3540
3656
  for ( let [ userAnsIndex, userAns ] of question.userAnswer.entries() ) {
3541
3657
  if ( ( userAns.validationType == 'Capture Image' || userAns.validationType == 'Capture Video' ) && userAns.validationAnswer && userAns.validationAnswer != '' ) {
3542
- getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].validationAnswer = await signedUrl( { file_path: decodeURIComponent( userAns.validationAnswer ), Bucket: bucket.sop } );
3658
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].validationAnswer = `${cdnurl.TraxAnswerCDN}${userAns.validationAnswer}`;
3543
3659
  }
3544
3660
  if ( userAns.validationType == 'Capture Multiple Image with description' ) {
3545
3661
  let imageAnswers = userAns.validationImage;
3546
3662
  userAns.validationImage = [];
3547
3663
  for ( let image of imageAnswers ) {
3548
- getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].validationImage.push( await signedUrl( { file_path: decodeURIComponent( image ), Bucket: bucket.sop } ) );
3664
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].validationImage.push( `${cdnurl.TraxAnswerCDN}${image}` );
3549
3665
  }
3550
3666
  }
3551
3667
  if ( [ 'image', 'descriptiveImage', 'video' ].includes( question.answerType ) && userAns.answer != '' ) {
3552
- getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].answer = await signedUrl( { file_path: decodeURIComponent( userAns.answer ), Bucket: bucket.sop } );
3668
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].answer =`${cdnurl.TraxAnswerCDN}${userAns.answer}`;
3553
3669
  }
3554
3670
  if ( userAns.referenceImage != '' ) {
3555
3671
  // getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].referenceImage = await signedUrl( { file_path: decodeURIComponent( userAns.referenceImage ), Bucket: bucket.sop } );
@@ -3856,7 +3972,7 @@ export async function taskQuestionList( req, res ) {
3856
3972
  return res.sendError( 'Task Got Edited Please Fill Again', 422 );
3857
3973
  } else {
3858
3974
  logger.info( `v5 => Task Continue => store Name: ${getchecklist[0].storeName}, User Email: ${getchecklist[0].userEmail}, Task Name: ${getchecklist[0].checkListName}` );
3859
- let bucket = JSON.parse( process.env.BUCKET );
3975
+ // let bucket = JSON.parse( process.env.BUCKET );
3860
3976
  let cdnurl = JSON.parse( process.env.CDNURL );
3861
3977
  for ( let [ secIndex, section ] of getchecklist[0].questionAnswers.entries() ) {
3862
3978
  for ( let [ questionIndex, question ] of section.questions.entries() ) {
@@ -3867,13 +3983,10 @@ export async function taskQuestionList( req, res ) {
3867
3983
  if ( Array.isArray( questionReferenceImage ) ) {
3868
3984
  questionReferenceImage = questionReferenceImage.filter( ( item ) => item != '' );
3869
3985
  getchecklist[0].questionAnswers[secIndex].questions[questionIndex].questionReferenceImage = await Promise.all(
3870
- questionReferenceImage.map( async ( image ) => image ? await signedUrl( { file_path: decodeURIComponent( image ), Bucket: bucket.sop } ) : '' ),
3986
+ questionReferenceImage.map( async ( image ) => image ? `${cdnurl.TraxAnswerCDN}${image}` : '' ),
3871
3987
  );
3872
3988
  } else if ( questionReferenceImage !== '' ) {
3873
- getchecklist[0].questionAnswers[secIndex].questions[questionIndex].questionReferenceImage = await signedUrl( {
3874
- file_path: decodeURIComponent( questionReferenceImage ),
3875
- Bucket: bucket.sop,
3876
- } );
3989
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].questionReferenceImage = `${cdnurl.TraxAnswerCDN}${questionReferenceImage}`;
3877
3990
  }
3878
3991
  }
3879
3992
 
@@ -3884,13 +3997,10 @@ export async function taskQuestionList( req, res ) {
3884
3997
  if ( Array.isArray( referenceImage ) ) {
3885
3998
  referenceImage = referenceImage.filter( ( item ) => item != '' );
3886
3999
  getchecklist[0].questionAnswers[secIndex].questions[questionIndex].answers[ansIndex].referenceImage = await Promise.all(
3887
- referenceImage.map( async ( image ) => image ? await signedUrl( { file_path: decodeURIComponent( image ), Bucket: bucket.sop } ) : '' ),
4000
+ referenceImage.map( async ( image ) => image ? `${cdnurl.TraxAnswerCDN}${image}` : '' ),
3888
4001
  );
3889
4002
  } else if ( referenceImage !== '' ) {
3890
- getchecklist[0].questionAnswers[secIndex].questions[questionIndex].answers[ansIndex].referenceImage = await signedUrl( {
3891
- file_path: decodeURIComponent( referenceImage ),
3892
- Bucket: bucket.sop,
3893
- } );
4003
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].answers[ansIndex].referenceImage = `${cdnurl.TraxAnswerCDN}${referenceImage}`;
3894
4004
  }
3895
4005
  }
3896
4006
 
@@ -3898,7 +4008,7 @@ export async function taskQuestionList( req, res ) {
3898
4008
  let checkvalidation = null;
3899
4009
  if ( answer.validationAnswer && answer.validationAnswer != '' ) {
3900
4010
  if ( answer.validationType != 'Descriptive Answer' ) {
3901
- checkvalidation = await signedUrl( { file_path: decodeURIComponent( answer.validationAnswer ), Bucket: bucket.sop } );
4011
+ checkvalidation = `${cdnurl.TraxAnswerCDN}${answer.validationAnswer}`;
3902
4012
  } else {
3903
4013
  checkvalidation = answer.validationAnswer;
3904
4014
  }
@@ -3907,10 +4017,7 @@ export async function taskQuestionList( req, res ) {
3907
4017
  getchecklist[0].questionAnswers[secIndex].questions[questionIndex].answers[ansIndex].index = ansIndex;
3908
4018
  }
3909
4019
  if ( ( answer.validationType == 'Capture Image' || answer.validationType == 'Capture Video' ) && answer.validationAnswer && answer.validationAnswer != '' ) {
3910
- getchecklist[0].questionAnswers[secIndex].questions[questionIndex].answers[ansIndex].validationAnswer = await signedUrl( {
3911
- file_path: decodeURIComponent( answer.validationAnswer ),
3912
- Bucket: bucket.sop,
3913
- } );
4020
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].answers[ansIndex].validationAnswer = `${cdnurl.TraxAnswerCDN}${answer.validationAnswer}`;
3914
4021
  }
3915
4022
  }
3916
4023
 
@@ -3921,25 +4028,16 @@ export async function taskQuestionList( req, res ) {
3921
4028
  getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].linearType = question.answers[0].linearType;
3922
4029
  }
3923
4030
  if ( ( userAns.validationType == 'Capture Image' || userAns.validationType == 'Capture Video' ) && userAns.validationAnswer && userAns.validationAnswer != '' ) {
3924
- getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].validationAnswer = await signedUrl( {
3925
- file_path: decodeURIComponent( userAns.validationAnswer ),
3926
- Bucket: bucket.sop,
3927
- } );
4031
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].validationAnswer = `${cdnurl.TraxAnswerCDN}${userAns.validationAnswer}`;
3928
4032
  }
3929
4033
  if ( [ 'image', 'descriptiveImage', 'video' ].includes( question.answerType ) && rawAnswer != '' ) {
3930
- getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].answer = await signedUrl( {
3931
- file_path: decodeURIComponent( rawAnswer ),
3932
- Bucket: bucket.sop,
3933
- } );
4034
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].answer = `${cdnurl.TraxAnswerCDN}${rawAnswer}`;
3934
4035
  }
3935
4036
  if ( question.answerType == 'image/video' && rawAnswer != '' ) {
3936
4037
  getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].answer = `${cdnurl.TraxAnswerCDN}${rawAnswer}`;
3937
4038
  }
3938
4039
  if ( userAns.referenceImage != '' ) {
3939
- getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].referenceImage = await signedUrl( {
3940
- file_path: decodeURIComponent( userAns.referenceImage ),
3941
- Bucket: bucket.sop,
3942
- } );
4040
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].referenceImage = `${cdnurl.TraxAnswerCDN}${userAns.referenceImage}`;
3943
4041
  }
3944
4042
  if ( question.answerType == 'multiplechoicemultiple' || ( question.answerType == 'dropdown' && question.allowMultiple ) ) {
3945
4043
  let ansIndex = Multianswer.findIndex( ( item ) => item.answer == rawAnswer );
@@ -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' ] },
611
+ checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring' ] },
612
612
  },
613
613
  { checkListType: 1 },
614
614
  );
@@ -2743,7 +2743,7 @@ export const checklistDropdownV1 = async ( req, res ) => {
2743
2743
  $or: [
2744
2744
  { questionFlag: { $gte: 1 } },
2745
2745
  { timeFlag: { $gte: 1 } },
2746
- { checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert' ] } },
2746
+ { checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring' ] } },
2747
2747
  {
2748
2748
  runAIQuestionCount: { $gte: 1 },
2749
2749
  },
@@ -2945,7 +2945,7 @@ export const flagComparisonCardsV2 = async ( req, res ) => {
2945
2945
  {
2946
2946
  client_id: requestData.clientId,
2947
2947
  publish: true,
2948
- checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert' ] },
2948
+ checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring' ] },
2949
2949
  },
2950
2950
  { checkListType: 1 },
2951
2951
  );
@@ -3047,7 +3047,7 @@ export const flagTablesV2 = async ( req, res ) => {
3047
3047
  }
3048
3048
 
3049
3049
  if ( requestData?.filter === 'all' ) {
3050
- findAndQuery.push( { $or: [ { checkListType: { $in: [ 'custom', 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert' ] } } ] } );
3050
+ findAndQuery.push( { $or: [ { checkListType: { $in: [ 'custom', 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring' ] } } ] } );
3051
3051
  } else if ( requestData?.filter === 'question' ) {
3052
3052
  findAndQuery.push( { checkListType: 'custom' } );
3053
3053
  findAndQuery.push( { questionFlag: { $gte: 1 } } );
@@ -3055,7 +3055,7 @@ export const flagTablesV2 = async ( req, res ) => {
3055
3055
  findAndQuery.push( { checkListType: 'custom' } );
3056
3056
  findAndQuery.push( { timeFlag: { $gte: 1 } } );
3057
3057
  } else if ( requestData?.filter === 'detection' ) {
3058
- findAndQuery.push( { checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert' ] } } );
3058
+ findAndQuery.push( { checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring' ] } } );
3059
3059
  } else if ( requestData?.filter === 'runAI' ) {
3060
3060
  if ( req.body.runAIChecklistName ) {
3061
3061
  findAndQuery.push( { checkListName: { $in: req.body.runAIChecklistName } } );
@@ -1729,6 +1729,7 @@ export const updateConfigure = async ( req, res ) => {
1729
1729
  owner: inputBody?.checkListDetails?.owner || [],
1730
1730
  restrictAttendance: inputBody?.checkListDetails?.restrictAttendance || false,
1731
1731
  enableNewDeployedStore: inputBody?.checkListDetails?.enableNewDeployedStore || false,
1732
+ redoValidity: inputBody?.checkListDetails?.redoValidity || 7,
1732
1733
  };
1733
1734
 
1734
1735
  if ( inputBody?.checkListDetails?.approver.length ) {
@@ -3907,6 +3908,8 @@ async function insertPCBulkV4( getCLconfig, checklistId, currentdate, updatedche
3907
3908
  }
3908
3909
  }
3909
3910
  getsubmitDetails[0].questionAnswers = sectionList;
3911
+ getsubmitDetails[0].scheduleEndTime = getCLconfig.scheduleEndTime;
3912
+ getsubmitDetails[0].scheduleEndTime_iso = endTimeIso.format();
3910
3913
  if ( modifiedCount ) {
3911
3914
  getsubmitDetails[0].checklistStatus = 'inprogress';
3912
3915
  getsubmitDetails[0].date_string = dayjs( currentdate ).format( 'YYYY-MM-DD' );
@@ -4030,6 +4033,7 @@ async function insertPCBulkV4( getCLconfig, checklistId, currentdate, updatedche
4030
4033
  }, { userId: 1, store_id: 1 } );
4031
4034
 
4032
4035
  if ( inprogressData.length ) {
4036
+ await processedchecklist.updateMany( { _id: { $in: inprogressData.map( ( ele ) => new ObjectId( ele._id ) ) } }, { scheduleEndTime: getCLconfig.scheduleEndTime, scheduleEndTime_iso: endTimeIso.format() } );
4033
4037
  inprogressData.forEach( ( item ) => {
4034
4038
  let checkData = assignUserList.find( ( ele ) => ele.userId.toString() == item.userId.toString() && ele.store_id == item.store_id );
4035
4039
  if ( !checkData ) {
@@ -4127,7 +4131,7 @@ async function updateOpenSearch( user, data ) {
4127
4131
  export const aiChecklist = async ( req, res ) => {
4128
4132
  try {
4129
4133
  let storeDetails = await storeService.count( { clientId: req.query.clientId, status: 'active' } );
4130
- let aiList = [ 'mobileusagedetection', 'storeopenandclose', 'uniformdetection', 'staffleftinthemiddle', 'customerunattended', 'eyetest', 'remoteoptometrist', 'storehygienemonitoring', 'cleaning', 'scrum', 'suspiciousactivity', 'boxalert', 'suspiciousfootfall', 'drinking', 'bagdetection', 'inventorycount', 'carsattended', 'numberplateinfo', 'vehicle_check_in', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert' ];
4134
+ 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' ];
4131
4135
  let checklistDetails = [];
4132
4136
  let publishList = [];
4133
4137
  let unpublishList = [];
@@ -4140,7 +4144,7 @@ export const aiChecklist = async ( req, res ) => {
4140
4144
  checklistDetails = [ ...publishList, ...unpublishList ];
4141
4145
 
4142
4146
  checklistDetails.forEach( ( item ) => {
4143
- if ( ![ 'mobileusagedetection', 'storeopenandclose', 'cleaning', 'scrum', 'uniformdetection', 'staffleftinthemiddle', 'customerunattended', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert' ].includes( item.checkListType ) ) {
4147
+ if ( ![ 'mobileusagedetection', 'storeopenandclose', 'cleaning', 'scrum', 'uniformdetection', 'staffleftinthemiddle', 'customerunattended', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount' ].includes( item.checkListType ) ) {
4144
4148
  item.storeCount = storeDetails;
4145
4149
  }
4146
4150
  } );