tango-app-api-audit 1.0.25 → 1.0.26
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 +2 -2
- package/src/controllers/auditMetrics.controllers.js +137 -3
- package/src/docs/auditMetrics.docs.js +45 -1
- package/src/dtos/auditMetrics.dtos.js +16 -0
- package/src/routes/auditMetrics.routes.js +5 -3
- package/src/service/assignAudit.service.js +4 -0
- package/src/service/client.service.js +4 -0
- package/src/validation/audit.validation.js +43 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tango-app-api-audit",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.26",
|
|
4
4
|
"description": "audit & audit metrics apis",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"mongodb": "^6.7.0",
|
|
24
24
|
"nodemon": "^3.1.3",
|
|
25
25
|
"swagger-ui-express": "^5.0.1",
|
|
26
|
-
"tango-api-schema": "^2.0.
|
|
26
|
+
"tango-api-schema": "^2.0.124",
|
|
27
27
|
"tango-app-api-middleware": "^3.1.24",
|
|
28
28
|
"winston": "^3.13.0",
|
|
29
29
|
"winston-daily-rotate-file": "^5.0.0"
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import { download, getUTC, logger } from 'tango-app-api-middleware';
|
|
1
|
+
import { download, getUTC, insertOpenSearchData, logger, sendMessageToQueue } from 'tango-app-api-middleware';
|
|
2
2
|
import { aggregateAuditClientData } from '../service/auditClientData.service.js';
|
|
3
|
-
import { aggregateUserAudit } from '../service/userAudit.service.js';
|
|
3
|
+
import { aggregateUserAudit, findOneUserAudit, updateOneUserAudit } from '../service/userAudit.service.js';
|
|
4
4
|
import mongoose from 'mongoose';
|
|
5
|
-
import { aggregateStoreAudit } from '../service/storeAudit.service.js';
|
|
5
|
+
import { aggregateStoreAudit, updateOneStoreAudit } from '../service/storeAudit.service.js';
|
|
6
|
+
import { findOneUser } from '../service/user.service.js';
|
|
7
|
+
import dayjs from 'dayjs';
|
|
8
|
+
import { createAssignAudit } from '../service/assignAudit.service.js';
|
|
9
|
+
import { countDocumentsStore } from '../service/store.service.js';
|
|
10
|
+
import { findOneClient } from '../service/client.service.js';
|
|
6
11
|
// import { listQueue } from 'tango-app-api-middleware/src/utils/aws/sqs.js';
|
|
7
12
|
|
|
8
13
|
export async function userAuditHistory( req, res ) {
|
|
@@ -1153,3 +1158,132 @@ export async function overAllAuditSummary( req, res ) {
|
|
|
1153
1158
|
return res.sendError( err, 500 );
|
|
1154
1159
|
}
|
|
1155
1160
|
}
|
|
1161
|
+
|
|
1162
|
+
export async function reTrigger( req, res ) {
|
|
1163
|
+
try {
|
|
1164
|
+
const openSearch = JSON.parse( process.env.OPENSEARCH );
|
|
1165
|
+
const inputData = req.body;
|
|
1166
|
+
const sqs = JSON.parse( process.env.SQS );
|
|
1167
|
+
const userAudit = await findOneUserAudit( { _id: inputData.auditId } );
|
|
1168
|
+
const query ={
|
|
1169
|
+
storeId: inputData.storeId,
|
|
1170
|
+
fileDate: inputData.fileDate,
|
|
1171
|
+
};
|
|
1172
|
+
const getQueueName = await findOneClient( { clientId: req.audit.clientId }, { 'auditConfigs.queueName': 1 } );
|
|
1173
|
+
|
|
1174
|
+
if ( !getQueueName || getQueueName?.auditConfigs?.queueName == '' ) {
|
|
1175
|
+
return res.sendError( 'queueName does not create', 400 );
|
|
1176
|
+
}
|
|
1177
|
+
const queueName = getQueueName?.auditConfigs?.queueName;
|
|
1178
|
+
logger.info( { queueName: queueName } );
|
|
1179
|
+
switch ( inputData.triggerType ) {
|
|
1180
|
+
case 'queue':
|
|
1181
|
+
const msg = {
|
|
1182
|
+
store_id: inputData.storeId,
|
|
1183
|
+
curr_date: inputData.fileDate,
|
|
1184
|
+
audit_type: inputData.auditType,
|
|
1185
|
+
total_count: inputData.totalCount,
|
|
1186
|
+
};
|
|
1187
|
+
|
|
1188
|
+
const sqsProduceQueue = {
|
|
1189
|
+
QueueUrl: `${sqs.url}${queueName}`,
|
|
1190
|
+
MessageBody: JSON.stringify( msg ),
|
|
1191
|
+
};
|
|
1192
|
+
const sqsQueue = await sendMessageToQueue( sqsProduceQueue.QueueUrl, sqsProduceQueue.MessageBody );
|
|
1193
|
+
if ( sqsQueue?.errorCode ) {
|
|
1194
|
+
const error = sqsQueue?.errorMsg;
|
|
1195
|
+
const code = sqsQueue?.errorCode;
|
|
1196
|
+
return res.sendError( error, code );
|
|
1197
|
+
} else {
|
|
1198
|
+
if ( userAudit?.auditStatus !== 'completed' ) {
|
|
1199
|
+
const userRecord ={
|
|
1200
|
+
auditStatus: 'skipped',
|
|
1201
|
+
isDraft: false,
|
|
1202
|
+
};
|
|
1203
|
+
await updateOneUserAudit( { _id: inputData.auditId }, userRecord );
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
const storeRecord ={
|
|
1207
|
+
status: userAudit?.auditStatus !== 'completed' ? 'skipped': 'not_assign',
|
|
1208
|
+
};
|
|
1209
|
+
|
|
1210
|
+
await updateOneStoreAudit( query, storeRecord );
|
|
1211
|
+
const logData = {
|
|
1212
|
+
userId: req.user._id,
|
|
1213
|
+
userName: req.user.userName,
|
|
1214
|
+
logType: 'audit',
|
|
1215
|
+
logSubType: 'reTrigger',
|
|
1216
|
+
logData: {
|
|
1217
|
+
beforeCount: inputData.totalCount,
|
|
1218
|
+
afterCount: '',
|
|
1219
|
+
fileDate: inputData.fileDate,
|
|
1220
|
+
auditType: inputData.auditType,
|
|
1221
|
+
storeId: inputData.storeId,
|
|
1222
|
+
queueName: queueName,
|
|
1223
|
+
auditId: inputData.auditId,
|
|
1224
|
+
message: inputData.comments,
|
|
1225
|
+
triggerBy: req.user.userName,
|
|
1226
|
+
triggerId: req.user._id,
|
|
1227
|
+
triggerType: inputData.triggerType,
|
|
1228
|
+
},
|
|
1229
|
+
};
|
|
1230
|
+
await insertOpenSearchData( openSearch.activityLog, logData );
|
|
1231
|
+
}
|
|
1232
|
+
break;
|
|
1233
|
+
case 'user':
|
|
1234
|
+
const assignUser = await findOneUser( { _id: new mongoose.Types.ObjectId( inputData.userId ) } );
|
|
1235
|
+
const assignUserRecord = {
|
|
1236
|
+
storeId: inputData.storeId,
|
|
1237
|
+
clientId: req.audit.clientId,
|
|
1238
|
+
fileDate: inputData.fileDate,
|
|
1239
|
+
fileDateISO: dayjs( inputData.fileDate, 'DD-MM-YYYY' ).format(),
|
|
1240
|
+
auditType: inputData.auditType,
|
|
1241
|
+
fileCount: inputData.beforeCount,
|
|
1242
|
+
queueName: queueName,
|
|
1243
|
+
userId: inputData.userId,
|
|
1244
|
+
userName: assignUser.userName,
|
|
1245
|
+
};
|
|
1246
|
+
await createAssignAudit( assignUserRecord );
|
|
1247
|
+
|
|
1248
|
+
if ( userAudit?.auditStatus !== 'completed' ) {
|
|
1249
|
+
const userRecord ={
|
|
1250
|
+
auditStatus: 'skipped',
|
|
1251
|
+
isDraft: false,
|
|
1252
|
+
};
|
|
1253
|
+
await updateOneUserAudit( { _id: inputData.auditId }, userRecord );
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
const storeRecord ={
|
|
1257
|
+
status: userAudit?.auditStatus !== 'completed' ? 'skipped': 'assigned',
|
|
1258
|
+
};
|
|
1259
|
+
|
|
1260
|
+
await updateOneStoreAudit( query, storeRecord );
|
|
1261
|
+
const logData = {
|
|
1262
|
+
userId: req.user._id,
|
|
1263
|
+
userName: req.user.userName,
|
|
1264
|
+
logType: 'audit',
|
|
1265
|
+
logSubType: 'reTrigger',
|
|
1266
|
+
logData: {
|
|
1267
|
+
beforeCount: inputData.totalCount,
|
|
1268
|
+
afterCount: '',
|
|
1269
|
+
fileDate: inputData.fileDate,
|
|
1270
|
+
auditType: inputData.auditType,
|
|
1271
|
+
storeId: inputData.storeId,
|
|
1272
|
+
queueName: queueName,
|
|
1273
|
+
auditId: inputData.auditId,
|
|
1274
|
+
message: inputData.comments,
|
|
1275
|
+
triggerBy: req.user.userName,
|
|
1276
|
+
triggerId: req.user._id,
|
|
1277
|
+
triggerType: inputData.triggerType,
|
|
1278
|
+
},
|
|
1279
|
+
};
|
|
1280
|
+
await insertOpenSearchData( openSearch.activityLog, logData );
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
return res.sendSuccess( { result: 'The File has been Re Trigger Succesfully' } );
|
|
1284
|
+
} catch ( error ) {
|
|
1285
|
+
const err = error.message;
|
|
1286
|
+
logger.error( { error: error, message: req.body } );
|
|
1287
|
+
return res.sendError( err, 500 );
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import j2s from 'joi-to-swagger';
|
|
2
|
-
import { clientMetricsSchema, getAuditImagesSchema, overViewCardSchema, overViewTableSchema, storeMetricsSchema, summarySplitSchema, userAuditHistorySchema, userMetricsSchema } from '../dtos/auditMetrics.dtos.js';
|
|
2
|
+
import { clientMetricsSchema, getAuditImagesSchema, overAllAuditSummarySchema, overViewCardSchema, overViewTableSchema, reTriggerValidSchema, storeMetricsSchema, summarySplitSchema, userAuditHistorySchema, userMetricsSchema } from '../dtos/auditMetrics.dtos.js';
|
|
3
3
|
|
|
4
4
|
export const auditMetricsDocs = {
|
|
5
5
|
|
|
@@ -179,4 +179,48 @@ export const auditMetricsDocs = {
|
|
|
179
179
|
},
|
|
180
180
|
},
|
|
181
181
|
},
|
|
182
|
+
'/v3/audit-metrics/overall-audit-summary': {
|
|
183
|
+
post: {
|
|
184
|
+
tags: [ 'Audit Metrics' ],
|
|
185
|
+
description: `Get overall user taken data with some filters `,
|
|
186
|
+
operationId: 'overall-audit-summary',
|
|
187
|
+
parameters: {},
|
|
188
|
+
requestBody: {
|
|
189
|
+
content: {
|
|
190
|
+
'application/json': {
|
|
191
|
+
schema: j2s( overAllAuditSummarySchema ).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
|
+
'/v3/audit-metrics/re-trigger': {
|
|
205
|
+
post: {
|
|
206
|
+
tags: [ 'Audit Metrics' ],
|
|
207
|
+
description: `Manual re trigger a file`,
|
|
208
|
+
operationId: 're-trigger',
|
|
209
|
+
parameters: {},
|
|
210
|
+
requestBody: {
|
|
211
|
+
content: {
|
|
212
|
+
'application/json': {
|
|
213
|
+
schema: j2s( reTriggerValidSchema ).swagger,
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
responses: {
|
|
218
|
+
200: { description: 'Successful' },
|
|
219
|
+
401: { description: 'Unauthorized User' },
|
|
220
|
+
422: { description: 'Field Error' },
|
|
221
|
+
500: { description: 'Server Error' },
|
|
222
|
+
204: { description: 'Not Found' },
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
},
|
|
182
226
|
};
|
|
@@ -150,3 +150,19 @@ export const overAllAuditSummarySchema = joi.object(
|
|
|
150
150
|
export const overAllAuditSummaryValid = {
|
|
151
151
|
body: overAllAuditSummarySchema,
|
|
152
152
|
};
|
|
153
|
+
|
|
154
|
+
export const reTriggerValidSchema = joi.object(
|
|
155
|
+
{
|
|
156
|
+
fileDate: joi.string().required(),
|
|
157
|
+
storeId: joi.string().required(),
|
|
158
|
+
auditType: joi.string().optional(),
|
|
159
|
+
triggerType: joi.string().optional(),
|
|
160
|
+
totalCount: joi.number().required(),
|
|
161
|
+
userId: joi.string().optional(),
|
|
162
|
+
auditId: joi.string().required(),
|
|
163
|
+
},
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
export const reTriggerValid = {
|
|
167
|
+
body: reTriggerValidSchema,
|
|
168
|
+
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
|
|
2
2
|
import express from 'express';
|
|
3
3
|
import { isAllowedSessionHandler, validate } from 'tango-app-api-middleware';
|
|
4
|
-
import { clientMetrics, overAllAuditSummary, overViewCard, overViewTable, storeMetrics, summarySplit, userAuditHistory, userMetrics } from '../controllers/auditMetrics.controllers.js';
|
|
5
|
-
import { clientMetricsValid, overAllAuditSummaryValid, overViewCardValid, overViewTableValid, storeMetricsValid, summarySplitValid, userAuditHistoryValid, userMetricsValid } from '../dtos/auditMetrics.dtos.js';
|
|
4
|
+
import { clientMetrics, overAllAuditSummary, overViewCard, overViewTable, reTrigger, storeMetrics, summarySplit, userAuditHistory, userMetrics } from '../controllers/auditMetrics.controllers.js';
|
|
5
|
+
import { clientMetricsValid, overAllAuditSummaryValid, overViewCardValid, overViewTableValid, reTriggerValid, storeMetricsValid, summarySplitValid, userAuditHistoryValid, userMetricsValid } from '../dtos/auditMetrics.dtos.js';
|
|
6
|
+
import { isAuditDocumentExist, isAuditInputFolderExist } from '../validation/audit.validation.js';
|
|
6
7
|
|
|
7
8
|
export const auditMetricsRouter = express.Router();
|
|
8
9
|
|
|
@@ -13,6 +14,7 @@ auditMetricsRouter.post( '/user-metrics', isAllowedSessionHandler, validate( use
|
|
|
13
14
|
auditMetricsRouter.post( '/overview-card', isAllowedSessionHandler, validate( overViewCardValid ), overViewCard );
|
|
14
15
|
auditMetricsRouter.post( '/summary-split-up', isAllowedSessionHandler, validate( summarySplitValid ), summarySplit );
|
|
15
16
|
auditMetricsRouter.post( '/overview-table', isAllowedSessionHandler, validate( overViewTableValid ), overViewTable );
|
|
16
|
-
auditMetricsRouter.post( '/overall-audit-summary', isAllowedSessionHandler, validate( overAllAuditSummaryValid, overAllAuditSummary )
|
|
17
|
+
auditMetricsRouter.post( '/overall-audit-summary', isAllowedSessionHandler, validate( overAllAuditSummaryValid ), overAllAuditSummary );
|
|
18
|
+
auditMetricsRouter.post( '/re-trigger', isAllowedSessionHandler, validate( reTriggerValid ), isAuditDocumentExist, isAuditInputFolderExist, reTrigger );
|
|
17
19
|
|
|
18
20
|
export default auditMetricsRouter;
|
|
@@ -6,3 +6,7 @@ export function aggregateAssignAudit( query ) {
|
|
|
6
6
|
export function updateOneAssignAudit( query, record ) {
|
|
7
7
|
return assignAuditModel.updateOne( query, { $set: record } );
|
|
8
8
|
}
|
|
9
|
+
|
|
10
|
+
export function createAssignAudit( query ) {
|
|
11
|
+
return assignAuditModel.create( query );
|
|
12
|
+
}
|
|
@@ -8,3 +8,7 @@ export function aggregateClient( query ) {
|
|
|
8
8
|
export function findClient( query, fields, sort={ createdAt: -1 } ) {
|
|
9
9
|
return clientModel.find( query, fields ).sort( sort );
|
|
10
10
|
}
|
|
11
|
+
|
|
12
|
+
export function findOneClient( query, fields ) {
|
|
13
|
+
return clientModel.findOne( query, fields );
|
|
14
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { checkFileExist, chunkArray, getQueueUrl, logger } from 'tango-app-api-middleware';
|
|
2
2
|
import { findOneUserAudit } from '../service/userAudit.service.js';
|
|
3
|
+
import { findOneStoreAudit } from '../service/storeAudit.service.js';
|
|
3
4
|
|
|
4
5
|
export async function isExistsQueue( req, res, next ) {
|
|
5
6
|
try {
|
|
@@ -159,4 +160,46 @@ const mapFunction = async ( chunkData, filterData ) => {
|
|
|
159
160
|
return chunkData;
|
|
160
161
|
};
|
|
161
162
|
|
|
163
|
+
export async function isAuditInputFolderExist( req, res, next ) {
|
|
164
|
+
try {
|
|
165
|
+
const bucket = JSON.parse( process.env.BUCKET );
|
|
166
|
+
const inputData = req.body;
|
|
167
|
+
const params={
|
|
168
|
+
Bucket: bucket.auditInput,
|
|
169
|
+
Key: `${inputData.fileDate}/${inputData.storeId}`,
|
|
170
|
+
};
|
|
171
|
+
const isExist = await checkFileExist( params );
|
|
172
|
+
if ( isExist ) {
|
|
173
|
+
next();
|
|
174
|
+
} else {
|
|
175
|
+
return res.sendError( `Audit Input folder not available : ${inputData.fileDate}/${inputData.storeId}`, 400 );
|
|
176
|
+
}
|
|
177
|
+
} catch ( error ) {
|
|
178
|
+
const err = error.message || 'Internal Server Error';
|
|
179
|
+
logger.error( { error: error, message: req.query, function: 'isAuidtInputFolderExist' } );
|
|
180
|
+
return res.sendError( err, 500 );
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export async function isAuditDocumentExist( req, res, next ) {
|
|
185
|
+
try {
|
|
186
|
+
const inputData = req.body;
|
|
187
|
+
const query={
|
|
188
|
+
storeId: inputData.storeId,
|
|
189
|
+
fileDate: inputData.fileDate,
|
|
190
|
+
};
|
|
191
|
+
const auditInfo = await findOneStoreAudit( query );
|
|
192
|
+
if ( auditInfo ) {
|
|
193
|
+
req.audit = auditInfo;
|
|
194
|
+
return next();
|
|
195
|
+
} else {
|
|
196
|
+
return res.sendError( 'No audited Record', 400 );
|
|
197
|
+
}
|
|
198
|
+
} catch ( error ) {
|
|
199
|
+
const err = error.message || 'Internal Server Error';
|
|
200
|
+
logger.error( { error: error, message: req.body, function: 'isAuditFileExist' } );
|
|
201
|
+
return res.sendError( err, 500 );
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
162
205
|
|