tango-app-api-audit 1.0.40 → 1.0.42
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 +1 -1
- package/src/controllers/auditMetrics.controllers.js +220 -47
- package/src/controllers/zoneAudit.controller.js +379 -108
- package/src/docs/zoneAudit.docs.js +48 -1
- package/src/dtos/auditMetrics.dtos.js +4 -1
- package/src/dtos/zoneAudit.dtos.js +40 -0
- package/src/routes/zone.routes.js +7 -2
package/package.json
CHANGED
|
@@ -36,9 +36,9 @@ export async function userAuditHistory( req, res ) {
|
|
|
36
36
|
);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
if ( inputData.
|
|
39
|
+
if ( inputData.filterByAuditType?.length > 0 ) {
|
|
40
40
|
filter.push( {
|
|
41
|
-
moduleType: { $in: inputData.
|
|
41
|
+
moduleType: { $in: inputData.filterByAuditType },
|
|
42
42
|
} );
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -63,14 +63,6 @@ export async function userAuditHistory( req, res ) {
|
|
|
63
63
|
];
|
|
64
64
|
|
|
65
65
|
|
|
66
|
-
if ( inputData.sortColumnName ) {
|
|
67
|
-
const sortBy = inputData.sortBy || -1;
|
|
68
|
-
query.push( {
|
|
69
|
-
$sort: { [inputData.sortColumName]: sortBy },
|
|
70
|
-
},
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
66
|
query.push( {
|
|
75
67
|
$lookup: {
|
|
76
68
|
from: 'stores',
|
|
@@ -93,17 +85,50 @@ export async function userAuditHistory( req, res ) {
|
|
|
93
85
|
|
|
94
86
|
} );
|
|
95
87
|
|
|
88
|
+
|
|
96
89
|
query.push( {
|
|
97
90
|
$unwind: {
|
|
98
91
|
path: '$store', preserveNullAndEmptyArrays: true,
|
|
99
92
|
},
|
|
100
93
|
} );
|
|
101
94
|
|
|
95
|
+
query.push( {
|
|
96
|
+
$lookup: {
|
|
97
|
+
from: 'clients',
|
|
98
|
+
let: { clientId: '$clientId' },
|
|
99
|
+
pipeline: [
|
|
100
|
+
{
|
|
101
|
+
$match: {
|
|
102
|
+
$expr: {
|
|
103
|
+
$eq: [ '$clientId', '$$clientId' ],
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
$project: {
|
|
109
|
+
clientName: 1,
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
], as: 'client',
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
} );
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
query.push( {
|
|
119
|
+
$unwind: {
|
|
120
|
+
path: '$client', preserveNullAndEmptyArrays: true,
|
|
121
|
+
},
|
|
122
|
+
} );
|
|
123
|
+
|
|
102
124
|
query.push( {
|
|
103
125
|
$project: {
|
|
104
126
|
storeId: 1,
|
|
105
127
|
userId: 1,
|
|
106
128
|
storeName: '$store.storeName',
|
|
129
|
+
clientId: 1,
|
|
130
|
+
clientName: 'client.clientName',
|
|
131
|
+
fileDate: 1,
|
|
107
132
|
auditType: 1,
|
|
108
133
|
zoneName: 1,
|
|
109
134
|
moduleType: 1,
|
|
@@ -112,14 +137,51 @@ export async function userAuditHistory( req, res ) {
|
|
|
112
137
|
accuracy: { $round: [
|
|
113
138
|
{
|
|
114
139
|
$divide: [ { $multiply: [ '$beforeCount', { $ifNull: [ '$afterCount', 0 ] } ] }, 100 ],
|
|
115
|
-
},
|
|
140
|
+
}, 1,
|
|
116
141
|
],
|
|
117
142
|
},
|
|
118
|
-
startTime:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
143
|
+
startTime: {
|
|
144
|
+
$dateToString: {
|
|
145
|
+
format: '%Y-%m-%d %H:%M:%S',
|
|
146
|
+
date: '$startTime',
|
|
147
|
+
timezone: 'Asia/Kolkata',
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
endTime: {
|
|
151
|
+
$dateToString: {
|
|
152
|
+
format: '%Y-%m-%d %H:%M:%S',
|
|
153
|
+
date: '$endTime',
|
|
154
|
+
timezone: 'Asia/Kolkata',
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
// timeSpent: { $round: [
|
|
158
|
+
// { $divide: [ '$timeSpent', 60 ] }, 2,
|
|
159
|
+
// ] },
|
|
160
|
+
timeSpent: {
|
|
161
|
+
|
|
162
|
+
$cond: [
|
|
163
|
+
{ $lt: [ '$timeSpent', 60 ] }, // Case 1: If less than 60 seconds
|
|
164
|
+
{ $concat: [ { $toString: '$timeSpent' }, ' sec' ] },
|
|
165
|
+
{
|
|
166
|
+
$cond: [
|
|
167
|
+
{ $lt: [ '$timeSpent', 3600 ] }, // Case 2: If less than 60 minutes (3600 seconds)
|
|
168
|
+
{
|
|
169
|
+
$concat: [
|
|
170
|
+
{ $toString: { $round: [ { $divide: [ '$timeSpent', 60 ] }, 1 ] } }, // Convert to minutes
|
|
171
|
+
' min',
|
|
172
|
+
],
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
$concat: [
|
|
176
|
+
{ $toString: { $round: [ { $divide: [ '$timeSpent', 3600 ] }, 1 ] } }, // Convert to hours
|
|
177
|
+
' hr',
|
|
178
|
+
],
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
|
|
184
|
+
},
|
|
123
185
|
auditStatus: 1,
|
|
124
186
|
createdAt: 1,
|
|
125
187
|
},
|
|
@@ -129,17 +191,26 @@ export async function userAuditHistory( req, res ) {
|
|
|
129
191
|
query.push( {
|
|
130
192
|
$match: {
|
|
131
193
|
$or: [
|
|
194
|
+
{ clientName: { $regex: inputData.searchValue, $options: 'i' } },
|
|
195
|
+
{ clientType: { $regex: inputData.searchValue, $options: 'i' } },
|
|
132
196
|
{ zoneName: { $regex: inputData.searchValue, $options: 'i' } },
|
|
133
|
-
{ storeId: { $regex: inputData.
|
|
134
|
-
{ storeName: { $regex: inputData.
|
|
135
|
-
{ moduleType: { $regex: inputData.
|
|
136
|
-
{ auditStatus: { $regex: inputData.
|
|
197
|
+
{ storeId: { $regex: inputData.searchValue, $options: 'i' } },
|
|
198
|
+
{ storeName: { $regex: inputData.searchValue, $options: 'i' } },
|
|
199
|
+
{ moduleType: { $regex: inputData.searchValue, $options: 'i' } },
|
|
200
|
+
{ auditStatus: { $regex: inputData.searchValue, $options: 'i' } },
|
|
137
201
|
],
|
|
138
202
|
|
|
139
203
|
},
|
|
140
204
|
} );
|
|
141
205
|
}
|
|
142
206
|
|
|
207
|
+
if ( inputData.sortColumnName ) {
|
|
208
|
+
const sortBy = inputData.sortBy || -1;
|
|
209
|
+
query.push( {
|
|
210
|
+
$sort: { [inputData.sortColumName]: sortBy },
|
|
211
|
+
},
|
|
212
|
+
);
|
|
213
|
+
}
|
|
143
214
|
const count = await aggregateUserAudit( query );
|
|
144
215
|
if ( count.length == 0 ) {
|
|
145
216
|
return res.sendError( 'No Data Found', 204 );
|
|
@@ -151,6 +222,8 @@ export async function userAuditHistory( req, res ) {
|
|
|
151
222
|
const exportData = [];
|
|
152
223
|
chunk.forEach( ( element ) => {
|
|
153
224
|
exportData.push( {
|
|
225
|
+
'Client Id': element.clientId,
|
|
226
|
+
'Client Name': element.clientName,
|
|
154
227
|
'Store Id': element.storeId,
|
|
155
228
|
'Store Name': element.storeName,
|
|
156
229
|
'Type': element.auditType,
|
|
@@ -163,7 +236,7 @@ export async function userAuditHistory( req, res ) {
|
|
|
163
236
|
'End Time': element.endTime,
|
|
164
237
|
'Time Spent': element.timeSpent,
|
|
165
238
|
'Audit Status': element.auditStatus,
|
|
166
|
-
'CreatedAt': element.createdAt,
|
|
239
|
+
'CreatedAt': dayjs( element.createdAt ).format( 'YYYY,MMM D' ),
|
|
167
240
|
|
|
168
241
|
} );
|
|
169
242
|
} );
|
|
@@ -184,7 +257,7 @@ export async function userAuditHistory( req, res ) {
|
|
|
184
257
|
} );
|
|
185
258
|
const result = await aggregateUserAudit( query );
|
|
186
259
|
|
|
187
|
-
return res.sendSuccess( { result: result } );
|
|
260
|
+
return res.sendSuccess( { result: result, count: count.length } );
|
|
188
261
|
} catch ( error ) {
|
|
189
262
|
const err = error.message || 'Internal Server Error';
|
|
190
263
|
logger.info( { error: error, message: req.body, function: 'userAuditHistory' } );
|
|
@@ -214,6 +287,10 @@ export async function storeMetrics( req, res ) {
|
|
|
214
287
|
filter.push( { status: { $in: inputData.filterByStatus } } );
|
|
215
288
|
}
|
|
216
289
|
|
|
290
|
+
if ( inputData.filterByType && inputData.filterByType?.length > 0 ) {
|
|
291
|
+
filter.push( { auditType: { $in: inputData.filterByType } } );
|
|
292
|
+
}
|
|
293
|
+
|
|
217
294
|
|
|
218
295
|
const query = [
|
|
219
296
|
{
|
|
@@ -221,16 +298,45 @@ export async function storeMetrics( req, res ) {
|
|
|
221
298
|
$and: filter,
|
|
222
299
|
},
|
|
223
300
|
},
|
|
301
|
+
|
|
302
|
+
{
|
|
303
|
+
$lookup: {
|
|
304
|
+
from: 'stores',
|
|
305
|
+
let: { storeId: '$storeId' },
|
|
306
|
+
pipeline: [
|
|
307
|
+
{
|
|
308
|
+
$match: {
|
|
309
|
+
$expr: {
|
|
310
|
+
$eq: [ '$storeId', '$$storeId' ],
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
$project: {
|
|
316
|
+
_id: 0,
|
|
317
|
+
storeName: 1,
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
], as: 'stores',
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
$unwind: {
|
|
325
|
+
path: '$stores',
|
|
326
|
+
preserveNullAndEmptyArrays: true,
|
|
327
|
+
},
|
|
328
|
+
},
|
|
224
329
|
{
|
|
225
330
|
$project: {
|
|
226
331
|
_id: 0,
|
|
227
332
|
fileDate: 1,
|
|
228
333
|
storeId: 1,
|
|
229
|
-
storeName: '$
|
|
334
|
+
storeName: '$store.storeName',
|
|
335
|
+
clientName: '',
|
|
336
|
+
clientId: 1,
|
|
230
337
|
userId: {
|
|
231
338
|
$arrayElemAt: [ '$userId', { $subtract: [ { $size: '$userId' }, 1 ] } ],
|
|
232
339
|
},
|
|
233
|
-
clientId: 1,
|
|
234
340
|
auditType: 1,
|
|
235
341
|
beforeCount: 1,
|
|
236
342
|
afterCount: { $ifNull: [ '$afterCount', null ] },
|
|
@@ -247,56 +353,56 @@ export async function storeMetrics( req, res ) {
|
|
|
247
353
|
},
|
|
248
354
|
{
|
|
249
355
|
$lookup: {
|
|
250
|
-
from: '
|
|
251
|
-
let: {
|
|
356
|
+
from: 'users',
|
|
357
|
+
let: { userId: '$userId' },
|
|
252
358
|
pipeline: [
|
|
253
359
|
{
|
|
254
360
|
$match: {
|
|
255
361
|
$expr: {
|
|
256
|
-
$eq: [ '$
|
|
362
|
+
$eq: [ '$_id', '$$userId' ],
|
|
257
363
|
},
|
|
258
364
|
},
|
|
259
365
|
},
|
|
260
366
|
{
|
|
261
367
|
$project: {
|
|
262
368
|
_id: 0,
|
|
263
|
-
|
|
369
|
+
userName: 1,
|
|
370
|
+
userEmail: '$email',
|
|
264
371
|
},
|
|
265
372
|
},
|
|
266
|
-
], as: '
|
|
373
|
+
], as: 'users',
|
|
267
374
|
},
|
|
268
375
|
},
|
|
269
376
|
{
|
|
270
377
|
$unwind: {
|
|
271
|
-
path: '$
|
|
378
|
+
path: '$users',
|
|
272
379
|
preserveNullAndEmptyArrays: true,
|
|
273
380
|
},
|
|
274
381
|
},
|
|
275
382
|
{
|
|
276
383
|
$lookup: {
|
|
277
|
-
from: '
|
|
278
|
-
let: {
|
|
384
|
+
from: 'clients',
|
|
385
|
+
let: { clientId: '$clientId' },
|
|
279
386
|
pipeline: [
|
|
280
387
|
{
|
|
281
388
|
$match: {
|
|
282
389
|
$expr: {
|
|
283
|
-
$eq: [ '$
|
|
390
|
+
$eq: [ '$clientId', '$$clientId' ],
|
|
284
391
|
},
|
|
285
392
|
},
|
|
286
393
|
},
|
|
287
394
|
{
|
|
288
395
|
$project: {
|
|
289
396
|
_id: 0,
|
|
290
|
-
|
|
291
|
-
userEmail: '$email',
|
|
397
|
+
clientName: 1,
|
|
292
398
|
},
|
|
293
399
|
},
|
|
294
|
-
], as: '
|
|
400
|
+
], as: 'client',
|
|
295
401
|
},
|
|
296
402
|
},
|
|
297
403
|
{
|
|
298
404
|
$unwind: {
|
|
299
|
-
path: '$
|
|
405
|
+
path: '$client',
|
|
300
406
|
preserveNullAndEmptyArrays: true,
|
|
301
407
|
},
|
|
302
408
|
},
|
|
@@ -308,19 +414,43 @@ export async function storeMetrics( req, res ) {
|
|
|
308
414
|
storeName: '$stores.storeName',
|
|
309
415
|
userName: '$users.userName',
|
|
310
416
|
userEmail: '$users.userEmail',
|
|
311
|
-
|
|
312
417
|
clientId: 1,
|
|
418
|
+
clientName: '$client.clientName',
|
|
313
419
|
auditType: 1,
|
|
314
420
|
beforeCount: 1,
|
|
315
421
|
afterCount: { $ifNull: [ '$afterCount', null ] },
|
|
316
422
|
accuracy: { $round: [
|
|
317
423
|
{ $divide: [
|
|
318
424
|
{ $multiply: [ { $ifNull: [ '$afterCount', 0 ] }, '$beforeCount' ] }, 100,
|
|
319
|
-
] },
|
|
425
|
+
] }, 1,
|
|
320
426
|
],
|
|
321
427
|
|
|
322
428
|
},
|
|
323
|
-
timeSpent:
|
|
429
|
+
timeSpent: {
|
|
430
|
+
|
|
431
|
+
$cond: [
|
|
432
|
+
{ $lt: [ '$timeSpent', 60 ] }, // Case 1: If less than 60 seconds
|
|
433
|
+
{ $concat: [ { $toString: '$timeSpent' }, ' sec' ] },
|
|
434
|
+
{
|
|
435
|
+
$cond: [
|
|
436
|
+
{ $lt: [ '$timeSpent', 3600 ] }, // Case 2: If less than 60 minutes (3600 seconds)
|
|
437
|
+
{
|
|
438
|
+
$concat: [
|
|
439
|
+
{ $toString: { $round: [ { $divide: [ '$timeSpent', 60 ] }, 1 ] } }, // Convert to minutes
|
|
440
|
+
' min',
|
|
441
|
+
],
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
$concat: [
|
|
445
|
+
{ $toString: { $round: [ { $divide: [ '$timeSpent', 3600 ] }, 1 ] } }, // Convert to hours
|
|
446
|
+
' hr',
|
|
447
|
+
],
|
|
448
|
+
},
|
|
449
|
+
],
|
|
450
|
+
},
|
|
451
|
+
],
|
|
452
|
+
|
|
453
|
+
},
|
|
324
454
|
status: 1,
|
|
325
455
|
},
|
|
326
456
|
},
|
|
@@ -333,10 +463,23 @@ export async function storeMetrics( req, res ) {
|
|
|
333
463
|
$or: [
|
|
334
464
|
{ clientId: { $regex: inputData.searchValue, $options: 'i' } },
|
|
335
465
|
{ clientName: { $regex: inputData.searchValue, $options: 'i' } },
|
|
466
|
+
{ storeId: { $regex: inputData.searchValue, $options: 'i' } },
|
|
467
|
+
{ storeName: { $regex: inputData.searchValue, $options: 'i' } },
|
|
468
|
+
{ userName: { $regex: inputData.searchValue, $options: 'i' } },
|
|
469
|
+
{ status: { $regex: inputData.searchValue, $options: 'i' } },
|
|
470
|
+
{ auditType: { $regex: inputData.searchValue, $options: 'i' } },
|
|
336
471
|
],
|
|
337
472
|
},
|
|
338
473
|
} );
|
|
339
474
|
}
|
|
475
|
+
|
|
476
|
+
if ( inputData.sortColumnName ) {
|
|
477
|
+
const sortBy = inputData.sortBy || -1;
|
|
478
|
+
query.push( {
|
|
479
|
+
$sort: { [inputData.sortColumName]: sortBy },
|
|
480
|
+
},
|
|
481
|
+
);
|
|
482
|
+
}
|
|
340
483
|
const count = await aggregateStoreAudit( query );
|
|
341
484
|
|
|
342
485
|
if ( count.length == 0 ) {
|
|
@@ -361,6 +504,7 @@ export async function storeMetrics( req, res ) {
|
|
|
361
504
|
'Store Id': element.storeId,
|
|
362
505
|
'Store Name': element.storeName,
|
|
363
506
|
'Client Id': element.clientId,
|
|
507
|
+
'Client Name': element.clientName,
|
|
364
508
|
'User Name': element.userName,
|
|
365
509
|
'User Email': element.userEmail,
|
|
366
510
|
'Audit Type': element.auditType,
|
|
@@ -389,6 +533,7 @@ export async function clientMetrics( req, res ) {
|
|
|
389
533
|
let filter = [
|
|
390
534
|
{ fileDateISO: { $gte: dateRange.start } },
|
|
391
535
|
{ fileDateISO: { $lte: dateRange.end } },
|
|
536
|
+
{ moduleType: { $eq: 'traffic' } },
|
|
392
537
|
|
|
393
538
|
];
|
|
394
539
|
if ( inputData?.filterByClient?.length> 0 ) {
|
|
@@ -433,6 +578,7 @@ export async function clientMetrics( req, res ) {
|
|
|
433
578
|
{
|
|
434
579
|
$project: {
|
|
435
580
|
completedStores: { $cond: [ { $eq: [ '$status', 'completed' ] }, 1, 0 ] },
|
|
581
|
+
notAssignedStores: { $cond: [ { $eq: [ '$status', 'not_assign' ] }, 1, 0 ] },
|
|
436
582
|
inprogressStores: { $cond: [ { $in: [ '$status', [ 'inprogress', 'drafted', 'assigned' ] ] }, 1, 0 ] },
|
|
437
583
|
},
|
|
438
584
|
},
|
|
@@ -441,6 +587,8 @@ export async function clientMetrics( req, res ) {
|
|
|
441
587
|
_id: { clientId: '$clientId', fileDate: '$fileDate' },
|
|
442
588
|
completedStores: { $sum: '$completedStores' },
|
|
443
589
|
inprogressStores: { $sum: '$inprogressStores' },
|
|
590
|
+
notAssignedStores: { $sum: '$notAssignedStores' },
|
|
591
|
+
fileCount: { $sum: 1 },
|
|
444
592
|
},
|
|
445
593
|
},
|
|
446
594
|
{
|
|
@@ -448,6 +596,8 @@ export async function clientMetrics( req, res ) {
|
|
|
448
596
|
_id: 0,
|
|
449
597
|
completedStores: 1,
|
|
450
598
|
inprogressStores: 1,
|
|
599
|
+
notAssignedStores: 1,
|
|
600
|
+
fileCount: 1,
|
|
451
601
|
completionPercentage: { $ifNull: [
|
|
452
602
|
{
|
|
453
603
|
$round: [ {
|
|
@@ -482,15 +632,18 @@ export async function clientMetrics( req, res ) {
|
|
|
482
632
|
clientName: 1,
|
|
483
633
|
totalFilesCount: 1,
|
|
484
634
|
installedStore: 1,
|
|
635
|
+
notAssignedStores: '$storeAudit.notAssignedStores',
|
|
485
636
|
inprogressStoresCount: '$storeAudit.inprogressStores',
|
|
637
|
+
fileCount: '$storeAudit.fileCount',
|
|
486
638
|
notAssignedCount: 1,
|
|
487
|
-
clientStatus: { $cond: [ { $
|
|
639
|
+
clientStatus: { $cond: [ { $eq: [ '$storeAudit.fileCount', 0 ] }, 'not-taken', { $cond: [ { $or: [ { $gt: [ '$notAssignedCount', 0 ] }, { $gt: [ '$storeAudit.notAssignedStores', 0 ] } ] }, 'pending', 'completed' ] } ] },
|
|
488
640
|
completedStores: '$storeAudit.completedStores',
|
|
489
641
|
completionPercentage: '$storeAudit.completionPercentage',
|
|
490
642
|
|
|
491
643
|
},
|
|
492
644
|
},
|
|
493
645
|
];
|
|
646
|
+
|
|
494
647
|
if ( inputData.searchValue && inputData.searchValue!== '' ) {
|
|
495
648
|
query.push( {
|
|
496
649
|
$match: {
|
|
@@ -532,6 +685,7 @@ export async function clientMetrics( req, res ) {
|
|
|
532
685
|
'Audit Stores': '$totalFilesCount',
|
|
533
686
|
'Inprogress Stores': '$inprogressStoresCount',
|
|
534
687
|
'Not Assigned': '$notAssignedCount',
|
|
688
|
+
'Not Assigned Stores': '$notAssignedStores',
|
|
535
689
|
'Completed': '$completedStores',
|
|
536
690
|
'Status': '$clientStatus',
|
|
537
691
|
},
|
|
@@ -573,6 +727,11 @@ export async function userMetrics( req, res ) {
|
|
|
573
727
|
|
|
574
728
|
);
|
|
575
729
|
}
|
|
730
|
+
if ( inputData?.filterByAuditType?.length> 0 ) {
|
|
731
|
+
filter.push(
|
|
732
|
+
{ moduleType: { $in: inputData.filterByAuditType } },
|
|
733
|
+
);
|
|
734
|
+
}
|
|
576
735
|
if ( inputData?.filterByStatus?.length> 0 ) {
|
|
577
736
|
filter.push(
|
|
578
737
|
{ auditStatus: { $in: inputData.filterByStatus } },
|
|
@@ -599,7 +758,7 @@ export async function userMetrics( req, res ) {
|
|
|
599
758
|
startTime: 1,
|
|
600
759
|
endTime: 1,
|
|
601
760
|
totalCompletedFiles: { $cond: [ { $eq: [ '$auditStatus', 'completed' ] }, 1, 0 ] },
|
|
602
|
-
beforeCount:
|
|
761
|
+
beforeCount: 1,
|
|
603
762
|
afterCount: { $cond: [ { $eq: [ '$auditStatus', 'completed' ] }, '$afterCount', 0 ] },
|
|
604
763
|
},
|
|
605
764
|
},
|
|
@@ -694,6 +853,7 @@ export async function userMetrics( req, res ) {
|
|
|
694
853
|
beforeCount: 1,
|
|
695
854
|
afterCount: 1,
|
|
696
855
|
checkIntime: 1,
|
|
856
|
+
zoneName: 1,
|
|
697
857
|
checkOutTime: 1,
|
|
698
858
|
workingHours: {
|
|
699
859
|
$concat: [ '$hours', ':', '$minutes', ':', '$seconds' ],
|
|
@@ -735,8 +895,20 @@ export async function userMetrics( req, res ) {
|
|
|
735
895
|
totalCompletedFiles: 1,
|
|
736
896
|
beforeCount: 1,
|
|
737
897
|
afterCount: 1,
|
|
738
|
-
checkIntime:
|
|
739
|
-
|
|
898
|
+
checkIntime: {
|
|
899
|
+
$dateToString: {
|
|
900
|
+
format: '%Y-%m-%d %H:%M:%S',
|
|
901
|
+
date: '$checkIntime',
|
|
902
|
+
timezone: 'Asia/Kolkata',
|
|
903
|
+
},
|
|
904
|
+
},
|
|
905
|
+
checkOutTime: {
|
|
906
|
+
$dateToString: {
|
|
907
|
+
format: '%Y-%m-%d %H:%M:%S',
|
|
908
|
+
date: '$checkOutTime',
|
|
909
|
+
timezone: 'Asia/Kolkata',
|
|
910
|
+
},
|
|
911
|
+
},
|
|
740
912
|
workingHours: 1,
|
|
741
913
|
},
|
|
742
914
|
},
|
|
@@ -745,7 +917,7 @@ export async function userMetrics( req, res ) {
|
|
|
745
917
|
query.push( {
|
|
746
918
|
$match: {
|
|
747
919
|
$or: [
|
|
748
|
-
{
|
|
920
|
+
{ userName: { $regex: inputData.searchValue, $options: 'i' } },
|
|
749
921
|
{ clientName: { $regex: inputData.searchValue, $options: 'i' } },
|
|
750
922
|
],
|
|
751
923
|
|
|
@@ -775,7 +947,7 @@ export async function userMetrics( req, res ) {
|
|
|
775
947
|
$project: {
|
|
776
948
|
'_id': 0,
|
|
777
949
|
'File Date': '$fileDate',
|
|
778
|
-
'
|
|
950
|
+
'User Name': '$userName',
|
|
779
951
|
'User Id': '$userId',
|
|
780
952
|
'Total Completed Files Count': '$totalCompletedFiles',
|
|
781
953
|
'Total efore Count': '$beforeCount',
|
|
@@ -1152,7 +1324,8 @@ export async function overAllAuditSummary( req, res ) {
|
|
|
1152
1324
|
let filters =[
|
|
1153
1325
|
{ fileDateISO: { $gte: dateRange.start } },
|
|
1154
1326
|
{ fileDateISO: { $lte: dateRange.end } },
|
|
1155
|
-
|
|
1327
|
+
{ moduleType: { $eq: inputData.moduleType },
|
|
1328
|
+
},
|
|
1156
1329
|
];
|
|
1157
1330
|
if ( inputData.clientId.length > 0 ) {
|
|
1158
1331
|
filters.push( { clientId: { $in: inputData.clientId } } );
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { download, fileUpload, getJsonFileData, getUTC, insertOpenSearchData, listFileByPath, sendMessageToQueue, signedUrl, sqsReceive } from 'tango-app-api-middleware';
|
|
2
2
|
import { aggregateZoneUserAudit, createZoneUserAudit, findOneZoneUserAudit } from '../service/zoneUserAudit.service.js';
|
|
3
3
|
import { logger } from 'tango-app-api-middleware';
|
|
4
4
|
import { aggregateAssignZoneAudit } from '../service/assignZoneAudit.service.js';
|
|
@@ -899,40 +899,30 @@ export async function workSpace( req, res ) {
|
|
|
899
899
|
}
|
|
900
900
|
}
|
|
901
901
|
|
|
902
|
-
export async function
|
|
902
|
+
export async function storeMetrics( req, res ) {
|
|
903
903
|
try {
|
|
904
904
|
const inputData = req.body;
|
|
905
|
-
const userId = inputData.userId || req.user._id;
|
|
906
905
|
const limit = inputData.limit || 10;
|
|
907
906
|
const offset = inputData.offset ? ( inputData.offset - 1 ) * limit : 0;
|
|
908
907
|
const dateRange = await getUTC( new Date( inputData.fromDate ), new Date( inputData.toDate ) );
|
|
909
908
|
let filter = [
|
|
910
|
-
|
|
911
|
-
{
|
|
912
|
-
{ moduleType: 'zone' },
|
|
913
|
-
|
|
909
|
+
{ fileDateISO: { $gte: dateRange.start } },
|
|
910
|
+
{ fileDateISO: { $lte: dateRange.end } },
|
|
914
911
|
];
|
|
915
|
-
if ( inputData.
|
|
916
|
-
filter.push(
|
|
917
|
-
{ fileDateISO: { $gte: dateRange.start } },
|
|
918
|
-
{ fileDateISO: { $lte: dateRange.end } },
|
|
919
|
-
);
|
|
920
|
-
} else {
|
|
921
|
-
filter.push(
|
|
922
|
-
{ createdAt: { $gte: dateRange.start } },
|
|
923
|
-
{ createdAt: { $lte: dateRange.end } },
|
|
924
|
-
);
|
|
912
|
+
if ( inputData.filterByClientId && inputData.filterByClientId?.length > 0 ) {
|
|
913
|
+
filter.push( { clientId: { $in: inputData.filterByClientId } } );
|
|
925
914
|
}
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
} );
|
|
915
|
+
|
|
916
|
+
if ( inputData.filterByStoreId && inputData.filterByStoreId?.length > 0 ) {
|
|
917
|
+
filter.push( { storeId: { $in: inputData.filterByStoreId } } );
|
|
930
918
|
}
|
|
931
919
|
|
|
932
|
-
if ( inputData.filterByStatus?.length > 0 ) {
|
|
933
|
-
filter.push( {
|
|
934
|
-
|
|
935
|
-
|
|
920
|
+
if ( inputData.filterByStatus && inputData.filterByStatus?.length > 0 ) {
|
|
921
|
+
filter.push( { status: { $in: inputData.filterByStatus } } );
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
if ( inputData.filterByType && inputData.filterByType?.length > 0 ) {
|
|
925
|
+
filter.push( { auditType: { $in: inputData.filterByType } } );
|
|
936
926
|
}
|
|
937
927
|
|
|
938
928
|
const query = [
|
|
@@ -941,19 +931,179 @@ export async function userZoneAuditHistory( req, res ) {
|
|
|
941
931
|
$and: filter,
|
|
942
932
|
},
|
|
943
933
|
},
|
|
934
|
+
{
|
|
935
|
+
$lookup: {
|
|
936
|
+
from: 'stores',
|
|
937
|
+
let: { storeId: '$storeId' },
|
|
938
|
+
pipeline: [
|
|
939
|
+
{
|
|
940
|
+
$match: {
|
|
941
|
+
$expr: {
|
|
942
|
+
$eq: [ '$storeId', '$$storeId' ],
|
|
943
|
+
},
|
|
944
|
+
},
|
|
945
|
+
},
|
|
946
|
+
{
|
|
947
|
+
$project: {
|
|
948
|
+
storeName: 1,
|
|
949
|
+
},
|
|
950
|
+
},
|
|
951
|
+
], as: 'store',
|
|
952
|
+
},
|
|
953
|
+
},
|
|
954
|
+
{
|
|
955
|
+
$unwind: {
|
|
956
|
+
path: '$store', preserveNullAndEmptyArrays: true,
|
|
957
|
+
},
|
|
958
|
+
},
|
|
959
|
+
{
|
|
960
|
+
$project: {
|
|
961
|
+
_id: 0,
|
|
962
|
+
fileDate: 1,
|
|
963
|
+
storeId: 1,
|
|
964
|
+
storeName: '$store.storeName',
|
|
965
|
+
clientName: '',
|
|
966
|
+
clientId: 1,
|
|
967
|
+
userId: {
|
|
968
|
+
$arrayElemAt: [ '$userId', { $subtract: [ { $size: '$userId' }, 1 ] } ],
|
|
969
|
+
},
|
|
970
|
+
clientId: 1,
|
|
971
|
+
auditType: 1,
|
|
972
|
+
beforeCount: 1,
|
|
973
|
+
afterCount: { $ifNull: [ '$afterCount', null ] },
|
|
974
|
+
accuracy: { $round: [
|
|
975
|
+
{ $divide: [
|
|
976
|
+
{ $multiply: [ { $ifNull: [ '$afterCount', 0 ] }, '$beforeCount' ] }, 100,
|
|
977
|
+
] }, 2,
|
|
978
|
+
],
|
|
979
|
+
|
|
980
|
+
},
|
|
981
|
+
timeSpent: 1,
|
|
982
|
+
status: 1,
|
|
983
|
+
},
|
|
984
|
+
},
|
|
985
|
+
{
|
|
986
|
+
$lookup: {
|
|
987
|
+
from: 'users',
|
|
988
|
+
let: { userId: '$userId' },
|
|
989
|
+
pipeline: [
|
|
990
|
+
{
|
|
991
|
+
$match: {
|
|
992
|
+
$expr: {
|
|
993
|
+
$eq: [ '$_id', '$$userId' ],
|
|
994
|
+
},
|
|
995
|
+
},
|
|
996
|
+
},
|
|
997
|
+
{
|
|
998
|
+
$project: {
|
|
999
|
+
_id: 0,
|
|
1000
|
+
userName: 1,
|
|
1001
|
+
userEmail: '$email',
|
|
1002
|
+
},
|
|
1003
|
+
},
|
|
1004
|
+
], as: 'users',
|
|
1005
|
+
},
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
$unwind: {
|
|
1009
|
+
path: '$users',
|
|
1010
|
+
preserveNullAndEmptyArrays: true,
|
|
1011
|
+
},
|
|
1012
|
+
},
|
|
1013
|
+
{
|
|
1014
|
+
$lookup: {
|
|
1015
|
+
from: 'clients',
|
|
1016
|
+
let: { clientId: '$clientId' },
|
|
1017
|
+
pipeline: [
|
|
1018
|
+
{
|
|
1019
|
+
$match: {
|
|
1020
|
+
$expr: {
|
|
1021
|
+
$eq: [ '$clientId', '$$clientId' ],
|
|
1022
|
+
},
|
|
1023
|
+
},
|
|
1024
|
+
},
|
|
1025
|
+
{
|
|
1026
|
+
$project: {
|
|
1027
|
+
_id: 0,
|
|
1028
|
+
clientName: 1,
|
|
1029
|
+
},
|
|
1030
|
+
},
|
|
1031
|
+
], as: 'client',
|
|
1032
|
+
},
|
|
1033
|
+
},
|
|
1034
|
+
{
|
|
1035
|
+
$unwind: {
|
|
1036
|
+
path: '$client',
|
|
1037
|
+
preserveNullAndEmptyArrays: true,
|
|
1038
|
+
},
|
|
1039
|
+
},
|
|
1040
|
+
{
|
|
1041
|
+
$project: {
|
|
1042
|
+
_id: 0,
|
|
1043
|
+
fileDate: 1,
|
|
1044
|
+
storeId: 1,
|
|
1045
|
+
storeName: '$stores.storeName',
|
|
1046
|
+
userName: '$users.userName',
|
|
1047
|
+
userEmail: '$users.userEmail',
|
|
1048
|
+
clientId: 1,
|
|
1049
|
+
clientName: '$client.clientName',
|
|
1050
|
+
auditType: 1,
|
|
1051
|
+
beforeCount: 1,
|
|
1052
|
+
afterCount: { $ifNull: [ '$afterCount', null ] },
|
|
1053
|
+
accuracy: { $round: [
|
|
1054
|
+
{ $divide: [
|
|
1055
|
+
{ $multiply: [ { $ifNull: [ '$afterCount', 0 ] }, '$beforeCount' ] }, 100,
|
|
1056
|
+
] }, 1,
|
|
1057
|
+
],
|
|
1058
|
+
|
|
1059
|
+
},
|
|
1060
|
+
timeSpent: {
|
|
1061
|
+
|
|
1062
|
+
$cond: [
|
|
1063
|
+
{ $lt: [ '$timeSpent', 60 ] }, // Case 1: If less than 60 seconds
|
|
1064
|
+
{ $concat: [ { $toString: '$timeSpent' }, ' sec' ] },
|
|
1065
|
+
{
|
|
1066
|
+
$cond: [
|
|
1067
|
+
{ $lt: [ '$timeSpent', 3600 ] }, // Case 2: If less than 60 minutes (3600 seconds)
|
|
1068
|
+
{
|
|
1069
|
+
$concat: [
|
|
1070
|
+
{ $toString: { $round: [ { $divide: [ '$timeSpent', 60 ] }, 1 ] } }, // Convert to minutes
|
|
1071
|
+
' min',
|
|
1072
|
+
],
|
|
1073
|
+
},
|
|
1074
|
+
{
|
|
1075
|
+
$concat: [
|
|
1076
|
+
{ $toString: { $round: [ { $divide: [ '$timeSpent', 3600 ] }, 1 ] } }, // Convert to hours
|
|
1077
|
+
' hr',
|
|
1078
|
+
],
|
|
1079
|
+
},
|
|
1080
|
+
],
|
|
1081
|
+
},
|
|
1082
|
+
],
|
|
1083
|
+
|
|
1084
|
+
},
|
|
1085
|
+
status: 1,
|
|
1086
|
+
},
|
|
1087
|
+
},
|
|
1088
|
+
|
|
944
1089
|
];
|
|
945
1090
|
|
|
946
|
-
if ( inputData.searchValue && inputData.searchValue!== '' ) {
|
|
1091
|
+
if ( inputData.searchValue && inputData.searchValue !== '' ) {
|
|
947
1092
|
query.push( {
|
|
948
1093
|
$match: {
|
|
949
1094
|
$or: [
|
|
950
1095
|
{ clientId: { $regex: inputData.searchValue, $options: 'i' } },
|
|
951
1096
|
{ clientName: { $regex: inputData.searchValue, $options: 'i' } },
|
|
1097
|
+
{ storeId: { $regex: inputData.searchValue, $options: 'i' } },
|
|
1098
|
+
{ storeName: { $regex: inputData.searchValue, $options: 'i' } },
|
|
1099
|
+
{ userName: { $regex: inputData.searchValue, $options: 'i' } },
|
|
1100
|
+
{ status: { $regex: inputData.searchValue, $options: 'i' } },
|
|
1101
|
+
{ auditType: { $regex: inputData.searchValue, $options: 'i' } },
|
|
952
1102
|
],
|
|
953
|
-
|
|
954
1103
|
},
|
|
955
1104
|
} );
|
|
956
1105
|
}
|
|
1106
|
+
|
|
957
1107
|
if ( inputData.sortColumnName ) {
|
|
958
1108
|
const sortBy = inputData.sortBy || -1;
|
|
959
1109
|
query.push( {
|
|
@@ -962,108 +1112,229 @@ export async function userZoneAuditHistory( req, res ) {
|
|
|
962
1112
|
);
|
|
963
1113
|
}
|
|
964
1114
|
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
1115
|
+
const count = await aggregateStoreZoneAudit( query );
|
|
1116
|
+
|
|
1117
|
+
if ( count.length == 0 ) {
|
|
1118
|
+
return res.sendError( 'No data Found', 204 );
|
|
1119
|
+
}
|
|
1120
|
+
if ( !inputData.isExport ) {
|
|
1121
|
+
query.push( {
|
|
1122
|
+
$skip: offset,
|
|
1123
|
+
},
|
|
1124
|
+
{
|
|
1125
|
+
$limit: limit,
|
|
1126
|
+
} );
|
|
1127
|
+
} else {
|
|
1128
|
+
query.push( { $limit: 10000 } );
|
|
1129
|
+
}
|
|
1130
|
+
const result = await aggregateStoreZoneAudit( query );
|
|
1131
|
+
if ( inputData.isExport ) {
|
|
1132
|
+
const exportdata = [];
|
|
1133
|
+
result.forEach( ( element ) => {
|
|
1134
|
+
exportdata.push( {
|
|
1135
|
+
'File Date': element.fileDate,
|
|
1136
|
+
'Store Id': element.storeId,
|
|
1137
|
+
'Store Name': element.storeName,
|
|
1138
|
+
'Client Id': element.clientId,
|
|
1139
|
+
'Client Name': element.clientName,
|
|
1140
|
+
'User Name': element.userName,
|
|
1141
|
+
'User Email': element.userEmail,
|
|
1142
|
+
'Audit Type': element.auditType,
|
|
1143
|
+
'Accuracy': element.accuracy,
|
|
1144
|
+
'Time Spent': element.timeSpent,
|
|
1145
|
+
'Status': element.status,
|
|
1146
|
+
} );
|
|
1147
|
+
} );
|
|
1148
|
+
await download( exportdata, res );
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1151
|
+
return res.sendSuccess( { result: result, count: count.length } );
|
|
1152
|
+
} catch ( error ) {
|
|
1153
|
+
const err = error.message || 'Internal Server Error';
|
|
1154
|
+
logger.error( { error: error, data: req.body, function: 'storeMetrics' } );
|
|
1155
|
+
return res.sendError( err, 500 );
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
export async function clientMetrics( req, res ) {
|
|
1160
|
+
try {
|
|
1161
|
+
const inputData = req.body;
|
|
1162
|
+
const limit = inputData.limit || 10;
|
|
1163
|
+
const offset = inputData.offset ? ( inputData.offset - 1 ) * limit : 0;
|
|
1164
|
+
const dateRange = await getUTC( new Date( inputData.fromDate ), new Date( inputData.toDate ) );
|
|
1165
|
+
let filter = [
|
|
1166
|
+
{ fileDateISO: { $gte: dateRange.start } },
|
|
1167
|
+
{ fileDateISO: { $lte: dateRange.end } },
|
|
1168
|
+
{ moduleType: { $eq: 'zone' } },
|
|
1169
|
+
|
|
1170
|
+
];
|
|
1171
|
+
if ( inputData?.filterByClient?.length> 0 ) {
|
|
1172
|
+
filter.push(
|
|
1173
|
+
{ clientId: { $in: inputData.filterByClient } },
|
|
1174
|
+
);
|
|
1175
|
+
}
|
|
1176
|
+
const query = [
|
|
1177
|
+
{
|
|
1178
|
+
$match: {
|
|
1179
|
+
$and: filter,
|
|
1180
|
+
},
|
|
1181
|
+
},
|
|
1182
|
+
{
|
|
1183
|
+
$project: {
|
|
1184
|
+
fileDate: 1,
|
|
1185
|
+
clientId: 1,
|
|
1186
|
+
clientName: 1,
|
|
1187
|
+
queueName: 1,
|
|
1188
|
+
installedStore: 1,
|
|
1189
|
+
totalFilesCount: 1,
|
|
1190
|
+
notAssignedCount: { $ifNull: [ 0, 0 ] },
|
|
1191
|
+
clientStatus: { $ifNull: [ '', '' ] },
|
|
1192
|
+
},
|
|
1193
|
+
},
|
|
1194
|
+
{
|
|
1195
|
+
$lookup: {
|
|
1196
|
+
'from': 'storeZoneAudit',
|
|
1197
|
+
'let': { clientId: '$clientId', fileDate: '$fileDate', totalAuditFiles: '$totalAuditFiles' },
|
|
1198
|
+
'pipeline': [
|
|
1199
|
+
|
|
1200
|
+
{
|
|
1201
|
+
$match: {
|
|
1202
|
+
$expr: {
|
|
1203
|
+
$and: [
|
|
1204
|
+
{ $eq: [ '$clientId', '$$clientId' ] },
|
|
1205
|
+
{ $eq: [ '$fileDate', '$$fileDate' ] },
|
|
1206
|
+
],
|
|
1207
|
+
},
|
|
974
1208
|
},
|
|
975
1209
|
},
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
1210
|
+
{
|
|
1211
|
+
$project: {
|
|
1212
|
+
completedStores: { $cond: [ { $eq: [ '$status', 'completed' ] }, 1, 0 ] },
|
|
1213
|
+
notAssignedStores: { $cond: [ { $eq: [ '$status', 'not_assign' ] }, 1, 0 ] },
|
|
1214
|
+
inprogressStores: { $cond: [ { $in: [ '$status', [ 'inprogress', 'drafted', 'assigned' ] ] }, 1, 0 ] },
|
|
1215
|
+
},
|
|
980
1216
|
},
|
|
981
|
-
|
|
982
|
-
|
|
1217
|
+
{
|
|
1218
|
+
$group: {
|
|
1219
|
+
_id: { clientId: '$clientId', fileDate: '$fileDate' },
|
|
1220
|
+
completedStores: { $sum: '$completedStores' },
|
|
1221
|
+
inprogressStores: { $sum: '$inprogressStores' },
|
|
1222
|
+
notAssignedStores: { $sum: '$notAssignedStores' },
|
|
1223
|
+
fileCount: { $sum: 1 },
|
|
1224
|
+
},
|
|
1225
|
+
},
|
|
1226
|
+
{
|
|
1227
|
+
$project: {
|
|
1228
|
+
_id: 0,
|
|
1229
|
+
completedStores: 1,
|
|
1230
|
+
inprogressStores: 1,
|
|
1231
|
+
notAssignedStores: 1,
|
|
1232
|
+
fileCount: 1,
|
|
1233
|
+
completionPercentage: { $ifNull: [
|
|
1234
|
+
{
|
|
1235
|
+
$round: [ {
|
|
1236
|
+
$multiply: [
|
|
1237
|
+
100, {
|
|
1238
|
+
$divide: [
|
|
1239
|
+
'$completedStores', '$$totalAuditFiles',
|
|
1240
|
+
],
|
|
1241
|
+
},
|
|
1242
|
+
],
|
|
1243
|
+
}, 1 ],
|
|
1244
|
+
|
|
1245
|
+
},
|
|
1246
|
+
0,
|
|
1247
|
+
],
|
|
1248
|
+
},
|
|
1249
|
+
},
|
|
1250
|
+
},
|
|
1251
|
+
], 'as': 'storeZoneAudit',
|
|
1252
|
+
},
|
|
983
1253
|
},
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
path: '$store', preserveNullAndEmptyArrays: true,
|
|
1254
|
+
{
|
|
1255
|
+
$unwind: {
|
|
1256
|
+
path: '$storeZoneAudit',
|
|
1257
|
+
preserveNullAndEmptyArrays: true,
|
|
1258
|
+
},
|
|
990
1259
|
},
|
|
991
|
-
|
|
1260
|
+
{
|
|
1261
|
+
$project: {
|
|
1262
|
+
fileDate: 1,
|
|
1263
|
+
clientId: 1,
|
|
1264
|
+
clientName: 1,
|
|
1265
|
+
totalFilesCount: 1,
|
|
1266
|
+
installedStore: 1,
|
|
1267
|
+
fileCount: '$storeZoneAudit.fileCount',
|
|
1268
|
+
notAssignedStores: '$storeZoneAudit.notAssignedStores',
|
|
1269
|
+
inprogressStoresCount: '$storeZoneAudit.inprogressStores',
|
|
1270
|
+
notAssignedCount: 1,
|
|
1271
|
+
clientStatus: { $cond: [ { $eq: [ '$storeZoneAudit.fileCount', 0 ] }, 'not-taken', { $cond: [ { $or: [ { $gt: [ '$notAssignedCount', 0 ] }, { $gt: [ '$storeZoneAudit.notAssignedStores', 0 ] } ] }, 'pending', 'completed' ] } ] },
|
|
1272
|
+
completedStores: '$storeZoneAudit.completedStores',
|
|
1273
|
+
completionPercentage: '$storeZoneAudit.completionPercentage',
|
|
992
1274
|
|
|
1275
|
+
},
|
|
1276
|
+
},
|
|
1277
|
+
];
|
|
993
1278
|
|
|
994
|
-
|
|
1279
|
+
if ( inputData.searchValue && inputData.searchValue!== '' ) {
|
|
1280
|
+
query.push( {
|
|
1281
|
+
$match: {
|
|
1282
|
+
$or: [
|
|
1283
|
+
{ clientId: { $regex: inputData.searchValue, $options: 'i' } },
|
|
1284
|
+
{ clientName: { $regex: inputData.searchValue, $options: 'i' } },
|
|
1285
|
+
],
|
|
995
1286
|
|
|
996
|
-
$project: {
|
|
997
|
-
storeId: 1,
|
|
998
|
-
userId: 1,
|
|
999
|
-
storeName: '$store.storeName',
|
|
1000
|
-
zoneName: 1,
|
|
1001
|
-
auditType: 1,
|
|
1002
|
-
beforeCount: 1,
|
|
1003
|
-
afterCount: 1,
|
|
1004
|
-
accuracy: { $round: [
|
|
1005
|
-
{
|
|
1006
|
-
$divide: [ { $multiply: [ '$beforeCount', { $ifNull: [ '$afterCount', 0 ] } ] }, 100 ],
|
|
1007
|
-
}, 2,
|
|
1008
|
-
],
|
|
1009
1287
|
},
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
createdAt: 1,
|
|
1288
|
+
} );
|
|
1289
|
+
}
|
|
1290
|
+
if ( inputData.sortColumnName ) {
|
|
1291
|
+
const sortBy = inputData.sortBy || -1;
|
|
1292
|
+
query.push( {
|
|
1293
|
+
$sort: { [inputData.sortColumName]: sortBy },
|
|
1017
1294
|
},
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1018
1297
|
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
const count = await aggregateUserAudit( query );
|
|
1298
|
+
const count = await aggregateAuditClientData( query );
|
|
1022
1299
|
if ( count.length == 0 ) {
|
|
1023
1300
|
return res.sendError( 'No Data Found', 204 );
|
|
1024
1301
|
}
|
|
1025
1302
|
|
|
1303
|
+
query.push(
|
|
1304
|
+
{ $skip: offset },
|
|
1305
|
+
{ $limit: limit },
|
|
1306
|
+
);
|
|
1026
1307
|
if ( inputData.isExport ) {
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1308
|
+
query.push(
|
|
1309
|
+
{
|
|
1310
|
+
$project: {
|
|
1311
|
+
'_id': 0,
|
|
1312
|
+
'File Date': '$fileDate',
|
|
1313
|
+
'Client Name': '$clientName',
|
|
1314
|
+
'Client Id': '$clientId',
|
|
1315
|
+
'Completed Percentage': '$completionPercentage',
|
|
1316
|
+
'Installed Stores': '$installedStore',
|
|
1317
|
+
'Audit Stores': '$totalFilesCount',
|
|
1318
|
+
'Inprogress Stores': '$inprogressStoresCount',
|
|
1319
|
+
'Not Assigned': '$notAssignedCount',
|
|
1320
|
+
'Not Assigned Stores': '$notAssignedStores',
|
|
1321
|
+
'Completed': '$completedStores',
|
|
1322
|
+
'Status': '$clientStatus',
|
|
1323
|
+
},
|
|
1324
|
+
},
|
|
1325
|
+
);
|
|
1326
|
+
}
|
|
1043
1327
|
|
|
1044
|
-
} );
|
|
1045
|
-
} );
|
|
1046
|
-
return exportData;
|
|
1047
|
-
} );
|
|
1048
|
-
const mappedArrays = await Promise.all( promises );
|
|
1049
|
-
mappedArrays.flat();
|
|
1050
1328
|
|
|
1051
|
-
|
|
1329
|
+
const result = await aggregateAuditClientData( query );
|
|
1330
|
+
if ( inputData.isExport ) {
|
|
1331
|
+
await download( result, res );
|
|
1052
1332
|
return;
|
|
1053
1333
|
}
|
|
1054
|
-
|
|
1055
|
-
query.push( {
|
|
1056
|
-
$skip: offset,
|
|
1057
|
-
},
|
|
1058
|
-
{
|
|
1059
|
-
$limit: limit,
|
|
1060
|
-
} );
|
|
1061
|
-
const result = await aggregateUserAudit( query );
|
|
1062
|
-
|
|
1063
|
-
return res.sendSuccess( { result: result } );
|
|
1334
|
+
return res.sendSuccess( { result: result, count: count.length } );
|
|
1064
1335
|
} catch ( error ) {
|
|
1065
|
-
const err = error.
|
|
1066
|
-
logger.info( { error: error, message: req.body, function: '
|
|
1336
|
+
const err = error.error || 'Internal Server Error';
|
|
1337
|
+
logger.info( { error: error, message: req.body, function: 'clientMetrics' } );
|
|
1067
1338
|
return res.sendError( err, 500 );
|
|
1068
1339
|
}
|
|
1069
1340
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import j2s from 'joi-to-swagger';
|
|
2
|
-
import { getDraftedDataSchema, getFileSchema, saveDraftSchema, saveSchema, workSpaceSchema } from '../dtos/zoneAudit.dtos.js';
|
|
2
|
+
import { clientMetricsSchema, getDraftedDataSchema, getFileSchema, saveDraftSchema, saveSchema, storeMetricsSchema, workSpaceSchema } from '../dtos/zoneAudit.dtos.js';
|
|
3
3
|
|
|
4
4
|
export const zoneAuditDocs = {
|
|
5
5
|
'/v3/zone-audit/get-file': {
|
|
@@ -155,4 +155,51 @@ export const zoneAuditDocs = {
|
|
|
155
155
|
},
|
|
156
156
|
},
|
|
157
157
|
|
|
158
|
+
// metrics
|
|
159
|
+
'/v3/zone-audit/metrics/store-metrics': {
|
|
160
|
+
post: {
|
|
161
|
+
tags: [ 'Zone Audit Metrics' ],
|
|
162
|
+
description: `Get store level zone metrics`,
|
|
163
|
+
operationId: 'save',
|
|
164
|
+
parameters: {},
|
|
165
|
+
requestBody: {
|
|
166
|
+
content: {
|
|
167
|
+
'application/json': {
|
|
168
|
+
schema: j2s( storeMetricsSchema ).swagger,
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
responses: {
|
|
173
|
+
200: { description: 'Successful' },
|
|
174
|
+
401: { description: 'Unauthorized User' },
|
|
175
|
+
422: { description: 'Field Error' },
|
|
176
|
+
500: { description: 'Server Error' },
|
|
177
|
+
204: { description: 'Not Found' },
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
'/v3/zone-audit/metrics/client-metrics': {
|
|
183
|
+
post: {
|
|
184
|
+
tags: [ 'Zone Audit Metrics' ],
|
|
185
|
+
description: `Get list of client wise details with date range`,
|
|
186
|
+
operationId: 'metrics/client-metrics',
|
|
187
|
+
parameters: {},
|
|
188
|
+
requestBody: {
|
|
189
|
+
content: {
|
|
190
|
+
'application/json': {
|
|
191
|
+
schema: j2s( clientMetricsSchema ).swagger,
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
responses: {
|
|
196
|
+
200: { description: 'Successful' },
|
|
197
|
+
401: { description: 'Unauthorized User' },
|
|
198
|
+
422: { description: 'Field Error' },
|
|
199
|
+
500: { description: 'Server Error' },
|
|
200
|
+
204: { description: 'Not Found' },
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
|
|
158
205
|
};
|
|
@@ -21,6 +21,7 @@ export const userAuditHistorySchema = joi.object(
|
|
|
21
21
|
fileType: joi.string().required(),
|
|
22
22
|
filterByStoreId: joi.array().required(),
|
|
23
23
|
filterByType: joi.array().optional(),
|
|
24
|
+
filterByAuditType: joi.array().optional(),
|
|
24
25
|
filterByStatus: joi.array().optional(),
|
|
25
26
|
searchValue: joi.string().optional().allow( '' ),
|
|
26
27
|
limit: joi.number().optional(),
|
|
@@ -44,7 +45,7 @@ export const storeMetricsSchema = joi.object(
|
|
|
44
45
|
filterByClientId: joi.array().required(),
|
|
45
46
|
filterByStoreId: joi.array().optional(),
|
|
46
47
|
filterByStatus: joi.array().optional(),
|
|
47
|
-
|
|
48
|
+
filterByType: joi.array().optional(),
|
|
48
49
|
sortColumnName: joi.string().optional(),
|
|
49
50
|
sortBy: joi.number().optional(),
|
|
50
51
|
limit: joi.number().optional(),
|
|
@@ -83,6 +84,7 @@ export const userMetricsSchema = joi.object(
|
|
|
83
84
|
fileType: joi.string().required(),
|
|
84
85
|
searchValue: joi.string().optional().allow( '' ),
|
|
85
86
|
filterByUser: joi.array().optional(),
|
|
87
|
+
filterByAuditType: joi.array().optional(),
|
|
86
88
|
filterByStatus: joi.array().optional(),
|
|
87
89
|
sortColumnName: joi.string().optional(),
|
|
88
90
|
sortBy: joi.number().optional(),
|
|
@@ -145,6 +147,7 @@ export const overAllAuditSummarySchema = joi.object(
|
|
|
145
147
|
fromDate: joi.string().required(),
|
|
146
148
|
toDate: joi.string().required(),
|
|
147
149
|
clientId: joi.array().optional(),
|
|
150
|
+
moduleType: joi.string().required(),
|
|
148
151
|
},
|
|
149
152
|
);
|
|
150
153
|
|
|
@@ -87,3 +87,43 @@ export const workSpaceValid = {
|
|
|
87
87
|
query: workSpaceSchema,
|
|
88
88
|
};
|
|
89
89
|
|
|
90
|
+
export const storeMetricsSchema = joi.object(
|
|
91
|
+
{
|
|
92
|
+
fromDate: joi.string().required(),
|
|
93
|
+
toDate: joi.string().required(),
|
|
94
|
+
searchValue: joi.string().optional().allow( '' ),
|
|
95
|
+
filterByClientId: joi.array().required(),
|
|
96
|
+
filterByStoreId: joi.array().optional(),
|
|
97
|
+
filterByStatus: joi.array().optional(),
|
|
98
|
+
filterByType: joi.array().optional(),
|
|
99
|
+
sortColumnName: joi.string().optional(),
|
|
100
|
+
sortBy: joi.number().optional(),
|
|
101
|
+
limit: joi.number().optional(),
|
|
102
|
+
offset: joi.number().optional(),
|
|
103
|
+
isExport: joi.boolean().optional(),
|
|
104
|
+
},
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
export const storeMetricsValid = {
|
|
108
|
+
body: storeMetricsSchema,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export const clientMetricsSchema = joi.object(
|
|
112
|
+
{
|
|
113
|
+
fromDate: joi.string().required(),
|
|
114
|
+
toDate: joi.string().required(),
|
|
115
|
+
searchValue: joi.string().optional().allow( '' ),
|
|
116
|
+
filterByClient: joi.array().required(),
|
|
117
|
+
filterByStatus: joi.array().optional(),
|
|
118
|
+
sortColumnName: joi.string().optional(),
|
|
119
|
+
sortBy: joi.number().optional(),
|
|
120
|
+
limit: joi.number().optional(),
|
|
121
|
+
offset: joi.number().optional(),
|
|
122
|
+
isExport: joi.boolean().optional(),
|
|
123
|
+
},
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
export const clientMetricsValid = {
|
|
127
|
+
body: clientMetricsSchema,
|
|
128
|
+
};
|
|
129
|
+
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
|
-
import { getDraftedDataValid, getFileValid, saveDraftValid, saveValid, workSpaceValid } from '../dtos/zoneAudit.dtos.js';
|
|
2
|
+
import { clientMetricsValid, getDraftedDataValid, getFileValid, saveDraftValid, saveValid, storeMetricsValid, workSpaceValid } from '../dtos/zoneAudit.dtos.js';
|
|
3
3
|
import { isExistsQueue, validateUserAudit } from '../validation/audit.validation.js';
|
|
4
4
|
import { isAllowedSessionHandler, validate } from 'tango-app-api-middleware';
|
|
5
|
-
import { getDraftedData, getZoneAuditFile, save, saveDraft, workSpace } from '../controllers/zoneAudit.controller.js';
|
|
5
|
+
import { clientMetrics, getDraftedData, getZoneAuditFile, save, saveDraft, storeMetrics, workSpace } from '../controllers/zoneAudit.controller.js';
|
|
6
6
|
|
|
7
7
|
export const zoneAuditRouter=Router();
|
|
8
8
|
|
|
@@ -12,3 +12,8 @@ zoneAuditRouter.post( '/save-draft', isAllowedSessionHandler, validate( saveDraf
|
|
|
12
12
|
zoneAuditRouter.get( '/get-drafted-data', isAllowedSessionHandler, validate( getDraftedDataValid ), getDraftedData );
|
|
13
13
|
zoneAuditRouter.post( '/save', isAllowedSessionHandler, validate( saveValid ), validateUserAudit, save );
|
|
14
14
|
zoneAuditRouter.get( '/work-space', isAllowedSessionHandler, validate( workSpaceValid ), workSpace );
|
|
15
|
+
|
|
16
|
+
// metrics
|
|
17
|
+
|
|
18
|
+
zoneAuditRouter.post( '/metrics/store-metrics', isAllowedSessionHandler, validate( storeMetricsValid ), storeMetrics );
|
|
19
|
+
zoneAuditRouter.post( '/metrics/client-metrics', isAllowedSessionHandler, validate( clientMetricsValid ), clientMetrics );
|