tango-app-api-analysis-traffic 3.8.0-alpha.2 → 3.8.1-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/README.md CHANGED
@@ -1,29 +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
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
29
  * Other community or team contact
package/index.js CHANGED
@@ -4,7 +4,8 @@ import { analysisTrafficRouter } from './src/routes/traffic.routes.js';
4
4
  import { revopRouter } from './src/routes/revop.routes.js';
5
5
  import { mobileTrafficAnalysisRouter } from './src/routes/mobileTraffic.routes.js';
6
6
  import { nobDocs } from './src/docs/nob.docs.js';
7
+ import { revopDocs } from './src/docs/revop.docs.js';
7
8
  import nobRouter from './src/routes/nob.routes.js';
8
9
 
9
- export { analysisTrafficRouter, mobileTrafficAnalysisRouter, nobDocs, nobRouter, revopRouter };
10
+ export { analysisTrafficRouter, mobileTrafficAnalysisRouter, nobDocs, nobRouter, revopRouter, revopDocs };
10
11
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tango-app-api-analysis-traffic",
3
- "version": "3.8.0-alpha.2",
3
+ "version": "3.8.1-alpha.1",
4
4
  "description": "Traffic Analysis",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -23,8 +23,8 @@
23
23
  "mongodb": "^6.8.0",
24
24
  "nodemon": "^3.1.4",
25
25
  "swagger-ui-express": "^5.0.1",
26
- "tango-api-schema": "^2.2.192",
27
- "tango-app-api-middleware": "^3.1.86",
26
+ "tango-api-schema": "^2.2.201",
27
+ "tango-app-api-middleware": "^3.1.88",
28
28
  "winston": "^3.13.1",
29
29
  "winston-daily-rotate-file": "^5.0.0"
30
30
  },
@@ -1,7 +1,8 @@
1
1
  import { logger, insertOpenSearchData, getOpenSearchData, updateOpenSearchData } from 'tango-app-api-middleware';
2
2
  import { findOnerevopConfig } from '../services/revopConfig.service.js';
3
3
  import * as clientService from '../services/clients.services.js';
4
-
4
+ import { upsertWithScript } from 'tango-app-api-middleware/src/utils/openSearch.js';
5
+ import dayjs from 'dayjs';
5
6
  // Lamda Service Call //
