tango-app-api-infra 3.8.1-beta.2 → 3.8.1-beta.21
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/footfallDirectory.controllers.js +1033 -224
- package/src/docs/footfallDirectory.docs.js +166 -12
- package/src/dtos/footfallDirectory.dtos.js +137 -45
- package/src/routes/footfallDirectory.routes.js +7 -7
- package/src/services/camera.service.js +3 -0
- package/src/services/revopDownload.service.js +9 -0
- package/src/validations/footfallDirectory.validation.js +91 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import j2s from 'joi-to-swagger';
|
|
2
|
-
import { createTicketSchema, getTicketsSchema, ticketListSchema, ticketSummarySchema,
|
|
2
|
+
import { createTicketSchema, getTaggedStoresSchema, getTicketsSchema, ticketListSchema, ticketSummarySchema, updateStatusSchemea } from '../dtos/footfallDirectory.dtos.js';
|
|
3
3
|
|
|
4
4
|
export const footfallDirectoryDocs = {
|
|
5
5
|
|
|
@@ -59,7 +59,6 @@ export const footfallDirectoryDocs = {
|
|
|
59
59
|
},
|
|
60
60
|
},
|
|
61
61
|
},
|
|
62
|
-
|
|
63
62
|
'/v3/footfall-directory-tagging/ticket-list': {
|
|
64
63
|
get: {
|
|
65
64
|
tags: [ 'Footfall Directory Ticket' ],
|
|
@@ -72,6 +71,12 @@ export const footfallDirectoryDocs = {
|
|
|
72
71
|
scema: j2s( ticketListSchema ).swagger,
|
|
73
72
|
required: true,
|
|
74
73
|
},
|
|
74
|
+
{
|
|
75
|
+
in: 'query',
|
|
76
|
+
name: 'storeId',
|
|
77
|
+
scema: j2s( ticketListSchema ).swagger,
|
|
78
|
+
required: false,
|
|
79
|
+
},
|
|
75
80
|
{
|
|
76
81
|
in: 'query',
|
|
77
82
|
name: 'fromDate',
|
|
@@ -86,7 +91,7 @@ export const footfallDirectoryDocs = {
|
|
|
86
91
|
},
|
|
87
92
|
{
|
|
88
93
|
in: 'query',
|
|
89
|
-
name: '
|
|
94
|
+
name: 'searchValue',
|
|
90
95
|
scema: j2s( ticketListSchema ).swagger,
|
|
91
96
|
required: false,
|
|
92
97
|
},
|
|
@@ -108,6 +113,18 @@ export const footfallDirectoryDocs = {
|
|
|
108
113
|
scema: j2s( ticketListSchema ).swagger,
|
|
109
114
|
required: false,
|
|
110
115
|
},
|
|
116
|
+
{
|
|
117
|
+
in: 'query',
|
|
118
|
+
name: 'sortBy',
|
|
119
|
+
scema: j2s( ticketListSchema ).swagger,
|
|
120
|
+
required: false,
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
in: 'query',
|
|
124
|
+
name: 'sortOrder',
|
|
125
|
+
scema: j2s( ticketListSchema ).swagger,
|
|
126
|
+
required: false,
|
|
127
|
+
},
|
|
111
128
|
],
|
|
112
129
|
responses: {
|
|
113
130
|
200: { description: 'Successful' },
|
|
@@ -131,6 +148,12 @@ export const footfallDirectoryDocs = {
|
|
|
131
148
|
scema: j2s( getTicketsSchema ).swagger,
|
|
132
149
|
required: true,
|
|
133
150
|
},
|
|
151
|
+
{
|
|
152
|
+
in: 'query',
|
|
153
|
+
name: 'dateString',
|
|
154
|
+
scema: j2s( getTicketsSchema ).swagger,
|
|
155
|
+
required: false,
|
|
156
|
+
},
|
|
134
157
|
{
|
|
135
158
|
in: 'query',
|
|
136
159
|
name: 'fromDate',
|
|
@@ -151,10 +174,22 @@ export const footfallDirectoryDocs = {
|
|
|
151
174
|
},
|
|
152
175
|
{
|
|
153
176
|
in: 'query',
|
|
154
|
-
name: '
|
|
177
|
+
name: 'status',
|
|
178
|
+
scema: j2s( getTicketsSchema ).swagger,
|
|
179
|
+
required: false,
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
in: 'query',
|
|
183
|
+
name: 'action',
|
|
155
184
|
scema: j2s( getTicketsSchema ).swagger,
|
|
156
185
|
required: false,
|
|
157
186
|
},
|
|
187
|
+
{
|
|
188
|
+
in: 'query',
|
|
189
|
+
name: 'limit',
|
|
190
|
+
scema: j2s( getTicketsSchema ).swagger,
|
|
191
|
+
required: true,
|
|
192
|
+
},
|
|
158
193
|
{
|
|
159
194
|
in: 'query',
|
|
160
195
|
name: 'offset',
|
|
@@ -177,14 +212,7 @@ export const footfallDirectoryDocs = {
|
|
|
177
212
|
tags: [ 'Footfall Directory Ticket' ],
|
|
178
213
|
description: 'approve or reject the ticket status',
|
|
179
214
|
operationId: 'update-status',
|
|
180
|
-
parameters: [
|
|
181
|
-
{
|
|
182
|
-
in: 'query',
|
|
183
|
-
name: '_id',
|
|
184
|
-
scema: j2s( updateStatusQuerySchema ).swagger,
|
|
185
|
-
required: true,
|
|
186
|
-
},
|
|
187
|
-
],
|
|
215
|
+
parameters: [],
|
|
188
216
|
requestBody: {
|
|
189
217
|
content: {
|
|
190
218
|
'application/json': {
|
|
@@ -201,4 +229,130 @@ export const footfallDirectoryDocs = {
|
|
|
201
229
|
},
|
|
202
230
|
},
|
|
203
231
|
},
|
|
232
|
+
|
|
233
|
+
'/v3/footfall-directory-tagging/get-tagged-stores': {
|
|
234
|
+
get: {
|
|
235
|
+
tags: [ 'Footfall Directory Ticket' ],
|
|
236
|
+
description: 'To get list of tagged stores',
|
|
237
|
+
operationId: 'get-tagged-stores',
|
|
238
|
+
parameters: [
|
|
239
|
+
{
|
|
240
|
+
in: 'query',
|
|
241
|
+
name: 'clientId',
|
|
242
|
+
scema: j2s( getTaggedStoresSchema ).swagger,
|
|
243
|
+
required: true,
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
in: 'query',
|
|
247
|
+
name: 'clusters',
|
|
248
|
+
scema: j2s( getTaggedStoresSchema ).swagger,
|
|
249
|
+
required: false,
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
in: 'query',
|
|
253
|
+
name: 'fromDate',
|
|
254
|
+
scema: j2s( getTaggedStoresSchema ).swagger,
|
|
255
|
+
required: true,
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
in: 'query',
|
|
259
|
+
name: 'toDate',
|
|
260
|
+
scema: j2s( getTaggedStoresSchema ).swagger,
|
|
261
|
+
required: true,
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
in: 'query',
|
|
265
|
+
name: 'searchValue',
|
|
266
|
+
scema: j2s( getTaggedStoresSchema ).swagger,
|
|
267
|
+
required: false,
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
in: 'query',
|
|
271
|
+
name: 'sortOrder',
|
|
272
|
+
scema: j2s( getTaggedStoresSchema ).swagger,
|
|
273
|
+
required: false,
|
|
274
|
+
},
|
|
275
|
+
],
|
|
276
|
+
responses: {
|
|
277
|
+
200: { description: 'Successful' },
|
|
278
|
+
401: { description: 'Unauthorized User' },
|
|
279
|
+
422: { description: 'Field Error' },
|
|
280
|
+
500: { description: 'Server Error' },
|
|
281
|
+
204: { description: 'Not Found' },
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
'/v3/footfall-directory-tagging/download-tickets': {
|
|
286
|
+
get: {
|
|
287
|
+
tags: [ 'Footfall Directory Ticket' ],
|
|
288
|
+
description: 'To get tickets Details by selction stores and date range',
|
|
289
|
+
operationId: 'download-tickets',
|
|
290
|
+
parameters: [
|
|
291
|
+
{
|
|
292
|
+
in: 'query',
|
|
293
|
+
name: 'storeId',
|
|
294
|
+
scema: j2s( getTicketsSchema ).swagger,
|
|
295
|
+
required: true,
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
in: 'query',
|
|
299
|
+
name: 'dateString',
|
|
300
|
+
scema: j2s( getTicketsSchema ).swagger,
|
|
301
|
+
required: false,
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
in: 'query',
|
|
305
|
+
name: 'fromDate',
|
|
306
|
+
scema: j2s( getTicketsSchema ).swagger,
|
|
307
|
+
required: true,
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
in: 'query',
|
|
311
|
+
name: 'toDate',
|
|
312
|
+
scema: j2s( getTicketsSchema ).swagger,
|
|
313
|
+
required: true,
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
in: 'query',
|
|
317
|
+
name: 'revopsType',
|
|
318
|
+
scema: j2s( getTicketsSchema ).swagger,
|
|
319
|
+
required: false,
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
in: 'query',
|
|
323
|
+
name: 'status',
|
|
324
|
+
scema: j2s( getTicketsSchema ).swagger,
|
|
325
|
+
required: false,
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
in: 'query',
|
|
329
|
+
name: 'action',
|
|
330
|
+
scema: j2s( getTicketsSchema ).swagger,
|
|
331
|
+
required: false,
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
in: 'query',
|
|
335
|
+
name: 'limit',
|
|
336
|
+
scema: j2s( getTicketsSchema ).swagger,
|
|
337
|
+
required: true,
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
in: 'query',
|
|
341
|
+
name: 'offset',
|
|
342
|
+
scema: j2s( getTicketsSchema ).swagger,
|
|
343
|
+
required: false,
|
|
344
|
+
},
|
|
345
|
+
],
|
|
346
|
+
responses: {
|
|
347
|
+
200: { description: 'Successful' },
|
|
348
|
+
401: { description: 'Unauthorized User' },
|
|
349
|
+
422: { description: 'Field Error' },
|
|
350
|
+
500: { description: 'Server Error' },
|
|
351
|
+
204: { description: 'Not Found' },
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
|
|
204
356
|
};
|
|
357
|
+
|
|
358
|
+
|
|
@@ -121,10 +121,13 @@ export const ticketSummaryValid = {
|
|
|
121
121
|
|
|
122
122
|
export const ticketListSchema = Joi.object().keys( {
|
|
123
123
|
clientId: Joi.string().required(),
|
|
124
|
+
storeId: Joi.string().optional(),
|
|
124
125
|
searchValue: Joi.string().optional().allow( '' ),
|
|
125
126
|
limit: Joi.number().optional(),
|
|
126
127
|
offset: Joi.number().optional(),
|
|
127
128
|
isExport: Joi.boolean().optional(),
|
|
129
|
+
sortBy: Joi.string().optional().allow( '' ),
|
|
130
|
+
sortOrder: Joi.number().valid( -1, 1 ).optional(),
|
|
128
131
|
fromDate: Joi.string()
|
|
129
132
|
.pattern( /^\d{4}-\d{2}-\d{2}$/, 'YYYY-MM-DD format' )
|
|
130
133
|
.required()
|
|
@@ -184,7 +187,8 @@ export const ticketListValid = {
|
|
|
184
187
|
};
|
|
185
188
|
|
|
186
189
|
export const getTicketsSchema = Joi.object().keys( {
|
|
187
|
-
storeId: Joi.string().required(),
|
|
190
|
+
storeId: Joi.string().required().allow( '' ),
|
|
191
|
+
dateString: Joi.string().optional(),
|
|
188
192
|
fromDate: Joi.string()
|
|
189
193
|
.pattern( /^\d{4}-\d{2}-\d{2}$/, 'YYYY-MM-DD format' )
|
|
190
194
|
.required()
|
|
@@ -223,7 +227,7 @@ export const getTicketsSchema = Joi.object().keys( {
|
|
|
223
227
|
status: Joi.string().optional(),
|
|
224
228
|
action: Joi.string().optional(),
|
|
225
229
|
revopsType: Joi.string().optional(),
|
|
226
|
-
limit: Joi.number().
|
|
230
|
+
limit: Joi.number().required(),
|
|
227
231
|
offset: Joi.number().optional(),
|
|
228
232
|
|
|
229
233
|
} ).custom( ( value, helpers ) => {
|
|
@@ -249,26 +253,31 @@ export const getTicketsValid = {
|
|
|
249
253
|
query: getTicketsSchema,
|
|
250
254
|
};
|
|
251
255
|
|
|
252
|
-
export const updateStatusQuerySchema =Joi.object().keys( {
|
|
253
|
-
|
|
254
|
-
_id: Joi.string().required(),
|
|
255
|
-
} );
|
|
256
|
-
|
|
257
256
|
export const updateStatusSchemea =Joi.object().keys( {
|
|
258
|
-
|
|
259
|
-
duplicateACCount: Joi.number().required(),
|
|
260
|
-
employeeACCount: Joi.number().required(),
|
|
261
|
-
houseKeepingACCount: Joi.number().required(),
|
|
262
|
-
comments: Joi.string().optional().allow( '' ),
|
|
263
|
-
duplicateImages: Joi.array().items(
|
|
257
|
+
data: Joi.array().items(
|
|
264
258
|
Joi.object( {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
259
|
+
_id: Joi.string().required(),
|
|
260
|
+
dateString: Joi.string().required().custom( ( value, helpers ) => {
|
|
261
|
+
const inputDate = dayjs( value, 'YYYY-MM-DD', true );
|
|
262
|
+
const today = dayjs();
|
|
263
|
+
|
|
264
|
+
if ( !inputDate.isValid() ) {
|
|
265
|
+
return helpers.error( 'any.invalid' );
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const diff = today.diff( inputDate, 'day' );
|
|
269
|
+
|
|
270
|
+
if ( diff > 10 ) {
|
|
271
|
+
return helpers.message( 'Approval is not allowed for a period exceeding 10 days' );
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return value;
|
|
275
|
+
} ),
|
|
276
|
+
duplicateACCount: Joi.number().optional(),
|
|
277
|
+
employeeACCount: Joi.number().optional(),
|
|
278
|
+
houseKeepingACCount: Joi.number().optional(),
|
|
279
|
+
comments: Joi.string().optional().allow( '' ),
|
|
280
|
+
duplicateImages: Joi.array().items(
|
|
272
281
|
Joi.object( {
|
|
273
282
|
tempId: Joi.number().required(),
|
|
274
283
|
filePath: Joi.string().required(),
|
|
@@ -276,41 +285,56 @@ export const updateStatusSchemea =Joi.object().keys( {
|
|
|
276
285
|
exitTime: Joi.string().required(),
|
|
277
286
|
timeRange: Joi.string().required(),
|
|
278
287
|
isChecked: Joi.boolean().required(),
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
288
|
+
selected: Joi.boolean().optional(),
|
|
289
|
+
data: Joi.array().items(
|
|
290
|
+
Joi.object( {
|
|
291
|
+
tempId: Joi.number().required(),
|
|
292
|
+
filePath: Joi.string().required(),
|
|
293
|
+
entryTime: Joi.string().required(),
|
|
294
|
+
exitTime: Joi.string().required(),
|
|
295
|
+
timeRange: Joi.string().required(),
|
|
296
|
+
isChecked: Joi.boolean().required(),
|
|
297
|
+
selected: Joi.boolean().optional(),
|
|
298
|
+
} ),
|
|
299
|
+
).optional(),
|
|
300
|
+
} ) ).optional(),
|
|
301
|
+
houseKeeping: Joi.array().items( Joi.object( {
|
|
302
|
+
tempId: Joi.number().required(),
|
|
303
|
+
filePath: Joi.string().required(),
|
|
304
|
+
entryTime: Joi.string().required(),
|
|
305
|
+
exitTime: Joi.string().required(),
|
|
306
|
+
timeRange: Joi.string().required(),
|
|
307
|
+
isChecked: Joi.boolean().required(),
|
|
308
|
+
selected: Joi.boolean().optional(),
|
|
309
|
+
|
|
310
|
+
} ) ).optional(),
|
|
311
|
+
employee: Joi.array().items( Joi.object( {
|
|
312
|
+
tempId: Joi.number().required(),
|
|
313
|
+
filePath: Joi.string().required(),
|
|
314
|
+
entryTime: Joi.string().required(),
|
|
315
|
+
exitTime: Joi.string().required(),
|
|
316
|
+
timeRange: Joi.string().required(),
|
|
317
|
+
isChecked: Joi.boolean().required(),
|
|
318
|
+
selected: Joi.boolean().optional(),
|
|
319
|
+
|
|
320
|
+
} ) ).optional(),
|
|
321
|
+
duplicateStatus: Joi.string().optional(),
|
|
322
|
+
employeeStatus: Joi.string().optional(),
|
|
323
|
+
houseKeepingStatus: Joi.string().optional(),
|
|
324
|
+
} ) ).required(),
|
|
298
325
|
|
|
299
|
-
} ) ).optional(),
|
|
300
|
-
duplicateStatus: Joi.string().required(),
|
|
301
|
-
employeeStatus: Joi.string().required(),
|
|
302
|
-
houseKeepingStatus: Joi.string().required(),
|
|
303
326
|
} );
|
|
304
327
|
|
|
305
328
|
export const updateStatusValid = {
|
|
306
|
-
query: updateStatusQuerySchema,
|
|
307
329
|
body: updateStatusSchemea,
|
|
308
330
|
};
|
|
309
331
|
|
|
310
332
|
|
|
311
333
|
export const getTaggedStoresSchema = Joi.object().keys( {
|
|
312
334
|
clientId: Joi.string().required(),
|
|
313
|
-
|
|
335
|
+
searchValue: Joi.string().optional().allow( '' ),
|
|
336
|
+
clusters: Joi.string().optional(),
|
|
337
|
+
sortOrder: Joi.number().optional(),
|
|
314
338
|
fromDate: Joi.string()
|
|
315
339
|
.pattern( /^\d{4}-\d{2}-\d{2}$/, 'YYYY-MM-DD format' )
|
|
316
340
|
.required()
|
|
@@ -368,3 +392,71 @@ export const getTaggedStoresSchema = Joi.object().keys( {
|
|
|
368
392
|
export const getTaggedStoresValid = {
|
|
369
393
|
query: getTaggedStoresSchema,
|
|
370
394
|
};
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
export const downloadTicketsSchema = Joi.object().keys( {
|
|
398
|
+
storeId: Joi.string().required().allow( '' ),
|
|
399
|
+
dateString: Joi.string().optional(),
|
|
400
|
+
fromDate: Joi.string()
|
|
401
|
+
.pattern( /^\d{4}-\d{2}-\d{2}$/, 'YYYY-MM-DD format' )
|
|
402
|
+
.required()
|
|
403
|
+
.messages( {
|
|
404
|
+
'string.pattern.name': `'fromDate' must be in the format YYYY-MM-DD (e.g., 2025-07-19).`,
|
|
405
|
+
'string.empty': `'fromDate' is required.`,
|
|
406
|
+
} )
|
|
407
|
+
.custom( ( value, helpers ) => {
|
|
408
|
+
const from = dayjs( value );
|
|
409
|
+
if ( !from.isValid() ) {
|
|
410
|
+
return helpers.error( 'any.invalid', { message: 'Invalid fromDate' } );
|
|
411
|
+
}
|
|
412
|
+
return value;
|
|
413
|
+
} ),
|
|
414
|
+
|
|
415
|
+
toDate: Joi.string()
|
|
416
|
+
.pattern( /^\d{4}-\d{2}-\d{2}$/, 'YYYY-MM-DD format' )
|
|
417
|
+
.required()
|
|
418
|
+
.messages( {
|
|
419
|
+
'string.pattern.name': `'toDate' must be in the format YYYY-MM-DD (e.g., 2025-07-19).`,
|
|
420
|
+
'string.empty': `'toDate' is required.`,
|
|
421
|
+
} )
|
|
422
|
+
.custom( ( value, helpers ) => {
|
|
423
|
+
const to = dayjs( value );
|
|
424
|
+
const today = dayjs();
|
|
425
|
+
|
|
426
|
+
if ( !to.isValid() ) {
|
|
427
|
+
return helpers.error( 'any.invalid', { message: 'Invalid toDate' } );
|
|
428
|
+
}
|
|
429
|
+
if ( to.isAfter( today, 'day' ) ) {
|
|
430
|
+
return helpers.error( 'any.invalid', { message: 'toDate cannot be in the future' } );
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
return value;
|
|
434
|
+
} ),
|
|
435
|
+
status: Joi.string().optional(),
|
|
436
|
+
action: Joi.string().optional(),
|
|
437
|
+
revopsType: Joi.string().optional(),
|
|
438
|
+
limit: Joi.number().required(),
|
|
439
|
+
offset: Joi.number().optional(),
|
|
440
|
+
|
|
441
|
+
} ).custom( ( value, helpers ) => {
|
|
442
|
+
const from = dayjs( value.fromDate );
|
|
443
|
+
const to = dayjs( value.toDate );
|
|
444
|
+
|
|
445
|
+
if ( !from.isValid() || !to.isValid() ) {
|
|
446
|
+
return helpers.error( 'any.invalid', { message: 'Invalid dates' } );
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if ( from.isAfter( to ) ) {
|
|
450
|
+
return helpers.error( 'any.invalid', { message: 'fromDate cannot be after toDate' } );
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if ( to.diff( from, 'day' ) > 90 ) {
|
|
454
|
+
return helpers.error( 'any.invalid', { message: 'Date range cannot exceed 90 days' } );
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
return value;
|
|
458
|
+
} );
|
|
459
|
+
|
|
460
|
+
export const downloadTicketsValid = {
|
|
461
|
+
query: downloadTicketsSchema,
|
|
462
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
|
-
import { isExist } from '../validations/footfallDirectory.validation.js';
|
|
3
|
-
import { createTicket, getTaggedStores, getTickets, ticketList, ticketSummary, updateStatus } from '../controllers/footfallDirectory.controllers.js';
|
|
4
|
-
import { createTicketValid, getTaggedStoresValid, getTicketsValid, ticketListValid, ticketSummaryValid, updateStatusValid } from '../dtos/footfallDirectory.dtos.js';
|
|
5
|
-
import { bulkValidate, isAllowedSessionHandler, validate } from 'tango-app-api-middleware';
|
|
2
|
+
import { getClusters, isExist, isTicketExists } from '../validations/footfallDirectory.validation.js';
|
|
3
|
+
import { createTicket, downloadTickets, getTaggedStores, getTickets, ticketList, ticketSummary, updateStatus } from '../controllers/footfallDirectory.controllers.js';
|
|
4
|
+
import { createTicketValid, downloadTicketsValid, getTaggedStoresValid, getTicketsValid, ticketListValid, ticketSummaryValid, updateStatusValid } from '../dtos/footfallDirectory.dtos.js';
|
|
5
|
+
import { bulkValidate, getAssinedStore, isAllowedSessionHandler, validate } from 'tango-app-api-middleware';
|
|
6
6
|
|
|
7
7
|
export const footfallDirectoryRouter = express.Router();
|
|
8
8
|
|
|
@@ -11,7 +11,7 @@ footfallDirectoryRouter.get( '/ticket-summary', isAllowedSessionHandler, bulkVal
|
|
|
11
11
|
|
|
12
12
|
footfallDirectoryRouter.get( '/ticket-list', isAllowedSessionHandler, bulkValidate( ticketListValid ), ticketList );
|
|
13
13
|
footfallDirectoryRouter.get( '/get-tickets', isAllowedSessionHandler, bulkValidate( getTicketsValid ), getTickets );
|
|
14
|
-
footfallDirectoryRouter.get( '/get-tagged-stores', bulkValidate( getTaggedStoresValid ), getTaggedStores );
|
|
15
|
-
|
|
16
|
-
footfallDirectoryRouter.
|
|
14
|
+
footfallDirectoryRouter.get( '/get-tagged-stores', isAllowedSessionHandler, bulkValidate( getTaggedStoresValid ), getAssinedStore, getClusters, getTaggedStores );
|
|
15
|
+
footfallDirectoryRouter.put( '/update-status', isAllowedSessionHandler, bulkValidate( updateStatusValid ), updateStatus );
|
|
16
|
+
footfallDirectoryRouter.get( '/download-tickets', isAllowedSessionHandler, bulkValidate( downloadTicketsValid ), isTicketExists, downloadTickets );
|
|
17
17
|
|
|
@@ -6,3 +6,6 @@ export async function aggregateCamera( query ) {
|
|
|
6
6
|
export async function updateOneCamera( query, record ) {
|
|
7
7
|
return await cameraModel.updateOne( query, { $set: record } );
|
|
8
8
|
}
|
|
9
|
+
export async function countDocumnetsCamera( query ) {
|
|
10
|
+
return await cameraModel.countDocuments( query );
|
|
11
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import revopDownloadModel from 'tango-api-schema/schema/revopDownload.model.js';
|
|
2
|
+
|
|
3
|
+
export async function upsertRevopDownload( query, record ) {
|
|
4
|
+
return await revopDownloadModel.updateOne( query, { $set: record }, { upsert: true } );
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export async function findOneRevopDownload( query, fields={} ) {
|
|
8
|
+
return await revopDownloadModel.findOne( query, fields );
|
|
9
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { getOpenSearchCount, logger } from 'tango-app-api-middleware';
|
|
2
|
+
import { aggregateCluster } from '../services/cluster.service.js';
|
|
3
|
+
import { findOneRevopDownload } from '../services/revopDownload.service.js';
|
|
2
4
|
|
|
3
5
|
export async function isExist( req, res, next ) {
|
|
4
6
|
try {
|
|
@@ -37,3 +39,92 @@ export async function isExist( req, res, next ) {
|
|
|
37
39
|
return res.sendError( err, 500 );
|
|
38
40
|
}
|
|
39
41
|
}
|
|
42
|
+
|
|
43
|
+
export async function getClusters( req, res, next ) {
|
|
44
|
+
try {
|
|
45
|
+
const inputData=req.query;
|
|
46
|
+
// const assignedStores = req.body.assignedStores;
|
|
47
|
+
const clusters = inputData?.clusters?.split( ',' ); // convert strig to array
|
|
48
|
+
// logger.info( { assignedStores, clusters } );
|
|
49
|
+
let filter =[
|
|
50
|
+
{
|
|
51
|
+
clientId: inputData.clientId,
|
|
52
|
+
},
|
|
53
|
+
];
|
|
54
|
+
if ( inputData?.clusters ) {
|
|
55
|
+
filter.push( {
|
|
56
|
+
clusterName: { $in: clusters },
|
|
57
|
+
} );
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let query = [
|
|
61
|
+
{
|
|
62
|
+
$match: {
|
|
63
|
+
|
|
64
|
+
$and: filter,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
$unwind: { path: '$stores', preserveNullAndEmptyArrays: true },
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
$group: {
|
|
72
|
+
_id: null,
|
|
73
|
+
stores: { $addToSet: '$stores.storeId' },
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
// if ( req?.user?.userType == 'client' && req?.user?.role !== 'superadmin' && assignedStores?.length == 0 ) {
|
|
79
|
+
// return res.sendError( 'Access this if assigned atleast a store', 403 );
|
|
80
|
+
// }
|
|
81
|
+
|
|
82
|
+
// if ( req?.user?.userType == 'client' && assignedStores?.length> 0 ) {
|
|
83
|
+
// query.push( {
|
|
84
|
+
// $match: {
|
|
85
|
+
|
|
86
|
+
// stores: { $in: assignedStores },
|
|
87
|
+
// },
|
|
88
|
+
// } );
|
|
89
|
+
// }
|
|
90
|
+
|
|
91
|
+
const getStores = await aggregateCluster( query );
|
|
92
|
+
if ( getStores?.[0]?.stores?.length == 0 ) {
|
|
93
|
+
return res.sendError( 'No data', 204 );
|
|
94
|
+
}
|
|
95
|
+
logger.info( { getStores: getStores, length: getStores?.[0]?.stores?.length, stores: getStores?.[0]?.stores } );
|
|
96
|
+
req.stores = getStores?.[0]?.stores;
|
|
97
|
+
return next();
|
|
98
|
+
} catch ( error ) {
|
|
99
|
+
const err = error.message || 'Internal Server Error';
|
|
100
|
+
logger.error( { error: error, message: req.body, function: 'footfallDirectoryTicket-getClusters' } );
|
|
101
|
+
return res.sendError( err, 500 );
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export async function isTicketExists( req, res, next ) {
|
|
106
|
+
try {
|
|
107
|
+
const inputData = req.query;
|
|
108
|
+
inputData.storeId = inputData?.storeId?.split( ',' );
|
|
109
|
+
const query = {
|
|
110
|
+
stores: { $in: inputData.storeId },
|
|
111
|
+
fromDate: inputData?.fromDate,
|
|
112
|
+
toDate: inputData?.toDate,
|
|
113
|
+
ticketStatus: inputData?.status,
|
|
114
|
+
ticketAction: inputData?.action,
|
|
115
|
+
revopsType: inputData?.revopsType,
|
|
116
|
+
type: 'get-tickets',
|
|
117
|
+
};
|
|
118
|
+
const getId = await findOneRevopDownload( query, { _id: 1, status: 1, outputFilePath: 1 } );
|
|
119
|
+
if ( getId ) {
|
|
120
|
+
return res.sendSuccess( { result: { status: getId?.status, outputFilePath: getId?.outputFilePath } } );
|
|
121
|
+
} else {
|
|
122
|
+
return next();
|
|
123
|
+
}
|
|
124
|
+
} catch ( error ) {
|
|
125
|
+
const err = error.message || 'Internal Server Error';
|
|
126
|
+
logger.error( { error: error, message: req.body, function: 'footfallDirectoryTicket-isTicketExists' } );
|
|
127
|
+
return res.sendError( err, 500 );
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|