tango-app-api-analysis-traffic 3.8.7-vms.32 → 3.8.7-vms.33

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.8.7-vms.32",
3
+ "version": "3.8.7-vms.33",
4
4
  "description": "Traffic Analysis",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -23,7 +23,7 @@
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.5.5",
26
+ "tango-api-schema": "^2.5.14",
27
27
  "tango-app-api-middleware": "^3.6.5",
28
28
  "winston": "^3.13.1",
29
29
  "winston-daily-rotate-file": "^5.0.0"
@@ -3,6 +3,7 @@ import { aggregateStore } from '../services/stores.service.js';
3
3
  import { findOneNobBilling, updateOneNobBilling } from '../services/nob.service.js';
4
4
  import dayjs from 'dayjs';
5
5
  import { findOne } from '../services/clients.services.js';
6
+ import { find } from '../services/tagging.service.js';
6
7
 
7
8
  export async function storeList( req, res ) {
8
9
  try {
@@ -27,7 +28,7 @@ export async function storeList( req, res ) {
27
28
  );
28
29
  }
29
30
 
30
- const query =[
31
+ const query = [
31
32
  {
32
33
  $match: {
33
34
  $and: filter,
@@ -59,11 +60,12 @@ export async function storeList( req, res ) {
59
60
 
60
61
  export async function addBills( req, res ) {
61
62
  try {
62
- let resData=[];
63
+ let resData = [];
63
64
  const openSearch = JSON.parse( process.env.OPENSEARCH );
64
65
  const inputData = req.tempInserData;
66
+ console.log( '🚀 ~ addBills ~ inputData:', inputData );
65
67
 
66
- for ( let i=0; i<inputData?.length; i++ ) {
68
+ for ( let i = 0; i < inputData?.length; i++ ) {
67
69
  await updateOneNobBilling( inputData[i]?.query, inputData[i]?.data );
68
70
  const getData = await findOneNobBilling( inputData[i]?.query, { _id: 0 } );
69
71
  if ( !inputData[i]?.isUpdated ) {
@@ -77,7 +79,7 @@ export async function addBills( req, res ) {
77
79
  logger.info( { resData: resData } );
78
80
  return res.sendSuccess( 'Data has been inserted/updated successfully' );
79
81
  } catch ( error ) {
80
- const err= error.message || 'Internal Server Error';
82
+ const err = error.message || 'Internal Server Error';
81
83
  logger.error( { error: error, message: req.body, function: 'nob-addBills' } );
82
84
  return res.sendError( err, 500 );
83
85
  }
@@ -91,7 +93,7 @@ export async function getNobData( req, res ) {
91
93
  return res.sendError( 'No data found', 204 );
92
94
  }
93
95
  const dateRange = await getUTC( new Date( inputData.fromDate ), new Date( new Date( inputData.toDate ) ) );
94
- let temp ={};
96
+ let temp = {};
95
97
  let filter = [
96
98
  {
97
99
  'terms': {
@@ -99,8 +101,12 @@ export async function getNobData( req, res ) {
99
101
  },
100
102
  },
101
103
  {
102
- range: { nobDate: { gte: dateRange.start,
103
- lte: dateRange.end } },
104
+ range: {
105
+ nobDate: {
106
+ gte: dateRange.start,
107
+ lte: dateRange.end,
108
+ },
109
+ },
104
110
  },
105
111
  ];
106
112
  if ( req.user.role !== 'superadmin' && req.user.userType !== 'tango' ) {
@@ -116,7 +122,7 @@ export async function getNobData( req, res ) {
116
122
  'must': filter,
117
123
  };
118
124
 
119
- if ( inputData.searchValue && inputData.searchValue!== '' ) {
125
+ if ( inputData.searchValue && inputData.searchValue !== '' ) {
120
126
  const searchValue = escapeSpecialChars( inputData.searchValue );
121
127
  temp = {
122
128
 
@@ -149,9 +155,9 @@ export async function getNobData( req, res ) {
149
155
  }
150
156
  const getClient = await findOne( { clientId: req.clientId }, { featureConfigs: 1 } );
151
157
  const openSearch = JSON.parse( process.env.OPENSEARCH );
152
- const limit = inputData.isExport? 10000 : inputData.limit || 200;
153
- const skip = inputData.offset? ( inputData.offset - 1 ) * limit : 0;
154
- const nobQuery={
158
+ const limit = inputData.isExport ? 10000 : inputData.limit || 200;
159
+ const skip = inputData.offset ? ( inputData.offset - 1 ) * limit : 0;
160
+ const nobQuery = {
155
161
  'from': skip,
156
162
  'size': limit,
157
163
  'query': {
@@ -159,17 +165,17 @@ export async function getNobData( req, res ) {
159
165
  },
160
166
  };
161
167
 
162
- const getNobData=await getOpenSearchData( openSearch.nob, nobQuery );
168
+ const getNobData = await getOpenSearchData( openSearch.nob, nobQuery );
163
169
  const nobData = getNobData?.body?.hits?.hits;
164
- if ( !nobData ||nobData?.length == 0 ) {
165
- if ( inputData.searchValue && inputData.searchValue!== '' || inputData.offset> 1 ) {
170
+ if ( !nobData || nobData?.length == 0 ) {
171
+ if ( inputData.searchValue && inputData.searchValue !== '' || inputData.offset > 1 ) {
166
172
  return res.sendError( 'No Data Found', 204 );
167
173
  } else {
168
174
  return res.sendSuccess( { initialInsert: false } );
169
175
  }
170
176
  }
171
177
 
172
- const footfallQuery={
178
+ const footfallQuery = {
173
179
  'size': 10000,
174
180
  'query': {
175
181
  'bool': {
@@ -180,29 +186,33 @@ export async function getNobData( req, res ) {
180
186
  },
181
187
  },
182
188
  {
183
- range: { date_iso: { gte: `${inputData.fromDate}T00:00:00`,
184
- lte: `${inputData.toDate}T00:00:00` } },
189
+ range: {
190
+ date_iso: {
191
+ gte: `${inputData.fromDate}T00:00:00`,
192
+ lte: `${inputData.toDate}T00:00:00`,
193
+ },
194
+ },
185
195
  },
186
196
  ],
187
197
  },
188
198
  },
189
199
  };
190
200
 
191
- const getFootfall= await getOpenSearchData( openSearch.footfall, footfallQuery );
201
+ const getFootfall = await getOpenSearchData( openSearch.footfall, footfallQuery );
192
202
  const footfall = getFootfall?.body?.hits?.hits;
193
203
  logger.info( { footfall: getFootfall, nobData: nobData } );
194
- let result=[];
204
+ let result = [];
195
205
  nobData.map( async ( data ) => {
196
206
  let count = 0;
197
- let temp=[];
207
+ let temp = [];
198
208
 
199
- data._source.isUpdated = data._source.createdAt !== data._source.updatedAt? true : false;
200
- !data._source.isUpdated ? isEdit = true: null;
209
+ data._source.isUpdated = data._source.createdAt !== data._source.updatedAt ? true : false;
210
+ !data._source.isUpdated ? isEdit = true : null;
201
211
 
202
212
  footfall.map( ( item ) => {
203
213
  if ( ( data._source.dateString === item._source.date_string ) && ( data._source.storeId === item._source.store_id ) ) {
204
214
  count = 1;
205
- temp =[
215
+ temp = [
206
216
  {
207
217
  storeName: item._source.store_name,
208
218
  footfallCount: item._source.footfall_count,
@@ -217,16 +227,16 @@ export async function getNobData( req, res ) {
217
227
  if ( count === 1 ) {
218
228
  switch ( getClient?.featureConfigs?.conversionCalculation ) {
219
229
  case 'footfall-count':
220
- conversionCount = temp[0]?.footfallCount? ( data?._source?.nobCount/temp[0]?.footfallCount )*100 : null;
230
+ conversionCount = temp[0]?.footfallCount ? ( data?._source?.nobCount / temp[0]?.footfallCount ) * 100 : null;
221
231
  break;
222
232
  case 'billable-entities':
223
- conversionCount = temp[0]?.potentialBuyers? ( data?._source?.nobCount/temp[0]?.potentialBuyers )*100 : null;
233
+ conversionCount = temp[0]?.potentialBuyers ? ( data?._source?.nobCount / temp[0]?.potentialBuyers ) * 100 : null;
224
234
  break;
225
235
  case 'engagers-count':
226
- conversionCount = temp[0]?.engagersCount? ( data?._source?.nobCount/temp[0]?.engagersCount )*100 : null;
236
+ conversionCount = temp[0]?.engagersCount ? ( data?._source?.nobCount / temp[0]?.engagersCount ) * 100 : null;
227
237
  break;
228
238
  default:
229
- conversionCount = temp[0]?.engagersCount? ( data?._source?.nobCount/temp[0]?.engagersCount )*100 : null;
239
+ conversionCount = temp[0]?.engagersCount ? ( data?._source?.nobCount / temp[0]?.engagersCount ) * 100 : null;
230
240
  }
231
241
  result.push( {
232
242
 
@@ -235,7 +245,7 @@ export async function getNobData( req, res ) {
235
245
  footfallCount: temp[0]?.footfallCount || null,
236
246
  engagersCount: temp[0]?.engagersCount || null,
237
247
  potentialBuyers: temp[0]?.potentialBuyers || null,
238
- conversionRate: conversionCount == null ? null :`${Math.round( conversionCount )} %`,
248
+ conversionRate: conversionCount == null ? null : `${Math.round( conversionCount )} %`,
239
249
 
240
250
  } );
241
251
  } else {
@@ -279,7 +289,7 @@ export async function getNobData( req, res ) {
279
289
  default:
280
290
  exportData[index]['Engagers Count'] = element.engagersCount;
281
291
  }
282
- element.conversionRate? exportData[index]['Conversion Rate'] = `${element.conversionRate}` : exportData[index]['Conversion Rate'] =null;
292
+ element.conversionRate ? exportData[index]['Conversion Rate'] = `${element.conversionRate}` : exportData[index]['Conversion Rate'] = null;
283
293
  } );
284
294
  return exportData;
285
295
  } );
@@ -301,3 +311,66 @@ export async function getNobData( req, res ) {
301
311
  function escapeSpecialChars( str ) {
302
312
  return str.replace( /[-[\]{}()*+?.,\\^$|#]/g, '\\$&' );
303
313
  }
314
+
315
+
316
+ export async function zonelist( req, res ) {
317
+ try {
318
+ let zonelist = await find( { storeId: { $in: req.body.storeId }, productName: 'tangoZone' }, { tagName: 1 } );
319
+ return res.sendSuccess( zonelist );
320
+ } catch ( error ) {
321
+ const err = error.message || 'Internal Server Error';
322
+ logger.error( { error: error, message: req.body, function: 'nob-getNobData' } );
323
+ return res.sendError( err, 500 );
324
+ }
325
+ }
326
+ export async function zonetemplate( req, res ) {
327
+ try {
328
+ if ( req.user.userType === 'tango'||req.user.userType === 'client'&&req.user.role==='superadmin' ) {
329
+ let storeList = await aggregateStore(
330
+ [
331
+ {
332
+ $match: {
333
+ clientId: req.body.clientId,
334
+ },
335
+ },
336
+ ],
337
+ );
338
+
339
+
340
+ let stores = storeList.map( ( data ) => data.storeId );
341
+
342
+ req.body.assignedStores = stores;
343
+ }
344
+
345
+
346
+ let exportData = [];
347
+ const zonelist = await find(
348
+ { storeId: { $in: req.body.assignedStores }, productName: 'tangoZone' },
349
+ { tagName: 1, storeId: 1 },
350
+ );
351
+ let uniqueZone = zonelist.map( ( data ) => data.tagName );
352
+
353
+ for ( const element of req.body.assignedStores ) {
354
+ const row = {
355
+ 'Store Id': element,
356
+ 'NoB Date': '',
357
+ 'Overall NoB Count': '',
358
+ };
359
+
360
+ // make tagName as key
361
+ uniqueZone.forEach( ( zone ) => {
362
+ row[zone] = ''; // or 0 / true / any value you want
363
+ } );
364
+
365
+ exportData.push( row );
366
+ }
367
+
368
+
369
+ await download( exportData, res );
370
+ return;
371
+ } catch ( error ) {
372
+ const err = error.message || 'Internal Server Error';
373
+ logger.error( { error: error, message: req.body, function: 'nob-getNobData' } );
374
+ return res.sendError( err, 500 );
375
+ }
376
+ }
@@ -21,6 +21,19 @@ export const addBillsSchema = joi.object( {
21
21
  'string.empty': 'Please enter a valid NOB Count',
22
22
  'any.required': 'NOB Count is required',
23
23
  } ).allow( null ),
24
+ zonewisenob: joi.array().items(
25
+ joi.object( {
26
+ zoneName: joi.string().required().messages( {
27
+ 'string.empty': 'Zone name is required',
28
+ 'any.required': 'Zone name is required',
29
+ } ),
30
+
31
+ nobCount: joi.number().required().messages( {
32
+ 'number.base': 'Please enter a valid Zone NOB Count',
33
+ 'any.required': 'Zone NOB Count is required',
34
+ } ),
35
+ } ),
36
+ ).optional(),
24
37
  } ),
25
38
  ).required(),
26
39
 
@@ -1,7 +1,7 @@
1
1
  import express from 'express';
2
2
  import { accessVerification, bulkValidate, getAssinedStore, isAllowedSessionHandler, validate } from 'tango-app-api-middleware';
3
3
  import { addBillsValid, getNobDataValid, storeListValid } from '../dtos/nob.dtos.js';
4
- import { addBills, getNobData, storeList } from '../controllers/nob.controllers.js';
4
+ import { addBills, getNobData, storeList, zonelist, zonetemplate } from '../controllers/nob.controllers.js';
5
5
  import { clientValidations, fieldValidation, roleVerification } from '../validations/nob.validations.js';
6
6
 
7
7
  const nobRouter=express.Router();
@@ -13,4 +13,8 @@ nobRouter.post( '/add-bills', isAllowedSessionHandler, accessVerification( { use
13
13
 
14
14
  nobRouter.post( '/get-nob-data', isAllowedSessionHandler, accessVerification( { userType: [ 'client', 'tango' ] } ), validate( getNobDataValid ), clientValidations, getAssinedStore, getNobData );
15
15
 
16
+ nobRouter.post( '/zonelist', isAllowedSessionHandler, accessVerification( { userType: [ 'client', 'tango' ] } ), zonelist );
17
+
18
+ nobRouter.post( '/zonetemplate', isAllowedSessionHandler, accessVerification( { userType: [ 'client', 'tango' ] } ), getAssinedStore, zonetemplate );
19
+
16
20
  export default nobRouter;
@@ -1,6 +1,7 @@
1
1
  import nobBillingModel from 'tango-api-schema/schema/nobBilling.model.js';
2
2
 
3
3
  export async function updateOneNobBilling( query, record ) {
4
+ console.log( '🚀 ~ updateOneNobBilling ~ record:', record );
4
5
  return await nobBillingModel.updateOne( query, { $set: record }, { upsert: true } );
5
6
  }
6
7
 
@@ -121,6 +121,7 @@ export async function fieldValidation( req, res, next ) {
121
121
  nobDate: nobDateIso,
122
122
  nobCount: inputFilter[i]?.nobCount,
123
123
  dateString: inputFilter[i]?.nobDate,
124
+ zonewisenob: inputFilter[i]?.zonewisenob?inputFilter[i]?.zonewisenob:[],
124
125
  };
125
126
  const query ={ storeId: storeData[0]?.storeId, nobDate: inputFilter[i]?.nobDate };
126
127