tango-app-api-infra 3.9.5-vms.84 → 3.9.5-vms.85
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
|
@@ -902,9 +902,13 @@ export async function ticketSummary( req, res ) {
|
|
|
902
902
|
const userInfo = req.user;
|
|
903
903
|
const ticketsFeature = userInfo?.rolespermission?.some( ( f ) => f.featureName === 'FootfallDirectory' && ( f.modules.find( ( m ) => m.name == 'reviewer' && ( m.isAdd == true || m.isEdit == true ) ) ) );
|
|
904
904
|
const ticketsApproveFeature = userInfo?.rolespermission?.some( ( f ) => f.featureName === 'FootfallDirectory' && ( f.modules.find( ( m ) => m.name == 'approver' && ( m.isAdd == true || m.isEdit == true ) ) ) );
|
|
905
|
-
|
|
905
|
+
const getConfig = await findOneClient( { clientId: inputData?.clientId }, { footfallDirectoryConfigs: 1 } );
|
|
906
|
+
if ( !getConfig || getConfig ==null ) {
|
|
907
|
+
return res.sendError( 'this client not configured against footfall directory', 400 );
|
|
908
|
+
}
|
|
909
|
+
inputData.clientId = inputData?.clientId?.split( ',' );
|
|
906
910
|
// const ticketsApproveFeature = userInfo?.rolespermission?.some( ( f ) => f.featureName === 'FootfallDirectory' && ( f.modules.find( ( m ) => m.name == 'approver' && ( m.isAdd == true || m.isEdit == true ) ) ) );
|
|
907
|
-
if ( req?.user?.userType
|
|
911
|
+
if ( req?.user?.userType !== 'tango' ) {
|
|
908
912
|
switch ( inputData?.tangoType ) {
|
|
909
913
|
case 'store':
|
|
910
914
|
const storeQuery = {
|
|
@@ -921,6 +925,24 @@ export async function ticketSummary( req, res ) {
|
|
|
921
925
|
},
|
|
922
926
|
},
|
|
923
927
|
},
|
|
928
|
+
|
|
929
|
+
{
|
|
930
|
+
terms: {
|
|
931
|
+
'clientId.keyword': Array.isArray( inputData.clientId ) ?
|
|
932
|
+
inputData.clientId :
|
|
933
|
+
[ inputData.clientId ],
|
|
934
|
+
},
|
|
935
|
+
|
|
936
|
+
},
|
|
937
|
+
|
|
938
|
+
{
|
|
939
|
+
range: {
|
|
940
|
+
reviced: {
|
|
941
|
+
lt: parseInt( getConfig?.footfallDirectoryConfigs?.tangoReview ),
|
|
942
|
+
}
|
|
943
|
+
,
|
|
944
|
+
},
|
|
945
|
+
},
|
|
924
946
|
{
|
|
925
947
|
nested: {
|
|
926
948
|
path: 'mappingInfo',
|
|
@@ -983,20 +1005,7 @@ export async function ticketSummary( req, res ) {
|
|
|
983
1005
|
size: 0,
|
|
984
1006
|
aggs: {
|
|
985
1007
|
avg_value: {
|
|
986
|
-
avg:
|
|
987
|
-
script: {
|
|
988
|
-
lang: 'painless',
|
|
989
|
-
source: `
|
|
990
|
-
if (doc['revicedPerc.keyword'].size() == 0) return null;
|
|
991
|
-
String v = doc['revicedPerc.keyword'].value.replace('%','');
|
|
992
|
-
try {
|
|
993
|
-
return Double.parseDouble(v);
|
|
994
|
-
} catch (Exception e) {
|
|
995
|
-
return null;
|
|
996
|
-
}
|
|
997
|
-
`,
|
|
998
|
-
},
|
|
999
|
-
},
|
|
1008
|
+
avg: 'reviced',
|
|
1000
1009
|
},
|
|
1001
1010
|
},
|
|
1002
1011
|
};
|
|
@@ -1029,11 +1038,10 @@ export async function ticketSummary( req, res ) {
|
|
|
1029
1038
|
// openInfraIssues: mappingInfo.status: 'Open Accuracy Issue'
|
|
1030
1039
|
let openInfraIssues = 0;
|
|
1031
1040
|
|
|
1032
|
-
let oiQ = buildStoreQueryWithStatus( baseStoreQuery, 'Open Accuracy Issue' );
|
|
1041
|
+
let oiQ = buildStoreQueryWithStatus( baseStoreQuery, 'Open - Accuracy Issue' );
|
|
1033
1042
|
oiQ.size = 0;
|
|
1034
1043
|
const infraResp = await getOpenSearchData( openSearch.footfallDirectory, oiQ );
|
|
1035
1044
|
openInfraIssues = infraResp?.body?.hits?.total?.value || 0;
|
|
1036
|
-
|
|
1037
1045
|
// inprogress: mappingInfo.status: 'in-Progress'
|
|
1038
1046
|
let inprogress = 0;
|
|
1039
1047
|
|
|
@@ -1063,14 +1071,9 @@ export async function ticketSummary( req, res ) {
|
|
|
1063
1071
|
// For this, add a filter on revicedPerc >= 85
|
|
1064
1072
|
let aboveQ = buildAggStoreQuery( baseStoreQuery, [
|
|
1065
1073
|
{
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
source: `
|
|
1070
|
-
doc['revicedPerc.keyword'].size()!=0 &&
|
|
1071
|
-
Integer.parseInt(doc['revicedPerc.keyword'].value.replace('%','')) >= params.num
|
|
1072
|
-
`,
|
|
1073
|
-
params: { num: 85 },
|
|
1074
|
+
range: {
|
|
1075
|
+
reviced: {
|
|
1076
|
+
gte: parseInt( getConfig?.footfallDirectoryConfigs?.tangoReview ),
|
|
1074
1077
|
},
|
|
1075
1078
|
},
|
|
1076
1079
|
},
|
|
@@ -1085,14 +1088,9 @@ export async function ticketSummary( req, res ) {
|
|
|
1085
1088
|
|
|
1086
1089
|
let belowQ = buildAggStoreQuery( baseStoreQuery, [
|
|
1087
1090
|
{
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
source: `
|
|
1092
|
-
doc['revicedPerc.keyword'].size()!=0 &&
|
|
1093
|
-
Integer.parseInt(doc['revicedPerc.keyword'].value.replace('%','')) < params.num
|
|
1094
|
-
`,
|
|
1095
|
-
params: { num: 85 },
|
|
1091
|
+
range: {
|
|
1092
|
+
reviced: {
|
|
1093
|
+
lt: parseInt( getConfig?.footfallDirectoryConfigs?.tangoReview ),
|
|
1096
1094
|
},
|
|
1097
1095
|
},
|
|
1098
1096
|
},
|
|
@@ -1128,23 +1126,48 @@ export async function ticketSummary( req, res ) {
|
|
|
1128
1126
|
},
|
|
1129
1127
|
},
|
|
1130
1128
|
},
|
|
1129
|
+
{
|
|
1130
|
+
terms: {
|
|
1131
|
+
'clientId.keyword': Array.isArray( inputData.clientId ) ?
|
|
1132
|
+
inputData.clientId :
|
|
1133
|
+
[ inputData.clientId ],
|
|
1134
|
+
},
|
|
1135
|
+
|
|
1136
|
+
},
|
|
1137
|
+
|
|
1138
|
+
],
|
|
1139
|
+
},
|
|
1140
|
+
},
|
|
1141
|
+
};
|
|
1131
1142
|
|
|
1143
|
+
const internalOpen = {
|
|
1144
|
+
size: 0,
|
|
1145
|
+
query: {
|
|
1146
|
+
bool: {
|
|
1147
|
+
must: [
|
|
1132
1148
|
{
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
{
|
|
1139
|
-
terms: {
|
|
1140
|
-
'mappingInfo.type': [ 'tagging', 'review', 'approve', 'tangoreview' ],
|
|
1141
|
-
},
|
|
1142
|
-
},
|
|
1143
|
-
],
|
|
1144
|
-
},
|
|
1149
|
+
'range': {
|
|
1150
|
+
'dateString': {
|
|
1151
|
+
'gte': inputData?.fromDate,
|
|
1152
|
+
'lte': inputData?.toDate,
|
|
1153
|
+
'format': 'yyyy-MM-dd',
|
|
1145
1154
|
},
|
|
1146
1155
|
},
|
|
1147
1156
|
},
|
|
1157
|
+
{
|
|
1158
|
+
terms: {
|
|
1159
|
+
'clientId.keyword': Array.isArray( inputData.clientId ) ?
|
|
1160
|
+
inputData.clientId :
|
|
1161
|
+
[ inputData.clientId ],
|
|
1162
|
+
},
|
|
1163
|
+
|
|
1164
|
+
},
|
|
1165
|
+
{
|
|
1166
|
+
terms: {
|
|
1167
|
+
'status.keyword': [ 'Open', 'Raised' ],
|
|
1168
|
+
},
|
|
1169
|
+
|
|
1170
|
+
},
|
|
1148
1171
|
|
|
1149
1172
|
],
|
|
1150
1173
|
},
|
|
@@ -1154,20 +1177,32 @@ export async function ticketSummary( req, res ) {
|
|
|
1154
1177
|
// Helper function to clone deep and replace mappingInfo.status for openTickets/closed/etc
|
|
1155
1178
|
function buildInternalQueryWithStatus( baseQuery, statusValue ) {
|
|
1156
1179
|
let q = JSON.parse( JSON.stringify( baseQuery ) );
|
|
1157
|
-
//
|
|
1180
|
+
// Check if nested query exists, if not create it
|
|
1158
1181
|
let nested = q.query.bool.must.find( ( m ) => m.nested );
|
|
1159
|
-
if ( nested ) {
|
|
1160
|
-
//
|
|
1161
|
-
nested
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1182
|
+
if ( !nested ) {
|
|
1183
|
+
// Create nested query structure
|
|
1184
|
+
nested = {
|
|
1185
|
+
nested: {
|
|
1186
|
+
path: 'mappingInfo',
|
|
1187
|
+
query: {
|
|
1188
|
+
bool: {
|
|
1189
|
+
must: [],
|
|
1190
|
+
},
|
|
1191
|
+
},
|
|
1168
1192
|
},
|
|
1169
|
-
}
|
|
1193
|
+
};
|
|
1194
|
+
q.query.bool.must.push( nested );
|
|
1170
1195
|
}
|
|
1196
|
+
// filter out all mappingInfo.status
|
|
1197
|
+
nested.nested.query.bool.must = nested?.nested?.query?.bool?.must.filter( ( mustItem ) => {
|
|
1198
|
+
return !( mustItem.term && mustItem.term['mappingInfo.status'] );
|
|
1199
|
+
} );
|
|
1200
|
+
// add desired status
|
|
1201
|
+
nested.nested.query.bool.must.push( {
|
|
1202
|
+
term: {
|
|
1203
|
+
'mappingInfo.status': statusValue,
|
|
1204
|
+
},
|
|
1205
|
+
} );
|
|
1171
1206
|
return q;
|
|
1172
1207
|
}
|
|
1173
1208
|
|
|
@@ -1183,7 +1218,7 @@ export async function ticketSummary( req, res ) {
|
|
|
1183
1218
|
nested.nested.query.bool.must.filter( ( m ) => !( m.term && m.term['mappingInfo.status'] ) );
|
|
1184
1219
|
|
|
1185
1220
|
// add new filters
|
|
1186
|
-
|
|
1221
|
+
q.query.bool.must.push( ...filters );
|
|
1187
1222
|
}
|
|
1188
1223
|
|
|
1189
1224
|
return {
|
|
@@ -1192,18 +1227,7 @@ export async function ticketSummary( req, res ) {
|
|
|
1192
1227
|
aggs: {
|
|
1193
1228
|
avg_value: {
|
|
1194
1229
|
avg: {
|
|
1195
|
-
|
|
1196
|
-
lang: 'painless',
|
|
1197
|
-
source: `
|
|
1198
|
-
if (doc['revicedPerc.keyword'].size() == 0) return null;
|
|
1199
|
-
String v = doc['revicedPerc.keyword'].value.replace('%','');
|
|
1200
|
-
try {
|
|
1201
|
-
return Double.parseDouble(v);
|
|
1202
|
-
} catch (Exception e) {
|
|
1203
|
-
return null;
|
|
1204
|
-
}
|
|
1205
|
-
`,
|
|
1206
|
-
},
|
|
1230
|
+
field: 'reviced',
|
|
1207
1231
|
},
|
|
1208
1232
|
},
|
|
1209
1233
|
},
|
|
@@ -1224,13 +1248,14 @@ export async function ticketSummary( req, res ) {
|
|
|
1224
1248
|
allInternalQuery.size = 0;
|
|
1225
1249
|
const totalInternalResp = await getOpenSearchData( openSearch.footfallDirectory, allInternalQuery );
|
|
1226
1250
|
totalInternalTickets = totalInternalResp?.body?.hits?.total?.value || 0;
|
|
1251
|
+
logger.info( { totalInternalResp } );
|
|
1227
1252
|
|
|
1228
1253
|
// openTickets: mappingInfo.status: 'Open'
|
|
1229
1254
|
let openInternalTickets = 0;
|
|
1230
1255
|
|
|
1231
|
-
let otQInternal = buildInternalQueryWithStatus( baseInternalQuery, 'Open' );
|
|
1232
|
-
otQInternal.size = 0;
|
|
1233
|
-
const openInternalResp = await getOpenSearchData( openSearch.footfallDirectory,
|
|
1256
|
+
// let otQInternal = buildInternalQueryWithStatus( baseInternalQuery, 'Open' );
|
|
1257
|
+
// otQInternal.size = 0;
|
|
1258
|
+
const openInternalResp = await getOpenSearchData( openSearch.footfallDirectory, internalOpen );
|
|
1234
1259
|
openInternalTickets = openInternalResp?.body?.hits?.total?.value || 0;
|
|
1235
1260
|
// logger.info( { msd: '..............2', openResp } );
|
|
1236
1261
|
|
|
@@ -1238,11 +1263,12 @@ export async function ticketSummary( req, res ) {
|
|
|
1238
1263
|
// openInfraIssues: mappingInfo.status: 'Open Accuracy Issue'
|
|
1239
1264
|
let openInternalInfraIssues = 0;
|
|
1240
1265
|
|
|
1241
|
-
let oiQinternal = buildInternalQueryWithStatus( baseInternalQuery, 'Open Accuracy Issue' );
|
|
1266
|
+
let oiQinternal = buildInternalQueryWithStatus( baseInternalQuery, 'Open - Accuracy Issue' );
|
|
1242
1267
|
oiQinternal.size = 0;
|
|
1243
1268
|
const infraInternalResp = await getOpenSearchData( openSearch.footfallDirectory, oiQinternal );
|
|
1244
1269
|
openInternalInfraIssues = infraInternalResp?.body?.hits?.total?.value || 0;
|
|
1245
1270
|
|
|
1271
|
+
|
|
1246
1272
|
// inprogress: mappingInfo.status: 'in-Progress'
|
|
1247
1273
|
let inprogressIntrenal = 0;
|
|
1248
1274
|
|
|
@@ -1272,14 +1298,9 @@ export async function ticketSummary( req, res ) {
|
|
|
1272
1298
|
// For this, add a filter on revicedPerc >= 85
|
|
1273
1299
|
let aboveQinternal = buildAggInternalQuery( baseInternalQuery, [
|
|
1274
1300
|
{
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
source: `
|
|
1279
|
-
doc['revicedPerc.keyword'].size()!=0 &&
|
|
1280
|
-
Integer.parseInt(doc['revicedPerc.keyword'].value.replace('%','')) >= params.num
|
|
1281
|
-
`,
|
|
1282
|
-
params: { num: 85 },
|
|
1301
|
+
range: {
|
|
1302
|
+
reviced: {
|
|
1303
|
+
gte: parseInt( getConfig?.footfallDirectoryConfigs?.tangoReview ),
|
|
1283
1304
|
},
|
|
1284
1305
|
},
|
|
1285
1306
|
},
|
|
@@ -1294,14 +1315,9 @@ export async function ticketSummary( req, res ) {
|
|
|
1294
1315
|
|
|
1295
1316
|
let belowQIneranl = buildAggInternalQuery( baseInternalQuery, [
|
|
1296
1317
|
{
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
source: `
|
|
1301
|
-
doc['revicedPerc.keyword'].size()!=0 &&
|
|
1302
|
-
Integer.parseInt(doc['revicedPerc.keyword'].value.replace('%','')) < params.num
|
|
1303
|
-
`,
|
|
1304
|
-
params: { num: 85 },
|
|
1318
|
+
range: {
|
|
1319
|
+
reviced: {
|
|
1320
|
+
lt: parseInt( getConfig?.footfallDirectoryConfigs?.tangoReview ),
|
|
1305
1321
|
},
|
|
1306
1322
|
},
|
|
1307
1323
|
},
|
|
@@ -1324,8 +1340,10 @@ export async function ticketSummary( req, res ) {
|
|
|
1324
1340
|
break;
|
|
1325
1341
|
default: '';
|
|
1326
1342
|
}
|
|
1327
|
-
} else if ( req?.user?.userType === '
|
|
1343
|
+
} else if ( req?.user?.userType === 'tango' ) {
|
|
1344
|
+
logger.info( { msg: '.........1', ticketsFeature, ticketsApproveFeature } );
|
|
1328
1345
|
if ( ticketsFeature && !ticketsApproveFeature ) {
|
|
1346
|
+
logger.info( '.........3' );
|
|
1329
1347
|
const storeQuery = {
|
|
1330
1348
|
size: 0,
|
|
1331
1349
|
query: {
|
|
@@ -1340,6 +1358,14 @@ export async function ticketSummary( req, res ) {
|
|
|
1340
1358
|
},
|
|
1341
1359
|
},
|
|
1342
1360
|
},
|
|
1361
|
+
{
|
|
1362
|
+
terms: {
|
|
1363
|
+
'clientId.keyword': Array.isArray( inputData.clientId ) ?
|
|
1364
|
+
inputData.clientId :
|
|
1365
|
+
[ inputData.clientId ],
|
|
1366
|
+
},
|
|
1367
|
+
|
|
1368
|
+
},
|
|
1343
1369
|
{
|
|
1344
1370
|
nested: {
|
|
1345
1371
|
path: 'mappingInfo',
|
|
@@ -1402,20 +1428,7 @@ export async function ticketSummary( req, res ) {
|
|
|
1402
1428
|
size: 0,
|
|
1403
1429
|
aggs: {
|
|
1404
1430
|
avg_value: {
|
|
1405
|
-
avg:
|
|
1406
|
-
script: {
|
|
1407
|
-
lang: 'painless',
|
|
1408
|
-
source: `
|
|
1409
|
-
if (doc['revicedPerc.keyword'].size() == 0) return null;
|
|
1410
|
-
String v = doc['revicedPerc.keyword'].value.replace('%','');
|
|
1411
|
-
try {
|
|
1412
|
-
return Double.parseDouble(v);
|
|
1413
|
-
} catch (Exception e) {
|
|
1414
|
-
return null;
|
|
1415
|
-
}
|
|
1416
|
-
`,
|
|
1417
|
-
},
|
|
1418
|
-
},
|
|
1431
|
+
avg: 'mappingInfo.reviced',
|
|
1419
1432
|
},
|
|
1420
1433
|
},
|
|
1421
1434
|
};
|
|
@@ -1490,48 +1503,44 @@ try {
|
|
|
1490
1503
|
const eResp = await getOpenSearchData( openSearch.footfallDirectory, eQ );
|
|
1491
1504
|
expiredTickets = eResp?.body?.hits?.total?.value || 0;
|
|
1492
1505
|
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1506
|
+
// Calculate average ticket percentage: avg((reviced/footfallCount)*100) filtered by baseStoreQuery
|
|
1507
|
+
|
|
1508
|
+
// Build aggregation query for ticket percentage
|
|
1509
|
+
let ticketPercentageAvg = 0;
|
|
1510
|
+
|
|
1511
|
+
let avgTicketPercentageQuery = JSON.parse( JSON.stringify( baseStoreQuery ) );
|
|
1512
|
+
avgTicketPercentageQuery.size = 0;
|
|
1513
|
+
avgTicketPercentageQuery.aggs = {
|
|
1514
|
+
avg_ticket_percentage: {
|
|
1515
|
+
avg: {
|
|
1498
1516
|
script: {
|
|
1499
|
-
lang: 'painless',
|
|
1500
1517
|
source: `
|
|
1501
|
-
doc['
|
|
1502
|
-
|
|
1518
|
+
if (doc.containsKey('reviced') && doc['reviced'].size()!=0 &&
|
|
1519
|
+
doc.containsKey('footfallCount') && doc['footfallCount'].size()!=0 && doc['footfallCount'].value != 0) {
|
|
1520
|
+
return (doc['reviced'].value / doc['footfallCount'].value) * 100;
|
|
1521
|
+
} else {
|
|
1522
|
+
return null;
|
|
1523
|
+
}
|
|
1503
1524
|
`,
|
|
1504
|
-
|
|
1525
|
+
lang: 'painless',
|
|
1505
1526
|
},
|
|
1506
1527
|
},
|
|
1507
1528
|
},
|
|
1529
|
+
};
|
|
1508
1530
|
|
|
1531
|
+
const avgTicketPercentageResp = await getOpenSearchData( openSearch.footfallDirectory, avgTicketPercentageQuery );
|
|
1509
1532
|
|
|
1510
|
-
|
|
1511
|
-
const aboveResp = await getOpenSearchData( openSearch.footfallDirectory, aboveQ );
|
|
1512
|
-
ticketAccuracyAbove = aboveResp?.body?.aggregations?.avg_value?.value?.toFixed( 2 ) || '0';
|
|
1533
|
+
ticketPercentageAvg = avgTicketPercentageResp?.body?.aggregations?.avg_ticket_percentage?.value?.toFixed( 2 ) || '0';
|
|
1513
1534
|
|
|
1535
|
+
logger.info( { avgTicketPercentageResp } );
|
|
1514
1536
|
// ticketAccuracyBelow: avg of revicedPerc < 85%
|
|
1515
|
-
let
|
|
1516
|
-
|
|
1517
|
-
let belowQ = buildAggStoreQuery( baseStoreQuery, [
|
|
1518
|
-
{
|
|
1519
|
-
script: {
|
|
1520
|
-
script: {
|
|
1521
|
-
lang: 'painless',
|
|
1522
|
-
source: `
|
|
1523
|
-
doc['revicedPerc.keyword'].size()!=0 &&
|
|
1524
|
-
Integer.parseInt(doc['revicedPerc.keyword'].value.replace('%','')) < params.num
|
|
1525
|
-
`,
|
|
1526
|
-
params: { num: 85 },
|
|
1527
|
-
},
|
|
1528
|
-
},
|
|
1529
|
-
},
|
|
1530
|
-
|
|
1531
|
-
] );
|
|
1532
|
-
const belowResp = await getOpenSearchData( openSearch.footfallDirectory, belowQ );
|
|
1533
|
-
ticketAccuracyBelow = belowResp?.body?.aggregations?.avg_value?.value?.toFixed( 2 ) || '0';
|
|
1537
|
+
let ticketAccuracy = 0;
|
|
1534
1538
|
|
|
1539
|
+
let belowQ = buildAggStoreQuery( baseStoreQuery );
|
|
1540
|
+
logger.info( { belowQ } );
|
|
1541
|
+
const accuracyResp = await getOpenSearchData( openSearch.footfallDirectory, belowQ );
|
|
1542
|
+
ticketAccuracy = accuracyResp?.body?.aggregations?.avg_value?.value?.toFixed( 2 ) || '0';
|
|
1543
|
+
logger.info( { accuracyResp } );
|
|
1535
1544
|
// Final result object
|
|
1536
1545
|
result = {
|
|
1537
1546
|
totalTickets,
|
|
@@ -1540,465 +1549,435 @@ try {
|
|
|
1540
1549
|
closedTickets,
|
|
1541
1550
|
dueToday: dueToday,
|
|
1542
1551
|
Expired: expiredTickets,
|
|
1543
|
-
avgTicket:
|
|
1544
|
-
avgAccuracy:
|
|
1552
|
+
avgTicket: ticketPercentageAvg+'%',
|
|
1553
|
+
avgAccuracy: ticketAccuracy+'%',
|
|
1545
1554
|
};
|
|
1546
|
-
}
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1555
|
+
} else if ( ticketsFeature && ticketsApproveFeature ) {
|
|
1556
|
+
logger.info( '.........2' );
|
|
1557
|
+
if ( inputData?.permissionType === 'review' ) {
|
|
1558
|
+
const storeQuery = {
|
|
1559
|
+
size: 0,
|
|
1560
|
+
query: {
|
|
1561
|
+
bool: {
|
|
1562
|
+
must: [
|
|
1563
|
+
{
|
|
1564
|
+
'range': {
|
|
1565
|
+
'dateString': {
|
|
1566
|
+
'gte': inputData?.fromDate,
|
|
1567
|
+
'lte': inputData?.toDate,
|
|
1568
|
+
'format': 'yyyy-MM-dd',
|
|
1569
|
+
},
|
|
1560
1570
|
},
|
|
1561
1571
|
},
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
+
{
|
|
1573
|
+
terms: {
|
|
1574
|
+
'clientId.keyword': Array.isArray( inputData.clientId ) ?
|
|
1575
|
+
inputData.clientId :
|
|
1576
|
+
[ inputData.clientId ],
|
|
1577
|
+
},
|
|
1578
|
+
|
|
1579
|
+
},
|
|
1580
|
+
{
|
|
1581
|
+
nested: {
|
|
1582
|
+
path: 'mappingInfo',
|
|
1583
|
+
query: {
|
|
1584
|
+
bool: {
|
|
1585
|
+
must: [
|
|
1586
|
+
{
|
|
1587
|
+
term: {
|
|
1588
|
+
'mappingInfo.type': 'review',
|
|
1589
|
+
},
|
|
1572
1590
|
},
|
|
1573
|
-
|
|
1574
|
-
|
|
1591
|
+
],
|
|
1592
|
+
},
|
|
1575
1593
|
},
|
|
1576
1594
|
},
|
|
1577
1595
|
},
|
|
1578
|
-
},
|
|
1579
1596
|
|
|
1580
|
-
|
|
1597
|
+
],
|
|
1598
|
+
},
|
|
1581
1599
|
},
|
|
1582
|
-
}
|
|
1583
|
-
};
|
|
1600
|
+
};
|
|
1584
1601
|
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1602
|
+
// Helper function to clone deep and replace mappingInfo.status for openTickets/closed/etc
|
|
1603
|
+
function buildStoreQueryWithStatus( baseQuery, statusValue ) {
|
|
1604
|
+
let q = JSON.parse( JSON.stringify( baseQuery ) );
|
|
1605
|
+
// Remove any previous mappingInfo.status term
|
|
1606
|
+
let nested = q.query.bool.must.find( ( m ) => m.nested );
|
|
1607
|
+
if ( nested ) {
|
|
1608
|
+
// filter out all mappingInfo.status
|
|
1609
|
+
nested.nested.query.bool.must = nested?.nested?.query?.bool?.must.filter( ( mustItem ) => {
|
|
1610
|
+
return !( mustItem.term && mustItem.term['mappingInfo.status'] );
|
|
1611
|
+
} );
|
|
1612
|
+
// add desired status
|
|
1613
|
+
nested.nested.query.bool.must.push( {
|
|
1614
|
+
term: {
|
|
1615
|
+
'mappingInfo.status': statusValue,
|
|
1616
|
+
},
|
|
1617
|
+
} );
|
|
1618
|
+
}
|
|
1619
|
+
return q;
|
|
1601
1620
|
}
|
|
1602
|
-
return q;
|
|
1603
|
-
}
|
|
1604
1621
|
|
|
1605
|
-
|
|
1606
|
-
|
|
1622
|
+
const buildAggStoreQuery = ( baseQuery, filters = [] ) => {
|
|
1623
|
+
const q = JSON.parse( JSON.stringify( baseQuery ) );
|
|
1607
1624
|
|
|
1608
|
-
|
|
1609
|
-
|
|
1625
|
+
// locate nested section
|
|
1626
|
+
const nested = q.query.bool.must.find( ( m ) => m.nested );
|
|
1610
1627
|
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1628
|
+
if ( nested ) {
|
|
1629
|
+
// remove old status filters
|
|
1630
|
+
nested.nested.query.bool.must =
|
|
1631
|
+
nested.nested.query.bool.must.filter( ( m ) => !( m.term && m.term['mappingInfo.status'] ) );
|
|
1615
1632
|
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1633
|
+
// add new filters
|
|
1634
|
+
nested.nested.query.bool.must.push( ...filters );
|
|
1635
|
+
}
|
|
1619
1636
|
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
script: {
|
|
1627
|
-
lang: 'painless',
|
|
1628
|
-
source: `
|
|
1629
|
-
if (doc['revicedPerc.keyword'].size() == 0) return null;
|
|
1630
|
-
String v = doc['revicedPerc.keyword'].value.replace('%','');
|
|
1631
|
-
try {
|
|
1632
|
-
return Double.parseDouble(v);
|
|
1633
|
-
} catch (Exception e) {
|
|
1634
|
-
return null;
|
|
1635
|
-
}
|
|
1636
|
-
`,
|
|
1637
|
-
},
|
|
1637
|
+
return {
|
|
1638
|
+
...q,
|
|
1639
|
+
size: 0,
|
|
1640
|
+
aggs: {
|
|
1641
|
+
avg_value: {
|
|
1642
|
+
avg: 'mappingInfo.reviced',
|
|
1638
1643
|
},
|
|
1639
1644
|
},
|
|
1640
|
-
}
|
|
1645
|
+
};
|
|
1641
1646
|
};
|
|
1642
|
-
};
|
|
1643
1647
|
|
|
1644
1648
|
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
const baseStoreQuery = JSON.parse( JSON.stringify( storeQuery ) );
|
|
1648
|
-
|
|
1649
|
-
// Total Tickets (all tickets with mappingInfo.type == tangoreview)
|
|
1650
|
-
let totalTickets = 0;
|
|
1649
|
+
// Get OpenSearch connection
|
|
1651
1650
|
|
|
1652
|
-
|
|
1651
|
+
const baseStoreQuery = JSON.parse( JSON.stringify( storeQuery ) );
|
|
1653
1652
|
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
totalTickets = totalResp?.body?.hits?.total?.value || 0;
|
|
1653
|
+
// Total Tickets (all tickets with mappingInfo.type == tangoreview)
|
|
1654
|
+
let totalTickets = 0;
|
|
1657
1655
|
|
|
1658
|
-
|
|
1659
|
-
let openTickets = 0;
|
|
1656
|
+
let allQuery = JSON.parse( JSON.stringify( baseStoreQuery ) );
|
|
1660
1657
|
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
openTickets = openResp?.body?.hits?.total?.value || 0;
|
|
1665
|
-
// logger.info( { msd: '..............2', openResp } );
|
|
1658
|
+
allQuery.size = 0;
|
|
1659
|
+
const totalResp = await getOpenSearchData( openSearch.footfallDirectory, allQuery );
|
|
1660
|
+
totalTickets = totalResp?.body?.hits?.total?.value || 0;
|
|
1666
1661
|
|
|
1662
|
+
// openTickets: mappingInfo.status: 'Open'
|
|
1663
|
+
let openTickets = 0;
|
|
1667
1664
|
|
|
1668
|
-
|
|
1669
|
-
|
|
1665
|
+
let otQ = buildStoreQueryWithStatus( baseStoreQuery, 'Open' );
|
|
1666
|
+
otQ.size = 0;
|
|
1667
|
+
const openResp = await getOpenSearchData( openSearch.footfallDirectory, otQ );
|
|
1668
|
+
openTickets = openResp?.body?.hits?.total?.value || 0;
|
|
1669
|
+
// logger.info( { msd: '..............2', openResp } );
|
|
1670
1670
|
|
|
1671
|
-
let ipQ = buildStoreQueryWithStatus( baseStoreQuery, 'In-Progress' );
|
|
1672
|
-
ipQ.size = 0;
|
|
1673
|
-
const ipResp = await getOpenSearchData( openSearch.footfallDirectory, ipQ );
|
|
1674
|
-
inprogress = ipResp?.body?.hits?.total?.value || 0;
|
|
1675
1671
|
|
|
1676
|
-
|
|
1677
|
-
|
|
1672
|
+
// inprogress: mappingInfo.status: 'in-Progress'
|
|
1673
|
+
let inprogress = 0;
|
|
1678
1674
|
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
// Average revisedPerc (for all tangoreview)
|
|
1675
|
+
let ipQ = buildStoreQueryWithStatus( baseStoreQuery, 'In-Progress' );
|
|
1676
|
+
ipQ.size = 0;
|
|
1677
|
+
const ipResp = await getOpenSearchData( openSearch.footfallDirectory, ipQ );
|
|
1678
|
+
inprogress = ipResp?.body?.hits?.total?.value || 0;
|
|
1684
1679
|
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
let todayDateString = new Date().toISOString().slice( 0, 10 );
|
|
1680
|
+
// closedTickets: mappingInfo.status: 'closed'
|
|
1681
|
+
let closedTickets = 0;
|
|
1688
1682
|
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
if ( nestedDue ) {
|
|
1694
|
-
// Remove any previous mappingInfo.dueDate term
|
|
1695
|
-
nestedDue.nested.query.bool.must = nestedDue.nested.query.bool.must.filter(
|
|
1696
|
-
( mustItem ) => !( mustItem.term && mustItem.term['mappingInfo.dueDate'] ),
|
|
1697
|
-
);
|
|
1698
|
-
// Add new dueDate filter
|
|
1699
|
-
nestedDue.nested.query.bool.must.push( {
|
|
1700
|
-
term: { 'mappingInfo.dueDate': todayDateString },
|
|
1701
|
-
} );
|
|
1702
|
-
}
|
|
1703
|
-
dueTodayQuery.size = 0;
|
|
1704
|
-
const dueTodayResp = await getOpenSearchData( openSearch.footfallDirectory, dueTodayQuery );
|
|
1705
|
-
dueToday = dueTodayResp?.body?.hits?.total?.value || 0;
|
|
1683
|
+
let clQ = buildStoreQueryWithStatus( baseStoreQuery, 'Closed' );
|
|
1684
|
+
clQ.size = 0;
|
|
1685
|
+
const clResp = await getOpenSearchData( openSearch.footfallDirectory, clQ );
|
|
1686
|
+
closedTickets = clResp?.body?.hits?.total?.value || 0;
|
|
1706
1687
|
|
|
1688
|
+
let dueToday = 0;
|
|
1689
|
+
let todayDateString = new Date().toISOString().slice( 0, 10 );
|
|
1690
|
+
|
|
1691
|
+
// Build a query for tickets with mappingInfo.dueDate == todayDateString
|
|
1692
|
+
let dueTodayQuery = JSON.parse( JSON.stringify( baseStoreQuery ) );
|
|
1693
|
+
// Locate nested mappingInfo query
|
|
1694
|
+
let nestedDue = dueTodayQuery.query.bool.must.find( ( m ) => m.nested );
|
|
1695
|
+
if ( nestedDue ) {
|
|
1696
|
+
// Remove any previous mappingInfo.dueDate term
|
|
1697
|
+
nestedDue.nested.query.bool.must = nestedDue.nested.query.bool.must.filter(
|
|
1698
|
+
( mustItem ) => !( mustItem.term && mustItem.term['mappingInfo.dueDate'] ),
|
|
1699
|
+
);
|
|
1700
|
+
// Add new dueDate filter
|
|
1701
|
+
nestedDue.nested.query.bool.must.push( {
|
|
1702
|
+
term: { 'mappingInfo.dueDate': todayDateString },
|
|
1703
|
+
} );
|
|
1704
|
+
}
|
|
1705
|
+
dueTodayQuery.size = 0;
|
|
1706
|
+
const dueTodayResp = await getOpenSearchData( openSearch.footfallDirectory, dueTodayQuery );
|
|
1707
|
+
dueToday = dueTodayResp?.body?.hits?.total?.value || 0;
|
|
1707
1708
|
|
|
1708
|
-
|
|
1709
|
-
|
|
1709
|
+
// filter expired Tickets
|
|
1710
|
+
let expiredTickets = 0;
|
|
1710
1711
|
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1712
|
+
let eQ = buildStoreQueryWithStatus( baseStoreQuery, 'Under Tango Review' );
|
|
1713
|
+
eQ.size = 0;
|
|
1714
|
+
const eResp = await getOpenSearchData( openSearch.footfallDirectory, eQ );
|
|
1715
|
+
expiredTickets = eResp?.body?.hits?.total?.value || 0;
|
|
1715
1716
|
|
|
1716
|
-
|
|
1717
|
-
let ticketAccuracyAbove = 0;
|
|
1717
|
+
// Calculate average ticket percentage: avg((reviced/footfallCount)*100) filtered by baseStoreQuery
|
|
1718
1718
|
|
|
1719
|
+
// Build aggregation query for ticket percentage
|
|
1720
|
+
let ticketPercentageAvg = 0;
|
|
1719
1721
|
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
{
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1722
|
+
let avgTicketPercentageQuery = JSON.parse( JSON.stringify( baseStoreQuery ) );
|
|
1723
|
+
avgTicketPercentageQuery.size = 0;
|
|
1724
|
+
avgTicketPercentageQuery.aggs = {
|
|
1725
|
+
avg_ticket_percentage: {
|
|
1726
|
+
avg: {
|
|
1727
|
+
script: {
|
|
1728
|
+
source: `
|
|
1729
|
+
if (doc.containsKey('reviced') && doc['reviced'].size()!=0 &&
|
|
1730
|
+
doc.containsKey('footfallCount') && doc['footfallCount'].size()!=0 && doc['footfallCount'].value != 0) {
|
|
1731
|
+
return (doc['reviced'].value / doc['footfallCount'].value) * 100;
|
|
1732
|
+
} else {
|
|
1733
|
+
return null;
|
|
1734
|
+
}
|
|
1735
|
+
`,
|
|
1736
|
+
lang: 'painless',
|
|
1737
|
+
},
|
|
1731
1738
|
},
|
|
1732
1739
|
},
|
|
1733
|
-
}
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
] );
|
|
1737
|
-
const aboveResp = await getOpenSearchData( openSearch.footfallDirectory, aboveQ );
|
|
1738
|
-
ticketAccuracyAbove = aboveResp?.body?.aggregations?.avg_value?.value?.toFixed( 2 ) || '0';
|
|
1740
|
+
};
|
|
1739
1741
|
|
|
1740
|
-
|
|
1741
|
-
let ticketAccuracyBelow = 0;
|
|
1742
|
+
const avgTicketPercentageResp = await getOpenSearchData( openSearch.footfallDirectory, avgTicketPercentageQuery );
|
|
1742
1743
|
|
|
1743
|
-
|
|
1744
|
-
{
|
|
1745
|
-
script: {
|
|
1746
|
-
script: {
|
|
1747
|
-
lang: 'painless',
|
|
1748
|
-
source: `
|
|
1749
|
-
doc['revicedPerc.keyword'].size()!=0 &&
|
|
1750
|
-
Integer.parseInt(doc['revicedPerc.keyword'].value.replace('%','')) < params.num
|
|
1751
|
-
`,
|
|
1752
|
-
params: { num: 85 },
|
|
1753
|
-
},
|
|
1754
|
-
},
|
|
1755
|
-
},
|
|
1744
|
+
ticketPercentageAvg = avgTicketPercentageResp?.body?.aggregations?.avg_ticket_percentage?.value?.toFixed( 2 ) || '0';
|
|
1756
1745
|
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1746
|
+
logger.info( { avgTicketPercentageResp } );
|
|
1747
|
+
// ticketAccuracyBelow: avg of revicedPerc < 85%
|
|
1748
|
+
let ticketAccuracy = 0;
|
|
1760
1749
|
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1750
|
+
let belowQ = buildAggStoreQuery( baseStoreQuery );
|
|
1751
|
+
logger.info( { belowQ } );
|
|
1752
|
+
const accuracyResp = await getOpenSearchData( openSearch.footfallDirectory, belowQ );
|
|
1753
|
+
ticketAccuracy = accuracyResp?.body?.aggregations?.avg_value?.value?.toFixed( 2 ) || '0';
|
|
1754
|
+
logger.info( { accuracyResp } );
|
|
1755
|
+
// Final result object
|
|
1756
|
+
result = {
|
|
1757
|
+
totalTickets,
|
|
1758
|
+
openTickets,
|
|
1759
|
+
inprogress,
|
|
1760
|
+
closedTickets,
|
|
1761
|
+
dueToday: dueToday,
|
|
1762
|
+
Expired: expiredTickets,
|
|
1763
|
+
avgTicket: ticketPercentageAvg+'%',
|
|
1764
|
+
avgAccuracy: ticketAccuracy+'%',
|
|
1765
|
+
};
|
|
1766
|
+
} else {
|
|
1767
|
+
const storeQuery = {
|
|
1768
|
+
size: 0,
|
|
1769
|
+
query: {
|
|
1770
|
+
bool: {
|
|
1771
|
+
must: [
|
|
1772
|
+
{
|
|
1773
|
+
'range': {
|
|
1774
|
+
'dateString': {
|
|
1775
|
+
'gte': inputData?.fromDate,
|
|
1776
|
+
'lte': inputData?.toDate,
|
|
1777
|
+
'format': 'yyyy-MM-dd',
|
|
1778
|
+
},
|
|
1784
1779
|
},
|
|
1785
1780
|
},
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1781
|
+
{
|
|
1782
|
+
terms: {
|
|
1783
|
+
'clientId.keyword': Array.isArray( inputData.clientId ) ?
|
|
1784
|
+
inputData.clientId :
|
|
1785
|
+
[ inputData.clientId ],
|
|
1786
|
+
},
|
|
1787
|
+
|
|
1788
|
+
},
|
|
1789
|
+
{
|
|
1790
|
+
nested: {
|
|
1791
|
+
path: 'mappingInfo',
|
|
1792
|
+
query: {
|
|
1793
|
+
bool: {
|
|
1794
|
+
must: [
|
|
1795
|
+
{
|
|
1796
|
+
term: {
|
|
1797
|
+
'mappingInfo.type': inputData.permissionType === 'review'? 'review':'approve',
|
|
1798
|
+
},
|
|
1796
1799
|
},
|
|
1797
|
-
|
|
1798
|
-
|
|
1800
|
+
],
|
|
1801
|
+
},
|
|
1799
1802
|
},
|
|
1800
1803
|
},
|
|
1801
1804
|
},
|
|
1802
|
-
},
|
|
1803
1805
|
|
|
1804
|
-
|
|
1806
|
+
],
|
|
1807
|
+
},
|
|
1805
1808
|
},
|
|
1806
|
-
}
|
|
1807
|
-
};
|
|
1809
|
+
};
|
|
1808
1810
|
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1811
|
+
// Helper function to clone deep and replace mappingInfo.status for openTickets/closed/etc
|
|
1812
|
+
function buildStoreQueryWithStatus( baseQuery, statusValue ) {
|
|
1813
|
+
let q = JSON.parse( JSON.stringify( baseQuery ) );
|
|
1814
|
+
// Remove any previous mappingInfo.status term
|
|
1815
|
+
let nested = q.query.bool.must.find( ( m ) => m.nested );
|
|
1816
|
+
if ( nested ) {
|
|
1817
|
+
// filter out all mappingInfo.status
|
|
1818
|
+
nested.nested.query.bool.must = nested?.nested?.query?.bool?.must.filter( ( mustItem ) => {
|
|
1819
|
+
return !( mustItem.term && mustItem.term['mappingInfo.status'] );
|
|
1820
|
+
} );
|
|
1821
|
+
// add desired status
|
|
1822
|
+
nested.nested.query.bool.must.push( {
|
|
1823
|
+
term: {
|
|
1824
|
+
'mappingInfo.status': statusValue,
|
|
1825
|
+
},
|
|
1826
|
+
} );
|
|
1827
|
+
}
|
|
1828
|
+
return q;
|
|
1825
1829
|
}
|
|
1826
|
-
return q;
|
|
1827
|
-
}
|
|
1828
1830
|
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
+
const buildAggStoreQuery = ( baseQuery, filters = [] ) => {
|
|
1832
|
+
const q = JSON.parse( JSON.stringify( baseQuery ) );
|
|
1831
1833
|
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
+
// locate nested section
|
|
1835
|
+
const nested = q.query.bool.must.find( ( m ) => m.nested );
|
|
1834
1836
|
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1837
|
+
if ( nested ) {
|
|
1838
|
+
// remove old status filters
|
|
1839
|
+
nested.nested.query.bool.must =
|
|
1840
|
+
nested.nested.query.bool.must.filter( ( m ) => !( m.term && m.term['mappingInfo.status'] ) );
|
|
1839
1841
|
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1842
|
+
// add new filters
|
|
1843
|
+
nested.nested.query.bool.must.push( ...filters );
|
|
1844
|
+
}
|
|
1843
1845
|
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
script: {
|
|
1851
|
-
lang: 'painless',
|
|
1852
|
-
source: `
|
|
1853
|
-
if (doc['revicedPerc.keyword'].size() == 0) return null;
|
|
1854
|
-
String v = doc['revicedPerc.keyword'].value.replace('%','');
|
|
1855
|
-
try {
|
|
1856
|
-
return Double.parseDouble(v);
|
|
1857
|
-
} catch (Exception e) {
|
|
1858
|
-
return null;
|
|
1859
|
-
}
|
|
1860
|
-
`,
|
|
1861
|
-
},
|
|
1846
|
+
return {
|
|
1847
|
+
...q,
|
|
1848
|
+
size: 0,
|
|
1849
|
+
aggs: {
|
|
1850
|
+
avg_value: {
|
|
1851
|
+
avg: 'mappingInfp.reviced',
|
|
1862
1852
|
},
|
|
1863
1853
|
},
|
|
1864
|
-
}
|
|
1854
|
+
};
|
|
1865
1855
|
};
|
|
1866
|
-
};
|
|
1867
|
-
|
|
1868
1856
|
|
|
1869
|
-
// Get OpenSearch connection
|
|
1870
1857
|
|
|
1871
|
-
|
|
1858
|
+
// Get OpenSearch connection
|
|
1872
1859
|
|
|
1873
|
-
|
|
1874
|
-
let totalTickets = 0;
|
|
1860
|
+
const baseStoreQuery = JSON.parse( JSON.stringify( storeQuery ) );
|
|
1875
1861
|
|
|
1876
|
-
|
|
1862
|
+
// Total Tickets (all tickets with mappingInfo.type == tangoreview)
|
|
1863
|
+
let totalTickets = 0;
|
|
1877
1864
|
|
|
1878
|
-
|
|
1879
|
-
const totalResp = await getOpenSearchData( openSearch.footfallDirectory, allQuery );
|
|
1880
|
-
totalTickets = totalResp?.body?.hits?.total?.value || 0;
|
|
1865
|
+
let allQuery = JSON.parse( JSON.stringify( baseStoreQuery ) );
|
|
1881
1866
|
|
|
1882
|
-
|
|
1883
|
-
|
|
1867
|
+
allQuery.size = 0;
|
|
1868
|
+
const totalResp = await getOpenSearchData( openSearch.footfallDirectory, allQuery );
|
|
1869
|
+
totalTickets = totalResp?.body?.hits?.total?.value || 0;
|
|
1884
1870
|
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
const openResp = await getOpenSearchData( openSearch.footfallDirectory, otQ );
|
|
1888
|
-
openTickets = openResp?.body?.hits?.total?.value || 0;
|
|
1889
|
-
// logger.info( { msd: '..............2', openResp } );
|
|
1871
|
+
// openTickets: mappingInfo.status: 'Open'
|
|
1872
|
+
let openTickets = 0;
|
|
1890
1873
|
|
|
1874
|
+
let otQ = buildStoreQueryWithStatus( baseStoreQuery, 'Open' );
|
|
1875
|
+
otQ.size = 0;
|
|
1876
|
+
const openResp = await getOpenSearchData( openSearch.footfallDirectory, otQ );
|
|
1877
|
+
openTickets = openResp?.body?.hits?.total?.value || 0;
|
|
1878
|
+
// logger.info( { msd: '..............2', openResp } );
|
|
1891
1879
|
|
|
1892
|
-
// inprogress: mappingInfo.status: 'in-Progress'
|
|
1893
|
-
let inprogress = 0;
|
|
1894
1880
|
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
const ipResp = await getOpenSearchData( openSearch.footfallDirectory, ipQ );
|
|
1898
|
-
inprogress = ipResp?.body?.hits?.total?.value || 0;
|
|
1881
|
+
// inprogress: mappingInfo.status: 'in-Progress'
|
|
1882
|
+
let inprogress = 0;
|
|
1899
1883
|
|
|
1900
|
-
|
|
1901
|
-
|
|
1884
|
+
let ipQ = buildStoreQueryWithStatus( baseStoreQuery, 'In-Progress' );
|
|
1885
|
+
ipQ.size = 0;
|
|
1886
|
+
const ipResp = await getOpenSearchData( openSearch.footfallDirectory, ipQ );
|
|
1887
|
+
inprogress = ipResp?.body?.hits?.total?.value || 0;
|
|
1902
1888
|
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
const clResp = await getOpenSearchData( openSearch.footfallDirectory, clQ );
|
|
1906
|
-
closedTickets = clResp?.body?.hits?.total?.value || 0;
|
|
1907
|
-
// dueToday: Tickets whose dueDate is today (format 'yyyy-MM-dd')
|
|
1908
|
-
let dueToday = 0;
|
|
1909
|
-
let todayDateString = new Date().toISOString().slice( 0, 10 );
|
|
1889
|
+
// closedTickets: mappingInfo.status: 'closed'
|
|
1890
|
+
let closedTickets = 0;
|
|
1910
1891
|
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1892
|
+
let clQ = buildStoreQueryWithStatus( baseStoreQuery, 'Closed' );
|
|
1893
|
+
clQ.size = 0;
|
|
1894
|
+
const clResp = await getOpenSearchData( openSearch.footfallDirectory, clQ );
|
|
1895
|
+
closedTickets = clResp?.body?.hits?.total?.value || 0;
|
|
1896
|
+
// dueToday: Tickets whose dueDate is today (format 'yyyy-MM-dd')
|
|
1897
|
+
let dueToday = 0;
|
|
1898
|
+
let todayDateString = new Date().toISOString().slice( 0, 10 );
|
|
1899
|
+
|
|
1900
|
+
// Build a query for tickets with mappingInfo.dueDate == todayDateString
|
|
1901
|
+
let dueTodayQuery = JSON.parse( JSON.stringify( baseStoreQuery ) );
|
|
1902
|
+
// Locate nested mappingInfo query
|
|
1903
|
+
let nestedDue = dueTodayQuery.query.bool.must.find( ( m ) => m.nested );
|
|
1904
|
+
if ( nestedDue ) {
|
|
1905
|
+
// Remove any previous mappingInfo.dueDate term
|
|
1906
|
+
nestedDue.nested.query.bool.must = nestedDue.nested.query.bool.must.filter(
|
|
1907
|
+
( mustItem ) => !( mustItem.term && mustItem.term['mappingInfo.dueDate'] ),
|
|
1908
|
+
);
|
|
1909
|
+
// Add new dueDate filter
|
|
1910
|
+
nestedDue.nested.query.bool.must.push( {
|
|
1911
|
+
term: { 'mappingInfo.dueDate': todayDateString },
|
|
1912
|
+
} );
|
|
1913
|
+
}
|
|
1914
|
+
dueTodayQuery.size = 0;
|
|
1915
|
+
const dueTodayResp = await getOpenSearchData( openSearch.footfallDirectory, dueTodayQuery );
|
|
1916
|
+
dueToday = dueTodayResp?.body?.hits?.total?.value || 0;
|
|
1928
1917
|
|
|
1929
1918
|
|
|
1930
|
-
|
|
1931
|
-
|
|
1919
|
+
// filter expired Tickets
|
|
1920
|
+
let expiredTickets = 0;
|
|
1932
1921
|
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1922
|
+
let eQ = buildStoreQueryWithStatus( baseStoreQuery, 'Under Tango Review' );
|
|
1923
|
+
eQ.size = 0;
|
|
1924
|
+
const eResp = await getOpenSearchData( openSearch.footfallDirectory, eQ );
|
|
1925
|
+
expiredTickets = eResp?.body?.hits?.total?.value || 0;
|
|
1937
1926
|
|
|
1938
|
-
|
|
1927
|
+
// filter under tango review
|
|
1939
1928
|
|
|
1940
|
-
|
|
1929
|
+
let undertangoTickets = 0;
|
|
1941
1930
|
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1931
|
+
let utrQ = buildStoreQueryWithStatus( baseStoreQuery, 'Under Tango Review' );
|
|
1932
|
+
utrQ.size = 0;
|
|
1933
|
+
const utrResp = await getOpenSearchData( openSearch.footfallDirectory, utrQ );
|
|
1934
|
+
undertangoTickets = utrResp?.body?.hits?.total?.value || 0;
|
|
1946
1935
|
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
{
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1936
|
+
let ticketPercentageAvg =0;
|
|
1937
|
+
let avgTicketPercentageQuery = JSON.parse( JSON.stringify( baseStoreQuery ) );
|
|
1938
|
+
avgTicketPercentageQuery.size = 0;
|
|
1939
|
+
avgTicketPercentageQuery.aggs = {
|
|
1940
|
+
avg_ticket_percentage: {
|
|
1941
|
+
avg: {
|
|
1942
|
+
script: {
|
|
1943
|
+
source: `
|
|
1944
|
+
if (doc.containsKey('reviced') && doc['reviced'].size()!=0 &&
|
|
1945
|
+
doc.containsKey('footfallCount') && doc['footfallCount'].size()!=0 && doc['footfallCount'].value != 0) {
|
|
1946
|
+
return (doc['reviced'].value / doc['footfallCount'].value) * 100;
|
|
1947
|
+
} else {
|
|
1948
|
+
return null;
|
|
1949
|
+
}
|
|
1950
|
+
`,
|
|
1951
|
+
lang: 'painless',
|
|
1952
|
+
},
|
|
1959
1953
|
},
|
|
1960
1954
|
},
|
|
1961
|
-
}
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
] );
|
|
1965
|
-
|
|
1966
|
-
const aboveResp = await getOpenSearchData( openSearch.footfallDirectory, aboveQ );
|
|
1967
|
-
ticketAccuracyAbove = aboveResp?.body?.aggregations?.avg_value?.value?.toFixed( 2 ) || '0';
|
|
1968
|
-
|
|
1969
|
-
// ticketAccuracyBelow: avg of revicedPerc < 85%
|
|
1970
|
-
let ticketAccuracyBelow = 0;
|
|
1955
|
+
};
|
|
1971
1956
|
|
|
1972
|
-
|
|
1973
|
-
{
|
|
1974
|
-
script: {
|
|
1975
|
-
script: {
|
|
1976
|
-
lang: 'painless',
|
|
1977
|
-
source: `
|
|
1978
|
-
doc['revicedPerc.keyword'].size()!=0 &&
|
|
1979
|
-
Integer.parseInt(doc['revicedPerc.keyword'].value.replace('%','')) < params.num
|
|
1980
|
-
`,
|
|
1981
|
-
params: { num: 85 },
|
|
1982
|
-
},
|
|
1983
|
-
},
|
|
1984
|
-
},
|
|
1957
|
+
const avgTicketPercentageResp = await getOpenSearchData( openSearch.footfallDirectory, avgTicketPercentageQuery );
|
|
1985
1958
|
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1959
|
+
ticketPercentageAvg = avgTicketPercentageResp?.body?.aggregations?.avg_ticket_percentage?.value?.toFixed( 2 ) || '0';
|
|
1960
|
+
logger.info( { avgTicketPercentageResp } );
|
|
1961
|
+
let ticketAccuracy = 0;
|
|
1989
1962
|
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
1963
|
+
let belowQ = buildAggStoreQuery( baseStoreQuery );
|
|
1964
|
+
logger.info( { belowQ } );
|
|
1965
|
+
const accuracyResp = await getOpenSearchData( openSearch.footfallDirectory, belowQ );
|
|
1966
|
+
ticketAccuracy = accuracyResp?.body?.aggregations?.avg_value?.value?.toFixed( 2 ) || '0';
|
|
1967
|
+
logger.info( { accuracyResp } );
|
|
1968
|
+
// Final result object
|
|
1969
|
+
result = {
|
|
1970
|
+
totalTickets,
|
|
1971
|
+
openTickets,
|
|
1972
|
+
inprogress,
|
|
1973
|
+
closedTickets,
|
|
1974
|
+
dueToday: dueToday,
|
|
1975
|
+
Expired: expiredTickets,
|
|
1976
|
+
underTangoReview: undertangoTickets,
|
|
1977
|
+
avgTicket: ticketPercentageAvg+'%',
|
|
1978
|
+
avgAccuracy: ticketAccuracy+'%',
|
|
1979
|
+
};
|
|
1980
|
+
}
|
|
2002
1981
|
}
|
|
2003
1982
|
}
|
|
2004
1983
|
|
|
@@ -4925,7 +4904,7 @@ export async function updateUserTicketStatus( req, res ) {
|
|
|
4925
4904
|
|
|
4926
4905
|
const updatePayload = {
|
|
4927
4906
|
doc: {
|
|
4928
|
-
status: 'In
|
|
4907
|
+
status: lastEntry?.type == 'review'? 'Reviewer In progress':lastEntry?.type == 'approve'? 'Approver In progress':ticketSource?.status,
|
|
4929
4908
|
mappingInfo: updatedMappingInfo,
|
|
4930
4909
|
updatedAt: currentTime,
|
|
4931
4910
|
},
|