tango-app-api-analysis-zone 3.0.0-alpha.10 → 3.0.0-alpha.12

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/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
 
2
2
 
3
3
  import { analysisZoneRouter } from './src/routes/analysisZone.js';
4
+ import { analysisZoneV2Router } from './src/routes/analysisZoneV2.js';
4
5
 
5
- export { analysisZoneRouter };
6
+ export { analysisZoneRouter, analysisZoneV2Router };
6
7
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tango-app-api-analysis-zone",
3
- "version": "3.0.0-alpha.10",
3
+ "version": "3.0.0-alpha.12",
4
4
  "description": "zone Analysis",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -0,0 +1,416 @@
1
+ import { logger } from 'tango-app-api-middleware';
2
+
3
+
4
+ export const zonecards = async ( req, res ) => {
5
+ try {
6
+ let reqestData = req.body;
7
+ let checkNoData = await returnNoData( reqestData.storeId );
8
+ if ( checkNoData ) {
9
+ return res.sendError( { error: 'No Data Found' }, 204 );
10
+ }
11
+
12
+ let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
13
+ if ( checkInvalidRequest ) {
14
+ return res.sendError( { error: 'Invalid Date' }, 400 );
15
+ }
16
+
17
+ let checkServerError = await returnServerError( reqestData.storeId );
18
+ if ( checkServerError ) {
19
+ return res.sendError( { error: 'Server Error' }, 500 );
20
+ }
21
+
22
+ let result = {
23
+ 'card': {
24
+ 'footfall': {
25
+ 'count': 100, // Store Footfall Count
26
+ 'zoneName': 'Entry', // highest Zone Footfall
27
+ 'zoneFootfallCount': 40,
28
+ },
29
+ 'impression': {
30
+ 'rate': 89.5, // Store impression rate
31
+ 'zoneName': 'EXit', // highest Impression(Concentration)
32
+ 'zoneImpressionRate': 40.0,
33
+ },
34
+ 'bounced': {
35
+ 'rate': 89.5, // Store bounced rate
36
+ 'zoneName': 'EXit', // highest Bounced
37
+ },
38
+ 'engagers': {
39
+ 'rate': 89.5, // Store engagers rate
40
+ 'zoneName': 'EXit', // highest Engagers
41
+ },
42
+ 'avgDwellTime': {
43
+ 'rate': 89.5, // Store avgDwellTime rate
44
+ 'zoneName': 'EXit', // highest Average Dwell Time
45
+ },
46
+ },
47
+ };
48
+ return res.sendSuccess( result );
49
+ } catch ( error ) {
50
+ logger.error( { error: error, message: req.query, function: 'zonecards' } );
51
+ return res.sendError( { error: error }, 500 );
52
+ }
53
+ };
54
+ export const topPerformingZones = async ( req, res ) => {
55
+ try {
56
+ let reqestData = req.body;
57
+ let checkNoData = await returnNoData( reqestData.storeId );
58
+ if ( checkNoData ) {
59
+ return res.sendError( { error: 'No Data Found' }, 204 );
60
+ }
61
+
62
+ let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
63
+ if ( checkInvalidRequest ) {
64
+ return res.sendError( { error: 'Invalid Date' }, 400 );
65
+ }
66
+
67
+ let checkServerError = await returnServerError( reqestData.storeId );
68
+ if ( checkServerError ) {
69
+ return res.sendError( { error: 'Server Error' }, 500 );
70
+ }
71
+
72
+ let result = {
73
+ 'topPerformingZones': [
74
+ { 'zoneName': 'zone-0', 'footfallCount': 100, 'bouncedCount': 40, 'engagersCount': 30, 'impressionRate': 50.0 },
75
+ { 'zoneName': 'zone-0', 'footfallCount': 98, 'bouncedCount': 38, 'engagersCount': 28, 'impressionRate': 48.5 },
76
+ { 'zoneName': 'zone-0', 'footfallCount': 96, 'bouncedCount': 36, 'engagersCount': 26, 'impressionRate': 46.5 },
77
+ { 'zoneName': 'zone-0', 'footfallCount': 94, 'bouncedCount': 34, 'engagersCount': 24, 'impressionRate': 44.5 },
78
+ { 'zoneName': 'zone-0', 'footfallCount': 92, 'bouncedCount': 32, 'engagersCount': 22, 'impressionRate': 42.5 },
79
+ ],
80
+ };
81
+ return res.sendSuccess( result );
82
+ } catch ( error ) {
83
+ logger.error( { error: error, message: req.query, function: 'topPerformingZones' } );
84
+ return res.sendError( { error: error }, 500 );
85
+ }
86
+ };
87
+ export const topPerformingStores = async ( req, res ) => {
88
+ try {
89
+ let reqestData = req.body;
90
+ let checkNoData = await returnNoData( reqestData.storeId );
91
+ if ( checkNoData ) {
92
+ return res.sendError( { error: 'No Data Found' }, 204 );
93
+ }
94
+
95
+ let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
96
+ if ( checkInvalidRequest ) {
97
+ return res.sendError( { error: 'Invalid Date' }, 400 );
98
+ }
99
+
100
+ let checkServerError = await returnServerError( reqestData.storeId );
101
+ if ( checkServerError ) {
102
+ return res.sendError( { error: 'Server Error' }, 500 );
103
+ }
104
+
105
+ let result = {
106
+ 'topPerformingStores': [
107
+ { 'storeName': 'LKST11-300', 'storeId': '11-300', 'zoneName': 'zone-0', 'zoneFootfallCount': 90, 'impressionRate': 40.4, 'avgDwellTime': 39.9 },
108
+ { 'storeName': 'LKST11-301', 'storeId': '11-301', 'zoneName': 'zone-1', 'zoneFootfallCount': 90, 'impressionRate': 40.4, 'avgDwellTime': 39.9 },
109
+ { 'storeName': 'LKST11-302', 'storeId': '11-302', 'zoneName': 'zone-2', 'zoneFootfallCount': 90, 'impressionRate': 40.4, 'avgDwellTime': 39.9 },
110
+ { 'storeName': 'LKST11-303', 'storeId': '11-303', 'zoneName': 'zone-3', 'zoneFootfallCount': 90, 'impressionRate': 40.4, 'avgDwellTime': 39.9 },
111
+ { 'storeName': 'LKST11-304', 'storeId': '11-304', 'zoneName': 'zone-4', 'zoneFootfallCount': 90, 'impressionRate': 40.4, 'avgDwellTime': 39.9 },
112
+ ],
113
+ };
114
+ return res.sendSuccess( result );
115
+ } catch ( error ) {
116
+ logger.error( { error: error, message: req.query, function: 'topPerformingStores' } );
117
+ return res.sendError( { error: error }, 500 );
118
+ }
119
+ };
120
+ export const zoneSummaryTable = async ( req, res ) => {
121
+ try {
122
+ let reqestData = req.body;
123
+ let checkNoData = await returnNoData( reqestData.storeId );
124
+ if ( checkNoData ) {
125
+ return res.sendError( { error: 'No Data Found' }, 204 );
126
+ }
127
+
128
+ let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
129
+ if ( checkInvalidRequest ) {
130
+ return res.sendError( { error: 'Invalid Date' }, 400 );
131
+ }
132
+
133
+ let checkServerError = await returnServerError( reqestData.storeId );
134
+ if ( checkServerError ) {
135
+ return res.sendError( { error: 'Server Error' }, 500 );
136
+ }
137
+
138
+ let result = [
139
+ {
140
+ 'storeName': 'LKST400',
141
+ 'date': '2024-01-01',
142
+ 'storeId': '11-10',
143
+ 'zoneName': 'zone-1',
144
+ 'footfallCount': 400,
145
+ 'bouncedCount': 40,
146
+ 'engagersCount': 60,
147
+ 'impressionRate': 70.5,
148
+ 'avgDwellTime': 50,
149
+ 'bellow12': 30,
150
+ '13-19': 50,
151
+ '20-30': 40,
152
+ '31-45': 20,
153
+ '46-59': 30,
154
+ '60 above': 60,
155
+ 'maleCount': 40,
156
+ 'femaleCount': 50,
157
+ },
158
+ ];
159
+ return res.sendSuccess( result );
160
+ } catch ( error ) {
161
+ logger.error( { error: error, message: req.query, function: 'zoneSummaryTable' } );
162
+ return res.sendError( { error: error }, 500 );
163
+ }
164
+ };
165
+ export const availableZoneNames = async ( req, res ) => {
166
+ try {
167
+ let reqestData = req.body;
168
+ let checkNoData = await returnNoData( reqestData.storeId );
169
+ if ( checkNoData ) {
170
+ return res.sendError( { error: 'No Data Found' }, 204 );
171
+ }
172
+
173
+ let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
174
+ if ( checkInvalidRequest ) {
175
+ return res.sendError( { error: 'Invalid Date' }, 400 );
176
+ }
177
+
178
+ let checkServerError = await returnServerError( reqestData.storeId );
179
+ if ( checkServerError ) {
180
+ return res.sendError( { error: 'Server Error' }, 500 );
181
+ }
182
+
183
+ let result = {
184
+ 'availableZoneData': [
185
+ { 'zoneName': 'zone-1' },
186
+ { 'zoneName': 'zone-2' },
187
+ { 'zoneName': 'zone-3' },
188
+ ],
189
+ };
190
+ return res.sendSuccess( result );
191
+ } catch ( error ) {
192
+ logger.error( { error: error, message: req.query, function: 'availableZoneNames' } );
193
+ return res.sendError( { error: error }, 500 );
194
+ }
195
+ };
196
+ export const zoneConcentrationSummary = async ( req, res ) => {
197
+ try {
198
+ let reqestData = req.body;
199
+ let checkNoData = await returnNoData( reqestData.storeId );
200
+ if ( checkNoData ) {
201
+ return res.sendError( { error: 'No Data Found' }, 204 );
202
+ }
203
+
204
+ let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
205
+ if ( checkInvalidRequest ) {
206
+ return res.sendError( { error: 'Invalid Date' }, 400 );
207
+ }
208
+
209
+ let checkServerError = await returnServerError( reqestData.storeId );
210
+ if ( checkServerError ) {
211
+ return res.sendError( { error: 'Server Error' }, 500 );
212
+ }
213
+
214
+ let result = [
215
+ {
216
+ 'zoneName': 'zone-1',
217
+ 'footfall': {
218
+ 'zoneCount': 10,
219
+ 'storeRate': 65.0,
220
+ },
221
+ 'impression': {
222
+ 'zoneRate': 10.0,
223
+ 'storeRate': 65.0,
224
+ },
225
+ 'bounced': {
226
+ 'zoneCount': 10,
227
+ 'storeRate': 65.0,
228
+ },
229
+ 'engagers': {
230
+ 'zoneCount': 10,
231
+ 'storeRate': 65.0,
232
+ },
233
+ 'avgDwellTime': {
234
+ 'zoneAvgDwellTime': 10,
235
+ 'storeAvgDwellTime': 65,
236
+ },
237
+ 'bellow-12': 30.0, // Rate
238
+ '13-19': 50.0,
239
+ '20-30': 40.0,
240
+ '31-45': 20.0,
241
+ '46-59': 30.0,
242
+ '60-above': 60.0,
243
+ 'maleRate': 40.0,
244
+ 'femaleRate': 50.0,
245
+ },
246
+ ];
247
+ return res.sendSuccess( result );
248
+ } catch ( error ) {
249
+ logger.error( { error: error, message: req.query, function: 'zoneConcentrationSummary' } );
250
+ return res.sendError( { error: error }, 500 );
251
+ }
252
+ };
253
+ export const overallStoreConcentrationDates = async ( req, res ) => {
254
+ try {
255
+ let reqestData = req.body;
256
+ let checkNoData = await returnNoData( reqestData.storeId );
257
+ if ( checkNoData ) {
258
+ return res.sendError( { error: 'No Data Found' }, 204 );
259
+ }
260
+
261
+ let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
262
+ if ( checkInvalidRequest ) {
263
+ return res.sendError( { error: 'Invalid Date' }, 400 );
264
+ }
265
+
266
+ let checkServerError = await returnServerError( reqestData.storeId );
267
+ if ( checkServerError ) {
268
+ return res.sendError( { error: 'Server Error' }, 500 );
269
+ }
270
+
271
+ let result = {
272
+ 'overallStoreConcentrationDates': [
273
+ { 'zoneDate': 'Jan 01-30' },
274
+ { 'zoneDate': 'Feb 01-07' },
275
+ { 'zoneDate': 'Feb 08' },
276
+ ],
277
+ };
278
+ return res.sendSuccess( result );
279
+ } catch ( error ) {
280
+ logger.error( { error: error, message: req.query, function: 'overallStoreConcentrationDates' } );
281
+ return res.sendError( { error: error }, 500 );
282
+ }
283
+ };
284
+ export const overallStoreConcentrationHeatmap = async ( req, res ) => {
285
+ try {
286
+ let reqestData = req.body;
287
+ let checkNoData = await returnNoData( reqestData.storeId );
288
+ if ( checkNoData ) {
289
+ return res.sendError( { error: 'No Data Found' }, 204 );
290
+ }
291
+
292
+ let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
293
+ if ( checkInvalidRequest ) {
294
+ return res.sendError( { error: 'Invalid Date' }, 400 );
295
+ }
296
+
297
+ let checkServerError = await returnServerError( reqestData.storeId );
298
+ if ( checkServerError ) {
299
+ return res.sendError( { error: 'Server Error' }, 500 );
300
+ }
301
+
302
+ let result = {
303
+ 'overallStoreConcentrationData': {
304
+ 'ImageURLs': [
305
+ {
306
+ 'streamName': 'ABC',
307
+ 'URL': 'DEFGHI',
308
+ },
309
+ {
310
+ 'streamName': 'ABC-1',
311
+ 'URL': 'DEFGHI-1',
312
+ },
313
+ ],
314
+ },
315
+ };
316
+ return res.sendSuccess( result );
317
+ } catch ( error ) {
318
+ logger.error( { error: error, message: req.query, function: 'overallStoreConcentrationHeatmap' } );
319
+ return res.sendError( { error: error }, 500 );
320
+ }
321
+ };
322
+ export const trajectoryAnalysis = async ( req, res ) => {
323
+ try {
324
+ let reqestData = req.body;
325
+ let checkNoData = await returnNoData( reqestData.storeId );
326
+ if ( checkNoData ) {
327
+ return res.sendError( { error: 'No Data Found' }, 204 );
328
+ }
329
+
330
+ let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
331
+ if ( checkInvalidRequest ) {
332
+ return res.sendError( { error: 'Invalid Date' }, 400 );
333
+ }
334
+
335
+ let checkServerError = await returnServerError( reqestData.storeId );
336
+ if ( checkServerError ) {
337
+ return res.sendError( { error: 'Server Error' }, 500 );
338
+ }
339
+
340
+ let result = {
341
+ 'trajectoryAnalysisData': {
342
+ 'zoneList': [ 'zone-1', 'zone-2', 'zone-3' ],
343
+ 'otherZone': {
344
+ 'impressionRate': 40.0,
345
+ 'gender': 'Male', // ["Male","Female"]
346
+ 'ageGroup': '20-30',
347
+ },
348
+ 'currentZone': {
349
+ 'impressionRate': 40.0,
350
+ 'gender': 'Female', // ["Male","Female"]
351
+ 'ageGroup': '20-30',
352
+ },
353
+ },
354
+ };
355
+ return res.sendSuccess( result );
356
+ } catch ( error ) {
357
+ logger.error( { error: error, message: req.query, function: 'trajectoryAnalysis' } );
358
+ return res.sendError( { error: error }, 500 );
359
+ }
360
+ };
361
+ export const customerJourney = async ( req, res ) => {
362
+ try {
363
+ let reqestData = req.body;
364
+ let checkNoData = await returnNoData( reqestData.storeId );
365
+ if ( checkNoData ) {
366
+ return res.sendError( { error: 'No Data Found' }, 204 );
367
+ }
368
+
369
+ let checkInvalidRequest = await returnInvalidRequest( reqestData.storeId );
370
+ if ( checkInvalidRequest ) {
371
+ return res.sendError( { error: 'Invalid Date' }, 400 );
372
+ }
373
+
374
+ let checkServerError = await returnServerError( reqestData.storeId );
375
+ if ( checkServerError ) {
376
+ return res.sendError( { error: 'Server Error' }, 500 );
377
+ }
378
+
379
+ let result = {
380
+ 'customerJourneyData': { },
381
+ };
382
+ return res.sendSuccess( result );
383
+ } catch ( error ) {
384
+ logger.error( { error: error, message: req.query, function: 'customerJourney' } );
385
+ return res.sendError( { error: error }, 500 );
386
+ }
387
+ };
388
+ async function returnNoData( requestData ) {
389
+ try {
390
+ if ( requestData && requestData.includes( '204' ) ) {
391
+ return true;
392
+ }
393
+ } catch ( error ) {
394
+ logger.error( { error: error, message: data, function: 'returnNoData' } );
395
+ }
396
+ }
397
+
398
+ async function returnInvalidRequest( requestData ) {
399
+ try {
400
+ if ( requestData && requestData.includes( '400' ) ) {
401
+ return true;
402
+ }
403
+ } catch ( error ) {
404
+ logger.error( { error: error, message: data, function: 'returnInvalidRequest' } );
405
+ }
406
+ }
407
+
408
+ async function returnServerError( requestData ) {
409
+ try {
410
+ if ( requestData && requestData.includes( '500' ) ) {
411
+ return true;
412
+ }
413
+ } catch ( error ) {
414
+ logger.error( { error: error, message: data, function: 'returnServerError' } );
415
+ }
416
+ }
@@ -30,6 +30,8 @@ export const validateTopPerformingStoresSchema = joi.object( {
30
30
  ...baseSchema,
31
31
  search: joi.string().optional().allow( '' ),
32
32
  export: joi.boolean().required(),
33
+ sortBy: joi.number().optional().allow( '' ),
34
+ sort: joi.string().optional().allow( '' ),
33
35
  } );
