tango-app-api-audit 1.0.43 → 1.0.46
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/audit.controllers.js +3 -1
- package/src/controllers/zoneAudit.controller.js +362 -17
- package/src/docs/zoneAudit.docs.js +58 -18
- package/src/dtos/auditMetrics.dtos.js +11 -0
- package/src/dtos/zoneAudit.dtos.js +25 -0
- package/src/routes/auditMetrics.routes.js +2 -1
- package/src/routes/zone.routes.js +6 -3
- package/src/validation/audit.validation.js +1 -0
- package/src/validation/zoneAudit.validation.js +123 -1
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.46",
|
|
4
4
|
"description": "audit & audit metrics apis",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"mongodb": "^6.7.0",
|
|
25
25
|
"nodemon": "^3.1.3",
|
|
26
26
|
"swagger-ui-express": "^5.0.1",
|
|
27
|
-
"tango-api-schema": "^2.0.
|
|
27
|
+
"tango-api-schema": "^2.0.146",
|
|
28
28
|
"tango-app-api-middleware": "^3.1.28",
|
|
29
29
|
"winston": "^3.13.0",
|
|
30
30
|
"winston-daily-rotate-file": "^5.0.0"
|
|
@@ -210,7 +210,7 @@ export async function getAuditFile( req, res ) {
|
|
|
210
210
|
address: '$storeProfile.address',
|
|
211
211
|
};
|
|
212
212
|
const storeDetails = await findOneStore( storeQuery, storeFields );
|
|
213
|
-
|
|
213
|
+
res.sendSuccess( {
|
|
214
214
|
result: result,
|
|
215
215
|
storeId: storeDetails?.storeId,
|
|
216
216
|
storeName: storeDetails?.storeName,
|
|
@@ -257,6 +257,7 @@ export async function getAuditFile( req, res ) {
|
|
|
257
257
|
queueName: inputData.queueName,
|
|
258
258
|
beforeCount: reauditImg.length,
|
|
259
259
|
auditStatus: 'inprogress',
|
|
260
|
+
moduleType: 'traffic',
|
|
260
261
|
fileDateISO: start,
|
|
261
262
|
timeSpent: 0,
|
|
262
263
|
startTime: new Date(),
|
|
@@ -377,6 +378,7 @@ export async function getAuditFile( req, res ) {
|
|
|
377
378
|
queueName: inputData.queueName,
|
|
378
379
|
beforeCount: msg.total_count || files.length,
|
|
379
380
|
auditStatus: 'inprogress',
|
|
381
|
+
moduleType: 'traffic',
|
|
380
382
|
fileDateISO: start,
|
|
381
383
|
timeSpent: 0,
|
|
382
384
|
startTime: new Date(),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { download, fileUpload, getJsonFileData, getUTC, insertOpenSearchData, listFileByPath, sendMessageToQueue, signedUrl, sqsReceive } from 'tango-app-api-middleware';
|
|
2
|
-
import { aggregateZoneUserAudit, createZoneUserAudit, findOneZoneUserAudit } from '../service/zoneUserAudit.service.js';
|
|
1
|
+
import { download, fileUpload, getJsonFileData, getUTC, insertOpenSearchData, listFileByPath, listFileWithoutLimit, sendMessageToQueue, signedUrl, sqsReceive } from 'tango-app-api-middleware';
|
|
2
|
+
import { aggregateZoneUserAudit, createZoneUserAudit, findOneZoneUserAudit, updateOneZoneUserAudit } from '../service/zoneUserAudit.service.js';
|
|
3
3
|
import { logger } from 'tango-app-api-middleware';
|
|
4
4
|
import { aggregateAssignZoneAudit } from '../service/assignZoneAudit.service.js';
|
|
5
5
|
import { aggregateStoreZoneAudit, createStoreZoneAudit, findOneStoreZoneAudit, updateOneStoreZoneAudit } from '../service/storeZoneAudit.service.js';
|
|
@@ -9,11 +9,14 @@ import dayjs from 'dayjs';
|
|
|
9
9
|
import { aggregateUserAudit, findOneUserAudit, updateOneUserAudit } from '../service/userAudit.service.js';
|
|
10
10
|
import { aggregateAssignAudit, createAssignAudit } from '../service/assignAudit.service.js';
|
|
11
11
|
import { createAuditLog, findOneAuditLog } from '../service/auditLog.service.js';
|
|
12
|
-
import { mapCustomer, mapEmployee, mapJunk, splitB20000, splitE0, splitG20000 } from '../validation/audit.validation.js';
|
|
12
|
+
import { mapCustomer, mapEmployee, mapJunk, splitB20000, splitE0, splitG20000, zipDownloadImage } from '../validation/audit.validation.js';
|
|
13
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
|
+
import mongoose from 'mongoose';
|
|
16
17
|
import { listQueue } from 'tango-app-api-middleware/src/utils/aws/sqs.js';
|
|
18
|
+
import { getReauditImg } from './audit.controllers.js';
|
|
19
|
+
import { getZoneAuditFilterData, getZoneAuditImageData } from '../validation/zoneAudit.validation.js';
|
|
17
20
|
|
|
18
21
|
export async function getZoneAuditFile( req, res ) {
|
|
19
22
|
try {
|
|
@@ -88,21 +91,100 @@ export async function getZoneAuditFile( req, res ) {
|
|
|
88
91
|
}
|
|
89
92
|
break;
|
|
90
93
|
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
case 'drafted':
|
|
95
|
+
logger.info( 'userDetails drafted', { inputData } );
|
|
93
96
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
const log = await findOneZoneUserAudit(
|
|
98
|
+
{
|
|
99
|
+
userId: userDetails[0].userId,
|
|
100
|
+
fileDate: userDetails[0].fileDate,
|
|
101
|
+
storeId: userDetails[0].storeId,
|
|
102
|
+
totalCount: userDetails[0].beforeCount,
|
|
103
|
+
moduleType: 'zone',
|
|
104
|
+
zoneName: userDetails[0].zoneName,
|
|
105
|
+
},
|
|
106
|
+
{},
|
|
107
|
+
{ createdAt: -1 },
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
if ( !log ) {
|
|
111
|
+
await updateOneZoneUserAudit(
|
|
112
|
+
{ _id: userDetails[0]._id },
|
|
113
|
+
{ $set: { isDraft: false, auditStatus: 'skipped' } },
|
|
114
|
+
);
|
|
115
|
+
logger.info( 'zone audit update in drafted', {
|
|
116
|
+
_id: userDetails[0]._id,
|
|
117
|
+
isDraft: false,
|
|
118
|
+
auditStatus: 'skipped',
|
|
119
|
+
} );
|
|
120
|
+
return res.sendError( 'User saved data has been deleted', 204 );
|
|
121
|
+
}
|
|
122
|
+
const file = {
|
|
123
|
+
auditId: userDetails[0]._id,
|
|
124
|
+
store_id: userDetails[0].storeId,
|
|
125
|
+
file_date: userDetails[0].fileDate,
|
|
126
|
+
type: userDetails[0].auditType,
|
|
127
|
+
queueName: log.queueName,
|
|
128
|
+
userId: log.userId,
|
|
129
|
+
zoneName: userDetails[0].zoneName,
|
|
130
|
+
};
|
|
131
|
+
const result = {
|
|
132
|
+
junk: log.junk,
|
|
133
|
+
junk_count: log.junkCount,
|
|
134
|
+
employee: log.employee,
|
|
135
|
+
employee_count: log.employeeCount,
|
|
136
|
+
customer: log.customer,
|
|
137
|
+
customer_count: log.customerCount,
|
|
138
|
+
retag_image: log.retagImage,
|
|
139
|
+
retag_count: log.retagCount,
|
|
140
|
+
total_count: log.totalCount,
|
|
141
|
+
};
|
|
100
142
|
|
|
101
|
-
|
|
102
|
-
// {},
|
|
103
|
-
// { createdAt: -1 },
|
|
104
|
-
// );
|
|
143
|
+
const userdata = await findOneUser( { _id: log.userId } );
|
|
105
144
|
|
|
145
|
+
if (
|
|
146
|
+
!inputData.nextId ||
|
|
147
|
+
inputData.nextId === '' ||
|
|
148
|
+
inputData.nextId == null
|
|
149
|
+
) {
|
|
150
|
+
const logData = {
|
|
151
|
+
userId: log.userId,
|
|
152
|
+
userName: userdata.name,
|
|
153
|
+
logType: 'auditZone',
|
|
154
|
+
logSubType: 'auditZoneStart',
|
|
155
|
+
logData: {
|
|
156
|
+
file_date: userDetails[0].fileDate,
|
|
157
|
+
auditType: userDetails[0].auditType,
|
|
158
|
+
storeId: userDetails[0].storeId,
|
|
159
|
+
clientName: log.queueName,
|
|
160
|
+
auditId: userDetails[0]._id,
|
|
161
|
+
zoneName: userDetails[0].zoneName,
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
logger.info( { logData: logData } );
|
|
165
|
+
await insertOpenSearchData( openSearch.activityLog, logData );
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const storeQuery = {
|
|
169
|
+
storeId: userDetails[0].storeId,
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const storeFields = {
|
|
173
|
+
storeId: 1,
|
|
174
|
+
storeName: 1,
|
|
175
|
+
address: '$storeProfile.address',
|
|
176
|
+
};
|
|
177
|
+
const storeDetails = await findOneStore( storeQuery, storeFields );
|
|
178
|
+
res.sendSuccess( {
|
|
179
|
+
result: result,
|
|
180
|
+
storeId: storeDetails?.storeId,
|
|
181
|
+
storeName: storeDetails?.storeName,
|
|
182
|
+
address: storeDetails?.address || '',
|
|
183
|
+
count: log.totalCount,
|
|
184
|
+
file: file,
|
|
185
|
+
isDraft: userDetails[0].isDraft,
|
|
186
|
+
} );
|
|
187
|
+
break;
|
|
106
188
|
|
|
107
189
|
default:
|
|
108
190
|
msg = {
|
|
@@ -119,6 +201,104 @@ export async function getZoneAuditFile( req, res ) {
|
|
|
119
201
|
* Reaudit pending
|
|
120
202
|
*/
|
|
121
203
|
|
|
204
|
+
if ( msg.audit_type === 'ReAudit' ) {
|
|
205
|
+
logger.info( 'Hit in zone user ReAudit', { inputData } );
|
|
206
|
+
let reauditInsert = {};
|
|
207
|
+
const [ filterData, auditImage ] = await Promise.all( [
|
|
208
|
+
getZoneFilterData( msg ),
|
|
209
|
+
getZoneAuditImage( msg ),
|
|
210
|
+
] );
|
|
211
|
+
if ( filterData.statusCode == 404 || auditImage.statusCode == 404 ) {
|
|
212
|
+
return res.sendError( 'No Data found', 204 );
|
|
213
|
+
}
|
|
214
|
+
const reauditImg = await getReauditImg( filterData, auditImage );
|
|
215
|
+
if ( userDetails.length === 0 ) {
|
|
216
|
+
const [ day, month, year ] = msg.curr_date.split( '-' );
|
|
217
|
+
const temp = `${year}-${month}-${day}`;
|
|
218
|
+
let start = new Date( temp );
|
|
219
|
+
const userTimezoneOffset = start.getTimezoneOffset() * 60000;
|
|
220
|
+
start = new Date( start.getTime() - userTimezoneOffset );
|
|
221
|
+
start.setUTCHours( 0, 0, 0, 0 );
|
|
222
|
+
const record = {
|
|
223
|
+
userId: req.user._id,
|
|
224
|
+
storeId: msg.store_id,
|
|
225
|
+
clientId: msg.store_id.split( '-' )[0],
|
|
226
|
+
auditType: msg.audit_type || 'ReAudit',
|
|
227
|
+
fileDate: msg.curr_date,
|
|
228
|
+
queueName: inputData.queueName,
|
|
229
|
+
beforeCount: reauditImg.length,
|
|
230
|
+
zoneAuditStatus: 'inprogress',
|
|
231
|
+
zoneName: msg.zone_id,
|
|
232
|
+
fileDateISO: start,
|
|
233
|
+
timeSpent: 0,
|
|
234
|
+
startTime: new Date(),
|
|
235
|
+
moduleType: 'zone',
|
|
236
|
+
};
|
|
237
|
+
const storeRecord = {
|
|
238
|
+
userId: req.user._id,
|
|
239
|
+
storeId: msg.store_id,
|
|
240
|
+
clientId: msg.store_id.split( '-' )[0],
|
|
241
|
+
auditType: msg.audit_type || 'ReAudit',
|
|
242
|
+
fileDate: msg.curr_date,
|
|
243
|
+
queueName: inputData.queueName,
|
|
244
|
+
beforeCount: reauditImg.length,
|
|
245
|
+
status: 'inprogress',
|
|
246
|
+
fileDateISO: start,
|
|
247
|
+
timeSpent: 0,
|
|
248
|
+
zoneName: msg.zone_id,
|
|
249
|
+
};
|
|
250
|
+
reauditInsert = await createZoneUserAudit( record );
|
|
251
|
+
await createStoreZoneAudit( storeRecord );
|
|
252
|
+
} else {
|
|
253
|
+
reauditInsert = userDetails[0];
|
|
254
|
+
}
|
|
255
|
+
const userdata = await findOneUser( { _id: req.user._id } );
|
|
256
|
+
if ( inputData.nextId ) {
|
|
257
|
+
const logData = {
|
|
258
|
+
userId: req.user._id,
|
|
259
|
+
userName: userdata.name,
|
|
260
|
+
logType: 'auditZone',
|
|
261
|
+
logSubType: 'auditZoneStart',
|
|
262
|
+
logData: {
|
|
263
|
+
fileDate: msg.curr_date,
|
|
264
|
+
auditType: msg.audit_type,
|
|
265
|
+
storeId: msg.store_id,
|
|
266
|
+
clientName: inputData.queueName,
|
|
267
|
+
auditId: reauditInsert._id,
|
|
268
|
+
zoneName: msg.zone_id,
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
await insertOpenSearchData( openSearch.activityLog, logData );
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const storeQuery = {
|
|
275
|
+
storeId: msg.store_id,
|
|
276
|
+
};
|
|
277
|
+
const storeFields = {
|
|
278
|
+
storeId: 1,
|
|
279
|
+
storeName: 1,
|
|
280
|
+
address: '$storeProfile.address',
|
|
281
|
+
};
|
|
282
|
+
const storeInfo = await findOneStore( storeQuery, storeFields );
|
|
283
|
+
return res.sendSuccess( {
|
|
284
|
+
result: reauditImg,
|
|
285
|
+
count: reauditImg.length,
|
|
286
|
+
storeId: storeInfo?.storeId,
|
|
287
|
+
storeName: storeInfo?.storeName,
|
|
288
|
+
address: storeInfo?.address || '',
|
|
289
|
+
file: {
|
|
290
|
+
store_id: msg.store_id,
|
|
291
|
+
file_date: msg.curr_date,
|
|
292
|
+
type: msg.audit_type || 'ReAudit',
|
|
293
|
+
queueName: inputData.queueName,
|
|
294
|
+
auditId: reauditInsert._id,
|
|
295
|
+
userId: reauditInsert.userId,
|
|
296
|
+
zoneName: msg.zone_id,
|
|
297
|
+
},
|
|
298
|
+
isDraft: reauditInsert.isDraft,
|
|
299
|
+
} );
|
|
300
|
+
}
|
|
301
|
+
// ////////////
|
|
122
302
|
|
|
123
303
|
const storeId = msg.store_id;
|
|
124
304
|
const fileDate = msg.curr_date;
|
|
@@ -233,6 +413,7 @@ export async function getZoneAuditFile( req, res ) {
|
|
|
233
413
|
storeId: storeId,
|
|
234
414
|
clientName: inputData.queueName,
|
|
235
415
|
auditId: insertData._id,
|
|
416
|
+
zoneName: msg.zone_id,
|
|
236
417
|
},
|
|
237
418
|
};
|
|
238
419
|
await insertOpenSearchData( openSearch.activityLog, logData );
|
|
@@ -964,6 +1145,7 @@ export async function storeMetrics( req, res ) {
|
|
|
964
1145
|
storeName: '$store.storeName',
|
|
965
1146
|
clientName: '',
|
|
966
1147
|
clientId: 1,
|
|
1148
|
+
zoneName: 1,
|
|
967
1149
|
userId: {
|
|
968
1150
|
$arrayElemAt: [ '$userId', { $subtract: [ { $size: '$userId' }, 1 ] } ],
|
|
969
1151
|
},
|
|
@@ -1042,6 +1224,7 @@ export async function storeMetrics( req, res ) {
|
|
|
1042
1224
|
_id: 0,
|
|
1043
1225
|
fileDate: 1,
|
|
1044
1226
|
storeId: 1,
|
|
1227
|
+
zoneName: 1,
|
|
1045
1228
|
storeName: '$stores.storeName',
|
|
1046
1229
|
userName: '$users.userName',
|
|
1047
1230
|
userEmail: '$users.userEmail',
|
|
@@ -1099,6 +1282,8 @@ export async function storeMetrics( req, res ) {
|
|
|
1099
1282
|
{ userName: { $regex: inputData.searchValue, $options: 'i' } },
|
|
1100
1283
|
{ status: { $regex: inputData.searchValue, $options: 'i' } },
|
|
1101
1284
|
{ auditType: { $regex: inputData.searchValue, $options: 'i' } },
|
|
1285
|
+
{ zoneName: { $regex: inputData.searchValue, $options: 'i' } },
|
|
1286
|
+
|
|
1102
1287
|
],
|
|
1103
1288
|
},
|
|
1104
1289
|
} );
|
|
@@ -1137,6 +1322,7 @@ export async function storeMetrics( req, res ) {
|
|
|
1137
1322
|
'Store Name': element.storeName,
|
|
1138
1323
|
'Client Id': element.clientId,
|
|
1139
1324
|
'Client Name': element.clientName,
|
|
1325
|
+
'Zone Name': element.clientName,
|
|
1140
1326
|
'User Name': element.userName,
|
|
1141
1327
|
'User Email': element.userEmail,
|
|
1142
1328
|
'Audit Type': element.auditType,
|
|
@@ -1156,6 +1342,152 @@ export async function storeMetrics( req, res ) {
|
|
|
1156
1342
|
}
|
|
1157
1343
|
}
|
|
1158
1344
|
|
|
1345
|
+
export async function zoneAuditImages( req, res ) {
|
|
1346
|
+
try {
|
|
1347
|
+
const inputData = req.query;
|
|
1348
|
+
let auditImageDownload = '';
|
|
1349
|
+
switch ( inputData.imageType ) {
|
|
1350
|
+
case 'BC':
|
|
1351
|
+
const auditImageBC = await getZoneAuditImageData( inputData );
|
|
1352
|
+
if ( auditImageBC?.errorCode ) {
|
|
1353
|
+
const error = auditImageBC?.errorMsg;
|
|
1354
|
+
const code = auditImageBC?.errorCode;
|
|
1355
|
+
return res.sendError( { error: error }, code );
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
if ( inputData.export==true ) {
|
|
1359
|
+
auditImageDownload= await zipDownloadImage( auditImageBC );
|
|
1360
|
+
// Set response headers for the zip file
|
|
1361
|
+
res.set( 'Content-Type', 'application/zip' );
|
|
1362
|
+
res.set( 'Content-Disposition', `attachment; filename=${inputData.storeId}_${inputData.fileDate}_${inputData.imageType}_${inputData.zoneName}.zip` );
|
|
1363
|
+
|
|
1364
|
+
// Send the zip file as the API response
|
|
1365
|
+
return res.send( auditImageDownload );
|
|
1366
|
+
}
|
|
1367
|
+
res.sendSuccess( { result: auditImageBC } );
|
|
1368
|
+
|
|
1369
|
+
break;
|
|
1370
|
+
|
|
1371
|
+
case 'AC':
|
|
1372
|
+
|
|
1373
|
+
const [ filterData, auditImageAC ] = await Promise.all( [ getZoneAuditFilterData( inputData ), getZoneAuditImageData( inputData ) ] );
|
|
1374
|
+
|
|
1375
|
+
if ( filterData?.errorCode || auditImageAC?.errorCode ) {
|
|
1376
|
+
const error = filterData?.errorMsg || auditImageAC.errorMsg;
|
|
1377
|
+
const code = filterData?.errorCode || auditImageAC.errorCode;
|
|
1378
|
+
return res.sendError( { error: error }, code );
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
const reauditImg = await getReauditImg( filterData, auditImageAC );
|
|
1382
|
+
|
|
1383
|
+
logger.info( { filterData: filterData } );
|
|
1384
|
+
logger.info( { auditImageAC: auditImageAC } );
|
|
1385
|
+
logger.info( { reauditImg: reauditImg } );
|
|
1386
|
+
if ( inputData.export==true ) {
|
|
1387
|
+
auditImageDownload= await zipDownloadImage( reauditImg );
|
|
1388
|
+
// Set response headers for the zip file
|
|
1389
|
+
res.set( 'Content-Type', 'application/zip' );
|
|
1390
|
+
res.set( 'Content-Disposition', `attachment; filename=${inputData.storeId}_${inputData.fileDate}_${inputData.imageType}.zip` );
|
|
1391
|
+
|
|
1392
|
+
// Send the zip file as the API response
|
|
1393
|
+
return res.send( auditImageDownload );
|
|
1394
|
+
}
|
|
1395
|
+
res.sendSuccess( { result: reauditImg } );
|
|
1396
|
+
break;
|
|
1397
|
+
default:
|
|
1398
|
+
res.sendError( 'No Data Found', 204 );
|
|
1399
|
+
break;
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
|
|
1403
|
+
// return res.sendSuccess( { result: inputData } );
|
|
1404
|
+
} catch ( error ) {
|
|
1405
|
+
const err = error.message || 'Internal Server Error';
|
|
1406
|
+
logger.info( { error: error, message: req.body, function: 'beforeCountImages' } );
|
|
1407
|
+
return res.sendError( err, 500 );
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
|
|
1412
|
+
export async function getZoneFilterData( msg ) {
|
|
1413
|
+
try {
|
|
1414
|
+
const bucket = JSON.parse( process.env.BUCKET );
|
|
1415
|
+
const params = {
|
|
1416
|
+
Bucket: `${bucket.auditOutput}`,
|
|
1417
|
+
Key: `${msg.store_id}/${inputData.zoneName}/${msg.curr_date}/${bucketName.masterJsonFile}`,
|
|
1418
|
+
};
|
|
1419
|
+
const mappingFile = await getJsonFileData( params );
|
|
1420
|
+
if ( mappingFile.statusCode ) {
|
|
1421
|
+
return mappingFile;
|
|
1422
|
+
} else {
|
|
1423
|
+
const mappingData = await JSON.parse( mappingFile.toString( 'utf-8' ) );
|
|
1424
|
+
const filterData = await mappingData.person_data.filter(
|
|
1425
|
+
( item ) =>
|
|
1426
|
+
item.temp_ids < 20000 &&
|
|
1427
|
+
item.temp_ids > 0 &&
|
|
1428
|
+
item.person_status === '',
|
|
1429
|
+
);
|
|
1430
|
+
const finalResult = await filterData.map( ( i ) => {
|
|
1431
|
+
return { ...i, img: i.index.concat( '_', i.temp_ids ) };
|
|
1432
|
+
} );
|
|
1433
|
+
return finalResult;
|
|
1434
|
+
}
|
|
1435
|
+
} catch ( error ) {
|
|
1436
|
+
logger.error( {
|
|
1437
|
+
error: error,
|
|
1438
|
+
type: 'MAPPING JSON getFilterData',
|
|
1439
|
+
function: 'getZoneFilterData',
|
|
1440
|
+
} );
|
|
1441
|
+
return error;
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
export async function getZoneAuditImage( msg ) {
|
|
1446
|
+
try {
|
|
1447
|
+
const bucket = JSON.parse( process.env.BUCKET );
|
|
1448
|
+
const storeId = msg.store_id;
|
|
1449
|
+
const fileDate = msg.curr_date;
|
|
1450
|
+
const files = [];
|
|
1451
|
+
const fetchData = {};
|
|
1452
|
+
fetchData.Bucket = `${bucket.auditInput}`;
|
|
1453
|
+
fetchData.filePath = `${fileDate}/${storeId}/${msg.zone_id}/`;
|
|
1454
|
+
const folderPath = await listFileWithoutLimit( fetchData );
|
|
1455
|
+
if ( folderPath.statusCode == 404 ) {
|
|
1456
|
+
return folderPath;
|
|
1457
|
+
}
|
|
1458
|
+
const auditImages = folderPath;
|
|
1459
|
+
if ( auditImages && auditImages?.length > 0 ) {
|
|
1460
|
+
for ( let i = 0; i < auditImages.length; i++ ) {
|
|
1461
|
+
const img = auditImages[i].Key.split( '/' );
|
|
1462
|
+
const image = img[2].split( '.' );
|
|
1463
|
+
const indexes = image[0].split( '_' );
|
|
1464
|
+
const params = {
|
|
1465
|
+
file_path: auditImages[i].Key,
|
|
1466
|
+
Bucket: fetchData.Bucket,
|
|
1467
|
+
};
|
|
1468
|
+
const data = await signedUrl( params );
|
|
1469
|
+
const mapimg = {
|
|
1470
|
+
img_path: data,
|
|
1471
|
+
img_name: indexes[1],
|
|
1472
|
+
img_id: image[0],
|
|
1473
|
+
};
|
|
1474
|
+
files.push( {
|
|
1475
|
+
img_path: data,
|
|
1476
|
+
img_name: indexes[1],
|
|
1477
|
+
img_id: image[0],
|
|
1478
|
+
selected: false,
|
|
1479
|
+
dropped: false,
|
|
1480
|
+
count: 1,
|
|
1481
|
+
mappedid: [ mapimg ],
|
|
1482
|
+
} );
|
|
1483
|
+
}
|
|
1484
|
+
return files;
|
|
1485
|
+
}
|
|
1486
|
+
} catch ( error ) {
|
|
1487
|
+
logger.error( { error: error, type: 'AWS BUCKET --getAuditImage' } );
|
|
1488
|
+
return error;
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1159
1491
|
export async function clientMetrics( req, res ) {
|
|
1160
1492
|
try {
|
|
1161
1493
|
const inputData = req.body;
|
|
@@ -1347,13 +1679,15 @@ export async function reTrigger( req, res ) {
|
|
|
1347
1679
|
const query ={
|
|
1348
1680
|
storeId: inputData.storeId,
|
|
1349
1681
|
fileDate: inputData.fileDate,
|
|
1682
|
+
zoneName: inputData.zoneName,
|
|
1350
1683
|
};
|
|
1351
|
-
const getQueueName = await findOneClient( { clientId: req.audit.clientId }, { 'auditConfigs
|
|
1352
|
-
|
|
1684
|
+
const getQueueName = await findOneClient( { clientId: req.audit.clientId }, { 'auditConfigs': 1 } );
|
|
1685
|
+
logger.info( { queueName: getQueueName.auditConfigs.zoneQueueName } );
|
|
1353
1686
|
if ( !getQueueName || getQueueName?.auditConfigs?.zoneQueueName == '' ) {
|
|
1354
1687
|
return res.sendError( 'queueName does not create', 400 );
|
|
1355
1688
|
}
|
|
1356
1689
|
const queueName = getQueueName?.auditConfigs?.zoneQueueName;
|
|
1690
|
+
|
|
1357
1691
|
logger.info( { queueName: queueName } );
|
|
1358
1692
|
switch ( inputData.triggerType ) {
|
|
1359
1693
|
case 'queue':
|
|
@@ -1483,3 +1817,14 @@ export async function reTrigger( req, res ) {
|
|
|
1483
1817
|
return res.sendError( err, 500 );
|
|
1484
1818
|
}
|
|
1485
1819
|
}
|
|
1820
|
+
|
|
1821
|
+
export async function viewLog( req, res ) {
|
|
1822
|
+
try {
|
|
1823
|
+
// const inputData = req.body;
|
|
1824
|
+
// const result = await
|
|
1825
|
+
} catch ( error ) {
|
|
1826
|
+
const err = error.message;
|
|
1827
|
+
logger.error( { error: error, message: req.body, function: 'viewLog' } );
|
|
1828
|
+
return res.sendError( err, 500 );
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import j2s from 'joi-to-swagger';
|
|
2
|
-
import { clientMetricsSchema, getDraftedDataSchema, getFileSchema,
|
|
2
|
+
import { clientMetricsSchema, getDraftedDataSchema, getFileSchema, saveDraftSchema, saveSchema, storeMetricsSchema, workSpaceSchema, zoneAuditImageValidSchema, reTriggerValidSchema } from '../dtos/zoneAudit.dtos.js';
|
|
3
3
|
|
|
4
4
|
export const zoneAuditDocs = {
|
|
5
5
|
'/v3/zone-audit/get-file': {
|
|
@@ -179,26 +179,66 @@ export const zoneAuditDocs = {
|
|
|
179
179
|
},
|
|
180
180
|
},
|
|
181
181
|
|
|
182
|
-
'/v3/zone-audit/metrics/
|
|
183
|
-
|
|
184
|
-
tags: [ 'Zone Audit Metrics' ],
|
|
185
|
-
description: `
|
|
186
|
-
operationId: '
|
|
187
|
-
parameters:
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
'
|
|
191
|
-
|
|
182
|
+
'/v3/zone-audit/metrics/audit-images': {
|
|
183
|
+
get: {
|
|
184
|
+
'tags': [ 'Zone Audit Metrics' ],
|
|
185
|
+
'description': `View and Download audit images`,
|
|
186
|
+
'operationId': 'zone audit-images',
|
|
187
|
+
'parameters': [
|
|
188
|
+
{
|
|
189
|
+
in: 'query',
|
|
190
|
+
name: 'fileDate',
|
|
191
|
+
scema: j2s( zoneAuditImageValidSchema ).swagger,
|
|
192
|
+
require: true,
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
in: 'query',
|
|
196
|
+
name: 'storeId',
|
|
197
|
+
scema: j2s( zoneAuditImageValidSchema ).swagger,
|
|
198
|
+
require: true,
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
in: 'query',
|
|
202
|
+
name: 'imageType',
|
|
203
|
+
scema: j2s( zoneAuditImageValidSchema ).swagger,
|
|
204
|
+
require: true,
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
in: 'query',
|
|
208
|
+
name: 'export',
|
|
209
|
+
scema: j2s( zoneAuditImageValidSchema ).swagger,
|
|
210
|
+
require: true,
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
in: 'query',
|
|
214
|
+
name: 'zoneName',
|
|
215
|
+
scema: j2s( zoneAuditImageValidSchema ).swagger,
|
|
216
|
+
require: true,
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
|
|
220
|
+
'/v3/zone-audit/metrics/client-metrics': {
|
|
221
|
+
post: {
|
|
222
|
+
tags: [ 'Zone Audit Metrics' ],
|
|
223
|
+
description: `Get list of client wise details with date range`,
|
|
224
|
+
operationId: 'metrics/client-metrics',
|
|
225
|
+
parameters: {},
|
|
226
|
+
requestBody: {
|
|
227
|
+
content: {
|
|
228
|
+
'application/json': {
|
|
229
|
+
schema: j2s( clientMetricsSchema ).swagger,
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
responses: {
|
|
234
|
+
200: { description: 'Successful' },
|
|
235
|
+
401: { description: 'Unauthorized User' },
|
|
236
|
+
422: { description: 'Field Error' },
|
|
237
|
+
500: { description: 'Server Error' },
|
|
238
|
+
204: { description: 'Not Found' },
|
|
192
239
|
},
|
|
193
240
|
},
|
|
194
241
|
},
|
|
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
242
|
},
|
|
203
243
|
},
|
|
204
244
|
|
|
@@ -184,3 +184,14 @@ export const auditImageValidSchema = joi.object(
|
|
|
184
184
|
export const auditImageValid = {
|
|
185
185
|
query: auditImageValidSchema,
|
|
186
186
|
};
|
|
187
|
+
|
|
188
|
+
export const viewLogSchema = joi.object(
|
|
189
|
+
{
|
|
190
|
+
fileDate: joi.string().required(),
|
|
191
|
+
storeId: joi.string().required(),
|
|
192
|
+
},
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
export const viewLogValid = {
|
|
196
|
+
query: viewLogSchema,
|
|
197
|
+
};
|
|
@@ -108,6 +108,19 @@ export const storeMetricsValid = {
|
|
|
108
108
|
body: storeMetricsSchema,
|
|
109
109
|
};
|
|
110
110
|
|
|
111
|
+
export const zoneAuditImageValidSchema = joi.object(
|
|
112
|
+
{
|
|
113
|
+
fileDate: joi.string().required(),
|
|
114
|
+
storeId: joi.string().required(),
|
|
115
|
+
imageType: joi.string().required(),
|
|
116
|
+
export: joi.boolean().required(),
|
|
117
|
+
zoneName: joi.string().required(),
|
|
118
|
+
},
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
export const zoneAuditImageValid = {
|
|
122
|
+
query: zoneAuditImageValidSchema,
|
|
123
|
+
};
|
|
111
124
|
export const clientMetricsSchema = joi.object(
|
|
112
125
|
{
|
|
113
126
|
fromDate: joi.string().required(),
|
|
@@ -144,3 +157,15 @@ export const reTriggerValid = {
|
|
|
144
157
|
body: reTriggerValidSchema,
|
|
145
158
|
};
|
|
146
159
|
|
|
160
|
+
export const viewLogSchema = joi.object(
|
|
161
|
+
{
|
|
162
|
+
fileDate: joi.string().required(),
|
|
163
|
+
storeId: joi.string().required(),
|
|
164
|
+
zoneName: joi.string().required(),
|
|
165
|
+
},
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
export const viewLogValid = {
|
|
169
|
+
body: viewLogSchema,
|
|
170
|
+
};
|
|
171
|
+
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import express from 'express';
|
|
3
3
|
import { isAllowedSessionHandler, validate } from 'tango-app-api-middleware';
|
|
4
4
|
import { auditImages, clientMetrics, overAllAuditSummary, overViewCard, overViewTable, reTrigger, storeMetrics, summarySplit, userAuditHistory, userMetrics } from '../controllers/auditMetrics.controllers.js';
|
|
5
|
-
import { auditImageValid, clientMetricsValid, overAllAuditSummaryValid, overViewCardValid, overViewTableValid, reTriggerValid, storeMetricsValid, summarySplitValid, userAuditHistoryValid, userMetricsValid } from '../dtos/auditMetrics.dtos.js';
|
|
5
|
+
import { auditImageValid, clientMetricsValid, overAllAuditSummaryValid, overViewCardValid, overViewTableValid, reTriggerValid, storeMetricsValid, summarySplitValid, userAuditHistoryValid, userMetricsValid, viewLogValid } from '../dtos/auditMetrics.dtos.js';
|
|
6
6
|
import { isAuditDocumentExist, isAuditInputFolderExist } from '../validation/audit.validation.js';
|
|
7
7
|
|
|
8
8
|
export const auditMetricsRouter = express.Router();
|
|
@@ -17,5 +17,6 @@ auditMetricsRouter.post( '/overview-table', isAllowedSessionHandler, validate( o
|
|
|
17
17
|
auditMetricsRouter.post( '/overall-audit-summary', isAllowedSessionHandler, validate( overAllAuditSummaryValid ), overAllAuditSummary );
|
|
18
18
|
auditMetricsRouter.post( '/re-trigger', isAllowedSessionHandler, validate( reTriggerValid ), isAuditDocumentExist, isAuditInputFolderExist, reTrigger );
|
|
19
19
|
auditMetricsRouter.get( '/audit-images', isAllowedSessionHandler, validate( auditImageValid ), isAuditInputFolderExist, auditImages );
|
|
20
|
+
auditMetricsRouter.post( '/view-log', isAllowedSessionHandler, validate( viewLogValid ), isAuditInputFolderExist, auditImages );
|
|
20
21
|
|
|
21
22
|
export default auditMetricsRouter;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
|
-
import { clientMetricsValid, getDraftedDataValid, getFileValid, reTriggerValid, saveDraftValid, saveValid,
|
|
2
|
+
import { clientMetricsValid, getDraftedDataValid, getFileValid, reTriggerValid, saveDraftValid, saveValid, viewLogValid, workSpaceValid, zoneAuditImageValid } 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, reTrigger, save, saveDraft, storeMetrics, workSpace } from '../controllers/zoneAudit.controller.js';
|
|
6
|
-
import {
|
|
5
|
+
import { clientMetrics, getDraftedData, getZoneAuditFile, reTrigger, save, saveDraft, storeMetrics, viewLog, workSpace, zoneAuditImages } from '../controllers/zoneAudit.controller.js';
|
|
6
|
+
import { storeMetricsValid } from '../dtos/auditMetrics.dtos.js';
|
|
7
|
+
import { isZoneAuditInputFolderExist, isAuditInputFolderExist, isAuditDocumentExist } from '../validation/zoneAudit.validation.js';
|
|
7
8
|
|
|
8
9
|
export const zoneAuditRouter=Router();
|
|
9
10
|
|
|
@@ -17,5 +18,7 @@ zoneAuditRouter.get( '/work-space', isAllowedSessionHandler, validate( workSpace
|
|
|
17
18
|
// metrics
|
|
18
19
|
|
|
19
20
|
zoneAuditRouter.post( '/metrics/store-metrics', isAllowedSessionHandler, validate( storeMetricsValid ), storeMetrics );
|
|
21
|
+
zoneAuditRouter.get( '/metrics/audit-images', isAllowedSessionHandler, validate( zoneAuditImageValid ), isZoneAuditInputFolderExist, zoneAuditImages );
|
|
20
22
|
zoneAuditRouter.post( '/metrics/client-metrics', isAllowedSessionHandler, validate( clientMetricsValid ), clientMetrics );
|
|
21
23
|
zoneAuditRouter.post( '/metrics/re-trigger', isAllowedSessionHandler, validate( reTriggerValid ), isAuditDocumentExist, isAuditInputFolderExist, reTrigger );
|
|
24
|
+
zoneAuditRouter.post( '/view-log', isAllowedSessionHandler, validate( viewLogValid ), viewLog );
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { checkFileExist } from 'tango-app-api-middleware';
|
|
1
|
+
import { checkFileExist, getJsonFileData, listFileWithoutLimit, signedUrl } from 'tango-app-api-middleware';
|
|
2
2
|
import { findOneStoreZoneAudit } from '../service/storeZoneAudit.service.js';
|
|
3
3
|
|
|
4
4
|
export async function isAuditDocumentExist( req, res, next ) {
|
|
@@ -43,3 +43,125 @@ export async function isAuditInputFolderExist( req, res, next ) {
|
|
|
43
43
|
return res.sendError( err, 500 );
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
+
|
|
47
|
+
export async function getZoneAuditFilterData( data ) {
|
|
48
|
+
try {
|
|
49
|
+
const bucket = JSON.parse( process.env.BUCKET );
|
|
50
|
+
const storeId = data.storeId;
|
|
51
|
+
const fileDate = data.fileDate;
|
|
52
|
+
const params = {
|
|
53
|
+
Bucket: `${bucket.auditOutput}`,
|
|
54
|
+
Key: `${storeId}/${data.zoneName}/${fileDate}/${bucket.masterJsonFile}`,
|
|
55
|
+
};
|
|
56
|
+
const mappingFile = await getJsonFileData( params );
|
|
57
|
+
if ( mappingFile.statusCode ) {
|
|
58
|
+
return mappingFile;
|
|
59
|
+
} else {
|
|
60
|
+
const mappingData = await JSON.parse( mappingFile.toString( 'utf-8' ) );
|
|
61
|
+
const filterData = await mappingData.person_data.filter(
|
|
62
|
+
( item ) =>
|
|
63
|
+
item.temp_ids < 20000 &&
|
|
64
|
+
item.temp_ids > 0 &&
|
|
65
|
+
item.person_status === '',
|
|
66
|
+
);
|
|
67
|
+
const finalResult = await filterData.map( ( i ) => {
|
|
68
|
+
return { ...i, img: i.index.concat( '_', i.temp_ids ) };
|
|
69
|
+
} );
|
|
70
|
+
return finalResult;
|
|
71
|
+
}
|
|
72
|
+
} catch ( error ) {
|
|
73
|
+
logger.error( {
|
|
74
|
+
error: error,
|
|
75
|
+
type: 'MAPPING JSON getFilterData',
|
|
76
|
+
function: 'getZoneAuditFilterData',
|
|
77
|
+
} );
|
|
78
|
+
return error;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export async function isZoneAuditInputFolderExist( req, res, next ) {
|
|
83
|
+
try {
|
|
84
|
+
const bucket = JSON.parse( process.env.BUCKET );
|
|
85
|
+
const inputData = req.method === 'POST' ? req.body : req.query;
|
|
86
|
+
const params={
|
|
87
|
+
Bucket: bucket.auditInput,
|
|
88
|
+
Key: `${inputData.fileDate}/${inputData.storeId}/${inputData.zoneName}`,
|
|
89
|
+
};
|
|
90
|
+
const isExist = await checkFileExist( params );
|
|
91
|
+
if ( isExist ) {
|
|
92
|
+
next();
|
|
93
|
+
} else {
|
|
94
|
+
return res.sendError( `Audit Input folder not available : ${inputData.fileDate}/${inputData.storeId}`, 400 );
|
|
95
|
+
}
|
|
96
|
+
} catch ( error ) {
|
|
97
|
+
const err = error.message || 'Internal Server Error';
|
|
98
|
+
logger.error( { error: error, message: req.query, function: 'isAuidtInputFolderExist' } );
|
|
99
|
+
return res.sendError( err, 500 );
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export async function getZoneAuditImageData( data ) {
|
|
104
|
+
try {
|
|
105
|
+
const bucket = JSON.parse( process.env.BUCKET );
|
|
106
|
+
const storeId = data.storeId;
|
|
107
|
+
const fileDate = data.fileDate;
|
|
108
|
+
const files = [];
|
|
109
|
+
const fetchData = {
|
|
110
|
+
Bucket: `${bucket.auditInput}`,
|
|
111
|
+
filePath: `${fileDate}/${storeId}/${data.zoneName}/`,
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const folderPath = await listFileWithoutLimit( fetchData );
|
|
115
|
+
if ( folderPath.statusCode == 404 ) {
|
|
116
|
+
return folderPath;
|
|
117
|
+
}
|
|
118
|
+
const auditImages = folderPath;
|
|
119
|
+
|
|
120
|
+
if ( data.export==false ) {
|
|
121
|
+
if ( auditImages && auditImages?.length > 0 ) {
|
|
122
|
+
for ( let i = 0; i < auditImages.length; i++ ) {
|
|
123
|
+
const img = auditImages[i].Key.split( '/' );
|
|
124
|
+
const image = img[3].split( '.' );
|
|
125
|
+
const indexes = image[0].split( '_' );
|
|
126
|
+
const params = {
|
|
127
|
+
file_path: auditImages[i].Key,
|
|
128
|
+
Bucket: fetchData.Bucket,
|
|
129
|
+
};
|
|
130
|
+
const data = await signedUrl( params );
|
|
131
|
+
files.push( {
|
|
132
|
+
imgPath: data,
|
|
133
|
+
imgName: indexes[1],
|
|
134
|
+
imgId: image[0],
|
|
135
|
+
img_name: indexes[1],
|
|
136
|
+
// imgFile: auditImages[i],
|
|
137
|
+
} );
|
|
138
|
+
}
|
|
139
|
+
return files;
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
if ( auditImages && auditImages?.length > 0 ) {
|
|
143
|
+
for ( let i = 0; i < auditImages.length; i++ ) {
|
|
144
|
+
const img = auditImages[i].Key.split( '/' );
|
|
145
|
+
const image = img[3].split( '.' );
|
|
146
|
+
const indexes = image[0].split( '_' );
|
|
147
|
+
const params = {
|
|
148
|
+
file_path: auditImages[i].Key,
|
|
149
|
+
Bucket: fetchData.Bucket,
|
|
150
|
+
};
|
|
151
|
+
const data = await signedUrl( params );
|
|
152
|
+
files.push( {
|
|
153
|
+
imgPath: data,
|
|
154
|
+
imgName: indexes[1],
|
|
155
|
+
imgId: image[0],
|
|
156
|
+
imgFile: auditImages[i],
|
|
157
|
+
img_name: indexes[1],
|
|
158
|
+
} );
|
|
159
|
+
}
|
|
160
|
+
return files;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
} catch ( error ) {
|
|
164
|
+
logger.error( { error: error, type: 'getZoneAuditImageData' } );
|
|
165
|
+
return error;
|
|
166
|
+
}
|
|
167
|
+
}
|