tango-app-api-trax 3.9.31 → 3.9.32
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/index.js +2 -1
- package/package.json +1 -1
- package/src/controllers/internalTrax.controller.js +112 -73
- package/src/controllers/mobileTrax.controller.js +69 -29
- package/src/controllers/trax.controller.js +2 -1
- package/src/controllers/traxDashboard.controllers.js +63 -54
- package/src/hbs/flag.hbs +1 -1
- package/src/hbs/login-otp.hbs +943 -943
- package/src/hbs/template.hbs +7 -0
- package/src/hbs/visit-checklist.hbs +51 -1
- package/src/logging/activityLogFlusher.js +59 -0
- package/src/logging/activityLogMiddleware.js +45 -0
- package/src/logging/activityLogStore.js +91 -0
- package/src/logging/compressBatches.js +83 -0
- package/src/logging/config.js +24 -0
- package/src/logging/createLoggableService.js +46 -0
- package/src/logging/logExternalCall.js +37 -0
- package/src/services/app.service.js +20 -14
- package/src/services/approver.service.js +28 -20
- package/src/services/authentication.service.js +12 -6
- package/src/services/camera.service.js +24 -18
- package/src/services/checklist.service.js +36 -31
- package/src/services/checklistAssign.service.js +44 -39
- package/src/services/checklistQuestion.service.js +40 -35
- package/src/services/checklistlog.service.js +40 -35
- package/src/services/clientRequest.service.js +12 -5
- package/src/services/clients.services.js +23 -18
- package/src/services/cluster.service.js +36 -28
- package/src/services/domain.service.js +33 -28
- package/src/services/download.services.js +48 -38
- package/src/services/group.service.js +28 -22
- package/src/services/lenskartEmployeeMapping.service.js +20 -15
- package/src/services/locus.service.js +41 -34
- package/src/services/notification.service.js +40 -31
- package/src/services/otp.service.js +24 -17
- package/src/services/planogram.service.js +12 -5
- package/src/services/processedTaskConfig.service.js +40 -32
- package/src/services/processedTaskList.service.js +36 -30
- package/src/services/processedchecklist.services.js +56 -48
- package/src/services/processedchecklistconfig.services.js +40 -35
- package/src/services/recurringFlagTracker.service.js +40 -33
- package/src/services/runAIFeatures.services.js +36 -31
- package/src/services/runAIRequest.services.js +44 -39
- package/src/services/store.service.js +36 -31
- package/src/services/tagging.service.js +12 -5
- package/src/services/taskConfig.service.js +40 -32
- package/src/services/teams.service.js +41 -30
- package/src/services/ticket.service.js +20 -15
- package/src/services/user.service.js +32 -25
- package/src/services/userAssignedstores.service.js +17 -10
- package/src/utils/visitChecklistPdf.utils.js +114 -11
package/index.js
CHANGED
|
@@ -9,5 +9,6 @@ import { mobileRouter } from './src/routes/mobileTrax.routes.js';
|
|
|
9
9
|
import { internalTraxRouter } from './src/routes/internalTraxApi.router.js';
|
|
10
10
|
import { locusOrderRouter } from './src/routes/locus.router.js';
|
|
11
11
|
import { traxActivityLogRouter } from './src/routes/activityLog.router.js';
|
|
12
|
+
import traxActivityLogMiddleware from './src/logging/activityLogMiddleware.js';
|
|
12
13
|
|
|
13
|
-
export { traxDashboardRouter, traxFlagRouter, traxRouter, galleryRouter, downloadRouter, mobileRouter, internalTraxRouter, locusOrderRouter, traxActivityLogRouter };
|
|
14
|
+
export { traxDashboardRouter, traxFlagRouter, traxRouter, galleryRouter, downloadRouter, mobileRouter, internalTraxRouter, locusOrderRouter, traxActivityLogRouter, traxActivityLogMiddleware };
|
package/package.json
CHANGED
|
@@ -624,6 +624,7 @@ export async function PCLconfigCreation( req, res ) {
|
|
|
624
624
|
element4.rawImageUpload = getCLconfig?.rawImageUpload || false;
|
|
625
625
|
element4.rawVideoUpload = getCLconfig?.rawVideoUpload || false;
|
|
626
626
|
element4.videoUploadTimeLimit = getCLconfig?.videoUploadTimeLimit || 0;
|
|
627
|
+
element4.userVerification = getCLconfig?.userVerification;
|
|
627
628
|
}
|
|
628
629
|
if ( userIdList.length ) {
|
|
629
630
|
allQuestion = allQuestion.filter( ( item ) => typeof item._id == 'undefined' );
|
|
@@ -1383,40 +1384,40 @@ export async function insertTimeDelayFlags( req, res ) {
|
|
|
1383
1384
|
let updatedDetails = await processedchecklist.updateMany( { _id: { $in: checklistId } }, { timeFlag: 1 } );
|
|
1384
1385
|
|
|
1385
1386
|
|
|
1386
|
-
let notifyStores = await processedchecklist.find( { _id: { $in: checklistId }, notify: { $exists: false } } );
|
|
1387
|
-
|
|
1388
|
-
if ( notifyStores.length ) {
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
}
|
|
1387
|
+
// let notifyStores = await processedchecklist.find( { _id: { $in: checklistId }, notify: { $exists: false } } );
|
|
1388
|
+
|
|
1389
|
+
// if ( notifyStores.length ) {
|
|
1390
|
+
// Promise.all( notifyStores.map( async ( store ) => {
|
|
1391
|
+
// let checklistDetails = await CLconfig.findOne( { _id: store.sourceCheckList_id }, { notifyFlags: 1, approver: 1 } );
|
|
1392
|
+
// if ( checklistDetails?.notifyFlags?.notifyType?.length ) {
|
|
1393
|
+
// let emailList = checklistDetails?.notifyFlags?.notifyType.includes( 'approver' ) ? checklistDetails.approver.map( ( ele ) => ele?.value ): [];
|
|
1394
|
+
// emailList = [ ...emailList, ...checklistDetails?.notifyFlags?.users?.map( ( ele ) => ele?.value ) ];
|
|
1395
|
+
// let data = {
|
|
1396
|
+
// storeName: store.storeName,
|
|
1397
|
+
// flagCount: 1,
|
|
1398
|
+
// checklistName: store.checkListName?.trim(),
|
|
1399
|
+
// submittedBy: '--',
|
|
1400
|
+
// time: '--',
|
|
1401
|
+
// domain: `${JSON.parse( process.env.URL ).domain}/manage/trax/flags?date=${dayjs().format( 'YYYY-MM-DD' )}`,
|
|
1402
|
+
// type: 'delay',
|
|
1403
|
+
// };
|
|
1404
|
+
// const fileContent = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/flag.hbs', 'utf8' );
|
|
1405
|
+
// const htmlContent = handlebars.compile( fileContent );
|
|
1406
|
+
// const html = htmlContent( { data: data } );
|
|
1407
|
+
// emailList.forEach( ( email ) => {
|
|
1408
|
+
// let params = {
|
|
1409
|
+
// toEmail: email,
|
|
1410
|
+
// mailSubject: 'TangoEye | Checklist Flag',
|
|
1411
|
+
// htmlBody: html,
|
|
1412
|
+
// attachment: '',
|
|
1413
|
+
// sourceEmail: JSON.parse( process.env.SES ).adminEmail,
|
|
1414
|
+
// };
|
|
1415
|
+
// sendEmailWithSES( params.toEmail, params.mailSubject, params.htmlBody, params.attachment, params.sourceEmail );
|
|
1416
|
+
// } );
|
|
1417
|
+
// }
|
|
1418
|
+
// await processedchecklist.updateOne( { _id: store._id }, { notify: true } );
|
|
1419
|
+
// } ) );
|
|
1420
|
+
// }
|
|
1420
1421
|
|
|
1421
1422
|
if ( updatedDetails ) {
|
|
1422
1423
|
return res.sendSuccess( { message: 'Time Delay Updated Successfully' } );
|
|
@@ -2700,10 +2701,57 @@ export async function countUpdateRunAI( req, res ) {
|
|
|
2700
2701
|
runAIFlag: req.body.runAICount,
|
|
2701
2702
|
};
|
|
2702
2703
|
|
|
2704
|
+
// complianceCount is already populated for the other answer types; add the image/video scores on top.
|
|
2705
|
+
let complianceCount = getDetails.userComplianceCount || 0;
|
|
2706
|
+
|
|
2707
|
+
// Pull every "Matched/Not Matched" verdict out of a runAIData array, tolerating both shapes we store:
|
|
2708
|
+
// 1) [ { answerImage, results: [ { featureName, value } ] } ] (verdict nested under results)
|
|
2709
|
+
// 2) [ { featureName, value } ] (flat verdict)
|
|
2710
|
+
const extractMatchValues = ( runAIData ) => {
|
|
2711
|
+
if ( !Array.isArray( runAIData ) ) return [];
|
|
2712
|
+
const values = [];
|
|
2713
|
+
runAIData.forEach( ( entry ) => {
|
|
2714
|
+
const results = Array.isArray( entry?.results ) ? entry.results : [ entry ];
|
|
2715
|
+
results.forEach( ( r ) => {
|
|
2716
|
+
if ( r?.featureName === 'Matched/Not Matched' ) values.push( r?.value );
|
|
2717
|
+
} );
|
|
2718
|
+
} );
|
|
2719
|
+
return values;
|
|
2720
|
+
};
|
|
2721
|
+
|
|
2722
|
+
getDetails.questionAnswers.forEach( ( section ) => {
|
|
2723
|
+
section.questions.forEach( ( question ) => {
|
|
2724
|
+
if ( question.compliance && [ 'image', 'image/video' ].includes( question.answerType ) ) {
|
|
2725
|
+
// For 'image/video' each userAnswer carries its own answerType and runAIData only lives on
|
|
2726
|
+
// the image entries; a pure 'image' question keeps runAIData directly on every userAnswer.
|
|
2727
|
+
const aiAnswers = question.answerType === 'image/video' ?
|
|
2728
|
+
( question.userAnswer || [] ).filter( ( ua ) => ua?.answerType === 'image' ) :
|
|
2729
|
+
( question.userAnswer || [] );
|
|
2730
|
+
|
|
2731
|
+
// Compliance comes from the first configured answer: every "Matched/Not Matched" verdict
|
|
2732
|
+
// across the image answers must be True to count as matched, otherwise it's not matched.
|
|
2733
|
+
const matchValues = aiAnswers.flatMap( ( ua ) => extractMatchValues( ua?.runAIData ) );
|
|
2734
|
+
const allMatched = matchValues.length > 0 && matchValues.every( ( v ) => v === 'True' || v === true );
|
|
2735
|
+
const score = allMatched ?
|
|
2736
|
+
( question.answers?.[0]?.matchedCount ?? 0 ) :
|
|
2737
|
+
( question.answers?.[0]?.notMatchedCount ?? 0 );
|
|
2738
|
+
|
|
2739
|
+
// Persist the derived score back onto each userAnswer so PDF/dashboard reads stay consistent.
|
|
2740
|
+
( question.userAnswer || [] ).forEach( ( ua ) => {
|
|
2741
|
+
ua.complianceScore = score;
|
|
2742
|
+
} );
|
|
2743
|
+
|
|
2744
|
+
complianceCount += score;
|
|
2745
|
+
}
|
|
2746
|
+
} );
|
|
2747
|
+
} );
|
|
2748
|
+
|
|
2749
|
+
updateData.complianceCount = complianceCount;
|
|
2750
|
+
|
|
2703
2751
|
await processedchecklist.updateOne( { _id: req.body.id }, updateData );
|
|
2704
2752
|
return res.sendSuccess( 'RunAI Count updated successfully' );
|
|
2705
2753
|
} catch ( e ) {
|
|
2706
|
-
logger.error( { functionName: '
|
|
2754
|
+
logger.error( { functionName: 'countUpdateRunAI', error: e } );
|
|
2707
2755
|
return res.sendError( e, 500 );
|
|
2708
2756
|
}
|
|
2709
2757
|
}
|
|
@@ -3540,47 +3588,38 @@ export async function runAIFlag( req, res ) {
|
|
|
3540
3588
|
],
|
|
3541
3589
|
},
|
|
3542
3590
|
}, { _id: 1, notifyFlags: 1, approver: 1 } );
|
|
3543
|
-
let date = dayjs().
|
|
3591
|
+
let date = dayjs().format( 'YYYY-MM-DD' );
|
|
3544
3592
|
if ( checklistDetails.length ) {
|
|
3545
3593
|
await Promise.all( checklistDetails.map( async ( ele ) => {
|
|
3546
|
-
let submitDetails = await processedchecklist.find( { sourceCheckList_id: ele._id,
|
|
3594
|
+
let submitDetails = await processedchecklist.find( { sourceCheckList_id: ele._id, date_string: date, $or: [ { timeFlag: { $gt: 0 } }, { questionFlag: { $gt: 0 } }, { runAIFlag: { $gt: 0 } } ] }, { storeName: 1, checkListName: 1, userName: 1, submitTime_string: 1, runAIFlag: 1, questionFlag: 1, checklistStatus: 1 } );
|
|
3595
|
+
let emailList = ele?.notifyFlags?.notifyType.includes( 'approver' ) ? ele.approver.map( ( approver ) => approver?.value ): [];
|
|
3596
|
+
emailList = [ ...emailList, ...ele?.notifyFlags?.users?.map( ( user ) => user?.value ) ];
|
|
3547
3597
|
await Promise.all( submitDetails.map( ( store ) => {
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
store.
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
} )
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
let params = {
|
|
3574
|
-
toEmail: email,
|
|
3575
|
-
mailSubject: 'TangoEye | Checklist Flag',
|
|
3576
|
-
htmlBody: html,
|
|
3577
|
-
attachment: '',
|
|
3578
|
-
sourceEmail: JSON.parse( process.env.SES ).adminEmail,
|
|
3579
|
-
};
|
|
3580
|
-
sendEmailWithSES( params.toEmail, params.mailSubject, params.htmlBody, params.attachment, params.sourceEmail );
|
|
3581
|
-
} );
|
|
3582
|
-
}
|
|
3583
|
-
}
|
|
3598
|
+
let data = {
|
|
3599
|
+
storeName: store.storeName,
|
|
3600
|
+
flagCount: store.timeFlag ? 1 : store?.runAIFlag + store?.questionFlag,
|
|
3601
|
+
runAIFlag: store?.runAIFlag,
|
|
3602
|
+
questionFlag: store?.questionFlag,
|
|
3603
|
+
checklistName: store.checkListName?.trim(),
|
|
3604
|
+
submittedBy: store?.userName,
|
|
3605
|
+
time: store?.submitTime_string ?? '--',
|
|
3606
|
+
domain: `${JSON.parse( process.env.URL ).domain}/manage/trax/flags?date=${dayjs().format( 'YYYY-MM-DD' )}`,
|
|
3607
|
+
status: store.checklistStatus,
|
|
3608
|
+
};
|
|
3609
|
+
const fileContent = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/flag.hbs', 'utf8' );
|
|
3610
|
+
const htmlContent = handlebars.compile( fileContent );
|
|
3611
|
+
const html = htmlContent( { data: data } );
|
|
3612
|
+
emailList.forEach( ( email ) => {
|
|
3613
|
+
console.log( email );
|
|
3614
|
+
let params = {
|
|
3615
|
+
toEmail: email,
|
|
3616
|
+
mailSubject: 'TangoEye | Checklist Flag',
|
|
3617
|
+
htmlBody: html,
|
|
3618
|
+
attachment: '',
|
|
3619
|
+
sourceEmail: JSON.parse( process.env.SES ).adminEmail,
|
|
3620
|
+
};
|
|
3621
|
+
sendEmailWithSES( params.toEmail, params.mailSubject, params.htmlBody, params.attachment, params.sourceEmail );
|
|
3622
|
+
} );
|
|
3584
3623
|
} ) );
|
|
3585
3624
|
} ) );
|
|
3586
3625
|
}
|
|
@@ -1765,6 +1765,7 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
1765
1765
|
} else {
|
|
1766
1766
|
if ( qaans[k].validationType == 'Capture Multiple Image with description' ) {
|
|
1767
1767
|
qaans[k]['validationImage']=[];
|
|
1768
|
+
qaans[k]['validationVideo']=[];
|
|
1768
1769
|
if ( requestSection[i].validationImage.length ) {
|
|
1769
1770
|
for ( let image of requestSection[i].validationImage ) {
|
|
1770
1771
|
let validationAnswer = decodeURIComponent( image.split( '?' )[0] );
|
|
@@ -1777,6 +1778,18 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
1777
1778
|
};
|
|
1778
1779
|
}
|
|
1779
1780
|
}
|
|
1781
|
+
if ( requestSection[i]?.validationVideo?.length ) {
|
|
1782
|
+
for ( let video of requestSection[i].validationVideo ) {
|
|
1783
|
+
let validationAnswer = decodeURIComponent( video.split( '?' )[0] );
|
|
1784
|
+
if ( validationAnswer.length ) {
|
|
1785
|
+
let splitImgUrl = validationAnswer.split( '/' );
|
|
1786
|
+
if ( splitImgUrl.length > 1 ) {
|
|
1787
|
+
splitImgUrl.splice( 0, 3 );
|
|
1788
|
+
qaans[k].validationVideo.push( splitImgUrl.join( '/' ) || '' );
|
|
1789
|
+
}
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1780
1793
|
}
|
|
1781
1794
|
// qaans[k].descriptivetype = qaAnswers[j].descriptivetype || '';
|
|
1782
1795
|
qaans[k].validationAnswer = requestSection[i].validationAnswer || '';
|
|
@@ -2127,12 +2140,18 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
2127
2140
|
logger.error( { message: requestData.questionAnswers, error: 'QuestionanswersPayload' } );
|
|
2128
2141
|
|
|
2129
2142
|
if ( requestData.submittype == 'submit' ) {
|
|
2143
|
+
requestData.userComplianceCount = 0;
|
|
2130
2144
|
for ( let section of sectionFormat ) {
|
|
2131
2145
|
for ( let question of section.questions ) {
|
|
2132
2146
|
let mustValidate = !question.linkType || ( question.linkType && question.linkquestionenabled );
|
|
2133
2147
|
if ( mustValidate && ( !question.userAnswer || !question.userAnswer.length ) ) {
|
|
2134
2148
|
return res.sendError( 'Please Fill All Fields', 400 );
|
|
2135
2149
|
}
|
|
2150
|
+
if ( question.compliance ) {
|
|
2151
|
+
const scores = ( question.userAnswer || [] ).map( ( ua ) => ua?.complianceScore ?? 0 );
|
|
2152
|
+
let score = scores.length ? Math.max( ...scores ) : 0;
|
|
2153
|
+
requestData.userComplianceCount += score;
|
|
2154
|
+
}
|
|
2136
2155
|
}
|
|
2137
2156
|
}
|
|
2138
2157
|
}
|
|
@@ -2776,6 +2795,15 @@ export async function submitChecklist( req, res ) {
|
|
|
2776
2795
|
updateData.checklistStatus = 'submit';
|
|
2777
2796
|
updateData.updatedAt = dayjs.utc( currentDateTime.format( 'hh:mm:ss A, DD MMM YYYY' ), 'hh:mm:ss A, DD MMM YYYY' ).format();
|
|
2778
2797
|
updateData.submitMobileTime = requestData?.currentTime;
|
|
2798
|
+
updateData.userComplianceCount = requestData?.userComplianceCount;
|
|
2799
|
+
updateData.userSignature = requestData?.userSignature;
|
|
2800
|
+
if ( requestData?.userImage ) {
|
|
2801
|
+
let splitImgUrl = requestData?.userImage.split( '/' );
|
|
2802
|
+
if ( splitImgUrl.length > 1 ) {
|
|
2803
|
+
splitImgUrl.splice( 0, 3 );
|
|
2804
|
+
updateData.userImage = splitImgUrl.join( '/' ) || '';
|
|
2805
|
+
}
|
|
2806
|
+
}
|
|
2779
2807
|
}
|
|
2780
2808
|
// updateData.questionAnswers.forEach( ( section ) => {
|
|
2781
2809
|
// section.questions.forEach( ( question ) => {
|
|
@@ -2876,34 +2904,34 @@ export async function submitChecklist( req, res ) {
|
|
|
2876
2904
|
userType: req.user.userType,
|
|
2877
2905
|
};
|
|
2878
2906
|
insertOpenSearchData( openSearch.traxActivityLog, inserttraxlogs );
|
|
2879
|
-
if ( updateData.questionFlag ) {
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
}
|
|
2907
|
+
// if ( updateData.questionFlag ) {
|
|
2908
|
+
// let checklistDetails = await checklistService.findOne( { _id: getchecklist[0].sourceCheckList_id }, { notifyFlags: 1, approver: 1 } );
|
|
2909
|
+
// if ( checklistDetails?.notifyFlags?.notifyType?.length ) {
|
|
2910
|
+
// let emailList = checklistDetails?.notifyFlags?.notifyType.includes( 'approver' ) ? checklistDetails.approver.map( ( ele ) => ele?.value ): [];
|
|
2911
|
+
// emailList = [ ...emailList, ...checklistDetails?.notifyFlags?.users?.map( ( ele ) => ele?.value ) ];
|
|
2912
|
+
// let data = {
|
|
2913
|
+
// storeName: getchecklist[0].storeName,
|
|
2914
|
+
// flagCount: updateData.questionFlag,
|
|
2915
|
+
// checklistName: getchecklist[0].checkListName,
|
|
2916
|
+
// submittedBy: getchecklist[0].userName,
|
|
2917
|
+
// time: updateData.submitTime_string,
|
|
2918
|
+
// domain: `${JSON.parse( process.env.URL ).domain}/manage/trax/flags?date=${dayjs().format( 'YYYY-MM-DD' )}`,
|
|
2919
|
+
// };
|
|
2920
|
+
// const fileContent = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/flag.hbs', 'utf8' );
|
|
2921
|
+
// const htmlContent = handlebars.compile( fileContent );
|
|
2922
|
+
// const html = htmlContent( { data: data } );
|
|
2923
|
+
// emailList.forEach( ( email ) => {
|
|
2924
|
+
// let params = {
|
|
2925
|
+
// toEmail: email,
|
|
2926
|
+
// mailSubject: 'TangoEye | Checklist Flag',
|
|
2927
|
+
// htmlBody: html,
|
|
2928
|
+
// attachment: '',
|
|
2929
|
+
// sourceEmail: JSON.parse( process.env.SES ).adminEmail,
|
|
2930
|
+
// };
|
|
2931
|
+
// sendEmailWithSES( params.toEmail, params.mailSubject, params.htmlBody, params.attachment, params.sourceEmail );
|
|
2932
|
+
// } );
|
|
2933
|
+
// }
|
|
2934
|
+
// }
|
|
2907
2935
|
}
|
|
2908
2936
|
if ( getchecklist?.[0]?.redoEdit?.toString() != requestData?.redoEdit ) {
|
|
2909
2937
|
return res.sendSuccess( 'New Questions Added So,Checklist moved back to In Progress. Please complete the updated checklist.' );
|
|
@@ -4177,6 +4205,9 @@ export async function questionList( req, res ) {
|
|
|
4177
4205
|
streamId: { $ifNull: [ '$streamId', '' ] },
|
|
4178
4206
|
export: { $ifNull: [ '$export', false ] },
|
|
4179
4207
|
redoEdit: 1,
|
|
4208
|
+
userVerification: 1,
|
|
4209
|
+
userSignature: 1,
|
|
4210
|
+
userImage: 1,
|
|
4180
4211
|
},
|
|
4181
4212
|
} );
|
|
4182
4213
|
|
|
@@ -4187,6 +4218,7 @@ export async function questionList( req, res ) {
|
|
|
4187
4218
|
logger.info( `v5 => Checklist Continue => store Name: ${getchecklist[0].storeName}, User Email: ${getchecklist[0].userEmail}, Checklist Name: ${getchecklist[0].checkListName}` );
|
|
4188
4219
|
// let bucket = JSON.parse( process.env.BUCKET );
|
|
4189
4220
|
let cdnurl = JSON.parse( process.env.CDNURL );
|
|
4221
|
+
getchecklist[0].userImage = `${cdnurl}/${getchecklist[0].userImage}`;
|
|
4190
4222
|
for ( let [ secIndex, section ] of getchecklist[0].questionAnswers.entries() ) {
|
|
4191
4223
|
for ( let [ questionIndex, question ] of section.questions.entries() ) {
|
|
4192
4224
|
let Multianswer = [];
|
|
@@ -4242,10 +4274,15 @@ export async function questionList( req, res ) {
|
|
|
4242
4274
|
}
|
|
4243
4275
|
if ( userAns.validationType == 'Capture Multiple Image with description' ) {
|
|
4244
4276
|
let imageAnswers = userAns.validationImage;
|
|
4245
|
-
|
|
4277
|
+
getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].validationImage = [];
|
|
4246
4278
|
for ( let image of imageAnswers ) {
|
|
4247
4279
|
getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].validationImage.push( `${cdnurl.TraxAnswerCDN}${image}` );
|
|
4248
4280
|
}
|
|
4281
|
+
let videoAnswer = userAns.validationVideo;
|
|
4282
|
+
getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].validationVideo = [];
|
|
4283
|
+
for ( let image of videoAnswer ) {
|
|
4284
|
+
getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].validationVideo.push( `${cdnurl.TraxAnswerCDN}${image}` );
|
|
4285
|
+
}
|
|
4249
4286
|
}
|
|
4250
4287
|
if ( [ 'image', 'descriptiveImage', 'video' ].includes( question.answerType ) && userAns.answer != '' ) {
|
|
4251
4288
|
getchecklist[0].questionAnswers[secIndex].questions[questionIndex].userAnswer[userAnsIndex].answer =`${cdnurl.TraxAnswerCDN}${userAns.answer}`;
|
|
@@ -5490,6 +5527,9 @@ export async function downloadChecklist( req, res ) {
|
|
|
5490
5527
|
if ( [ 'Capture Multiple Image with description' ].includes( answer.validationType ) && answer?.validationImage?.length ) {
|
|
5491
5528
|
answer.validationImage = answer?.validationImage?.map( ( ele ) => JSON.parse( process.env.CDNURL )?.TraxAnswerCDN+ele );
|
|
5492
5529
|
}
|
|
5530
|
+
if ( [ 'Capture Multiple Image with description' ].includes( answer.validationType ) && answer?.validationVideo?.length ) {
|
|
5531
|
+
answer.validationVideo = answer?.validationVideo?.map( ( ele ) => JSON.parse( process.env.CDNURL )?.TraxAnswerCDN+ele );
|
|
5532
|
+
}
|
|
5493
5533
|
if ( answer?.answer?.trim() && [ 'image', 'descriptiveImage', 'multipleImage', 'image/video', 'video' ].includes( question.answerType ) ) {
|
|
5494
5534
|
answer.answer = JSON.parse( process.env.CDNURL )?.TraxAnswerCDN+answer.answer;
|
|
5495
5535
|
}
|
|
@@ -620,6 +620,7 @@ export const zoneList = async ( req, res ) => {
|
|
|
620
620
|
const allowedChecklistsStreams = [
|
|
621
621
|
'Camera Angle Change Compliance',
|
|
622
622
|
];
|
|
623
|
+
console.log( allowedChecklists.includes( inputBody.checkListName ) );
|
|
623
624
|
|
|
624
625
|
if ( inputBody.checkListName && allowedChecklists.includes( inputBody.checkListName ) ) {
|
|
625
626
|
console.log( '==================' );
|
|
@@ -1914,7 +1915,6 @@ export const updateConfigure = async ( req, res ) => {
|
|
|
1914
1915
|
|
|
1915
1916
|
export const updateConfigurev1 = async ( req, res ) => {
|
|
1916
1917
|
try {
|
|
1917
|
-
console.log( '123' );
|
|
1918
1918
|
let inputBody = req.body;
|
|
1919
1919
|
let id;
|
|
1920
1920
|
let checklistDetails;
|
|
@@ -3972,6 +3972,7 @@ async function insertPCBulkV4( getCLconfig, checklistId, currentdate, updatedche
|
|
|
3972
3972
|
element4.rawVideoUpload = getCLconfig?.rawVideoUpload || false;
|
|
3973
3973
|
element4.videoUploadTimeLimit = getCLconfig?.videoUploadTimeLimit || 0;
|
|
3974
3974
|
element4.complianceCount = getCLconfig?.complianceCount || 0;
|
|
3975
|
+
element4.userVerification = getCLconfig?.userVerification;
|
|
3975
3976
|
assignUserList.push( { ...element4 } );
|
|
3976
3977
|
}
|
|
3977
3978
|
} ) );
|
|
@@ -276,29 +276,10 @@ export const checklistPerformance = async ( req, res ) => {
|
|
|
276
276
|
toDate = new Date( toDate.getTime() - userTimezoneOffset );
|
|
277
277
|
toDate.setUTCHours( 23, 59, 59, 59 );
|
|
278
278
|
let result = {};
|
|
279
|
-
let checklistIdList = [];
|
|
280
279
|
|
|
281
280
|
let limit = parseInt( requestData?.limit ) || 10;
|
|
282
281
|
let skip = limit * ( requestData?.offset ) || 0;
|
|
283
282
|
|
|
284
|
-
const detectionPayload = {
|
|
285
|
-
'fromDate': requestData.fromDate,
|
|
286
|
-
'toDate': requestData.toDate,
|
|
287
|
-
'clientId': requestData.clientId,
|
|
288
|
-
'sortColumnName': requestData.sortColumnName,
|
|
289
|
-
'sortBy': requestData.sortBy,
|
|
290
|
-
'storeId': requestData.storeId,
|
|
291
|
-
};
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
let complianceURL = JSON.parse( process.env.LAMBDAURL ).complianceURL;
|
|
295
|
-
const complianceData = await LamdaServiceCall( complianceURL, detectionPayload );
|
|
296
|
-
if ( complianceData?.data?.length && requestData?.sortColumnName == 'questionCompliance' ) {
|
|
297
|
-
const end = skip + requestData?.limit;
|
|
298
|
-
checklistIdList = complianceData.data.slice( skip, end )?.map( ( ele ) => ele?.sourceCheckList_id );
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
|
|
302
283
|
// Get User Based Checklist //
|
|
303
284
|
// let loginUser = { clientId: requestData.clientId, role: req.user.role, userType: req.user.userType, userEmail: req.user.email };
|
|
304
285
|
// let getUserEmails = await getChecklistUsers( loginUser );
|
|
@@ -314,10 +295,6 @@ export const checklistPerformance = async ( req, res ) => {
|
|
|
314
295
|
{ $or: [ { store_id: { $in: requestData.storeId } }, { store_id: { $eq: '' }, userEmail: { $in: requestData.userEmailes } } ] },
|
|
315
296
|
);
|
|
316
297
|
|
|
317
|
-
if ( requestData?.sortColumnName == 'questionCompliance' ) {
|
|
318
|
-
findAndQuery.push( { sourceCheckList_id: { $in: checklistIdList } } );
|
|
319
|
-
}
|
|
320
|
-
|
|
321
298
|
findQuery.push( { $match: { $and: findAndQuery } } );
|
|
322
299
|
|
|
323
300
|
if ( requestData.searchValue && requestData.searchValue != '' ) {
|
|
@@ -367,6 +344,16 @@ export const checklistPerformance = async ( req, res ) => {
|
|
|
367
344
|
timeFlag: { $sum: '$timeFlag' },
|
|
368
345
|
questionFlagCount: { $sum: '$questionFlag' },
|
|
369
346
|
runAIFlagCount: { $sum: '$runAIFlag' },
|
|
347
|
+
userComplianceCountTotal: {
|
|
348
|
+
$sum: {
|
|
349
|
+
$cond: [
|
|
350
|
+
{ $eq: [ '$checklistStatus', 'submit' ] },
|
|
351
|
+
{ $ifNull: [ '$userComplianceCount', 0 ] },
|
|
352
|
+
0,
|
|
353
|
+
],
|
|
354
|
+
},
|
|
355
|
+
},
|
|
356
|
+
complianceCount: { $first: '$complianceCount' },
|
|
370
357
|
checkListType: { $last: '$checkListType' },
|
|
371
358
|
redo: { $sum: { $cond: [ { $eq: [ '$redoStatus', true ] }, 1, 0 ] } },
|
|
372
359
|
task: {
|
|
@@ -426,6 +413,36 @@ export const checklistPerformance = async ( req, res ) => {
|
|
|
426
413
|
checkListType: 1,
|
|
427
414
|
redo: 1,
|
|
428
415
|
task: 1,
|
|
416
|
+
questionCompliance: {
|
|
417
|
+
$let: {
|
|
418
|
+
vars: {
|
|
419
|
+
divisor: {
|
|
420
|
+
$cond: [
|
|
421
|
+
{ $gt: [ '$submittedChecklist', 1 ] },
|
|
422
|
+
{ $multiply: [ { $ifNull: [ '$complianceCount', 0 ] }, '$submittedChecklist' ] },
|
|
423
|
+
{ $ifNull: [ '$complianceCount', 0 ] },
|
|
424
|
+
],
|
|
425
|
+
},
|
|
426
|
+
},
|
|
427
|
+
in: {
|
|
428
|
+
$cond: [
|
|
429
|
+
{ $gt: [ '$$divisor', 0 ] },
|
|
430
|
+
{
|
|
431
|
+
$round: [
|
|
432
|
+
{
|
|
433
|
+
$multiply: [
|
|
434
|
+
{ $divide: [ '$userComplianceCountTotal', '$$divisor' ] },
|
|
435
|
+
100,
|
|
436
|
+
],
|
|
437
|
+
},
|
|
438
|
+
0,
|
|
439
|
+
],
|
|
440
|
+
},
|
|
441
|
+
0,
|
|
442
|
+
],
|
|
443
|
+
},
|
|
444
|
+
},
|
|
445
|
+
},
|
|
429
446
|
},
|
|
430
447
|
} );
|
|
431
448
|
|
|
@@ -450,14 +467,6 @@ export const checklistPerformance = async ( req, res ) => {
|
|
|
450
467
|
return res.sendError( 'no data found', 204 );
|
|
451
468
|
}
|
|
452
469
|
|
|
453
|
-
getChecklistPerformanceData?.[0]?.data.forEach( ( ele ) => {
|
|
454
|
-
let findCompliance;
|
|
455
|
-
if ( complianceData?.data?.length ) {
|
|
456
|
-
findCompliance = complianceData?.data?.find( ( data ) => data.sourceCheckList_id == ele?.sourceCheckList_id );
|
|
457
|
-
}
|
|
458
|
-
ele['questionComplianceRate'] = findCompliance?.compliancePercentage ?? 0;
|
|
459
|
-
} );
|
|
460
|
-
|
|
461
470
|
if ( requestData.export ) {
|
|
462
471
|
const exportdata = [];
|
|
463
472
|
getChecklistPerformanceData[0].data.forEach( ( element ) => {
|
|
@@ -4335,26 +4344,26 @@ function escapeRegex( text ) {
|
|
|
4335
4344
|
// }
|
|
4336
4345
|
// }
|
|
4337
4346
|
|
|
4338
|
-
async function LamdaServiceCall( url, data ) {
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
}
|
|
4347
|
+
// async function LamdaServiceCall( url, data ) {
|
|
4348
|
+
// try {
|
|
4349
|
+
// const requestOptions = {
|
|
4350
|
+
// method: 'POST',
|
|
4351
|
+
// headers: {
|
|
4352
|
+
// 'Content-Type': 'application/json',
|
|
4353
|
+
// },
|
|
4354
|
+
// body: JSON.stringify( data ),
|
|
4355
|
+
// };
|
|
4356
|
+
// console.log( data );
|
|
4357
|
+
// const response = await fetch( url, requestOptions );
|
|
4358
|
+
// if ( !response.ok ) {
|
|
4359
|
+
// throw new Error( `Response status: ${response.status}` );
|
|
4360
|
+
// return false;
|
|
4361
|
+
// }
|
|
4362
|
+
// const json = await response.json();
|
|
4363
|
+
// return json;
|
|
4364
|
+
// } catch ( error ) {
|
|
4365
|
+
// console.log( error );
|
|
4366
|
+
// logger.error( { error: error, message: data, function: 'LamdaServiceCall' } );
|
|
4367
|
+
// return false;
|
|
4368
|
+
// }
|
|
4369
|
+
// }
|
package/src/hbs/flag.hbs
CHANGED
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
<td class="flagText" style="padding-left:30px; line-height: 24px;">No of Flags :</td>
|
|
177
177
|
<td></td>
|
|
178
178
|
<td></td>
|
|
179
|
-
<td class="flagText">{{data.flagCount}}</td>
|
|
179
|
+
<td class="flagText">{{data.flagCount}}{{#eq data.status 'submit'}}(RunAIFlag:{{data.runAIFlag}},QuestionFlag:{{data.questionFlag}}){{/eq}}</td>
|
|
180
180
|
</tr>
|
|
181
181
|
<tr bgcolor="#ffffff" style="border:none;margin-top:3px;">
|
|
182
182
|
<td class="flagText" style="padding-left:30px; line-height: 24px;">Submitted By :</td>
|