tango-app-api-trax 3.9.22 → 3.9.24
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 +2 -2
- package/src/controllers/internalTrax.controller.js +84 -44
- package/src/controllers/mobileTrax.controller.js +43 -2
- package/src/controllers/teaxFlag.controller.js +4 -3
- package/src/controllers/trax.controller.js +5 -2
- package/src/controllers/traxDashboard.controllers.js +63 -54
- package/src/hbs/login-otp.hbs +943 -943
- 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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tango-app-api-trax",
|
|
3
|
-
"version": "3.9.
|
|
3
|
+
"version": "3.9.24",
|
|
4
4
|
"description": "Trax",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"path": "^0.12.7",
|
|
31
31
|
"puppeteer": "^24.39.1",
|
|
32
32
|
"swagger-ui-express": "^5.0.1",
|
|
33
|
-
"tango-api-schema": "^2.6.
|
|
33
|
+
"tango-api-schema": "^2.6.12",
|
|
34
34
|
"tango-app-api-middleware": "^3.5.2",
|
|
35
35
|
"url": "^0.11.4",
|
|
36
36
|
"winston": "^3.13.1",
|
|
@@ -325,7 +325,7 @@ export async function PCLconfigCreation( req, res ) {
|
|
|
325
325
|
},
|
|
326
326
|
} );
|
|
327
327
|
let getSections = await CLquestions.aggregate( sectionQuery );
|
|
328
|
-
if ( getSections.length ||
|
|
328
|
+
if ( getSections.length || getCLconfig.checkListType != 'custom' ) {
|
|
329
329
|
if ( getSections.length ) {
|
|
330
330
|
for ( let element3 of getSections ) {
|
|
331
331
|
let collectQuestions = {};
|
|
@@ -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' );
|
|
@@ -651,11 +652,11 @@ export async function PCLconfigCreation( req, res ) {
|
|
|
651
652
|
// }
|
|
652
653
|
}
|
|
653
654
|
} else {
|
|
654
|
-
if (
|
|
655
|
+
if ( getCLconfig.checkListType != 'custom' ) {
|
|
655
656
|
let storeNameList = allQuestion.map( ( item ) => item.store_id );
|
|
656
|
-
let storeDetails = await storeService.find( { clientId: getCLconfig.client_id, status: 'active', ...(
|
|
657
|
+
let storeDetails = await storeService.find( { clientId: getCLconfig.client_id, status: 'active', ...( getCLconfig.checkListType != 'custom' ) ? { storeId: { $in: storeNameList } } : {} }, { storeId: 1 } );
|
|
657
658
|
let storeList = storeDetails.map( ( store ) => store.storeId );
|
|
658
|
-
if (
|
|
659
|
+
if ( getCLconfig.checkListType != 'custom' ) {
|
|
659
660
|
allQuestion = allQuestion.filter( ( ele ) => storeList.includes( ele?.store_id ) );
|
|
660
661
|
} else {
|
|
661
662
|
allQuestion = storeDetails.map( ( item ) => {
|
|
@@ -689,7 +690,7 @@ export async function PCLconfigCreation( req, res ) {
|
|
|
689
690
|
client_id: getCLconfig.client_id,
|
|
690
691
|
aiStoreList: allQuestion.length ? allQuestion.map( ( store ) => store.store_id ) : [],
|
|
691
692
|
};
|
|
692
|
-
if (
|
|
693
|
+
if ( getCLconfig.checkListType != 'custom' ) {
|
|
693
694
|
let processData = {
|
|
694
695
|
aiStoreList: allQuestion.length ? allQuestion.map( ( store ) => {
|
|
695
696
|
return { storeName: store.storeName, storeId: store.store_id, events: store.events };
|
|
@@ -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
|
}
|
|
@@ -3532,6 +3580,7 @@ export async function runAIFlag( req, res ) {
|
|
|
3532
3580
|
try {
|
|
3533
3581
|
let checklistDetails = await CLconfig.find( {
|
|
3534
3582
|
publish: true,
|
|
3583
|
+
client_id: '467',
|
|
3535
3584
|
runAIQuestionCount: { $ne: 0 },
|
|
3536
3585
|
$expr: {
|
|
3537
3586
|
$gt: [
|
|
@@ -3540,47 +3589,38 @@ export async function runAIFlag( req, res ) {
|
|
|
3540
3589
|
],
|
|
3541
3590
|
},
|
|
3542
3591
|
}, { _id: 1, notifyFlags: 1, approver: 1 } );
|
|
3543
|
-
let date = dayjs().
|
|
3592
|
+
let date = dayjs().format( 'YYYY-MM-DD' );
|
|
3544
3593
|
if ( checklistDetails.length ) {
|
|
3545
3594
|
await Promise.all( checklistDetails.map( async ( ele ) => {
|
|
3546
|
-
let submitDetails = await processedchecklist.find( { sourceCheckList_id: ele._id,
|
|
3595
|
+
let submitDetails = await processedchecklist.find( { sourceCheckList_id: ele._id, date_string: date }, { storeName: 1, checkListName: 1, userName: 1, submitTime_string: 1, runAIFlag: 1, questionFlag: 1, checklistStatus: 1 } );
|
|
3596
|
+
let emailList = ele?.notifyFlags?.notifyType.includes( 'approver' ) ? ele.approver.map( ( approver ) => approver?.value ): [];
|
|
3597
|
+
emailList = [ ...emailList, ...ele?.notifyFlags?.users?.map( ( user ) => user?.value ) ];
|
|
3547
3598
|
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
|
-
}
|
|
3599
|
+
let data = {
|
|
3600
|
+
storeName: store.storeName,
|
|
3601
|
+
flagCount: store?.runAIFlag + store?.questionFlag,
|
|
3602
|
+
runAIFlag: store?.runAIFlag,
|
|
3603
|
+
questionFlag: store?.questionFlag,
|
|
3604
|
+
checklistName: store.checkListName?.trim(),
|
|
3605
|
+
submittedBy: store?.userName,
|
|
3606
|
+
time: store?.submitTime_string,
|
|
3607
|
+
domain: `${JSON.parse( process.env.URL ).domain}/manage/trax/flags?date=${dayjs().format( 'YYYY-MM-DD' )}`,
|
|
3608
|
+
status: store.checklistStatus,
|
|
3609
|
+
};
|
|
3610
|
+
const fileContent = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/flag.hbs', 'utf8' );
|
|
3611
|
+
const htmlContent = handlebars.compile( fileContent );
|
|
3612
|
+
const html = htmlContent( { data: data } );
|
|
3613
|
+
emailList.forEach( ( email ) => {
|
|
3614
|
+
console.log( email );
|
|
3615
|
+
let params = {
|
|
3616
|
+
toEmail: email,
|
|
3617
|
+
mailSubject: 'TangoEye | Checklist Flag',
|
|
3618
|
+
htmlBody: html,
|
|
3619
|
+
attachment: '',
|
|
3620
|
+
sourceEmail: JSON.parse( process.env.SES ).adminEmail,
|
|
3621
|
+
};
|
|
3622
|
+
sendEmailWithSES( params.toEmail, params.mailSubject, params.htmlBody, params.attachment, params.sourceEmail );
|
|
3623
|
+
} );
|
|
3584
3624
|
} ) );
|
|
3585
3625
|
} ) );
|
|
3586
3626
|
}
|
|
@@ -1586,7 +1586,7 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
1586
1586
|
let CLQAnswers = getChecklistQA.questionAnswers;
|
|
1587
1587
|
|
|
1588
1588
|
if ( requestData.submittype == 'submit' ) {
|
|
1589
|
-
if ( getChecklistQA?.redoEdit ) {
|
|
1589
|
+
if ( getChecklistQA?.redoEdit?.toString() != requestData?.redoEdit ) {
|
|
1590
1590
|
requestData.submittype = 'draft';
|
|
1591
1591
|
}
|
|
1592
1592
|
reqAnswers.forEach( ( reqA ) => {
|
|
@@ -1677,6 +1677,7 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
1677
1677
|
let yn = [];
|
|
1678
1678
|
if ( ( getChecklistQA?.redoEdit && qaAnswers[j].redo == requestSection[i].redo ) || !getChecklistQA?.redoEdit ) {
|
|
1679
1679
|
for ( let k = 0; k < qaans.length; k++ ) {
|
|
1680
|
+
qaans[k].validationAnswer = '';
|
|
1680
1681
|
if ( requestSection[i].answer == qaans[k].answer ) {
|
|
1681
1682
|
if ( qaans[k].validationType == 'Capture Image' || qaans[k].validationType == 'Capture Video' ) {
|
|
1682
1683
|
if ( requestSection[i].validationAnswer ) {
|
|
@@ -1696,6 +1697,9 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
1696
1697
|
if ( requestSection[i]?.runAIData && requestSection[i]?.runAIData?.length ) {
|
|
1697
1698
|
qaans[k].runAIData = requestSection[i].runAIData;
|
|
1698
1699
|
}
|
|
1700
|
+
if ( requestSection[i]?.runAIAnswer ) {
|
|
1701
|
+
qaans[k].runAIAnswer = requestSection[i].runAIAnswer;
|
|
1702
|
+
}
|
|
1699
1703
|
yn.push( qaans[k] );
|
|
1700
1704
|
}
|
|
1701
1705
|
}
|
|
@@ -1737,6 +1741,7 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
1737
1741
|
};
|
|
1738
1742
|
structure.answers.forEach( ( ans ) => {
|
|
1739
1743
|
delete ans?.runAIData;
|
|
1744
|
+
delete ans?.runAIAnswer;
|
|
1740
1745
|
} );
|
|
1741
1746
|
newArray.push( structure );
|
|
1742
1747
|
} else if ( qaAnswers[j].answerType == 'multiplechoicesingle' || ( qaAnswers[j].answerType == 'dropdown' && !qaAnswers[j].allowMultiple ) ) {
|
|
@@ -1744,6 +1749,7 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
1744
1749
|
let ms = [];
|
|
1745
1750
|
if ( ( getChecklistQA?.redoEdit && qaAnswers[j].redo == requestSection[i].redo ) || !getChecklistQA?.redoEdit ) {
|
|
1746
1751
|
for ( let k = 0; k < qaans.length; k++ ) {
|
|
1752
|
+
qaans[k].validationAnswer = '';
|
|
1747
1753
|
if ( requestSection[i].answer == qaans[k].answer ) {
|
|
1748
1754
|
if ( qaans[k].validationType == 'Capture Image' || qaans[k].validationType == 'Capture Video' ) {
|
|
1749
1755
|
if ( requestSection[i].validationAnswer ) {
|
|
@@ -1771,6 +1777,18 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
1771
1777
|
};
|
|
1772
1778
|
}
|
|
1773
1779
|
}
|
|
1780
|
+
if ( requestSection[i]?.validationVideo?.length ) {
|
|
1781
|
+
for ( let video of requestSection[i].validationVideo ) {
|
|
1782
|
+
let validationAnswer = decodeURIComponent( video.split( '?' )[0] );
|
|
1783
|
+
if ( validationAnswer.length ) {
|
|
1784
|
+
let splitImgUrl = validationAnswer.split( '/' );
|
|
1785
|
+
if ( splitImgUrl.length > 1 ) {
|
|
1786
|
+
splitImgUrl.splice( 0, 3 );
|
|
1787
|
+
qaans[k].validationVideo.push( splitImgUrl.join( '/' ) || '' );
|
|
1788
|
+
}
|
|
1789
|
+
};
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1774
1792
|
}
|
|
1775
1793
|
// qaans[k].descriptivetype = qaAnswers[j].descriptivetype || '';
|
|
1776
1794
|
qaans[k].validationAnswer = requestSection[i].validationAnswer || '';
|
|
@@ -1778,6 +1796,9 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
1778
1796
|
if ( requestSection[i]?.runAIData && requestSection[i]?.runAIData?.length ) {
|
|
1779
1797
|
qaans[k].runAIData = requestSection[i].runAIData;
|
|
1780
1798
|
}
|
|
1799
|
+
if ( requestSection[i]?.runAIAnswer ) {
|
|
1800
|
+
qaans[k].runAIAnswer = requestSection[i].runAIAnswer;
|
|
1801
|
+
}
|
|
1781
1802
|
ms.push( qaans[k] );
|
|
1782
1803
|
}
|
|
1783
1804
|
}
|
|
@@ -1820,6 +1841,7 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
1820
1841
|
};
|
|
1821
1842
|
structure.answers.forEach( ( ans ) => {
|
|
1822
1843
|
delete ans?.runAIData;
|
|
1844
|
+
delete ans?.runAIAnswer;
|
|
1823
1845
|
} );
|
|
1824
1846
|
newArray.push( structure );
|
|
1825
1847
|
} else if ( qaAnswers[j].answerType == 'multiplechoicemultiple' || ( qaAnswers[j].answerType == 'dropdown' && qaAnswers[j].allowMultiple ) ) {
|
|
@@ -1827,6 +1849,7 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
1827
1849
|
let mcmo = [];
|
|
1828
1850
|
if ( ( getChecklistQA?.redoEdit && qaAnswers[j].redo == requestSection[i].redo ) || !getChecklistQA?.redoEdit || ( getChecklistQA?.redoEdit && qaAnswers[j].answers.some( ( ans ) => ans.redo ) ) ) {
|
|
1829
1851
|
for ( let k = 0; k < qaans.length; k++ ) {
|
|
1852
|
+
qaans[k].validationAnswer = '';
|
|
1830
1853
|
let separatedArray = typeof requestSection[i].Multianswer == 'string' ? JSON.parse( requestSection[i].Multianswer ) : requestSection[i].Multianswer;
|
|
1831
1854
|
for ( let s = 0; s < separatedArray.length; s++ ) {
|
|
1832
1855
|
if ( ( separatedArray[s].answer == qaans[k].answer ) ) {
|
|
@@ -1849,6 +1872,9 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
1849
1872
|
if ( separatedArray[s]?.runAIData && separatedArray[s]?.runAIData?.length ) {
|
|
1850
1873
|
qaans[k].runAIData = separatedArray[s].runAIData;
|
|
1851
1874
|
}
|
|
1875
|
+
if ( separatedArray[s]?.runAIAnswer ) {
|
|
1876
|
+
qaans[k].runAIAnswer = separatedArray[s].runAIAnswer;
|
|
1877
|
+
}
|
|
1852
1878
|
mcmo.push( qaans[k] );
|
|
1853
1879
|
}
|
|
1854
1880
|
}
|
|
@@ -1899,6 +1925,7 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
1899
1925
|
};
|
|
1900
1926
|
structure.answers.forEach( ( ans ) => {
|
|
1901
1927
|
delete ans?.runAIData;
|
|
1928
|
+
delete ans?.runAIAnswer;
|
|
1902
1929
|
} );
|
|
1903
1930
|
newArray.push( structure );
|
|
1904
1931
|
} else if ( [ 'image/video', 'multipleImage' ].includes( qaAnswers[j].answerType ) ) {
|
|
@@ -1938,6 +1965,9 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
1938
1965
|
if ( separatedArray[s]?.runAIData && separatedArray[s]?.runAIData?.length ) {
|
|
1939
1966
|
newAnswer.runAIData = separatedArray[s].runAIData;
|
|
1940
1967
|
}
|
|
1968
|
+
if ( separatedArray[s]?.runAIAnswer ) {
|
|
1969
|
+
newAnswer.runAIAnswer = separatedArray[s].runAIAnswer;
|
|
1970
|
+
}
|
|
1941
1971
|
mcmi.push( newAnswer );
|
|
1942
1972
|
}
|
|
1943
1973
|
}
|
|
@@ -2049,6 +2079,9 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
2049
2079
|
if ( requestSection[i]?.runAIData && requestSection[i]?.runAIData?.length ) {
|
|
2050
2080
|
ansstructure.runAIData = requestSection[i].runAIData;
|
|
2051
2081
|
}
|
|
2082
|
+
if ( requestSection[i]?.runAIAnswer ) {
|
|
2083
|
+
ansstructure.runAIAnswer = requestSection[i].runAIAnswer;
|
|
2084
|
+
}
|
|
2052
2085
|
des.push( ansstructure );
|
|
2053
2086
|
}
|
|
2054
2087
|
}
|
|
@@ -2106,12 +2139,18 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
2106
2139
|
logger.error( { message: requestData.questionAnswers, error: 'QuestionanswersPayload' } );
|
|
2107
2140
|
|
|
2108
2141
|
if ( requestData.submittype == 'submit' ) {
|
|
2142
|
+
requestData.userComplianceCount = 0;
|
|
2109
2143
|
for ( let section of sectionFormat ) {
|
|
2110
2144
|
for ( let question of section.questions ) {
|
|
2111
2145
|
let mustValidate = !question.linkType || ( question.linkType && question.linkquestionenabled );
|
|
2112
2146
|
if ( mustValidate && ( !question.userAnswer || !question.userAnswer.length ) ) {
|
|
2113
2147
|
return res.sendError( 'Please Fill All Fields', 400 );
|
|
2114
2148
|
}
|
|
2149
|
+
if ( question.compliance ) {
|
|
2150
|
+
const scores = ( question.userAnswer || [] ).map( ( ua ) => ua?.complianceScore ?? 0 );
|
|
2151
|
+
let score = scores.length ? Math.max( ...scores ) : 0;
|
|
2152
|
+
requestData.userComplianceCount += score;
|
|
2153
|
+
}
|
|
2115
2154
|
}
|
|
2116
2155
|
}
|
|
2117
2156
|
}
|
|
@@ -2755,6 +2794,7 @@ export async function submitChecklist( req, res ) {
|
|
|
2755
2794
|
updateData.checklistStatus = 'submit';
|
|
2756
2795
|
updateData.updatedAt = dayjs.utc( currentDateTime.format( 'hh:mm:ss A, DD MMM YYYY' ), 'hh:mm:ss A, DD MMM YYYY' ).format();
|
|
2757
2796
|
updateData.submitMobileTime = requestData?.currentTime;
|
|
2797
|
+
updateData.userComplianceCount = requestData?.userComplianceCount;
|
|
2758
2798
|
}
|
|
2759
2799
|
// updateData.questionAnswers.forEach( ( section ) => {
|
|
2760
2800
|
// section.questions.forEach( ( question ) => {
|
|
@@ -2884,7 +2924,7 @@ export async function submitChecklist( req, res ) {
|
|
|
2884
2924
|
}
|
|
2885
2925
|
}
|
|
2886
2926
|
}
|
|
2887
|
-
if ( getchecklist?.[0]?.redoEdit ) {
|
|
2927
|
+
if ( getchecklist?.[0]?.redoEdit?.toString() != requestData?.redoEdit ) {
|
|
2888
2928
|
return res.sendSuccess( 'New Questions Added So,Checklist moved back to In Progress. Please complete the updated checklist.' );
|
|
2889
2929
|
} else {
|
|
2890
2930
|
return res.sendSuccess( 'Checklist Updated Successfully' );
|
|
@@ -4155,6 +4195,7 @@ export async function questionList( req, res ) {
|
|
|
4155
4195
|
taskType: { $ifNull: [ '$planoType', '' ] },
|
|
4156
4196
|
streamId: { $ifNull: [ '$streamId', '' ] },
|
|
4157
4197
|
export: { $ifNull: [ '$export', false ] },
|
|
4198
|
+
redoEdit: 1,
|
|
4158
4199
|
},
|
|
4159
4200
|
} );
|
|
4160
4201
|
|
|
@@ -2747,7 +2747,7 @@ export const checklistDropdownV1 = async ( req, res ) => {
|
|
|
2747
2747
|
$or: [
|
|
2748
2748
|
{ questionFlag: { $gte: 1 } },
|
|
2749
2749
|
{ timeFlag: { $gte: 1 } },
|
|
2750
|
-
{ checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring', 'unattendeddetection' ] } },
|
|
2750
|
+
{ checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring', 'unattendeddetection', 'vehicle_check_in' ] } },
|
|
2751
2751
|
{
|
|
2752
2752
|
runAIQuestionCount: { $gte: 1 },
|
|
2753
2753
|
},
|
|
@@ -3051,7 +3051,7 @@ export const flagTablesV2 = async ( req, res ) => {
|
|
|
3051
3051
|
}
|
|
3052
3052
|
|
|
3053
3053
|
if ( requestData?.filter === 'all' ) {
|
|
3054
|
-
findAndQuery.push( { $or: [ { checkListType: { $in: [ 'custom', 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring', 'unattendeddetection' ] } } ] } );
|
|
3054
|
+
findAndQuery.push( { $or: [ { checkListType: { $in: [ 'custom', 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring', 'unattendeddetection', 'vehicle_check_in' ] } } ] } );
|
|
3055
3055
|
} else if ( requestData?.filter === 'question' ) {
|
|
3056
3056
|
findAndQuery.push( { checkListType: 'custom' } );
|
|
3057
3057
|
findAndQuery.push( { questionFlag: { $gte: 1 } } );
|
|
@@ -3059,7 +3059,7 @@ export const flagTablesV2 = async ( req, res ) => {
|
|
|
3059
3059
|
findAndQuery.push( { checkListType: 'custom' } );
|
|
3060
3060
|
findAndQuery.push( { timeFlag: { $gte: 1 } } );
|
|
3061
3061
|
} else if ( requestData?.filter === 'detection' ) {
|
|
3062
|
-
findAndQuery.push( { checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring', 'unattendeddetection' ] } } );
|
|
3062
|
+
findAndQuery.push( { checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection', 'cleaning', 'scrum', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'storehygienemonitoring', 'unattendeddetection', 'vehicle_check_in' ] } } );
|
|
3063
3063
|
} else if ( requestData?.filter === 'runAI' ) {
|
|
3064
3064
|
if ( req.body.runAIChecklistName ) {
|
|
3065
3065
|
findAndQuery.push( { checkListName: { $in: req.body.runAIChecklistName } } );
|
|
@@ -3200,6 +3200,7 @@ export const flagTablesV2 = async ( req, res ) => {
|
|
|
3200
3200
|
} );
|
|
3201
3201
|
|
|
3202
3202
|
let getTotalCount = await processedchecklistService.aggregate( findQuery );
|
|
3203
|
+
console.log( getTotalCount );
|
|
3203
3204
|
if ( !getTotalCount.length ) {
|
|
3204
3205
|
return res.sendError( { error: 'No Data Found' }, 204 );
|
|
3205
3206
|
}
|
|
@@ -614,10 +614,13 @@ export const zoneList = async ( req, res ) => {
|
|
|
614
614
|
'Employee Count Detection',
|
|
615
615
|
'Staff Grouping Compliance',
|
|
616
616
|
'Retail Shelf Monitoring',
|
|
617
|
+
'Store Mopping Compliance Checklist',
|
|
618
|
+
'Occupancy Detection',
|
|
617
619
|
];
|
|
618
620
|
const allowedChecklistsStreams = [
|
|
619
621
|
'Camera Angle Change Compliance',
|
|
620
622
|
];
|
|
623
|
+
console.log( allowedChecklists.includes( inputBody.checkListName ) );
|
|
621
624
|
|
|
622
625
|
if ( inputBody.checkListName && allowedChecklists.includes( inputBody.checkListName ) ) {
|
|
623
626
|
console.log( '==================' );
|
|
@@ -1912,7 +1915,6 @@ export const updateConfigure = async ( req, res ) => {
|
|
|
1912
1915
|
|
|
1913
1916
|
export const updateConfigurev1 = async ( req, res ) => {
|
|
1914
1917
|
try {
|
|
1915
|
-
console.log( '123' );
|
|
1916
1918
|
let inputBody = req.body;
|
|
1917
1919
|
let id;
|
|
1918
1920
|
let checklistDetails;
|
|
@@ -3970,6 +3972,7 @@ async function insertPCBulkV4( getCLconfig, checklistId, currentdate, updatedche
|
|
|
3970
3972
|
element4.rawVideoUpload = getCLconfig?.rawVideoUpload || false;
|
|
3971
3973
|
element4.videoUploadTimeLimit = getCLconfig?.videoUploadTimeLimit || 0;
|
|
3972
3974
|
element4.complianceCount = getCLconfig?.complianceCount || 0;
|
|
3975
|
+
element4.userVerification = getCLconfig?.userVerification;
|
|
3973
3976
|
assignUserList.push( { ...element4 } );
|
|
3974
3977
|
}
|
|
3975
3978
|
} ) );
|
|
@@ -4134,7 +4137,7 @@ async function updateOpenSearch( user, data ) {
|
|
|
4134
4137
|
export const aiChecklist = async ( req, res ) => {
|
|
4135
4138
|
try {
|
|
4136
4139
|
let storeDetails = await storeService.count( { clientId: req.query.clientId, status: 'active' } );
|
|
4137
|
-
let aiList = [ 'mobileusagedetection', 'storeopenandclose', 'uniformdetection', 'staffleftinthemiddle', 'customerunattended', 'eyetest', 'remoteoptometrist', 'storehygienemonitoring', 'cleaning', 'scrum', 'suspiciousactivity', 'suspiciousfootfall', 'drinking', 'bagdetection', 'inventorycount', 'carsattended', 'numberplateinfo', 'vehicle_check_in', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'unattendeddetection' ];
|
|
4140
|
+
let aiList = [ 'mobileusagedetection', 'storeopenandclose', 'uniformdetection', 'staffleftinthemiddle', 'customerunattended', 'eyetest', 'remoteoptometrist', 'storehygienemonitoring', 'cleaning', 'scrum', 'suspiciousactivity', 'suspiciousfootfall', 'drinking', 'bagdetection', 'inventorycount', 'carsattended', 'numberplateinfo', 'vehicle_check_in', 'outsidebusinesshoursqueuetracking', 'halfshutter', 'tvcompliance', 'cameratampering', 'queuealert', 'staffgrouping', 'boxalert', 'employeeCount', 'unattendeddetection', 'occupancydetection' ];
|
|
4138
4141
|
let checklistDetails = [];
|
|
4139
4142
|
let publishList = [];
|
|
4140
4143
|
let unpublishList = [];
|
|
@@ -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
|
+
// }
|