6
7
  async function LamdaServiceCall( url, data ) {
7
8
  try {
@@ -204,3 +205,136 @@ export async function revoptaggingcount( req, res ) {
204
205
  return res.sendError( { error: error }, 500 );
205
206
  }
206
207
  }
208
+
209
+ export async function storeProcessedData( req, res ) {
210
+ try {
211
+ const openSearch = JSON.parse( process.env.OPENSEARCH );
212
+ const inputData = req.query;
213
+ const previousDate = dayjs( inputData.dateString ).subtract( 1, 'day' ).format( 'YYYY-MM-DD' );
214
+ const dateString = `${inputData.storeId}_${inputData.dateString}`;
215
+ const dateStringPrevious = `${inputData.storeId}_${previousDate}`;
216
+ const getQuery = {
217
+ query: {
218
+ terms: {
219
+ _id: [ dateString, dateStringPrevious ],
220
+ },
221
+ },
222
+ _source: [ 'footfall', 'date_string', 'store_id', 'down_time', 'footfall_count' ],
223
+ sort: [
224
+ {
225
+ date_iso: {
226
+ order: 'desc',
227
+ },
228
+ },
229
+ ],
230
+ };
231
+
232
+
233
+ const getData = await getOpenSearchData( openSearch.footfall, getQuery );
234
+ const processedData = getData?.body?.hits?.hits?.[0]?._source;
235
+ const previousData = getData?.body?.hits?.hits?.[1]?._source;
236
+ const result=( ( processedData?.footfall_count - previousData?.footfall_count )/previousData?.footfall_count )*100;
237
+ return res.sendSuccess( { footfallCount: processedData?.footfall_count, footfallCountTrend: Math.round( result ), downtime: processedData?.down_time } );
238
+ } catch ( error ) {
239
+ logger.error( { message: error, data: req.query, function: 'storeProcessedData' } );
240
+ const err = error.message || 'Internal Server Error';
241
+ return res.sendError( err, 500 );
242
+ }
243
+ }
244
+
245
+ export async function footFallImages( req, res ) {
246
+ try {
247
+ const inputData = req.query;
248
+ inputData.clientId = inputData.storeId.split( '-' )[0];
249
+ inputData.storeId=[ inputData.storeId ];
250
+
251
+ const LamdaURL = 'https://cncmzszloku7y3bewxbpiy6nkm0yunqe.lambda-url.ap-south-1.on.aws/';
252
+ let resultData = await LamdaServiceCall( LamdaURL, inputData );
253
+ if ( resultData ) {
254
+ if ( resultData.status_code == '200' ) {
255
+ return res.sendSuccess( { ...resultData, ticketStatus: '' } );
256
+ } else {
257
+ return res.sendError( 'No Content', 204 );
258
+ }
259
+ } else {
260
+ return res.sendError( 'No Content', 204 );
261
+ }
262
+ } catch ( error ) {
263
+ logger.error( { message: error, data: req.query, function: 'storeProcessedData' } );
264
+ const err = error.message || 'Internal Server Error';
265
+ return res.sendError( err, 500 );
266
+ }
267
+ }
268
+
269
+ export async function tagTempId( req, res ) {
270
+ try {
271
+ const openSearch = JSON.parse( process.env.OPENSEARCH );
272
+ const inputData = req.body;
273
+ const upsertRecord = {
274
+ clientId: inputData.storeId.split( '-' )[0],
275
+ storeId: inputData.storeId,
276
+ tempId: inputData.tempId,
277
+ dateString: inputData.dateString,
278
+ timeRange: inputData.timeRange,
279
+ processType: inputData.processType,
280
+ revopsType: inputData.revopsType,
281
+ entryTime: inputData.entryTime,
282
+ exitTime: inputData.exitTime,
283
+ filePath: inputData.filePath,
284
+ status: 'submitted',
285
+ description: '',
286
+ dublicateImage: inputData?.dublicateImage?.length>0? inputData?.dublicateImage :[],
287
+ createdAt: new Date(),
288
+ updatedAt: new Date(),
289
+
290
+ };
291
+ const script = {
292
+ source: `
293
+
294
+ ctx._source.revopsType = params.revopsType;
295
+ ctx._source.entryTime = params.entryTime;
296
+ ctx._source.exitTime = params.exitTime;
297
+ ctx._source.filePath = params.filePath;
298
+ ctx._source.status = params.status;
299
+ ctx._source.description = params.description;
300
+ ctx._source.dublicateImage = params.dublicateImage;
301
+ ctx._source.updatedAt = params.updatedAt;
302
+ if (ctx._source.createdAt == null) {
303
+ ctx._source.createdAt = params.createdAt;
304
+ ctx._source.clientId = params.clientId;
305
+ ctx._source.storeId = params.storeId;
306
+ ctx._source.tempId = params.tempId;
307
+ ctx._source.dateString = params.dateString;
308
+ ctx._source.timeRange = params.timeRange;
309
+ ctx._source.processType = params.processType;
310
+ }
311
+ `,
312
+ params: upsertRecord,
313
+ };
314
+ const id = `${inputData.storeId}_${inputData.dateString}_${inputData.timeRange}_${inputData.tempId}`;
315
+ await upsertWithScript( openSearch.revop, id, { script, upsert: upsertRecord } );
316
+ return res.sendSuccess( `tempId ${inputData.tempId} has been tagged successfully` );
317
+ } catch ( error ) {
318
+ logger.error( { message: error, data: req.query, function: 'tagTempId' } );
319
+ const err = error.message || 'Internal Server Error';
320
+ return res.sendError( err, 500 );
321
+ }
322
+ }
323
+
324
+ export async function getCategorizedImages( req, res ) {
325
+ try {
326
+ const inputQury = req.query;
327
+ logger.info( { inputQury: inputQury } );
328
+ const result={
329
+ nonTagged: [],
330
+ duplicates: [],
331
+ Employee: [],
332
+ HouseKepping: [],
333
+ };
334
+ return res.sendSuccess( { result: result } );
335
+ } catch ( error ) {
336
+ logger.error( { message: error, data: req.query, function: 'getCategorizedImages' } );
337
+ const err = error.message || 'Internal Server Error';
338
+ return res.sendError( err, 500 );
339
+ }
340
+ }
@@ -3069,50 +3069,6 @@ export const getStoreMapDataV3 = async ( req, res ) => {
3069
3069
  }
3070
3070
  };
