tango-app-api-analysis-traffic 3.0.0-alpha.33 → 3.0.0-alpha.35
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.35",
|
|
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';
|
|
@@ -62,6 +63,33 @@ export const cardsFunnelV1 = async ( req, res ) => {
|
|
|
62
63
|
}
|
|
63
64
|
};
|
|
64
65
|
|
|
66
|
+
export const funnelV1 = async ( req, res ) => {
|
|
67
|
+
try {
|
|
68
|
+
let reqestData = req.body;
|
|
69
|
+
let getClientData = await getClientConfig( reqestData.clientId );
|
|
70
|
+
if ( !getClientData ) {
|
|
71
|
+
return res.sendError( 'Invalid Client Id', 400 );
|
|
72
|
+
}
|
|
73
|
+
reqestData.featureConfigs = getClientData.featureConfigs;
|
|
74
|
+
reqestData.currency = getClientData.paymentInvoice?.currencyType || 'inr';
|
|
75
|
+
reqestData.revenue = getClientData.averageTransactionValue || '0';
|
|
76
|
+
let LamdaURL = 'https://k3mv4jr6w7er4tn3ku2kkdgdha0ovyog.lambda-url.ap-south-1.on.aws/';
|
|
77
|
+
let resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
78
|
+
if ( resultData ) {
|
|
79
|
+
if ( resultData.status_code == '200' ) {
|
|
80
|
+
return res.sendSuccess( resultData );
|
|
81
|
+
} else {
|
|
82
|
+
return res.sendError( 'No Content', 204 );
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
return res.sendError( 'No Content', 204 );
|
|
86
|
+
}
|
|
87
|
+
} catch ( error ) {
|
|
88
|
+
logger.error( { error: error, message: req.query, function: 'funnelV1' } );
|
|
89
|
+
return res.sendError( { error: error }, 500 );
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
65
93
|
export const cardsGraphsV1 = async ( req, res ) => {
|
|
66
94
|
try {
|
|
67
95
|
let reqestData = req.body;
|
|
@@ -655,7 +683,56 @@ export const headerLocationsV1 = async ( req, res ) => {
|
|
|
655
683
|
return res.sendError( { error: error }, 500 );
|
|
656
684
|
}
|
|
657
685
|
};
|
|
658
|
-
|
|
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
|
+
};
|
|
659
736
|
export const headerGroupsV1 = async ( req, res ) => {
|
|
660
737
|
try {
|
|
661
738
|
let requestData = req.body;
|
|
@@ -664,7 +741,7 @@ export const headerGroupsV1 = async ( req, res ) => {
|
|
|
664
741
|
let getRole = req.user.role;
|
|
665
742
|
let groupIds;
|
|
666
743
|
if ( requestData.city && requestData.city.length>0 ) {
|
|
667
|
-
let getGroupIds = await getCityStores( requestData.clientId, getUserEmail, getRole, requestData.city, getUserType );
|
|
744
|
+
let getGroupIds = await getCityStores( requestData.clientId, getUserEmail, getRole, requestData.city, getUserType, req );
|
|
668
745
|
if ( getGroupIds && getGroupIds.length>0 ) {
|
|
669
746
|
groupIds = getGroupIds;
|
|
670
747
|
} else {
|
|
@@ -730,7 +807,141 @@ export const headerGroupsV1 = async ( req, res ) => {
|
|
|
730
807
|
return res.sendError( { error: error }, 500 );
|
|
731
808
|
}
|
|
732
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
|
+
} else if ( getUserType == 'client' ) {
|
|
828
|
+
if ( getRole == 'superadmin' ) {
|
|
829
|
+
clusterNames = await getclusterList( requestData.clientId, req );
|
|
830
|
+
} else {
|
|
831
|
+
clusterNames = await getclusterList( requestData.clientId, req );
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
const dataObjects = clusterNames.map( ( item ) => ( { groupName: item } ) );
|
|
836
|
+
res.sendSuccess( { groupData: dataObjects } );
|
|
837
|
+
} catch ( error ) {
|
|
838
|
+
logger.error( { error: error, message: req.query, function: 'headerClustersV2' } );
|
|
839
|
+
return res.sendError( { error: error }, 500 );
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
|
|
733
843
|
|
|
844
|
+
async function getCityClusters( userClientId, getUserEmail, getRole, requestCity, getUserType, req ) {
|
|
845
|
+
try {
|
|
846
|
+
if ( userClientId && userClientId !='' && getUserEmail && getUserEmail !='', getRole && getRole !='', requestCity && requestCity.length>0 ) {
|
|
847
|
+
let cityStores = await getLocationStores( userClientId, requestCity, req );
|
|
848
|
+
if ( cityStores && cityStores.length > 0 ) {
|
|
849
|
+
let storeGroups = await getClusterStoresIds( userClientId, cityStores, getRole, getUserType, getUserEmail );
|
|
850
|
+
if ( storeGroups && storeGroups.length > 0 ) {
|
|
851
|
+
return storeGroups;
|
|
852
|
+
} else {
|
|
853
|
+
return false;
|
|
854
|
+
}
|
|
855
|
+
} else {
|
|
856
|
+
return false;
|
|
857
|
+
}
|
|
858
|
+
} else {
|
|
859
|
+
return false;
|
|
860
|
+
}
|
|
861
|
+
} catch ( error ) {
|
|
862
|
+
logger.error( { error: error, function: 'getCityClusters' } );
|
|
863
|
+
return false;
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
async function getClusterStoresIds( userClientId, storeIds, getRole, getUserType, getUserEmail ) {
|
|
867
|
+
try {
|
|
868
|
+
if ( userClientId && userClientId !='' && storeIds && storeIds !='' && getRole && getRole !='' && getUserType && getUserType !='', getUserEmail && getUserEmail !='' ) {
|
|
869
|
+
let clusterQuery = [];
|
|
870
|
+
if ( getUserType == 'client' ) {
|
|
871
|
+
if ( getRole == 'superadmin' ) {
|
|
872
|
+
clusterQuery = [
|
|
873
|
+
{
|
|
874
|
+
$match: {
|
|
875
|
+
$and: [
|
|
876
|
+
{ clientId: { $eq: userClientId } },
|
|
877
|
+
{ 'stores.storeId': { $in: storeIds } },
|
|
878
|
+
],
|
|
879
|
+
},
|
|
880
|
+
},
|
|
881
|
+
{
|
|
882
|
+
$group: {
|
|
883
|
+
_id: null,
|
|
884
|
+
clusterName: { $push: '$clusterName' },
|
|
885
|
+
},
|
|
886
|
+
},
|
|
887
|
+
];
|
|
888
|
+
} else {
|
|
889
|
+
let getAssignedGroupIds = [
|
|
890
|
+
{
|
|
891
|
+
$match: {
|
|
892
|
+
$and: [
|
|
893
|
+
{ clientId: { $eq: userClientId } },
|
|
894
|
+
{ 'stores.storeId': { $in: storeIds } },
|
|
895
|
+
],
|
|
896
|
+
},
|
|
897
|
+
},
|
|
898
|
+
{
|
|
899
|
+
$group: {
|
|
900
|
+
_id: null,
|
|
901
|
+
clusterName: { $push: '$clusterName' },
|
|
902
|
+
},
|
|
903
|
+
},
|
|
904
|
+
];
|
|
905
|
+
const assignedclusters = await aggregateCluster( getAssignedGroupIds );
|
|
906
|
+
if ( assignedclusters && assignedclusters.length>0 && assignedclusters[0]?.clusterName.length > 0 ) {
|
|
907
|
+
let uniqueclusters = [ ...new Set( assignedclusters[0].clusterName ) ];
|
|
908
|
+
return uniqueclusters;
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
} else if ( getUserType == 'tango' ) {
|
|
912
|
+
clusterQuery = [
|
|
913
|
+
{
|
|
914
|
+
$match: {
|
|
915
|
+
$and: [
|
|
916
|
+
{ clientId: { $eq: userClientId } },
|
|
917
|
+
{ 'stores.storeId': { $in: storeIds } },
|
|
918
|
+
],
|
|
919
|
+
},
|
|
920
|
+
},
|
|
921
|
+
{
|
|
922
|
+
$group: {
|
|
923
|
+
_id: null,
|
|
924
|
+
clusterName: { $push: '$clusterName' },
|
|
925
|
+
},
|
|
926
|
+
},
|
|
927
|
+
];
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
const assignedclusters = await aggregateCluster( clusterQuery );
|
|
931
|
+
if ( assignedclusters && assignedclusters.length>0 && assignedclusters[0]?.clusterName.length > 0 ) {
|
|
932
|
+
let uniqueclusters = [ ...new Set( assignedclusters[0].clusterName ) ];
|
|
933
|
+
return uniqueclusters;
|
|
934
|
+
} else {
|
|
935
|
+
return false;
|
|
936
|
+
}
|
|
937
|
+
} else {
|
|
938
|
+
return false;
|
|
939
|
+
}
|
|
940
|
+
} catch ( error ) {
|
|
941
|
+
logger.error( { error: error, function: 'getGroupIds' } );
|
|
942
|
+
return false;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
734
945
|
export const headerStoresV1 = async ( req, res ) => {
|
|
735
946
|
try {
|
|
736
947
|
let reqestData = req.body;
|
|
@@ -834,6 +1045,140 @@ export const headerStoresV1 = async ( req, res ) => {
|
|
|
834
1045
|
return res.sendError( { error: error }, 500 );
|
|
835
1046
|
}
|
|
836
1047
|
};
|
|
1048
|
+
export const headerStoresV2 = async ( req, res ) => {
|
|
1049
|
+
try {
|
|
1050
|
+
let reqestData = req.body;
|
|
1051
|
+
let getUserEmail = req.user.email;
|
|
1052
|
+
let getUserType = req.user.userType;
|
|
1053
|
+
let getRole = req.user.role;
|
|
1054
|
+
let getClientId = reqestData.clientId;
|
|
1055
|
+
let totalStores = await getStoresList( getUserEmail, getClientId, getUserType, getRole, req );
|
|
1056
|
+
if ( totalStores && totalStores.length>0 ) {
|
|
1057
|
+
let storeQuery = [];
|
|
1058
|
+
if ( reqestData.city.length>0 && reqestData.clusters.length>0 ) {
|
|
1059
|
+
let unqueCityStores = await getLocationStores( getClientId, reqestData.city, req );
|
|
1060
|
+
let unqueGroupStores = await getClusterStores( getClientId, reqestData.clusters );
|
|
1061
|
+
storeQuery = [
|
|
1062
|
+
{
|
|
1063
|
+
$match: {
|
|
1064
|
+
$and: [
|
|
1065
|
+
{ storeId: { $in: totalStores } },
|
|
1066
|
+
{ storeId: { $in: unqueCityStores } },
|
|
1067
|
+
{ storeId: { $in: unqueGroupStores } },
|
|
1068
|
+
],
|
|
1069
|
+
},
|
|
1070
|
+
},
|
|
1071
|
+
{
|
|
1072
|
+
$project: {
|
|
1073
|
+
_id: 0,
|
|
1074
|
+
storeId: '$storeId',
|
|
1075
|
+
storeName: '$storeName',
|
|
1076
|
+
},
|
|
1077
|
+
},
|
|
1078
|
+
];
|
|
1079
|
+
} else if ( reqestData.city.length>0 ) {
|
|
1080
|
+
let uniqueCityStores = await getLocationStores( getClientId, reqestData.city, req );
|
|
1081
|
+
storeQuery = [
|
|
1082
|
+
{
|
|
1083
|
+
$match: {
|
|
1084
|
+
$and: [
|
|
1085
|
+
{ storeId: { $in: totalStores } },
|
|
1086
|
+
{ storeId: { $in: uniqueCityStores } },
|
|
1087
|
+
],
|
|
1088
|
+
},
|
|
1089
|
+
},
|
|
1090
|
+
{
|
|
1091
|
+
$project: {
|
|
1092
|
+
_id: 0,
|
|
1093
|
+
storeId: '$storeId',
|
|
1094
|
+
storeName: '$storeName',
|
|
1095
|
+
},
|
|
1096
|
+
},
|
|
1097
|
+
];
|
|
1098
|
+
} else if ( reqestData.clusters.length>0 ) {
|
|
1099
|
+
let uniqueclusterStores = await getClusterStores( getClientId, reqestData.clusters );
|
|
1100
|
+
storeQuery = [
|
|
1101
|
+
{
|
|
1102
|
+
$match: {
|
|
1103
|
+
$and: [
|
|
1104
|
+
{ storeId: { $in: totalStores } },
|
|
1105
|
+
{ storeId: { $in: uniqueclusterStores } },
|
|
1106
|
+
],
|
|
1107
|
+
},
|
|
1108
|
+
},
|
|
1109
|
+
{
|
|
1110
|
+
$project: {
|
|
1111
|
+
_id: 0,
|
|
1112
|
+
storeId: '$storeId',
|
|
1113
|
+
storeName: '$storeName',
|
|
1114
|
+
},
|
|
1115
|
+
},
|
|
1116
|
+
];
|
|
1117
|
+
} else {
|
|
1118
|
+
let totalStores = await getStoresList( getUserEmail, getClientId, getUserType, getRole, req );
|
|
1119
|
+
storeQuery = [
|
|
1120
|
+
{
|
|
1121
|
+
$match: {
|
|
1122
|
+
$and: [
|
|
1123
|
+
{ storeId: { $in: totalStores } },
|
|
1124
|
+
],
|
|
1125
|
+
},
|
|
1126
|
+
},
|
|
1127
|
+
{
|
|
1128
|
+
$project: {
|
|
1129
|
+
_id: 0,
|
|
1130
|
+
storeId: '$storeId',
|
|
1131
|
+
storeName: '$storeName',
|
|
1132
|
+
},
|
|
1133
|
+
},
|
|
1134
|
+
];
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
const storeList = await aggregateStore( storeQuery );
|
|
1138
|
+
if ( storeList && storeList.length > 0 ) {
|
|
1139
|
+
return res.sendSuccess( { storesData: storeList } );
|
|
1140
|
+
} else {
|
|
1141
|
+
return res.sendError( 'No Stores', 400 );
|
|
1142
|
+
}
|
|
1143
|
+
} else {
|
|
1144
|
+
return res.sendError( 'No Stores', 400 );
|
|
1145
|
+
}
|
|
1146
|
+
} catch ( error ) {
|
|
1147
|
+
logger.error( { error: error, message: req.query, function: 'headerStoresV2' } );
|
|
1148
|
+
return res.sendError( { error: error }, 500 );
|
|
1149
|
+
}
|
|
1150
|
+
};
|
|
1151
|
+
|
|
1152
|
+
|
|
1153
|
+
async function getStoresList( getUserEmail, getClientId, getUserType, getRole, req ) {
|
|
1154
|
+
try {
|
|
1155
|
+
if ( getUserEmail && getUserEmail !='' && getClientId && getClientId !='' && getUserType && getUserType !='' && getRole && getRole!='' ) {
|
|
1156
|
+
let overAllStores = [];
|
|
1157
|
+
if ( getUserType == 'tango' ) {
|
|
1158
|
+
let getAllS = await getAssignedAllStores( getClientId );
|
|
1159
|
+
if ( getAllS && getAllS.length >0 ) {
|
|
1160
|
+
overAllStores = getAllS;
|
|
1161
|
+
}
|
|
1162
|
+
return overAllStores;
|
|
1163
|
+
} else if ( getUserType == 'client' ) {
|
|
1164
|
+
if ( getRole == 'superadmin' ) {
|
|
1165
|
+
let getAllS = await getAssignedAllStores( getClientId );
|
|
1166
|
+
if ( getAllS && getAllS.length >0 ) {
|
|
1167
|
+
overAllStores = getAllS;
|
|
1168
|
+
}
|
|
1169
|
+
return overAllStores;
|
|
1170
|
+
} else {
|
|
1171
|
+
return req.body.assignedStores;
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
} else {
|
|
1175
|
+
return false;
|
|
1176
|
+
}
|
|
1177
|
+
} catch ( error ) {
|
|
1178
|
+
logger.error( { error: error, message: req.query, function: 'getAllStores' } );
|
|
1179
|
+
}
|
|
1180
|
+
};
|
|
1181
|
+
|
|
837
1182
|
|
|
838
1183
|
async function getAllStores( getUserEmail, getClientId, getUserType, getRole ) {
|
|
839
1184
|
try {
|
|
@@ -1036,6 +1381,59 @@ async function getAssignedAllStores( userClientId ) {
|
|
|
1036
1381
|
}
|
|
1037
1382
|
}
|
|
1038
1383
|
|
|
1384
|
+
|
|
1385
|
+
async function getClusterStores( userClientId, ClusterList ) {
|
|
1386
|
+
try {
|
|
1387
|
+
if ( userClientId && userClientId !='' && ClusterList && ClusterList.length >0 ) {
|
|
1388
|
+
let ClusterQuery = [
|
|
1389
|
+
{
|
|
1390
|
+
$match: {
|
|
1391
|
+
$and: [
|
|
1392
|
+
{ clientId: { $eq: userClientId } },
|
|
1393
|
+
{ clusterName: { $in: ClusterList } },
|
|
1394
|
+
],
|
|
1395
|
+
},
|
|
1396
|
+
},
|
|
1397
|
+
{
|
|
1398
|
+
$unwind: {
|
|
1399
|
+
path: '$storeList', preserveNullAndEmptyArrays: true,
|
|
1400
|
+
},
|
|
1401
|
+
},
|
|
1402
|
+
{
|
|
1403
|
+
$group: {
|
|
1404
|
+
_id: null,
|
|
1405
|
+
storesList: { $push: '$stores' },
|
|
1406
|
+
},
|
|
1407
|
+
},
|
|
1408
|
+
{
|
|
1409
|
+
$project: {
|
|
1410
|
+
storesList: {
|
|
1411
|
+
$reduce: {
|
|
1412
|
+
input: '$storesList', // Merge arrays using $reduce
|
|
1413
|
+
initialValue: [],
|
|
1414
|
+
in: { $concatArrays: [ '$$value', '$$this' ] },
|
|
1415
|
+
},
|
|
1416
|
+
},
|
|
1417
|
+
},
|
|
1418
|
+
},
|
|
1419
|
+
];
|
|
1420
|
+
const clusterStoreList = await aggregateCluster( ClusterQuery );
|
|
1421
|
+
if ( clusterStoreList && clusterStoreList.length>0 && clusterStoreList[0]?.storesList.length > 0 ) {
|
|
1422
|
+
let storeIds = clusterStoreList[0].storesList.map( ( data ) => data.storeId );
|
|
1423
|
+
let uniqueStores = [ ...new Set( storeIds ) ];
|
|
1424
|
+
return uniqueStores;
|
|
1425
|
+
} else {
|
|
1426
|
+
return false;
|
|
1427
|
+
}
|
|
1428
|
+
} else {
|
|
1429
|
+
return false;
|
|
1430
|
+
}
|
|
1431
|
+
} catch ( error ) {
|
|
1432
|
+
logger.error( { error: error, message: data, function: 'getClusterStores' } );
|
|
1433
|
+
return false;
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1039
1437
|
async function getGroupStores( userClientId, groupList ) {
|
|
1040
1438
|
try {
|
|
1041
1439
|
if ( userClientId && userClientId !='' && groupList && groupList.length >0 ) {
|
|
@@ -1076,16 +1474,21 @@ async function getGroupStores( userClientId, groupList ) {
|
|
|
1076
1474
|
}
|
|
1077
1475
|
}
|
|
1078
1476
|
|
|
1079
|
-
async function getLocationStores( userClientId, cityList ) {
|
|
1477
|
+
async function getLocationStores( userClientId, cityList, req ) {
|
|
1080
1478
|
try {
|
|
1081
1479
|
if ( userClientId && userClientId !='' && cityList && cityList.length >0 ) {
|
|
1480
|
+
let filter = [
|
|
1481
|
+
{ clientId: { $eq: userClientId } },
|
|
1482
|
+
{ 'storeProfile.city': { $in: cityList } },
|
|
1483
|
+
];
|
|
1484
|
+
if ( req.body.assignedStores&&req.body.assignedStores.length>0 ) {
|
|
1485
|
+
filter.push( { storeId: { $in: req.body.assignedStores } } );
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1082
1488
|
let storeQuery = [
|
|
1083
1489
|
{
|
|
1084
1490
|
$match: {
|
|
1085
|
-
$and:
|
|
1086
|
-
{ clientId: { $eq: userClientId } },
|
|
1087
|
-
{ 'storeProfile.city': { $in: cityList } },
|
|
1088
|
-
],
|
|
1491
|
+
$and: filter,
|
|
1089
1492
|
},
|
|
1090
1493
|
},
|
|
1091
1494
|
{
|
|
@@ -1105,6 +1508,40 @@ async function getLocationStores( userClientId, cityList ) {
|
|
|
1105
1508
|
if ( cityStoreList && cityStoreList.length>0 && cityStoreList[0]?.stores.length > 0 ) {
|
|
1106
1509
|
let uniqueStores = [ ...new Set( cityStoreList[0].stores ) ];
|
|
1107
1510
|
return uniqueStores;
|
|
1511
|
+
} else {
|
|
1512
|
+
return [];
|
|
1513
|
+
}
|
|
1514
|
+
} else {
|
|
1515
|
+
return [];
|
|
1516
|
+
}
|
|
1517
|
+
} catch ( error ) {
|
|
1518
|
+
logger.error( { error: error, function: 'getLocationStores' } );
|
|
1519
|
+
return false;
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
async function getclusterList( userClientId, req ) {
|
|
1523
|
+
try {
|
|
1524
|
+
if ( userClientId && userClientId !='' ) {
|
|
1525
|
+
let clusterQuery = [
|
|
1526
|
+
{
|
|
1527
|
+
$match: {
|
|
1528
|
+
$and: [
|
|
1529
|
+
{ clientId: { $eq: userClientId } },
|
|
1530
|
+
{ 'stores.storeId': { $in: req.body.assignedStores } },
|
|
1531
|
+
],
|
|
1532
|
+
},
|
|
1533
|
+
},
|
|
1534
|
+
{
|
|
1535
|
+
$group: {
|
|
1536
|
+
_id: null,
|
|
1537
|
+
clusterName: { $push: '$clusterName' },
|
|
1538
|
+
},
|
|
1539
|
+
},
|
|
1540
|
+
];
|
|
1541
|
+
const clusterIds = await aggregateCluster( clusterQuery );
|
|
1542
|
+
if ( clusterIds && clusterIds.length>0 && clusterIds[0]?.clusterName.length > 0 ) {
|
|
1543
|
+
let uniqueclusterIds = [ ...new Set( clusterIds[0].clusterName ) ];
|
|
1544
|
+
return uniqueclusterIds;
|
|
1108
1545
|
} else {
|
|
1109
1546
|
return false;
|
|
1110
1547
|
}
|
|
@@ -1112,11 +1549,10 @@ async function getLocationStores( userClientId, cityList ) {
|
|
|
1112
1549
|
return false;
|
|
1113
1550
|
}
|
|
1114
1551
|
} catch ( error ) {
|
|
1115
|
-
logger.error( { error: error,
|
|
1552
|
+
logger.error( { error: error, function: 'getclusterList' } );
|
|
1116
1553
|
return false;
|
|
1117
1554
|
}
|
|
1118
1555
|
}
|
|
1119
|
-
|
|
1120
1556
|
async function getGroupIds( userClientId ) {
|
|
1121
1557
|
try {
|
|
1122
1558
|
if ( userClientId && userClientId !='' ) {
|
|
@@ -1191,10 +1627,10 @@ async function getAssignedGroupIds( userClientId, getUserEmail ) {
|
|
|
1191
1627
|
}
|
|
1192
1628
|
}
|
|
1193
1629
|
|
|
1194
|
-
async function getCityStores( userClientId, getUserEmail, getRole, requestCity, getUserType ) {
|
|
1630
|
+
async function getCityStores( userClientId, getUserEmail, getRole, requestCity, getUserType, req ) {
|
|
1195
1631
|
try {
|
|
1196
1632
|
if ( userClientId && userClientId !='' && getUserEmail && getUserEmail !='', getRole && getRole !='', requestCity && requestCity.length>0 ) {
|
|
1197
|
-
let cityStores = await getLocationStores( userClientId, requestCity );
|
|
1633
|
+
let cityStores = await getLocationStores( userClientId, requestCity, req );
|
|
1198
1634
|
if ( cityStores && cityStores.length > 0 ) {
|
|
1199
1635
|
let storeGroups = await getGroupStoresIds( userClientId, cityStores, getRole, getUserType, getUserEmail );
|
|
1200
1636
|
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();
|
|
@@ -53,6 +53,10 @@ import {
|
|
|
53
53
|
headerGroupsV1,
|
|
54
54
|
getMySubscription,
|
|
55
55
|
getStoreMapData,
|
|
56
|
+
funnelV1,
|
|
57
|
+
headerStoresV2,
|
|
58
|
+
headerClustersV2,
|
|
59
|
+
headerLocationsV2,
|
|
56
60
|
} from '../controllers/tangoTrafficV1.controllers.js';
|
|
57
61
|
|
|
58
62
|
|
|
@@ -79,112 +83,33 @@ analysisTrafficRouter
|
|
|
79
83
|
.post( '/headerLocations', headerLocations )
|
|
80
84
|
.post( '/headerGroups', headerGroups )
|
|
81
85
|
.post( '/headerStores', headerStores )
|
|
82
|
-
.post( '/cardsFunnel_v1', isAllowedSessionHandler, isAllowedClient,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
.post( '/
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
.post( '/
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
.post( '/
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
.post( '/
|
|
103
|
-
|
|
104
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
105
|
-
],
|
|
106
|
-
} ), validate( validationDtos.validateOverallCharParams ), overallCardsV1 )
|
|
107
|
-
.post( '/overallHourlyChart_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
108
|
-
userType: [ 'tango', 'client' ], access: [
|
|
109
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
110
|
-
],
|
|
111
|
-
} ), validate( validationDtos.validateOverallCharParams ), overallHourlyChartV1 )
|
|
112
|
-
.post( '/overallChart_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
113
|
-
userType: [ 'tango', 'client' ], access: [
|
|
114
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
115
|
-
],
|
|
116
|
-
} ), validate( validationDtos.validateOverallCharParams ), overallChartV1 )
|
|
117
|
-
.post( '/singleStoreChart_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
118
|
-
userType: [ 'tango', 'client' ], access: [
|
|
119
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
120
|
-
],
|
|
121
|
-
} ), validate( validationDtos.validateSingleStoreChartParams ), singleStoreChartV1 )
|
|
122
|
-
.post( '/demographicChart_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
123
|
-
userType: [ 'tango', 'client' ], access: [
|
|
124
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
125
|
-
],
|
|
126
|
-
} ), validate( validationDtos.validateDemographicChartParams ), demographicChartV1 )
|
|
127
|
-
.post( '/buyerChart_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
128
|
-
userType: [ 'tango', 'client' ], access: [
|
|
129
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
130
|
-
],
|
|
131
|
-
} ), validate( validationDtos.validateBuyerChartParams ), buyerChartV1 )
|
|
132
|
-
.post( '/footfallDirectoryFolders_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
133
|
-
userType: [ 'tango', 'client' ], access: [
|
|
134
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
135
|
-
],
|
|
136
|
-
} ), validate( validationDtos.validateFootfallDirectoryFoldersParams ), footfallDirectoryFoldersV1 )
|
|
137
|
-
.post( '/footfallDirectory_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
138
|
-
userType: [ 'tango', 'client' ], access: [
|
|
139
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
140
|
-
],
|
|
141
|
-
} ), validate( validationDtos.validateFootfallDirectoryParams ), footfallDirectoryV1 )
|
|
142
|
-
.post( '/summaryTable_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
143
|
-
userType: [ 'tango', 'client' ], access: [
|
|
144
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
145
|
-
],
|
|
146
|
-
} ), validate( validationDtos.validateSummaryTableParams ), summaryTableV1 )
|
|
147
|
-
.post( '/footfallTrend_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
148
|
-
userType: [ 'tango', 'client' ], access: [
|
|
149
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
150
|
-
],
|
|
151
|
-
} ), validate( validationDtos.validateFootfallTrendParams ), footfallTrendV1 )
|
|
152
|
-
.post( '/storeOperation_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
153
|
-
userType: [ 'tango', 'client' ], access: [
|
|
154
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
155
|
-
],
|
|
156
|
-
} ), validate( validationDtos.validateStoreOperationParams ), storeOperationV1 )
|
|
157
|
-
.post( '/performanceMatrix_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
158
|
-
userType: [ 'tango', 'client' ], access: [
|
|
159
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
160
|
-
],
|
|
161
|
-
} ), validate( validationDtos.validateperformanceMatrixParams ), performanceMatrixV1 )
|
|
162
|
-
.post( '/zoneDwellTimeSplit_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
163
|
-
userType: [ 'tango', 'client' ], access: [
|
|
164
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
165
|
-
],
|
|
166
|
-
} ), validate( validationDtos.validateStoreOperationParams ), zoneDwellTimeSplitV1 )
|
|
167
|
-
.post( '/storesMap_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
168
|
-
userType: [ 'tango', 'client' ], access: [
|
|
169
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
170
|
-
],
|
|
171
|
-
} ), validate( validationDtos.validateStoresMapParams ), storesMapV1 )
|
|
172
|
-
.post( '/headerLocations_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
173
|
-
userType: [ 'tango', 'client' ], access: [
|
|
174
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
175
|
-
],
|
|
176
|
-
} ), validate( validationDtos.validateHeaderParams ), headerLocationsV1 )
|
|
177
|
-
.post( '/headerGroups_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
178
|
-
userType: [ 'tango', 'client' ], access: [
|
|
179
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
180
|
-
],
|
|
181
|
-
} ), validate( validationDtos.validateHeaderParams ), headerGroupsV1 )
|
|
182
|
-
.post( '/headerStores_v1', isAllowedSessionHandler, isAllowedClient, authorize( {
|
|
183
|
-
userType: [ 'tango', 'client' ], access: [
|
|
184
|
-
{ featureName: 'analytics', name: 'tangoTraffic', permissions: [ 'isView' ] },
|
|
185
|
-
],
|
|
186
|
-
} ), 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 )
|
|
187
108
|
.post( '/getMySubscription', isAllowedSessionHandler, validate( validationDtos.getMyProductParams ), getMySubscription )
|
|
188
|
-
.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
|
+
|
|
189
114
|
|
|
190
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
|
+
};
|