tango-app-api-infra 3.9.5-vms.9 → 3.9.5-vms.91

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.
@@ -3,9 +3,25 @@ import dayjs from 'dayjs';
3
3
 
4
4
  export const createTicketSchema = Joi.object().keys( {
5
5
 
6
- dateString: Joi.string().required(),
6
+ dateString: Joi.string().required().custom( ( value, helpers ) => {
7
+ const inputDate = dayjs( value, 'YYYY-MM-DD', true );
8
+ const today = dayjs();
9
+
10
+ if ( !inputDate.isValid() ) {
11
+ return helpers.error( 'any.invalid' );
12
+ }
13
+
14
+ const diff = today.diff( inputDate, 'day' );
15
+
16
+ if ( diff > 3 ) {
17
+ return helpers.message( 'Ticket Creation is not allowed for a period exceeding 3 days' );
18
+ }
19
+
20
+ return value;
21
+ } ),
7
22
  storeId: Joi.string().required(),
8
23
  ticketName: Joi.string().required(),
24
+ comments: Joi.string().optional(),
9
25
  type: Joi.string()
10
26
  .required()
11
27
  .valid( 'create', 'review', 'approve', 'tangRreview' )
@@ -23,9 +39,55 @@ export const createTicketValid = {
23
39
  body: createTicketSchema,
24
40
  };
25
41
 
42
+ export const tangoReviewTicketSchema = Joi.object().keys( {
43
+
44
+ dateString: Joi.string().required().custom( ( value, helpers ) => {
45
+ const inputDate = dayjs( value, 'YYYY-MM-DD', true );
46
+
47
+ if ( !inputDate.isValid() ) {
48
+ return helpers.error( 'any.invalid' );
49
+ }
50
+
51
+ return value;
52
+ } ),
53
+ storeId: Joi.string().required(),
54
+ comments: Joi.string().optional(),
55
+ ticketType: Joi.string().optional(),
56
+ mappingInfo: Joi.object().keys( {
57
+ type: Joi.string().required(),
58
+ mode: Joi.string().required(),
59
+ revicedFootfall: Joi.number().required(),
60
+ revicedPerc: Joi.string().required(),
61
+ count: Joi.array().required(),
62
+ revisedDetail: Joi.array().required(),
63
+ createdByEmail: Joi.string().optional(),
64
+ createdByUserName: Joi.string().optional(),
65
+ createdByRole: Joi.string().optional(),
66
+ status: Joi.string().optional(),
67
+
68
+
69
+ } ).required(),
70
+ } );
71
+
72
+ export const tangoReviewTicketValid = {
73
+ body: tangoReviewTicketSchema,
74
+ };
75
+ export const tangoReviewAccuracyClosedTicketSchema = Joi.object().keys( {
76
+ storeId: Joi.string().required(),
77
+ dateString: Joi.string().required(),
78
+ comments: Joi.string().required(),
79
+ subComment: Joi.string().required(),
80
+
81
+ } );
82
+
83
+ export const tangoReviewAccuracyClosedTicketValid = {
84
+ body: tangoReviewAccuracyClosedTicketSchema,
85
+ };
86
+
26
87
  export const ticketSummarySchema = Joi.object().keys( {
27
88
  clientId: Joi.string().required(),
28
-
89
+ tangoType: Joi.string().valid( 'store', 'internal' ).optional(),
90
+ permissionType: Joi.string().valid( 'approve', 'review' ).optional(),
29
91
  fromDate: Joi.string()
30
92
  .pattern( /^\d{4}-\d{2}-\d{2}$/, 'YYYY-MM-DD format' )
31
93
  .required()
@@ -93,8 +155,17 @@ export const ticketListSchema = Joi.object().keys( {
93
155
  offset: Joi.number().optional(),
94
156
  isExport: Joi.boolean().optional(),
95
157
  sortBy: Joi.string().optional().allow( '' ),
158
+ status: Joi.string().optional(),
96
159
  sortOrder: Joi.number().valid( -1, 1 ).optional(),
97
160
  tangoType: Joi.string().valid( 'store', 'internal', '' ).optional(),
161
+ permissionType: Joi.string().valid( 'review', 'approve' ).optional(),
162
+ filterByStatus: Joi.string().optional().allow( '' ),
163
+ filterByStore: Joi.string().optional().allow( '' ),
164
+ filterByReviewer: Joi.string().optional().allow( '' ),
165
+ filterByApprover: Joi.string().optional().allow( '' ),
166
+ filterByTango: Joi.string().optional().allow( '' ),
167
+ filterByReviewedBy: Joi.string().optional().allow( '' ),
168
+ fileterByApprovedBy: Joi.string().optional().allow( '' ),
98
169
  fromDate: Joi.string()
99
170
  .pattern( /^\d{4}-\d{2}-\d{2}$/, 'YYYY-MM-DD format' )
100
171
  .required()
@@ -154,73 +225,75 @@ export const ticketListValid = {
154
225
  };
155
226
 
156
227
  export const getTicketsSchema = Joi.object().keys( {
157
- storeId: Joi.string().required().allow( '' ),
158
- dateString: Joi.string().optional(),
159
- fromDate: Joi.string()
160
- .pattern( /^\d{4}-\d{2}-\d{2}$/, 'YYYY-MM-DD format' )
161
- .required()
162
- .messages( {
163
- 'string.pattern.name': `'fromDate' must be in the format YYYY-MM-DD (e.g., 2025-07-19).`,
164
- 'string.empty': `'fromDate' is required.`,
165
- } )
166
- .custom( ( value, helpers ) => {
167
- const from = dayjs( value );
168
- if ( !from.isValid() ) {
169
- return helpers.error( 'any.invalid', { message: 'Invalid fromDate' } );
170
- }
171
- return value;
172
- } ),
173
-
174
- toDate: Joi.string()
175
- .pattern( /^\d{4}-\d{2}-\d{2}$/, 'YYYY-MM-DD format' )
176
- .required()
177
- .messages( {
178
- 'string.pattern.name': `'toDate' must be in the format YYYY-MM-DD (e.g., 2025-07-19).`,
179
- 'string.empty': `'toDate' is required.`,
180
- } )
181
- .custom( ( value, helpers ) => {
182
- const to = dayjs( value );
183
- const today = dayjs();
184
-
185
- if ( !to.isValid() ) {
186
- return helpers.error( 'any.invalid', { message: 'Invalid toDate' } );
187
- }
188
- if ( to.isAfter( today, 'day' ) ) {
189
- return helpers.error( 'any.invalid', { message: 'toDate cannot be in the future' } );
190
- }
191
-
192
- return value;
193
- } ),
194
- status: Joi.string().optional(),
228
+ // storeId: Joi.string().required().allow( '' ),
229
+ // dateString: Joi.string().required(),
230
+ // fromDate: Joi.string()
231
+ // .pattern( /^\d{4}-\d{2}-\d{2}$/, 'YYYY-MM-DD format' )
232
+ // .required()
233
+ // .messages( {
234
+ // 'string.pattern.name': `'fromDate' must be in the format YYYY-MM-DD (e.g., 2025-07-19).`,
235
+ // 'string.empty': `'fromDate' is required.`,
236
+ // } )
237
+ // .custom( ( value, helpers ) => {
238
+ // const from = dayjs( value );
239
+ // if ( !from.isValid() ) {
240
+ // return helpers.error( 'any.invalid', { message: 'Invalid fromDate' } );
241
+ // }
242
+ // return value;
243
+ // } ),
244
+
245
+ // toDate: Joi.string()
246
+ // .pattern( /^\d{4}-\d{2}-\d{2}$/, 'YYYY-MM-DD format' )
247
+ // .required()
248
+ // .messages( {
249
+ // 'string.pattern.name': `'toDate' must be in the format YYYY-MM-DD (e.g., 2025-07-19).`,
250
+ // 'string.empty': `'toDate' is required.`,
251
+ // } )
252
+ // .custom( ( value, helpers ) => {
253
+ // const to = dayjs( value );
254
+ // const today = dayjs();
255
+
256
+ // if ( !to.isValid() ) {
257
+ // return helpers.error( 'any.invalid', { message: 'Invalid toDate' } );
258
+ // }
259
+ // if ( to.isAfter( today, 'day' ) ) {
260
+ // return helpers.error( 'any.invalid', { message: 'toDate cannot be in the future' } );
261
+ // }
262
+
263
+ // return value;
264
+ // } ),
265
+ ticketId: Joi.string().required(),
266
+ // status: Joi.string().optional(),
195
267
  action: Joi.string().optional(),
196
- revopsType: Joi.string().optional(),
197
- limit: Joi.number().required(),
198
- offset: Joi.number().optional(),
268
+ // revopsType: Joi.string().optional(),
269
+ // limit: Joi.number().required(),
270
+ // offset: Joi.number().optional(),
199
271
 
200
- } ).custom( ( value, helpers ) => {
201
- const from = dayjs( value.fromDate );
202
- const to = dayjs( value.toDate );
272
+ } );
273
+ // .custom( ( value, helpers ) => {
274
+ // const from = dayjs( value.fromDate );
275
+ // const to = dayjs( value.toDate );
203
276
 
204
- if ( !from.isValid() || !to.isValid() ) {
205
- return helpers.error( 'any.invalid', { message: 'Invalid dates' } );
206
- }
277
+ // if ( !from.isValid() || !to.isValid() ) {
278
+ // return helpers.error( 'any.invalid', { message: 'Invalid dates' } );
279
+ // }
207
280
 
208
- if ( from.isAfter( to ) ) {
209
- return helpers.error( 'any.invalid', { message: 'fromDate cannot be after toDate' } );
210
- }
281
+ // if ( from.isAfter( to ) ) {
282
+ // return helpers.error( 'any.invalid', { message: 'fromDate cannot be after toDate' } );
283
+ // }
211
284
 
212
- if ( to.diff( from, 'day' ) > 90 ) {
213
- return helpers.error( 'any.invalid', { message: 'Date range cannot exceed 90 days' } );
214
- }
285
+ // if ( to.diff( from, 'day' ) > 90 ) {
286
+ // return helpers.error( 'any.invalid', { message: 'Date range cannot exceed 90 days' } );
287
+ // }
215
288
 
216
- return value;
217
- } );
289
+ // return value;
290
+ // } );
218
291
 
219
292
  export const getTicketsValid = {
220
293
  query: getTicketsSchema,
221
294
  };
222
295
 
223
- export const updateStatusSchemea =Joi.object().keys( {
296
+ export const updateStatusSchemea = Joi.object().keys( {
224
297
  data: Joi.array().items(
225
298
  Joi.object( {
226
299
  _id: Joi.string().required(),
@@ -442,6 +515,8 @@ export const downloadTicketsValid = {
442
515
 
443
516
  export const reviewerListSchema = Joi.object().keys( {
444
517
  clientId: Joi.string().required(),
518
+ tangotype: Joi.string().optional(),
519
+ type: Joi.string().required().allow( 'approve', 'review' ),
445
520
  } );
446
521
 
447
522
  export const reviewerListValid = {
@@ -454,6 +529,9 @@ export const openTicketListSchema = Joi.object().keys( {
454
529
  clientId: Joi.array().items(
455
530
  Joi.string().required(),
456
531
  ).required(),
532
+ type: Joi.string().required().allow( 'review', 'approve' ),
533
+ sortOrder: Joi.number().valid( 1, -1 ).optional(),
534
+ searchValue: Joi.string().allow( '' ).optional(),
457
535
 
458
536
 
459
537
  } );
@@ -468,7 +546,8 @@ export const assignTicketSchema = Joi.object().keys( {
468
546
  userName: Joi.string().optional(),
469
547
  role: Joi.string().optional(),
470
548
  actionType: Joi.string().required(),
471
- ticketId: Joi.string().required(),
549
+ storeId: Joi.string().required(),
550
+ dateString: Joi.string().required(),
472
551
 
473
552
 
474
553
  } );
@@ -480,7 +559,8 @@ export const assignTicketValid = {
480
559
  export const updateTempStatusSchema = Joi.object().keys( {
481
560
  id: Joi.array().items( Joi.string().required() ).required(),
482
561
  status: Joi.string().required(),
483
- type: Joi.string().required(),
562
+ type: Joi.string().required().allow( 'review', 'approve' ),
563
+ comments: Joi.string().optional().allow( '' ),
484
564
 
485
565
 
486
566
  } );
@@ -488,3 +568,52 @@ export const updateTempStatusSchema = Joi.object().keys( {
488
568
  export const updateTempStatusValid = {
489
569
  body: updateTempStatusSchema,
490
570
  };
571
+
572
+ export const updateTicketStatusSchema = Joi.object().keys( {
573
+ storeId: Joi.string().required(),
574
+ dateString: Joi.string().required(),
575
+ mode: Joi.string().required(),
576
+
577
+ } );
578
+
579
+ export const updateTicketStatusValid = {
580
+ body: updateTicketStatusSchema,
581
+ };
582
+
583
+ export const multiCloseTicketSchema = Joi.object().keys( {
584
+
585
+ ticketList: Joi.array().items( Joi.object().keys( {
586
+ storeId: Joi.string().required(),
587
+ dateString: Joi.string().required(),
588
+ } ) ),
589
+ mode: Joi.string().required(),
590
+
591
+ } );
592
+
593
+ export const multiCloseTicketValid = {
594
+ body: multiCloseTicketSchema,
595
+ };
596
+
597
+
598
+ export const getAccuracyIssuesSchema = Joi.object().keys( {
599
+
600
+
601
+ clientId: Joi.string().required(),
602
+
603
+ } );
604
+
605
+ export const getAccuracyIssuesValid = {
606
+ query: getAccuracyIssuesSchema,
607
+ };
608
+
609
+ export const updateAccuracyIssuesSchema = Joi.object().keys( {
610
+
611
+
612
+ clientId: Joi.string().required(),
613
+ issueName: Joi.string().required(),
614
+
615
+ } );
616
+
617
+ export const updateAccuracyIssuesValid = {
618
+ query: updateAccuracyIssuesSchema,
619
+ };
@@ -1,16 +1,21 @@
1
1
  import express from 'express';
2
- import { getClusters, getConfig, isGrantedUsers, isTicketExists, ticketCreation } from '../validations/footfallDirectory.validation.js';
3
- import { assignTicket, createTicket, downloadTickets, getTaggedStores, getTickets, openTicketList, reviewerList, ticketList, ticketSummary, updateStatus, updateTempStatus } from '../controllers/footfallDirectory.controllers.js';
4
- import { createTicketValid, downloadTicketsValid, getTaggedStoresValid, getTicketsValid, openTicketListValid, reviewerListValid, ticketListValid, ticketSummaryValid, updateStatusValid, assignTicketValid, updateTempStatusValid } from '../dtos/footfallDirectory.dtos.js';
2
+ import { getClusters, getConfig, isGrantedUsers, isTicketExists, ticketApprove, ticketCreation, ticketReview } from '../validations/footfallDirectory.validation.js';
3
+ import { assignTicket, createTicket, downloadTickets, getTaggedStores, getTickets, multiCloseTicket, openTicketList, reviewerList, tangoReviewTicket, ticketList, ticketSummary, updateStatus, updateTempStatus, updateUserTicketStatus, createinternalTicket, checkTicketExists, tangoReviewAccuracyClosedTicket, getAccuracyIssues, updateAccuracyIssues } from '../controllers/footfallDirectory.controllers.js';
4
+ import { createTicketValid, downloadTicketsValid, getTaggedStoresValid, getTicketsValid, openTicketListValid, reviewerListValid, ticketListValid, ticketSummaryValid, updateStatusValid, assignTicketValid, updateTempStatusValid, updateTicketStatusValid, tangoReviewTicketValid, multiCloseTicketValid, tangoReviewAccuracyClosedTicketValid, getAccuracyIssuesValid, updateAccuracyIssuesValid } from '../dtos/footfallDirectory.dtos.js';
5
5
  import { bulkValidate, getAssinedStore, isAllowedSessionHandler, validate } from 'tango-app-api-middleware';
6
6
 
7
7
  export const footfallDirectoryRouter = express.Router();
8
8
 
9
- footfallDirectoryRouter.post( '/create-ticket', isAllowedSessionHandler, validate( createTicketValid ), isGrantedUsers, getConfig, ticketCreation, createTicket );
9
+ footfallDirectoryRouter.post( '/create-ticket', isAllowedSessionHandler, validate( createTicketValid ), isGrantedUsers, getConfig, ticketCreation, ticketReview, ticketApprove, createTicket );
10
+ footfallDirectoryRouter.post( '/create-internalticket', isAllowedSessionHandler, createinternalTicket );
11
+ footfallDirectoryRouter.post( '/checkTicketExists', isAllowedSessionHandler, checkTicketExists );
12
+
13
+ footfallDirectoryRouter.post( '/tango-review-ticket', isAllowedSessionHandler, validate( tangoReviewTicketValid ), tangoReviewTicket );
14
+ footfallDirectoryRouter.post( '/tango-review-accuracy-ticket', isAllowedSessionHandler, validate( tangoReviewAccuracyClosedTicketValid ), tangoReviewAccuracyClosedTicket );
15
+
10
16
  footfallDirectoryRouter.get( '/ticket-summary', isAllowedSessionHandler, bulkValidate( ticketSummaryValid ), ticketSummary );
11
17
 
12
18
  footfallDirectoryRouter.get( '/ticket-list', isAllowedSessionHandler, bulkValidate( ticketListValid ), ticketList );
13
- // footfallDirectoryRouter.get( '/ticket-list', isAllowedSessionHandler, bulkValidate( ticketListValid ), ticketList );
14
19
  footfallDirectoryRouter.get( '/get-tickets', isAllowedSessionHandler, bulkValidate( getTicketsValid ), getTickets );
15
20
  footfallDirectoryRouter.get( '/get-tagged-stores', isAllowedSessionHandler, bulkValidate( getTaggedStoresValid ), getAssinedStore, getClusters, getTaggedStores );
16
21
  footfallDirectoryRouter.put( '/update-status', isAllowedSessionHandler, bulkValidate( updateStatusValid ), updateStatus );
@@ -19,5 +24,10 @@ footfallDirectoryRouter.get( '/reviewer-list', isAllowedSessionHandler, bulkVali
19
24
  footfallDirectoryRouter.post( '/open-ticket-list', isAllowedSessionHandler, bulkValidate( openTicketListValid ), openTicketList );
20
25
  footfallDirectoryRouter.post( '/assign-ticket', isAllowedSessionHandler, bulkValidate( assignTicketValid ), assignTicket );
21
26
  footfallDirectoryRouter.post( '/update-temp-status', isAllowedSessionHandler, bulkValidate( updateTempStatusValid ), updateTempStatus );
27
+ footfallDirectoryRouter.post( '/update-ticket-status', isAllowedSessionHandler, bulkValidate( updateTicketStatusValid ), updateUserTicketStatus );
28
+ footfallDirectoryRouter.post( '/multi-close-tickets', isAllowedSessionHandler, bulkValidate( multiCloseTicketValid ), multiCloseTicket );
29
+
30
+ footfallDirectoryRouter.get( '/get-accuarcy-issues', isAllowedSessionHandler, bulkValidate( getAccuracyIssuesValid ), getAccuracyIssues );
31
+ footfallDirectoryRouter.put( '/update-accuarcy-issues', isAllowedSessionHandler, bulkValidate( updateAccuracyIssuesValid ), updateAccuracyIssues );
22
32
 
23
33
 
@@ -0,0 +1,9 @@
1
+ import storeAccuracyIssuesModel from 'tango-api-schema/schema/storeAccuracyIssues.model.js';
2
+
3
+ export async function findStoreAccuracIssues( query, fiels ) {
4
+ return await storeAccuracyIssuesModel.find( query, fiels );
5
+ }
6
+
7
+ export async function upsertStoreAccuracIssues( query, record ) {
8
+ return await storeAccuracyIssuesModel.updateOne( query, { $set: record }, { upsert: true } );
9
+ }