tango-app-api-infra 3.9.5-vms.80 → 3.9.5-vms.82
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-infra",
|
|
3
|
-
"version": "3.9.5-vms.
|
|
3
|
+
"version": "3.9.5-vms.82",
|
|
4
4
|
"description": "infra",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"mongodb": "^6.4.0",
|
|
28
28
|
"nodemon": "^3.1.0",
|
|
29
29
|
"swagger-ui-express": "^5.0.0",
|
|
30
|
-
"tango-api-schema": "^2.5.
|
|
30
|
+
"tango-api-schema": "^2.5.2",
|
|
31
31
|
"tango-app-api-infra": "^3.9.5-vms.56",
|
|
32
32
|
"tango-app-api-middleware": "^3.1.93",
|
|
33
33
|
"winston": "^3.12.0",
|
|
@@ -304,7 +304,7 @@ export async function tangoReviewTicket( req, res ) {
|
|
|
304
304
|
revicedPerc: inputData.mappingInfo?.revicedPerc,
|
|
305
305
|
count: inputData.mappingInfo?.count,
|
|
306
306
|
revisedDetail: inputData.mappingInfo?.revisedDetail,
|
|
307
|
-
status: '
|
|
307
|
+
status: 'Open - Accuracy Issue',
|
|
308
308
|
createdByEmail: req?.user?.email,
|
|
309
309
|
createdByUserName: req?.user?.userName,
|
|
310
310
|
createdByRole: req?.user?.role,
|
|
@@ -2,7 +2,7 @@ import { bulkUpdate, getOpenSearchCount, getOpenSearchData, insertWithId, logger
|
|
|
2
2
|
import { aggregateCluster } from '../services/cluster.service.js';
|
|
3
3
|
import { findOneRevopDownload } from '../services/revopDownload.service.js';
|
|
4
4
|
import { findOneStore } from '../services/store.service.js';
|
|
5
|
-
import { findOneClient } from '../services/client.service.js';
|
|
5
|
+
import { aggregateClient, findOneClient } from '../services/client.service.js';
|
|
6
6
|
import { updateOneUpsertVmsStoreRequest } from '../services/vmsStoreRequest.service.js';
|
|
7
7
|
import { findOneUser, aggregateUser } from '../services/user.service.js';
|
|
8
8
|
import { findteams } from '../services/teams.service.js';
|
|
@@ -277,7 +277,75 @@ export async function ticketCreation( req, res, next ) {
|
|
|
277
277
|
}
|
|
278
278
|
|
|
279
279
|
// get category details from the client level configuration
|
|
280
|
-
const
|
|
280
|
+
const configQuery = [
|
|
281
|
+
{
|
|
282
|
+
$match: {
|
|
283
|
+
clientId: getstoreName?.clientId,
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
|
|
287
|
+
// Filter limitations based on effectiveFrom <= date
|
|
288
|
+
{
|
|
289
|
+
$addFields: {
|
|
290
|
+
matchedLimitation: {
|
|
291
|
+
$filter: {
|
|
292
|
+
input: '$footfallDirectoryConfigs.taggingLimitation',
|
|
293
|
+
as: 'item',
|
|
294
|
+
cond: { $lte: [ '$$item.effectiveFrom', inputData.dateString ] },
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
|
|
300
|
+
// Pick latest effective record
|
|
301
|
+
{
|
|
302
|
+
$addFields: {
|
|
303
|
+
effectiveLimitation: {
|
|
304
|
+
$arrayElemAt: [
|
|
305
|
+
{
|
|
306
|
+
$slice: [
|
|
307
|
+
{
|
|
308
|
+
$sortArray: {
|
|
309
|
+
input: '$matchedLimitation',
|
|
310
|
+
sortBy: { effectiveFrom: -1 },
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
1,
|
|
314
|
+
],
|
|
315
|
+
},
|
|
316
|
+
0,
|
|
317
|
+
],
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
|
|
322
|
+
// Remove originals before final merge
|
|
323
|
+
{
|
|
324
|
+
$project: {
|
|
325
|
+
'config.taggingLimitation': 0,
|
|
326
|
+
'matchedLimitation': 0,
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
|
|
330
|
+
// Attach effective limitation INSIDE config
|
|
331
|
+
{
|
|
332
|
+
$addFields: {
|
|
333
|
+
'config.effectiveLimitation': '$effectiveLimitation',
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
|
|
337
|
+
// Remove temporary field
|
|
338
|
+
{
|
|
339
|
+
$project: {
|
|
340
|
+
footfallDirectoryConfigs: 1,
|
|
341
|
+
clientId: 1,
|
|
342
|
+
},
|
|
343
|
+
},
|
|
344
|
+
];
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
const config = await aggregateClient( configQuery );
|
|
348
|
+
const getConfig = config[0];
|
|
281
349
|
if ( !getConfig || getConfig == null ) {
|
|
282
350
|
return res.sendError( 'The Client ID is either not configured or not found', 400 );
|
|
283
351
|
}
|
|
@@ -286,7 +354,7 @@ export async function ticketCreation( req, res, next ) {
|
|
|
286
354
|
const taggingLimitation = getConfig?.footfallDirectoryConfigs?.taggingLimitation;
|
|
287
355
|
// Initialize count object from taggingLimitation
|
|
288
356
|
const tempAcc = [];
|
|
289
|
-
taggingLimitation?.reduce( ( acc, item ) => {
|
|
357
|
+
taggingLimitation[taggingLimitation?.length - 1]?.values?.reduce( ( acc, item ) => {
|
|
290
358
|
if ( item?.type ) {
|
|
291
359
|
// Convert type to camelCase with "Count" suffix
|
|
292
360
|
// e.g., "duplicate" -> "duplicateCount", "housekeeping" -> "houseKeepingCount"
|
|
@@ -384,6 +452,7 @@ export async function ticketCreation( req, res, next ) {
|
|
|
384
452
|
const totalCount = Array.isArray( tempAcc ) ?
|
|
385
453
|
tempAcc.reduce( ( sum, acc ) => sum + ( acc.value || 0 ), 0 ) :
|
|
386
454
|
0;
|
|
455
|
+
|
|
387
456
|
const footfallCount = hits?.[0]?._source?.footfall_count || 0;
|
|
388
457
|
const revisedFootfall = Math.max( 0, footfallCount - totalCount );
|
|
389
458
|
if ( footfallCount - revisedFootfall == 0 ) {
|
|
@@ -920,7 +989,75 @@ export async function ticketReview( req, res, next ) {
|
|
|
920
989
|
}
|
|
921
990
|
|
|
922
991
|
// get category details from the client level configuration
|
|
923
|
-
const
|
|
992
|
+
const configQuery = [
|
|
993
|
+
{
|
|
994
|
+
$match: {
|
|
995
|
+
clientId: getstoreName?.clientId,
|
|
996
|
+
},
|
|
997
|
+
},
|
|
998
|
+
|
|
999
|
+
// Filter limitations based on effectiveFrom <= date
|
|
1000
|
+
{
|
|
1001
|
+
$addFields: {
|
|
1002
|
+
matchedLimitation: {
|
|
1003
|
+
$filter: {
|
|
1004
|
+
input: '$footfallDirectoryConfigs.taggingLimitation',
|
|
1005
|
+
as: 'item',
|
|
1006
|
+
cond: { $lte: [ '$$item.effectiveFrom', inputData.dateString ] },
|
|
1007
|
+
},
|
|
1008
|
+
},
|
|
1009
|
+
},
|
|
1010
|
+
},
|
|
1011
|
+
|
|
1012
|
+
// Pick latest effective record
|
|
1013
|
+
{
|
|
1014
|
+
$addFields: {
|
|
1015
|
+
effectiveLimitation: {
|
|
1016
|
+
$arrayElemAt: [
|
|
1017
|
+
{
|
|
1018
|
+
$slice: [
|
|
1019
|
+
{
|
|
1020
|
+
$sortArray: {
|
|
1021
|
+
input: '$matchedLimitation',
|
|
1022
|
+
sortBy: { effectiveFrom: -1 },
|
|
1023
|
+
},
|
|
1024
|
+
},
|
|
1025
|
+
1,
|
|
1026
|
+
],
|
|
1027
|
+
},
|
|
1028
|
+
0,
|
|
1029
|
+
],
|
|
1030
|
+
},
|
|
1031
|
+
},
|
|
1032
|
+
},
|
|
1033
|
+
|
|
1034
|
+
// Remove originals before final merge
|
|
1035
|
+
{
|
|
1036
|
+
$project: {
|
|
1037
|
+
'config.taggingLimitation': 0,
|
|
1038
|
+
'matchedLimitation': 0,
|
|
1039
|
+
},
|
|
1040
|
+
},
|
|
1041
|
+
|
|
1042
|
+
// Attach effective limitation INSIDE config
|
|
1043
|
+
{
|
|
1044
|
+
$addFields: {
|
|
1045
|
+
'config.effectiveLimitation': '$effectiveLimitation',
|
|
1046
|
+
},
|
|
1047
|
+
},
|
|
1048
|
+
|
|
1049
|
+
// Remove temporary field
|
|
1050
|
+
{
|
|
1051
|
+
$project: {
|
|
1052
|
+
footfallDirectoryConfigs: 1,
|
|
1053
|
+
clientId: 1,
|
|
1054
|
+
},
|
|
1055
|
+
},
|
|
1056
|
+
];
|
|
1057
|
+
|
|
1058
|
+
|
|
1059
|
+
const config = await aggregateClient( configQuery );
|
|
1060
|
+
const getConfig = config[0];
|
|
924
1061
|
if ( !getConfig || getConfig == null ) {
|
|
925
1062
|
return res.sendError( 'The Client ID is either not configured or not found', 400 );
|
|
926
1063
|
}
|
|
@@ -929,7 +1066,7 @@ export async function ticketReview( req, res, next ) {
|
|
|
929
1066
|
const taggingLimitation = getConfig?.footfallDirectoryConfigs?.taggingLimitation;
|
|
930
1067
|
// Initialize count object from taggingLimitation
|
|
931
1068
|
const tempAcc = [];
|
|
932
|
-
taggingLimitation?.reduce( ( acc, item ) => {
|
|
1069
|
+
taggingLimitation[taggingLimitation?.length - 1]?.values?.reduce( ( acc, item ) => {
|
|
933
1070
|
if ( item?.type ) {
|
|
934
1071
|
// Convert type to camelCase with "Count" suffix
|
|
935
1072
|
// e.g., "duplicate" -> "duplicateCount", "housekeeping" -> "houseKeepingCount"
|
|
@@ -1454,7 +1591,75 @@ export async function ticketApprove( req, res, next ) {
|
|
|
1454
1591
|
}
|
|
1455
1592
|
|
|
1456
1593
|
// get category details from the client level configuration
|
|
1457
|
-
const
|
|
1594
|
+
const configQuery = [
|
|
1595
|
+
{
|
|
1596
|
+
$match: {
|
|
1597
|
+
clientId: getstoreName?.clientId,
|
|
1598
|
+
},
|
|
1599
|
+
},
|
|
1600
|
+
|
|
1601
|
+
// Filter limitations based on effectiveFrom <= date
|
|
1602
|
+
{
|
|
1603
|
+
$addFields: {
|
|
1604
|
+
matchedLimitation: {
|
|
1605
|
+
$filter: {
|
|
1606
|
+
input: '$footfallDirectoryConfigs.taggingLimitation',
|
|
1607
|
+
as: 'item',
|
|
1608
|
+
cond: { $lte: [ '$$item.effectiveFrom', inputData.dateString ] },
|
|
1609
|
+
},
|
|
1610
|
+
},
|
|
1611
|
+
},
|
|
1612
|
+
},
|
|
1613
|
+
|
|
1614
|
+
// Pick latest effective record
|
|
1615
|
+
{
|
|
1616
|
+
$addFields: {
|
|
1617
|
+
effectiveLimitation: {
|
|
1618
|
+
$arrayElemAt: [
|
|
1619
|
+
{
|
|
1620
|
+
$slice: [
|
|
1621
|
+
{
|
|
1622
|
+
$sortArray: {
|
|
1623
|
+
input: '$matchedLimitation',
|
|
1624
|
+
sortBy: { effectiveFrom: -1 },
|
|
1625
|
+
},
|
|
1626
|
+
},
|
|
1627
|
+
1,
|
|
1628
|
+
],
|
|
1629
|
+
},
|
|
1630
|
+
0,
|
|
1631
|
+
],
|
|
1632
|
+
},
|
|
1633
|
+
},
|
|
1634
|
+
},
|
|
1635
|
+
|
|
1636
|
+
// Remove originals before final merge
|
|
1637
|
+
{
|
|
1638
|
+
$project: {
|
|
1639
|
+
'config.taggingLimitation': 0,
|
|
1640
|
+
'matchedLimitation': 0,
|
|
1641
|
+
},
|
|
1642
|
+
},
|
|
1643
|
+
|
|
1644
|
+
// Attach effective limitation INSIDE config
|
|
1645
|
+
{
|
|
1646
|
+
$addFields: {
|
|
1647
|
+
'config.effectiveLimitation': '$effectiveLimitation',
|
|
1648
|
+
},
|
|
1649
|
+
},
|
|
1650
|
+
|
|
1651
|
+
// Remove temporary field
|
|
1652
|
+
{
|
|
1653
|
+
$project: {
|
|
1654
|
+
footfallDirectoryConfigs: 1,
|
|
1655
|
+
clientId: 1,
|
|
1656
|
+
},
|
|
1657
|
+
},
|
|
1658
|
+
];
|
|
1659
|
+
|
|
1660
|
+
|
|
1661
|
+
const config = await aggregateClient( configQuery );
|
|
1662
|
+
const getConfig = config[0];
|
|
1458
1663
|
if ( !getConfig || getConfig == null ) {
|
|
1459
1664
|
return res.sendError( 'The Client ID is either not configured or not found', 400 );
|
|
1460
1665
|
}
|
|
@@ -1463,7 +1668,7 @@ export async function ticketApprove( req, res, next ) {
|
|
|
1463
1668
|
const taggingLimitation = getConfig?.footfallDirectoryConfigs?.taggingLimitation;
|
|
1464
1669
|
// Initialize count object from taggingLimitation
|
|
1465
1670
|
const tempAcc = [];
|
|
1466
|
-
taggingLimitation?.reduce( ( acc, item ) => {
|
|
1671
|
+
taggingLimitation[taggingLimitation?.length - 1]?.values?.reduce( ( acc, item ) => {
|
|
1467
1672
|
if ( item?.type ) {
|
|
1468
1673
|
// Convert type to camelCase with "Count" suffix
|
|
1469
1674
|
// e.g., "duplicate" -> "duplicateCount", "housekeeping" -> "houseKeepingCount"
|
|
@@ -1553,9 +1758,9 @@ export async function ticketApprove( req, res, next ) {
|
|
|
1553
1758
|
0;
|
|
1554
1759
|
const footfallCount = hits?.[0]?._source?.footfall_count || 0;
|
|
1555
1760
|
const revisedFootfall = Math.max( 0, footfallCount - totalCount );
|
|
1556
|
-
|
|
1761
|
+
|
|
1557
1762
|
if ( footfallCount - revisedFootfall == 0 ) {
|
|
1558
|
-
return res.sendError( 'Cannot
|
|
1763
|
+
return res.sendError( 'Cannot approve a ticket because footfall hasn’t changed', 400 );
|
|
1559
1764
|
}
|
|
1560
1765
|
|
|
1561
1766
|
const taggingData = {
|
|
@@ -1621,7 +1826,7 @@ export async function ticketApprove( req, res, next ) {
|
|
|
1621
1826
|
if ( !ticketData || ticketData?.length == 0 ) {
|
|
1622
1827
|
return res.sendError( 'You don’t have any tagged images right now', 400 );
|
|
1623
1828
|
}
|
|
1624
|
-
|
|
1829
|
+
|
|
1625
1830
|
const record = {
|
|
1626
1831
|
|
|
1627
1832
|
status: 'Approver-Closed',
|
|
@@ -1641,12 +1846,10 @@ export async function ticketApprove( req, res, next ) {
|
|
|
1641
1846
|
let autoCloseAccuracy = getConfig?.footfallDirectoryConfigs?.autoCloseAccuracy;
|
|
1642
1847
|
|
|
1643
1848
|
const getNumber = autoCloseAccuracy.split( '%' )[0];
|
|
1644
|
-
logger.info( { getNumber } );
|
|
1645
1849
|
let autoCloseAccuracyValue = parseFloat( ( autoCloseAccuracy || getNumber ).replace( '%', '' ) );
|
|
1646
1850
|
let revisedPercentage = Math.round( ( revisedFootfall / footfallCount ) * 100 || 0 );
|
|
1647
1851
|
const revised = Number( Math.round( ( revisedFootfall / footfallCount ) * 100 || 0 ) );
|
|
1648
1852
|
const tangoReview = Number( getConfig?.footfallDirectoryConfigs?.tangoReview?.split( '%' )[0] );
|
|
1649
|
-
logger.info( { tangoReview, revised } );
|
|
1650
1853
|
// If autoclose enabled and revisedPercentage meets/exceeds threshold, close ticket and skip revision
|
|
1651
1854
|
if (
|
|
1652
1855
|
isAutoCloseEnable === true &&
|