tango-app-api-audit 1.0.53 → 1.0.54

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.53",
3
+ "version": "1.0.54",
4
4
  "description": "audit & audit metrics apis",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -1884,3 +1884,539 @@ export async function clientMetrics( req, res ) {
1884
1884
  return res.sendError( err, 500 );
1885
1885
  }
1886
1886
  }
1887
+
1888
+ export async function storeMetrics( req, res ) {
1889
+ try {
1890
+ const inputData = req.body;
1891
+ const limit = inputData.limit || 10;
1892
+ const offset = inputData.offset ? ( inputData.offset - 1 ) * limit : 0;
1893
+ const dateRange = await getUTC( new Date( inputData.fromDate ), new Date( inputData.toDate ) );
1894
+ let filter = [
1895
+ { fileDateISO: { $gte: dateRange.start } },
1896
+ { fileDateISO: { $lte: dateRange.end } },
1897
+
1898
+ ];
1899
+ if ( inputData.filterByClientId && inputData.filterByClientId?.length > 0 ) {
1900
+ filter.push( { clientId: { $in: inputData.filterByClientId } } );
1901
+ }
1902
+
1903
+ if ( inputData.filterByStoreId && inputData.filterByStoreId?.length > 0 ) {
1904
+ filter.push( { storeId: { $in: inputData.filterByStoreId } } );
1905
+ }
1906
+
1907
+ if ( inputData.filterByStatus && inputData.filterByStatus?.length > 0 ) {
1908
+ filter.push( { status: { $in: inputData.filterByStatus } } );
1909
+ }
1910
+
1911
+ if ( inputData.filterByAuditType && inputData.filterByAuditType?.length > 0 ) {
1912
+ filter.push( { auditType: { $in: inputData.filterByAuditType } } );
1913
+ }
1914
+
1915
+ if ( inputData.filterByModuleType && inputData.filterByModuleType?.length > 0 ) {
1916
+ filter.push( { moduleType: { $in: inputData.filterByModuleType } } );
1917
+ }
1918
+
1919
+
1920
+ const query = [
1921
+ {
1922
+ $match: {
1923
+ $and: filter,
1924
+ },
1925
+ },
1926
+
1927
+ {
1928
+ $lookup: {
1929
+ from: 'stores',
1930
+ let: { storeId: '$storeId' },
1931
+ pipeline: [
1932
+ {
1933
+ $match: {
1934
+ $expr: {
1935
+ $eq: [ '$storeId', '$$storeId' ],
1936
+ },
1937
+ },
1938
+ },
1939
+ {
1940
+ $project: {
1941
+ _id: 0,
1942
+ storeName: 1,
1943
+ },
1944
+ },
1945
+ ], as: 'stores',
1946
+ },
1947
+ },
1948
+ {
1949
+ $unwind: {
1950
+ path: '$stores',
1951
+ preserveNullAndEmptyArrays: true,
1952
+ },
1953
+ },
1954
+ {
1955
+ $project: {
1956
+ _id: 0,
1957
+ fileDate: 1,
1958
+ storeId: 1,
1959
+ storeName: '$store.storeName',
1960
+ clientName: '',
1961
+ clientId: 1,
1962
+ zoneName: 1,
1963
+ moduleType: 1,
1964
+ userId: {
1965
+ $arrayElemAt: [ '$userId', { $subtract: [ { $size: '$userId' }, 1 ] } ],
1966
+ },
1967
+ auditType: 1,
1968
+ beforeCount: 1,
1969
+ afterCount: { $ifNull: [ '$afterCount', null ] },
1970
+ accuracy: { $round: [
1971
+ { $divide: [
1972
+ { $multiply: [ { $ifNull: [ '$afterCount', 0 ] }, '$beforeCount' ] }, 100,
1973
+ ] }, 2,
1974
+ ],
1975
+
1976
+ },
1977
+ timeSpent: 1,
1978
+ status: 1,
1979
+ },
1980
+ },
1981
+ {
1982
+ $lookup: {
1983
+ from: 'users',
1984
+ let: { userId: '$userId' },
1985
+ pipeline: [
1986
+ {
1987
+ $match: {
1988
+ $expr: {
1989
+ $eq: [ '$_id', '$$userId' ],
1990
+ },
1991
+ },
1992
+ },
1993
+ {
1994
+ $project: {
1995
+ _id: 0,
1996
+ userName: 1,
1997
+ userEmail: '$email',
1998
+ },
1999
+ },
2000
+ ], as: 'users',
2001
+ },
2002
+ },
2003
+ {
2004
+ $unwind: {
2005
+ path: '$users',
2006
+ preserveNullAndEmptyArrays: true,
2007
+ },
2008
+ },
2009
+ {
2010
+ $lookup: {
2011
+ from: 'clients',
2012
+ let: { clientId: '$clientId' },
2013
+ pipeline: [
2014
+ {
2015
+ $match: {
2016
+ $expr: {
2017
+ $eq: [ '$clientId', '$$clientId' ],
2018
+ },
2019
+ },
2020
+ },
2021
+ {
2022
+ $project: {
2023
+ _id: 0,
2024
+ clientName: 1,
2025
+ },
2026
+ },
2027
+ ], as: 'client',
2028
+ },
2029
+ },
2030
+ {
2031
+ $unwind: {
2032
+ path: '$client',
2033
+ preserveNullAndEmptyArrays: true,
2034
+ },
2035
+ },
2036
+ {
2037
+ $project: {
2038
+ _id: 0,
2039
+ fileDate: 1,
2040
+ storeId: 1,
2041
+ storeName: '$stores.storeName',
2042
+ userName: '$users.userName',
2043
+ userEmail: '$users.userEmail',
2044
+ clientId: 1,
2045
+ clientName: '$client.clientName',
2046
+ zoneName: 1,
2047
+ moduleType: 1,
2048
+ auditType: 1,
2049
+ beforeCount: 1,
2050
+ afterCount: { $ifNull: [ '$afterCount', null ] },
2051
+ accuracy: { $round: [
2052
+ { $divide: [
2053
+ { $multiply: [ { $ifNull: [ '$afterCount', 0 ] }, '$beforeCount' ] }, 100,
2054
+ ] }, 1,
2055
+ ],
2056
+
2057
+ },
2058
+ timeSpent: {
2059
+
2060
+ $cond: [
2061
+ { $lt: [ '$timeSpent', 60 ] }, // Case 1: If less than 60 seconds
2062
+ { $concat: [ { $toString: '$timeSpent' }, ' sec' ] },
2063
+ {
2064
+ $cond: [
2065
+ { $lt: [ '$timeSpent', 3600 ] }, // Case 2: If less than 60 minutes (3600 seconds)
2066
+ {
2067
+ $concat: [
2068
+ { $toString: { $round: [ { $divide: [ '$timeSpent', 60 ] }, 1 ] } }, // Convert to minutes
2069
+ ' min',
2070
+ ],
2071
+ },
2072
+ {
2073
+ $concat: [
2074
+ { $toString: { $round: [ { $divide: [ '$timeSpent', 3600 ] }, 1 ] } }, // Convert to hours
2075
+ ' hr',
2076
+ ],
2077
+ },
2078
+ ],
2079
+ },
2080
+ ],
2081
+
2082
+ },
2083
+ status: 1,
2084
+ },
2085
+ },
2086
+
2087
+ ];
2088
+
2089
+ if ( inputData.searchValue && inputData.searchValue !== '' ) {
2090
+ query.push( {
2091
+ $match: {
2092
+ $or: [
2093
+ { clientId: { $regex: inputData.searchValue, $options: 'i' } },
2094
+ { clientName: { $regex: inputData.searchValue, $options: 'i' } },
2095
+ { storeId: { $regex: inputData.searchValue, $options: 'i' } },
2096
+ { storeName: { $regex: inputData.searchValue, $options: 'i' } },
2097
+ { userName: { $regex: inputData.searchValue, $options: 'i' } },
2098
+ { status: { $regex: inputData.searchValue, $options: 'i' } },
2099
+ { auditType: { $regex: inputData.searchValue, $options: 'i' } },
2100
+ { moduleType: { $regex: inputData.searchValue, $options: 'i' } },
2101
+ ],
2102
+ },
2103
+ } );
2104
+ }
2105
+
2106
+ if ( inputData.sortColumnName ) {
2107
+ const sortBy = inputData.sortBy || -1;
2108
+ query.push( {
2109
+ $sort: { [inputData.sortColumName]: sortBy },
2110
+ },
2111
+ );
2112
+ }
2113
+ const count = await aggregateStoreAudit( query );
2114
+
2115
+ if ( count.length == 0 ) {
2116
+ return res.sendError( 'No data Found', 204 );
2117
+ }
2118
+ if ( !inputData.isExport ) {
2119
+ query.push( {
2120
+ $skip: offset,
2121
+ },
2122
+ {
2123
+ $limit: limit,
2124
+ } );
2125
+ } else {
2126
+ query.push( { $limit: 10000 } );
2127
+ }
2128
+ const result = await aggregateStoreAudit( query );
2129
+ if ( inputData.isExport ) {
2130
+ const exportdata = [];
2131
+ result.forEach( ( element ) => {
2132
+ exportdata.push( {
2133
+ 'File Date': element.fileDate,
2134
+ 'Store Id': element.storeId,
2135
+ 'Store Name': element.storeName,
2136
+ 'Client Id': element.clientId,
2137
+ 'Client Name': element.clientName,
2138
+ 'User Name': element.userName,
2139
+ 'User Email': element.userEmail,
2140
+ 'Audit Type': element.auditType,
2141
+ 'Accuracy': element.accuracy,
2142
+ 'Time Spent': element.timeSpent,
2143
+ 'Status': element.status,
2144
+ } );
2145
+ } );
2146
+ await download( exportdata, res );
2147
+ return;
2148
+ }
2149
+ return res.sendSuccess( { result: result, count: count.length } );
2150
+ } catch ( error ) {
2151
+ const err = error.message || 'Internal Server Error';
2152
+ logger.error( { error: error, data: req.body, function: 'storeMetrics' } );
2153
+ return res.sendError( err, 500 );
2154
+ }
2155
+ }
2156
+
2157
+ export async function userMetrics( req, res ) {
2158
+ try {
2159
+ const inputData = req.body;
2160
+ const limit = inputData.limit || 10;
2161
+ const offset = inputData.offset ? ( inputData.offset - 1 ) * limit : 0;
2162
+ const dateRange = await getUTC( new Date( inputData.fromDate ), new Date( inputData.toDate ) );
2163
+ let filter = [];
2164
+ if ( inputData.dateType == 'auditedDate' ) {
2165
+ filter.push(
2166
+ { updatedAt: { $gte: dateRange.start } },
2167
+ { updatedAt: { $lte: dateRange.end } },
2168
+
2169
+ );
2170
+ } else {
2171
+ filter.push(
2172
+ { fileDateISO: { $gte: dateRange.start } },
2173
+ { fileDateISO: { $lte: dateRange.end } },
2174
+
2175
+ );
2176
+ }
2177
+ if ( inputData?.filterByModuleType?.length> 0 ) {
2178
+ filter.push(
2179
+ { moduleType: { $in: inputData.filterByModuleType } },
2180
+ );
2181
+ }
2182
+ if ( inputData?.filterByStatus?.length> 0 ) {
2183
+ filter.push(
2184
+ { auditStatus: { $in: inputData.filterByStatus } },
2185
+ );
2186
+ }
2187
+ if ( inputData?.filterByUser?.length> 0 ) {
2188
+ const temp = inputData.filterByUser.map( ( item ) => new mongoose.Types.ObjectId( item ) );
2189
+ logger.info( { temp: temp } );
2190
+ filter.push(
2191
+ { userId: { $in: temp } },
2192
+ );
2193
+ }
2194
+
2195
+ const query = [
2196
+ {
2197
+ $match: {
2198
+ $and: filter,
2199
+ },
2200
+ },
2201
+ {
2202
+ $project: {
2203
+ userId: 1,
2204
+ fileDate: 1,
2205
+ startTime: 1,
2206
+ endTime: 1,
2207
+ totalCompletedFiles: { $cond: [ { $eq: [ '$auditStatus', 'completed' ] }, 1, 0 ] },
2208
+ beforeCount: 1,
2209
+ afterCount: { $cond: [ { $eq: [ '$auditStatus', 'completed' ] }, '$afterCount', 0 ] },
2210
+ },
2211
+ },
2212
+ {
2213
+ $group: {
2214
+ _id: { userId: '$userId', fileDate: '$fileDate' },
2215
+ userId: { $first: '$userId' },
2216
+ fileDate: { $first: '$fileDate' },
2217
+ totalCompletedFiles: { $sum: '$totalCompletedFiles' },
2218
+ beforeCount: { $sum: '$beforeCount' },
2219
+ afterCount: { $sum: '$afterCount' },
2220
+ checkIntime: { $first: '$startTime' },
2221
+ checkOutTime: { $last: '$endTime' },
2222
+
2223
+ },
2224
+ },
2225
+ {
2226
+ $project: {
2227
+ _id: 0,
2228
+ userId: 1,
2229
+ fileDate: 1,
2230
+ totalCompletedFiles: 1,
2231
+ beforeCount: 1,
2232
+ afterCount: 1,
2233
+ mappingPerc: { $round: [
2234
+ { $multiply: [
2235
+ { $divide: [ '$afterCount', '$beforeCount' ] }, 100,
2236
+ ] }, 2,
2237
+ ] },
2238
+ checkIntime: 1,
2239
+ checkOutTime: 1,
2240
+ differenceInSeconds: {
2241
+ $divide: [ { $subtract: [ '$checkOutTime', '$checkIntime' ] }, 1000 ],
2242
+ },
2243
+ },
2244
+ },
2245
+ {
2246
+ $project: {
2247
+ userId: 1,
2248
+ fileDate: 1,
2249
+ totalCompletedFiles: 1,
2250
+ beforeCount: 1,
2251
+ afterCount: 1,
2252
+ checkIntime: 1,
2253
+ checkOutTime: 1,
2254
+ mappingPerc: 1,
2255
+ hours: { $floor: { $divide: [ '$differenceInSeconds', 3600 ] } },
2256
+ minutes: { $floor: { $divide: [ { $mod: [ '$differenceInSeconds', 3600 ] }, 60 ] } },
2257
+ seconds: { $mod: [ '$differenceInSeconds', 60 ] },
2258
+ },
2259
+ },
2260
+ {
2261
+ $project: {
2262
+ event: 1,
2263
+ userId: 1,
2264
+ fileDate: 1,
2265
+ totalCompletedFiles: 1,
2266
+ beforeCount: 1,
2267
+ afterCount: 1,
2268
+ checkIntime: 1,
2269
+ checkOutTime: 1,
2270
+ hours: {
2271
+ $cond: {
2272
+ if: { $lt: [ '$hours', 10 ] },
2273
+ then: { $concat: [ '0', { $toString: { $round: [ '$hours', 0 ] } } ] },
2274
+ else: { $toString: { $round: [ '$hours', 0 ] } },
2275
+ },
2276
+ },
2277
+ minutes: {
2278
+ $cond: {
2279
+ if: { $lt: [ '$minutes', 10 ] },
2280
+ then: { $concat: [ '0', { $toString: { $round: [ '$minutes', 0 ] } } ] },
2281
+ else: { $toString: { $round: [ '$minutes', 0 ] } },
2282
+ },
2283
+ },
2284
+ seconds: {
2285
+ $cond: {
2286
+ if: { $lt: [ '$seconds', 10 ] },
2287
+ then: { $concat: [ '0', { $toString: { $round: [ '$seconds', 0 ] } } ] },
2288
+ else: { $toString: { $round: [ '$seconds', 0 ] } },
2289
+ },
2290
+ },
2291
+
2292
+ },
2293
+ },
2294
+ {
2295
+ $project: {
2296
+ event: 1,
2297
+ userId: 1,
2298
+ fileDate: 1,
2299
+ totalCompletedFiles: 1,
2300
+ beforeCount: 1,
2301
+ afterCount: 1,
2302
+ checkIntime: 1,
2303
+ zoneName: 1,
2304
+ checkOutTime: 1,
2305
+ workingHours: {
2306
+ $concat: [ '$hours', ':', '$minutes', ':', '$seconds' ],
2307
+ },
2308
+ },
2309
+ },
2310
+ {
2311
+ $lookup: {
2312
+ from: 'users',
2313
+ let: { userId: '$userId' },
2314
+ pipeline: [
2315
+ {
2316
+ $match: {
2317
+ $expr: {
2318
+ $eq: [ '$_id', '$$userId' ],
2319
+ },
2320
+ },
2321
+ },
2322
+ {
2323
+ $project: {
2324
+ _id: 0,
2325
+ userName: 1,
2326
+ },
2327
+ },
2328
+ ], as: 'userInfo',
2329
+ },
2330
+ },
2331
+ {
2332
+ $unwind: {
2333
+ path: '$userInfo', preserveNullAndEmptyArrays: true,
2334
+ },
2335
+ },
2336
+ {
2337
+ $project: {
2338
+ event: 1,
2339
+ userName: '$userInfo.userName',
2340
+ userId: 1,
2341
+ fileDate: 1,
2342
+ totalCompletedFiles: 1,
2343
+ beforeCount: 1,
2344
+ afterCount: 1,
2345
+ checkIntime: {
2346
+ $dateToString: {
2347
+ format: '%Y-%m-%d %H:%M:%S',
2348
+ date: '$checkIntime',
2349
+ timezone: 'Asia/Kolkata',
2350
+ },
2351
+ },
2352
+ checkOutTime: {
2353
+ $dateToString: {
2354
+ format: '%Y-%m-%d %H:%M:%S',
2355
+ date: '$checkOutTime',
2356
+ timezone: 'Asia/Kolkata',
2357
+ },
2358
+ },
2359
+ workingHours: 1,
2360
+ },
2361
+ },
2362
+ ];
2363
+ if ( inputData.searchValue && inputData.searchValue!== '' ) {
2364
+ query.push( {
2365
+ $match: {
2366
+ $or: [
2367
+ { userName: { $regex: inputData.searchValue, $options: 'i' } },
2368
+ { clientName: { $regex: inputData.searchValue, $options: 'i' } },
2369
+ ],
2370
+
2371
+ },
2372
+ } );
2373
+ }
2374
+ if ( inputData.sortColumnName ) {
2375
+ const sortBy = inputData.sortBy || -1;
2376
+ query.push( {
2377
+ $sort: { [inputData.sortColumName]: sortBy },
2378
+ },
2379
+ );
2380
+ }
2381
+
2382
+ const count = await aggregateUserAudit( query );
2383
+ if ( count.length == 0 ) {
2384
+ return res.sendError( 'No Data Found', 204 );
2385
+ }
2386
+
2387
+ query.push(
2388
+ { $skip: offset },
2389
+ { $limit: limit },
2390
+ );
2391
+ if ( inputData.isExport ) {
2392
+ query.push(
2393
+ {
2394
+ $project: {
2395
+ '_id': 0,
2396
+ 'File Date': '$fileDate',
2397
+ 'User Name': '$userName',
2398
+ 'User Id': '$userId',
2399
+ 'Total Completed Files Count': '$totalCompletedFiles',
2400
+ 'Total efore Count': '$beforeCount',
2401
+ 'Total After Count': '$afterCount',
2402
+ 'check Intime': '$checkIntime',
2403
+ 'check OutTime': '$checkOutTime',
2404
+ 'working Hours': '$workingHours',
2405
+ },
2406
+ },
2407
+ );
2408
+ }
2409
+
2410
+
2411
+ const result = await aggregateUserAudit( query );
2412
+ if ( inputData.isExport ) {
2413
+ await download( result, res );
2414
+ return;
2415
+ }
2416
+ return res.sendSuccess( { result: result, count: count.length } );
2417
+ } catch ( error ) {
2418
+ const err = error.error || 'Internal Server Error';
2419
+ logger.info( { error: error, message: req.body, function: 'clientMetrics' } );
2420
+ return res.sendError( err, 500 );
2421
+ }
2422
+ }
@@ -12,533 +12,6 @@ import { getReauditImg } from './audit.controllers.js';
12
12
  // import { listQueue } from 'tango-app-api-middleware/src/utils/aws/sqs.js';
