tango-app-api-audit 1.0.23 → 1.0.24
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
|
@@ -2,7 +2,6 @@ import { download, getUTC, logger } from 'tango-app-api-middleware';
|
|
|
2
2
|
import { aggregateAuditClientData } from '../service/auditClientData.service.js';
|
|
3
3
|
import { aggregateUserAudit } from '../service/userAudit.service.js';
|
|
4
4
|
import mongoose from 'mongoose';
|
|
5
|
-
import dayjs from 'dayjs';
|
|
6
5
|
import { aggregateStoreAudit } from '../service/storeAudit.service.js';
|
|
7
6
|
// import { listQueue } from 'tango-app-api-middleware/src/utils/aws/sqs.js';
|
|
8
7
|
|
|
@@ -103,16 +102,27 @@ export async function userAuditHistory( req, res ) {
|
|
|
103
102
|
|
|
104
103
|
export async function storeMetrics( req, res ) {
|
|
105
104
|
try {
|
|
106
|
-
const yesterday = dayjs().subtract( 1, 'days' ).format( 'YYYY-MM-DD' );
|
|
107
105
|
const inputData = req.body;
|
|
106
|
+
const limit = inputData.limit || 10;
|
|
107
|
+
const offset = inputData.offset ? ( inputData.offset - 1 ) * limit : 0;
|
|
108
108
|
const dateRange = await getUTC( new Date( inputData.fromDate ), new Date( inputData.toDate ) );
|
|
109
109
|
let filter = [
|
|
110
110
|
{ fileDateISO: { $gte: dateRange.start } },
|
|
111
111
|
{ fileDateISO: { $lte: dateRange.end } },
|
|
112
112
|
];
|
|
113
|
-
if ( inputData.
|
|
114
|
-
filter.push( { clientId: { $in: inputData.
|
|
113
|
+
if ( inputData.filterByClientId && inputData.filterByClientId?.length > 0 ) {
|
|
114
|
+
filter.push( { clientId: { $in: inputData.filterByClientId } } );
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if ( inputData.filterByStoreId && inputData.filterByStoreId?.length > 0 ) {
|
|
118
|
+
filter.push( { storeId: { $in: inputData.filterByStoreId } } );
|
|
115
119
|
}
|
|
120
|
+
|
|
121
|
+
if ( inputData.filterByStatus && inputData.filterByStatus?.length > 0 ) {
|
|
122
|
+
filter.push( { status: { $in: inputData.filterByStatus } } );
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
|
|
116
126
|
const query = [
|
|
117
127
|
{
|
|
118
128
|
$match: {
|
|
@@ -121,99 +131,109 @@ export async function storeMetrics( req, res ) {
|
|
|
121
131
|
},
|
|
122
132
|
{
|
|
123
133
|
$project: {
|
|
134
|
+
_id: 0,
|
|
124
135
|
fileDate: 1,
|
|
125
|
-
|
|
126
|
-
|
|
136
|
+
storeId: 1,
|
|
137
|
+
storeName: '$storeId',
|
|
138
|
+
userId: {
|
|
139
|
+
$arrayElemAt: [ '$userId', { $subtract: [ { $size: '$userId' }, 1 ] } ],
|
|
140
|
+
},
|
|
127
141
|
clientId: 1,
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
142
|
+
auditType: 1,
|
|
143
|
+
beforeCount: 1,
|
|
144
|
+
afterCount: { $ifNull: [ '$afterCount', null ] },
|
|
145
|
+
accuracy: { $round: [
|
|
146
|
+
{ $divide: [
|
|
147
|
+
{ $multiply: [ { $ifNull: [ '$afterCount', 0 ] }, '$beforeCount' ] }, 100,
|
|
148
|
+
] }, 2,
|
|
149
|
+
],
|
|
150
|
+
|
|
151
|
+
},
|
|
152
|
+
timeSpent: 1,
|
|
153
|
+
status: 1,
|
|
131
154
|
},
|
|
132
155
|
},
|
|
133
156
|
{
|
|
134
157
|
$lookup: {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
158
|
+
from: 'stores',
|
|
159
|
+
let: { storeId: '$storeId' },
|
|
160
|
+
pipeline: [
|
|
139
161
|
{
|
|
140
162
|
$match: {
|
|
141
163
|
$expr: {
|
|
142
|
-
$
|
|
143
|
-
{ $eq: [ '$clientId', '$$clientId' ] },
|
|
144
|
-
{ $eq: [ '$fileDate', '$$fileDate' ] },
|
|
145
|
-
],
|
|
164
|
+
$eq: [ '$storeId', '$$storeId' ],
|
|
146
165
|
},
|
|
147
166
|
},
|
|
148
167
|
},
|
|
149
168
|
{
|
|
150
169
|
$project: {
|
|
151
|
-
|
|
152
|
-
|
|
170
|
+
_id: 0,
|
|
171
|
+
storeName: 1,
|
|
153
172
|
},
|
|
154
173
|
},
|
|
174
|
+
], as: 'stores',
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
$unwind: {
|
|
179
|
+
path: '$stores',
|
|
180
|
+
preserveNullAndEmptyArrays: true,
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
$lookup: {
|
|
185
|
+
from: 'users',
|
|
186
|
+
let: { userId: '$userId' },
|
|
187
|
+
pipeline: [
|
|
155
188
|
{
|
|
156
|
-
$
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
fileCount: { $sum: 1 },
|
|
161
|
-
|
|
189
|
+
$match: {
|
|
190
|
+
$expr: {
|
|
191
|
+
$eq: [ '$_id', '$$userId' ],
|
|
192
|
+
},
|
|
162
193
|
},
|
|
163
194
|
},
|
|
164
195
|
{
|
|
165
196
|
$project: {
|
|
166
197
|
_id: 0,
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
assignedStores: 1,
|
|
170
|
-
completePercentage: {
|
|
171
|
-
$round: [ {
|
|
172
|
-
$multiply: [
|
|
173
|
-
100, {
|
|
174
|
-
$divide: [
|
|
175
|
-
'$completedStores', '$$totalFilesCount',
|
|
176
|
-
],
|
|
177
|
-
},
|
|
178
|
-
],
|
|
179
|
-
}, 1 ],
|
|
180
|
-
|
|
181
|
-
},
|
|
182
|
-
fileCount: 1,
|
|
198
|
+
userName: 1,
|
|
199
|
+
userEmail: '$email',
|
|
183
200
|
},
|
|
184
|
-
|
|
185
201
|
},
|
|
186
|
-
],
|
|
202
|
+
], as: 'users',
|
|
187
203
|
},
|
|
188
204
|
},
|
|
189
205
|
{
|
|
190
|
-
$unwind: {
|
|
206
|
+
$unwind: {
|
|
207
|
+
path: '$users',
|
|
208
|
+
preserveNullAndEmptyArrays: true,
|
|
209
|
+
},
|
|
191
210
|
},
|
|
192
211
|
{
|
|
193
212
|
$project: {
|
|
194
213
|
_id: 0,
|
|
195
|
-
clientId: 1,
|
|
196
|
-
clientName: 1,
|
|
197
214
|
fileDate: 1,
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
215
|
+
storeId: 1,
|
|
216
|
+
storeName: '$stores.storeName',
|
|
217
|
+
userName: '$users.userName',
|
|
218
|
+
userEmail: '$users.userEmail',
|
|
219
|
+
|
|
220
|
+
clientId: 1,
|
|
221
|
+
auditType: 1,
|
|
222
|
+
beforeCount: 1,
|
|
223
|
+
afterCount: { $ifNull: [ '$afterCount', null ] },
|
|
224
|
+
accuracy: { $round: [
|
|
225
|
+
{ $divide: [
|
|
226
|
+
{ $multiply: [ { $ifNull: [ '$afterCount', 0 ] }, '$beforeCount' ] }, 100,
|
|
227
|
+
] }, 2,
|
|
228
|
+
],
|
|
229
|
+
|
|
230
|
+
},
|
|
231
|
+
timeSpent: 1,
|
|
232
|
+
status: 1,
|
|
208
233
|
},
|
|
209
234
|
},
|
|
210
235
|
|
|
211
236
|
];
|
|
212
|
-
query.push( {
|
|
213
|
-
$sort: {
|
|
214
|
-
fileDateISO: -1,
|
|
215
|
-
},
|
|
216
|
-
} );
|
|
217
237
|
|
|
218
238
|
if ( inputData.searchValue && inputData.searchValue !== '' ) {
|
|
219
239
|
query.push( {
|
|
@@ -225,85 +245,42 @@ export async function storeMetrics( req, res ) {
|
|
|
225
245
|
},
|
|
226
246
|
} );
|
|
227
247
|
}
|
|
228
|
-
const
|
|
248
|
+
const count = await aggregateStoreAudit( query );
|
|
229
249
|
|
|
230
|
-
if (
|
|
250
|
+
if ( count.length == 0 ) {
|
|
231
251
|
return res.sendError( 'No data Found', 204 );
|
|
232
252
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
item.notAssigned = 'No Data';
|
|
243
|
-
}
|
|
244
|
-
item.status = ( item.totalFilesCount === item.completedStores && item.assignedStores === 0 && ( item.notAssigned == 0 || item.notAssigned === 'No Data' ) ) ? 'completed' :
|
|
245
|
-
item.fileCount > 0 ? 'pending' : 'not_taken';
|
|
246
|
-
delete item.fileCount;
|
|
247
|
-
testCount = result.filter( ( i ) => inputData.filterByStatus.includes( i.status ) );
|
|
248
|
-
count = testCount.length;
|
|
249
|
-
}
|
|
250
|
-
if ( !inputData.isExport ) {
|
|
251
|
-
const skip = ( inputData.offset - 1 ) * inputData.limit;
|
|
252
|
-
testCount = testCount.slice( skip, skip + inputData.limit );
|
|
253
|
-
}
|
|
254
|
-
if ( inputData.isExport ) {
|
|
255
|
-
const exportdata = [];
|
|
256
|
-
testCount.forEach( ( element ) => {
|
|
257
|
-
exportdata.push( {
|
|
258
|
-
'File Date': element.fileDate,
|
|
259
|
-
'Client Name': element.clientName,
|
|
260
|
-
'Client Id': element.clientId,
|
|
261
|
-
'Completed Percentage': element.completePercentage + ' %',
|
|
262
|
-
'Installed Stores': element.installedStore,
|
|
263
|
-
'Audit Stores': element.totalFilesCount,
|
|
264
|
-
'Inprogress Stores': element.assignedStores,
|
|
265
|
-
'Not Assigned': element.notAssigned && element.notAssigned == 'No Data' ? 0 : element.notAssigned,
|
|
266
|
-
'Completed': element.completedStores,
|
|
267
|
-
'Status': element.status,
|
|
268
|
-
} );
|
|
269
|
-
} );
|
|
270
|
-
await download( exportdata, res );
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
return res.sendSuccess( { result: testCount, count: count } );
|
|
274
|
-
}
|
|
275
|
-
for ( let i = 0; i < result.length; i++ ) {
|
|
276
|
-
const item = result[i];
|
|
277
|
-
if ( inputData.fromDate === inputData.toDate && inputData.fromDate === yesterday ) {
|
|
278
|
-
const temp = await listQueue( item.queueName );
|
|
279
|
-
item.notAssigned = Number( temp );
|
|
280
|
-
} else {
|
|
281
|
-
item.notAssigned = 'No Data';
|
|
282
|
-
}
|
|
283
|
-
item.status = ( item.totalFilesCount === item.completedStores && item.assignedStores === 0 && ( item.notAssigned == 0 || item.notAssigned === 'No Data' ) ) ? 'completed' :
|
|
284
|
-
item.fileCount > 0 ? 'pending' : 'not_taken';
|
|
285
|
-
delete item.fileCount;
|
|
253
|
+
if ( !inputData.isExport ) {
|
|
254
|
+
query.push( {
|
|
255
|
+
$skip: offset,
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
$limit: limit,
|
|
259
|
+
} );
|
|
260
|
+
} else {
|
|
261
|
+
query.push( { $limit: 10000 } );
|
|
286
262
|
}
|
|
263
|
+
const result = await aggregateStoreAudit( query );
|
|
287
264
|
if ( inputData.isExport ) {
|
|
288
265
|
const exportdata = [];
|
|
289
266
|
result.forEach( ( element ) => {
|
|
290
267
|
exportdata.push( {
|
|
291
268
|
'File Date': element.fileDate,
|
|
292
|
-
'
|
|
269
|
+
'Store Id': element.storeId,
|
|
270
|
+
'Store Name': element.storeName,
|
|
293
271
|
'Client Id': element.clientId,
|
|
294
|
-
'
|
|
295
|
-
'
|
|
296
|
-
'Audit
|
|
297
|
-
'
|
|
298
|
-
'
|
|
299
|
-
'Completed': element.completedStores,
|
|
272
|
+
'User Name': element.userName,
|
|
273
|
+
'User Email': element.userEmail,
|
|
274
|
+
'Audit Type': element.auditType,
|
|
275
|
+
'Accuracy': element.accuracy,
|
|
276
|
+
'Time Spent': element.timeSpent,
|
|
300
277
|
'Status': element.status,
|
|
301
278
|
} );
|
|
302
279
|
} );
|
|
303
280
|
await download( exportdata, res );
|
|
304
281
|
return;
|
|
305
282
|
}
|
|
306
|
-
return res.sendSuccess( { result: result, count: count } );
|
|
283
|
+
return res.sendSuccess( { result: result, count: count.length } );
|
|
307
284
|
} catch ( error ) {
|
|
308
285
|
const err = error.message || 'Internal Server Error';
|
|
309
286
|
logger.error( { error: error, data: req.body, function: 'storeMetrics' } );
|
|
@@ -1061,3 +1038,135 @@ export async function overViewTable( req, res ) {
|
|
|
1061
1038
|
return res.sendError( err, 500 );
|
|
1062
1039
|
}
|
|
1063
1040
|
}
|
|
1041
|
+
|
|
1042
|
+
export async function overAllAuditSummary( req, res ) {
|
|
1043
|
+
try {
|
|
1044
|
+
const inputData = req.body;
|
|
1045
|
+
let temp = {
|
|
1046
|
+
|
|
1047
|
+
};
|
|
1048
|
+
const limit = inputData.limit || 10;
|
|
1049
|
+
const offset = inputData.offset ? ( inputData.offset - 1 ) * limit : 0;
|
|
1050
|
+
const dateRange = await getUTC( new Date( inputData.fromDate ), new Date( inputData.toDate ) );
|
|
1051
|
+
let filters =[
|
|
1052
|
+
{ fileDateISO: { $gte: dateRange.start } },
|
|
1053
|
+
{ fileDateISO: { $lte: dateRange.end } },
|
|
1054
|
+
|
|
1055
|
+
];
|
|
1056
|
+
if ( inputData.clientId.length > 0 ) {
|
|
1057
|
+
filters.push( { clientId: { $in: inputData.clientId } } );
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
const query =[
|
|
1061
|
+
{
|
|
1062
|
+
$match: {
|
|
1063
|
+
$and: filters,
|
|
1064
|
+
},
|
|
1065
|
+
|
|
1066
|
+
},
|
|
1067
|
+
{
|
|
1068
|
+
$project: {
|
|
1069
|
+
_id: 0,
|
|
1070
|
+
storeId: 1,
|
|
1071
|
+
fileDate: 1,
|
|
1072
|
+
beforeCount: 1,
|
|
1073
|
+
startTime: 1,
|
|
1074
|
+
auditType: 1,
|
|
1075
|
+
auditStatus: 1,
|
|
1076
|
+
userId: 1,
|
|
1077
|
+
|
|
1078
|
+
|
|
1079
|
+
},
|
|
1080
|
+
},
|
|
1081
|
+
{
|
|
1082
|
+
$lookup: {
|
|
1083
|
+
from: 'users',
|
|
1084
|
+
let: { userId: '$userId' },
|
|
1085
|
+
pipeline: [
|
|
1086
|
+
{
|
|
1087
|
+
$match: {
|
|
1088
|
+
$expr: {
|
|
1089
|
+
$eq: [ '$_id', '$$userId' ],
|
|
1090
|
+
},
|
|
1091
|
+
},
|
|
1092
|
+
},
|
|
1093
|
+
{
|
|
1094
|
+
$project: {
|
|
1095
|
+
userName: 1,
|
|
1096
|
+
userEmail: '$email',
|
|
1097
|
+
},
|
|
1098
|
+
},
|
|
1099
|
+
], as: 'user',
|
|
1100
|
+
},
|
|
1101
|
+
},
|
|
1102
|
+
{
|
|
1103
|
+
$unwind: {
|
|
1104
|
+
path: '$user',
|
|
1105
|
+
preserveNullAndEmptyArrays: true,
|
|
1106
|
+
},
|
|
1107
|
+
},
|
|
1108
|
+
{
|
|
1109
|
+
$project: {
|
|
1110
|
+
storeId: 1,
|
|
1111
|
+
fileDate: 1,
|
|
1112
|
+
beforeCount: 1,
|
|
1113
|
+
startTime: 1,
|
|
1114
|
+
auditType: 1,
|
|
1115
|
+
auditStatus: 1,
|
|
1116
|
+
userName: '$users.userName',
|
|
1117
|
+
userEmail: '$users.userEmail',
|
|
1118
|
+
|
|
1119
|
+
},
|
|
1120
|
+
},
|
|
1121
|
+
];
|
|
1122
|
+
|
|
1123
|
+
if ( inputData.sortColumnName ) {
|
|
1124
|
+
const sortBy = inputData.sortBy || -1;
|
|
1125
|
+
query.push( {
|
|
1126
|
+
$sort: { [inputData.sortColumName]: sortBy },
|
|
1127
|
+
},
|
|
1128
|
+
);
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
const count = await aggregateAuditClientData( query );
|
|
1132
|
+
if ( count.length == 0 ) {
|
|
1133
|
+
return res.sendError( 'No Data Found', 204 );
|
|
1134
|
+
}
|
|
1135
|
+
if ( !inputData.isExport ) {
|
|
1136
|
+
query.push( {
|
|
1137
|
+
$skip: offset,
|
|
1138
|
+
},
|
|
1139
|
+
{
|
|
1140
|
+
$limit: limit,
|
|
1141
|
+
} );
|
|
1142
|
+
} else {
|
|
1143
|
+
query.push( { $limit: 10000 } );
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
const result = await aggregateStoreAudit( query );
|
|
1147
|
+
if ( inputData.isExport ) {
|
|
1148
|
+
const exportdata = [];
|
|
1149
|
+
result.forEach( ( element ) => {
|
|
1150
|
+
exportdata.push( {
|
|
1151
|
+
'File Date': element.storeId,
|
|
1152
|
+
'Store Id': element.fileDtae,
|
|
1153
|
+
'Store Name': element.audittype,
|
|
1154
|
+
'User Name': element.beforeCount,
|
|
1155
|
+
'user Email': element.startTime,
|
|
1156
|
+
'Audit Type': element.userName,
|
|
1157
|
+
'Before Count': element.userEmail,
|
|
1158
|
+
'After Count': element.auditStatus,
|
|
1159
|
+
'Accuracy': element.Accuracy,
|
|
1160
|
+
'Status': element.status,
|
|
1161
|
+
} );
|
|
1162
|
+
} );
|
|
1163
|
+
await download( exportdata, res );
|
|
1164
|
+
return;
|
|
1165
|
+
}
|
|
1166
|
+
return res.sendSuccess( { result: result.length> 0? result[0]: temp } );
|
|
1167
|
+
} catch ( error ) {
|
|
1168
|
+
const err = error.message || 'Internal Server Error';
|
|
1169
|
+
logger.error( { error: error, message: req.body, function: 'summarySplit' } );
|
|
1170
|
+
return res.sendError( err, 500 );
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
@@ -138,3 +138,15 @@ export const overViewTableSchema = joi.object(
|
|
|
138
138
|
export const overViewTableValid = {
|
|
139
139
|
body: overViewTableSchema,
|
|
140
140
|
};
|
|
141
|
+
|
|
142
|
+
export const overAllAuditSummarySchema = joi.object(
|
|
143
|
+
{
|
|
144
|
+
fromDate: joi.string().required(),
|
|
145
|
+
toDate: joi.string().required(),
|
|
146
|
+
clientId: joi.array().optional(),
|
|
147
|
+
},
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
export const overAllAuditSummaryValid = {
|
|
151
|
+
body: overAllAuditSummarySchema,
|
|
152
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
import express from 'express';
|
|
3
3
|
import { isAllowedSessionHandler, validate } from 'tango-app-api-middleware';
|
|
4
|
-
import { clientMetrics, overViewCard, overViewTable, storeMetrics, summarySplit, userAuditHistory, userMetrics } from '../controllers/auditMetrics.controllers.js';
|
|
5
|
-
import { clientMetricsValid, overViewCardValid, overViewTableValid, storeMetricsValid, summarySplitValid, userAuditHistoryValid, userMetricsValid } from '../dtos/auditMetrics.dtos.js';
|
|
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';
|
|
6
6
|
|
|
7
7
|
export const auditMetricsRouter = express.Router();
|
|
8
8
|
|
|
@@ -13,5 +13,6 @@ auditMetricsRouter.post( '/user-metrics', isAllowedSessionHandler, validate( use
|
|
|
13
13
|
auditMetricsRouter.post( '/overview-card', isAllowedSessionHandler, validate( overViewCardValid ), overViewCard );
|
|
14
14
|
auditMetricsRouter.post( '/summary-split-up', isAllowedSessionHandler, validate( summarySplitValid ), summarySplit );
|
|
15
15
|
auditMetricsRouter.post( '/overview-table', isAllowedSessionHandler, validate( overViewTableValid ), overViewTable );
|
|
16
|
+
auditMetricsRouter.post( '/overall-audit-summary', isAllowedSessionHandler, validate( overAllAuditSummaryValid, overAllAuditSummary ) );
|
|
16
17
|
|
|
17
18
|
export default auditMetricsRouter;
|