tango-app-api-analysis-zone 3.0.0-alpha.1
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/.eslintrc.cjs +41 -0
- package/README.md +29 -0
- package/index.js +6 -0
- package/package.json +36 -0
- package/src/controllers/analyseZone.controllers.js +624 -0
- package/src/routes/analyseZone.js +26 -0
- package/src/services/stores.service.js +9 -0
package/.eslintrc.cjs
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
|
|
2
|
+
module.exports = {
|
|
3
|
+
'env': {
|
|
4
|
+
'es2021': true,
|
|
5
|
+
'node': true,
|
|
6
|
+
},
|
|
7
|
+
'extends': 'google',
|
|
8
|
+
'overrides': [
|
|
9
|
+
{
|
|
10
|
+
'env': {
|
|
11
|
+
'node': true,
|
|
12
|
+
},
|
|
13
|
+
'files': [
|
|
14
|
+
'.eslintrc.{js,cjs}',
|
|
15
|
+
],
|
|
16
|
+
'parserOptions': {
|
|
17
|
+
'sourceType': 'script',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
'parserOptions': {
|
|
22
|
+
'ecmaVersion': 'latest',
|
|
23
|
+
'sourceType': 'module',
|
|
24
|
+
},
|
|
25
|
+
'rules': {
|
|
26
|
+
'linebreak-style': [ 'error', 'windows' ],
|
|
27
|
+
'require-jsdoc': 'off',
|
|
28
|
+
'arrow-spacing': 'error',
|
|
29
|
+
'key-spacing': [ 'error', { 'beforeColon': false, 'afterColon': true } ],
|
|
30
|
+
'object-curly-spacing': [ 'error', 'always' ],
|
|
31
|
+
'space-in-parens': [ 'error', 'always' ],
|
|
32
|
+
'keyword-spacing': 'error',
|
|
33
|
+
'array-bracket-spacing': [ 'error', 'always' ],
|
|
34
|
+
'spaced-comment': [ 'error', 'always' ],
|
|
35
|
+
'max-len': [ 'error', { 'code': 700 } ],
|
|
36
|
+
'no-unused-vars': 'error',
|
|
37
|
+
'new-cap': [ 'error', { 'newIsCap': true, 'capIsNew': false } ],
|
|
38
|
+
'prefer-const': 'off',
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# README #
|
|
2
|
+
|
|
3
|
+
This README would normally document whatever steps are necessary to get your application up and running.
|
|
4
|
+
|
|
5
|
+
### What is this repository for? ###
|
|
6
|
+
|
|
7
|
+
* Quick summary
|
|
8
|
+
* Version
|
|
9
|
+
* [Learn Markdown](https://bitbucket.org/tutorials/markdowndemo)
|
|
10
|
+
|
|
11
|
+
### How do I get set up? ###
|
|
12
|
+
|
|
13
|
+
* Summary of set up
|
|
14
|
+
* Configuration
|
|
15
|
+
* Dependencies
|
|
16
|
+
* Database configuration
|
|
17
|
+
* How to run tests
|
|
18
|
+
* Deployment instructions
|
|
19
|
+
|
|
20
|
+
### Contribution guidelines ###
|
|
21
|
+
|
|
22
|
+
* Writing tests
|
|
23
|
+
* Code review
|
|
24
|
+
* Other guidelines
|
|
25
|
+
|
|
26
|
+
### Who do I talk to? ###
|
|
27
|
+
|
|
28
|
+
* Repo owner or admin
|
|
29
|
+
* Other community or team contact
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tango-app-api-analysis-zone",
|
|
3
|
+
"version": "3.0.0-alpha.1",
|
|
4
|
+
"description": "zone Analysis",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "nodemon --exec \"eslint --fix . && node index.js\""
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=18.10.0"
|
|
12
|
+
},
|
|
13
|
+
"author": "praveenraj",
|
|
14
|
+
"license": "ISC",
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"aws-sdk": "^2.1665.0",
|
|
17
|
+
"dotenv": "^16.4.5",
|
|
18
|
+
"express": "^4.19.2",
|
|
19
|
+
"handlebars": "^4.7.8",
|
|
20
|
+
"lodash": "^4.17.21",
|
|
21
|
+
"mongodb": "^6.8.0",
|
|
22
|
+
"nodemon": "^3.1.4",
|
|
23
|
+
"tango-api-schema": "^2.0.131",
|
|
24
|
+
"tango-app-api-middleware": "^3.1.26",
|
|
25
|
+
"winston": "^3.13.1",
|
|
26
|
+
"winston-daily-rotate-file": "^5.0.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"eslint": "^8.57.0",
|
|
30
|
+
"eslint-config-google": "^0.14.0",
|
|
31
|
+
"eslint-config-semistandard": "^17.0.0",
|
|
32
|
+
"eslint-config-standard": "^17.1.0",
|
|
33
|
+
"eslint-plugin-import": "^2.29.1",
|
|
34
|
+
"eslint-plugin-promise": "^6.6.0"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,624 @@
|
|
|
1
|
+
import { logger } from 'tango-app-api-middleware';
|
|
2
|
+
|
|
3
|
+
export const welcome = async ( req, res ) => {
|
|
4
|
+
try {
|
|
5
|
+
let result = {
|
|
6
|
+
'Message': 'Welcome',
|
|
7
|
+
};
|
|
8
|
+
return res.sendSuccess( result );
|
|
9
|
+
} catch ( error ) {
|
|
10
|
+
logger.error( { error: error, message: req.query, function: 'trafficCards' } );
|
|
11
|
+
return res.sendError( { error: error }, 500 );
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const cardsAgeAnalysis = async ( req, res ) => {
|
|
16
|
+
try {
|
|
17
|
+
let reqestData = req.body;
|
|
18
|
+
// //Get Revenue form Client Collection and post to api
|
|
19
|
+
// reqestData.currency = 'INR';
|
|
20
|
+
// reqestData.revenue = '23000';
|
|
21
|
+
// let LamdaURL = 'https://55mojecvuvtphucgsalx5jtyki0untzp.lambda-url.ap-south-1.on.aws/';
|
|
22
|
+
// let resultData = await LamdaServiceCall( LamdaURL, reqestData );
|
|
23
|
+
// if ( resultData ) {
|
|
24
|
+
// const insideBrackets = resultData.status_code.match( /\[([^\]]+)\]/ )[1];
|
|
25
|
+
// if ( insideBrackets == 200 ) {
|
|
26
|
+
// let result = {};
|
|
27
|
+
// result.card = resultData.card;
|
|
28
|
+
// result.funnelChart = resultData.funnelChart;
|
|
29
|
+
// return res.sendSuccess( result );
|
|
30
|
+
// } else {
|
|
31
|
+
// return res.sendError( 'No Content', 204 );
|
|
32
|
+
// }
|
|
33
|
+
// } else {
|
|
34
|
+
// return res.sendError( 'No Content', 204 );
|
|
35
|
+
// }
|
|
36
|
+
|
|
37
|
+
let checkNoData = await returnNoData( reqestData.storeId );
|
|
38
|
+
if ( checkNoData ) {
|
|
39
|
+
return res.sendError( { error: 'No Data Found' }, 204 );
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
|
|
43
|
+
if ( checkInvalidRequest ) {
|
|
44
|
+
return res.sendError( { error: 'Invalid Date' }, 400 );
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let checkServerError = await returnServerError( reqestData.storeId );
|
|
48
|
+
if ( checkServerError ) {
|
|
49
|
+
return res.sendError( { error: 'Server Error' }, 500 );
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let result = {
|
|
53
|
+
'card': {
|
|
54
|
+
'oveallZoneFootfall': {
|
|
55
|
+
'count': 100,
|
|
56
|
+
'rate': 89.5,
|
|
57
|
+
},
|
|
58
|
+
'conversion': {
|
|
59
|
+
'count': 100,
|
|
60
|
+
'rate': 89.5,
|
|
61
|
+
},
|
|
62
|
+
'bounced': {
|
|
63
|
+
'count': 100,
|
|
64
|
+
'rate': 89.5,
|
|
65
|
+
},
|
|
66
|
+
'engagers': {
|
|
67
|
+
'count': 100,
|
|
68
|
+
'rate': 89.5,
|
|
69
|
+
},
|
|
70
|
+
'avgDwellTime': 89.5,
|
|
71
|
+
},
|
|
72
|
+
'genderAnalysis': [
|
|
73
|
+
{ 'category': 'Male', 'value': 30 },
|
|
74
|
+
{ 'category': 'Female', 'value': 70 },
|
|
75
|
+
],
|
|
76
|
+
'ageAnalysis': [
|
|
77
|
+
{ 'category': 'Below 12', 'value': 10 },
|
|
78
|
+
{ 'category': 'Age 13-19', 'value': 20 },
|
|
79
|
+
{ 'category': 'Age 20-30', 'value': 30 },
|
|
80
|
+
{ 'category': 'Age 31-45', 'value': 10 },
|
|
81
|
+
{ 'category': 'Age 46-59', 'value': 20 },
|
|
82
|
+
{ 'category': 'Above 60', 'value': 10 },
|
|
83
|
+
],
|
|
84
|
+
};
|
|
85
|
+
return res.sendSuccess( result );
|
|
86
|
+
} catch ( error ) {
|
|
87
|
+
logger.error( { error: error, message: req.query, function: 'trafficCards' } );
|
|
88
|
+
return res.sendError( { error: error }, 500 );
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const topPerformingZones = async ( req, res ) => {
|
|
93
|
+
try {
|
|
94
|
+
let reqestData = req.body;
|
|
95
|
+
let checkNoData = await returnNoData( reqestData.storeId );
|
|
96
|
+
if ( checkNoData ) {
|
|
97
|
+
return res.sendError( { error: 'No Data Found' }, 204 );
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
|
|
101
|
+
if ( checkInvalidRequest ) {
|
|
102
|
+
return res.sendError( { error: 'Invalid Date' }, 400 );
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let checkServerError = await returnServerError( reqestData.storeId );
|
|
106
|
+
if ( checkServerError ) {
|
|
107
|
+
return res.sendError( { error: 'Server Error' }, 500 );
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
let result = {
|
|
111
|
+
'topPerformingZones': [
|
|
112
|
+
{ 'zoneName': 'Entry', 'value': 90 },
|
|
113
|
+
{ 'zoneName': 'Exit', 'value': 80 },
|
|
114
|
+
{ 'zoneName': 'Zone-1', 'value': 70 },
|
|
115
|
+
{ 'zoneName': 'Zone-2', 'value': 60 },
|
|
116
|
+
{ 'zoneName': 'Zone-3', 'value': 50 },
|
|
117
|
+
{ 'zoneName': 'Zone-4', 'value': 50 },
|
|
118
|
+
{ 'zoneName': 'Zone-5', 'value': 40 },
|
|
119
|
+
{ 'zoneName': 'Zone-6', 'value': 30 },
|
|
120
|
+
{ 'zoneName': 'Zone-7', 'value': 20 },
|
|
121
|
+
{ 'zoneName': 'Zone-8', 'value': 10 },
|
|
122
|
+
],
|
|
123
|
+
};
|
|
124
|
+
return res.sendSuccess( result );
|
|
125
|
+
} catch ( error ) {
|
|
126
|
+
logger.error( { error: error, message: req.query, function: 'trafficCards' } );
|
|
127
|
+
return res.sendError( { error: error }, 500 );
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export const topPerformingStores = async ( req, res ) => {
|
|
132
|
+
try {
|
|
133
|
+
let reqestData = req.body;
|
|
134
|
+
let checkNoData = await returnNoData( reqestData.storeId );
|
|
135
|
+
if ( checkNoData ) {
|
|
136
|
+
return res.sendError( { error: 'No Data Found' }, 204 );
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
|
|
140
|
+
if ( checkInvalidRequest ) {
|
|
141
|
+
return res.sendError( { error: 'Invalid Date' }, 400 );
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
let checkServerError = await returnServerError( reqestData.storeId );
|
|
145
|
+
if ( checkServerError ) {
|
|
146
|
+
return res.sendError( { error: 'Server Error' }, 500 );
|
|
147
|
+
}
|
|
148
|
+
let result = {
|
|
149
|
+
'topPerformingStores': [
|
|
150
|
+
{ 'storeName': 'LKST11-300', 'zoneName': 'zone-0', 'conversionRate': 40.4, 'avgDwellTime': 39.9, 'overallFootfall': 400, 'zoneFootfall': 90 },
|
|
151
|
+
{ 'storeName': 'LKST11-301', 'zoneName': 'zone-1', 'conversionRate': 40.4, 'avgDwellTime': 39.9, 'overallFootfall': 400, 'zoneFootfall': 90 },
|
|
152
|
+
{ 'storeName': 'LKST11-302', 'zoneName': 'zone-2', 'conversionRate': 40.4, 'avgDwellTime': 39.9, 'overallFootfall': 400, 'zoneFootfall': 90 },
|
|
153
|
+
{ 'storeName': 'LKST11-303', 'zoneName': 'zone-3', 'conversionRate': 40.4, 'avgDwellTime': 39.9, 'overallFootfall': 400, 'zoneFootfall': 90 },
|
|
154
|
+
{ 'storeName': 'LKST11-304', 'zoneName': 'zone-4', 'conversionRate': 40.4, 'avgDwellTime': 39.9, 'overallFootfall': 400, 'zoneFootfall': 90 },
|
|
155
|
+
],
|
|
156
|
+
};
|
|
157
|
+
return res.sendSuccess( result );
|
|
158
|
+
} catch ( error ) {
|
|
159
|
+
logger.error( { error: error, message: req.query, function: 'trafficCards' } );
|
|
160
|
+
return res.sendError( { error: error }, 500 );
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
export const zoneSummaryTable = async ( req, res ) => {
|
|
165
|
+
try {
|
|
166
|
+
let reqestData = req.body;
|
|
167
|
+
let checkNoData = await returnNoData( reqestData.storeId );
|
|
168
|
+
if ( checkNoData ) {
|
|
169
|
+
return res.sendError( { error: 'No Data Found' }, 204 );
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
|
|
173
|
+
if ( checkInvalidRequest ) {
|
|
174
|
+
return res.sendError( { error: 'Invalid Date' }, 400 );
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
let checkServerError = await returnServerError( reqestData.storeId );
|
|
178
|
+
if ( checkServerError ) {
|
|
179
|
+
return res.sendError( { error: 'Server Error' }, 500 );
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
let result = {
|
|
183
|
+
'totalCount': 300,
|
|
184
|
+
'zoneSummaryData': [
|
|
185
|
+
{
|
|
186
|
+
'storeName': 'LKST400',
|
|
187
|
+
'date': '2024-01-01', // Single Store
|
|
188
|
+
'storeId': '11-10',
|
|
189
|
+
'zoneName': 'zone',
|
|
190
|
+
'footfallCount': 400,
|
|
191
|
+
'bouncedCount': 40,
|
|
192
|
+
'engagersCount': 60,
|
|
193
|
+
'missedOpportunityCount': 70,
|
|
194
|
+
'potentialBuyersCount': 80,
|
|
195
|
+
'conversionRate': 70.5,
|
|
196
|
+
'avgDwellTime': 50,
|
|
197
|
+
'avgInfraDowntime': 70,
|
|
198
|
+
'bellow12': 30,
|
|
199
|
+
'13-19': 50,
|
|
200
|
+
'20-30': 40,
|
|
201
|
+
'31-45': 20,
|
|
202
|
+
'46-59': 30,
|
|
203
|
+
'60 above': 60,
|
|
204
|
+
'maleCount': 40,
|
|
205
|
+
'femaleCount': 50,
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
'storeName': 'LKST401',
|
|
209
|
+
'date': '2024-01-01', // Single Store
|
|
210
|
+
'storeId': '11-11',
|
|
211
|
+
'zoneName': 'zone',
|
|
212
|
+
'footfallCount': 400,
|
|
213
|
+
'bouncedCount': 40,
|
|
214
|
+
'engagersCount': 60,
|
|
215
|
+
'missedOpportunityCount': 70,
|
|
216
|
+
'potentialBuyersCount': 80,
|
|
217
|
+
'conversionRate': 70.5,
|
|
218
|
+
'avgDwellTime': 50,
|
|
219
|
+
'avgInfraDowntime': 70,
|
|
220
|
+
'bellow12': 30,
|
|
221
|
+
'13-19': 50,
|
|
222
|
+
'20-30': 40,
|
|
223
|
+
'31-45': 20,
|
|
224
|
+
'46-59': 30,
|
|
225
|
+
'60 above': 60,
|
|
226
|
+
'maleCount': 40,
|
|
227
|
+
'femaleCount': 50,
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
'storeName': 'LKST402',
|
|
231
|
+
'date': '2024-01-01', // Single Store
|
|
232
|
+
'storeId': '11-12',
|
|
233
|
+
'zoneName': 'zone',
|
|
234
|
+
'footfallCount': 400,
|
|
235
|
+
'bouncedCount': 40,
|
|
236
|
+
'engagersCount': 60,
|
|
237
|
+
'missedOpportunityCount': 70,
|
|
238
|
+
'potentialBuyersCount': 80,
|
|
239
|
+
'conversionRate': 70.5,
|
|
240
|
+
'avgDwellTime': 50,
|
|
241
|
+
'avgInfraDowntime': 70,
|
|
242
|
+
'bellow12': 30,
|
|
243
|
+
'13-19': 50,
|
|
244
|
+
'20-30': 40,
|
|
245
|
+
'31-45': 20,
|
|
246
|
+
'46-59': 30,
|
|
247
|
+
'60 above': 60,
|
|
248
|
+
'maleCount': 40,
|
|
249
|
+
'femaleCount': 50,
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
'storeName': 'LKST403',
|
|
253
|
+
'date': '2024-01-01', // Single Store
|
|
254
|
+
'storeId': '11-13',
|
|
255
|
+
'zoneName': 'zone',
|
|
256
|
+
'footfallCount': 400,
|
|
257
|
+
'bouncedCount': 40,
|
|
258
|
+
'engagersCount': 60,
|
|
259
|
+
'missedOpportunityCount': 70,
|
|
260
|
+
'potentialBuyersCount': 80,
|
|
261
|
+
'conversionRate': 70.5,
|
|
262
|
+
'avgDwellTime': 50,
|
|
263
|
+
'avgInfraDowntime': 70,
|
|
264
|
+
'bellow12': 30,
|
|
265
|
+
'13-19': 50,
|
|
266
|
+
'20-30': 40,
|
|
267
|
+
'31-45': 20,
|
|
268
|
+
'46-59': 30,
|
|
269
|
+
'60 above': 60,
|
|
270
|
+
'maleCount': 40,
|
|
271
|
+
'femaleCount': 50,
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
'storeName': 'LKST404',
|
|
275
|
+
'date': '2024-01-01', // Single Store
|
|
276
|
+
'storeId': '11-14',
|
|
277
|
+
'zoneName': 'zone',
|
|
278
|
+
'footfallCount': 400,
|
|
279
|
+
'bouncedCount': 40,
|
|
280
|
+
'engagersCount': 60,
|
|
281
|
+
'missedOpportunityCount': 70,
|
|
282
|
+
'potentialBuyersCount': 80,
|
|
283
|
+
'conversionRate': 70.5,
|
|
284
|
+
'avgDwellTime': 50,
|
|
285
|
+
'avgInfraDowntime': 70,
|
|
286
|
+
'bellow12': 30,
|
|
287
|
+
'13-19': 50,
|
|
288
|
+
'20-30': 40,
|
|
289
|
+
'31-45': 20,
|
|
290
|
+
'46-59': 30,
|
|
291
|
+
'60 above': 60,
|
|
292
|
+
'maleCount': 40,
|
|
293
|
+
'femaleCount': 50,
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
'storeName': 'LKST405',
|
|
297
|
+
'date': '2024-01-01', // Single Store
|
|
298
|
+
'storeId': '11-15',
|
|
299
|
+
'zoneName': 'zone',
|
|
300
|
+
'footfallCount': 400,
|
|
301
|
+
'bouncedCount': 40,
|
|
302
|
+
'engagersCount': 60,
|
|
303
|
+
'missedOpportunityCount': 70,
|
|
304
|
+
'potentialBuyersCount': 80,
|
|
305
|
+
'conversionRate': 70.5,
|
|
306
|
+
'avgDwellTime': 50,
|
|
307
|
+
'avgInfraDowntime': 70,
|
|
308
|
+
'bellow12': 30,
|
|
309
|
+
'13-19': 50,
|
|
310
|
+
'20-30': 40,
|
|
311
|
+
'31-45': 20,
|
|
312
|
+
'46-59': 30,
|
|
313
|
+
'60 above': 60,
|
|
314
|
+
'maleCount': 40,
|
|
315
|
+
'femaleCount': 50,
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
'storeName': 'LKST406',
|
|
319
|
+
'date': '2024-01-01', // Single Store
|
|
320
|
+
'storeId': '11-16',
|
|
321
|
+
'zoneName': 'zone',
|
|
322
|
+
'footfallCount': 400,
|
|
323
|
+
'bouncedCount': 40,
|
|
324
|
+
'engagersCount': 60,
|
|
325
|
+
'missedOpportunityCount': 70,
|
|
326
|
+
'potentialBuyersCount': 80,
|
|
327
|
+
'conversionRate': 70.5,
|
|
328
|
+
'avgDwellTime': 50,
|
|
329
|
+
'avgInfraDowntime': 70,
|
|
330
|
+
'bellow12': 30,
|
|
331
|
+
'13-19': 50,
|
|
332
|
+
'20-30': 40,
|
|
333
|
+
'31-45': 20,
|
|
334
|
+
'46-59': 30,
|
|
335
|
+
'60 above': 60,
|
|
336
|
+
'maleCount': 40,
|
|
337
|
+
'femaleCount': 50,
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
'storeName': 'LKST407',
|
|
341
|
+
'date': '2024-01-01', // Single Store
|
|
342
|
+
'storeId': '11-17',
|
|
343
|
+
'zoneName': 'zone',
|
|
344
|
+
'footfallCount': 400,
|
|
345
|
+
'bouncedCount': 40,
|
|
346
|
+
'engagersCount': 60,
|
|
347
|
+
'missedOpportunityCount': 70,
|
|
348
|
+
'potentialBuyersCount': 80,
|
|
349
|
+
'conversionRate': 70.5,
|
|
350
|
+
'avgDwellTime': 50,
|
|
351
|
+
'avgInfraDowntime': 70,
|
|
352
|
+
'bellow12': 30,
|
|
353
|
+
'13-19': 50,
|
|
354
|
+
'20-30': 40,
|
|
355
|
+
'31-45': 20,
|
|
356
|
+
'46-59': 30,
|
|
357
|
+
'60 above': 60,
|
|
358
|
+
'maleCount': 40,
|
|
359
|
+
'femaleCount': 50,
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
'storeName': 'LKST408',
|
|
363
|
+
'date': '2024-01-01', // Single Store
|
|
364
|
+
'storeId': '11-18',
|
|
365
|
+
'zoneName': 'zone',
|
|
366
|
+
'footfallCount': 400,
|
|
367
|
+
'bouncedCount': 40,
|
|
368
|
+
'engagersCount': 60,
|
|
369
|
+
'missedOpportunityCount': 70,
|
|
370
|
+
'potentialBuyersCount': 80,
|
|
371
|
+
'conversionRate': 70.5,
|
|
372
|
+
'avgDwellTime': 50,
|
|
373
|
+
'avgInfraDowntime': 70,
|
|
374
|
+
'bellow12': 30,
|
|
375
|
+
'13-19': 50,
|
|
376
|
+
'20-30': 40,
|
|
377
|
+
'31-45': 20,
|
|
378
|
+
'46-59': 30,
|
|
379
|
+
'60 above': 60,
|
|
380
|
+
'maleCount': 40,
|
|
381
|
+
'femaleCount': 50,
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
'storeName': 'LKST409',
|
|
385
|
+
'date': '2024-01-01', // Single Store
|
|
386
|
+
'storeId': '11-19',
|
|
387
|
+
'zoneName': 'zone',
|
|
388
|
+
'footfallCount': 400,
|
|
389
|
+
'bouncedCount': 40,
|
|
390
|
+
'engagersCount': 60,
|
|
391
|
+
'missedOpportunityCount': 70,
|
|
392
|
+
'potentialBuyersCount': 80,
|
|
393
|
+
'conversionRate': 70.5,
|
|
394
|
+
'avgDwellTime': 50,
|
|
395
|
+
'avgInfraDowntime': 70,
|
|
396
|
+
'bellow12': 30,
|
|
397
|
+
'13-19': 50,
|
|
398
|
+
'20-30': 40,
|
|
399
|
+
'31-45': 20,
|
|
400
|
+
'46-59': 30,
|
|
401
|
+
'60 above': 60,
|
|
402
|
+
'maleCount': 40,
|
|
403
|
+
'femaleCount': 50,
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
'storeName': 'LKST410',
|
|
407
|
+
'date': '2024-01-01', // Single Store
|
|
408
|
+
'storeId': '11-10',
|
|
409
|
+
'zoneName': 'zone',
|
|
410
|
+
'footfallCount': 400,
|
|
411
|
+
'bouncedCount': 40,
|
|
412
|
+
'engagersCount': 60,
|
|
413
|
+
'missedOpportunityCount': 70,
|
|
414
|
+
'potentialBuyersCount': 80,
|
|
415
|
+
'conversionRate': 70.5,
|
|
416
|
+
'avgDwellTime': 50,
|
|
417
|
+
'avgInfraDowntime': 70,
|
|
418
|
+
'bellow12': 30,
|
|
419
|
+
'13-19': 50,
|
|
420
|
+
'20-30': 40,
|
|
421
|
+
'31-45': 20,
|
|
422
|
+
'46-59': 30,
|
|
423
|
+
'60 above': 60,
|
|
424
|
+
'maleCount': 40,
|
|
425
|
+
'femaleCount': 50,
|
|
426
|
+
},
|
|
427
|
+
],
|
|
428
|
+
};
|
|
429
|
+
return res.sendSuccess( result );
|
|
430
|
+
} catch ( error ) {
|
|
431
|
+
logger.error( { error: error, message: req.query, function: 'trafficCards' } );
|
|
432
|
+
return res.sendError( { error: error }, 500 );
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
export const zoneConcentrationSummaryTable = async ( req, res ) => {
|
|
437
|
+
try {
|
|
438
|
+
let reqestData = req.body;
|
|
439
|
+
let checkNoData = await returnNoData( reqestData.storeId );
|
|
440
|
+
if ( checkNoData ) {
|
|
441
|
+
return res.sendError( { error: 'No Data Found' }, 204 );
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
|
|
445
|
+
if ( checkInvalidRequest ) {
|
|
446
|
+
return res.sendError( { error: 'Invalid Date' }, 400 );
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
let checkServerError = await returnServerError( reqestData.storeId );
|
|
450
|
+
if ( checkServerError ) {
|
|
451
|
+
return res.sendError( { error: 'Server Error' }, 500 );
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
let result = {
|
|
455
|
+
'zoneConcentrationData': [
|
|
456
|
+
{
|
|
457
|
+
'zoneName': 'zone-1',
|
|
458
|
+
'footfallCount': 400,
|
|
459
|
+
'avgDwellTime': 50,
|
|
460
|
+
'conversionRate': 70.5,
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
'zoneName': 'zone-2',
|
|
464
|
+
'footfallCount': 400,
|
|
465
|
+
'avgDwellTime': 50,
|
|
466
|
+
'conversionRate': 70.5,
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
'zoneName': 'zone-3',
|
|
470
|
+
'footfallCount': 400,
|
|
471
|
+
'avgDwellTime': 50,
|
|
472
|
+
'conversionRate': 70.5,
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
'zoneName': 'zone-4',
|
|
476
|
+
'footfallCount': 400,
|
|
477
|
+
'avgDwellTime': 50,
|
|
478
|
+
'conversionRate': 70.5,
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
'zoneName': 'zone-5',
|
|
482
|
+
'footfallCount': 400,
|
|
483
|
+
'avgDwellTime': 50,
|
|
484
|
+
'conversionRate': 70.5,
|
|
485
|
+
},
|
|
486
|
+
],
|
|
487
|
+
};
|
|
488
|
+
return res.sendSuccess( result );
|
|
489
|
+
} catch ( error ) {
|
|
490
|
+
logger.error( { error: error, message: req.query, function: 'trafficCards' } );
|
|
491
|
+
return res.sendError( { error: error }, 500 );
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
export const zoneHeatmapAvailableDates = async ( req, res ) => {
|
|
496
|
+
try {
|
|
497
|
+
let reqestData = req.body;
|
|
498
|
+
let checkNoData = await returnNoData( reqestData.storeId );
|
|
499
|
+
if ( checkNoData ) {
|
|
500
|
+
return res.sendError( { error: 'No Data Found' }, 204 );
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
|
|
504
|
+
if ( checkInvalidRequest ) {
|
|
505
|
+
return res.sendError( { error: 'Invalid Date' }, 400 );
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
let checkServerError = await returnServerError( reqestData.storeId );
|
|
509
|
+
if ( checkServerError ) {
|
|
510
|
+
return res.sendError( { error: 'Server Error' }, 500 );
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
let result = {
|
|
514
|
+
'overallStoreConcentrationDates': [
|
|
515
|
+
{ 'zoneDate': 'Jan 01-30' },
|
|
516
|
+
{ 'zoneDate': 'Feb 01-07' },
|
|
517
|
+
{ 'zoneDate': 'Feb 08' },
|
|
518
|
+
],
|
|
519
|
+
};
|
|
520
|
+
return res.sendSuccess( result );
|
|
521
|
+
} catch ( error ) {
|
|
522
|
+
logger.error( { error: error, message: req.query, function: 'trafficCards' } );
|
|
523
|
+
return res.sendError( { error: error }, 500 );
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
export const zoneHeatmapDatas = async ( req, res ) => {
|
|
528
|
+
try {
|
|
529
|
+
let reqestData = req.body;
|
|
530
|
+
let checkNoData = await returnNoData( reqestData.storeId );
|
|
531
|
+
if ( checkNoData ) {
|
|
532
|
+
return res.sendError( { error: 'No Data Found' }, 204 );
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
|
|
536
|
+
if ( checkInvalidRequest ) {
|
|
537
|
+
return res.sendError( { error: 'Invalid Date' }, 400 );
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
let checkServerError = await returnServerError( reqestData.storeId );
|
|
541
|
+
if ( checkServerError ) {
|
|
542
|
+
return res.sendError( { error: 'Server Error' }, 500 );
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
let result = {
|
|
546
|
+
'overallStoreConcentrationDatas': {
|
|
547
|
+
'ImageURL\'s': [
|
|
548
|
+
{
|
|
549
|
+
'streamName': 'ABC',
|
|
550
|
+
'URL': 'DEFGHI',
|
|
551
|
+
},
|
|
552
|
+
{
|
|
553
|
+
'streamName': 'ABC-1',
|
|
554
|
+
'URL': 'DEFGHI-1',
|
|
555
|
+
},
|
|
556
|
+
],
|
|
557
|
+
'totalFootfall': 560,
|
|
558
|
+
'ConcentrationRate': 96.00,
|
|
559
|
+
'bouncedCount': 70,
|
|
560
|
+
'engagersCount': 50,
|
|
561
|
+
'avgDwellTime': 15,
|
|
562
|
+
'ageRange': '20-30',
|
|
563
|
+
'maleRate': 45.0,
|
|
564
|
+
'femaleRate': 50,
|
|
565
|
+
},
|
|
566
|
+
};
|
|
567
|
+
return res.sendSuccess( result );
|
|
568
|
+
} catch ( error ) {
|
|
569
|
+
logger.error( { error: error, message: req.query, function: 'trafficCards' } );
|
|
570
|
+
return res.sendError( { error: error }, 500 );
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
// async function LamdaServiceCall( url, data ) {
|
|
575
|
+
// try {
|
|
576
|
+
// const requestOptions = {
|
|
577
|
+
// method: 'POST',
|
|
578
|
+
// headers: {
|
|
579
|
+
// 'Content-Type': 'application/json',
|
|
580
|
+
// },
|
|
581
|
+
// body: JSON.stringify( data ),
|
|
582
|
+
// };
|
|
583
|
+
// const response = await fetch( url, requestOptions );
|
|
584
|
+
// if ( !response.ok ) {
|
|
585
|
+
// throw new Error( `Response status: ${response.status}` );
|
|
586
|
+
// return false;
|
|
587
|
+
// }
|
|
588
|
+
// const json = await response.json();
|
|
589
|
+
// return json;
|
|
590
|
+
// } catch ( error ) {
|
|
591
|
+
// console.log( 'error =>', error );
|
|
592
|
+
// logger.error( { error: error, message: data, function: 'LamdaServiceCall' } );
|
|
593
|
+
// }
|
|
594
|
+
// }
|
|
595
|
+
|
|
596
|
+
async function returnNoData( requestData ) {
|
|
597
|
+
try {
|
|
598
|
+
if ( requestData && requestData.includes( '204' ) ) {
|
|
599
|
+
return true;
|
|
600
|
+
}
|
|
601
|
+
} catch ( error ) {
|
|
602
|
+
logger.error( { error: error, message: data, function: 'returnNoData' } );
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
async function returnInvalidRequest( requestData ) {
|
|
607
|
+
try {
|
|
608
|
+
if ( requestData && requestData.includes( '400' ) ) {
|
|
609
|
+
return true;
|
|
610
|
+
}
|
|
611
|
+
} catch ( error ) {
|
|
612
|
+
logger.error( { error: error, message: data, function: 'returnInvalidRequest' } );
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
async function returnServerError( requestData ) {
|
|
617
|
+
try {
|
|
618
|
+
if ( requestData && requestData.includes( '500' ) ) {
|
|
619
|
+
return true;
|
|
620
|
+
}
|
|
621
|
+
} catch ( error ) {
|
|
622
|
+
logger.error( { error: error, message: data, function: 'returnServerError' } );
|
|
623
|
+
}
|
|
624
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
|
|
3
|
+
export const analyseZoneRouter = express.Router();
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
welcome,
|
|
7
|
+
cardsAgeAnalysis,
|
|
8
|
+
topPerformingZones,
|
|
9
|
+
topPerformingStores,
|
|
10
|
+
zoneSummaryTable,
|
|
11
|
+
zoneConcentrationSummaryTable,
|
|
12
|
+
zoneHeatmapAvailableDates,
|
|
13
|
+
zoneHeatmapDatas,
|
|
14
|
+
} from '../controllers/analyseZone.controllers.js';
|
|
15
|
+
|
|
16
|
+
analyseZoneRouter
|
|
17
|
+
.get( '/welcome', welcome )
|
|
18
|
+
.post( '/cardsAgeAnalysis', cardsAgeAnalysis )
|
|
19
|
+
.post( '/topPerformingZones', topPerformingZones )
|
|
20
|
+
.post( '/topPerformingStores', topPerformingStores )
|
|
21
|
+
.post( '/zoneSummaryTable', zoneSummaryTable )
|
|
22
|
+
.post( '/zoneConcentrationSummaryTable', zoneConcentrationSummaryTable )
|
|
23
|
+
.post( '/zoneHeatmapAvailableDates', zoneHeatmapAvailableDates )
|
|
24
|
+
.post( '/zoneHeatmapDatas', zoneHeatmapDatas );
|
|
25
|
+
|
|
26
|
+
export default analyseZoneRouter;
|