13
13
 
14
14
 
15
- export async function storeMetrics( req, res ) {
16
- try {
17
- const inputData = req.body;
18
- const limit = inputData.limit || 10;
19
- const offset = inputData.offset ? ( inputData.offset - 1 ) * limit : 0;
20
- const dateRange = await getUTC( new Date( inputData.fromDate ), new Date( inputData.toDate ) );
21
- let filter = [
22
- { fileDateISO: { $gte: dateRange.start } },
23
- { fileDateISO: { $lte: dateRange.end } },
24
- ];
25
- if ( inputData.filterByClientId && inputData.filterByClientId?.length > 0 ) {
26
- filter.push( { clientId: { $in: inputData.filterByClientId } } );
27
- }
28
-
29
- if ( inputData.filterByStoreId && inputData.filterByStoreId?.length > 0 ) {
30
- filter.push( { storeId: { $in: inputData.filterByStoreId } } );
31
- }
32
-
33
- if ( inputData.filterByStatus && inputData.filterByStatus?.length > 0 ) {
34
- filter.push( { status: { $in: inputData.filterByStatus } } );
35
- }
36
-
37
- if ( inputData.filterByType && inputData.filterByType?.length > 0 ) {
38
- filter.push( { auditType: { $in: inputData.filterByType } } );
39
- }
40
-
41
-
42
- const query = [
43
- {
44
- $match: {
45
- $and: filter,
46
- },
47
- },
48
-
49
- {
50
- $lookup: {
51
- from: 'stores',
52
- let: { storeId: '$storeId' },
53
- pipeline: [
54
- {
55
- $match: {
56
- $expr: {
57
- $eq: [ '$storeId', '$$storeId' ],
58
- },
59
- },
60
- },
61
- {
62
- $project: {
63
- _id: 0,
64
- storeName: 1,
65
- },
66
- },
67
- ], as: 'stores',
68
- },
69
- },
70
- {
71
- $unwind: {
72
- path: '$stores',
73
- preserveNullAndEmptyArrays: true,
74
- },
75
- },
76
- {
77
- $project: {
78
- _id: 0,
79
- fileDate: 1,
80
- storeId: 1,
81
- storeName: '$store.storeName',
82
- clientName: '',
83
- clientId: 1,
84
- userId: {
85
- $arrayElemAt: [ '$userId', { $subtract: [ { $size: '$userId' }, 1 ] } ],
86
- },
87
- auditType: 1,
88
- beforeCount: 1,
89
- afterCount: { $ifNull: [ '$afterCount', null ] },
90
- accuracy: { $round: [
91
- { $divide: [
92
- { $multiply: [ { $ifNull: [ '$afterCount', 0 ] }, '$beforeCount' ] }, 100,
93
- ] }, 2,
94
- ],
95
-
96
- },
97
- timeSpent: 1,
98
- status: 1,
99
- },
100
- },
101
- {
102
- $lookup: {
103
- from: 'users',
104
- let: { userId: '$userId' },
105
- pipeline: [
106
- {
107
- $match: {
108
- $expr: {
109
- $eq: [ '$_id', '$$userId' ],
110
- },
111
- },
112
- },
113
- {
114
- $project: {
115
- _id: 0,
116
- userName: 1,
117
- userEmail: '$email',
118
- },
119
- },
120
- ], as: 'users',
121
- },
122
- },
123
- {
124
- $unwind: {
125
- path: '$users',
126
- preserveNullAndEmptyArrays: true,
127
- },
128
- },
129
- {
130
- $lookup: {
131
- from: 'clients',
132
- let: { clientId: '$clientId' },
133
- pipeline: [
134
- {
135
- $match: {
136
- $expr: {
137
- $eq: [ '$clientId', '$$clientId' ],
138
- },
139
- },
140
- },
141
- {
142
- $project: {
143
- _id: 0,
144
- clientName: 1,
145
- },
146
- },
147
- ], as: 'client',
148
- },
149
- },
150
- {
151
- $unwind: {
152
- path: '$client',
153
- preserveNullAndEmptyArrays: true,
154
- },
155
- },
156
- {
157
- $project: {
158
- _id: 0,
159
- fileDate: 1,
160
- storeId: 1,
161
- storeName: '$stores.storeName',
162
- userName: '$users.userName',
163
- userEmail: '$users.userEmail',
164
- clientId: 1,
165
- clientName: '$client.clientName',
166
- auditType: 1,
167
- beforeCount: 1,
168
- afterCount: { $ifNull: [ '$afterCount', null ] },
169
- accuracy: { $round: [
170
- { $divide: [
171
- { $multiply: [ { $ifNull: [ '$afterCount', 0 ] }, '$beforeCount' ] }, 100,
172
- ] }, 1,
173
- ],
174
-
175
- },
176
- timeSpent: {
177
-
178
- $cond: [
179
- { $lt: [ '$timeSpent', 60 ] }, // Case 1: If less than 60 seconds
180
- { $concat: [ { $toString: '$timeSpent' }, ' sec' ] },
181
- {
182
- $cond: [
183
- { $lt: [ '$timeSpent', 3600 ] }, // Case 2: If less than 60 minutes (3600 seconds)
184
- {
185
- $concat: [
186
- { $toString: { $round: [ { $divide: [ '$timeSpent', 60 ] }, 1 ] } }, // Convert to minutes
187
- ' min',
188
- ],
189
- },
190
- {
191
- $concat: [
192
- { $toString: { $round: [ { $divide: [ '$timeSpent', 3600 ] }, 1 ] } }, // Convert to hours
193
- ' hr',
194
- ],
195
- },
196
- ],
197
- },
198
- ],
199
-
200
- },
201
- status: 1,
202
- },
203
- },
204
-
205
- ];
206
-
207
- if ( inputData.searchValue && inputData.searchValue !== '' ) {
208
- query.push( {
209
- $match: {
210
- $or: [
211
- { clientId: { $regex: inputData.searchValue, $options: 'i' } },
212
- { clientName: { $regex: inputData.searchValue, $options: 'i' } },
213
- { storeId: { $regex: inputData.searchValue, $options: 'i' } },
214
- { storeName: { $regex: inputData.searchValue, $options: 'i' } },
215
- { userName: { $regex: inputData.searchValue, $options: 'i' } },
216
- { status: { $regex: inputData.searchValue, $options: 'i' } },
217
- { auditType: { $regex: inputData.searchValue, $options: 'i' } },
218
- ],
219
- },
220
- } );
221
- }
222
-
223
- if ( inputData.sortColumnName ) {
224
- const sortBy = inputData.sortBy || -1;
225
- query.push( {
226
- $sort: { [inputData.sortColumName]: sortBy },
227
- },
228
- );
229
- }
230
- const count = await aggregateStoreAudit( query );
231
-
232
- if ( count.length == 0 ) {
233
- return res.sendError( 'No data Found', 204 );
234
- }
235
- if ( !inputData.isExport ) {
236
- query.push( {
237
- $skip: offset,
238
- },
239
- {
240
- $limit: limit,
241
- } );
242
- } else {
243
- query.push( { $limit: 10000 } );
244
- }
245
- const result = await aggregateStoreAudit( query );
246
- if ( inputData.isExport ) {
247
- const exportdata = [];
248
- result.forEach( ( element ) => {
249
- exportdata.push( {
250
- 'File Date': element.fileDate,
251
- 'Store Id': element.storeId,
252
- 'Store Name': element.storeName,
253
- 'Client Id': element.clientId,
254
- 'Client Name': element.clientName,
255
- 'User Name': element.userName,
256
- 'User Email': element.userEmail,
257
- 'Audit Type': element.auditType,
258
- 'Accuracy': element.accuracy,
259
- 'Time Spent': element.timeSpent,
260
- 'Status': element.status,
261
- } );
262
- } );
263
- await download( exportdata, res );
264
- return;
265
- }
266
- return res.sendSuccess( { result: result, count: count.length } );
267
- } catch ( error ) {
268
- const err = error.message || 'Internal Server Error';
269
- logger.error( { error: error, data: req.body, function: 'storeMetrics' } );
270
- return res.sendError( err, 500 );
271
- }
272
- }
273
-
274
-
275
- export async function userMetrics( req, res ) {
276
- try {
277
- const inputData = req.body;
278
- const limit = inputData.limit || 10;
279
- const offset = inputData.offset ? ( inputData.offset - 1 ) * limit : 0;
280
- const dateRange = await getUTC( new Date( inputData.fromDate ), new Date( inputData.toDate ) );
281
- let filter = [];
282
- if ( inputData.fileType == 'auditedDate' ) {
283
- filter.push(
284
- { updatedAt: { $gte: dateRange.start } },
285
- { updatedAt: { $lte: dateRange.end } },
286
-
287
- );
288
- } else {
289
- filter.push(
290
- { fileDateISO: { $gte: dateRange.start } },
291
- { fileDateISO: { $lte: dateRange.end } },
292
-
293
- );
294
- }
295
- if ( inputData?.filterByAuditType?.length> 0 ) {
296
- filter.push(
297
- { moduleType: { $in: inputData.filterByAuditType } },
298
- );
299
- }
300
- if ( inputData?.filterByStatus?.length> 0 ) {
301
- filter.push(
302
- { auditStatus: { $in: inputData.filterByStatus } },
303
- );
304
- }
305
- if ( inputData?.filterByUser?.length> 0 ) {
306
- const temp = inputData.filterByUser.map( ( item ) => new mongoose.Types.ObjectId( item ) );
307
- logger.info( { temp: temp } );
308
- filter.push(
309
- { userId: { $in: temp } },
310
- );
311
- }
312
-
313
- const query = [
314
- {
315
- $match: {
316
- $and: filter,
317
- },
318
- },
319
- {
320
- $project: {
321
- userId: 1,
322
- fileDate: 1,
323
- startTime: 1,
324
- endTime: 1,
325
- totalCompletedFiles: { $cond: [ { $eq: [ '$auditStatus', 'completed' ] }, 1, 0 ] },
326
- beforeCount: 1,
327
- afterCount: { $cond: [ { $eq: [ '$auditStatus', 'completed' ] }, '$afterCount', 0 ] },
328
- },
329
- },
330
- {
331
- $group: {
332
- _id: { userId: '$userId', fileDate: '$fileDate' },
333
- userId: { $first: '$userId' },
334
- fileDate: { $first: '$fileDate' },
335
- totalCompletedFiles: { $sum: '$totalCompletedFiles' },
336
- beforeCount: { $sum: '$beforeCount' },
337
- afterCount: { $sum: '$afterCount' },
338
- checkIntime: { $first: '$startTime' },
339
- checkOutTime: { $last: '$endTime' },
340
-
341
- },
342
- },
343
- {
344
- $project: {
345
- _id: 0,
346
- userId: 1,
347
- fileDate: 1,
348
- totalCompletedFiles: 1,
349
- beforeCount: 1,
350
- afterCount: 1,
351
- mappingPerc: { $round: [
352
- { $multiply: [
353
- { $divide: [ '$afterCount', '$beforeCount' ] }, 100,
354
- ] }, 2,
355
- ] },
356
- checkIntime: 1,
357
- checkOutTime: 1,
358
- differenceInSeconds: {
359
- $divide: [ { $subtract: [ '$checkOutTime', '$checkIntime' ] }, 1000 ],
360
- },
361
- },
362
- },
363
- {
364
- $project: {
365
- userId: 1,
366
- fileDate: 1,
367
- totalCompletedFiles: 1,
368
- beforeCount: 1,
369
- afterCount: 1,
370
- checkIntime: 1,
371
- checkOutTime: 1,
372
- mappingPerc: 1,
373
- hours: { $floor: { $divide: [ '$differenceInSeconds', 3600 ] } },
374
- minutes: { $floor: { $divide: [ { $mod: [ '$differenceInSeconds', 3600 ] }, 60 ] } },
375
- seconds: { $mod: [ '$differenceInSeconds', 60 ] },
376
- },
377
- },
378
- {
379
- $project: {
380
- event: 1,
381
- userId: 1,
382
- fileDate: 1,
383
- totalCompletedFiles: 1,
384
- beforeCount: 1,
385
- afterCount: 1,
386
- checkIntime: 1,
387
- checkOutTime: 1,
388
- hours: {
389
- $cond: {
390
- if: { $lt: [ '$hours', 10 ] },
391
- then: { $concat: [ '0', { $toString: { $round: [ '$hours', 0 ] } } ] },
392
- else: { $toString: { $round: [ '$hours', 0 ] } },
393
- },
394
- },
395
- minutes: {
396
- $cond: {
397
- if: { $lt: [ '$minutes', 10 ] },
398
- then: { $concat: [ '0', { $toString: { $round: [ '$minutes', 0 ] } } ] },
399
- else: { $toString: { $round: [ '$minutes', 0 ] } },
400
- },
401
- },
402
- seconds: {
403
- $cond: {
404
- if: { $lt: [ '$seconds', 10 ] },
405
- then: { $concat: [ '0', { $toString: { $round: [ '$seconds', 0 ] } } ] },
406
- else: { $toString: { $round: [ '$seconds', 0 ] } },
407
- },
408
- },
409
-
410
- },
411
- },
412
- {
413
- $project: {
414
- event: 1,
415
- userId: 1,
416
- fileDate: 1,
417
- totalCompletedFiles: 1,
418
- beforeCount: 1,
419
- afterCount: 1,
420
- checkIntime: 1,
421
- zoneName: 1,
422
- checkOutTime: 1,
423
- workingHours: {
424
- $concat: [ '$hours', ':', '$minutes', ':', '$seconds' ],
425
- },
426
- },
427
- },
428
- {
429
- $lookup: {
430
- from: 'users',
431
- let: { userId: '$userId' },
432
- pipeline: [
433
- {
434
- $match: {
435
- $expr: {
436
- $eq: [ '$_id', '$$userId' ],
437
- },
438
- },
439
- },
440
- {
441
- $project: {
442
- _id: 0,
443
- userName: 1,
444
- },
445
- },
446
- ], as: 'userInfo',
447
- },
448
- },
449
- {
450
- $unwind: {
451
- path: '$userInfo', preserveNullAndEmptyArrays: true,
452
- },
453
- },
454
- {
455
- $project: {
456
- event: 1,
457
- userName: '$userInfo.userName',
458
- userId: 1,
459
- fileDate: 1,
460
- totalCompletedFiles: 1,
461
- beforeCount: 1,
462
- afterCount: 1,
463
- checkIntime: {
464
- $dateToString: {
465
- format: '%Y-%m-%d %H:%M:%S',
466
- date: '$checkIntime',
467
- timezone: 'Asia/Kolkata',
468
- },
469
- },
470
- checkOutTime: {
471
- $dateToString: {
472
- format: '%Y-%m-%d %H:%M:%S',
473
- date: '$checkOutTime',
474
- timezone: 'Asia/Kolkata',
475
- },
476
- },
477
- workingHours: 1,
478
- },
479
- },
480
- ];
481
- if ( inputData.searchValue && inputData.searchValue!== '' ) {
482
- query.push( {
483
- $match: {
484
- $or: [
485
- { userName: { $regex: inputData.searchValue, $options: 'i' } },
486
- { clientName: { $regex: inputData.searchValue, $options: 'i' } },
487
- ],
488
-
489
- },
490
- } );
491
- }
492
- if ( inputData.sortColumnName ) {
493
- const sortBy = inputData.sortBy || -1;
494
- query.push( {
495
- $sort: { [inputData.sortColumName]: sortBy },
496
- },
497
- );
498
- }
499
-
500
- const count = await aggregateUserAudit( query );
501
- if ( count.length == 0 ) {
502
- return res.sendError( 'No Data Found', 204 );
503
- }
504
-
505
- query.push(
506
- { $skip: offset },
507
- { $limit: limit },
508
- );
509
- if ( inputData.isExport ) {
510
- query.push(
511
- {
512
- $project: {
513
- '_id': 0,
514
- 'File Date': '$fileDate',
515
- 'User Name': '$userName',
516
- 'User Id': '$userId',
517
- 'Total Completed Files Count': '$totalCompletedFiles',
518
- 'Total efore Count': '$beforeCount',
519
- 'Total After Count': '$afterCount',
520
- 'check Intime': '$checkIntime',
521
- 'check OutTime': '$checkOutTime',
522
- 'working Hours': '$workingHours',
523
- },
524
- },
525
- );
526
- }
527
-
528
-
529
- const result = await aggregateUserAudit( query );
530
- if ( inputData.isExport ) {
531
- await download( result, res );
532
- return;
533
- }
534
- return res.sendSuccess( { result: result, count: count.length } );
535
- } catch ( error ) {
536
- const err = error.error || 'Internal Server Error';
537
- logger.info( { error: error, message: req.body, function: 'clientMetrics' } );
538
- return res.sendError( err, 500 );
539
- }
540
- }
541
-
542
15
  export async function overViewCard( req, res ) {
543
16
  try {
544
17
  const inputData = req.body;
@@ -1,4 +1,4 @@
1
- import { auditStoreSchema, clientMetricsSchema, clientSchema, getDraftedDataSchema, getFileSchema, saveDraftSchema, saveSchema, userAuditHistorySchema, userSchema, workSpaceSchema } from '../dtos/audit.dtos.js';
1
+ import { auditStoreSchema, clientMetricsSchema, clientSchema, getDraftedDataSchema, getFileSchema, saveDraftSchema, saveSchema, storeMetricsSchema, userAuditHistorySchema, userMetricsSchema, userSchema, workSpaceSchema } from '../dtos/audit.dtos.js';
2
2
  import j2s from 'joi-to-swagger';
3
3
 
4
4
  export const auditDocs = {
@@ -308,5 +308,50 @@ export const auditDocs = {
308
308
  },
309
309
  },
310
310
  },
311
+ '/v3/audit/metrics/store-metrics': {
312
+ post: {
313
+ tags: [ 'Audit Metrics' ],
314
+ description: `Get list of store wise details with date range and client Id`,
315
+ operationId: 'store-metrics',
316
+ parameters: {},
317
+ requestBody: {
318
+ content: {
319
+ 'application/json': {
320
+ schema: j2s( storeMetricsSchema ).swagger,
321
+ },
322
+ },
323
+ },
324
+ responses: {
325
+ 200: { description: 'Successful' },
326
+ 401: { description: 'Unauthorized User' },
327
+ 422: { description: 'Field Error' },
328
+ 500: { description: 'Server Error' },
329
+ 204: { description: 'Not Found' },
330
+ },
331
+ },
332
+ },
333
+
334
+ '/v3/audit/metrics/user-metrics': {
335
+ post: {
336
+ tags: [ 'Audit Metrics' ],
337
+ description: `Get list of file wise details with date range and users`,
338
+ operationId: 'user-metrics',
339
+ parameters: {},
340
+ requestBody: {
341
+ content: {
342
+ 'application/json': {
343
+ schema: j2s( userMetricsSchema ).swagger,
344
+ },
345
+ },
346
+ },
347
+ responses: {
348
+ 200: { description: 'Successful' },
349
+ 401: { description: 'Unauthorized User' },
350
+ 422: { description: 'Field Error' },
351
+ 500: { description: 'Server Error' },
352
+ 204: { description: 'Not Found' },
353
+ },
354
+ },
355
+ },
311
356
 
312
357
  };