3071
3071
 
3072
- export const managerTrafficDensityExport = async ( req, res ) => {
3073
- try {
3074
- let reqestData = req.body;
3075
- let getClientData = await getClientConfig( reqestData.clientId );
3076
- if ( !getClientData ) {
3077
- return res.sendError( 'Invalid Client Id', 400 );
3078
- }
3079
- reqestData.featureConfigs = getClientData.featureConfigs;
3080
- let LamdaURL = 'https://bkmqop3brhzloib2bik3hn7xey0uadas.lambda-url.ap-south-1.on.aws/';
3081
- let resultData = await LamdaServiceCall( LamdaURL, reqestData );
3082
- let resultDataValue = resultData.data;
3083
- if ( resultData ) {
3084
- if ( resultData.status_code == '200' ) {
3085
- if ( reqestData.export ) {
3086
- if ( resultDataValue && resultDataValue.length > 0 ) {
3087
- let exportdata = [];
3088
- resultDataValue.forEach( ( element ) => {
3089
- let row = {};
3090
- row['Date'] = element.date || '--';
3091
- row['Time'] = element.time ?? '--';
3092
- row['Day'] = element.day ?? '--';
3093
- row['Count'] = element.count || '--';
3094
- exportdata.push( row );
3095
- } );
3096
-
3097
- return await download( exportdata, res );
3098
- } else {
3099
- return res.sendError( 'No Content', 204 );
3100
- }
3101
- } else {
3102
- return res.sendSuccess( resultData );
3103
- }
3104
- } else {
3105
- return res.sendError( 'No Content', 204 );
3106
- }
3107
- } else {
3108
- return res.sendError( 'No Content', 204 );
3109
- }
3110
- } catch ( error ) {
3111
- logger.error( { error: error, message: req.query, function: 'managerTrafficDensityExport' } );
3112
- return res.sendError( { error: error }, 500 );
3113
- }
3114
- };
3115
-
3116
3072
  // async function getGeocodedAddress( lat, lng ) {
3117
3073
  // try {
3118
3074
  // const apiKey = 'AIzaSyDlOezgwQO0JviD0aizrCuN1FY9tcWfR3o'; // Use this if you're using dotenv
