tango-app-api-audit 1.0.42 → 1.0.43

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-audit",
3
- "version": "1.0.42",
3
+ "version": "1.0.43",
4
4
  "description": "audit & audit metrics apis",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -10,12 +10,13 @@ import { countDocumentsStore } from '../service/store.service.js';
10
10
  import { findOneClient } from '../service/client.service.js';
11
11
  import { getAuditFilterData, getAuditImageData, zipDownloadImage } from '../validation/audit.validation.js';
12
12
  import { getReauditImg } from './audit.controllers.js';
13
+ import { aggregateStoreZoneAudit } from '../service/storeZoneAudit.service.js';
13
14
  // import { listQueue } from 'tango-app-api-middleware/src/utils/aws/sqs.js';
14
15
 
15
16
  export async function userAuditHistory( req, res ) {
16
17
  try {
17
18
  const inputData = req.body;
18
- const userId = inputData.userId || req.user._id;
19
+ const userId = inputData.userId? new mongoose.Types.ObjectId( inputData.userId ) : req.user._id;
19
20
  const limit = inputData.limit || 10;
20
21
  const offset = inputData.offset ? ( inputData.offset - 1 ) * limit : 0;
21
22
  const dateRange = await getUTC( new Date( inputData.fromDate ), new Date( inputData.toDate ) );
@@ -1174,12 +1175,15 @@ export async function overViewTable( req, res ) {
1174
1175
  { fileDateISO: { $gte: dateRange.start } },
1175
1176
  { fileDateISO: { $lte: dateRange.end } },
1176
1177
  { auditStatus: { $in: inputData.filterByStatus } },
1177
- { auditType: { $in: inputData.filterByAuditType } },
1178
+ { auditType: { $in: inputData.filterByType } },
1178
1179
 
1179
1180
  ];
1180
1181
  if ( inputData.clientId.length > 0 ) {
1181
1182
  filters.push( { clientId: { $in: inputData.clientId } } );
1182
1183
  }
1184
+ if ( inputData.filterByAuditType.length > 0 ) {
1185
+ filters.push( { moduleType: { $in: inputData.filterByAuditType } } );
1186
+ }
1183
1187
 
1184
1188
  const query =[
1185
1189
  {
@@ -1198,8 +1202,6 @@ export async function overViewTable( req, res ) {
1198
1202
  auditType: 1,
1199
1203
  auditStatus: 1,
1200
1204
  userId: 1,
1201
-
1202
-
1203
1205
  },
1204
1206
  },
1205
1207
  {
@@ -1237,8 +1239,8 @@ export async function overViewTable( req, res ) {
1237
1239
  startTime: 1,
1238
1240
  auditType: 1,
1239
1241
  auditStatus: 1,
1240
- userName: '$users.userName',
1241
- userEmail: '$users.userEmail',
1242
+ userName: '$user.userName',
1243
+ userEmail: '$user.userEmail',
1242
1244
 
1243
1245
  },
1244
1246
  },
@@ -1247,8 +1249,12 @@ export async function overViewTable( req, res ) {
1247
1249
  query.push( {
1248
1250
  $match: {
1249
1251
  $or: [
1250
- { clientId: { $regex: inputData.searchValue, $options: 'i' } },
1251
- { clientName: { $regex: inputData.searchValue, $options: 'i' } },
1252
+ { storeId: { $regex: inputData.searchValue, $options: 'i' } },
1253
+ { fileDate: { $regex: inputData.searchValue, $options: 'i' } },
1254
+ { auditType: { $regex: inputData.searchValue, $options: 'i' } },
1255
+ { auditStatus: { $regex: inputData.searchValue, $options: 'i' } },
1256
+ { userName: { $regex: inputData.searchValue, $options: 'i' } },
1257
+ { userEmail: { $regex: inputData.searchValue, $options: 'i' } },
1252
1258
  ],
1253
1259
 
1254
1260
  },
@@ -1284,12 +1290,13 @@ export async function overViewTable( req, res ) {
1284
1290
  exportdata.push( {
1285
1291
  'Store Id': element.storeId,
1286
1292
  'File Date': element.fileDtae,
1287
- 'Audit Type': element.audittype,
1293
+ 'Type': element.audittype,
1288
1294
  'Before Count': element.beforeCount,
1289
1295
  'Start Time': element.startTime,
1290
1296
  'User Name': element.userName,
1291
1297
  'User Email': element.userEmail,
1292
1298
  'Status': element.auditStatus,
1299
+ 'Audit Type': element.moduleType,
1293
1300
  } );
1294
1301
  } );
1295
1302
  await download( exportdata, res );
@@ -1398,7 +1405,7 @@ export async function overAllAuditSummary( req, res ) {
1398
1405
  },
1399
1406
  },
1400
1407
  ];
1401
- const storeAudit = await aggregateStoreAudit( storeAuditQuery );
1408
+ const storeAudit = inputData.moduleType == 'zone'?await aggregateStoreZoneAudit( storeAuditQuery ) : await aggregateStoreAudit( storeAuditQuery );
1402
1409
  if ( storeAudit.length > 0 ) {
1403
1410
  temp.inprogreseStores= storeAudit[0].inprogreseStores;
1404
1411
  temp.completedStores = storeAudit[0].completedStores;
@@ -1440,7 +1447,7 @@ export async function reTrigger( req, res ) {
1440
1447
  const msg = {
1441
1448
  store_id: inputData.storeId,
1442
1449
  curr_date: inputData.fileDate,
1443
- audit_type: inputData.auditType,
1450
+ audit_type: inputData.type,
1444
1451
  total_count: inputData.totalCount,
1445
1452
  };
1446
1453
 
@@ -1482,7 +1489,7 @@ export async function reTrigger( req, res ) {
1482
1489
  beforeCount: inputData.totalCount,
1483
1490
  afterCount: '',
1484
1491
  fileDate: inputData.fileDate,
1485
- auditType: inputData.auditType,
1492
+ auditType: inputData.type,
1486
1493
  storeId: inputData.storeId,
1487
1494
  queueName: queueName,
1488
1495
  message: inputData.comments,
@@ -1500,8 +1507,9 @@ export async function reTrigger( req, res ) {
1500
1507
  storeId: inputData.storeId,
1501
1508
  clientId: req.audit.clientId,
1502
1509
  fileDate: inputData.fileDate,
1510
+ moduleType: 'traffic',
1503
1511
  fileDateISO: dayjs( inputData.fileDate, 'DD-MM-YYYY' ).format(),
1504
- auditType: inputData.auditType,
1512
+ auditType: inputData.type,
1505
1513
  fileCount: inputData.beforeCount,
1506
1514
  queueName: queueName,
1507
1515
  userId: inputData.userId,
@@ -1537,7 +1545,7 @@ export async function reTrigger( req, res ) {
1537
1545
  beforeCount: inputData.totalCount,
1538
1546
  afterCount: '',
1539
1547
  fileDate: inputData.fileDate,
1540
- auditType: inputData.auditType,
1548
+ auditType: inputData.type,
1541
1549
  storeId: inputData.storeId,
1542
1550
  queueName: queueName,
1543
1551
  message: inputData.comments,
@@ -7,10 +7,10 @@ import { findOneUser } from '../service/user.service.js';
7
7
  import { findOneStore } from '../service/store.service.js';
8
8
  import dayjs from 'dayjs';
9
9
  import { aggregateUserAudit, findOneUserAudit, updateOneUserAudit } from '../service/userAudit.service.js';
10
- import { aggregateAssignAudit } from '../service/assignAudit.service.js';
10
+ import { aggregateAssignAudit, createAssignAudit } from '../service/assignAudit.service.js';
11
11
  import { createAuditLog, findOneAuditLog } from '../service/auditLog.service.js';
12
12
  import { mapCustomer, mapEmployee, mapJunk, splitB20000, splitE0, splitG20000 } from '../validation/audit.validation.js';
13
- import { aggregateClient, findClient } from '../service/client.service.js';
13
+ import { aggregateClient, findClient, findOneClient } from '../service/client.service.js';
14
14
  import { aggregateAuditClientData } from '../service/auditClientData.service.js';
15
15
  import _ from 'lodash';
16
16
  import { listQueue } from 'tango-app-api-middleware/src/utils/aws/sqs.js';
@@ -1338,3 +1338,148 @@ export async function clientMetrics( req, res ) {
1338
1338
  return res.sendError( err, 500 );
1339
1339
  }
1340
1340
  }
1341
+
1342
+ export async function reTrigger( req, res ) {
1343
+ try {
1344
+ const openSearch = JSON.parse( process.env.OPENSEARCH );
1345
+ const inputData = req.body;
1346
+ const sqs = JSON.parse( process.env.SQS );
1347
+ const query ={
1348
+ storeId: inputData.storeId,
1349
+ fileDate: inputData.fileDate,
1350
+ };
1351
+ const getQueueName = await findOneClient( { clientId: req.audit.clientId }, { 'auditConfigs.zoneQueueName': 1 } );
1352
+
1353
+ if ( !getQueueName || getQueueName?.auditConfigs?.zoneQueueName == '' ) {
1354
+ return res.sendError( 'queueName does not create', 400 );
1355
+ }
1356
+ const queueName = getQueueName?.auditConfigs?.zoneQueueName;
1357
+ logger.info( { queueName: queueName } );
1358
+ switch ( inputData.triggerType ) {
1359
+ case 'queue':
1360
+ const msg = {
1361
+ store_id: inputData.storeId,
1362
+ curr_date: inputData.fileDate,
1363
+ audit_type: inputData.type,
1364
+ total_count: inputData.totalCount,
1365
+ zone_id: inputData.zoneName,
1366
+ };
1367
+
1368
+ const sqsProduceQueue = {
1369
+ QueueUrl: `${sqs.url}${queueName}`,
1370
+ MessageBody: JSON.stringify( msg ),
1371
+ };
1372
+ const sqsQueue = await sendMessageToQueue( sqsProduceQueue.QueueUrl, sqsProduceQueue.MessageBody );
1373
+ if ( sqsQueue?.errorCode ) {
1374
+ const error = sqsQueue?.errorMsg;
1375
+ const code = sqsQueue?.errorCode;
1376
+ return res.sendError( error, code );
1377
+ } else {
1378
+ if ( req.audit.status !== 'completed' ) {
1379
+ const userRecord ={
1380
+ auditStatus: 'skipped',
1381
+ isDraft: false,
1382
+ };
1383
+ const query ={
1384
+ storeId: inputData.storeId,
1385
+ fileDate: inputData.fileDate,
1386
+ zoneName: inputData.zoneName,
1387
+ auditStatus: req.audit.status,
1388
+
1389
+ };
1390
+ await updateOneUserAudit( query, userRecord );
1391
+ }
1392
+
1393
+ const storeRecord ={
1394
+ status: req.audit.status !== 'completed' ? 'skipped': 'not_assign',
1395
+ };
1396
+
1397
+ await updateOneStoreZoneAudit( query, storeRecord );
1398
+ const logData = {
1399
+ userId: req.user._id,
1400
+ userName: req.user.userName,
1401
+ logType: 'zoneAudit',
1402
+ logSubType: 'reTrigger',
1403
+ logData: {
1404
+ beforeCount: inputData.totalCount,
1405
+ afterCount: '',
1406
+ fileDate: inputData.fileDate,
1407
+ auditType: inputData.type,
1408
+ storeId: inputData.storeId,
1409
+ zoneName: inputData.zoneName,
1410
+ queueName: queueName,
1411
+ message: inputData.comments,
1412
+ triggerBy: req.user.userName,
1413
+ triggerId: req.user._id,
1414
+ triggerType: inputData.triggerType,
1415
+ },
1416
+ };
1417
+ await insertOpenSearchData( openSearch.activityLog, logData );
1418
+ }
1419
+ break;
1420
+ case 'user':
1421
+ const assignUser = await findOneUser( { _id: new mongoose.Types.ObjectId( inputData.userId ) } );
1422
+ const assignUserRecord = {
1423
+ storeId: inputData.storeId,
1424
+ clientId: req.audit.clientId,
1425
+ fileDate: inputData.fileDate,
1426
+ zoneName: inputData.zoneName,
1427
+ fileDateISO: dayjs( inputData.fileDate, 'DD-MM-YYYY' ).format(),
1428
+ auditType: inputData.type,
1429
+ moduleType: 'zone',
1430
+ fileCount: inputData.beforeCount,
1431
+ queueName: queueName,
1432
+ userId: inputData.userId,
1433
+ userName: assignUser.userName,
1434
+ };
1435
+ await createAssignAudit( assignUserRecord );
1436
+
1437
+ if ( req.audit.status !== 'completed' ) {
1438
+ const userRecord ={
1439
+ auditStatus: 'skipped',
1440
+ isDraft: false,
1441
+ };
1442
+ const query ={
1443
+ storeId: inputData.storeId,
1444
+ fileDate: inputData.fileDate,
1445
+ zoneName: inputData.zoneName,
1446
+ auditStatus: req.audit.status,
1447
+
1448
+ };
1449
+ await updateOneUserAudit( query, userRecord );
1450
+ }
1451
+
1452
+ const storeRecord ={
1453
+ status: req.audit.status !== 'completed' ? 'skipped': 'assigned',
1454
+ };
1455
+
1456
+ await updateOneStoreZoneAudit( query, storeRecord );
1457
+ const logData = {
1458
+ userId: req.user._id,
1459
+ userName: req.user.userName,
1460
+ logType: 'zoneAudit',
1461
+ logSubType: 'reTrigger',
1462
+ logData: {
1463
+ beforeCount: inputData.totalCount,
1464
+ afterCount: '',
1465
+ fileDate: inputData.fileDate,
1466
+ auditType: inputData.type,
1467
+ storeId: inputData.storeId,
1468
+ zoneName: inputData.zoneName,
1469
+ queueName: queueName,
1470
+ message: inputData.comments,
1471
+ triggerBy: req.user.userName,
1472
+ triggerId: req.user._id,
1473
+ triggerType: inputData.triggerType,
1474
+ },
1475
+ };
1476
+ await insertOpenSearchData( openSearch.activityLog, logData );
1477
+ }
1478
+
1479
+ return res.sendSuccess( { result: 'The File has been Re Trigger Succesfully' } );
1480
+ } catch ( error ) {
1481
+ const err = error.message;
1482
+ logger.error( { error: error, message: req.body } );
1483
+ return res.sendError( err, 500 );
1484
+ }
1485
+ }
@@ -1,5 +1,5 @@
1
1
  import j2s from 'joi-to-swagger';
2
- import { clientMetricsSchema, getDraftedDataSchema, getFileSchema, saveDraftSchema, saveSchema, storeMetricsSchema, workSpaceSchema } from '../dtos/zoneAudit.dtos.js';
2
+ import { clientMetricsSchema, getDraftedDataSchema, getFileSchema, reTriggerValidSchema, saveDraftSchema, saveSchema, storeMetricsSchema, workSpaceSchema } from '../dtos/zoneAudit.dtos.js';
3
3
 
4
4
  export const zoneAuditDocs = {
5
5
  '/v3/zone-audit/get-file': {
@@ -202,4 +202,27 @@ export const zoneAuditDocs = {
202
202
  },
203
203
  },
204
204
 
205
+ '/v3/zone-audit/metrics/re-trigger': {
206
+ post: {
207
+ tags: [ 'Zone Audit Metrics' ],
208
+ description: `Manual re trigger a file`,
209
+ operationId: 'metrics/re-trigger',
210
+ parameters: {},
211
+ requestBody: {
212
+ content: {
213
+ 'application/json': {
214
+ schema: j2s( reTriggerValidSchema ).swagger,
215
+ },
216
+ },
217
+ },
218
+ responses: {
219
+ 200: { description: 'Successful' },
220
+ 401: { description: 'Unauthorized User' },
221
+ 422: { description: 'Field Error' },
222
+ 500: { description: 'Server Error' },
223
+ 204: { description: 'Not Found' },
224
+ },
225
+ },
226
+ },
227
+
205
228
  };
@@ -129,8 +129,9 @@ export const overViewTableSchema = joi.object(
129
129
  clientId: joi.array().optional(),
130
130
  limit: joi.number().optional(),
131
131
  offset: joi.number().optional(),
132
- searchValue: joi.number().optional().allow( '' ),
132
+ searchValue: joi.string().optional().allow( '' ),
133
133
  filterByStatus: joi.array().required(),
134
+ filterByType: joi.array().optional(),
134
135
  filterByAuditType: joi.array().required(),
135
136
  sortColumnName: joi.string().optional(),
136
137
  sortBy: joi.number().optional(),
@@ -159,7 +160,7 @@ export const reTriggerValidSchema = joi.object(
159
160
  {
160
161
  fileDate: joi.string().required(),
161
162
  storeId: joi.string().required(),
162
- auditType: joi.string().optional(),
163
+ type: joi.string().optional(),
163
164
  triggerType: joi.string().optional(),
164
165
  totalCount: joi.number().required(),
165
166
  userId: joi.string().optional(),
@@ -127,3 +127,20 @@ export const clientMetricsValid = {
127
127
  body: clientMetricsSchema,
128
128
  };
129
129
 
130
+ export const reTriggerValidSchema = joi.object(
131
+ {
132
+ fileDate: joi.string().required(),
133
+ storeId: joi.string().required(),
134
+ zoneName: joi.string().required(),
135
+ type: joi.string().optional(),
136
+ triggerType: joi.string().optional(),
137
+ totalCount: joi.number().required(),
138
+ userId: joi.string().optional(),
139
+ comments: joi.string().optional().allow( '' ),
140
+ },
141
+ );
142
+
143
+ export const reTriggerValid = {
144
+ body: reTriggerValidSchema,
145
+ };
146
+
@@ -1,8 +1,9 @@
1
1
  import { Router } from 'express';
2
- import { clientMetricsValid, getDraftedDataValid, getFileValid, saveDraftValid, saveValid, storeMetricsValid, workSpaceValid } from '../dtos/zoneAudit.dtos.js';
2
+ import { clientMetricsValid, getDraftedDataValid, getFileValid, reTriggerValid, 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 { clientMetrics, getDraftedData, getZoneAuditFile, save, saveDraft, storeMetrics, workSpace } from '../controllers/zoneAudit.controller.js';
5
+ import { clientMetrics, getDraftedData, getZoneAuditFile, reTrigger, save, saveDraft, storeMetrics, workSpace } from '../controllers/zoneAudit.controller.js';
6
+ import { isAuditDocumentExist, isAuditInputFolderExist } from '../validation/zoneAudit.validation.js';
6
7
 
7
8
  export const zoneAuditRouter=Router();
8
9
 
@@ -17,3 +18,4 @@ zoneAuditRouter.get( '/work-space', isAllowedSessionHandler, validate( workSpace
17
18
 
18
19
  zoneAuditRouter.post( '/metrics/store-metrics', isAllowedSessionHandler, validate( storeMetricsValid ), storeMetrics );
19
20
  zoneAuditRouter.post( '/metrics/client-metrics', isAllowedSessionHandler, validate( clientMetricsValid ), clientMetrics );
21
+ zoneAuditRouter.post( '/metrics/re-trigger', isAllowedSessionHandler, validate( reTriggerValid ), isAuditDocumentExist, isAuditInputFolderExist, reTrigger );
@@ -0,0 +1,45 @@
1
+ import { checkFileExist } from 'tango-app-api-middleware';
2
+ import { findOneStoreZoneAudit } from '../service/storeZoneAudit.service.js';
3
+
4
+ export async function isAuditDocumentExist( req, res, next ) {
5
+ try {
6
+ const inputData = req.body;
7
+ const query={
8
+ storeId: inputData.storeId,
9
+ fileDate: inputData.fileDate,
10
+ zoneName: inputData.zoneName,
11
+ };
12
+ const auditInfo = await findOneStoreZoneAudit( query );
13
+ if ( auditInfo ) {
14
+ req.audit = auditInfo;
15
+ return next();
16
+ } else {
17
+ return res.sendError( 'No audited Record', 400 );
18
+ }
19
+ } catch ( error ) {
20
+ const err = error.message || 'Internal Server Error';
21
+ logger.error( { error: error, message: req.body, function: 'isAuditFileExist' } );
22
+ return res.sendError( err, 500 );
23
+ }
24
+ }
25
+
26
+ export async function isAuditInputFolderExist( req, res, next ) {
27
+ try {
28
+ const bucket = JSON.parse( process.env.BUCKET );
29
+ const inputData = req.method === 'POST' ? req.body : req.query;
30
+ const params={
31
+ Bucket: bucket.auditInput,
32
+ Key: `${inputData.fileDate}/${inputData.storeId}/${inputData.zoneName}`,
33
+ };
34
+ const isExist = await checkFileExist( params );
35
+ if ( isExist ) {
36
+ next();
37
+ } else {
38
+ return res.sendError( `Audit Input folder not available : ${inputData.fileDate}/${inputData.storeId}/${inputData.zoneName}`, 400 );
39
+ }
40
+ } catch ( error ) {
41
+ const err = error.message || 'Internal Server Error';
42
+ logger.error( { error: error, message: req.query, function: 'isAuidtInputFolderExist' } );
43
+ return res.sendError( err, 500 );
44
+ }
45
+ }