@@ -1,5 +1,5 @@
1
1
  import j2s from 'joi-to-swagger';
2
- import { auditImageValidSchema, getAuditImagesSchema, overAllAuditSummarySchema, overViewCardSchema, overViewTableSchema, reTriggerValidSchema, storeMetricsSchema, summarySplitSchema, userMetricsSchema } from '../dtos/auditMetrics.dtos.js';
2
+ import { auditImageValidSchema, getAuditImagesSchema, overAllAuditSummarySchema, overViewCardSchema, overViewTableSchema, reTriggerValidSchema, summarySplitSchema } from '../dtos/auditMetrics.dtos.js';
3
3
 
4
4
  export const auditMetricsDocs = {
5
5
 
@@ -27,50 +27,6 @@ export const auditMetricsDocs = {
27
27
  },
28
28
 
29
29
 
30
- '/v3/audit-metrics/store-metrics': {
31
- post: {
32
- tags: [ 'Audit Metrics' ],
33
- description: `Get list of store wise details with date range and client Id`,
34
- operationId: 'store-metrics',
35
- parameters: {},
36
- requestBody: {
37
- content: {
38
- 'application/json': {
39
- schema: j2s( storeMetricsSchema ).swagger,
40
- },
41
- },
42
- },
43
- responses: {
44
- 200: { description: 'Successful' },
45
- 401: { description: 'Unauthorized User' },
46
- 422: { description: 'Field Error' },
47
- 500: { description: 'Server Error' },
48
- 204: { description: 'Not Found' },
49
- },
50
- },
51
- },
52
- '/v3/audit-metrics/user-metrics': {
53
- post: {
54
- tags: [ 'Audit Metrics' ],
55
- description: `Get list of file wise details with date range and users`,
56
- operationId: 'user-metrics',
57
- parameters: {},
58
- requestBody: {
59
- content: {
60
- 'application/json': {
61
- schema: j2s( userMetricsSchema ).swagger,
62
- },
63
- },
64
- },
65
- responses: {
66
- 200: { description: 'Successful' },
67
- 401: { description: 'Unauthorized User' },
68
- 422: { description: 'Field Error' },
69
- 500: { description: 'Server Error' },
70
- 204: { description: 'Not Found' },
71
- },
72
- },
73
- },
74
30
  '/v3/audit-metrics/overview-card': {
75
31
  post: {
76
32
  tags: [ 'Audit Metrics' ],
@@ -182,3 +182,47 @@ export const clientMetricsSchema = joi.object(
182
182
  export const clientMetricsValid = {
183
183
  body: clientMetricsSchema,
184
184
  };
185
+
186
+
187
+ export const storeMetricsSchema = joi.object(
188
+ {
189
+ fromDate: joi.string().required(),
190
+ toDate: joi.string().required(),
191
+ searchValue: joi.string().optional().allow( '' ),
192
+ filterByClientId: joi.array().required(),
193
+ filterByStoreId: joi.array().optional(),
194
+ filterByStatus: joi.array().optional(),
195
+ filterByAuditType: joi.array().optional(),
196
+ filterByModuleType: joi.array().optional(),
197
+ sortColumnName: joi.string().optional(),
198
+ sortBy: joi.number().optional(),
199
+ limit: joi.number().optional(),
200
+ offset: joi.number().optional(),
201
+ isExport: joi.boolean().optional(),
202
+ },
203
+ );
204
+
205
+ export const storeMetricsValid = {
206
+ body: storeMetricsSchema,
207
+ };
208
+
209
+ export const userMetricsSchema = joi.object(
210
+ {
211
+ fromDate: joi.string().required(),
212
+ toDate: joi.string().required(),
213
+ dateType: joi.string().required(),
214
+ searchValue: joi.string().optional().allow( '' ),
215
+ filterByUser: joi.array().optional(),
216
+ filterByModuleType: joi.array().optional(),
217
+ filterByStatus: joi.array().optional(),
218
+ sortColumnName: joi.string().optional(),
219
+ sortBy: joi.number().optional(),
220
+ limit: joi.number().optional(),
221
+ offset: joi.number().optional(),
222
+ isExport: joi.boolean().optional(),
223
+ },
224
+ );
225
+
226
+ export const userMetricsValid = {
227
+ body: userMetricsSchema,
228
+ };
@@ -14,49 +14,6 @@ export const getAuditImagesValid = {
14
14
  };
15
15
 
16
16
 
17
- export const storeMetricsSchema = joi.object(
18
- {
19
- fromDate: joi.string().required(),
20
- toDate: joi.string().required(),
21
- searchValue: joi.string().optional().allow( '' ),
22
- filterByClientId: joi.array().required(),
23
- filterByStoreId: joi.array().optional(),
24
- filterByStatus: joi.array().optional(),
25
- filterByType: joi.array().optional(),
26
- sortColumnName: joi.string().optional(),
27
- sortBy: joi.number().optional(),
28
- limit: joi.number().optional(),
29
- offset: joi.number().optional(),
30
- isExport: joi.boolean().optional(),
31
- },
32
- );
33
-
34
- export const storeMetricsValid = {
35
- body: storeMetricsSchema,
36
- };
37
-
38
-
39
- export const userMetricsSchema = joi.object(
40
- {
41
- fromDate: joi.string().required(),
42
- toDate: joi.string().required(),
43
- fileType: joi.string().required(),
44
- searchValue: joi.string().optional().allow( '' ),
45
- filterByUser: joi.array().optional(),
46
- filterByAuditType: joi.array().optional(),
47
- filterByStatus: joi.array().optional(),
48
- sortColumnName: joi.string().optional(),
49
- sortBy: joi.number().optional(),
50
- limit: joi.number().optional(),
51
- offset: joi.number().optional(),
52
- isExport: joi.boolean().optional(),
53
- },
54
- );
55
-
56
- export const userMetricsValid = {
57
- body: userMetricsSchema,
58
- };
59
-
60
17
  export const overViewCardSchema = joi.object(
61
18
  {
62
19
  fromDate: joi.string().required(),
@@ -1,8 +1,8 @@
1
1
  import express from 'express';
2
2
  import { isExistsQueue, validateUserAudit } from '../validation/audit.validation.js';
3
3
  import { isAllowedSessionHandler, validate } from 'tango-app-api-middleware';
4
- import { auditStoreList, auditUserList, clientMetrics, clients, getAuditFile, getDraftedData, save, saveDraft, userAuditHistory, workSpace } from '../controllers/audit.controllers.js';
5
- import { auditStoreValid, clientMetricsValid, clientValid, getDraftedDataValid, getFileValid, saveDraftValid, saveValid, userAuditHistoryValid, workSpaceValid } from '../dtos/audit.dtos.js';
4
+ import { auditStoreList, auditUserList, clientMetrics, clients, getAuditFile, getDraftedData, save, saveDraft, storeMetrics, userAuditHistory, userMetrics, workSpace } from '../controllers/audit.controllers.js';
5
+ import { auditStoreValid, clientMetricsValid, clientValid, getDraftedDataValid, getFileValid, saveDraftValid, saveValid, storeMetricsValid, userAuditHistoryValid, userMetricsValid, workSpaceValid } from '../dtos/audit.dtos.js';
6
6
 
7
7
  export const auditRouter = express.Router();
8
8
 
@@ -22,6 +22,8 @@ auditRouter.get( '/work-space', isAllowedSessionHandler, validate( workSpaceVali
22
22
  // Audit Metrics
23
23
  auditRouter.post( '/metrics/user-audit-history', isAllowedSessionHandler, validate( userAuditHistoryValid ), userAuditHistory );
24
24
  auditRouter.post( '/metrics/client-metrics', isAllowedSessionHandler, validate( clientMetricsValid ), clientMetrics );
25
+ auditRouter.post( '/metrics/store-metrics', isAllowedSessionHandler, validate( storeMetricsValid ), storeMetrics );
26
+ auditRouter.post( '/metrics/user-metrics', isAllowedSessionHandler, validate( userMetricsValid ), userMetrics );
25
27
 
26
28
 
27
29
  export default auditRouter;
@@ -1,16 +1,13 @@
1
1
 
2
2
  import express from 'express';
3
3
  import { isAllowedSessionHandler, validate } from 'tango-app-api-middleware';
4
- import { auditImages, overAllAuditSummary, overViewCard, overViewTable, reTrigger, storeMetrics, summarySplit, userMetrics } from '../controllers/auditMetrics.controllers.js';
5
- import { auditImageValid, overAllAuditSummaryValid, overViewCardValid, overViewTableValid, reTriggerValid, storeMetricsValid, summarySplitValid, userMetricsValid, viewLogValid } from '../dtos/auditMetrics.dtos.js';
4
+ import { auditImages, overAllAuditSummary, overViewCard, overViewTable, reTrigger, summarySplit } from '../controllers/auditMetrics.controllers.js';
5
+ import { auditImageValid, overAllAuditSummaryValid, overViewCardValid, overViewTableValid, reTriggerValid, summarySplitValid, 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();
9
9
 
10
10
 
11
- auditMetricsRouter.post( '/store-metrics', isAllowedSessionHandler, validate( storeMetricsValid ), storeMetrics );
12
-
13
- auditMetricsRouter.post( '/user-metrics', isAllowedSessionHandler, validate( userMetricsValid ), userMetrics );
14
11
  auditMetricsRouter.post( '/overview-card', isAllowedSessionHandler, validate( overViewCardValid ), overViewCard );
15
12
  auditMetricsRouter.post( '/summary-split-up', isAllowedSessionHandler, validate( summarySplitValid ), summarySplit );
16
13
  auditMetricsRouter.post( '/overview-table', isAllowedSessionHandler, validate( overViewTableValid ), overViewTable );