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

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,7 @@ export const downloadTicketsValid = {
442
515
 
443
516
  export const reviewerListSchema = Joi.object().keys( {
444
517
  clientId: Joi.string().required(),
518
+ type: Joi.string().required().allow( 'approve', 'review' ),
445
519
  } );
446
520
 
447
521
  export const reviewerListValid = {
@@ -454,6 +528,9 @@ export const openTicketListSchema = Joi.object().keys( {
454
528
  clientId: Joi.array().items(
455
529
  Joi.string().required(),
456
530
  ).required(),
531
+ type: Joi.string().required().allow( 'review', 'approve' ),
532
+ sortOrder: Joi.number().valid( 1, -1 ).optional(),
533
+ searchValue: Joi.string().allow( '' ).optional(),
457
534
 
458
535
 
459
536
  } );
@@ -468,7 +545,8 @@ export const assignTicketSchema = Joi.object().keys( {
468
545
  userName: Joi.string().optional(),
469
546
  role: Joi.string().optional(),
470
547
  actionType: Joi.string().required(),
471
- ticketId: Joi.string().required(),
548
+ storeId: Joi.string().required(),
549
+ dateString: Joi.string().required(),
472
550
 
473
551
 
474
552
  } );
@@ -480,7 +558,8 @@ export const assignTicketValid = {
480
558
  export const updateTempStatusSchema = Joi.object().keys( {
481
559
  id: Joi.array().items( Joi.string().required() ).required(),
482
560
  status: Joi.string().required(),
483
- type: Joi.string().required(),
561
+ type: Joi.string().required().allow( 'review', 'approve' ),
562
+ comments: Joi.string().optional().allow( '' ),
484
563
 
485
564
 
486
565
  } );
@@ -488,3 +567,52 @@ export const updateTempStatusSchema = Joi.object().keys( {
488
567
  export const updateTempStatusValid = {
489
568
  body: updateTempStatusSchema,
490
569
  };
570
+
571
+ export const updateTicketStatusSchema = Joi.object().keys( {
572
+ storeId: Joi.string().required(),
573
+ dateString: Joi.string().required(),
574
+ mode: Joi.string().required(),
575
+
576
+ } );
577
+
578
+ export const updateTicketStatusValid = {
579
+ body: updateTicketStatusSchema,
580
+ };
581
+
582
+ export const multiCloseTicketSchema = Joi.object().keys( {
583
+
584
+ ticketList: Joi.array().items( Joi.object().keys( {
585
+ storeId: Joi.string().required(),
586
+ dateString: Joi.string().required(),
587
+ } ) ),
588
+ mode: Joi.string().required(),
589
+
590
+ } );
591
+
592
+ export const multiCloseTicketValid = {
593
+ body: multiCloseTicketSchema,
594
+ };
595
+
596
+
597
+ export const getAccuracyIssuesSchema = Joi.object().keys( {
598
+
599
+
600
+ clientId: Joi.string().required(),
601
+
602
+ } );
603
+
604
+ export const getAccuracyIssuesValid = {
605
+ query: getAccuracyIssuesSchema,
606
+ };
607
+
608
+ export const updateAccuracyIssuesSchema = Joi.object().keys( {
609
+
610
+
611
+ clientId: Joi.string().required(),
612
+ issueName: Joi.string().required(),
613
+
614
+ } );
615
+
616
+ export const updateAccuracyIssuesValid = {
617
+ query: updateAccuracyIssuesSchema,
618
+ };
@@ -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
+ }