tango-app-api-trax 1.0.0-beta-task.3 → 1.0.0-beta-task.4

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.3",
3
+ "version": "1.0.0-beta-task.4",
4
4
  "description": "Trax",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -26,7 +26,7 @@
26
26
  "mongodb": "^6.8.0",
27
27
  "nodemon": "^3.1.4",
28
28
  "path": "^0.12.7",
29
- "tango-api-schema": "^2.2.2",
29
+ "tango-api-schema": "2.2.3",
30
30
  "tango-app-api-middleware": "3.1.43-alpha.10",
31
31
  "url": "^0.11.4",
32
32
  "winston": "^3.13.1",
@@ -572,10 +572,9 @@ export const getPDFCSVChecklistDetails = async ( req, res ) => {
572
572
 
573
573
  export async function cancelDownload( req, res ) {
574
574
  try {
575
-
576
- let finddata = await downloadService.findOne( { _id: req.params.id , status: 'completed' } );
577
- if(finddata){
578
- return res.sendError('Download Already Completed' ,500)
575
+ let finddata = await downloadService.findOne( { _id: req.params.id, status: 'completed' } );
576
+ if ( finddata ) {
577
+ return res.sendError( 'Download Already Completed', 500 );
579
578
  }
580
579
 
581
580
  let update = await downloadService.updateOne( { _id: req.params.id }, { status: 'canceled' } );
@@ -337,7 +337,7 @@ export async function redoChecklist( req, res ) {
337
337
  return res.sendError( 'section is not found', 400 );
338
338
  }
339
339
 
340
- let data = { ...question[sectionIndex].questions[req.body.payload.qno - 1], redo: true };
340
+ let data = { ...question[sectionIndex].questions[req.body.payload.qno - 1], redo: true, redoComment: req.body.payload?.checklistDescription || '' };
341
341
  let userAnswer = data.userAnswer;
342
342
 
343
343
 
@@ -9,6 +9,8 @@ import * as otpServices from '../services/otp.service.js';
9
9
  import * as downloadServices from '../services/download.services.js';
10
10
  import * as storeService from '../services/store.service.js';
11
11
  import * as userService from '../services/user.service.js';
12
+ import * as clientService from '../services/clients.services.js';
13
+ import * as processedTaskService from '../services/processedTaskList.service.js';
12
14
  import dayjs from 'dayjs';
13
15
  import customParseFormat from 'dayjs/plugin/customParseFormat.js';
14
16
  import timeZone from 'dayjs/plugin/timezone.js';
@@ -1146,3 +1148,229 @@ export async function getDownloads( req, res ) {
1146
1148
  else res.sendError( error, 500 );
1147
1149
  }
1148
1150
  };
1151
+
1152
+ export async function getPDFCSVChecklistDetails( req, res ) {
1153
+ try {
1154
+ let requestData = req.body;
1155
+ let getchecklistQuery = [];
1156
+ getchecklistQuery.push( new ObjectId( requestData.checklist ) );
1157
+ let selecteditems;
1158
+ if ( requestData.selectedFields ) {
1159
+ let selectedFields = requestData.selectedFields.split( ',' );
1160
+ let records = {};
1161
+ selectedFields.forEach( ( element ) => {
1162
+ records[element] = 1;
1163
+ } );
1164
+ selecteditems = records;
1165
+ }
1166
+
1167
+ let query = [
1168
+ {
1169
+ $match: {
1170
+ $and: [
1171
+ { _id: { $in: getchecklistQuery } },
1172
+ ],
1173
+ },
1174
+ },
1175
+ {
1176
+ $project: selecteditems,
1177
+ },
1178
+ ];
1179
+
1180
+ let getchecklistsData = await processedchecklist.aggregate( query );
1181
+ if ( getchecklistsData && getchecklistsData.length >0 ) {
1182
+ let getbrand = await clientService.findOne( { clientId: getchecklistsData[0].client_id }, { 'clientName': 1, 'profileDetails.logo': 1 } );
1183
+ let brandInfo = {};
1184
+ if ( getbrand ) {
1185
+ brandInfo.clientName = getbrand.clientName;
1186
+ brandInfo.brandLogo = getchecklistsData[0].client_id+'/logo/'+getbrand.profileDetails.logo;
1187
+ }
1188
+
1189
+ // let resultData = [];
1190
+ let getstore = await storeService.findOne( { storeId: getchecklistsData[0].store_id }, { storeName: 1, storeProfile: 1 } );
1191
+ getchecklistsData[0].location = getstore?.storeProfile?.location || '--';
1192
+ getchecklistsData[0].city = getstore?.storeProfile?.city || '--';
1193
+ getchecklistsData[0].state = getstore?.storeProfile?.state || '--';
1194
+ // console.log("getchecklistsData.length =>", getchecklistsData.length)
1195
+ // return res.sendSuccess({brandInfo,getchecklistsData});
1196
+ // let getchecklist = getchecklistsData;
1197
+ let questions = [];
1198
+ function processQuestion( question, section, questions, nested=false ) {
1199
+ let findExists = questions.find( ( item ) => item?.qno && item.qno == question.qno );
1200
+ if ( findExists && nested ) {
1201
+ let findIndex = questions.findIndex( ( item ) => item?.qno && item.qno == question.qno );
1202
+ questions.splice( findIndex, 1 );
1203
+ questions.push( question );
1204
+ }
1205
+ if ( !findExists ) {
1206
+ questions.push( question );
1207
+ for ( let answer of question.answers ) {
1208
+ if ( answer.showLinked && answer?.linkedQuestion != '' ) {
1209
+ let linkedQuestion = section.questions.find( ( item ) => item.qno == answer.linkedQuestion );
1210
+ if ( linkedQuestion ) {
1211
+ processQuestion( linkedQuestion, section, questions, true );
1212
+ }
1213
+ }
1214
+ }
1215
+ }
1216
+ }
1217
+ for ( let [ index, data ] of getchecklistsData.entries() ) {
1218
+ for ( let [ secIndex, section ] of data.questionAnswers.entries() ) {
1219
+ questions = [];
1220
+ for ( let question of section.questions ) {
1221
+ processQuestion( question, section, questions );
1222
+ }
1223
+ getchecklistsData[index].questionAnswers[secIndex].questions = questions;
1224
+ }
1225
+ }
1226
+
1227
+ getchecklistsData.forEach( ( item, index ) => {
1228
+ item.questionAnswers.forEach( ( qAnswers, qaIdx ) => {
1229
+ qAnswers.questions.forEach( ( question, sIdx ) => {
1230
+ question.answers.forEach( ( answer, ansIdx ) => {
1231
+ if ( answer?.referenceImage ) {
1232
+ getchecklistsData[index].questionAnswers[qaIdx].questions[sIdx].answers[ansIdx].referenceImage = decodeURIComponent( answer?.referenceImage );
1233
+ }
1234
+ if ( ( getchecklistsData[index].questionAnswers[qaIdx].questions[sIdx].answerType == 'video' || getchecklistsData[index].questionAnswers[qaIdx].questions[sIdx].answerType == 'image' || getchecklistsData[index].questionAnswers[qaIdx].questions[sIdx].answerType == 'descriptiveImage' ) && answer?.answer ) {
1235
+ getchecklistsData[index].questionAnswers[qaIdx].questions[sIdx].answers[ansIdx].answer = decodeURIComponent( answer?.answer );
1236
+ }
1237
+ if ( answer?.validationType && ( answer?.validationType == 'Capture Image' || answer?.validationType == 'Capture Video' ) && answer?.validationAnswer ) {
1238
+ getchecklistsData[index].questionAnswers[qaIdx].questions[sIdx].answers[ansIdx].validationAnswer = decodeURIComponent( answer?.validationAnswer );
1239
+ }
1240
+ // console.log(getchecklistsData[index].questionAnswers[qaIdx].questions[sIdx].answers[ansIdx].validationAnswer)
1241
+ } );
1242
+ question.userAnswer.forEach( ( uAnswer, uIdx ) => {
1243
+ if ( uAnswer?.referenceImage ) {
1244
+ getchecklistsData[index].questionAnswers[qaIdx].questions[sIdx].userAnswer[uIdx].referenceImage = decodeURIComponent( uAnswer?.referenceImage );
1245
+ }
1246
+
1247
+ if ( ( getchecklistsData[index].questionAnswers[qaIdx].questions[sIdx].answerType == 'video' || getchecklistsData[index].questionAnswers[qaIdx].questions[sIdx].answerType == 'image' || getchecklistsData[index].questionAnswers[qaIdx].questions[sIdx].answerType == 'descriptiveImage' ) && uAnswer?.answer ) {
1248
+ getchecklistsData[index].questionAnswers[qaIdx].questions[sIdx].userAnswer[uIdx].answer = decodeURIComponent( uAnswer?.answer );
1249
+ }
1250
+ if ( uAnswer?.validationType && ( uAnswer?.validationType == 'Capture Image' || uAnswer?.validationType == 'Capture Video' ) && uAnswer?.validationAnswer ) {
1251
+ getchecklistsData[index].questionAnswers[qaIdx].questions[sIdx].userAnswer[uIdx].validationAnswer = decodeURIComponent( uAnswer?.validationAnswer );
1252
+ }
1253
+ } );
1254
+ } );
1255
+ } );
1256
+ } );
1257
+ return res.sendSuccess( { brandInfo, getchecklistsData } );
1258
+ } else {
1259
+ return res.sendError( 'Checklist Not Available', 204 );
1260
+ }
1261
+ } catch ( error ) {
1262
+ console.log( 'getPDFCSVChecklistDetails error =>', error );
1263
+ if ( error.name === 'ValidationError' ) res.sendBadRequest( error );
1264
+ else res.sendError( error, 500 );
1265
+ }
1266
+ }
1267
+
1268
+
1269
+ export async function taskPushNotification( req, res ) {
1270
+ try {
1271
+ let query = [ {
1272
+ $match: {
1273
+ date_iso: new Date( dayjs().format( 'YYYY-MM-DD' ) ),
1274
+ $expr: { $gt: [ { $size: '$remainder' }, 0 ] },
1275
+ checklistStatus: { $ne: 'submit' },
1276
+ },
1277
+ } ];
1278
+
1279
+ if ( req.body.client_id && req.body.client_id.length ) {
1280
+ query.push( {
1281
+ $match: {
1282
+ client_id: { $in: req.body.client_id },
1283
+ },
1284
+ } );
1285
+ }
1286
+
1287
+ query.push( {
1288
+ $project: {
1289
+ scheduleEndTime_iso: 1,
1290
+ store_id: 1,
1291
+ storeName: 1,
1292
+ checkListId: 1,
1293
+ checkListName: 1,
1294
+ client_id: 1,
1295
+ date_iso: 1,
1296
+ userId: 1,
1297
+ scheduleEndTime: 1,
1298
+ remainder: 1,
1299
+ },
1300
+ } );
1301
+
1302
+
1303
+ let taskList = await processedTaskService.aggregate( query );
1304
+ console.log( taskList );
1305
+
1306
+
1307
+ if ( !taskList.length ) {
1308
+ return res.sendError( 'no data', 204 );
1309
+ }
1310
+
1311
+ let taskDetails = [];
1312
+
1313
+ let promises = taskList.map( async ( item ) => {
1314
+ await checkTimeZone( [ item ] );
1315
+ } );
1316
+
1317
+ await Promise.all( promises );
1318
+
1319
+ async function checkTimeZone( ele ) {
1320
+ return Promise.all(
1321
+ ele.map( async ( data ) => {
1322
+ let getStoreZone = await storeService.findOne(
1323
+ { storeId: data.store_id, clientId: data.client_id },
1324
+ { storeProfile: 1 },
1325
+ );
1326
+ if ( getStoreZone ) {
1327
+ let taskDate = dayjs( dayjs.utc( data.scheduleEndTime_iso ) ).tz( getStoreZone.storeProfile.timeZone, true );
1328
+ let date = dayjs( dayjs().format( 'hh:mm A' ), 'hh:mm A' ).tz( getStoreZone.storeProfile.timeZone );
1329
+ console.log( taskDate.diff( date, 'minute' ) );
1330
+
1331
+ if ( data?.remainder?.length && data.remainder.includes( taskDate.diff( date, 'minute' ) ) ) {
1332
+ let getToken = await userService.findOne( { _id: data.userId }, { fcmToken: 1 } );
1333
+ if ( getToken?.fcmToken ) {
1334
+ let existCheck = taskDetails.findIndex( ( item ) => item.checklistName == data.checkListName );
1335
+ if ( existCheck != -1 ) {
1336
+ taskDetails[existCheck].token.push( getToken.fcmToken );
1337
+ } else {
1338
+ taskDetails.push( { checklistName: data.checkListName, token: [ getToken.fcmToken ] } );
1339
+ }
1340
+ }
1341
+ }
1342
+ }
1343
+ } ),
1344
+ );
1345
+ }
1346
+
1347
+ if ( !taskDetails.length ) {
1348
+ return res.sendError( 'no data found', 204 );
1349
+ }
1350
+
1351
+ for ( let [ index, item ] of taskDetails.entries() ) {
1352
+ const message = {
1353
+ tokens: item.token,
1354
+ notification: {
1355
+ title: 'Reminder to Fill checklist',
1356
+ body: `${item.checklistName} checklist is going to breach within few minutes`,
1357
+ },
1358
+ data: {
1359
+ customKey: 'customValue',
1360
+ },
1361
+ };
1362
+ const response = await admin.messaging().sendEachForMulticast( message );
1363
+ if ( response.successCount ) {
1364
+ logger.info( { message: 'push notification', success: item.token } );
1365
+ if ( index == taskDetails.length - 1 ) {
1366
+ return res.sendSuccess( 'Push notification send successfully' );
1367
+ }
1368
+ } else {
1369
+ logger.error( { message: 'push notification', error: item.token } );
1370
+ }
1371
+ }
1372
+ } catch ( e ) {
1373
+ logger.error( { function: 'taskPushNotification', error: e } );
1374
+ return res.sendError( e, 500 );
1375
+ }
1376
+ }
@@ -386,6 +386,7 @@ export async function startTask( req, res ) {
386
386
  const logData = {
387
387
  store_id: task.store_id,
388
388
  storeName: task.storeName,
389
+ type: 'task',
389
390
  action: 'started',
390
391
  checklistId: task.checkListId,
391
392
  checkListName: task.checkListName,
@@ -879,6 +880,7 @@ export async function sopMobileTaskMultiSectionFormatter( req, res, next ) {
879
880
  structure.questionReferenceImage = qaAnswers[j].questionReferenceImage,
880
881
  structure.descriptivetype = qaAnswers[j].descriptivetype,
881
882
  structure.redo = qaAnswers[j]?.redo,
883
+ structure.redoComment = qaAnswers[j]?.redoComment,
882
884
  newArray.push( structure );
883
885
  } else if ( qaAnswers[j].answerType == 'multiplechoicesingle' ) {
884
886
  let qaans = qaAnswers[j].answers;
@@ -919,6 +921,7 @@ export async function sopMobileTaskMultiSectionFormatter( req, res, next ) {
919
921
  structure.questionReferenceImage = qaAnswers[j].questionReferenceImage,
920
922
  structure.descriptivetype = qaAnswers[j].descriptivetype,
921
923
  structure.redo = qaAnswers[j]?.redo,
924
+ structure.redoComment = qaAnswers[j]?.redoComment,
922
925
  newArray.push( structure );
923
926
  } else if ( qaAnswers[j].answerType == 'multiplechoicemultiple' ) {
924
927
  let qaans = qaAnswers[j].answers;
@@ -963,6 +966,7 @@ export async function sopMobileTaskMultiSectionFormatter( req, res, next ) {
963
966
  structure.questionReferenceImage = qaAnswers[j].questionReferenceImage,
964
967
  structure.descriptivetype = qaAnswers[j].descriptivetype,
965
968
  structure.redo = qaAnswers[j]?.redo,
969
+ structure.redoComment = qaAnswers[j]?.redoComment,
966
970
  newArray.push( structure );
967
971
  } else if ( qaAnswers[j].answerType == 'multipleImage' ) {
968
972
  let separatedArray = typeof requestSection[i].Multianswer == 'string' ? JSON.parse( requestSection[i].Multianswer ) : requestSection[i].Multianswer;
@@ -1012,6 +1016,7 @@ export async function sopMobileTaskMultiSectionFormatter( req, res, next ) {
1012
1016
  structure.questionReferenceImage = qaAnswers[j].questionReferenceImage,
1013
1017
  structure.descriptivetype = qaAnswers[j].descriptivetype,
1014
1018
  structure.redo = qaAnswers[j]?.redo,
1019
+ structure.redoComment = qaAnswers[j]?.redoComment,
1015
1020
  newArray.push( structure );
1016
1021
  } else {
1017
1022
  let des = [];
@@ -1059,6 +1064,7 @@ export async function sopMobileTaskMultiSectionFormatter( req, res, next ) {
1059
1064
  structure.questionReferenceImage = qaAnswers[j].questionReferenceImage,
1060
1065
  structure.descriptivetype = qaAnswers[j].descriptivetype,
1061
1066
  structure.redo = qaAnswers[j]?.redo,
1067
+ structure.redoComment = qaAnswers[j]?.redoComment,
1062
1068
  newArray.push( structure );
1063
1069
  }
1064
1070
  }
@@ -2266,10 +2272,15 @@ export async function login( req, res ) {
2266
2272
  await userService.updateOne( { _id: userDetails?._id }, { fcmToken: '' } );
2267
2273
  }
2268
2274
 
2275
+ await userService.updateOne( { _id: result?._id }, { } );
2276
+
2277
+
2269
2278
  const auth = await create( record );
2270
- if ( !result?.refreshToken ) {
2271
- await userService.updateOne( { _id: result?._id }, { refreshToken: token?.refreshToken } );
2272
- }
2279
+ let data = {
2280
+ fcmToken: inputData.fcmToken,
2281
+ ...( !result?.refreshToken ) ? { refreshToken: token?.refreshToken } : {},
2282
+ };
2283
+ await userService.updateOne( { _id: result?._id }, data );
2273
2284
 
2274
2285
  if ( auth ) {
2275
2286
  return res.sendSuccess( { result: token } );
@@ -208,6 +208,7 @@ export const create = async ( req, res ) => {
208
208
  createdByName: req.user.userName,
209
209
  client_id: req.body.clientId,
210
210
  sections: inputBody?.sections,
211
+ createdByEmail: req.user.email,
211
212
  };
212
213
  await checklistLogs.create( logInsertData );
213
214
  if ( inputBody.sections.length ) {
@@ -494,6 +495,7 @@ export const deleteChecklist = async ( req, res ) => {
494
495
  createdBy: req.user._id,
495
496
  createdByName: req.user.userName,
496
497
  client_id: req.user?.clientId || checklistDetails?.client_id,
498
+ createdByEmail: req.user.email,
497
499
  };
498
500
  await checklistLogs.create( logInsertData );
499
501
  // await checklistService.updateMany( { type: 'section', checkListId: req.params.checklistId }, { isdeleted: true } );
@@ -547,6 +549,7 @@ export const duplicateChecklist = async ( req, res ) => {
547
549
  createdBy: req.user._id,
548
550
  createdByName: req.user.userName,
549
551
  client_id: req.query.clientId,
552
+ createdByEmail: req.user.email,
550
553
  };
551
554
  await checklistLogs.create( logInsertData );
552
555
  checklistService.create( dupDetails ).then( async ( data ) => {
@@ -635,6 +638,7 @@ export const update = async ( req, res ) => {
635
638
  createdByName: req.user.userName,
636
639
  client_id: req.body.clientId,
637
640
  sections: inputBody?.sections,
641
+ createdByEmail: req.user.email,
638
642
  };
639
643
  await checklistLogs.create( logInsertData );
640
644
  if ( inputBody.sections.length ) {
@@ -913,6 +917,8 @@ export const updateConfigure =async ( req, res ) => {
913
917
  createdBy: req.user._id,
914
918
  createdByName: req.user.userName,
915
919
  client_id: req.body.clientId,
920
+ createdByEmail: req.user.email,
921
+ approver: inputBody?.checkListDetails?.approver || [],
916
922
  };
917
923
  await checklistLogs.create( logInsertData );
918
924
 
@@ -976,6 +982,7 @@ export const updateConfigure =async ( req, res ) => {
976
982
  checkListId: inputBody.checkListDetails._id,
977
983
  type: 'checklist',
978
984
  checkListName: inputBody?.checkListDetails.checkListName,
985
+ client_id: inputBody?.clientId,
979
986
  } );
980
987
  }
981
988
  } );
@@ -1274,6 +1281,7 @@ export const updatePublish = async ( req, res ) => {
1274
1281
  createdBy: req.user._id,
1275
1282
  createdByName: req.user.userName,
1276
1283
  client_id: req.body.clientId,
1284
+ createdByEmail: req.user.email,
1277
1285
  };
1278
1286
  await checklistLogs.create( logInsertData );
1279
1287
  return res.sendSuccess( { checklistName: getCheckDetails.checkListName, message: 'Updated Successfully' } );
@@ -3529,7 +3529,7 @@ export async function sendAlert( req, res ) {
3529
3529
  try {
3530
3530
  let inputBody = req.body;
3531
3531
  let query = {
3532
- date_iso: new Date( dayjs( inputBody.date ).format( 'YYYY-MM-DD' ) ),
3532
+ date_iso: new Date( dayjs().format( 'YYYY-MM-DD' ) ),
3533
3533
  sourceCheckList_id: new mongoose.Types.ObjectId( inputBody.sourceCheckList_id ),
3534
3534
  checklistStatus: { $ne: 'submit' },
3535
3535
  timeFlag: 0,
@@ -14,8 +14,10 @@ internalTraxRouter
14
14
  .post( '/updateAomDetails', isAllowedInternalAPIHandler, internalController.aomupdateCollection )
15
15
  .post( '/updateSaleManagerDetails', isAllowedInternalAPIHandler, internalController.saleUpdateCollection )
16
16
  .get( '/profile', isAllowedMobileSessionHandler, internalController.getUserStoreList )
17
- .post( '/pushNotification', internalController.pushNotification )
17
+ .post( '/pushNotification', isAllowedInternalAPIHandler, internalController.pushNotification )
18
+ .post( '/taskPushNotification', isAllowedInternalAPIHandler, internalController.taskPushNotification )
18
19
  .get( '/checklist', isAllowedInternalAPIHandler, internalController.internalAPIChecklist )
20
+ .post( '/getPDFCSVChecklistDetails', isAllowedInternalAPIHandler, internalController.getPDFCSVChecklistDetails )
19
21
  .get( '/getOTP', isAllowedInternalAPIHandler, internalController.getOTP )
20
22
  .get( '/getDownloads', isAllowedInternalAPIHandler, internalController.getDownloads );
21
23