tango-app-api-trax 1.0.0-beta-task.7 → 1.0.0-beta-task.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tango-app-api-trax",
3
- "version": "1.0.0-beta-task.7",
3
+ "version": "1.0.0-beta-task.9",
4
4
  "description": "Trax",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -28,6 +28,7 @@
28
28
  "path": "^0.12.7",
29
29
  "tango-api-schema": "2.2.5",
30
30
  "tango-app-api-middleware": "3.1.43-alpha.10",
31
+ "tango-app-api-trax": "^1.0.0-beta-task.7",
31
32
  "url": "^0.11.4",
32
33
  "winston": "^3.13.1",
33
34
  "winston-daily-rotate-file": "^5.0.0"
@@ -343,6 +343,7 @@ export async function redoChecklist( req, res ) {
343
343
 
344
344
  question[sectionIndex].questions[req.body.payload.qno - 1] = data;
345
345
  question[sectionIndex].questions[req.body.payload.qno - 1].userAnswer = [];
346
+ question[sectionIndex].questions[req.body.payload.qno - 1].remarks = '';
346
347
  checklistDetails.questionAnswers = question;
347
348
  let updateData = {
348
349
  checklistStatus: 'open',
@@ -443,9 +444,7 @@ export async function getLogs( req, res ) {
443
444
 
444
445
  export async function approvalstatus( req, res ) {
445
446
  try {
446
- if ( ( req?.user?.userType == 'client' && req.user.role == 'superadmin' ) ) {
447
- return res.sendError( 'No Content', 204 );
448
- }
447
+
449
448
 
450
449
 
451
450
  let Approver = await ApproverModel.find( { checkListId: req.body.checklistId } );
@@ -454,6 +453,17 @@ export async function approvalstatus( req, res ) {
454
453
  }
455
454
  let filterApprover = Approver.filter( ( data ) => data.userEmail=== req.user.email );
456
455
  if ( filterApprover.length === 0 ) {
456
+ if ( ( req?.user?.userType == 'client' && req.user.role == 'superadmin' ) ) {
457
+ let url = JSON.parse( process.env.LAMBDAURL );
458
+ let resultData = await LamdaServiceCall( url.approvalstatus, req.body );
459
+ if ( resultData ) {
460
+ console.log( resultData.status_code );
461
+ if ( resultData.status_code == '200' ) {
462
+ return res.sendSuccess( resultData );
463
+ }
464
+ }
465
+ return res.sendError( 'No Content', 204 );
466
+ }
457
467
  return res.sendSuccess( 'suceess' );
458
468
  }
459
469
 
@@ -953,9 +953,9 @@ export async function pushNotification( req, res ) {
953
953
  if ( getToken?.fcmToken ) {
954
954
  let existCheck = checklistDetails.findIndex( ( item ) => item.checklistName == data.checkListName );
955
955
  if ( existCheck != -1 ) {
956
- checklistDetails[existCheck].token.push( getToken.fcmToken );
956
+ checklistDetails[existCheck].token.push( { token: getToken.fcmToken, store: data.storeName } );
957
957
  } else {
958
- checklistDetails.push( { checklistName: data.checkListName, token: [ getToken.fcmToken ] } );
958
+ checklistDetails.push( { checklistName: data.checkListName, token: [ { token: getToken.fcmToken, store: data.storeName } ], time: checklistDate.diff( date, 'minute' ) } );
959
959
  }
960
960
  }
961
961
  }
@@ -968,26 +968,36 @@ export async function pushNotification( req, res ) {
968
968
  return res.sendError( 'no data found', 204 );
969
969
  }
970
970
 
971
- for ( let [ index, item ] of checklistDetails.entries() ) {
972
- const message = {
973
- tokens: item.token,
974
- notification: {
975
- title: 'Reminder to Fill checklist',
976
- body: `${item.checklistName} checklist is going to breach within few minutes`,
977
- },
978
- data: {
979
- customKey: 'customValue',
980
- },
981
- };
982
- const response = await admin.messaging().sendEachForMulticast( message );
983
- if ( response.successCount ) {
984
- logger.info( { message: 'push notification', success: item.token } );
985
- if ( index == checklistDetails.length - 1 ) {
986
- return res.sendSuccess( 'Push notification send successfully' );
987
- }
988
- } else {
989
- logger.error( { message: 'push notification', error: item.token } );
990
- }
971
+ const checklistPromise = checklistDetails.map( async ( ele ) => {
972
+ await sendNotification( ele );
973
+ } );
974
+
975
+ await Promise.all( checklistPromise );
976
+ return res.sendSuccess( 'Push notification send successfully' );
977
+
978
+ async function sendNotification( data ) {
979
+ return Promise.all(
980
+ data.token.map( async ( item ) => {
981
+ const message = {
982
+ token: item.token,
983
+ notification: {
984
+ title: item.store,
985
+ body: `The ${data.checklistName} is due. Complete it within ${data.time} minutes to avoid compliance.`,
986
+ },
987
+ data: {
988
+ customKey: 'customValue',
989
+ },
990
+ };
991
+ try {
992
+ let response = await admin.messaging().send( message );
993
+ if ( !response ) {
994
+ logger.error( { message: 'push notification', error: element.token } );
995
+ }
996
+ } catch ( e ) {
997
+ logger.error( { message: 'push notification', error: e, details: data } );
998
+ }
999
+ } ),
1000
+ );
991
1001
  }
992
1002
  } catch ( e ) {
993
1003
  logger.error( { function: 'pushNotification', error: e } );
@@ -1334,9 +1344,9 @@ export async function taskPushNotification( req, res ) {
1334
1344
  if ( getToken?.fcmToken ) {
1335
1345
  let existCheck = taskDetails.findIndex( ( item ) => item.checklistName == data.checkListName );
1336
1346
  if ( existCheck != -1 ) {
1337
- taskDetails[existCheck].token.push( getToken.fcmToken );
1347
+ taskDetails[existCheck].token.push( { token: getToken.fcmToken, store: data.storeName } );
1338
1348
  } else {
1339
- taskDetails.push( { checklistName: data.checkListName, token: [ getToken.fcmToken ] } );
1349
+ taskDetails.push( { checklistName: data.checkListName, token: [ { token: getToken.fcmToken, store: data.storeName } ], time: taskDate.diff( date, 'minute' ) } );
1340
1350
  }
1341
1351
  }
1342
1352
  }
@@ -1349,26 +1359,36 @@ export async function taskPushNotification( req, res ) {
1349
1359
  return res.sendError( 'no data found', 204 );
1350
1360
  }
1351
1361
 
1352
- for ( let [ index, item ] of taskDetails.entries() ) {
1353
- const message = {
1354
- tokens: item.token,
1355
- notification: {
1356
- title: 'Reminder to Fill task',
1357
- body: `${item.checklistName} task is going to breach within few minutes`,
1358
- },
1359
- data: {
1360
- customKey: 'customValue',
1361
- },
1362
- };
1363
- const response = await admin.messaging().sendEachForMulticast( message );
1364
- if ( response.successCount ) {
1365
- logger.info( { message: 'push notification', success: item.token } );
1366
- if ( index == taskDetails.length - 1 ) {
1367
- return res.sendSuccess( 'Push notification send successfully' );
1368
- }
1369
- } else {
1370
- logger.error( { message: 'push notification', error: item.token } );
1371
- }
1362
+ const checklistPromise = taskDetails.map( async ( ele ) => {
1363
+ await sendNotification( ele );
1364
+ } );
1365
+
1366
+ await Promise.all( checklistPromise );
1367
+ return res.sendSuccess( 'Push notification send successfully' );
1368
+
1369
+ async function sendNotification( data ) {
1370
+ return Promise.all(
1371
+ data.token.map( async ( item ) => {
1372
+ try {
1373
+ const message = {
1374
+ token: item.token,
1375
+ notification: {
1376
+ title: item.store,
1377
+ body: `The ${data.checklistName} is due. Complete it within ${data.time} minutes to avoid compliance`,
1378
+ },
1379
+ data: {
1380
+ customKey: 'customValue',
1381
+ },
1382
+ };
1383
+ let response = await admin.messaging().send( message );
1384
+ if ( !response ) {
1385
+ logger.error( { message: 'push notification', error: data.token } );
1386
+ }
1387
+ } catch ( e ) {
1388
+ logger.error( { message: 'push notification', error: e, details: data } );
1389
+ }
1390
+ } ),
1391
+ );
1372
1392
  }
1373
1393
  } catch ( e ) {
1374
1394
  logger.error( { function: 'taskPushNotification', error: e } );
@@ -2006,142 +2006,338 @@ export async function questionList( req, res ) {
2006
2006
  }
2007
2007
  }
2008
2008
 
2009
+ // export async function taskQuestionList( req, res ) {
2010
+ // try {
2011
+ // const { processedcheckListId } = req.query;
2012
+
2013
+ // if ( !processedcheckListId ) {
2014
+ // return res.sendError( 'processedcheckListId is required', 400 );
2015
+ // }
2016
+
2017
+ // const findQuery = [
2018
+ // {
2019
+ // $match: {
2020
+ // _id: new ObjectId( processedcheckListId ),
2021
+ // },
2022
+ // },
2023
+ // {
2024
+ // $project: {
2025
+ // checkListName: { $ifNull: [ '$checkListName', '' ] },
2026
+ // scheduleStartTime: { $ifNull: [ '$scheduleStartTime', '' ] },
2027
+ // scheduleStartTime_iso: { $ifNull: [ '$scheduleStartTime_iso', '' ] },
2028
+ // scheduleEndTime: { $ifNull: [ '$scheduleEndTime', '' ] },
2029
+ // scheduleEndTime_iso: { $ifNull: [ '$scheduleEndTime_iso', '' ] },
2030
+ // checklistStatus: { $ifNull: [ '$checklistStatus', '' ] },
2031
+ // checkListId: { $ifNull: [ '$checkListId', '' ] },
2032
+ // startTime: { $ifNull: [ '$startTime', '' ] },
2033
+ // submitTime: { $ifNull: [ '$submitTime', '' ] },
2034
+ // allowedOverTime: { $ifNull: [ '$allowedOverTime', '' ] },
2035
+ // allowedStoreLocation: { $ifNull: [ '$allowedStoreLocation', '' ] },
2036
+ // reinitiateStatus: { $ifNull: [ '$reinitiateStatus', '' ] },
2037
+ // questionAnswers: { $ifNull: [ '$questionAnswers', '' ] },
2038
+ // userEmail: { $ifNull: [ '$userEmail', '' ] },
2039
+ // storeName: { $ifNull: [ '$storeName', '' ] },
2040
+ // redoStatus: { $ifNull: [ '$redoStatus', false ] },
2041
+ // },
2042
+ // },
2043
+ // ];
2044
+
2045
+ // const [ checklist ] = await processedTask.aggregate( findQuery );
2046
+
2047
+ // if ( !checklist ) {
2048
+ // return res.sendError( 'Task got edited, please fill again', 422 );
2049
+ // }
2050
+
2051
+ // logger.info(
2052
+ // `v5 => Checklist Continue => store Name: ${checklist.storeName}, User Email: ${checklist.userEmail}, Checklist Name: ${checklist.checkListName}`,
2053
+ // );
2054
+
2055
+ // const bucket = JSON.parse( process.env.BUCKET );
2056
+ // const sopBucket = bucket.sop;
2057
+
2058
+ // const getSignedUrl = async ( filePath ) =>
2059
+ // filePath && filePath !== '' ?
2060
+ // await signedUrl( { file_path: decodeURIComponent( filePath ), Bucket: sopBucket } ) :
2061
+ // '';
2062
+
2063
+ // for ( const section of checklist.questionAnswers || [] ) {
2064
+ // for ( const question of section.questions || [] ) {
2065
+ // const { answerType, answers = [], userAnswer = [] } = question;
2066
+ // const multiAnswer = [];
2067
+
2068
+ // if ( typeof question.questionReferenceImage === 'string' && question.questionReferenceImage ) {
2069
+ // question.questionReferenceImage = await getSignedUrl( question.questionReferenceImage );
2070
+ // } else if ( Array.isArray( question.questionReferenceImage ) && question.questionReferenceImage.length ) {
2071
+ // question.questionReferenceImage = await Promise.all(
2072
+ // question.questionReferenceImage.map( async ( img ) => await getSignedUrl( img ) ),
2073
+ // );
2074
+ // }
2075
+
2076
+ // for ( const [ ansIndex, answer ] of answers.entries() ) {
2077
+ // answer.index = ansIndex;
2078
+
2079
+ // if ( answer.referenceImage.length > 0 ) {
2080
+ // answer.referenceImage = await Promise.all(
2081
+ // answer.referenceImage.map( async ( image ) => await getSignedUrl( image ) ),
2082
+ // );
2083
+ // }
2084
+
2085
+ // if ( [ 'Capture Image', 'Capture Video' ].includes( answer.validationType ) && answer.validationAnswer ) {
2086
+ // answer.validationAnswer = await getSignedUrl( answer.validationAnswer );
2087
+ // }
2088
+
2089
+ // if ( answerType === 'multiplechoicemultiple' && answer.validationAnswer ) {
2090
+ // const validationAnswer = await getSignedUrl( answer.validationAnswer );
2091
+ // multiAnswer.push( { answer: answer.answer, no: ansIndex, validationAnswer } );
2092
+ // }
2093
+ // }
2094
+
2095
+ // for ( const [ userAnsIndex, userAns ] of userAnswer.entries() ) {
2096
+ // if ( [ 'Capture Image', 'Capture Video' ].includes( userAns.validationType ) && userAns.validationAnswer ) {
2097
+ // userAns.validationAnswer = await getSignedUrl( userAns.validationAnswer );
2098
+ // }
2099
+
2100
+ // if ( [ 'image', 'descriptiveImage', 'video', 'multipleImage' ].includes( answerType ) && userAns.answer ) {
2101
+ // userAns.answer = await getSignedUrl( userAns.answer );
2102
+ // }
2103
+
2104
+ // if ( Array.isArray( userAns.referenceImage ) ) {
2105
+ // userAns.referenceImage = await Promise.all(
2106
+ // userAns.referenceImage.map( async ( image ) => await getSignedUrl( image ) ),
2107
+ // );
2108
+ // } else if ( userAns.referenceImage ) {
2109
+ // userAns.referenceImage = await getSignedUrl( userAns.referenceImage );
2110
+ // }
2111
+
2112
+ // if ( answerType === 'multiplechoicemultiple' ) {
2113
+ // const ansIndex = multiAnswer.findIndex( ( item ) => item.answer === userAns.answer );
2114
+ // if ( ansIndex >= 0 ) {
2115
+ // multiAnswer[ansIndex].validationAnswer = userAns.validationAnswer;
2116
+ // }
2117
+ // }
2118
+
2119
+ // if ( answerType === 'multipleImage' && userAns.answer ) {
2120
+ // const manswer = await getSignedUrl( userAns.answer );
2121
+ // multiAnswer.push( { answer: manswer, no: userAnsIndex, validationAnswer: '' } );
2122
+ // }
2123
+ // }
2124
+
2125
+ // if ( [ 'multiplechoicemultiple', 'multipleImage' ].includes( answerType ) ) {
2126
+ // question.Multianswer =
2127
+ // multiAnswer.length > 0 ?
2128
+ // multiAnswer.map( ( item ) => ( {
2129
+ // answer: item.validationAnswer ? item.answer : null,
2130
+ // no: item.no,
2131
+ // validationAnswer: item.validationAnswer,
2132
+ // } ) ) :
2133
+ // answers.map( ( _, index ) => ( {
2134
+ // answer: null,
2135
+ // no: index,
2136
+ // validationAnswer: null,
2137
+ // } ) );
2138
+ // }
2139
+ // }
2140
+ // }
2141
+
2142
+ // return res.sendSuccess( [ checklist ] );
2143
+ // } catch ( error ) {
2144
+ // logger.error( { function: 'taskQuestionList', error, body: req.body } );
2145
+ // return res.sendError( error.message || 'Internal Server Error', 500 );
2146
+ // }
2147
+ // }
2148
+
2009
2149
  export async function taskQuestionList( req, res ) {
2010
2150
  try {
2011
- const { processedcheckListId } = req.query;
2012
-
2013
- if ( !processedcheckListId ) {
2014
- return res.sendError( 'processedcheckListId is required', 400 );
2151
+ let requestData = req.query;
2152
+ if ( !requestData.processedcheckListId ) {
2153
+ res.sendError( 'processedTaskId is Required', 400 );
2015
2154
  }
2016
2155
 
2017
- const findQuery = [
2018
- {
2019
- $match: {
2020
- _id: new ObjectId( processedcheckListId ),
2021
- },
2022
- },
2023
- {
2024
- $project: {
2025
- checkListName: { $ifNull: [ '$checkListName', '' ] },
2026
- scheduleStartTime: { $ifNull: [ '$scheduleStartTime', '' ] },
2027
- scheduleStartTime_iso: { $ifNull: [ '$scheduleStartTime_iso', '' ] },
2028
- scheduleEndTime: { $ifNull: [ '$scheduleEndTime', '' ] },
2029
- scheduleEndTime_iso: { $ifNull: [ '$scheduleEndTime_iso', '' ] },
2030
- checklistStatus: { $ifNull: [ '$checklistStatus', '' ] },
2031
- checkListId: { $ifNull: [ '$checkListId', '' ] },
2032
- startTime: { $ifNull: [ '$startTime', '' ] },
2033
- submitTime: { $ifNull: [ '$submitTime', '' ] },
2034
- allowedOverTime: { $ifNull: [ '$allowedOverTime', '' ] },
2035
- allowedStoreLocation: { $ifNull: [ '$allowedStoreLocation', '' ] },
2036
- reinitiateStatus: { $ifNull: [ '$reinitiateStatus', '' ] },
2037
- questionAnswers: { $ifNull: [ '$questionAnswers', '' ] },
2038
- userEmail: { $ifNull: [ '$userEmail', '' ] },
2039
- storeName: { $ifNull: [ '$storeName', '' ] },
2040
- redoStatus: { $ifNull: [ '$redoStatus', false ] },
2041
- },
2042
- },
2043
- ];
2044
-
2045
- const [ checklist ] = await processedTask.aggregate( findQuery );
2156
+ let findQuery = [];
2157
+ let findAndQuery = [];
2158
+ findAndQuery.push( { _id: new ObjectId( requestData.processedcheckListId ) } );
2159
+ findQuery.push( { $match: { $and: findAndQuery } } );
2046
2160
 
2047
- if ( !checklist ) {
2048
- return res.sendError( 'Task got edited, please fill again', 422 );
2049
- }
2161
+ findQuery.push( {
2162
+ $project: {
2163
+ checkListName: { $ifNull: [ '$checkListName', '' ] },
2164
+ scheduleStartTime: { $ifNull: [ '$scheduleStartTime', '' ] },
2165
+ scheduleStartTime_iso: { $ifNull: [ '$scheduleStartTime_iso', '' ] },
2166
+ scheduleEndTime: { $ifNull: [ '$scheduleEndTime', '' ] },
2167
+ scheduleEndTime_iso: { $ifNull: [ '$scheduleEndTime_iso', '' ] },
2168
+ checklistStatus: { $ifNull: [ '$checklistStatus', '' ] },
2169
+ checkListId: { $ifNull: [ '$checkListId', '' ] },
2170
+ startTime: { $ifNull: [ '$startTime', '' ] },
2171
+ submitTime: { $ifNull: [ '$submitTime', '' ] },
2172
+ allowedOverTime: { $ifNull: [ '$allowedOverTime', '' ] },
2173
+ allowedStoreLocation: { $ifNull: [ '$allowedStoreLocation', '' ] },
2174
+ reinitiateStatus: { $ifNull: [ '$reinitiateStatus', '' ] },
2175
+ questionAnswers: { $ifNull: [ '$questionAnswers', '' ] },
2176
+ getchecklist: { $ifNull: [ '$getchecklist', '' ] },
2177
+ userEmail: { $ifNull: [ '$userEmail', '' ] },
2178
+ storeName: { $ifNull: [ '$storeName', '' ] },
2179
+ redoStatus: { $ifNull: [ '$redoStatus', false ] },
2180
+ },
2181
+ } );
2050
2182
 
2051
- logger.info(
2052
- `v5 => Checklist Continue => store Name: ${checklist.storeName}, User Email: ${checklist.userEmail}, Checklist Name: ${checklist.checkListName}`,
2053
- );
2183
+ let getchecklist = await processedtask.aggregate( findQuery );
2184
+ if ( !getchecklist.length ) {
2185
+ return res.sendError( 'Task Got Edited Please Fill Again', 422 );
2186
+ } else {
2187
+ logger.info( `v5 => Task Continue => store Name: ${getchecklist[0].storeName}, User Email: ${getchecklist[0].userEmail}, Task Name: ${getchecklist[0].checkListName}` );
2188
+ let bucket = JSON.parse( process.env.BUCKET );
2189
+ for ( let [ secIndex, section ] of getchecklist[0].questionAnswers.entries() ) {
2190
+ for ( let [ questionIndex, question ] of section.questions.entries() ) {
2191
+ let Multianswer = [];
2192
+ let questionReferenceImage = getchecklist[0].questionAnswers[secIndex].questions[questionIndex].questionReferenceImage;
2054
2193
 
2055
- const bucket = JSON.parse( process.env.BUCKET );
2056
- const sopBucket = bucket.sop;
2057
-
2058
- const getSignedUrl = async ( filePath ) =>
2059
- filePath && filePath !== '' ?
2060
- await signedUrl( { file_path: decodeURIComponent( filePath ), Bucket: sopBucket } ) :
2061
- '';
2062
-
2063
- for ( const section of checklist.questionAnswers || [] ) {
2064
- for ( const question of section.questions || [] ) {
2065
- const { answerType, answers = [], userAnswer = [] } = question;
2066
- const multiAnswer = [];
2067
-
2068
- if ( typeof question.questionReferenceImage == 'string' && question.questionReferenceImage ) {
2069
- question.questionReferenceImage = await getSignedUrl( question.questionReferenceImage );
2070
- } else {
2071
- if ( question.questionReferenceImage.length ) {
2072
- let image = [];
2073
- for ( let img of question.questionReferenceImage ) {
2074
- image.push( await getSignedUrl( img ) );
2194
+ if ( questionReferenceImage ) {
2195
+ if ( Array.isArray( questionReferenceImage ) ) {
2196
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].questionReferenceImage = await Promise.all(
2197
+ questionReferenceImage.map( async ( image ) => await signedUrl( { file_path: decodeURIComponent( image ), Bucket: bucket.sop } ) ),
2198
+ );
2199
+ } else if ( questionReferenceImage !== '' ) {
2200
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].questionReferenceImage = await signedUrl( {
2201
+ file_path: decodeURIComponent( questionReferenceImage ),
2202
+ Bucket: bucket.sop,
2203
+ } );
2075
2204
  }
2076
- question.questionReferenceImage = image;
2077
2205
  }
2078
- }
2079
2206
 
2080
- for ( const [ ansIndex, answer ] of answers.entries() ) {
2081
- answer.index = ansIndex;
2207
+ for ( let [ ansIndex, answer ] of question.answers.entries() ) {
2208
+ let referenceImage = getchecklist[0].questionAnswers[secIndex].questions[questionIndex].answers[ansIndex].referenceImage;
2209
+
2210
+ if ( referenceImage ) {
2211
+ if ( Array.isArray( referenceImage ) ) {
2212
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].answers[ansIndex].referenceImage = await Promise.all(
2213
+ referenceImage.map( async ( image ) => await signedUrl( { file_path: decodeURIComponent( image ), Bucket: bucket.sop } ) ),
2214
+ );
2215
+ } else if ( referenceImage !== '' ) {
2216
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].answers[ansIndex].referenceImage = await signedUrl( {
2217
+ file_path: decodeURIComponent( referenceImage ),
2218
+ Bucket: bucket.sop,
2219
+ } );
2220
+ }
2221
+ }
2082
2222
 
2083
- if ( answer.referenceImage.length > 0 ) {
2084
- answer.referenceImage = await Promise.all(
2085
- answer.referenceImage.map( async ( image ) => {
2086
- return await getSignedUrl( image );
2087
- } ),
2088
- );
2223
+ if ( question.answerType == 'multiplechoicemultiple' ) {
2224
+ let checkvalidation = null;
2225
+ if ( answer.validationAnswer && answer.validationAnswer != '' ) {
2226
+ checkvalidation = await signedUrl( { file_path: decodeURIComponent( answer.validationAnswer ), Bucket: bucket.sop } );
2227
+ }
2228
+ Multianswer.push( { 'answer': answer.answer, 'no': ansIndex, 'validationAnswer': checkvalidation } );
2229
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].answers[ansIndex].index = ansIndex;
2230
+ }
2231
+ if ( ( answer.validationType == 'Capture Image' || answer.validationType == 'Capture Video' ) && answer.validationAnswer && answer.validationAnswer != '' ) {
2232
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].answers[ansIndex].validationAnswer = await signedUrl( {
2233
+ file_path: decodeURIComponent( answer.validationAnswer ),
2234
+ Bucket: bucket.sop,
2235
+ } );
2236
+ }
2089
2237
  }
2090
2238
 
2091
- if ( [ 'Capture Image', 'Capture Video' ].includes( answer.validationType ) && answer.validationAnswer ) {
2092
- answer.validationAnswer = await getSignedUrl( answer.validationAnswer );
2093
- }
2239
+ if ( question?.userAnswer ) {
2240
+ for ( let [ userAnsIndex, userAns ] of question.userAnswer.entries() ) {
2241
+ if ( ( userAns.validationType == 'Capture Image' || userAns.validationType == 'Capture Video' ) && userAns.validationAnswer && userAns.validationAnswer != '' ) {
2242
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].validationAnswer = await signedUrl( {
2243
+ file_path: decodeURIComponent( userAns.validationAnswer ),
2244
+ Bucket: bucket.sop,
2245
+ } );
2246
+ }
2247
+ if ( [ 'image', 'descriptiveImage', 'video' ].includes( question.answerType ) && userAns.answer != '' ) {
2248
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].answer = await signedUrl( {
2249
+ file_path: decodeURIComponent( userAns.answer ),
2250
+ Bucket: bucket.sop,
2251
+ } );
2252
+ }
2253
+ if ( userAns.referenceImage != '' ) {
2254
+ getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].referenceImage = await signedUrl( {
2255
+ file_path: decodeURIComponent( userAns.referenceImage ),
2256
+ Bucket: bucket.sop,
2257
+ } );
2258
+ }
2259
+ if ( question.answerType == 'multiplechoicemultiple' ) {
2260
+ let ansIndex = Multianswer.findIndex( ( item ) => item.answer == userAns.answer );
2261
+ if ( ansIndex ) {
2262
+ Multianswer[ansIndex].validationAnswer = userAns.validationAnswer;
2263
+ }
2264
+ }
2265
+ if ( question.answerType == 'multipleImage' ) {
2266
+ if ( userAns && userAns.answer && userAns.answer != '' ) {
2267
+ let manswer = await signedUrl( { file_path: decodeURIComponent( userAns.answer ), Bucket: bucket.sop } );
2268
+ Multianswer.push( { 'answer': manswer, 'no': userAnsIndex, 'validationAnswer': '' } );
2269
+ } else {
2094
2270
 
2095
- if ( answerType === 'multiplechoicemultiple'&& answer.validationAnswer ) {
2096
- const validationAnswer = await getSignedUrl( answer.validationAnswer );
2097
- multiAnswer.push( { answer: answer.answer, no: ansIndex, validationAnswer } );
2271
+ }
2272
+ }
2273
+ }
2098
2274
  }
2099
- }
2100
-
2101
- for ( const [ userAnsIndex, userAns ] of userAnswer.entries() ) {
2102
- if ( [ 'Capture Image', 'Capture Video' ].includes( userAns.validationType ) && userAns.validationAnswer ) {
2103
- userAns.validationAnswer = await getSignedUrl( userAns.validationAnswer );
2275
+ if ( question.answerType == 'multiplechoicemultiple' ) {
2276
+ Multianswer.forEach( ( item ) => {
2277
+ if ( item.validationAnswer == null ) {
2278
+ item.answer = null;
2279
+ }
2280
+ } );
2281
+ if ( Multianswer.length ) {
2282
+ question.Multianswer = Multianswer;
2283
+ } else {
2284
+ question.Multianswer = Multianswer;
2285
+ }
2104
2286
  }
2105
-
2106
- if ( [ 'image', 'descriptiveImage', 'video' ].includes( answerType ) && userAns.answer ) {
2107
- userAns.answer = await getSignedUrl( userAns.answer );
2287
+ if ( question.answerType == 'multipleImage' ) {
2288
+ if ( Multianswer.length ) {
2289
+ question.Multianswer = Multianswer;
2290
+ } else {
2291
+ Multianswer.push( { 'answer': null, 'no': 0, 'validationAnswer': null } );
2292
+ question.Multianswer = Multianswer;
2293
+ }
2108
2294
  }
2295
+ }
2296
+ }
2109
2297
 
2110
- userAns.referenceImage = userAns.referenceImage ? await getSignedUrl( userAns.referenceImage ) : '';
2111
-
2112
- if ( answerType === 'multiplechoicemultiple' ) {
2113
- const ansIndex = multiAnswer.findIndex( ( item ) => item.answer === userAns.answer );
2114
- if ( ansIndex >= 0 ) {
2115
- multiAnswer[ansIndex].validationAnswer = userAns.validationAnswer;
2298
+ let questions = [];
2299
+ function processQuestion( question, section, questions, nested = false ) {
2300
+ let findExists = questions.find( ( item ) => item?.qno && item.qno == question.qno );
2301
+ if ( findExists && nested ) {
2302
+ let findIndex = questions.findIndex( ( item ) => item?.qno && item.qno == question.qno );
2303
+ questions.splice( findIndex, 1 );
2304
+ questions.push( question );
2305
+ for ( let answer of question.answers ) {
2306
+ if ( answer.showLinked && answer?.linkedQuestion != '' ) {
2307
+ let linkedQuestion = section.questions.find( ( item ) => item.qno == answer.linkedQuestion );
2308
+ if ( linkedQuestion ) {
2309
+ processQuestion( linkedQuestion, section, questions, true );
2310
+ }
2116
2311
  }
2117
2312
  }
2118
-
2119
- if ( answerType === 'multipleImage' && userAns.answer ) {
2120
- const manswer = await getSignedUrl( userAns.answer );
2121
- multiAnswer.push( { answer: manswer, no: userAnsIndex, validationAnswer: '' } );
2313
+ }
2314
+ if ( !findExists ) {
2315
+ questions.push( question );
2316
+ for ( let answer of question.answers ) {
2317
+ if ( answer.showLinked && answer?.linkedQuestion != '' ) {
2318
+ let linkedQuestion = section.questions.find( ( item ) => item.qno == answer.linkedQuestion );
2319
+ if ( linkedQuestion ) {
2320
+ processQuestion( linkedQuestion, section, questions, true );
2321
+ }
2322
+ }
2122
2323
  }
2123
2324
  }
2124
-
2125
- if ( [ 'multiplechoicemultiple', 'multipleImage' ].includes( answerType ) ) {
2126
- question.Multianswer = multiAnswer.length > 0 ?
2127
- multiAnswer.map( ( item ) => ( {
2128
- answer: item.validationAnswer ? item.answer : null,
2129
- no: item.no,
2130
- validationAnswer: item.validationAnswer,
2131
- } ) ) :
2132
- answers.map( ( _, index ) => ( {
2133
- answer: null,
2134
- no: index,
2135
- validationAnswer: null,
2136
- } ) );
2325
+ }
2326
+ for ( let [ index, data ] of getchecklist.entries() ) {
2327
+ for ( let [ secIndex, section ] of data.questionAnswers.entries() ) {
2328
+ questions = [];
2329
+ for ( let question of section.questions ) {
2330
+ processQuestion( question, section, questions );
2331
+ }
2332
+ getchecklist[index].questionAnswers[secIndex].questions = questions;
2137
2333
  }
2138
2334
  }
2139
- }
2140
2335
 
2141
- return res.sendSuccess( [ checklist ] );
2142
- } catch ( error ) {
2143
- logger.error( { function: 'taskQuestionList', error, body: req.body } );
2144
- return res.sendError( error.message || 'Internal Server Error', 500 );
2336
+ return res.sendSuccess( getchecklist );
2337
+ }
2338
+ } catch ( e ) {
2339
+ logger.error( { function: 'taskQuestionList', error: e, body: req.body } );
2340
+ return res.sendError( e, 500 );
2145
2341
  }
2146
2342
  }
2147
2343
 
@@ -932,6 +932,15 @@ export const updateConfigure =async ( req, res ) => {
932
932
  return res.sendError( 'no data found', 204 );
933
933
  }
934
934
 
935
+ if ( checklistDetails?.publishDate && inputBody.submitType == 'publish' ) {
936
+ let date = dayjs();
937
+ let diff = date.diff( dayjs.utc( checklistDetails?.publishDate ), 'minutes' );
938
+ if ( diff < 5 ) {
939
+ let mins = ( 5 - diff ) > 1 ? 'minutes' : 'minute';
940
+ return res.sendError( `Please try after ${5 - diff} ${mins}`, 400 );
941
+ }
942
+ }
943
+
935
944
  if ( inputBody?.checkListDetails?.scheduleRepeatedMonthSetup == 'date' ) {
936
945
  inputBody.checkListDetails.scheduleRepeatedDay = inputBody?.checkListDetails?.scheduleRepeatedDay;
937
946
  }
@@ -1200,6 +1200,7 @@ export const checklistInfo = async ( req, res ) => {
1200
1200
  date_string: 1,
1201
1201
  sourceCheckList_id: 1,
1202
1202
  reinitiateStatus: 1,
1203
+ redoStatus: 1,
1203
1204
  },
1204
1205
  } );
1205
1206
 
@@ -1244,6 +1245,7 @@ export const checklistInfo = async ( req, res ) => {
1244
1245
  checklistDate: '$date_string',
1245
1246
  sourceCheckList_id: 1,
1246
1247
  reinitiateStatus: 1,
1248
+ redoStatus: 1,
1247
1249
  },
1248
1250
  } );
1249
1251
 
@@ -3575,9 +3577,9 @@ export async function sendAlert( req, res ) {
3575
3577
  if ( getToken?.fcmToken ) {
3576
3578
  let existCheck = checklistDetails.findIndex( ( item ) => item.checklistName == data.checkListName );
3577
3579
  if ( existCheck != -1 ) {
3578
- checklistDetails[existCheck].token.push( getToken.fcmToken );
3580
+ checklistDetails[existCheck].token.push( { token: getToken.fcmToken, store: data.storeName } );
3579
3581
  } else {
3580
- checklistDetails.push( { checklistName: data.checkListName, token: [ getToken.fcmToken ] } );
3582
+ checklistDetails.push( { checklistName: data.checkListName, token: [ { token: getToken.fcmToken, store: data.storeName } ] } );
3581
3583
  }
3582
3584
  }
3583
3585
  } ),
@@ -3588,6 +3590,38 @@ export async function sendAlert( req, res ) {
3588
3590
  return res.sendError( 'no data found', 204 );
3589
3591
  }
3590
3592
 
3593
+ const checklistPromise = checklistDetails.map( async ( ele ) => {
3594
+ await sendNotification( ele );
3595
+ } );
3596
+
3597
+ await Promise.all( checklistPromise );
3598
+ return res.sendSuccess( 'Alert send successfully' );
3599
+
3600
+ async function sendNotification( data ) {
3601
+ return Promise.all(
3602
+ data.token.map( async ( item ) => {
3603
+ const message = {
3604
+ token: item.token,
3605
+ notification: {
3606
+ title: `${item.store} Checklist In-progress`,
3607
+ body: `The ${data.checklistName} checklist is currently in progress. Complete now to avoid compliance.`,
3608
+ },
3609
+ data: {
3610
+ customKey: 'customValue',
3611
+ },
3612
+ };
3613
+ try {
3614
+ let response = await admin.messaging().send( message );
3615
+ if ( !response ) {
3616
+ logger.error( { message: 'send alert', error: element.token } );
3617
+ }
3618
+ } catch ( e ) {
3619
+ logger.error( { message: 'send alert', error: e, details: data } );
3620
+ }
3621
+ } ),
3622
+ );
3623
+ }
3624
+
3591
3625
  for ( let [ index, item ] of checklistDetails.entries() ) {
3592
3626
  const message = {
3593
3627
  tokens: item.token,