@@ -0,0 +1,104 @@
1
+ import j2s from 'joi-to-swagger';
2
+ import { footfallImagesSchema, storeProcessedDataSchema, tagTempIdSchema } from '../dtos/revop.dtos.js';
3
+
4
+
5
+ export const revopDocs = {
6
+ '/v3/revop/store-processed-data': {
7
+ get: {
8
+ tags: [ 'Revop' ],
9
+ description: 'To get a Store Processed data',
10
+ operationId: 'store-list',
11
+ parameters: [
12
+ {
13
+ in: 'query',
14
+ name: 'storeId',
15
+ scema: j2s( storeProcessedDataSchema ).swagger,
16
+ required: true,
17
+ },
18
+ {
19
+ in: 'query',
20
+ name: 'dateString',
21
+ scema: j2s( storeProcessedDataSchema ).swagger,
22
+ required: true,
23
+ },
24
+ ],
25
+ responses: {
26
+ 200: { description: 'Successfully' },
27
+ 401: { description: 'Unauthorized User' },
28
+ 422: { description: 'Field Error' },
29
+ 500: { description: 'Server Error' },
30
+ 204: { description: 'Not Found' },
31
+ },
32
+ },
33
+ },
34
+
35
+ '/v3/revop/footfall-images': {
36
+ get: {
37
+ tags: [ 'Revop' ],
38
+ description: 'To get list of image directory by the selection',
39
+ operationId: 'footfall-images',
40
+ parameters: [
41
+ {
42
+ in: 'query',
43
+ name: 'storeId',
44
+ scema: j2s( footfallImagesSchema ).swagger,
45
+ required: true,
46
+ },
47
+ {
48
+ in: 'query',
49
+ name: 'dateString',
50
+ scema: j2s( footfallImagesSchema ).swagger,
51
+ required: true,
52
+ },
53
+ {
54
+ in: 'query',
55
+ name: 'groupByKey',
56
+ scema: j2s( footfallImagesSchema ).swagger,
57
+ required: true,
58
+ },
59
+ {
60
+ in: 'query',
61
+ name: 'type',
62
+ scema: j2s( footfallImagesSchema ).swagger,
63
+ required: false,
64
+ },
65
+ {
66
+ in: 'query',
67
+ name: 'processType',
68
+ scema: j2s( footfallImagesSchema ).swagger,
69
+ required: true,
70
+ },
71
+ ],
72
+ responses: {
73
+ 200: { description: 'Successfully' },
74
+ 401: { description: 'Unauthorized User' },
75
+ 422: { description: 'Field Error' },
76
+ 500: { description: 'Server Error' },
77
+ 204: { description: 'Not Found' },
78
+ },
79
+ },
80
+ },
81
+
82
+ '/v3/revop/tag-tempId': {
83
+ post: {
84
+ tags: [ 'Revop' ],
85
+ description: 'To add/edit tag against a temp ID ',
86
+ operationId: 'tag-tempId',
87
+ parameters: [],
88
+ requestBody: {
89
+ content: {
90
+ 'application/json': {
91
+ schema: j2s( tagTempIdSchema ).swagger,
92
+ },
93
+ },
94
+ },
95
+ responses: {
96
+ 200: { description: 'Temp ID has been tagged successfully' },
97
+ 401: { description: 'Unauthorized User' },
98
+ 422: { description: 'Field Error' },
99
+ 500: { description: 'Server Error' },
100
+ 204: { description: 'Not Found' },
101
+ },
102
+ },
103
+ },
104
+ };
@@ -0,0 +1,59 @@
1
+ import joi from 'joi';
2
+
3
+ export const storeProcessedDataSchema = joi.object( {
4
+
5
+ storeId: joi.string().required(),
6
+ dateString: joi.string().required(),
7
+
8
+ } );
9
+
10
+ export const storeProcessedDataValid = {
11
+ query: storeProcessedDataSchema,
12
+ };
13
+
14
+ export const footfallImagesSchema = joi.object( {
15
+
16
+ storeId: joi.string().required(),
17
+ dateString: joi.string().required(),
18
+ groupByKey: joi.string().required(),
19
+ processType: joi.string().required(),
20
+ type: joi.string().optional(),
21
+
22
+ } );
23
+
24
+ export const footfallImagesValid = {
25
+ query: footfallImagesSchema,
26
+ };
27
+
28
+ export const tagTempIdSchema = joi.object( {
29
+
30
+ storeId: joi.string().required(),
31
+ dateString: joi.string().required(), // yyyy-mm-dd
32
+ tempId: joi.number().required(),
33
+ revopsType: joi.string().required(),
34
+ timeRange: joi.string().required(),
35
+ dublicateImage: joi.array().optional(),
36
+ processType: joi.string().required(),
37
+ entryTime: joi.string().required(),
38
+ exitTime: joi.string().required(),
39
+ filePath: joi.string().required(),
40
+
41
+ } );
42
+
43
+ export const tagTempIdValid = {
44
+ body: tagTempIdSchema,
45
+ };
46
+
47
+
48
+ export const getCategorizedImagesSchema = joi.object( {
49
+
50
+ storeId: joi.string().required(),
51
+ fileDate: joi.string().required(),
52
+ type: joi.array().optional(),
53
+
54
+ } );
55
+
56
+ export const getCategorizedImagesValid = {
57
+ body: getCategorizedImagesSchema,
58
+ };
59
+
@@ -1,7 +1,8 @@
1
1
 
