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.
|
|
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.
|
|
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: {
|
|
103
|
-
|
|
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: {
|
|
184
|
-
|
|
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
|
|
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
|
+
}
|
package/src/dtos/nob.dtos.js
CHANGED
|
@@ -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
|
|
package/src/routes/nob.routes.js
CHANGED
|
@@ -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
|
|