tango-app-api-infra 3.9.5-vms.91 → 3.9.5-vms.95
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
|
@@ -151,6 +151,7 @@ export async function tangoReviewTicket( req, res ) {
|
|
|
151
151
|
query: {
|
|
152
152
|
bool: {
|
|
153
153
|
must: [
|
|
154
|
+
|
|
154
155
|
{
|
|
155
156
|
term: {
|
|
156
157
|
'storeId.keyword': inputData.storeId,
|
|
@@ -177,6 +178,11 @@ export async function tangoReviewTicket( req, res ) {
|
|
|
177
178
|
query: {
|
|
178
179
|
bool: {
|
|
179
180
|
must: [
|
|
181
|
+
{
|
|
182
|
+
term: {
|
|
183
|
+
'type.keyword': 'store',
|
|
184
|
+
},
|
|
185
|
+
},
|
|
180
186
|
{
|
|
181
187
|
term: {
|
|
182
188
|
'storeId.keyword': inputData.storeId,
|
|
@@ -505,6 +511,12 @@ export async function tangoReviewAccuracyClosedTicket( req, res ) {
|
|
|
505
511
|
query: {
|
|
506
512
|
bool: {
|
|
507
513
|
must: [
|
|
514
|
+
{
|
|
515
|
+
term: {
|
|
516
|
+
'type.keyword': 'store',
|
|
517
|
+
},
|
|
518
|
+
},
|
|
519
|
+
|
|
508
520
|
{
|
|
509
521
|
term: {
|
|
510
522
|
'storeId.keyword': inputData.storeId,
|
|
@@ -572,36 +584,17 @@ export async function tangoReviewAccuracyClosedTicket( req, res ) {
|
|
|
572
584
|
subComments: inputData?.subComments ||'',
|
|
573
585
|
} ) );
|
|
574
586
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
// return {
|
|
580
|
-
// ...item,
|
|
581
|
-
// status: 'Closed',
|
|
582
|
-
// };
|
|
583
|
-
// } );
|
|
584
|
-
// }
|
|
585
|
-
|
|
586
|
-
record.mappingInfo.push(
|
|
587
|
-
{
|
|
588
|
-
type: 'finalRevision',
|
|
589
|
-
mode: 'web',
|
|
590
|
-
revicedFootfall: temp?.[0]?.revicedFootfall,
|
|
591
|
-
revicedPerc: temp?.[0].revicedPerc,
|
|
592
|
-
count: temp?.[0].count,
|
|
593
|
-
revisedDetail: temp?.[0]?.revisedDetail,
|
|
594
|
-
status: 'Closed',
|
|
595
|
-
createdByEmail: req?.user?.email,
|
|
596
|
-
createdByUserName: req?.user?.userName,
|
|
597
|
-
createdByRole: req?.user?.role,
|
|
598
|
-
createdAt: new Date(),
|
|
587
|
+
const temp2 = record.mappingInfo
|
|
588
|
+
.filter( ( item ) => item.type === 'finalRevision' )
|
|
589
|
+
.map( ( item ) => ( {
|
|
590
|
+
...item,
|
|
599
591
|
comments: inputData?.comments || '',
|
|
600
|
-
subComments: inputData?.subComments ||
|
|
601
|
-
}
|
|
602
|
-
);
|
|
603
|
-
}
|
|
592
|
+
subComments: inputData?.subComments ||'',
|
|
593
|
+
} ) );
|
|
604
594
|
|
|
595
|
+
record.mappingInfo = [ ...ticketData?.[0]?._source?.mappingInfo.slice( 0, -2 ),
|
|
596
|
+
...temp, ...temp2 ];
|
|
597
|
+
}
|
|
605
598
|
|
|
606
599
|
// return;
|
|
607
600
|
|
|
@@ -610,84 +603,6 @@ export async function tangoReviewAccuracyClosedTicket( req, res ) {
|
|
|
610
603
|
const insertResult = await updateOpenSearchData( openSearch.footfallDirectory, id, { doc: record } );
|
|
611
604
|
|
|
612
605
|
if ( insertResult && ( insertResult.statusCode === 201 || insertResult.statusCode === 200 ) ) {
|
|
613
|
-
const query = {
|
|
614
|
-
storeId: inputData?.storeId,
|
|
615
|
-
isVideoStream: true,
|
|
616
|
-
};
|
|
617
|
-
const getStoreType = await countDocumnetsCamera( query );
|
|
618
|
-
const revopInfoQuery = {
|
|
619
|
-
size: 10000,
|
|
620
|
-
query: {
|
|
621
|
-
bool: {
|
|
622
|
-
must: [
|
|
623
|
-
{
|
|
624
|
-
term: {
|
|
625
|
-
'storeId.keyword': inputData.storeId,
|
|
626
|
-
},
|
|
627
|
-
},
|
|
628
|
-
{
|
|
629
|
-
term: {
|
|
630
|
-
'dateString': inputData.dateString,
|
|
631
|
-
},
|
|
632
|
-
},
|
|
633
|
-
{
|
|
634
|
-
term: {
|
|
635
|
-
'isParent': false,
|
|
636
|
-
},
|
|
637
|
-
},
|
|
638
|
-
{
|
|
639
|
-
term: {
|
|
640
|
-
isChecked: true,
|
|
641
|
-
},
|
|
642
|
-
},
|
|
643
|
-
],
|
|
644
|
-
},
|
|
645
|
-
},
|
|
646
|
-
_source: [ 'tempId' ],
|
|
647
|
-
|
|
648
|
-
};
|
|
649
|
-
const revopInfo = await getOpenSearchData( openSearch.revop, revopInfoQuery );
|
|
650
|
-
// Get all tempIds from revopInfo response
|
|
651
|
-
const tempIds = revopInfo?.body?.hits?.hits?.map( ( hit ) => hit?._source?.tempId ).filter( Boolean ) || [];
|
|
652
|
-
// Prepare management eyeZone query based on storeId and dateString
|
|
653
|
-
const managerEyeZoneQuery = {
|
|
654
|
-
size: 1,
|
|
655
|
-
query: {
|
|
656
|
-
bool: {
|
|
657
|
-
must: [
|
|
658
|
-
{
|
|
659
|
-
term: {
|
|
660
|
-
'storeId.keyword': inputData.storeId,
|
|
661
|
-
},
|
|
662
|
-
},
|
|
663
|
-
{
|
|
664
|
-
term: {
|
|
665
|
-
'storeDate': inputData.dateString,
|
|
666
|
-
},
|
|
667
|
-
},
|
|
668
|
-
],
|
|
669
|
-
},
|
|
670
|
-
},
|
|
671
|
-
_source: [ 'originalToTrackerCustomerMapping' ],
|
|
672
|
-
};
|
|
673
|
-
|
|
674
|
-
// Query the managerEyeZone index for the matching document
|
|
675
|
-
const managerEyeZoneResp = await getOpenSearchData( openSearch.managerEyeZone, managerEyeZoneQuery );
|
|
676
|
-
const managerEyeZoneHit = managerEyeZoneResp?.body?.hits?.hits?.[0]?._source;
|
|
677
|
-
// Extract originalToTrackerCustomerMapping if it exists
|
|
678
|
-
const mapping =
|
|
679
|
-
managerEyeZoneHit && managerEyeZoneHit.originalToTrackerCustomerMapping ?
|
|
680
|
-
managerEyeZoneHit.originalToTrackerCustomerMapping :
|
|
681
|
-
{};
|
|
682
|
-
|
|
683
|
-
// Find tempIds that exist in both revopInfo results and manager mapping
|
|
684
|
-
const temp = [];
|
|
685
|
-
tempIds.filter( ( tid ) => mapping[tid] !== null ? temp.push( { tempId: mapping[tid] } ) :'' );
|
|
686
|
-
const isSendMessge = await sendSqsMessage( inputData, temp, getStoreType, inputData.storeId );
|
|
687
|
-
if ( isSendMessge == true ) {
|
|
688
|
-
logger.info( '....1' );
|
|
689
|
-
}
|
|
690
|
-
|
|
691
606
|
return res.sendSuccess( 'Ticket closed successfully' );
|
|
692
607
|
} else {
|
|
693
608
|
return res.sendError( 'Internal Server Error', 500 );
|
|
@@ -1511,6 +1426,220 @@ export async function ticketSummary( req, res ) {
|
|
|
1511
1426
|
avgTicket: ticketPercentageAvg+'%',
|
|
1512
1427
|
avgAccuracy: ticketAccuracy+'%',
|
|
1513
1428
|
};
|
|
1429
|
+
} else if ( !ticketsFeature && ticketsApproveFeature ) {
|
|
1430
|
+
const storeQuery = {
|
|
1431
|
+
size: 0,
|
|
1432
|
+
query: {
|
|
1433
|
+
bool: {
|
|
1434
|
+
must: [
|
|
1435
|
+
{
|
|
1436
|
+
'range': {
|
|
1437
|
+
'dateString': {
|
|
1438
|
+
'gte': inputData?.fromDate,
|
|
1439
|
+
'lte': inputData?.toDate,
|
|
1440
|
+
'format': 'yyyy-MM-dd',
|
|
1441
|
+
},
|
|
1442
|
+
},
|
|
1443
|
+
},
|
|
1444
|
+
{
|
|
1445
|
+
terms: {
|
|
1446
|
+
'clientId.keyword': Array.isArray( inputData.clientId ) ?
|
|
1447
|
+
inputData.clientId :
|
|
1448
|
+
[ inputData.clientId ],
|
|
1449
|
+
},
|
|
1450
|
+
|
|
1451
|
+
},
|
|
1452
|
+
{
|
|
1453
|
+
nested: {
|
|
1454
|
+
path: 'mappingInfo',
|
|
1455
|
+
query: {
|
|
1456
|
+
bool: {
|
|
1457
|
+
must: [
|
|
1458
|
+
{
|
|
1459
|
+
term: {
|
|
1460
|
+
'mappingInfo.type': inputData.permissionType === 'review'? 'review':'approve',
|
|
1461
|
+
},
|
|
1462
|
+
},
|
|
1463
|
+
],
|
|
1464
|
+
},
|
|
1465
|
+
},
|
|
1466
|
+
},
|
|
1467
|
+
},
|
|
1468
|
+
|
|
1469
|
+
],
|
|
1470
|
+
},
|
|
1471
|
+
},
|
|
1472
|
+
};
|
|
1473
|
+
|
|
1474
|
+
// Helper function to clone deep and replace mappingInfo.status for openTickets/closed/etc
|
|
1475
|
+
function buildStoreQueryWithStatus( baseQuery, statusValue ) {
|
|
1476
|
+
let q = JSON.parse( JSON.stringify( baseQuery ) );
|
|
1477
|
+
// Remove any previous mappingInfo.status term
|
|
1478
|
+
let nested = q.query.bool.must.find( ( m ) => m.nested );
|
|
1479
|
+
if ( nested ) {
|
|
1480
|
+
// filter out all mappingInfo.status
|
|
1481
|
+
nested.nested.query.bool.must = nested?.nested?.query?.bool?.must.filter( ( mustItem ) => {
|
|
1482
|
+
return !( mustItem.term && mustItem.term['mappingInfo.status'] );
|
|
1483
|
+
} );
|
|
1484
|
+
// add desired status
|
|
1485
|
+
nested.nested.query.bool.must.push( {
|
|
1486
|
+
term: {
|
|
1487
|
+
'mappingInfo.status': statusValue,
|
|
1488
|
+
},
|
|
1489
|
+
} );
|
|
1490
|
+
}
|
|
1491
|
+
return q;
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
const buildAggStoreQuery = ( baseQuery, filters = [] ) => {
|
|
1495
|
+
const q = JSON.parse( JSON.stringify( baseQuery ) );
|
|
1496
|
+
|
|
1497
|
+
// locate nested section
|
|
1498
|
+
const nested = q.query.bool.must.find( ( m ) => m.nested );
|
|
1499
|
+
|
|
1500
|
+
if ( nested ) {
|
|
1501
|
+
// remove old status filters
|
|
1502
|
+
nested.nested.query.bool.must =
|
|
1503
|
+
nested.nested.query.bool.must.filter( ( m ) => !( m.term && m.term['mappingInfo.status'] ) );
|
|
1504
|
+
|
|
1505
|
+
// add new filters
|
|
1506
|
+
nested.nested.query.bool.must.push( ...filters );
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
return {
|
|
1510
|
+
...q,
|
|
1511
|
+
size: 0,
|
|
1512
|
+
aggs: {
|
|
1513
|
+
avg_value: {
|
|
1514
|
+
avg: 'mappingInfp.reviced',
|
|
1515
|
+
},
|
|
1516
|
+
},
|
|
1517
|
+
};
|
|
1518
|
+
};
|
|
1519
|
+
|
|
1520
|
+
|
|
1521
|
+
// Get OpenSearch connection
|
|
1522
|
+
|
|
1523
|
+
const baseStoreQuery = JSON.parse( JSON.stringify( storeQuery ) );
|
|
1524
|
+
|
|
1525
|
+
// Total Tickets (all tickets with mappingInfo.type == tangoreview)
|
|
1526
|
+
let totalTickets = 0;
|
|
1527
|
+
|
|
1528
|
+
let allQuery = JSON.parse( JSON.stringify( baseStoreQuery ) );
|
|
1529
|
+
|
|
1530
|
+
allQuery.size = 0;
|
|
1531
|
+
const totalResp = await getOpenSearchData( openSearch.footfallDirectory, allQuery );
|
|
1532
|
+
totalTickets = totalResp?.body?.hits?.total?.value || 0;
|
|
1533
|
+
|
|
1534
|
+
// openTickets: mappingInfo.status: 'Open'
|
|
1535
|
+
let openTickets = 0;
|
|
1536
|
+
|
|
1537
|
+
let otQ = buildStoreQueryWithStatus( baseStoreQuery, 'Open' );
|
|
1538
|
+
otQ.size = 0;
|
|
1539
|
+
const openResp = await getOpenSearchData( openSearch.footfallDirectory, otQ );
|
|
1540
|
+
openTickets = openResp?.body?.hits?.total?.value || 0;
|
|
1541
|
+
// logger.info( { msd: '..............2', openResp } );
|
|
1542
|
+
|
|
1543
|
+
|
|
1544
|
+
// inprogress: mappingInfo.status: 'in-Progress'
|
|
1545
|
+
let inprogress = 0;
|
|
1546
|
+
|
|
1547
|
+
let ipQ = buildStoreQueryWithStatus( baseStoreQuery, 'In-Progress' );
|
|
1548
|
+
ipQ.size = 0;
|
|
1549
|
+
const ipResp = await getOpenSearchData( openSearch.footfallDirectory, ipQ );
|
|
1550
|
+
inprogress = ipResp?.body?.hits?.total?.value || 0;
|
|
1551
|
+
|
|
1552
|
+
// closedTickets: mappingInfo.status: 'closed'
|
|
1553
|
+
let closedTickets = 0;
|
|
1554
|
+
|
|
1555
|
+
let clQ = buildStoreQueryWithStatus( baseStoreQuery, 'Closed' );
|
|
1556
|
+
clQ.size = 0;
|
|
1557
|
+
const clResp = await getOpenSearchData( openSearch.footfallDirectory, clQ );
|
|
1558
|
+
closedTickets = clResp?.body?.hits?.total?.value || 0;
|
|
1559
|
+
// dueToday: Tickets whose dueDate is today (format 'yyyy-MM-dd')
|
|
1560
|
+
let dueToday = 0;
|
|
1561
|
+
let todayDateString = new Date().toISOString().slice( 0, 10 );
|
|
1562
|
+
|
|
1563
|
+
// Build a query for tickets with mappingInfo.dueDate == todayDateString
|
|
1564
|
+
let dueTodayQuery = JSON.parse( JSON.stringify( baseStoreQuery ) );
|
|
1565
|
+
// Locate nested mappingInfo query
|
|
1566
|
+
let nestedDue = dueTodayQuery.query.bool.must.find( ( m ) => m.nested );
|
|
1567
|
+
if ( nestedDue ) {
|
|
1568
|
+
// Remove any previous mappingInfo.dueDate term
|
|
1569
|
+
nestedDue.nested.query.bool.must = nestedDue.nested.query.bool.must.filter(
|
|
1570
|
+
( mustItem ) => !( mustItem.term && mustItem.term['mappingInfo.dueDate'] ),
|
|
1571
|
+
);
|
|
1572
|
+
// Add new dueDate filter
|
|
1573
|
+
nestedDue.nested.query.bool.must.push( {
|
|
1574
|
+
term: { 'mappingInfo.dueDate': todayDateString },
|
|
1575
|
+
} );
|
|
1576
|
+
}
|
|
1577
|
+
dueTodayQuery.size = 0;
|
|
1578
|
+
const dueTodayResp = await getOpenSearchData( openSearch.footfallDirectory, dueTodayQuery );
|
|
1579
|
+
dueToday = dueTodayResp?.body?.hits?.total?.value || 0;
|
|
1580
|
+
|
|
1581
|
+
|
|
1582
|
+
// filter expired Tickets
|
|
1583
|
+
let expiredTickets = 0;
|
|
1584
|
+
|
|
1585
|
+
let eQ = buildStoreQueryWithStatus( baseStoreQuery, 'Under Tango Review' );
|
|
1586
|
+
eQ.size = 0;
|
|
1587
|
+
const eResp = await getOpenSearchData( openSearch.footfallDirectory, eQ );
|
|
1588
|
+
expiredTickets = eResp?.body?.hits?.total?.value || 0;
|
|
1589
|
+
|
|
1590
|
+
// filter under tango review
|
|
1591
|
+
|
|
1592
|
+
let undertangoTickets = 0;
|
|
1593
|
+
|
|
1594
|
+
let utrQ = buildStoreQueryWithStatus( baseStoreQuery, 'Under Tango Review' );
|
|
1595
|
+
utrQ.size = 0;
|
|
1596
|
+
const utrResp = await getOpenSearchData( openSearch.footfallDirectory, utrQ );
|
|
1597
|
+
undertangoTickets = utrResp?.body?.hits?.total?.value || 0;
|
|
1598
|
+
|
|
1599
|
+
let ticketPercentageAvg =0;
|
|
1600
|
+
let avgTicketPercentageQuery = JSON.parse( JSON.stringify( baseStoreQuery ) );
|
|
1601
|
+
avgTicketPercentageQuery.size = 0;
|
|
1602
|
+
avgTicketPercentageQuery.aggs = {
|
|
1603
|
+
avg_ticket_percentage: {
|
|
1604
|
+
avg: {
|
|
1605
|
+
script: {
|
|
1606
|
+
source: `
|
|
1607
|
+
if (doc.containsKey('reviced') && doc['reviced'].size()!=0 &&
|
|
1608
|
+
doc.containsKey('footfallCount') && doc['footfallCount'].size()!=0 && doc['footfallCount'].value != 0) {
|
|
1609
|
+
return (doc['reviced'].value / doc['footfallCount'].value) * 100;
|
|
1610
|
+
} else {
|
|
1611
|
+
return null;
|
|
1612
|
+
}
|
|
1613
|
+
`,
|
|
1614
|
+
lang: 'painless',
|
|
1615
|
+
},
|
|
1616
|
+
},
|
|
1617
|
+
},
|
|
1618
|
+
};
|
|
1619
|
+
|
|
1620
|
+
const avgTicketPercentageResp = await getOpenSearchData( openSearch.footfallDirectory, avgTicketPercentageQuery );
|
|
1621
|
+
|
|
1622
|
+
ticketPercentageAvg = avgTicketPercentageResp?.body?.aggregations?.avg_ticket_percentage?.value?.toFixed( 2 ) || '0';
|
|
1623
|
+
logger.info( { avgTicketPercentageResp } );
|
|
1624
|
+
let ticketAccuracy = 0;
|
|
1625
|
+
|
|
1626
|
+
let belowQ = buildAggStoreQuery( baseStoreQuery );
|
|
1627
|
+
logger.info( { belowQ } );
|
|
1628
|
+
const accuracyResp = await getOpenSearchData( openSearch.footfallDirectory, belowQ );
|
|
1629
|
+
ticketAccuracy = accuracyResp?.body?.aggregations?.avg_value?.value?.toFixed( 2 ) || '0';
|
|
1630
|
+
logger.info( { accuracyResp } );
|
|
1631
|
+
// Final result object
|
|
1632
|
+
result = {
|
|
1633
|
+
totalTickets,
|
|
1634
|
+
openTickets,
|
|
1635
|
+
inprogress,
|
|
1636
|
+
closedTickets,
|
|
1637
|
+
dueToday: dueToday,
|
|
1638
|
+
Expired: expiredTickets,
|
|
1639
|
+
underTangoReview: undertangoTickets,
|
|
1640
|
+
avgTicket: ticketPercentageAvg+'%',
|
|
1641
|
+
avgAccuracy: ticketAccuracy+'%',
|
|
1642
|
+
};
|
|
1514
1643
|
} else if ( ticketsFeature && ticketsApproveFeature ) {
|
|
1515
1644
|
if ( inputData?.permissionType === 'review' ) {
|
|
1516
1645
|
const storeQuery = {
|
|
@@ -2212,6 +2341,20 @@ export async function ticketList( req, res ) {
|
|
|
2212
2341
|
},
|
|
2213
2342
|
};
|
|
2214
2343
|
|
|
2344
|
+
if ( req?.user?.userType !== 'tango', req?.user?.role !== 'superadmin' ) {
|
|
2345
|
+
if ( req?.body?.assignedStores?.length > 0 ) {
|
|
2346
|
+
searchQuery.query.bool.must.push( {
|
|
2347
|
+
terms: {
|
|
2348
|
+
'storeId.keyword': Array.isArray( req?.body?.assignedStores ) ?
|
|
2349
|
+
req?.body?.assignedStores :
|
|
2350
|
+
[ req?.body?.assignedStores ],
|
|
2351
|
+
},
|
|
2352
|
+
} );
|
|
2353
|
+
} else {
|
|
2354
|
+
return res.sendError( 'no data', 204 );
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2215
2358
|
if ( inputData.sortBy ) {
|
|
2216
2359
|
let sortOrder = inputData.sortOrder === 1 ? 'asc' : 'desc';
|
|
2217
2360
|
|
|
@@ -2423,6 +2566,28 @@ export async function ticketList( req, res ) {
|
|
|
2423
2566
|
},
|
|
2424
2567
|
},
|
|
2425
2568
|
} );
|
|
2569
|
+
} else if ( !ticketsFeature && ticketsApproveFeature ) {
|
|
2570
|
+
searchQuery.query.bool.must.push( {
|
|
2571
|
+
nested: {
|
|
2572
|
+
path: 'mappingInfo',
|
|
2573
|
+
query: {
|
|
2574
|
+
bool: {
|
|
2575
|
+
must: [
|
|
2576
|
+
{
|
|
2577
|
+
term: {
|
|
2578
|
+
'mappingInfo.type': 'approve',
|
|
2579
|
+
},
|
|
2580
|
+
},
|
|
2581
|
+
{
|
|
2582
|
+
terms: {
|
|
2583
|
+
'mappingInfo.status': inputData?.filterByStatus,
|
|
2584
|
+
},
|
|
2585
|
+
},
|
|
2586
|
+
],
|
|
2587
|
+
},
|
|
2588
|
+
},
|
|
2589
|
+
},
|
|
2590
|
+
} );
|
|
2426
2591
|
} else if ( ticketsFeature && ticketsApproveFeature ) {
|
|
2427
2592
|
switch ( inputData.permisisionType ) {
|
|
2428
2593
|
case 'review':
|
|
@@ -2992,9 +3157,18 @@ export async function ticketList( req, res ) {
|
|
|
2992
3157
|
'Ticket ID': item?.ticketId,
|
|
2993
3158
|
'store Name': item?.storeName,
|
|
2994
3159
|
'store ID': item?.storeId,
|
|
2995
|
-
'Ticket Raised': item?.mappingInfo?.find( ( f ) => f.type === 'tangoreview' )?.createdAt,
|
|
2996
|
-
'Issue Date': item?.dateString,
|
|
2997
|
-
'Due Date':
|
|
3160
|
+
'Ticket Raised': item?.mappingInfo?.find( ( f ) => f.type === 'tangoreview' )?.createdAt? dayjs( item?.mappingInfo?.find( ( f ) => f.type === 'tangoreview' )?.createdAt ).format( 'DD MMM, YYYY' ) : '',
|
|
3161
|
+
'Issue Date': item?.dateString ? dayjs( item.dateString ).format( 'DD MMM, YYYY' ) : '',
|
|
3162
|
+
'Due Date': ( () => {
|
|
3163
|
+
const dueDate = item?.mappingInfo?.find( ( f ) => f.type === 'tangoreview' )?.dueDate;
|
|
3164
|
+
if ( dueDate ) {
|
|
3165
|
+
if ( dayjs( dueDate ).isSame( dayjs(), 'day' ) ) {
|
|
3166
|
+
return 'Due Today';
|
|
3167
|
+
}
|
|
3168
|
+
return dayjs( dueDate ).format( 'DD MMM, YYYY' );
|
|
3169
|
+
}
|
|
3170
|
+
return '';
|
|
3171
|
+
} )(),
|
|
2998
3172
|
'Actual FF': item?.footfallCount,
|
|
2999
3173
|
'Store (%)': item?.mappingInfo?.find( ( f ) => f.type === 'tagging' )?.revicedPerc || '--',
|
|
3000
3174
|
'Reviewer (%)': item?.mappingInfo?.find( ( f ) => f.type === 'review' )?.revicedPerc || '--',
|
|
@@ -3011,20 +3185,29 @@ export async function ticketList( req, res ) {
|
|
|
3011
3185
|
for ( let item of ticketListData ) {
|
|
3012
3186
|
temp.push( {
|
|
3013
3187
|
|
|
3014
|
-
ticketId: item?.ticketId,
|
|
3015
|
-
storeId: item?.storeId,
|
|
3016
|
-
storeName: item?.storeName,
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3188
|
+
'ticketId': item?.ticketId,
|
|
3189
|
+
'storeId': item?.storeId,
|
|
3190
|
+
'storeName': item?.storeName,
|
|
3191
|
+
'Ticket Raised': item?.mappingInfo?.find( ( f ) => f.type === 'tangoreview' )?.createdAt? dayjs( item?.mappingInfo?.find( ( f ) => f.type === 'tangoreview' )?.createdAt ).format( 'DD MMM, YYYY' ) : '',
|
|
3192
|
+
'Issue Date': item?.dateString ? dayjs( item.dateString ).format( 'DD MMM, YYYY' ) : '',
|
|
3193
|
+
'Due Date': ( () => {
|
|
3194
|
+
const dueDate = item?.mappingInfo?.find( ( f ) => f.type === 'tangoreview' )?.dueDate;
|
|
3195
|
+
if ( dueDate ) {
|
|
3196
|
+
if ( dayjs( dueDate ).isSame( dayjs(), 'day' ) ) {
|
|
3197
|
+
return 'Due Today';
|
|
3198
|
+
}
|
|
3199
|
+
return dayjs( dueDate ).format( 'DD MMM, YYYY' );
|
|
3200
|
+
}
|
|
3201
|
+
return '';
|
|
3202
|
+
} )(),
|
|
3203
|
+
'footfall': item?.footfallCount,
|
|
3204
|
+
'storeRevisedAccuracy': item?.mappingInfo?.find( ( f ) => f.type === 'tagging' )?.revicedPerc || '--',
|
|
3205
|
+
'reviewerRevisedAccuracy': item?.mappingInfo?.find( ( f ) => f.type === 'review' )?.revicedPerc || '--',
|
|
3206
|
+
'approverRevisedAccuracy': item?.mappingInfo?.find( ( f ) => f.type === 'approve' )?.revicedPerc || '--',
|
|
3207
|
+
'tangoRevisedAccuracy': item?.mappingInfo?.find( ( f ) => f.type === 'tangoreview' )?.revicedPerc || '--',
|
|
3208
|
+
'status': item?.mappingInfo?.find( ( f ) => f.type === 'tangoreview' )?.status || '--',
|
|
3209
|
+
'comments': item?.mappingInfo?.find( ( f ) => f.type === 'finalRevision' )?.comments || '--',
|
|
3210
|
+
'subComments': item?.mappingInfo?.find( ( f ) => f.type === 'finalRevision' )?.subComments || '--',
|
|
3028
3211
|
|
|
3029
3212
|
} );
|
|
3030
3213
|
}
|
|
@@ -3039,18 +3222,38 @@ export async function ticketList( req, res ) {
|
|
|
3039
3222
|
'Ticket ID': item?.ticketId,
|
|
3040
3223
|
'Store Name': item?.storeName,
|
|
3041
3224
|
'Store ID': item?.storeId,
|
|
3042
|
-
'Ticket Raised': item?.mappingInfo?.find( ( f ) => f.type === 'tagging' )?.createdAt,
|
|
3043
|
-
'Issue Date': item?.dateString,
|
|
3225
|
+
'Ticket Raised': item?.mappingInfo?.find( ( f ) => f.type === 'tagging' )?.createdAt? dayjs( item?.mappingInfo?.find( ( f ) => f.type === 'tagging' )?.createdAt ).format( 'DD MMM, YYYY' ) : '',
|
|
3226
|
+
'Issue Date': item?.dateString ? dayjs( item.dateString ).format( 'DD MMM, YYYY' ) : '',
|
|
3044
3227
|
'Ticket Type': item?.type,
|
|
3045
3228
|
'Actual FF': item?.footfallCount,
|
|
3046
|
-
// Use the dueDate from the last mappingInfo item whose type is NOT '
|
|
3229
|
+
// Use the dueDate from the last mappingInfo item whose type is NOT 'finalRevison'
|
|
3230
|
+
|
|
3047
3231
|
'Due Date': ( () => {
|
|
3048
3232
|
if ( Array.isArray( item?.mappingInfo ) ) {
|
|
3049
|
-
const filtered = item.mappingInfo.filter( ( f ) => f.dueDate && f.type !== '
|
|
3233
|
+
const filtered = item.mappingInfo.filter( ( f ) => f.dueDate && f.type !== 'finalRevison' );
|
|
3050
3234
|
return filtered.length > 0 ? filtered[filtered.length - 1].dueDate : '';
|
|
3051
3235
|
}
|
|
3052
3236
|
return '';
|
|
3053
3237
|
} )(),
|
|
3238
|
+
'Due Date (Formatted)': ( () => {
|
|
3239
|
+
if ( Array.isArray( item?.mappingInfo ) ) {
|
|
3240
|
+
// Find last mappingInfo whose type is NOT 'finalRevison'
|
|
3241
|
+
const filtered = item.mappingInfo.filter(
|
|
3242
|
+
( f ) => f.dueDate && f.type !== 'finalRevison',
|
|
3243
|
+
);
|
|
3244
|
+
if ( filtered.length > 0 ) {
|
|
3245
|
+
const lastDueDate = filtered[filtered.length - 1].dueDate;
|
|
3246
|
+
if ( lastDueDate ) {
|
|
3247
|
+
if ( dayjs( lastDueDate ).isSame( dayjs(), 'day' ) ) {
|
|
3248
|
+
return 'Due Today';
|
|
3249
|
+
}
|
|
3250
|
+
return dayjs( lastDueDate ).format( 'DD MMM, YYYY' );
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3253
|
+
}
|
|
3254
|
+
return '';
|
|
3255
|
+
} )(),
|
|
3256
|
+
|
|
3054
3257
|
'Store (%)': item?.mappingInfo?.find( ( f ) => f.type === 'tagging' )?.revicedPerc || '--',
|
|
3055
3258
|
'Reviewer (%)': item?.mappingInfo?.find( ( f ) => f.type === 'review' )?.revicedPerc || '--',
|
|
3056
3259
|
'Approver (%)': item?.mappingInfo?.find( ( f ) => f.type === 'approve' )?.revicedPerc || '--',
|
|
@@ -3063,7 +3266,6 @@ export async function ticketList( req, res ) {
|
|
|
3063
3266
|
return await download( exportData, res );
|
|
3064
3267
|
} else {
|
|
3065
3268
|
for ( let item of ticketListData ) {
|
|
3066
|
-
console.log( '🚀 ~ ticketList ~ item:', item );
|
|
3067
3269
|
temp.push( {
|
|
3068
3270
|
|
|
3069
3271
|
ticketId: item?.ticketId,
|
|
@@ -3101,9 +3303,18 @@ export async function ticketList( req, res ) {
|
|
|
3101
3303
|
'Ticket ID': item?.ticketId,
|
|
3102
3304
|
'Store Name': item?.storeName,
|
|
3103
3305
|
'Store ID': item?.storeId,
|
|
3104
|
-
'Ticket Raised': item?.mappingInfo?.find( ( f ) => f.type === 'approve' )?.createdAt,
|
|
3105
|
-
'Issue Date': item?.dateString,
|
|
3106
|
-
'Due Date':
|
|
3306
|
+
'Ticket Raised': item?.mappingInfo?.find( ( f ) => f.type === 'approve' )?.createdAt? dayjs( item?.mappingInfo?.find( ( f ) => f.type === 'approve' )?.createdAt ).format( 'DD MMM, YYYY' ) : '',
|
|
3307
|
+
'Issue Date': item?.dateString ? dayjs( item.dateString ).format( 'DD MMM, YYYY' ) : '',
|
|
3308
|
+
'Due Date': ( () => {
|
|
3309
|
+
const dueDate = item?.mappingInfo?.find( ( f ) => f.type === 'approve' )?.dueDate;
|
|
3310
|
+
if ( dueDate ) {
|
|
3311
|
+
if ( dayjs( dueDate ).isSame( dayjs(), 'day' ) ) {
|
|
3312
|
+
return 'Due Today';
|
|
3313
|
+
}
|
|
3314
|
+
return dayjs( dueDate ).format( 'DD MMM, YYYY' );
|
|
3315
|
+
}
|
|
3316
|
+
return '';
|
|
3317
|
+
} )(),
|
|
3107
3318
|
'Actual FF': item?.footfallCount,
|
|
3108
3319
|
'Store (%)': item?.mappingInfo?.find( ( f ) => f.type === 'tagging' )?.revicedPerc || '--',
|
|
3109
3320
|
'Reviewer (%)': item?.mappingInfo?.find( ( f ) => f.type === 'review' )?.revicedPerc || '--',
|
|
@@ -3148,10 +3359,19 @@ export async function ticketList( req, res ) {
|
|
|
3148
3359
|
'Ticket ID': item?.ticketId,
|
|
3149
3360
|
'Store Name': item?.storeName,
|
|
3150
3361
|
'Store ID': item?.storeId,
|
|
3151
|
-
'Ticket Raised': item?.mappingInfo?.find( ( f ) => f.type === 'review' )?.createdAt,
|
|
3152
|
-
'Issue Date': item?.dateString,
|
|
3362
|
+
'Ticket Raised': item?.mappingInfo?.find( ( f ) => f.type === 'review' )?.createdAt? dayjs( item?.mappingInfo?.find( ( f ) => f.type === 'review' )?.createdAt ).format( 'DD MMM, YYYY' ) : '',
|
|
3363
|
+
'Issue Date': item?.dateString ? dayjs( item.dateString ).format( 'DD MMM, YYYY' ) : '',
|
|
3364
|
+
'Due Date': ( () => {
|
|
3365
|
+
const dueDate = item?.mappingInfo?.find( ( f ) => f.type === 'review' )?.dueDate;
|
|
3366
|
+
if ( dueDate ) {
|
|
3367
|
+
if ( dayjs( dueDate ).isSame( dayjs(), 'day' ) ) {
|
|
3368
|
+
return 'Due Today';
|
|
3369
|
+
}
|
|
3370
|
+
return dayjs( dueDate ).format( 'DD MMM, YYYY' );
|
|
3371
|
+
}
|
|
3372
|
+
return '';
|
|
3373
|
+
} )(),
|
|
3153
3374
|
'Actual FF': item?.footfallCount,
|
|
3154
|
-
'Due Date': item?.mappingInfo?.find( ( f ) => f.type === 'review' )?.dueDate,
|
|
3155
3375
|
'Store (%)': item?.mappingInfo?.find( ( f ) => f.type === 'tagging' )?.revicedPerc || '--',
|
|
3156
3376
|
'Reviewer (%)': item?.mappingInfo?.find( ( f ) => f.type === 'review' )?.revicedPerc || '--',
|
|
3157
3377
|
'Status': item?.mappingInfo?.find( ( f ) => f.type === 'review' )?.status || '--',
|
|
@@ -3191,10 +3411,20 @@ export async function ticketList( req, res ) {
|
|
|
3191
3411
|
'Ticket ID': item?.ticketId,
|
|
3192
3412
|
'Store ID': item?.storeId,
|
|
3193
3413
|
'Store Name': item?.storeName,
|
|
3194
|
-
'Ticket Raised': item?.mappingInfo?.find( ( f ) => f.type === 'review' )?.createdAt,
|
|
3195
|
-
'Issue Date': item?.dateString,
|
|
3414
|
+
'Ticket Raised': item?.mappingInfo?.find( ( f ) => f.type === 'review' )?.createdAt? dayjs( item?.mappingInfo?.find( ( f ) => f.type === 'review' )?.createdAt ).format( 'DD MMM, YYYY' ) : '',
|
|
3415
|
+
'Issue Date': item?.dateString ? dayjs( item.dateString ).format( 'DD MMM, YYYY' ) : '',
|
|
3416
|
+
'Due Date': ( () => {
|
|
3417
|
+
const dueDate = item?.mappingInfo?.find( ( f ) => f.type === 'review' )?.dueDate;
|
|
3418
|
+
if ( dueDate ) {
|
|
3419
|
+
if ( dayjs( dueDate ).isSame( dayjs(), 'day' ) ) {
|
|
3420
|
+
return 'Due Today';
|
|
3421
|
+
}
|
|
3422
|
+
return dayjs( dueDate ).format( 'DD MMM, YYYY' );
|
|
3423
|
+
}
|
|
3424
|
+
return '';
|
|
3425
|
+
} )(),
|
|
3196
3426
|
'Actual FF': item?.footfallCount,
|
|
3197
|
-
|
|
3427
|
+
|
|
3198
3428
|
'Store (%)': item?.mappingInfo?.find( ( f ) => f.type === 'tagging' )?.revicedPerc || '--',
|
|
3199
3429
|
'Reviewer (%)': item?.mappingInfo?.find( ( f ) => f.type === 'review' )?.revicedPerc || '--',
|
|
3200
3430
|
'Status': item?.mappingInfo?.find( ( f ) => f.type === 'review' )?.status || '--',
|
|
@@ -3232,9 +3462,18 @@ export async function ticketList( req, res ) {
|
|
|
3232
3462
|
'Ticket ID': item?.ticketId,
|
|
3233
3463
|
'Store Name': item?.storeName,
|
|
3234
3464
|
'Store ID': item?.storeId,
|
|
3235
|
-
'Ticket Raised': item?.mappingInfo?.find( ( f ) => f.type === 'approve' )?.createdAt,
|
|
3236
|
-
'Issue Date': item?.dateString,
|
|
3237
|
-
'Due Date':
|
|
3465
|
+
'Ticket Raised': item?.mappingInfo?.find( ( f ) => f.type === 'approve' )?.createdAt? dayjs( item?.mappingInfo?.find( ( f ) => f.type === 'approve' )?.createdAt ).format( 'DD MMM, YYYY' ) : '',
|
|
3466
|
+
'Issue Date': item?.dateString ? dayjs( item.dateString ).format( 'DD MMM, YYYY' ) : '',
|
|
3467
|
+
'Due Date': ( () => {
|
|
3468
|
+
const dueDate = item?.mappingInfo?.find( ( f ) => f.type === 'approve' )?.dueDate;
|
|
3469
|
+
if ( dueDate ) {
|
|
3470
|
+
if ( dayjs( dueDate ).isSame( dayjs(), 'day' ) ) {
|
|
3471
|
+
return 'Due Today';
|
|
3472
|
+
}
|
|
3473
|
+
return dayjs( dueDate ).format( 'DD MMM, YYYY' );
|
|
3474
|
+
}
|
|
3475
|
+
return '';
|
|
3476
|
+
} )(),
|
|
3238
3477
|
'Actual FF': item?.footfallCount,
|
|
3239
3478
|
'Store (%)': item?.mappingInfo?.find( ( f ) => f.type === 'tagging' )?.revicedPerc || '--',
|
|
3240
3479
|
'Reviewer (%)': item?.mappingInfo?.find( ( f ) => f.type === 'review' )?.revicedPerc || '--',
|
|
@@ -3331,88 +3570,9 @@ export async function getTickets( req, res ) {
|
|
|
3331
3570
|
if ( !response || response.length == 0 ) {
|
|
3332
3571
|
return res.sendError( `No Pending items in the selected dates for the store`, 400 );
|
|
3333
3572
|
}
|
|
3334
|
-
let temp = [];
|
|
3335
|
-
if ( inputData?.action ) {
|
|
3336
|
-
response.map( ( hit ) => {
|
|
3337
|
-
const defaultData = {
|
|
3338
|
-
storeId: hit._source.storeId,
|
|
3339
|
-
createdByEmail: hit?._source?.createdByEmail,
|
|
3340
|
-
dateString: hit?._source?.dateString,
|
|
3341
|
-
ticketName: hit?._source?.ticketName,
|
|
3342
|
-
status: hit?._source?.status?.revicedFootfall,
|
|
3343
|
-
revicedPerc: hit?._source?.revicedPerc,
|
|
3344
|
-
revicedFootfall: hit?._source?.revicedFootfall,
|
|
3345
|
-
mappingInfo: hit?._source?.mappingInfo,
|
|
3346
|
-
employeeStatus: hit?._source?.employeeStatus,
|
|
3347
|
-
houseKeepingStatus: hit?._source?.houseKeepingStatus,
|
|
3348
|
-
duplicateStatus: hit?._source?.duplicateStatus,
|
|
3349
|
-
junkStatus: hit?._source?.junkStatus,
|
|
3350
|
-
storeName: hit?._source?.storeName,
|
|
3351
|
-
ticketId: hit?._source?.ticketId,
|
|
3352
|
-
footfallCount: hit?._source?.footfallCount,
|
|
3353
|
-
comments: hit?._source?.comments,
|
|
3354
|
-
email: hit?._source?.comments,
|
|
3355
|
-
userName: hit?._source?.userName,
|
|
3356
|
-
role: hit?._source?.role,
|
|
3357
|
-
createdAt: hit?._source?.createdAt,
|
|
3358
|
-
updatedAt: hit?._source?.updatedAt,
|
|
3359
|
-
tempId: hit?._source?.tempId,
|
|
3360
|
-
houseKeepingCount: hit?._source?.houseKeepingCount,
|
|
3361
|
-
employeeCount: hit?._source?.employeeCount,
|
|
3362
|
-
duplicateCount: hit?._source?.duplicateCount,
|
|
3363
|
-
junkCount: hit?._source?.junkCount,
|
|
3364
|
-
houseKeepingACCount: hit?._source?.houseKeepingACCount,
|
|
3365
|
-
employeeACCount: hit?._source?.employeeACCount,
|
|
3366
|
-
duplicateACCount: hit?._source?.duplicateACCount,
|
|
3367
|
-
junkACCount: hit?._source?.junkACCount,
|
|
3368
|
-
approverUserName: hit?._source?.approverUserName,
|
|
3369
|
-
approverEmail: hit?._source?.approverEmail,
|
|
3370
|
-
approverRole: hit?._source?.approverRole,
|
|
3371
|
-
type: hit?._source?.type,
|
|
3372
|
-
};
|
|
3373
|
-
let result;
|
|
3374
3573
|
|
|
3375
3574
|
|
|
3376
|
-
|
|
3377
|
-
// Add only matched data array
|
|
3378
|
-
if ( matched.includes( 'matched_employee' ) && ( !inputData.revopsType || inputData.revopsType == 'employee' ) ) {
|
|
3379
|
-
result = defaultData;
|
|
3380
|
-
result.employee = hit?._source?.employee;
|
|
3381
|
-
// result.type = 'employee';
|
|
3382
|
-
result.matched = matched;
|
|
3383
|
-
}
|
|
3384
|
-
if ( matched.includes( 'matched_housekeeping' ) && ( !inputData.revopsType || inputData.revopsType == 'houseKeeping' ) ) {
|
|
3385
|
-
result = defaultData;
|
|
3386
|
-
result.houseKeeping = hit?._source?.houseKeeping;
|
|
3387
|
-
result.matched = matched;
|
|
3388
|
-
}
|
|
3389
|
-
if ( matched.includes( 'matched_duplicate' ) && ( !inputData.revopsType || inputData.revopsType == 'duplicateImages' ) ) {
|
|
3390
|
-
result = defaultData;
|
|
3391
|
-
result.duplicateImages = hit?._source?.duplicateImages;
|
|
3392
|
-
result.matched = matched;
|
|
3393
|
-
}
|
|
3394
|
-
|
|
3395
|
-
if ( matched.includes( 'matched_junk' ) && ( !inputData.revopsType || inputData.revopsType == 'junk' ) ) {
|
|
3396
|
-
result = defaultData;
|
|
3397
|
-
result.junk = hit?._source?.junk;
|
|
3398
|
-
result.matched = matched;
|
|
3399
|
-
}
|
|
3400
|
-
|
|
3401
|
-
if ( result ) {
|
|
3402
|
-
const nested = [
|
|
3403
|
-
{
|
|
3404
|
-
_id: hit._id,
|
|
3405
|
-
_index: hit._index,
|
|
3406
|
-
_score: 0,
|
|
3407
|
-
_source: result,
|
|
3408
|
-
},
|
|
3409
|
-
];
|
|
3410
|
-
temp.push( ...nested );
|
|
3411
|
-
}
|
|
3412
|
-
} );
|
|
3413
|
-
}
|
|
3414
|
-
|
|
3415
|
-
const finalResponse = inputData.action ? temp : response;
|
|
3575
|
+
const finalResponse = response;
|
|
3416
3576
|
const getRevopQuery = {
|
|
3417
3577
|
size: 10000,
|
|
3418
3578
|
query: {
|
|
@@ -3655,9 +3815,10 @@ export async function getTickets( req, res ) {
|
|
|
3655
3815
|
mappingObj.revisedDetail = processedRevopSources;
|
|
3656
3816
|
}
|
|
3657
3817
|
} );
|
|
3658
|
-
} else {
|
|
3659
|
-
item._source.mappingInfo.revisedDetail = processedRevopSources;
|
|
3660
3818
|
}
|
|
3819
|
+
// else {
|
|
3820
|
+
// item._source.mappingInfo.revisedDetail = processedRevopSources;
|
|
3821
|
+
// }
|
|
3661
3822
|
}
|
|
3662
3823
|
}
|
|
3663
3824
|
} else if (
|
|
@@ -3667,7 +3828,11 @@ export async function getTickets( req, res ) {
|
|
|
3667
3828
|
) {
|
|
3668
3829
|
finalResponse._source.mappingInfo.revisedDetail = processedRevopSources;
|
|
3669
3830
|
}
|
|
3831
|
+
if ( inputData.action && inputData.action !== '' ) {
|
|
3832
|
+
const isCheck = inputData.action === 'approved'? true : false;
|
|
3670
3833
|
|
|
3834
|
+
finalResponse[0]._source.mappingInfo[finalResponse?.[0]?._source.mappingInfo?.length -1].revisedDetail = filterRevisedDetailByIsChecked( finalResponse?.[0]?._source?.mappingInfo[finalResponse?.[0]?._source?.mappingInfo?.length -1].revisedDetail, isCheck );
|
|
3835
|
+
}
|
|
3671
3836
|
return res.sendSuccess( { result: finalResponse } );
|
|
3672
3837
|
} catch ( error ) {
|
|
3673
3838
|
const err = error.message || 'Internal Server Error';
|
|
@@ -3676,6 +3841,35 @@ export async function getTickets( req, res ) {
|
|
|
3676
3841
|
}
|
|
3677
3842
|
}
|
|
3678
3843
|
|
|
3844
|
+
function filterRevisedDetailByIsChecked( revisedDetailArr, isCheckedValue ) {
|
|
3845
|
+
if ( !Array.isArray( revisedDetailArr ) ) return [];
|
|
3846
|
+
|
|
3847
|
+
// Helper function to filter duplicateImage recursively, only for revopsType === "duplicate"
|
|
3848
|
+
function filterDuplicateImages( duplicateImages, isChecked ) {
|
|
3849
|
+
if ( !Array.isArray( duplicateImages ) ) return [];
|
|
3850
|
+
return duplicateImages
|
|
3851
|
+
.filter( ( img ) => img.isChecked === isChecked )
|
|
3852
|
+
.map( ( img ) => ( {
|
|
3853
|
+
...img,
|
|
3854
|
+
duplicateImage: filterDuplicateImages( img.duplicateImage, isChecked ),
|
|
3855
|
+
} ) );
|
|
3856
|
+
}
|
|
3857
|
+
|
|
3858
|
+
return revisedDetailArr
|
|
3859
|
+
.filter( ( item ) => item.isChecked === isCheckedValue )
|
|
3860
|
+
.map( ( item ) => {
|
|
3861
|
+
if ( item.revopsType === 'duplicate' && Array.isArray( item.duplicateImage ) ) {
|
|
3862
|
+
// Filter the duplicateImage recursively for duplicates only
|
|
3863
|
+
return {
|
|
3864
|
+
...item,
|
|
3865
|
+
duplicateImage: filterDuplicateImages( item.duplicateImage, isCheckedValue ),
|
|
3866
|
+
};
|
|
3867
|
+
} else {
|
|
3868
|
+
return { ...item };
|
|
3869
|
+
}
|
|
3870
|
+
} );
|
|
3871
|
+
}
|
|
3872
|
+
|
|
3679
3873
|
export async function updateStatus( req, res ) {
|
|
3680
3874
|
try {
|
|
3681
3875
|
const openSearch = JSON.parse( process.env.OPENSEARCH );
|
|
@@ -5062,7 +5256,7 @@ export async function checkTicketExists( req, res ) {
|
|
|
5062
5256
|
},
|
|
5063
5257
|
};
|
|
5064
5258
|
let findTicket = await getOpenSearchData( openSearch.footfallDirectory, findQuery );
|
|
5065
|
-
let Ticket = findTicket
|
|
5259
|
+
let Ticket = findTicket?.body?.hits?.hits;
|
|
5066
5260
|
|
|
5067
5261
|
|
|
5068
5262
|
res.sendSuccess( Ticket );
|
|
@@ -264,7 +264,7 @@ export const getTicketsSchema = Joi.object().keys( {
|
|
|
264
264
|
// } ),
|
|
265
265
|
ticketId: Joi.string().required(),
|
|
266
266
|
// status: Joi.string().optional(),
|
|
267
|
-
action: Joi.string().optional(),
|
|
267
|
+
action: Joi.string().optional().allow( '' ),
|
|
268
268
|
// revopsType: Joi.string().optional(),
|
|
269
269
|
// limit: Joi.number().required(),
|
|
270
270
|
// offset: Joi.number().optional(),
|
|
@@ -15,7 +15,7 @@ footfallDirectoryRouter.post( '/tango-review-accuracy-ticket', isAllowedSessionH
|
|
|
15
15
|
|
|
16
16
|
footfallDirectoryRouter.get( '/ticket-summary', isAllowedSessionHandler, bulkValidate( ticketSummaryValid ), ticketSummary );
|
|
17
17
|
|
|
18
|
-
footfallDirectoryRouter.get( '/ticket-list', isAllowedSessionHandler, bulkValidate( ticketListValid ), ticketList );
|
|
18
|
+
footfallDirectoryRouter.get( '/ticket-list', isAllowedSessionHandler, bulkValidate( ticketListValid ), getAssinedStore, ticketList );
|
|
19
19
|
footfallDirectoryRouter.get( '/get-tickets', isAllowedSessionHandler, bulkValidate( getTicketsValid ), getTickets );
|
|
20
20
|
footfallDirectoryRouter.get( '/get-tagged-stores', isAllowedSessionHandler, bulkValidate( getTaggedStoresValid ), getAssinedStore, getClusters, getTaggedStores );
|
|
21
21
|
footfallDirectoryRouter.put( '/update-status', isAllowedSessionHandler, bulkValidate( updateStatusValid ), updateStatus );
|
|
@@ -359,6 +359,7 @@ export async function ticketCreation( req, res, next ) {
|
|
|
359
359
|
// Get taggingLimitation from config (check both possible paths)
|
|
360
360
|
const taggingLimitation = getConfig?.effectiveLimitation?.values;
|
|
361
361
|
// Initialize count object from taggingLimitation
|
|
362
|
+
|
|
362
363
|
const tempAcc = [];
|
|
363
364
|
taggingLimitation.reduce( ( acc, item ) => {
|
|
364
365
|
if ( item?.type ) {
|
|
@@ -409,11 +410,6 @@ export async function ticketCreation( req, res, next ) {
|
|
|
409
410
|
'isParent': false,
|
|
410
411
|
},
|
|
411
412
|
},
|
|
412
|
-
{
|
|
413
|
-
term: {
|
|
414
|
-
isChecked: true,
|
|
415
|
-
},
|
|
416
|
-
},
|
|
417
413
|
],
|
|
418
414
|
},
|
|
419
415
|
},
|
|
@@ -421,7 +417,7 @@ export async function ticketCreation( req, res, next ) {
|
|
|
421
417
|
type_counts: {
|
|
422
418
|
terms: {
|
|
423
419
|
field: 'revopsType.keyword',
|
|
424
|
-
size:
|
|
420
|
+
size: 10000,
|
|
425
421
|
},
|
|
426
422
|
},
|
|
427
423
|
},
|
|
@@ -430,7 +426,6 @@ export async function ticketCreation( req, res, next ) {
|
|
|
430
426
|
|
|
431
427
|
const revopData = await getOpenSearchData( openSearch.revop, revopQuery );
|
|
432
428
|
const buckets = revopData?.body?.aggregations?.type_counts?.buckets || [];
|
|
433
|
-
|
|
434
429
|
// Map OpenSearch revopsType values to count object keys
|
|
435
430
|
buckets.forEach( ( bucket ) => {
|
|
436
431
|
const revopsType = bucket.key;
|
|
@@ -458,13 +453,13 @@ export async function ticketCreation( req, res, next ) {
|
|
|
458
453
|
const totalCount = Array.isArray( tempAcc ) ?
|
|
459
454
|
tempAcc.reduce( ( sum, acc ) => sum + ( acc.value || 0 ), 0 ) :
|
|
460
455
|
0;
|
|
461
|
-
|
|
456
|
+
logger.info( { totalCount, tempAcc } );
|
|
462
457
|
const footfallCount = hits?.[0]?._source?.footfall_count || 0;
|
|
463
458
|
const revisedFootfall = Math.max( 0, footfallCount - totalCount );
|
|
464
459
|
if ( footfallCount - revisedFootfall == 0 ) {
|
|
465
460
|
return res.sendError( 'Cannot create a ticket because footfall hasn’t changed', 400 );
|
|
466
461
|
}
|
|
467
|
-
|
|
462
|
+
logger.info( { footfallCount, revisedFootfall } );
|
|
468
463
|
const taggingData = {
|
|
469
464
|
size: 10000,
|
|
470
465
|
query: {
|