tango-app-api-trax 3.3.1-beta-3 → 3.3.1-beta-5

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.3.1-beta-3",
3
+ "version": "3.3.1-beta-5",
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.24",
29
+ "tango-api-schema": "^2.2.32",
30
30
  "tango-app-api-middleware": "^3.1.50",
31
31
  "url": "^0.11.4",
32
32
  "winston": "^3.13.1",
@@ -247,6 +247,10 @@ export async function startChecklist( req, res ) {
247
247
  questions.push( question );
248
248
  let linkedAnswer = new Set( question.answers.filter( ( ele ) => ele.showLinked ).flatMap( ( ele ) => ele.nestedQuestion ) );
249
249
  let linkedQuestion = section.questions.filter( ( qn ) => linkedAnswer.has( qn.qno ) );
250
+ linkedQuestion = JSON.parse( JSON.stringify( linkedQuestion ) );
251
+ linkedQuestion.forEach( ( linkQn ) => {
252
+ linkQn.parentQuestion = question.qno;
253
+ } );
250
254
  questions.push( ...linkedQuestion );
251
255
  }
252
256
  }
@@ -1079,6 +1083,7 @@ export async function sopMobilechecklistMultiSectionFormatterv1( req, res, next
1079
1083
  structure.parentanswer = requestSection[i].parentanswer;
1080
1084
  structure.questionReferenceImage = qaAnswers[j].questionReferenceImage;
1081
1085
  structure.descriptivetype = qaAnswers[j].descriptivetype;
1086
+ structure.parentQuestion = requestSection[i]?.parentQuestion || qaAnswers[j].qno;
1082
1087
  if ( qaAnswers[j]?.taskId ) {
1083
1088
  structure.taskId = qaAnswers[j]?.taskId;
1084
1089
  structure.task = true;
@@ -1130,6 +1135,7 @@ export async function sopMobilechecklistMultiSectionFormatterv1( req, res, next
1130
1135
  structure.parentanswer = requestSection[i].parentanswer;
1131
1136
  structure.questionReferenceImage = qaAnswers[j].questionReferenceImage;
1132
1137
  structure.descriptivetype = qaAnswers[j].descriptivetype;
1138
+ structure.parentQuestion = requestSection[i]?.parentQuestion || qaAnswers[j].qno;
1133
1139
  if ( qaAnswers[j]?.taskId ) {
1134
1140
  structure.taskId = qaAnswers[j]?.taskId;
1135
1141
  structure.task = true;
@@ -1185,6 +1191,7 @@ export async function sopMobilechecklistMultiSectionFormatterv1( req, res, next
1185
1191
  structure.parentanswer = requestSection[i].parentanswer;
1186
1192
  structure.questionReferenceImage = qaAnswers[j].questionReferenceImage;
1187
1193
  structure.descriptivetype = qaAnswers[j].descriptivetype;
1194
+ structure.parentQuestion = requestSection[i]?.parentQuestion || qaAnswers[j].qno;
1188
1195
  if ( qaAnswers[j]?.taskId ) {
1189
1196
  structure.taskId = qaAnswers[j]?.taskId;
1190
1197
  structure.task = true;
@@ -1245,6 +1252,7 @@ export async function sopMobilechecklistMultiSectionFormatterv1( req, res, next
1245
1252
  structure.parentanswer = requestSection[i].parentanswer;
1246
1253
  structure.questionReferenceImage = qaAnswers[j].questionReferenceImage;
1247
1254
  structure.descriptivetype = qaAnswers[j].descriptivetype;
1255
+ structure.parentQuestion = requestSection[i]?.parentQuestion || qaAnswers[j].qno;
1248
1256
  if ( qaAnswers[j]?.taskId ) {
1249
1257
  structure.taskId = qaAnswers[j]?.taskId;
1250
1258
  structure.task = true;
@@ -1303,6 +1311,7 @@ export async function sopMobilechecklistMultiSectionFormatterv1( req, res, next
1303
1311
  structure.parentanswer = requestSection[i].parentanswer;
1304
1312
  structure.questionReferenceImage = qaAnswers[j].questionReferenceImage;
1305
1313
  structure.descriptivetype = qaAnswers[j].descriptivetype;
1314
+ structure.parentQuestion = requestSection[i]?.parentQuestion || qaAnswers[j].qno;
1306
1315
  if ( qaAnswers[j]?.taskId ) {
1307
1316
  structure.taskId = qaAnswers[j]?.taskId;
1308
1317
  structure.task = true;
@@ -2586,7 +2595,11 @@ export async function questionList( req, res ) {
2586
2595
  if ( !question.linkType ) {
2587
2596
  questions.push( question );
2588
2597
  let linkedAnswer = new Set( question.answers.filter( ( ele ) => ele.showLinked ).flatMap( ( ele ) => ele.nestedQuestion ) );
2589
- let linkedQuestion = section.questions.filter( ( qn ) => linkedAnswer.has( qn.qno ) );
2598
+ let linkedQuestion = section.questions.filter( ( qn ) => qn?.parentQuestion ? qn?.parentQuestion == question.qno && linkedAnswer.has( qn.qno ) : linkedAnswer.has( qn.qno ) );
2599
+ linkedQuestion = JSON.parse( JSON.stringify( linkedQuestion ) );
2600
+ linkedQuestion.forEach( ( linkQn ) => {
2601
+ linkQn.parentQuestion = question.qno;
2602
+ } );
2590
2603
  questions.push( ...linkedQuestion );
2591
2604
  }
2592
2605
  }
@@ -2737,3 +2737,261 @@ export const checklistDropdownV1 = async ( req, res ) => {
2737
2737
  return res.sendError( { error: error }, 500 );
2738
2738
  }
2739
2739
  };
2740
+
2741
+ export const flagTablesV2 = async ( req, res ) => {
2742
+ try {
2743
+ let requestData = req.body;
2744
+ let fromDate = new Date( requestData.fromDate );
2745
+ let toDate = new Date( requestData.toDate );
2746
+ let userTimezoneOffset = toDate.getTimezoneOffset() * 60000;
2747
+ toDate = new Date( toDate.getTime() - userTimezoneOffset );
2748
+ toDate.setUTCHours( 23, 59, 59, 59 );
2749
+ let result = {};
2750
+
2751
+ let findQuery = [];
2752
+ let findAndQuery = [];
2753
+ findAndQuery.push(
2754
+ { client_id: requestData.clientId },
2755
+ { $or: [ { store_id: { $in: requestData.storeId } }, { aiStoreList: { $in: requestData.storeId } } ] },
2756
+ { date_iso: { $gte: fromDate } },
2757
+ { date_iso: { $lte: toDate } },
2758
+ );
2759
+
2760
+ if ( requestData?.filter === 'all' ) {
2761
+ findAndQuery.push( { $or: [ { questionFlag: { $gte: 1 } }, { timeFlag: { $gte: 1 } }, { checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection' ] } } ] } );
2762
+ } else if ( requestData?.filter === 'question' ) {
2763
+ findAndQuery.push( { checkListType: 'custom' } );
2764
+ findAndQuery.push( { questionFlag: { $gte: 1 } } );
2765
+ } else if ( requestData?.filter === 'time' ) {
2766
+ findAndQuery.push( { checkListType: 'custom' } );
2767
+ findAndQuery.push( { timeFlag: { $gte: 1 } } );
2768
+ } else if ( requestData?.filter === 'detection' ) {
2769
+ findAndQuery.push( { checkListType: { $in: [ 'customerunattended', 'mobileusagedetection', 'staffleftinthemiddle', 'storeopenandclose', 'uniformdetection' ] } } );
2770
+ }
2771
+
2772
+ findQuery.push( { $match: { $and: findAndQuery } } );
2773
+
2774
+ if ( requestData.searchValue && requestData.searchValue != '' ) {
2775
+ findQuery.push( { $match: { $or: [ { checkListName: { $regex: requestData.searchValue, $options: 'i' } } ] } } );
2776
+ }
2777
+
2778
+ findQuery.push( {
2779
+ $project: {
2780
+ sourceCheckList_id: 1,
2781
+ checkListId: 1,
2782
+ checkListName: 1,
2783
+ coverage: 1,
2784
+ storeCount: 1,
2785
+ createdBy: 1,
2786
+ createdByName: 1,
2787
+ checklistStatus: 1,
2788
+ timeFlag: 1,
2789
+ questionFlag: 1,
2790
+ questionCount: 1,
2791
+ mobileDetectionFlag: 1,
2792
+ storeOpenCloseFlag: 1,
2793
+ uniformDetectionFlag: 1,
2794
+ checkListType: 1,
2795
+ scheduleRepeatedType: 1,
2796
+ store_id: 1,
2797
+ aiStoreList: 1,
2798
+ },
2799
+ } );
2800
+
2801
+ findQuery.push( {
2802
+ $group: {
2803
+ _id: '$sourceCheckList_id',
2804
+ checkListName: { $last: '$checkListName' },
2805
+ coverage: { $last: '$coverage' },
2806
+ checkListChar: { $last: { $substr: [ '$checkListName', 0, 2 ] } },
2807
+ sourceCheckList_id: { $last: '$sourceCheckList_id' },
2808
+ checkListType: { $last: '$checkListType' },
2809
+ storeCount: { $sum: 1 },
2810
+ storeCountAi: { $max: '$storeCount' },
2811
+ flaggedStores: {
2812
+ $addToSet: {
2813
+ $cond: [
2814
+ {
2815
+ $or: [
2816
+ { $gt: [ '$timeFlag', 0 ] },
2817
+ { $gt: [ '$questionFlag', 0 ] },
2818
+ { $gt: [ '$mobileDetectionFlag', 0 ] },
2819
+ { $gt: [ '$storeOpenCloseFlag', 0 ] },
2820
+ { $gt: [ '$uniformDetectionFlag', 0 ] },
2821
+ { $gt: [ '$customerUnattended', 0 ] },
2822
+ { $gt: [ '$staffLeftInTheMiddle', 0 ] },
2823
+ ],
2824
+ },
2825
+ '$store_id',
2826
+ '$$REMOVE',
2827
+ ],
2828
+ },
2829
+ },
2830
+ flagCount: {
2831
+ $sum: {
2832
+ $add: [ '$questionFlag', '$timeFlag' ],
2833
+ },
2834
+ },
2835
+ submittedChecklist: {
2836
+ $sum: {
2837
+ $cond: [ { $eq: [ '$checklistStatus', 'submit' ] }, 1, 0 ],
2838
+ },
2839
+ },
2840
+ questionFlag: {
2841
+ $sum: '$questionFlag',
2842
+ },
2843
+ timeFlag: {
2844
+ $sum: '$timeFlag',
2845
+ },
2846
+ questionCount: {
2847
+ $sum: '$questionCount',
2848
+ },
2849
+ aiStoreList: { $max: '$aiStoreList' },
2850
+ submittedQuestionCount: {
2851
+ $sum: {
2852
+ $cond: [ { $eq: [ '$checklistStatus', 'submit' ] }, '$questionCount', 0 ],
2853
+ },
2854
+ },
2855
+ },
2856
+ } );
2857
+
2858
+ findQuery.push( {
2859
+ $project: {
2860
+ assignedStores: '$storeCount',
2861
+ assignedStoresAi: '$storeCountAi',
2862
+ checkListName: 1,
2863
+ coverage: 1,
2864
+ checkListChar: 1,
2865
+ sourceCheckList_id: 1,
2866
+ checkListType: 1,
2867
+ flagType: 1,
2868
+ uniqueFlaggedStores: 1,
2869
+ flaggedStores: { $size: '$flaggedStores' },
2870
+ flagCount: 1,
2871
+ questionCount: 1,
2872
+ correctAnswers: { $subtract: [ '$submittedQuestionCount', '$questionFlag' ] },
2873
+ customQuestionFlagCount: '$questionFlag',
2874
+ customTimeFlagCount: '$timeFlag',
2875
+ aiStoreList: 1,
2876
+ },
2877
+ } );
2878
+
2879
+ findQuery.push( {
2880
+ $project: {
2881
+ checkListName: 1,
2882
+ coverage: 1,
2883
+ checkListChar: 1,
2884
+ sourceCheckList_id: 1,
2885
+ checkListType: 1,
2886
+ flagType: 1,
2887
+ assignedStores: 1,
2888
+ assignedStoresAi: 1,
2889
+ flaggedStores: 1,
2890
+ flagCount: 1,
2891
+ uniqueFlaggedStores: 1,
2892
+ complianceRate: {
2893
+ $cond: {
2894
+ if: { $eq: [ '$questionCount', 0 ] },
2895
+ then: 0,
2896
+ else: {
2897
+ $round: [ { $multiply: [ { $divide: [ '$correctAnswers', '$questionCount' ] }, 100 ] }, 2 ],
2898
+ },
2899
+ },
2900
+ },
2901
+ customQuestionFlagCount: 1,
2902
+ customTimeFlagCount: 1,
2903
+ aiStoreList: 1,
2904
+
2905
+ },
2906
+ } );
2907
+
2908
+ let getTotalCount = await processedchecklistService.aggregate( findQuery );
2909
+ if ( !getTotalCount.length ) {
2910
+ return res.sendError( { error: 'No Data Found' }, 204 );
2911
+ }
2912
+
2913
+ if ( requestData.sortColumnName && requestData.sortColumnName != '' && requestData.sortBy && requestData.sortBy !='' ) {
2914
+ findQuery.push( { $sort: { [requestData.sortColumnName]: requestData.sortBy } } );
2915
+ } else {
2916
+ findQuery.push( { $sort: { ['submittedChecklist']: -1 } } );
2917
+ }
2918
+
2919
+ if ( !requestData.export ) {
2920
+ let limit = parseInt( requestData?.limit ) || 10;
2921
+ let skip = limit * ( requestData?.offset ) || 0;
2922
+ findQuery.push( { $skip: skip }, { $limit: limit } );
2923
+ }
2924
+
2925
+
2926
+ let getChecklistPerformanceData = await processedchecklistService.aggregate( findQuery );
2927
+
2928
+ if ( getChecklistPerformanceData.length ) {
2929
+ const detectionChecklists = getChecklistPerformanceData?.filter( ( val ) => val?.checkListType !== 'custom' );
2930
+
2931
+ if ( detectionChecklists?.length ) {
2932
+ const detectionPayload = {
2933
+ 'fromDate': requestData.fromDate,
2934
+ 'toDate': requestData.toDate,
2935
+ 'storeId': requestData.storeId,
2936
+ 'clientId': requestData.clientId,
2937
+ };
2938
+
2939
+ let LamdaURL = 'https://f65azvtljclaxp6l7rnx65cdmm0lcgvp.lambda-url.ap-south-1.on.aws/';
2940
+ let resultData = await LamdaServiceCall( LamdaURL, detectionPayload );
2941
+ if ( resultData ) {
2942
+ if ( resultData.status_code == '200' ) {
2943
+ for ( let index = 0; index < getChecklistPerformanceData.length; index++ ) {
2944
+ if ( getChecklistPerformanceData[index].checkListType !== 'custom' ) {
2945
+ getChecklistPerformanceData[index].coverage = 'Store';
2946
+ getChecklistPerformanceData[index].flagCount = resultData?.[getChecklistPerformanceData[index]?.checkListType] || 0;
2947
+ getChecklistPerformanceData[index].flaggedStores = resultData?.[`${getChecklistPerformanceData[index]?.checkListType}_flaggedstores`] || 0;
2948
+ getChecklistPerformanceData[index].assignedStores = getChecklistPerformanceData[index]?.aiStoreList?.filter( ( element ) => requestData.storeId.includes( element ) )?.length || 0;
2949
+ getChecklistPerformanceData[index].complianceRate = ( 100- ( getChecklistPerformanceData[index].flaggedStores / getChecklistPerformanceData[index].assignedStores ) * 100 );
2950
+ getChecklistPerformanceData[index].complianceRate = Math.min( 100, Math.max( 0, getChecklistPerformanceData[index].complianceRate ) );
2951
+ getChecklistPerformanceData[index].complianceRate = ( getChecklistPerformanceData[index].complianceRate % 1 === 0 ) ? getChecklistPerformanceData[index].complianceRate.toFixed( 0 ) : getChecklistPerformanceData[index].complianceRate.toFixed( 2 );
2952
+ }
2953
+ }
2954
+ }
2955
+ }
2956
+ }
2957
+ }
2958
+
2959
+ if ( requestData.export ) {
2960
+ const exportdata = [];
2961
+ getChecklistPerformanceData.forEach( ( element ) => {
2962
+ const data = {
2963
+ 'Checklist Name': element.checkListName,
2964
+ 'Coverage': element.coverage || 'Store',
2965
+ 'Flag Type': element?.checkListType === 'custom' ? 'Question' : 'Detection',
2966
+ 'Assigned Stores': element?.assignedStores,
2967
+ 'Flagged Stores': element?.flaggedStores,
2968
+ 'Compliance': element?.complianceRate,
2969
+ 'Flagged Count': element?.flagCount,
2970
+ 'Question Flags': element?.customQuestionFlagCount,
2971
+ 'Not Submitted Flags': element?.customTimeFlagCount,
2972
+ };
2973
+ if ( requestData?.filter === 'question' ) {
2974
+ delete data['Flagged Count'];
2975
+ delete data['Not Submitted Flags'];
2976
+ } else if ( requestData?.filter === 'time' ) {
2977
+ delete data['Flagged Count'];
2978
+ delete data['Question Flags'];
2979
+ } else if ( requestData?.filter === 'detection' ) {
2980
+ delete data['Not Submitted Flags'];
2981
+ delete data['Question Flags'];
2982
+ }
2983
+ exportdata.push( data );
2984
+ } );
2985
+ return await download( exportdata, res );
2986
+ }
2987
+
2988
+
2989
+ result.totalCount = getTotalCount.length;
2990
+ result.checklistPerformance = getChecklistPerformanceData;
2991
+ return res.sendSuccess( result );
2992
+ } catch ( error ) {
2993
+ console.log( 'error =>', error );
2994
+ logger.error( { error: error, message: req.query, function: 'checklistPerformance' } );
2995
+ return res.sendError( { error: error }, 500 );
2996
+ }
2997
+ };
@@ -2610,3 +2610,104 @@ export const selectAssign = async ( req, res ) => {
2610
2610
  }
2611
2611
  };
2612
2612
 
2613
+ export const checklistV2 = async ( req, res ) => {
2614
+ try {
2615
+ let limit = parseInt( req.query.limit ) || 10;
2616
+ let offset = parseInt( req.query.offset - 1 ) || 0;
2617
+ let page = offset * limit;
2618
+ let query = [];
2619
+ query.push(
2620
+ {
2621
+ $match: {
2622
+ type: 'checklist',
2623
+ client_id: req.query.clientId,
2624
+ isdeleted: false,
2625
+ ...( req.user.userType == 'client' && req.user.role != 'superadmin' ) ? { 'owner.value': { $in: [ req.user.email ] } } : {},
2626
+ },
2627
+ },
2628
+ );
2629
+
2630
+ if ( req.query.search && req.query.search != '' ) {
2631
+ req.query.search = req.query.search.replace( /([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1' );
2632
+ query.push( {
2633
+ $match: {
2634
+ checkListName: { $regex: new RegExp( req.query.search, 'i' ) },
2635
+ },
2636
+ } );
2637
+ }
2638
+
2639
+ query.push(
2640
+ {
2641
+ $project: {
2642
+ checkList: { $toLower: '$checkListName' },
2643
+ checkListName: 1,
2644
+ coverage: 1,
2645
+ createdBy: 1,
2646
+ userName: { $toLower: '$createdByName' },
2647
+ createdByName: 1,
2648
+ storeCount: 1,
2649
+ createdAt: 1,
2650
+ publish: 1,
2651
+ checkListType: 1,
2652
+ questionCount: 1,
2653
+ checkListChar: { $substr: [ '$checkListName', 0, 2 ] },
2654
+ },
2655
+ },
2656
+ );
2657
+
2658
+ if ( req.query.sortColumnName && req.query.sortColumnName != '' && req.query.sortBy != '' ) {
2659
+ if ( req.query.sortColumnName == 'status' ) {
2660
+ req.query.sortColumnName = 'publish';
2661
+ }
2662
+ if ( req.query.sortColumnName != 'publish' ) {
2663
+ query.push( {
2664
+ $addFields: { lowerName: { $toLower: `$${req.query.sortColumnName}` } },
2665
+ } );
2666
+ query.push( {
2667
+ $sort: { lowerName: parseInt( req.query.sortBy ) },
2668
+ } );
2669
+ } else {
2670
+ query.push( {
2671
+ $sort: { publish: parseInt( req.query.sortBy ) },
2672
+ } );
2673
+ }
2674
+ } else {
2675
+ query.push(
2676
+ { $sort: { createdAt: -1 } },
2677
+ );
2678
+ }
2679
+
2680
+ query.push( {
2681
+ $facet: {
2682
+ data: [
2683
+ { $skip: page },
2684
+ { $limit: limit },
2685
+ ],
2686
+ count: [
2687
+ { $count: 'totalCount' },
2688
+ ],
2689
+ },
2690
+ } );
2691
+
2692
+ let checkList = await checklistService.aggregate( query );
2693
+
2694
+ if ( !checkList[0].data.length ) {
2695
+ return res.sendError( 'no data found', 204 );
2696
+ }
2697
+
2698
+ checkList[0].data.forEach( ( item ) => {
2699
+ if ( item.storeCount > 0 && item.storeCount <= 9 ) {
2700
+ item.storeCount = '0' + item.storeCount;
2701
+ }
2702
+ if ( item.questionCount > 0 && item.questionCount <= 9 ) {
2703
+ item.questionCount = '0' + item.questionCount;
2704
+ }
2705
+ item.createdAt = dayjs( item.createdAt ).format( 'DD MMM, YYYY' );
2706
+ } );
2707
+
2708
+ return res.sendSuccess( { result: checkList[0].data, count: checkList[0].count[0].totalCount } );
2709
+ } catch ( e ) {
2710
+ logger.error( 'checklist V2 =>', e );
2711
+ return res.sendError( e, 500 );
2712
+ }
2713
+ };
@@ -3641,3 +3641,166 @@ export async function sendAlert( req, res ) {
3641
3641
  return res.sendError( e, 500 );
3642
3642
  }
3643
3643
  }
3644
+
3645
+ export const checklistPerformanceV2 = async ( req, res ) => {
3646
+ try {
3647
+ let requestData = req.body;
3648
+ let fromDate = new Date( requestData.fromDate );
3649
+ let toDate = new Date( requestData.toDate );
3650
+ let userTimezoneOffset = toDate.getTimezoneOffset() * 60000;
3651
+ toDate = new Date( toDate.getTime() - userTimezoneOffset );
3652
+ toDate.setUTCHours( 23, 59, 59, 59 );
3653
+ let result = {};
3654
+
3655
+ let findQuery = [];
3656
+ let findAndQuery = [];
3657
+ findAndQuery.push(
3658
+ { checkListType: { $eq: 'custom' } },
3659
+ { date_iso: { $gte: fromDate, $lte: toDate } },
3660
+ { client_id: requestData.clientId },
3661
+ { store_id: { $in: requestData.storeId } },
3662
+ );
3663
+
3664
+ findQuery.push( { $match: { $and: findAndQuery } } );
3665
+
3666
+ if ( requestData.searchValue && requestData.searchValue != '' ) {
3667
+ let checkListSearch = requestData.searchValue.split( ',' ).map( ( item ) => item.trim().toLowerCase() );
3668
+ let query;
3669
+ if ( checkListSearch.length > 1 ) {
3670
+ findQuery.push( { $addFields: { cheklistlowercase: { $toLower: '$checkListName' } } } );
3671
+ query = { cheklistlowercase: { $in: checkListSearch } };
3672
+ } else {
3673
+ query = { checkListName: { $regex: requestData.searchValue.trim(), $options: 'i' } };
3674
+ }
3675
+ findQuery.push( { $match: { $or: [ query ] } } );
3676
+ }
3677
+
3678
+ findQuery.push( {
3679
+ $group: {
3680
+ _id: '$sourceCheckList_id',
3681
+ sourceCheckList_id: { $last: '$sourceCheckList_id' },
3682
+ checkListName: { $last: '$checkListName' },
3683
+ coverage: { $last: '$coverage' },
3684
+ checkListChar: { $last: { $substr: [ '$checkListName', 0, 2 ] } },
3685
+ scheduleRepeatedType: { $last: '$scheduleRepeatedType' },
3686
+ // storeCount: { $max: '$storeCount' },
3687
+ storeCount: { $sum: 1 },
3688
+ submittedChecklist: {
3689
+ $sum: {
3690
+ $cond: [ { $eq: [ '$checklistStatus', 'submit' ] }, 1, 0 ],
3691
+ },
3692
+ },
3693
+ timeFlag: { $sum: '$timeFlag' },
3694
+ questionFlagCount: { $sum: '$questionFlag' },
3695
+ checkListType: { $last: '$checkListType' },
3696
+ redo: { $sum: { $cond: [ { $eq: [ '$redoStatus', true ] }, 1, 0 ] } },
3697
+ task: {
3698
+ $sum: {
3699
+ $reduce: {
3700
+ input: '$questionAnswers',
3701
+ initialValue: 0,
3702
+ in: {
3703
+ $add: [
3704
+ '$$value',
3705
+ {
3706
+ $reduce: {
3707
+ input: { $ifNull: [ '$$this.questions', [] ] },
3708
+ initialValue: 0,
3709
+ in: {
3710
+ $add: [
3711
+ '$$value',
3712
+ {
3713
+ $cond: [
3714
+ { $ifNull: [ '$$this.taskId', false ] },
3715
+ 1,
3716
+ 0,
3717
+ ],
3718
+ },
3719
+ ],
3720
+ },
3721
+ },
3722
+ },
3723
+ ],
3724
+ },
3725
+ },
3726
+ },
3727
+ },
3728
+ },
3729
+ } );
3730
+ findQuery.push( {
3731
+ $project: {
3732
+ _id: 1,
3733
+ sourceCheckList_id: 1,
3734
+ checkListName: 1,
3735
+ checkListChar: 1,
3736
+ coverage: {
3737
+ $concat: [
3738
+ { $toUpper: { $substr: [ { $ifNull: [ '$coverage', '' ] }, 0, 1 ] } },
3739
+ { $substr: [ { $ifNull: [ '$coverage', '' ] }, 1, { $strLenCP: { $ifNull: [ '$coverage', '' ] } } ] },
3740
+ ],
3741
+ },
3742
+ scheduleRepeatedType: {
3743
+ $concat: [
3744
+ { $toUpper: { $substr: [ '$scheduleRepeatedType', 0, 1 ] } }, // Capitalize the first letter
3745
+ { $substr: [ '$scheduleRepeatedType', 1, { $strLenCP: '$scheduleRepeatedType' } ] }, // Append the rest of the string
3746
+ ],
3747
+ },
3748
+ storeCount: 1,
3749
+ submittedChecklist: 1,
3750
+ flaggedChecklist: { $add: [ '$timeFlag', '$questionFlagCount' ] },
3751
+ checkListType: 1,
3752
+ redo: 1,
3753
+ task: 1,
3754
+ },
3755
+ } );
3756
+
3757
+ if ( requestData.sortColumnName && requestData.sortColumnName != '' && requestData.sortBy && requestData.sortBy !='' ) {
3758
+ findQuery.push( { $sort: { [requestData.sortColumnName]: requestData.sortBy } } );
3759
+ } else {
3760
+ findQuery.push( { $sort: { ['submittedChecklist']: -1 } } );
3761
+ }
3762
+
3763
+ let limit = parseInt( requestData?.limit ) || 10;
3764
+ let skip = limit * ( requestData?.offset ) || 0;
3765
+
3766
+ findQuery.push( {
3767
+ $facet: {
3768
+ data: [
3769
+ { $skip: skip }, { $limit: limit },
3770
+ ],
3771
+ count: [
3772
+ { $count: 'total' },
3773
+ ],
3774
+ },
3775
+ } );
3776
+ let getChecklistPerformanceData = await processedchecklistService.aggregate( findQuery );
3777
+ if ( !getChecklistPerformanceData[0].data.length ) {
3778
+ return res.sendError( 'no data found', 204 );
3779
+ }
3780
+
3781
+ if ( requestData.export ) {
3782
+ const exportdata = [];
3783
+ getChecklistPerformanceData[0].data.forEach( ( element ) => {
3784
+ exportdata.push( {
3785
+ 'Checklist Name': element.checkListName || '--',
3786
+ 'Coverage': element.coverage || '--',
3787
+ 'Scheduled': element.scheduleRepeatedType || '--',
3788
+ 'Assigned To': element.storeCount || '--',
3789
+ 'Submitted': element.submittedChecklist || '--',
3790
+ 'Flags': element.flaggedChecklist || '--',
3791
+ 'Tasks': element.task || '--',
3792
+ 'ReDo': element.redo || '--',
3793
+ } );
3794
+ } );
3795
+ return await download( exportdata, res );
3796
+ }
3797
+
3798
+ result.totalCount = getChecklistPerformanceData[0].count[0].total;
3799
+ result.checklistPerformance = getChecklistPerformanceData[0].data;
3800
+ return res.sendSuccess( result );
3801
+ } catch ( error ) {
3802
+ console.log( 'error =>', error );
3803
+ logger.error( { error: error, message: req.query, function: 'checklistPerformance' } );
3804
+ return res.sendError( { error: error }, 500 );
3805
+ }
3806
+ };
@@ -22,6 +22,7 @@ traxRouter
22
22
  .get( '/zoneList', isAllowedSessionHandler, isAllowedClient, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoTrax', name: 'checklist', permissions: [ ] } ] } ), traxController.zoneList )
23
23
  .get( '/aichecklist', isAllowedSessionHandler, isAllowedClient, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoTrax', name: 'checklist', permissions: [ ] } ] } ), validate( aichecklistValidation ), traxController.aiChecklist )
24
24
  .get( '/predefinedChecklist', isAllowedSessionHandler, isAllowedClient, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoTrax', name: 'checklist', permissions: [ ] } ] } ), validate( aichecklistValidation ), traxController.preDefinedChecklist )
25
- .post( '/selectAssign', validate( selectAssign ), traxController.selectAssign );
25
+ .post( '/selectAssign', validate( selectAssign ), traxController.selectAssign )
26
+ .get( '/checklistV2', isAllowedSessionHandler, isAllowedClient, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoTrax', name: 'checklist', permissions: [ ] } ] } ), validate( checklistPageSchema ), traxController.checklistV2 );
26
27
 
27
28
  // isAllowedSessionHandler, isAllowedClient, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoTrax', name: 'checklist', permissions: [ ] } ] } ),
@@ -29,6 +29,7 @@ import {
29
29
  reportChecklistTableV1,
30
30
  reinitiatechecklist,
31
31
  sendAlert,
32
+ checklistPerformanceV2,
32
33
  } from '../controllers/traxDashboard.controllers.js';
33
34
 
34
35
  traxDashboardRouter
@@ -56,6 +57,7 @@ traxDashboardRouter
56
57
  .post( '/reportChecklistData', reportChecklistTable )
57
58
  .post( '/reportChecklistDataV1', isAllowedSessionHandler, isAllowedClient, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoTrax', name: 'checklist', permissions: [] } ] } ), validate( dashboardValidationDtos.validateReportChecklistTableParams ), reportChecklistTableV1 )
58
59
  .post( '/reinitiatechecklist', isAllowedSessionHandler, isAllowedClient, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoTrax', name: 'checklist', permissions: [ 'isAdd', 'isEdit' ] } ] } ), reinitiatechecklist )
59
- .post( '/sendAlert', isAllowedSessionHandler, sendAlert );
60
+ .post( '/sendAlert', isAllowedSessionHandler, sendAlert )
61
+ .post( '/checklistPerformanceV2', isAllowedSessionHandler, isAllowedClient, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoTrax', name: 'checklist', permissions: [] } ] } ), validate( dashboardValidationDtos.validateChecklistPerformanceParams ), checklistPerformanceV2 );
60
62
 
61
63
  export default traxDashboardRouter;
@@ -18,6 +18,7 @@ import {
18
18
  flagComparisonCardsV1,
19
19
  flagTablesV1,
20
20
  checklistDropdownV1,
21
+ flagTablesV2,
21
22
  } from '../controllers/teaxFlag.controller.js';
22
23
  import { isAllowedSessionHandler } from 'tango-app-api-middleware';
23
24
  import { accessVerification } from 'tango-app-api-middleware';
@@ -68,7 +69,10 @@ traxFlagRouter
68
69
  flagComparisonCardsV1 )
69
70
  .post( '/flagTablesV1', isAllowedSessionHandler,
70
71
  accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoTrax', name: 'checklist', permissions: [] } ] } ),
71
- flagTablesV1 );
72
+ flagTablesV1 )
73
+ .post( '/flagTablesV2', isAllowedSessionHandler,
74
+ accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoTrax', name: 'checklist', permissions: [] } ] } ),
75
+ flagTablesV2 );
72
76
 
73
77
 
74
78
  export default traxFlagRouter;