tango-app-api-trax 3.7.52 → 3.7.54

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": "3.7.52",
3
+ "version": "3.7.54",
4
4
  "description": "Trax",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -23,11 +23,12 @@
23
23
  "firebase-admin": "^13.0.0",
24
24
  "fs": "^0.0.1-security",
25
25
  "handlebars": "^4.7.8",
26
+ "html-pdf": "^3.0.1",
26
27
  "lodash": "^4.17.21",
27
28
  "mongodb": "^6.8.0",
28
29
  "nodemon": "^3.1.4",
29
30
  "path": "^0.12.7",
30
- "tango-api-schema": "^2.5.59",
31
+ "tango-api-schema": "^2.5.61",
31
32
  "tango-app-api-middleware": "^3.5.2",
32
33
  "url": "^0.11.4",
33
34
  "winston": "^3.13.1",
@@ -0,0 +1,11 @@
1
+ import Handlebars from 'handlebars';
2
+
3
+ Handlebars.registerHelper( 'eq', function( arg1, arg2, options ) {
4
+ return ( arg1 == arg2 ) ? options.fn( this ) : options.inverse( this );
5
+ } );
6
+
7
+ Handlebars.registerHelper( 'neq', function( a, b, options ) {
8
+ return a !== b ? options.fn( this ) : options.inverse( this );
9
+ } );
10
+
11
+ export default Handlebars;
@@ -3203,9 +3203,37 @@ export async function checklistTaskSubmissionDetails( req, res ) {
3203
3203
  }
3204
3204
  let details = [];
3205
3205
  if ( req.body.type == 'checklist' ) {
3206
- details = await processedchecklist.find( { sourceCheckList_id: req.body.checklistId, date_iso: new Date( dayjs( req.body.date ).format( 'YYYY-MM-DD' ) ) }, { submitTime: '$submitTime_string', status: '$checklistStatus', approvalStatus: '$approvalStatus', approvalTime: '$approvalTime_string', _id: 0 } );
3206
+ details = await processedchecklist.find( { sourceCheckList_id: req.body.checklistId, checklistStatus: 'submit', date_iso: new Date( dayjs( req.body.date ).format( 'YYYY-MM-DD' ) ) }, {
3207
+ date_string: 1,
3208
+ checkListName: 1,
3209
+ createdByName: 1,
3210
+ store_id: 1,
3211
+ storeName: 1,
3212
+ submmitedBy: '$userName',
3213
+ submmitedByEmail: '$userEmail',
3214
+ checklistStatus: 1,
3215
+ submitTime: 1,
3216
+ approvalTime: 1,
3217
+ approvalTime_string: 1,
3218
+ approvalByName: 1,
3219
+ approvalByEmail: 1,
3220
+ } );
3207
3221
  } else {
3208
- details = await processedTaskService.find( { sourceCheckList_id: req.body.checklistId, date_iso: new Date( dayjs( req.body.date ).format( 'YYYY-MM-DD' ) ) }, { submitTime: '$submitTime_string', status: '$checklistStatus', approvalStatus: '$approvalStatus', approvalTime: '$approvalTime_string', _id: 0 } );
3222
+ details = await processedTaskService.find( { sourceCheckList_id: req.body.checklistId, checklistStatus: 'submit', date_iso: new Date( dayjs( req.body.date ).format( 'YYYY-MM-DD' ) ) }, {
3223
+ date_string: 1,
3224
+ checkListName: 1,
3225
+ createdByName: 1,
3226
+ store_id: 1,
3227
+ storeName: 1,
3228
+ submmitedBy: '$userName',
3229
+ submmitedByEmail: '$userEmail',
3230
+ checklistStatus: 1,
3231
+ submitTime: 1,
3232
+ approvalTime: 1,
3233
+ approvalTime_string: 1,
3234
+ approvalByName: 1,
3235
+ approvalByEmail: 1,
3236
+ } );
3209
3237
  }
3210
3238
  return res.sendSuccess( details );
