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.
@@ -1,5 +1,5 @@
1
1
  import j2s from 'joi-to-swagger';
2
- import { createTicketSchema, getTicketsSchema, ticketListSchema, ticketSummarySchema, updateStatusQuerySchema, updateStatusSchemea } from '../dtos/footfallDirectory.dtos.js';
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: 'searchvalue',
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: 'limit',
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().optional(),
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
- tempId: Joi.number().required(),
266
- filePath: Joi.string().required(),
267
- entryTime: Joi.string().required(),
268
- exitTime: Joi.string().required(),
269
- timeRange: Joi.string().required(),
270
- isChecked: Joi.boolean().required(),
271
- data: Joi.array().items(
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
- ).optional(),
281
- } ) ).optional(),
282
-
283
- houseKeeping: Joi.array().items( Joi.object( {
284
- tempId: Joi.number().required(),
285
- filePath: Joi.string().required(),
286
- entryTime: Joi.string().required(),
287
- exitTime: Joi.string().required(),
288
- timeRange: Joi.string().required(),
289
- isChecked: Joi.boolean().required(),
290
- } ) ).optional(),
291
- employee: Joi.array().items( Joi.object( {
292
- tempId: Joi.number().required(),
293
- filePath: Joi.string().required(),
294
- entryTime: Joi.string().required(),
295
- exitTime: Joi.string().required(),
296
- timeRange: Joi.string().required(),
297
- isChecked: Joi.boolean().required(),
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.put( '/update-status', bulkValidate( updateStatusValid ), updateStatus );
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
+