2
2
  import express from 'express';
3
- import { getconfig, revoptagging, getrevoptagging, revoptaggingcount } from '../controllers/revop.controller.js';
4
- import { isAllowedSessionHandler } from 'tango-app-api-middleware';
3
+ import { storeProcessedData, getconfig, revoptagging, getrevoptagging, revoptaggingcount, footFallImages, tagTempId, getCategorizedImages } from '../controllers/revop.controller.js';
4
+ import { isAllowedSessionHandler, validate } from 'tango-app-api-middleware';
5
+ import { footfallImagesValid, getCategorizedImagesValid, storeProcessedDataValid, tagTempIdValid } from '../dtos/revop.dtos.js';
5
6
 
6
7
  export const revopRouter = express.Router();
7
8
 
@@ -9,6 +10,15 @@ revopRouter
9
10
  .get( '/getconfig', isAllowedSessionHandler, getconfig )
10
11
  .post( '/tagging', isAllowedSessionHandler, revoptagging )
11
12
  .post( '/getrevoptagging', isAllowedSessionHandler, getrevoptagging )
12
- .post( '/revoptaggingcount', isAllowedSessionHandler, revoptaggingcount );
13
+ .post( '/revoptaggingcount', isAllowedSessionHandler, revoptaggingcount )
14
+
15
+ // new enhnacemnet (for footfall directory)
16
+ .get( '/store-processed-data', isAllowedSessionHandler, validate( storeProcessedDataValid ), storeProcessedData )
17
+ .get( '/footfall-images', isAllowedSessionHandler, validate( footfallImagesValid ), footFallImages )
18
+ .post( '/tag-tempId', isAllowedSessionHandler, validate( tagTempIdValid ), tagTempId )
19
+
20
+
21
+ .post( '/get-categorized-images', isAllowedSessionHandler, validate( getCategorizedImagesValid ), getCategorizedImages );
22
+
13
23
 
14
24
  export default revopRouter;
@@ -91,7 +91,7 @@ import {
91
91
  zoneDwellTimeSplitV3,
92
92
  funnelV3,
93
93
  getStoreMapDataV3,
94
- managerTrafficDensityExport,
94
+
95
95
  } from '../controllers/tangoTrafficV3.controllers.js';
96
96
  analysisTrafficRouter
97
97
  .get( '/welcome', welcome )
@@ -174,6 +174,5 @@ analysisTrafficRouter
174
174
  .post( '/headerUserEmails_v2', isAllowedSessionHandler, getUserEmails )
175
175
  .post( '/headerCountry_v2', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateCountryHeaderParamsv2 ), getAssinedStore, headerCountryV2 )
176
176
  .post( '/checkTodayReportStatus', isAllowedSessionHandler, checkTodayReportStatus )
177
- .post( '/headerZoneV2', isAllowedSessionHandler, headerZoneV2 )
178
- .post( '/trafficDensityExport_v2', managerTrafficDensityExport );
177
+ .post( '/headerZoneV2', isAllowedSessionHandler, headerZoneV2 );
179
178
  export default analysisTrafficRouter;