tango-app-api-analysis-traffic 3.0.0-alpha.34 → 3.0.0-alpha.36
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-analysis-traffic",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.36",
|
|
4
4
|
"description": "Traffic Analysis",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"mongodb": "^6.8.0",
|
|
23
23
|
"nodemon": "^3.1.4",
|
|
24
24
|
"tango-api-schema": "^2.0.131",
|
|
25
|
-
"tango-app-api-middleware": "^3.1.
|
|
25
|
+
"tango-app-api-middleware": "^3.1.43-alpha.6",
|
|
26
26
|
"winston": "^3.13.1",
|
|
27
27
|
"winston-daily-rotate-file": "^5.0.0"
|
|
28
28
|
},
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
findOneStore,
|
|
6
6
|
} from '../services/stores.service.js';
|
|
7
7
|
import { aggregateUserAssignedStore, findOneUserAssignedStore } from '../services/userAssignedStore.service.js';
|
|
8
|
+
import { aggregateCluster } from '../services/cluster.service.js';
|
|
8
9
|
import { aggregateGroup } from '../services/group.service.js';
|
|
9
10
|
import dayjs from 'dayjs';
|
|
10
11
|
import mongoose from 'mongoose';
|
|
@@ -682,7 +683,56 @@ export const headerLocationsV1 = async ( req, res ) => {
|
|
|
682
683
|
return res.sendError( { error: error }, 500 );
|
|
683
684
|
}
|
|
684
685
|
};
|
|
685
|
-
|
|
686
|
+
export const headerLocationsV2 = async ( req, res ) => {
|
|
687
|
+
try {
|
|
688
|
+
let reqestData = req.body;
|
|
689
|
+
let getUserEmail = req.user.email;
|
|
690
|
+
let getUserType = req.user.userType;
|
|
691
|
+
let getRole = req.user.role;
|
|
692
|
+
let getClientId = reqestData.clientId;
|
|
693
|
+
let totalStores = await getStoresList( getUserEmail, getClientId, getUserType, getRole, req );
|
|
694
|
+
if ( totalStores && totalStores.length>0 ) {
|
|
695
|
+
let storeQuery = [
|
|
696
|
+
{
|
|
697
|
+
$match: {
|
|
698
|
+
$and: [
|
|
699
|
+
{ clientId: { $eq: getClientId } },
|
|
700
|
+
{ storeId: { $in: totalStores } },
|
|
701
|
+
],
|
|
702
|
+
},
|
|
703
|
+
},
|
|
704
|
+
{
|
|
705
|
+
$group: {
|
|
706
|
+
_id: '$storeProfile.city',
|
|
707
|
+
},
|
|
708
|
+
},
|
|
709
|
+
{
|
|
710
|
+
$project: {
|
|
711
|
+
_id: 0,
|
|
712
|
+
city: '$_id',
|
|
713
|
+
},
|
|
714
|
+
},
|
|
715
|
+
{
|
|
716
|
+
$sort: {
|
|
717
|
+
city: -1,
|
|
718
|
+
},
|
|
719
|
+
},
|
|
720
|
+
];
|
|
721
|
+
const cityList = await aggregateStore( storeQuery );
|
|
722
|
+
if ( cityList && cityList.length > 0 ) {
|
|
723
|
+
let city = cityList.filter( ( data ) => data.city!='' );
|
|
724
|
+
return res.sendSuccess( { locationData: city } );
|
|
725
|
+
} else {
|
|
726
|
+
return res.sendError( 'No City', 400 );
|
|
727
|
+
}
|
|
728
|
+
} else {
|
|
729
|
+
return res.sendError( 'No stores', 400 );
|
|
730
|
+
}
|
|
731
|
+
} catch ( error ) {
|
|
732
|
+
logger.error( { error: error, message: req.query, function: 'trafficCards' } );
|
|
733
|
+
return res.sendError( { error: error }, 500 );
|
|
734
|
+
}
|
|
735
|
+
};
|
|
686
736
|
export const headerGroupsV1 = async ( req, res ) => {
|
|
687
737
|
try {
|
|
688
738
|
let requestData = req.body;
|
|
@@ -691,7 +741,7 @@ export const headerGroupsV1 = async ( req, res ) => {
|
|
|
691
741
|
let getRole = req.user.role;
|
|
692
742
|
let groupIds;
|
|
693
743
|
if ( requestData.city && requestData.city.length>0 ) {
|
|
694
|
-
let getGroupIds = await getCityStores( requestData.clientId, getUserEmail, getRole, requestData.city, getUserType );
|
|
744
|
+
let getGroupIds = await getCityStores( requestData.clientId, getUserEmail, getRole, requestData.city, getUserType, req );
|
|
695
745
|
if ( getGroupIds && getGroupIds.length>0 ) {
|
|
696
746
|
groupIds = getGroupIds;
|
|
697
747
|
} else {
|
|
@@ -757,7 +807,147 @@ export const headerGroupsV1 = async ( req, res ) => {
|
|
|
757
807
|
return res.sendError( { error: error }, 500 );
|
|
758
808
|
}
|
|
759
809
|
};
|
|
810
|
+
export async function headerClustersV2( req, res ) {
|
|
811
|
+
try {
|
|
812
|
+
let requestData = req.body;
|
|
813
|
+
let getUserEmail = req.user.email;
|
|
814
|
+
let getUserType = req.user.userType;
|
|
815
|
+
let getRole = req.user.role;
|
|
816
|
+
let clusterNames=[];
|
|
817
|
+
if ( requestData.city && requestData.city.length>0 ) {
|
|
818
|
+
let getcityclustes = await getCityClusters( requestData.clientId, getUserEmail, getRole, requestData.city, getUserType, req );
|
|
819
|
+
if ( getcityclustes && getcityclustes.length>0 ) {
|
|
820
|
+
clusterNames = getcityclustes;
|
|
821
|
+
} else {
|
|
822
|
+
clusterNames = [];
|
|
823
|
+
}
|
|
824
|
+
} else {
|
|
825
|
+
if ( getUserType == 'tango' ) {
|
|
826
|
+
clusterNames = await getclusterList( requestData.clientId, req );
|
|
827
|
+
console.log( clusterNames );
|
|
828
|
+
} else if ( getUserType == 'client' ) {
|
|
829
|
+
if ( getRole == 'superadmin' ) {
|
|
830
|
+
clusterNames = await getclusterList( requestData.clientId, req );
|
|
831
|
+
} else {
|
|
832
|
+
clusterNames = await getclusterList( requestData.clientId, req );
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
console.log( clusterNames );
|
|
837
|
+
if ( clusterNames.length>0 ) {
|
|
838
|
+
const dataObjects = clusterNames.map( ( item ) => ( { groupName: item } ) );
|
|
839
|
+
res.sendSuccess( { groupData: dataObjects } );
|
|
840
|
+
} else {
|
|
841
|
+
res.sendSuccess( { groupData: [] } );
|
|
842
|
+
}
|
|
843
|
+
} catch ( error ) {
|
|
844
|
+
logger.error( { error: error, message: req.query, function: 'headerClustersV2' } );
|
|
845
|
+
return res.sendError( { error: error }, 500 );
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
async function getCityClusters( userClientId, getUserEmail, getRole, requestCity, getUserType, req ) {
|
|
851
|
+
try {
|
|
852
|
+
if ( userClientId && userClientId !='' && getUserEmail && getUserEmail !='', getRole && getRole !='', requestCity && requestCity.length>0 ) {
|
|
853
|
+
let cityStores = await getLocationStores( userClientId, requestCity, req );
|
|
854
|
+
if ( cityStores && cityStores.length > 0 ) {
|
|
855
|
+
let storeGroups = await getClusterStoresIds( userClientId, cityStores, getRole, getUserType, getUserEmail );
|
|
856
|
+
if ( storeGroups && storeGroups.length > 0 ) {
|
|
857
|
+
return storeGroups;
|
|
858
|
+
} else {
|
|
859
|
+
return false;
|
|
860
|
+
}
|
|
861
|
+
} else {
|
|
862
|
+
return false;
|
|
863
|
+
}
|
|
864
|
+
} else {
|
|
865
|
+
return false;
|
|
866
|
+
}
|
|
867
|
+
} catch ( error ) {
|
|
868
|
+
logger.error( { error: error, function: 'getCityClusters' } );
|
|
869
|
+
return false;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
async function getClusterStoresIds( userClientId, storeIds, getRole, getUserType, getUserEmail ) {
|
|
873
|
+
try {
|
|
874
|
+
if ( userClientId && userClientId !='' && storeIds && storeIds !='' && getRole && getRole !='' && getUserType && getUserType !='', getUserEmail && getUserEmail !='' ) {
|
|
875
|
+
let clusterQuery = [];
|
|
876
|
+
if ( getUserType == 'client' ) {
|
|
877
|
+
if ( getRole == 'superadmin' ) {
|
|
878
|
+
clusterQuery = [
|
|
879
|
+
{
|
|
880
|
+
$match: {
|
|
881
|
+
$and: [
|
|
882
|
+
{ clientId: { $eq: userClientId } },
|
|
883
|
+
{ 'stores.storeId': { $in: storeIds } },
|
|
884
|
+
],
|
|
885
|
+
},
|
|
886
|
+
},
|
|
887
|
+
{
|
|
888
|
+
$group: {
|
|
889
|
+
_id: null,
|
|
890
|
+
clusterName: { $push: '$clusterName' },
|
|
891
|
+
},
|
|
892
|
+
},
|
|
893
|
+
];
|
|
894
|
+
} else {
|
|
895
|
+
let getAssignedGroupIds = [
|
|
896
|
+
{
|
|
897
|
+
$match: {
|
|
898
|
+
$and: [
|
|
899
|
+
{ clientId: { $eq: userClientId } },
|
|
900
|
+
{ 'stores.storeId': { $in: storeIds } },
|
|
901
|
+
],
|
|
902
|
+
},
|
|
903
|
+
},
|
|
904
|
+
{
|
|
905
|
+
$group: {
|
|
906
|
+
_id: null,
|
|
907
|
+
clusterName: { $push: '$clusterName' },
|
|
908
|
+
},
|
|
909
|
+
},
|
|
910
|
+
];
|
|
911
|
+
const assignedclusters = await aggregateCluster( getAssignedGroupIds );
|
|
912
|
+
if ( assignedclusters && assignedclusters.length>0 && assignedclusters[0]?.clusterName.length > 0 ) {
|
|
913
|
+
let uniqueclusters = [ ...new Set( assignedclusters[0].clusterName ) ];
|
|
914
|
+
return uniqueclusters;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
} else if ( getUserType == 'tango' ) {
|
|
918
|
+
clusterQuery = [
|
|
919
|
+
{
|
|
920
|
+
$match: {
|
|
921
|
+
$and: [
|
|
922
|
+
{ clientId: { $eq: userClientId } },
|
|
923
|
+
{ 'stores.storeId': { $in: storeIds } },
|
|
924
|
+
],
|
|
925
|
+
},
|
|
926
|
+
},
|
|
927
|
+
{
|
|
928
|
+
$group: {
|
|
929
|
+
_id: null,
|
|
930
|
+
clusterName: { $push: '$clusterName' },
|
|
931
|
+
},
|
|
932
|
+
},
|
|
933
|
+
];
|
|
934
|
+
}
|
|
760
935
|
|
|
936
|
+
const assignedclusters = await aggregateCluster( clusterQuery );
|
|
937
|
+
if ( assignedclusters && assignedclusters.length>0 && assignedclusters[0]?.clusterName.length > 0 ) {
|
|
938
|
+
let uniqueclusters = [ ...new Set( assignedclusters[0].clusterName ) ];
|
|
939
|
+
return uniqueclusters;
|
|
940
|
+
} else {
|
|
941
|
+
return false;
|
|
942
|
+
}
|
|
943
|
+
} else {
|
|
944
|
+
return false;
|
|
945
|
+
}
|
|
946
|
+
} catch ( error ) {
|
|
947
|
+
logger.error( { error: error, function: 'getGroupIds' } );
|
|
948
|
+
return false;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
761
951
|
export const headerStoresV1 = async ( req, res ) => {
|
|
762
952
|
try {
|
|
763
953
|
let reqestData = req.body;
|
|
@@ -861,6 +1051,140 @@ export const headerStoresV1 = async ( req, res ) => {
|
|
|
861
1051
|
return res.sendError( { error: error }, 500 );
|
|
862
1052
|
}
|
|
863
1053
|
};
|
|
1054
|
+
export const headerStoresV2 = async ( req, res ) => {
|
|
1055
|
+
try {
|
|
1056
|
+
let reqestData = req.body;
|
|
1057
|
+
let getUserEmail = req.user.email;
|
|
1058
|
+
let getUserType = req.user.userType;
|
|
1059
|
+
let getRole = req.user.role;
|
|
1060
|
+
let getClientId = reqestData.clientId;
|
|
1061
|
+
let totalStores = await getStoresList( getUserEmail, getClientId, getUserType, getRole, req );
|
|
1062
|
+
if ( totalStores && totalStores.length>0 ) {
|
|
1063
|
+
let storeQuery = [];
|
|
1064
|
+
if ( reqestData.city.length>0 && reqestData.clusters.length>0 ) {
|
|
1065
|
+
let unqueCityStores = await getLocationStores( getClientId, reqestData.city, req );
|
|
1066
|
+
let unqueGroupStores = await getClusterStores( getClientId, reqestData.clusters );
|
|
1067
|
+
storeQuery = [
|
|
1068
|
+
{
|
|
1069
|
+
$match: {
|
|
1070
|
+
$and: [
|
|
1071
|
+
{ storeId: { $in: totalStores } },
|
|
1072
|
+
{ storeId: { $in: unqueCityStores } },
|
|
1073
|
+
{ storeId: { $in: unqueGroupStores } },
|
|
1074
|
+
],
|
|
1075
|
+
},
|
|
1076
|
+
},
|
|
1077
|
+
{
|
|
1078
|
+
$project: {
|
|
1079
|
+
_id: 0,
|
|
1080
|
+
storeId: '$storeId',
|
|
1081
|
+
storeName: '$storeName',
|
|
1082
|
+
},
|
|
1083
|
+
},
|
|
1084
|
+
];
|
|
1085
|
+
} else if ( reqestData.city.length>0 ) {
|
|
1086
|
+
let uniqueCityStores = await getLocationStores( getClientId, reqestData.city, req );
|
|
1087
|
+
storeQuery = [
|
|
1088
|
+
{
|
|
1089
|
+
$match: {
|
|
1090
|
+
$and: [
|
|
1091
|
+
{ storeId: { $in: totalStores } },
|
|
1092
|
+
{ storeId: { $in: uniqueCityStores } },
|
|
1093
|
+
],
|
|
1094
|
+
},
|
|
1095
|
+
},
|
|
1096
|
+
{
|
|
1097
|
+
$project: {
|
|
1098
|
+
_id: 0,
|
|
1099
|
+
storeId: '$storeId',
|
|
1100
|
+
storeName: '$storeName',
|
|
1101
|
+
},
|
|
1102
|
+
},
|
|
1103
|
+
];
|
|
1104
|
+
} else if ( reqestData.clusters.length>0 ) {
|
|
1105
|
+
let uniqueclusterStores = await getClusterStores( getClientId, reqestData.clusters );
|
|
1106
|
+
storeQuery = [
|
|
1107
|
+
{
|
|
1108
|
+
$match: {
|
|
1109
|
+
$and: [
|
|
1110
|
+
{ storeId: { $in: totalStores } },
|
|
1111
|
+
{ storeId: { $in: uniqueclusterStores } },
|
|
1112
|
+
],
|
|
1113
|
+
},
|
|
1114
|
+
},
|
|
1115
|
+
{
|
|
1116
|
+
$project: {
|
|
1117
|
+
_id: 0,
|
|
1118
|
+
storeId: '$storeId',
|
|
1119
|
+
storeName: '$storeName',
|
|
1120
|
+
},
|
|
1121
|
+
},
|
|
1122
|
+
];
|
|
1123
|
+
} else {
|
|
1124
|
+
let totalStores = await getStoresList( getUserEmail, getClientId, getUserType, getRole, req );
|
|
1125
|
+
storeQuery = [
|
|
1126
|
+
{
|
|
1127
|
+
$match: {
|
|
1128
|
+
$and: [
|
|
1129
|
+
{ storeId: { $in: totalStores } },
|
|
1130
|
+
],
|
|
1131
|
+
},
|
|
1132
|
+
},
|
|
1133
|
+
{
|
|
1134
|
+
$project: {
|
|
1135
|
+
_id: 0,
|
|
1136
|
+
storeId: '$storeId',
|
|
1137
|
+
storeName: '$storeName',
|
|
1138
|
+
},
|
|
1139
|
+
},
|
|
1140
|
+
];
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
const storeList = await aggregateStore( storeQuery );
|
|
1144
|
+
if ( storeList && storeList.length > 0 ) {
|
|
1145
|
+
return res.sendSuccess( { storesData: storeList } );
|
|
1146
|
+
} else {
|
|
1147
|
+
return res.sendError( 'No Stores', 400 );
|
|
1148
|
+
}
|
|
1149
|
+
} else {
|
|
1150
|
+
return res.sendError( 'No Stores', 400 );
|
|
1151
|
+
}
|
|
1152
|
+
} catch ( error ) {
|
|
1153
|
+
logger.error( { error: error, message: req.query, function: 'headerStoresV2' } );
|
|
1154
|
+
return res.sendError( { error: error }, 500 );
|
|
1155
|
+
}
|
|
1156
|
+
};
|
|
1157
|
+
|
|
1158
|
+
|
|
1159
|
+
async function getStoresList( getUserEmail, getClientId, getUserType, getRole, req ) {
|
|
1160
|
+
try {
|
|
1161
|
+
if ( getUserEmail && getUserEmail !='' && getClientId && getClientId !='' && getUserType && getUserType !='' && getRole && getRole!='' ) {
|
|
1162
|
+
let overAllStores = [];
|
|
1163
|
+
if ( getUserType == 'tango' ) {
|
|
1164
|
+
let getAllS = await getAssignedAllStores( getClientId );
|
|
1165
|
+
if ( getAllS && getAllS.length >0 ) {
|
|
1166
|
+
overAllStores = getAllS;
|
|
1167
|
+
}
|
|
1168
|
+
return overAllStores;
|
|
1169
|
+
} else if ( getUserType == 'client' ) {
|
|
1170
|
+
if ( getRole == 'superadmin' ) {
|
|
1171
|
+
let getAllS = await getAssignedAllStores( getClientId );
|
|
1172
|
+
if ( getAllS && getAllS.length >0 ) {
|
|
1173
|
+
overAllStores = getAllS;
|
|
1174
|
+
}
|
|
1175
|
+
return overAllStores;
|
|
1176
|
+
} else {
|
|
1177
|
+
return req.body.assignedStores;
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
} else {
|
|
1181
|
+
return false;
|
|
1182
|
+
}
|
|
1183
|
+
} catch ( error ) {
|
|
1184
|
+
logger.error( { error: error, message: req.query, function: 'getAllStores' } );
|
|
1185
|
+
}
|
|
1186
|
+
};
|
|
1187
|
+
|
|
864
1188
|
|
|
865
1189
|
async function getAllStores( getUserEmail, getClientId, getUserType, getRole ) {
|
|
866
1190
|
try {
|
|
@@ -1063,6 +1387,59 @@ async function getAssignedAllStores( userClientId ) {
|
|
|
1063
1387
|
}
|
|
1064
1388
|
}
|
|
1065
1389
|
|
|
1390
|
+
|
|
1391
|
+
async function getClusterStores( userClientId, ClusterList ) {
|
|
1392
|
+
try {
|
|
1393
|
+
if ( userClientId && userClientId !='' && ClusterList && ClusterList.length >0 ) {
|
|
1394
|
+
let ClusterQuery = [
|
|
1395
|
+
{
|
|
1396
|
+
$match: {
|
|
1397
|
+
$and: [
|
|
1398
|
+
{ clientId: { $eq: userClientId } },
|
|
1399
|
+
{ clusterName: { $in: ClusterList } },
|
|
1400
|
+
],
|
|
1401
|
+
},
|
|
1402
|
+
},
|
|
1403
|
+
{
|
|
1404
|
+
$unwind: {
|
|
1405
|
+
path: '$storeList', preserveNullAndEmptyArrays: true,
|
|
1406
|
+
},
|
|
1407
|
+
},
|
|
1408
|
+
{
|
|
1409
|
+
$group: {
|
|
1410
|
+
_id: null,
|
|
1411
|
+
storesList: { $push: '$stores' },
|
|
1412
|
+
},
|
|
1413
|
+
},
|
|
1414
|
+
{
|
|
1415
|
+
$project: {
|
|
1416
|
+
storesList: {
|
|
1417
|
+
$reduce: {
|
|
1418
|
+
input: '$storesList', // Merge arrays using $reduce
|
|
1419
|
+
initialValue: [],
|
|
1420
|
+
in: { $concatArrays: [ '$$value', '$$this' ] },
|
|
1421
|
+
},
|
|
1422
|
+
},
|
|
1423
|
+
},
|
|
1424
|
+
},
|
|
1425
|
+
];
|
|
1426
|
+
const clusterStoreList = await aggregateCluster( ClusterQuery );
|
|
1427
|
+
if ( clusterStoreList && clusterStoreList.length>0 && clusterStoreList[0]?.storesList.length > 0 ) {
|
|
1428
|
+
let storeIds = clusterStoreList[0].storesList.map( ( data ) => data.storeId );
|
|
1429
|
+
let uniqueStores = [ ...new Set( storeIds ) ];
|
|
1430
|
+
return uniqueStores;
|
|
1431
|
+
} else {
|
|
1432
|
+
return false;
|
|
1433
|
+
}
|
|
1434
|
+
} else {
|
|
1435
|
+
return false;
|
|
1436
|
+
}
|
|
1437
|
+
} catch ( error ) {
|
|
1438
|
+
logger.error( { error: error, message: data, function: 'getClusterStores' } );
|
|
1439
|
+
return false;
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1066
1443
|
async function getGroupStores( userClientId, groupList ) {
|
|
1067
1444
|
try {
|
|
1068
1445
|
if ( userClientId && userClientId !='' && groupList && groupList.length >0 ) {
|
|
@@ -1103,16 +1480,21 @@ async function getGroupStores( userClientId, groupList ) {
|
|
|
1103
1480
|
}
|
|
1104
1481
|
}
|
|
1105
1482
|
|
|
1106
|
-
async function getLocationStores( userClientId, cityList ) {
|
|
1483
|
+
async function getLocationStores( userClientId, cityList, req ) {
|
|
1107
1484
|
try {
|
|
1108
1485
|
if ( userClientId && userClientId !='' && cityList && cityList.length >0 ) {
|
|
1486
|
+
let filter = [
|
|
1487
|
+
{ clientId: { $eq: userClientId } },
|
|
1488
|
+
{ 'storeProfile.city': { $in: cityList } },
|
|
1489
|
+
];
|
|
1490
|
+
if ( req.body.assignedStores&&req.body.assignedStores.length>0 ) {
|
|
1491
|
+
filter.push( { storeId: { $in: req.body.assignedStores } } );
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1109
1494
|
let storeQuery = [
|
|
1110
1495
|
{
|
|
1111
1496
|
$match: {
|
|
1112
|
-
$and:
|
|
1113
|
-
{ clientId: { $eq: userClientId } },
|
|
1114
|
-
{ 'storeProfile.city': { $in: cityList } },
|
|
1115
|
-
],
|
|
1497
|
+
$and: filter,
|
|
1116
1498
|
},
|
|
1117
1499
|
},
|
|
1118
1500
|
{
|
|
@@ -1132,6 +1514,44 @@ async function getLocationStores( userClientId, cityList ) {
|
|
|
1132
1514
|
if ( cityStoreList && cityStoreList.length>0 && cityStoreList[0]?.stores.length > 0 ) {
|
|
1133
1515
|
let uniqueStores = [ ...new Set( cityStoreList[0].stores ) ];
|
|
1134
1516
|
return uniqueStores;
|
|
1517
|
+
} else {
|
|
1518
|
+
return [];
|
|
1519
|
+
}
|
|
1520
|
+
} else {
|
|
1521
|
+
return [];
|
|
1522
|
+
}
|
|
1523
|
+
} catch ( error ) {
|
|
1524
|
+
logger.error( { error: error, function: 'getLocationStores' } );
|
|
1525
|
+
return false;
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
async function getclusterList( userClientId, req ) {
|
|
1529
|
+
try {
|
|
1530
|
+
if ( userClientId && userClientId !='' ) {
|
|
1531
|
+
let filter = [
|
|
1532
|
+
{ clientId: { $eq: userClientId } },
|
|
1533
|
+
];
|
|
1534
|
+
if ( req.body.assignedStores&&req.body.assignedStores.length>0 ) {
|
|
1535
|
+
filter.push( { 'stores.storeId': { $in: req.body.assignedStores } } );
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
let clusterQuery = [
|
|
1539
|
+
{
|
|
1540
|
+
$match: {
|
|
1541
|
+
$and: filter,
|
|
1542
|
+
},
|
|
1543
|
+
},
|
|
1544
|
+
{
|
|
1545
|
+
$group: {
|
|
1546
|
+
_id: null,
|
|
1547
|
+
clusterName: { $push: '$clusterName' },
|
|
1548
|
+
},
|
|
1549
|
+
},
|
|
1550
|
+
];
|
|
1551
|
+
const clusterIds = await aggregateCluster( clusterQuery );
|
|
1552
|
+
if ( clusterIds && clusterIds.length>0 && clusterIds[0]?.clusterName.length > 0 ) {
|
|
1553
|
+
let uniqueclusterIds = [ ...new Set( clusterIds[0].clusterName ) ];
|
|
1554
|
+
return uniqueclusterIds;
|
|
1135
1555
|
} else {
|
|
1136
1556
|
return false;
|
|
1137
1557
|
}
|
|
@@ -1139,11 +1559,10 @@ async function getLocationStores( userClientId, cityList ) {
|
|
|
1139
1559
|
return false;
|
|
1140
1560
|
}
|
|
1141
1561
|
} catch ( error ) {
|
|
1142
|
-
logger.error( { error: error,
|
|
1562
|
+
logger.error( { error: error, function: 'getclusterList' } );
|
|
1143
1563
|
return false;
|
|
1144
1564
|
}
|
|
1145
1565
|
}
|
|
1146
|
-
|
|
1147
1566
|
async function getGroupIds( userClientId ) {
|
|
1148
1567
|
try {
|
|
1149
1568
|
if ( userClientId && userClientId !='' ) {
|
|
@@ -1218,10 +1637,10 @@ async function getAssignedGroupIds( userClientId, getUserEmail ) {
|
|
|
1218
1637
|
}
|
|
1219
1638
|
}
|
|
1220
1639
|
|
|
1221
|
-
async function getCityStores( userClientId, getUserEmail, getRole, requestCity, getUserType ) {
|
|
1640
|
+
async function getCityStores( userClientId, getUserEmail, getRole, requestCity, getUserType, req ) {
|
|
1222
1641
|
try {
|
|
1223
1642
|
if ( userClientId && userClientId !='' && getUserEmail && getUserEmail !='', getRole && getRole !='', requestCity && requestCity.length>0 ) {
|
|
1224
|
-
let cityStores = await getLocationStores( userClientId, requestCity );
|
|
1643
|
+
let cityStores = await getLocationStores( userClientId, requestCity, req );
|
|
1225
1644
|
if ( cityStores && cityStores.length > 0 ) {
|
|
1226
1645
|
let storeGroups = await getGroupStoresIds( userClientId, cityStores, getRole, getUserType, getUserEmail );
|
|
1227
1646
|
if ( storeGroups && storeGroups.length > 0 ) {
|
|
@@ -202,10 +202,17 @@ export const validateHeaderSchema = joi.object( {
|
|
|
202
202
|
group: joi.array().required(),
|
|
203
203
|
} );
|
|
204
204
|
|
|
205
|
+
export const validateHeaderSchemav2 = joi.object( {
|
|
206
|
+
clientId: joi.string().required(),
|
|
207
|
+
city: joi.array().required(),
|
|
208
|
+
clusters: joi.array().required(),
|
|
209
|
+
} );
|
|
205
210
|
export const validateHeaderParams = {
|
|
206
211
|
body: validateHeaderSchema,
|
|
207
212
|
};
|
|
208
|
-
|
|
213
|
+
export const validateHeaderParamsv2 = {
|
|
214
|
+
body: validateHeaderSchemav2,
|
|
215
|
+
};
|
|
209
216
|
export const getMyProductSchema = joi.object( {
|
|
210
217
|
clientId: joi.string().required(),
|
|
211
218
|
storeId: joi.array().optional().empty(),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
|
-
import { validate, isAllowedSessionHandler,
|
|
2
|
+
import { validate, isAllowedSessionHandler, isAllowedClient, getAssinedStore } from 'tango-app-api-middleware';
|
|
3
3
|
import * as validationDtos from '../dtos/validation.dtos.js';
|
|
4
4
|
|
|
5
5
|
export const analysisTrafficRouter = express.Router();
|
|
@@ -54,6 +54,9 @@ import {
|
|
|
54
54
|
getMySubscription,
|
|
55
55
|
getStoreMapData,
|
|
56
56
|
funnelV1,
|
|
57
|
+
headerStoresV2,
|
|
58
|
+
headerClustersV2,
|
|
59
|
+
headerLocationsV2,
|
|
57
60
|
} from '../controllers/tangoTrafficV1.controllers.js';
|
|
58
61
|
|
|
59
62
|
|
|
@@ -80,117 +83,33 @@ analysisTrafficRouter
|
|
|
80
83
|
.post( '/headerLocations', headerLocations )
|
|
81
84
|
.post( '/headerGroups', headerGroups )
|
|
82
85
|
.post( '/headerStores', headerStores )
|
|
83
|
-
.post( '/cardsFunnel_v1', isAllowedSessionHandler, isAllowedClient,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
.post( '/
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
.post( '/
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
.post( '/
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
.post( '/
|
|
104
|
-
|
|
105
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
106
|
-
],
|
|
107
|
-
} ), validate( validationDtos.validateDensityDwellParams ), densityDwellV1 )
|
|
108
|
-
.post( '/overallCards_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
109
|
-
userType: [ 'tango', 'client' ], access: [
|
|
110
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
111
|
-
],
|
|
112
|
-
} ), validate( validationDtos.validateOverallCharParams ), overallCardsV1 )
|
|
113
|
-
.post( '/overallHourlyChart_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
114
|
-
userType: [ 'tango', 'client' ], access: [
|
|
115
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
116
|
-
],
|
|
117
|
-
} ), validate( validationDtos.validateOverallCharParams ), overallHourlyChartV1 )
|
|
118
|
-
.post( '/overallChart_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
119
|
-
userType: [ 'tango', 'client' ], access: [
|
|
120
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
121
|
-
],
|
|
122
|
-
} ), validate( validationDtos.validateOverallCharParams ), overallChartV1 )
|
|
123
|
-
.post( '/singleStoreChart_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
124
|
-
userType: [ 'tango', 'client' ], access: [
|
|
125
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
126
|
-
],
|
|
127
|
-
} ), validate( validationDtos.validateSingleStoreChartParams ), singleStoreChartV1 )
|
|
128
|
-
.post( '/demographicChart_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
129
|
-
userType: [ 'tango', 'client' ], access: [
|
|
130
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
131
|
-
],
|
|
132
|
-
} ), validate( validationDtos.validateDemographicChartParams ), demographicChartV1 )
|
|
133
|
-
.post( '/buyerChart_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
134
|
-
userType: [ 'tango', 'client' ], access: [
|
|
135
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
136
|
-
],
|
|
137
|
-
} ), validate( validationDtos.validateBuyerChartParams ), buyerChartV1 )
|
|
138
|
-
.post( '/footfallDirectoryFolders_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
139
|
-
userType: [ 'tango', 'client' ], access: [
|
|
140
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
141
|
-
],
|
|
142
|
-
} ), validate( validationDtos.validateFootfallDirectoryFoldersParams ), footfallDirectoryFoldersV1 )
|
|
143
|
-
.post( '/footfallDirectory_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
144
|
-
userType: [ 'tango', 'client' ], access: [
|
|
145
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
146
|
-
],
|
|
147
|
-
} ), validate( validationDtos.validateFootfallDirectoryParams ), footfallDirectoryV1 )
|
|
148
|
-
.post( '/summaryTable_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
149
|
-
userType: [ 'tango', 'client' ], access: [
|
|
150
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
151
|
-
],
|
|
152
|
-
} ), validate( validationDtos.validateSummaryTableParams ), summaryTableV1 )
|
|
153
|
-
.post( '/footfallTrend_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
154
|
-
userType: [ 'tango', 'client' ], access: [
|
|
155
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
156
|
-
],
|
|
157
|
-
} ), validate( validationDtos.validateFootfallTrendParams ), footfallTrendV1 )
|
|
158
|
-
.post( '/storeOperation_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
159
|
-
userType: [ 'tango', 'client' ], access: [
|
|
160
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
161
|
-
],
|
|
162
|
-
} ), validate( validationDtos.validateStoreOperationParams ), storeOperationV1 )
|
|
163
|
-
.post( '/performanceMatrix_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
164
|
-
userType: [ 'tango', 'client' ], access: [
|
|
165
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
166
|
-
],
|
|
167
|
-
} ), validate( validationDtos.validateperformanceMatrixParams ), performanceMatrixV1 )
|
|
168
|
-
.post( '/zoneDwellTimeSplit_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
169
|
-
userType: [ 'tango', 'client' ], access: [
|
|
170
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
171
|
-
],
|
|
172
|
-
} ), validate( validationDtos.validateStoreOperationParams ), zoneDwellTimeSplitV1 )
|
|
173
|
-
.post( '/storesMap_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
174
|
-
userType: [ 'tango', 'client' ], access: [
|
|
175
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
176
|
-
],
|
|
177
|
-
} ), validate( validationDtos.validateStoresMapParams ), storesMapV1 )
|
|
178
|
-
.post( '/headerLocations_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
179
|
-
userType: [ 'tango', 'client' ], access: [
|
|
180
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
181
|
-
],
|
|
182
|
-
} ), validate( validationDtos.validateHeaderParams ), headerLocationsV1 )
|
|
183
|
-
.post( '/headerGroups_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
184
|
-
userType: [ 'tango', 'client' ], access: [
|
|
185
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
186
|
-
],
|
|
187
|
-
} ), validate( validationDtos.validateHeaderParams ), headerGroupsV1 )
|
|
188
|
-
.post( '/headerStores_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
189
|
-
userType: [ 'tango', 'client' ], access: [
|
|
190
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
191
|
-
],
|
|
192
|
-
} ), validate( validationDtos.validateHeaderParams ), headerStoresV1 )
|
|
86
|
+
.post( '/cardsFunnel_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateCardFunnelParams ), cardsFunnelV1 )
|
|
87
|
+
.post( '/funnel_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateCardFunnelParams ), funnelV1 )
|
|
88
|
+
.post( '/cardsGraphs_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateCardGraphParams ), cardsGraphsV1 )
|
|
89
|
+
.post( '/recapVideo_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateRecapVideoParams ), recapVideoV1 )
|
|
90
|
+
.post( '/densityDwell_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateDensityDwellParams ), densityDwellV1 )
|
|
91
|
+
.post( '/overallCards_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateOverallCharParams ), overallCardsV1 )
|
|
92
|
+
.post( '/overallHourlyChart_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateOverallCharParams ), overallHourlyChartV1 )
|
|
93
|
+
.post( '/overallChart_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateOverallCharParams ), overallChartV1 )
|
|
94
|
+
.post( '/singleStoreChart_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateSingleStoreChartParams ), singleStoreChartV1 )
|
|
95
|
+
.post( '/demographicChart_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateDemographicChartParams ), demographicChartV1 )
|
|
96
|
+
.post( '/buyerChart_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateBuyerChartParams ), buyerChartV1 )
|
|
97
|
+
.post( '/footfallDirectoryFolders_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateFootfallDirectoryFoldersParams ), footfallDirectoryFoldersV1 )
|
|
98
|
+
.post( '/footfallDirectory_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateFootfallDirectoryParams ), footfallDirectoryV1 )
|
|
99
|
+
.post( '/summaryTable_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateSummaryTableParams ), summaryTableV1 )
|
|
100
|
+
.post( '/footfallTrend_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateFootfallTrendParams ), footfallTrendV1 )
|
|
101
|
+
.post( '/storeOperation_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateStoreOperationParams ), storeOperationV1 )
|
|
102
|
+
.post( '/performanceMatrix_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateperformanceMatrixParams ), performanceMatrixV1 )
|
|
103
|
+
.post( '/zoneDwellTimeSplit_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateStoreOperationParams ), zoneDwellTimeSplitV1 )
|
|
104
|
+
.post( '/storesMap_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateStoresMapParams ), storesMapV1 )
|
|
105
|
+
.post( '/headerLocations_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateHeaderParams ), headerLocationsV1 )
|
|
106
|
+
.post( '/headerGroups_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateHeaderParams ), headerGroupsV1 )
|
|
107
|
+
.post( '/headerStores_v1', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateHeaderParams ), headerStoresV1 )
|
|
193
108
|
.post( '/getMySubscription', isAllowedSessionHandler, validate( validationDtos.getMyProductParams ), getMySubscription )
|
|
194
|
-
.post( '/getStoreMapData', isAllowedSessionHandler, validate( validationDtos.getStoreCameraImageParams ), getStoreMapData )
|
|
109
|
+
.post( '/getStoreMapData', isAllowedSessionHandler, validate( validationDtos.getStoreCameraImageParams ), getStoreMapData )
|
|
110
|
+
.post( '/headerStores_v2', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateHeaderParamsv2 ), getAssinedStore, headerStoresV2 )
|
|
111
|
+
.post( '/headercluster_v2', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateHeaderParams ), getAssinedStore, headerClustersV2 )
|
|
112
|
+
.post( '/headerLocations_v2', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateHeaderParams ), getAssinedStore, headerLocationsV2 );
|
|
113
|
+
|
|
195
114
|
|
|
196
115
|
export default analysisTrafficRouter;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import clusterModel from 'tango-api-schema/schema/cluster.model.js';
|
|
2
|
+
|
|
3
|
+
export async function updateOneCluster( query, record ) {
|
|
4
|
+
return await clusterModel.updateOne( query, { $set: record } );
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export async function updateCluster( query, record ) {
|
|
8
|
+
return await clusterModel.updateMany( query, record );
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export async function aggregateCluster( query ) {
|
|
12
|
+
return await clusterModel.aggregate( query );
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export async function findOneCluster( query ={}, field={} ) {
|
|
16
|
+
return await clusterModel.findOne( query, field );
|
|
17
|
+
};
|
|
18
|
+
export async function deleteCluster( query ={} ) {
|
|
19
|
+
return await clusterModel.deleteOne( query );
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export async function createclusterModel( data ) {
|
|
23
|
+
return await clusterModel.create( data );
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export async function findcluster( query, project ) {
|
|
27
|
+
return await clusterModel.find( query, project );
|
|
28
|
+
};
|