3211
3239
  } catch ( e ) {
@@ -21,12 +21,19 @@ import * as clientService from '../services/clients.services.js';
21
21
  import { create } from '../services/authentication.service.js';
22
22
  import { readFileSync } from 'fs';
23
23
  import { join } from 'path';
24
- import handlebars from 'handlebars';
24
+ // import handlebars from 'handlebars';
25
25
  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
29
  dayjs.extend( isSameOrBefore );
30
+ import * as pdf from 'html-pdf';
31
+ import handlebars from './handlebar-helper.js';
32
+ import fs from 'fs';
33
+ import { fileURLToPath } from 'url';
34
+ import path from 'path';
35
+ const __filename = fileURLToPath( import.meta.url );
36
+ const __dirname = path.dirname( __filename );
30
37
 
31
38
  export async function storeList( req, res ) {
32
39
  try {
@@ -1082,7 +1089,7 @@ export async function sopMobilechecklistMultiSectionFormatterv1( req, res, next
1082
1089
 
1083
1090
  if ( requestData.submittype == 'submit' ) {
1084
1091
  reqAnswers.forEach( ( reqA ) => {
1085
- if ( ![ 'multiplechoicemultiple', 'multipleImage' ].includes( reqA?.answerType ) ) {
1092
+ if ( ![ 'multiplechoicemultiple', 'multipleImage' ].includes( reqA?.answerType ) && ( reqA.answerType == 'dropDown' && !reqA.allowMultiple ) ) {
1086
1093
  if ( ( !reqA.linkType && ( reqA.answer == null || reqA.answer == '' ) ) || ( reqA.linkType && reqA.linkquestionenabled && ( reqA.answer == null || reqA.answer == '' ) ) ) {
1087
1094
  return res.sendError( 'Please Fill All Fields', 400 );
1088
1095
  }
@@ -1220,7 +1227,7 @@ export async function sopMobilechecklistMultiSectionFormatterv1( req, res, next
1220
1227
  structure.redoComment = qaAnswers[j]?.redoComment;
1221
1228
  };
1222
1229
  newArray.push( structure );
1223
- } else if ( qaAnswers[j].answerType == 'multiplechoicesingle' ) {
1230
+ } else if ( qaAnswers[j].answerType == 'multiplechoicesingle' || ( qaAnswers[j].answerType == 'dropdown' && !qaAnswers[j].allowMultiple ) ) {
1224
1231
  let qaans = qaAnswers[j].answers;
1225
1232
  let ms = [];
1226
1233
  for ( let k = 0; k < qaans.length; k++ ) {
@@ -1276,7 +1283,7 @@ export async function sopMobilechecklistMultiSectionFormatterv1( req, res, next
1276
1283
  structure.redoComment = qaAnswers[j]?.redoComment;
1277
1284
  };
1278
1285
  newArray.push( structure );
1279
- } else if ( qaAnswers[j].answerType == 'multiplechoicemultiple' ) {
1286
+ } else if ( qaAnswers[j].answerType == 'multiplechoicemultiple' || ( qaAnswers[j].answerType == 'dropdown' && qaAnswers[j].allowMultiple ) ) {
1280
1287
  let qaans = qaAnswers[j].answers;
1281
1288
  let mcmo = [];
1282
1289
  for ( let k = 0; k < qaans.length; k++ ) {
@@ -3230,6 +3237,7 @@ export async function questionList( req, res ) {
3230
3237
  startTime: { $ifNull: [ '$startTime', '' ] },
3231
3238
  submitTime: { $ifNull: [ '$submitTime', '' ] },
3232
3239
  allowedOverTime: { $ifNull: [ '$allowedOverTime', '' ] },
3240
+ sourceCheckList_id: 1,
3233
3241
  // allowedStoreLocation: { $ifNull: [ '$allowedStoreLocation', '' ] },
3234
3242
  allowedStoreLocation: {
3235
3243
  $cond: {
@@ -3285,7 +3293,7 @@ export async function questionList( req, res ) {
3285
3293
  }
3286
3294
 
3287
3295
  for ( let [ ansIndex, answer ] of question.answers.entries() ) {
3288
- if ( question.answerType == 'multiplechoicemultiple' ) {
3296
+ if ( question.answerType == 'multiplechoicemultiple' || ( question.answerType == 'dropdown' && question.allowMultiple ) ) {
3289
3297
  let checkvalidation = null;
3290
3298
  if ( answer.validationAnswer && answer.validationAnswer !='' ) {
3291
3299
  if ( answer.validationType != 'Descriptive Answer' ) {
@@ -3339,7 +3347,7 @@ export async function questionList( req, res ) {
3339
3347
  getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].multiReferenceImage = userAns.multiReferenceImage;
3340
3348
  }
3341
3349
 
3342
- if ( question.answerType == 'multiplechoicemultiple' ) {
3350
+ if ( question.answerType == 'multiplechoicemultiple' || ( question.answerType == 'dropdown' && question.allowMultiple ) ) {
3343
3351
  let ansIndex = Multianswer.findIndex( ( item ) => item.answer == userAns.answer );
3344
3352
  if ( ansIndex ) {
3345
3353
  Multianswer[ansIndex].validationAnswer = userAns.validationAnswer;
@@ -3356,7 +3364,7 @@ export async function questionList( req, res ) {
3356
3364
  }
3357
3365
  }
3358
3366
  }
3359
- if ( question.answerType == 'multiplechoicemultiple' ) {
3367
+ if ( question.answerType == 'multiplechoicemultiple' || ( question.answerType == 'dropdown' && question.allowMultiple ) ) {
3360
3368
  Multianswer.forEach( ( item ) => {
3361
3369
  if ( item.validationAnswer == null ) {
3362
3370
  item.answer = null;
@@ -3417,6 +3425,11 @@ export async function questionList( req, res ) {
3417
3425
  }
3418
3426
  }
3419
3427
 
3428
+ let checklisDetails = await checklistService.findOne( { _id: getchecklist?.[0]?.sourceCheckList_id }, { export: 1 } );
3429
+ if ( checklisDetails ) {
3430
+ getchecklist[0]['export'] = checklisDetails.export;
3431
+ }
3432
+
3420
3433
  return res.sendSuccess( getchecklist );
3421
3434
  }
3422
3435
  } catch ( e ) {
@@ -4238,6 +4251,7 @@ export async function questionListV1( req, res ) {
4238
4251
  startTime: { $ifNull: [ '$startTime', '' ] },
4239
4252
  submitTime: { $ifNull: [ '$submitTime', '' ] },
4240
4253
  allowedOverTime: { $ifNull: [ '$allowedOverTime', '' ] },
4254
+ sourceCheckList_id: { $ifNull: [ '$sourceCheckList_id', '' ] },
4241
4255
  // allowedStoreLocation: { $ifNull: [ '$allowedStoreLocation', '' ] },
4242
4256
  allowedStoreLocation: {
4243
4257
  $cond: {
@@ -4293,7 +4307,7 @@ export async function questionListV1( req, res ) {
4293
4307
  }
4294
4308
 
4295
4309
  for ( let [ ansIndex, answer ] of question.answers.entries() ) {
4296
- if ( question.answerType == 'multiplechoicemultiple' ) {
4310
+ if ( question.answerType == 'multiplechoicemultiple' || ( question.answerType == 'dropdown' && question.allowMultiple ) ) {
4297
4311
  let checkvalidation = null;
4298
4312
  if ( answer.validationAnswer && answer.validationAnswer !='' ) {
4299
4313
  if ( answer.validationType != 'Descriptive Answer' ) {
@@ -4345,7 +4359,7 @@ export async function questionListV1( req, res ) {
4345
4359
 
4346
4360
  getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].multiReferenceImage = userAns.multiReferenceImage;
4347
4361
  }
4348
- if ( question.answerType == 'multiplechoicemultiple' ) {
4362
+ if ( question.answerType == 'multiplechoicemultiple' || ( question.answerType == 'dropdown' && question.allowMultiple ) ) {
4349
4363
  let ansIndex = Multianswer.findIndex( ( item ) => item.answer == userAns.answer );
4350
4364
  if ( ansIndex ) {
4351
4365
  Multianswer[ansIndex].validationAnswer = userAns.validationAnswer;
@@ -4361,7 +4375,7 @@ export async function questionListV1( req, res ) {
4361
4375
  }
4362
4376
  }
4363
4377
  }
4364
- if ( question.answerType == 'multiplechoicemultiple' ) {
4378
+ if ( question.answerType == 'multiplechoicemultiple' || ( question.answerType == 'dropdown' && question.allowMultiple ) ) {
4365
4379
  Multianswer.forEach( ( item ) => {
4366
4380
  if ( item.validationAnswer == null ) {
4367
4381
  item.answer = null;
@@ -4422,6 +4436,11 @@ export async function questionListV1( req, res ) {
4422
4436
  }
4423
4437
  }
4424
4438
 
4439
+ let checklisDetails = await checklistService.findOne( { _id: getchecklist?.[0]?.sourceCheckList_id }, { export: 1 } );
4440
+ if ( checklisDetails ) {
4441
+ getchecklist[0]['export'] = checklisDetails.export;
4442
+ }
4443
+
4425
4444
  return res.sendSuccess( getchecklist );
4426
4445
  }
4427
4446
  } catch ( e ) {
@@ -4484,3 +4503,135 @@ export async function chunkUpload( req, res ) {
4484
4503
  return res.sendError( e, 500 );
4485
4504
  }
4486
4505
  }
4506
+
4507
+ export async function downloadChecklist( req, res ) {
4508
+ try {
4509
+ let requestData = req.body;
4510
+
4511
+ if ( !requestData.checklistId ) {
4512
+ res.sendBadRequest( 'checklistId is Required' );
4513
+ }
4514
+
4515
+ let checklistDetails;
4516
+
4517
+ if ( requestData.type == 'checklist' ) {
4518
+ checklistDetails = await processedchecklist.findOne( { _id: requestData.checklistId, checklistStatus: 'submit' } );
4519
+ } else {
4520
+ checklistDetails = await processedTask.findOne( { _id: requestData.checklistId, checklistStatus: 'submit' } );
4521
+ }
4522
+
4523
+ if ( !checklistDetails ) {
4524
+ return res.sendError( 'No data found', 204 );
4525
+ }
4526
+
4527
+ let storeDetails = await storeService.findOne( { storeId: checklistDetails.store_id }, { storeProfile: 1 } );
4528
+ if ( !storeDetails ) {
4529
+ return res.sendError( 'No data found', 204 );
4530
+ }
4531
+
4532
+ let clientDetails = await clientService.findOne( { clientId: checklistDetails.client_id } );
4533
+
4534
+ if ( !clientDetails ) {
4535
+ return res.sendError( 'No client found', 204 );
4536
+ }
4537
+
4538
+ checklistDetails = { ...checklistDetails.toObject(), ...storeDetails?.toObject()?.storeProfile };
4539
+
4540
+
4541
+ let scheduleDateTime = dayjs( checklistDetails.submitTime );
4542
+ checklistDetails.submitDate = scheduleDateTime.format( 'DD MMM, YYYY' );
4543
+ checklistDetails.submitTime = scheduleDateTime.format( 'hh:mm A' );
4544
+ if ( clientDetails?.profileDetails?.logo ) {
4545
+ let bucketpath = checklistDetails.client_id + '/logo';
4546
+
4547
+ let params = {
4548
+ Bucket: JSON.parse( process.env.BUCKET )?.assets,
4549
+ file_path: `${bucketpath}/${clientDetails?.profileDetails?.logo}`,
4550
+ };
4551
+ let url = await signedUrl( params );
4552
+ let brandImage = await convertUrltoBase64( url );
4553
+ if ( brandImage ) {
4554
+ checklistDetails['brandLogo'] = brandImage;
4555
+ }
4556
+ }
4557
+ checklistDetails['brandName'] = clientDetails?.clientName;
4558
+ for ( let section of checklistDetails.questionAnswers ) {
4559
+ for ( let question of section.questions ) {
4560
+ question.remarks = question.remarks == null || question.remarks == 'null' ? '' : question.remarks;
4561
+ for ( let answer of question.userAnswer ) {
4562
+ if ( answer?.referenceImage?.trim() ) {
4563
+ let inputData = {
4564
+ Bucket: JSON.parse( process.env.BUCKET )?.sop,
4565
+ file_path: answer.referenceImage,
4566
+ };
4567
+ let url = await signedUrl( inputData );
4568
+ const base64Image = await convertUrltoBase64( url );
4569
+ if ( base64Image ) {
4570
+ answer.referenceImage = base64Image;
4571
+ }
4572
+ }
4573
+ if ( answer.validationType == 'Capture Image' && answer?.validationAnswer?.trim() ) {
4574
+ let inputData = {
4575
+ Bucket: JSON.parse( process.env.BUCKET )?.sop,
4576
+ file_path: answer.validationAnswer,
4577
+ };
4578
+ let url = await signedUrl( inputData );
4579
+ const base64Image = await convertUrltoBase64( url );
4580
+ if ( base64Image ) {
4581
+ answer.validationAnswer = base64Image;
4582
+ }
4583
+ }
4584
+ if ( answer?.answer?.trim() && [ 'image', 'descriptiveImage', 'multipleImage', 'image/video' ].includes( question.answerType ) ) {
4585
+ let inputData = {
4586
+ Bucket: JSON.parse( process.env.BUCKET )?.sop,
4587
+ file_path: answer.answer,
4588
+ };
4589
+ let url = await signedUrl( inputData );
4590
+ const base64Image = await convertUrltoBase64( url );
4591
+ if ( base64Image ) {
4592
+ answer.answer = base64Image;
4593
+ }
4594
+ }
4595
+ }
4596
+ }
4597
+ }
4598
+ const targetFolder = path.join( __dirname, '..', '/hbs/template.hbs' );
4599
+ const templateHtml = fs.readFileSync( targetFolder, 'utf8' );
4600
+ const template = handlebars.compile( templateHtml );
4601
+ const html = template( { data: checklistDetails } );
4602
+ pdf.create( html ).toBuffer( ( err, buffer ) => {
4603
+ if ( err ) {
4604
+ res.status( 500 ).send( 'Error Generating PDF' );
4605
+ } else {
4606
+ res.setHeader( 'Content-Disposition', 'attachment; filename=checkListDetails.pdf' );
4607
+ res.contentType( 'application/pdf' );
4608
+ res.send( buffer );
4609
+ }
4610
+ } );
4611
+ } catch ( e ) {
4612
+ console.log( 'getChecklistQuestionAnswers =>', e );
4613
+ return false;
4614
+ }
4615
+ }
4616
+
4617
+ async function convertUrltoBase64( url ) {
4618
+ try {
4619
+ const response = await fetch( url );
4620
+
4621
+ if ( !response.ok ) {
4622
+ throw new Error( 'Failed to fetch image' );
4623
+ }
4624
+
4625
+ const contentType = response.headers.get( 'content-type' );
4626
+ const arrayBuffer = await response.arrayBuffer();
4627
+
4628
+ const base64Image =
4629
+ `data:${contentType};base64,` +
4630
+ Buffer.from( arrayBuffer ).toString( 'base64' );
4631
+
4632
+ return base64Image;
4633
+ } catch ( error ) {
4634
+ // console.error( 'Error fetching image:', error.message );
4635
+ return false;
4636
+ }
4637
+ }
@@ -4093,7 +4093,7 @@ async function updateOpenSearch( user, data ) {
4093
4093
  export const aiChecklist = async ( req, res ) => {
4094
4094
  try {
4095
4095
  let storeDetails = await storeService.count( { clientId: req.query.clientId, status: 'active' } );
4096
- 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' ];
4096
+ 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' ];
4097
4097
  let checklistDetails = [];
4098
4098
  let publishList = [];
4099
4099
  let unpublishList = [];
@@ -4106,7 +4106,7 @@ export const aiChecklist = async ( req, res ) => {
4106
4106
  checklistDetails = [ ...publishList, ...unpublishList ];
4107
4107
 
4108
4108
  checklistDetails.forEach( ( item ) => {
4109
- if ( ![ 'mobileusagedetection', 'storeopenandclose', 'cleaning', 'scrum', 'uniformdetection', 'staffleftinthemiddle', 'customerunattended', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering','queuealert' ].includes( item.checkListType ) ) {
4109
+ if ( ![ 'mobileusagedetection', 'storeopenandclose', 'cleaning', 'scrum', 'uniformdetection', 'staffleftinthemiddle', 'customerunattended', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert' ].includes( item.checkListType ) ) {
4110
4110
  item.storeCount = storeDetails;
4111
4111
  }
4112
4112
  } );