tango-app-api-analysis-traffic 3.8.14 → 3.8.15
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
|
@@ -702,12 +702,16 @@ export async function expireReviewStatus( req, res ) {
|
|
|
702
702
|
export async function expireApproveStatus( req, res ) {
|
|
703
703
|
try {
|
|
704
704
|
const {
|
|
705
|
-
thresholdDate
|
|
705
|
+
thresholdDate,
|
|
706
706
|
batchSize = 500,
|
|
707
707
|
storeId,
|
|
708
708
|
dateString,
|
|
709
709
|
} = req.body;
|
|
710
710
|
const cutoffDate = new Date( thresholdDate );
|
|
711
|
+
// Convert cutoffDate to "2026-01-12T23:59:59.000Z"
|
|
712
|
+
|
|
713
|
+
cutoffDate.setUTCHours( 23, 59, 59, 0 );
|
|
714
|
+
|
|
711
715
|
if ( Number.isNaN( cutoffDate.getTime() ) ) {
|
|
712
716
|
return res.sendError( 'Invalid thresholdDate', 400 );
|
|
713
717
|
}
|
|
@@ -761,7 +765,6 @@ export async function expireApproveStatus( req, res ) {
|
|
|
761
765
|
let updatedMapping = mappingInfo.map( ( item ) => {
|
|
762
766
|
if ( item?.type === 'approve' && item?.status !== 'Closed' && item?.dueDate ) {
|
|
763
767
|
const due = new Date( item.dueDate );
|
|
764
|
-
logger.info( { item, due, msg: '..........1', cutoffDate } );
|
|
765
768
|
if ( !Number.isNaN( due.getTime() ) && due < cutoffDate ) {
|
|
766
769
|
changed = true;
|
|
767
770
|
|
|
@@ -771,24 +774,19 @@ export async function expireApproveStatus( req, res ) {
|
|
|
771
774
|
|
|
772
775
|
return item;
|
|
773
776
|
} );
|
|
774
|
-
logger.info( { updatedMapping, msh: '.......12' } );
|
|
775
777
|
if ( changed ) {
|
|
776
|
-
logger.info( { changed, msg: '.......2' } );
|
|
777
778
|
updatedMapping = updatedMapping.map( ( item ) => {
|
|
778
|
-
logger.info( { item, msg: '.......3' } );
|
|
779
779
|
if ( item?.type === 'tagging' ) {
|
|
780
|
-
logger.info( { item: item?.type, msg: '.......4' } );
|
|
781
780
|
return { ...item, status: 'Expired' };
|
|
782
781
|
}
|
|
783
782
|
return item;
|
|
784
783
|
} );
|
|
785
784
|
}
|
|
786
785
|
|
|
787
|
-
logger.info( { updatedMapping, msh: '.......13' } );
|
|
788
786
|
if ( changed ) {
|
|
789
787
|
const doc = {
|
|
790
788
|
mappingInfo: updatedMapping,
|
|
791
|
-
status: 'Expired',
|
|
789
|
+
status: 'Approver-Expired',
|
|
792
790
|
};
|
|
793
791
|
logger.info( { updatedMapping } );
|
|
794
792
|
bulkBody.push(
|
|
@@ -814,7 +812,130 @@ export async function expireApproveStatus( req, res ) {
|
|
|
814
812
|
|
|
815
813
|
return res.sendSuccess( { message: 'Expired approve status updated', updated: totalUpdated } );
|
|
816
814
|
} catch ( error ) {
|
|
817
|
-
logger.error( { error: error, message: req.body, function: '
|
|
815
|
+
logger.error( { error: error, message: req.body, function: 'expireReviewStatus' } );
|
|
816
|
+
return res.sendError( { error: error }, 500 );
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
|
|
821
|
+
export async function expireTangoReviewStatus( req, res ) {
|
|
822
|
+
try {
|
|
823
|
+
const {
|
|
824
|
+
thresholdDate,
|
|
825
|
+
batchSize = 500,
|
|
826
|
+
storeId,
|
|
827
|
+
dateString,
|
|
828
|
+
} = req.body;
|
|
829
|
+
const cutoffDate = new Date( thresholdDate );
|
|
830
|
+
// Convert cutoffDate to "2026-01-12T23:59:59.000Z"
|
|
831
|
+
|
|
832
|
+
cutoffDate.setUTCHours( 23, 59, 59, 0 );
|
|
833
|
+
|
|
834
|
+
if ( Number.isNaN( cutoffDate.getTime() ) ) {
|
|
835
|
+
return res.sendError( 'Invalid thresholdDate', 400 );
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
const openSearch = JSON.parse( process.env.OPENSEARCH );
|
|
840
|
+
const query = {
|
|
841
|
+
size: batchSize,
|
|
842
|
+
query: {
|
|
843
|
+
bool: {
|
|
844
|
+
must: [
|
|
845
|
+
{ term: { 'ticketName.keyword': 'footfall-directory' } },
|
|
846
|
+
{ term: { 'type.keyword': 'store' } },
|
|
847
|
+
],
|
|
848
|
+
must_not: [
|
|
849
|
+
{ terms: { 'status.keyword': [ 'Closed' ] } },
|
|
850
|
+
],
|
|
851
|
+
},
|
|
852
|
+
},
|
|
853
|
+
};
|
|
854
|
+
|
|
855
|
+
|
|
856
|
+
if ( storeId ) {
|
|
857
|
+
query.query.bool.must.push( { term: { 'storeId.keyword': storeId } } );
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
|
|
861
|
+
if ( dateString ) {
|
|
862
|
+
query.query.bool.must.push( {
|
|
863
|
+
terms: {
|
|
864
|
+
dateString: Array.isArray( dateString ) ? dateString : `${dateString}`.split( ',' ),
|
|
865
|
+
},
|
|
866
|
+
} );
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
|
|
870
|
+
let totalUpdated = 0;
|
|
871
|
+
let scrollId = null;
|
|
872
|
+
|
|
873
|
+
let firstResponse = await searchOpenSearchData( openSearch.footfallDirectory, query );
|
|
874
|
+
let hitsBatch = firstResponse?.body?.hits?.hits || [];
|
|
875
|
+
scrollId = firstResponse?.body?._scroll_id;
|
|
876
|
+
|
|
877
|
+
while ( hitsBatch.length > 0 ) {
|
|
878
|
+
const bulkBody = [];
|
|
879
|
+
|
|
880
|
+
for ( const hit of hitsBatch ) {
|
|
881
|
+
const src = hit._source || {};
|
|
882
|
+
const mappingInfo = Array.isArray( src.mappingInfo ) ? src.mappingInfo : [];
|
|
883
|
+
let changed = false;
|
|
884
|
+
let updatedMapping = mappingInfo.map( ( item ) => {
|
|
885
|
+
if ( item?.type === 'tangoreview' && item?.status !== 'Closed' && item?.dueDate ) {
|
|
886
|
+
const due = new Date( item.dueDate );
|
|
887
|
+
if ( !Number.isNaN( due.getTime() ) && due < cutoffDate ) {
|
|
888
|
+
changed = true;
|
|
889
|
+
|
|
890
|
+
return { ...item, status: 'Expired' };
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
return item;
|
|
895
|
+
} );
|
|
896
|
+
if ( changed ) {
|
|
897
|
+
const getConfig = await clientService.findOne( src.clientId, { 'footfallDirectoryConfigs.tangoApproved': 1 } );
|
|
898
|
+
if ( getConfig?.footfallDirectoryConfigs?.tangoApproved && getConfig?.footfallDirectoryConfigs?.tangoApproved === true ) {
|
|
899
|
+
;
|
|
900
|
+
updatedMapping = updatedMapping.map( ( item ) => {
|
|
901
|
+
if ( item?.type === 'tagging' ) {
|
|
902
|
+
return { ...item, status: 'Expired' };
|
|
903
|
+
}
|
|
904
|
+
return item;
|
|
905
|
+
} );
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
if ( changed ) {
|
|
910
|
+
const doc = {
|
|
911
|
+
mappingInfo: updatedMapping,
|
|
912
|
+
status: 'Tango-Expired',
|
|
913
|
+
};
|
|
914
|
+
logger.info( { updatedMapping } );
|
|
915
|
+
bulkBody.push(
|
|
916
|
+
{ update: { _index: openSearch.footfallDirectory, _id: hit._id } },
|
|
917
|
+
{ doc: doc, doc_as_upsert: true },
|
|
918
|
+
);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
if ( bulkBody.length > 0 ) {
|
|
923
|
+
const bulkRes = await bulkUpdate( bulkBody );
|
|
924
|
+
if ( bulkRes?.errors ) {
|
|
925
|
+
logger.error( { message: 'Bulk expire errors', items: bulkRes.items } );
|
|
926
|
+
}
|
|
927
|
+
totalUpdated += bulkBody.length / 2;
|
|
928
|
+
}
|
|
929
|
+
logger.info( { totalUpdated, msg: '........9' } );
|
|
930
|
+
if ( !scrollId ) break;
|
|
931
|
+
const nextRes = await scrollResponse( scrollId );
|
|
932
|
+
hitsBatch = nextRes?.body?.hits?.hits || [];
|
|
933
|
+
scrollId = nextRes?.body?._scroll_id;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
return res.sendSuccess( { message: 'Expired approve status updated', updated: totalUpdated } );
|
|
937
|
+
} catch ( error ) {
|
|
938
|
+
logger.error( { error: error, message: req.body, function: 'expireReviewStatus' } );
|
|
818
939
|
return res.sendError( { error: error }, 500 );
|
|
819
940
|
}
|
|
820
941
|
}
|
|
@@ -89,6 +89,16 @@ export const validateOverallCharParams = {
|
|
|
89
89
|
body: validateOverallCharSchema,
|
|
90
90
|
};
|
|
91
91
|
|
|
92
|
+
// Same as validateOverallCharSchema, plus an optional hourFormat key used only by overallHourlyChart_v3
|
|
93
|
+
export const validateOverallHourlyCharSchema = validateOverallCharSchema.keys( {
|
|
94
|
+
hourBucket: joi.number().optional(),
|
|
95
|
+
} );
|
|
96
|
+
|
|
97
|
+
export const validateOverallHourlyCharParams = {
|
|
98
|
+
body: validateOverallHourlyCharSchema,
|
|
99
|
+
...validateOverallCharSchema,
|
|
100
|
+
};
|
|
101
|
+
|
|
92
102
|
export const validateSingleStoreChartSchema = joi.object( {
|
|
93
103
|
...baseSchema,
|
|
94
104
|
limit: joi.number().required(),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import express from 'express';
|
|
3
|
-
import { storeProcessedData, getconfig, revoptagging, getrevoptagging, revoptaggingcount, footFallImages, tagTempId, getCategorizedImages, vmsDataMigration, migrateRevopIndex, expireReviewStatus } from '../controllers/revop.controller.js';
|
|
3
|
+
import { storeProcessedData, getconfig, revoptagging, getrevoptagging, revoptaggingcount, footFallImages, tagTempId, getCategorizedImages, vmsDataMigration, migrateRevopIndex, expireReviewStatus, expireApproveStatus } from '../controllers/revop.controller.js';
|
|
4
4
|
import { isAllowedSessionHandler, validate } from 'tango-app-api-middleware';
|
|
5
5
|
import { footfallImagesValid, getCategorizedImagesValid, storeProcessedDataValid, tagTempIdValid, vmsDataMigrationValid } from '../dtos/revop.dtos.js';
|
|
6
6
|
import { deleteTaggedDuplicate, getTaggingConfig, mappingConfig } from '../validations/revop.validation.js';
|
|
@@ -13,9 +13,10 @@ revopRouter
|
|
|
13
13
|
.post( '/getrevoptagging', isAllowedSessionHandler, getrevoptagging )
|
|
14
14
|
.post( '/migrate-revop', migrateRevopIndex )
|
|
15
15
|
.post( '/expire-review-status', expireReviewStatus )
|
|
16
|
+
.post( '/expire-approve-status', expireApproveStatus )
|
|
16
17
|
.post( '/revoptaggingcount', isAllowedSessionHandler, revoptaggingcount )
|
|
17
18
|
|
|
18
|
-
// new
|
|
19
|
+
// new enhancement (for footfall directory)
|
|
19
20
|
.get( '/store-processed-data', isAllowedSessionHandler, validate( storeProcessedDataValid ), storeProcessedData )
|
|
20
21
|
.get( '/footfall-images', isAllowedSessionHandler, validate( footfallImagesValid ), getTaggingConfig, footFallImages )
|
|
21
22
|
.post( '/tag-tempId', isAllowedSessionHandler, validate( tagTempIdValid ), mappingConfig, deleteTaggedDuplicate, tagTempId )
|
|
@@ -159,7 +159,7 @@ analysisTrafficRouter
|
|
|
159
159
|
.post( '/densityDwell_v3', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateDensityDwellParams ), densityDwellV3 )
|
|
160
160
|
.post( '/trafficDensityDwell_v3', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateDensityDwellParams ), trafficDensityDwellV3 )
|
|
161
161
|
.post( '/overallCards_v3', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateOverallCharParams ), overallCardsV3 )
|
|
162
|
-
.post( '/overallHourlyChart_v3', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.
|
|
162
|
+
.post( '/overallHourlyChart_v3', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateOverallHourlyCharParams ), overallHourlyChartV3 )
|
|
163
163
|
.post( '/overallChart_v3', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateOverallCharParams ), overallChartV3 )
|
|
164
164
|
.post( '/singleStoreChart_v3', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateSingleStoreChartParams ), singleStoreChartV3 )
|
|
165
165
|
.post( '/demographicChart_v3', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateDemographicChartParams ), demographicChartV3 )
|