34
36
 
35
37
  export const validateTopPerformingStoresParams = {
@@ -0,0 +1,30 @@
1
+ import express from 'express';
2
+ // import { validate, isAllowedSessionHandler, authorize } from 'tango-app-api-middleware';
3
+ // import * as validationDtos from '../dtos/validation.dtos.js';
4
+
5
+ export const analysisZoneV2Router = express.Router();
6
+ import {
7
+ zonecards,
8
+ topPerformingZones,
9
+ topPerformingStores,
10
+ zoneSummaryTable,
11
+ availableZoneNames,
12
+ zoneConcentrationSummary,
13
+ overallStoreConcentrationDates,
14
+ overallStoreConcentrationHeatmap,
15
+ trajectoryAnalysis,
16
+ customerJourney,
17
+ } from '../controllers/analysisZoneSampleDataV2.controllers.js';
18
+
19
+ analysisZoneV2Router
20
+ .post( '/zonecards', zonecards )
21
+ .post( '/topPerformingZones', topPerformingZones )
22
+ .post( '/topPerformingStores', topPerformingStores )
23
+ .post( '/zoneSummaryTable', zoneSummaryTable )
24
+ .post( '/availableZoneNames', availableZoneNames )
25
+ .post( '/zoneConcentrationSummary', zoneConcentrationSummary )
26
+ .post( '/overallStoreConcentrationDates', overallStoreConcentrationDates )
27
+ .post( '/overallStoreConcentrationHeatmap', overallStoreConcentrationHeatmap )
28
+ .post( '/trajectoryAnalysis', trajectoryAnalysis )
29
+ .post( '/customerJourney', customerJourney );
30
+ export default analysisZoneV2Router;