tango-app-api-analysis-traffic 3.8.7-vms.33 → 3.8.7-vms.34
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.34",
|
|
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.5",
|
|
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,7 +3,6 @@ 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';
|
|
7
6
|
|
|
8
7
|
export async function storeList( req, res ) {
|
|
9
8
|
try {
|
|
@@ -28,7 +27,7 @@ export async function storeList( req, res ) {
|
|
|
28
27
|
);
|
|
29
28
|
}
|
|
30
29
|
|
|
31
|
-
const query =
|
|
30
|
+
const query =[
|
|
32
31
|
{
|
|
33
32
|
$match: {
|
|
34
33
|
$and: filter,
|
|
@@ -60,12 +59,11 @@ export async function storeList( req, res ) {
|
|
|
60
59
|
|
|
61
60
|
export async function addBills( req, res ) {
|
|
62
61
|
try {
|
|
63
|
-
let resData
|
|
62
|
+
let resData=[];
|
|
64
63
|
const openSearch = JSON.parse( process.env.OPENSEARCH );
|
|
65
64
|
const inputData = req.tempInserData;
|
|
66
|
-
console.log( '🚀 ~ addBills ~ inputData:', inputData );
|
|
67
65
|
|
|
68
|
-
for ( let i
|
|
66
|
+
for ( let i=0; i<inputData?.length; i++ ) {
|
|
69
67
|
await updateOneNobBilling( inputData[i]?.query, inputData[i]?.data );
|
|
70
68
|
const getData = await findOneNobBilling( inputData[i]?.query, { _id: 0 } );
|
|
71
69
|
if ( !inputData[i]?.isUpdated ) {
|
|
@@ -79,7 +77,7 @@ export async function addBills( req, res ) {
|
|
|
79
77
|
logger.info( { resData: resData } );
|
|
80
78
|
return res.sendSuccess( 'Data has been inserted/updated successfully' );
|
|
81
79
|
} catch ( error ) {
|
|
82
|
-
const err
|
|
80
|
+
const err= error.message || 'Internal Server Error';
|
|
83
81
|
logger.error( { error: error, message: req.body, function: 'nob-addBills' } );
|
|
84
82
|
return res.sendError( err, 500 );
|
|
85
83
|
}
|
|
@@ -93,7 +91,7 @@ export async function getNobData( req, res ) {
|
|
|
93
91
|
return res.sendError( 'No data found', 204 );
|
|
94
92
|
}
|
|
95
93
|
const dateRange = await getUTC( new Date( inputData.fromDate ), new Date( new Date( inputData.toDate ) ) );
|
|
96
|
-
let temp =
|
|
94
|
+
let temp ={};
|
|
97
95
|
let filter = [
|
|
98
96
|
{
|
|
99
97
|
'terms': {
|
|
@@ -101,12 +99,8 @@ export async function getNobData( req, res ) {
|
|
|
101
99
|
},
|
|
102
100
|
},
|
|
103
101
|
{
|
|
104
|
-
range: {
|
|
105
|
-
|
|
106
|
-
gte: dateRange.start,
|
|
107
|
-
lte: dateRange.end,
|
|
108
|
-
},
|
|
109
|
-
},
|
|
102
|
+
range: { nobDate: { gte: dateRange.start,
|
|
103
|
+
lte: dateRange.end } },
|
|
110
104
|
},
|
|
111
105
|
];
|
|
112
106
|
if ( req.user.role !== 'superadmin' && req.user.userType !== 'tango' ) {
|
|
@@ -122,7 +116,7 @@ export async function getNobData( req, res ) {
|
|
|
122
116
|
'must': filter,
|
|
123
117
|
};
|
|
124
118
|
|
|
125
|
-
if ( inputData.searchValue && inputData.searchValue
|
|
119
|
+
if ( inputData.searchValue && inputData.searchValue!== '' ) {
|
|
126
120
|
const searchValue = escapeSpecialChars( inputData.searchValue );
|
|
127
121
|
temp = {
|
|
128
122
|
|
|
@@ -155,9 +149,9 @@ export async function getNobData( req, res ) {
|
|
|
155
149
|
}
|
|
156
150
|
const getClient = await findOne( { clientId: req.clientId }, { featureConfigs: 1 } );
|
|
157
151
|
const openSearch = JSON.parse( process.env.OPENSEARCH );
|
|
158
|
-
const limit = inputData.isExport
|
|
159
|
-
const skip = inputData.offset
|
|
160
|
-
const nobQuery
|
|
152
|
+
const limit = inputData.isExport? 10000 : inputData.limit || 200;
|
|
153
|
+
const skip = inputData.offset? ( inputData.offset - 1 ) * limit : 0;
|
|
154
|
+
const nobQuery={
|
|
161
155
|
'from': skip,
|
|
162
156
|
'size': limit,
|
|
163
157
|
'query': {
|
|
@@ -165,17 +159,17 @@ export async function getNobData( req, res ) {
|
|
|
165
159
|
},
|
|
166
160
|
};
|
|
167
161
|
|
|
168
|
-
const getNobData
|
|
162
|
+
const getNobData=await getOpenSearchData( openSearch.nob, nobQuery );
|
|
169
163
|
const nobData = getNobData?.body?.hits?.hits;
|
|
170
|
-
if ( !nobData ||
|
|
171
|
-
if ( inputData.searchValue && inputData.searchValue
|
|
164
|
+
if ( !nobData ||nobData?.length == 0 ) {
|
|
165
|
+
if ( inputData.searchValue && inputData.searchValue!== '' || inputData.offset> 1 ) {
|
|
172
166
|
return res.sendError( 'No Data Found', 204 );
|
|
173
167
|
} else {
|
|
174
168
|
return res.sendSuccess( { initialInsert: false } );
|
|
175
169
|
}
|
|
176
170
|
}
|
|
177
171
|
|
|
178
|
-
const footfallQuery
|
|
172
|
+
const footfallQuery={
|
|
179
173
|
'size': 10000,
|
|
180
174
|
'query': {
|
|
181
175
|
'bool': {
|
|
@@ -186,33 +180,29 @@ export async function getNobData( req, res ) {
|
|
|
186
180
|
},
|
|
187
181
|
},
|
|
188
182
|
{
|
|
189
|
-
range: {
|
|
190
|
-
|
|
191
|
-
gte: `${inputData.fromDate}T00:00:00`,
|
|
192
|
-
lte: `${inputData.toDate}T00:00:00`,
|
|
193
|
-
},
|
|
194
|
-
},
|
|
183
|
+
range: { date_iso: { gte: `${inputData.fromDate}T00:00:00`,
|
|
184
|
+
lte: `${inputData.toDate}T00:00:00` } },
|
|
195
185
|
},
|
|
196
186
|
],
|
|
197
187
|
},
|
|
198
188
|
},
|
|
199
189
|
};
|
|
200
190
|
|
|
201
|
-
const getFootfall
|
|
191
|
+
const getFootfall= await getOpenSearchData( openSearch.footfall, footfallQuery );
|
|
202
192
|
const footfall = getFootfall?.body?.hits?.hits;
|
|
203
193
|
logger.info( { footfall: getFootfall, nobData: nobData } );
|
|
204
|
-
let result
|
|
194
|
+
let result=[];
|
|
205
195
|
nobData.map( async ( data ) => {
|
|
206
196
|
let count = 0;
|
|
207
|
-
let temp
|
|
197
|
+
let temp=[];
|
|
208
198
|
|
|
209
|
-
data._source.isUpdated = data._source.createdAt !== data._source.updatedAt
|
|
210
|
-
!data._source.isUpdated ? isEdit = true
|
|
199
|
+
data._source.isUpdated = data._source.createdAt !== data._source.updatedAt? true : false;
|
|
200
|
+
!data._source.isUpdated ? isEdit = true: null;
|
|
211
201
|
|
|
212
202
|
footfall.map( ( item ) => {
|
|
213
203
|
if ( ( data._source.dateString === item._source.date_string ) && ( data._source.storeId === item._source.store_id ) ) {
|
|
214
204
|
count = 1;
|
|
215
|
-
temp =
|
|
205
|
+
temp =[
|
|
216
206
|
{
|
|
217
207
|
storeName: item._source.store_name,
|
|
218
208
|
footfallCount: item._source.footfall_count,
|
|
@@ -227,16 +217,16 @@ export async function getNobData( req, res ) {
|
|
|
227
217
|
if ( count === 1 ) {
|
|
228
218
|
switch ( getClient?.featureConfigs?.conversionCalculation ) {
|
|
229
219
|
case 'footfall-count':
|
|
230
|
-
conversionCount = temp[0]?.footfallCount
|
|
220
|
+
conversionCount = temp[0]?.footfallCount? ( data?._source?.nobCount/temp[0]?.footfallCount )*100 : null;
|
|
231
221
|
break;
|
|
232
222
|
case 'billable-entities':
|
|
233
|
-
conversionCount = temp[0]?.potentialBuyers
|
|
223
|
+
conversionCount = temp[0]?.potentialBuyers? ( data?._source?.nobCount/temp[0]?.potentialBuyers )*100 : null;
|
|
234
224
|
break;
|
|
235
225
|
case 'engagers-count':
|
|
236
|
-
conversionCount = temp[0]?.engagersCount
|
|
226
|
+
conversionCount = temp[0]?.engagersCount? ( data?._source?.nobCount/temp[0]?.engagersCount )*100 : null;
|
|
237
227
|
break;
|
|
238
228
|
default:
|
|
239
|
-
conversionCount = temp[0]?.engagersCount
|
|
229
|
+
conversionCount = temp[0]?.engagersCount? ( data?._source?.nobCount/temp[0]?.engagersCount )*100 : null;
|
|
240
230
|
}
|
|
241
231
|
result.push( {
|
|
242
232
|
|
|
@@ -245,7 +235,7 @@ export async function getNobData( req, res ) {
|
|
|
245
235
|
footfallCount: temp[0]?.footfallCount || null,
|
|
246
236
|
engagersCount: temp[0]?.engagersCount || null,
|
|
247
237
|
potentialBuyers: temp[0]?.potentialBuyers || null,
|
|
248
|
-
conversionRate: conversionCount == null ? null
|
|
238
|
+
conversionRate: conversionCount == null ? null :`${Math.round( conversionCount )} %`,
|
|
249
239
|
|
|
250
240
|
} );
|
|
251
241
|
} else {
|
|
@@ -289,7 +279,7 @@ export async function getNobData( req, res ) {
|
|
|
289
279
|
default:
|
|
290
280
|
exportData[index]['Engagers Count'] = element.engagersCount;
|
|
291
281
|
}
|
|
292
|
-
element.conversionRate
|
|
282
|
+
element.conversionRate? exportData[index]['Conversion Rate'] = `${element.conversionRate}` : exportData[index]['Conversion Rate'] =null;
|
|
293
283
|
} );
|
|
294
284
|
return exportData;
|
|
295
285
|
} );
|
|
@@ -311,66 +301,3 @@ export async function getNobData( req, res ) {
|
|
|
311
301
|
function escapeSpecialChars( str ) {
|
|
312
302
|
return str.replace( /[-[\]{}()*+?.,\\^$|#]/g, '\\$&' );
|
|
313
303
|
}
|
|
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
|
-
}
|
|
@@ -584,7 +584,7 @@ export async function migrateRevopIndex( req, res ) {
|
|
|
584
584
|
export async function expireReviewStatus( req, res ) {
|
|
585
585
|
try {
|
|
586
586
|
const {
|
|
587
|
-
thresholdDate = '2025-12-
|
|
587
|
+
thresholdDate = '2025-12-22',
|
|
588
588
|
batchSize = 500,
|
|
589
589
|
storeId,
|
|
590
590
|
dateString,
|
|
@@ -1099,7 +1099,7 @@ export async function footFallImages( req, res ) {
|
|
|
1099
1099
|
actionType: type,
|
|
1100
1100
|
footfall: footfallValue,
|
|
1101
1101
|
revicedFootfall: mapping.revicedFootfall ?? 0,
|
|
1102
|
-
revicedPerc: mapping
|
|
1102
|
+
revicedPerc: mapping?.reviced?.toString() ?? '--',
|
|
1103
1103
|
count: countObj,
|
|
1104
1104
|
createdAt: mapping.createdAt ?? '',
|
|
1105
1105
|
createdByEmail: mapping.createdByEmail ?? '',
|
|
@@ -1114,7 +1114,7 @@ export async function footFallImages( req, res ) {
|
|
|
1114
1114
|
actionType: type,
|
|
1115
1115
|
footfall: footfallValue,
|
|
1116
1116
|
revicedFootfall: mapping.revicedFootfall ?? 0,
|
|
1117
|
-
revicedPerc: mapping
|
|
1117
|
+
revicedPerc: mapping?.reviced?.toString() ?? '--',
|
|
1118
1118
|
count: countObj,
|
|
1119
1119
|
createdAt: mapping.createdAt ?? '',
|
|
1120
1120
|
createdByEmail: mapping.createdByEmail ?? '',
|
package/src/dtos/nob.dtos.js
CHANGED
|
@@ -21,19 +21,6 @@ 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(),
|
|
37
24
|
} ),
|
|
38
25
|
).required(),
|
|
39
26
|
|
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
|
|
4
|
+
import { addBills, getNobData, storeList } 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,8 +13,4 @@ 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
|
-
|
|
20
16
|
export default nobRouter;
|
|
@@ -1,7 +1,6 @@
|
|
|
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 );
|
|
5
4
|
return await nobBillingModel.updateOne( query, { $set: record }, { upsert: true } );
|
|
6
5
|
}
|
|
7
6
|
|
|
@@ -121,7 +121,6 @@ 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:[],
|
|
125
124
|
};
|
|
126
125
|
const query ={ storeId: storeData[0]?.storeId, nobDate: inputFilter[i]?.nobDate };
|
|
127
126
|
|