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.
- package/package.json +3 -2
- package/src/controllers/footfallDirectory.controllers.js +3780 -693
- package/src/dtos/footfallDirectory.dtos.js +189 -60
- package/src/routes/footfallDirectory.routes.js +15 -5
- package/src/services/storeAccuracyIssues.service.js +9 -0
- package/src/validations/footfallDirectory.validation.js +1803 -90
|
@@ -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().
|
|
159
|
-
fromDate: Joi.string()
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
toDate: Joi.string()
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
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
|
-
} )
|
|
201
|
-
|
|
202
|
-
|
|
272
|
+
} );
|
|
273
|
+
// .custom( ( value, helpers ) => {
|
|
274
|
+
// const from = dayjs( value.fromDate );
|
|
275
|
+
// const to = dayjs( value.toDate );
|
|
203
276
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
277
|
+
// if ( !from.isValid() || !to.isValid() ) {
|
|
278
|
+
// return helpers.error( 'any.invalid', { message: 'Invalid dates' } );
|
|
279
|
+
// }
|
|
207
280
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
281
|
+
// if ( from.isAfter( to ) ) {
|
|
282
|
+
// return helpers.error( 'any.invalid', { message: 'fromDate cannot be after toDate' } );
|
|
283
|
+
// }
|
|
211
284
|
|
|
212
|
-
|
|
213
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
}
|