tango-app-api-trax 1.0.0-alpha.0

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/.eslintrc.cjs ADDED
@@ -0,0 +1,41 @@
1
+
2
+ module.exports = {
3
+ 'env': {
4
+ 'es2021': true,
5
+ 'node': true,
6
+ },
7
+ 'extends': 'google',
8
+ 'overrides': [
9
+ {
10
+ 'env': {
11
+ 'node': true,
12
+ },
13
+ 'files': [
14
+ '.eslintrc.{js,cjs}',
15
+ ],
16
+ 'parserOptions': {
17
+ 'sourceType': 'script',
18
+ },
19
+ },
20
+ ],
21
+ 'parserOptions': {
22
+ 'ecmaVersion': 'latest',
23
+ 'sourceType': 'module',
24
+ },
25
+ 'rules': {
26
+ 'linebreak-style': [ 'error', 'windows' ],
27
+ 'require-jsdoc': 'off',
28
+ 'arrow-spacing': 'error',
29
+ 'key-spacing': [ 'error', { 'beforeColon': false, 'afterColon': true } ],
30
+ 'object-curly-spacing': [ 'error', 'always' ],
31
+ 'space-in-parens': [ 'error', 'always' ],
32
+ 'keyword-spacing': 'error',
33
+ 'array-bracket-spacing': [ 'error', 'always' ],
34
+ 'spaced-comment': [ 'error', 'always' ],
35
+ 'max-len': [ 'error', { 'code': 700 } ],
36
+ 'no-unused-vars': 'error',
37
+ 'new-cap': [ 'error', { 'newIsCap': true, 'capIsNew': false } ],
38
+ 'prefer-const': 'off',
39
+ },
40
+ };
41
+
package/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # README #
2
+
3
+ This README would normally document whatever steps are necessary to get your application up and running.
4
+
5
+ ### What is this repository for? ###
6
+
7
+ * Quick summary
8
+ * Version
9
+ * [Learn Markdown](https://bitbucket.org/tutorials/markdowndemo)
10
+
11
+ ### How do I get set up? ###
12
+
13
+ * Summary of set up
14
+ * Configuration
15
+ * Dependencies
16
+ * Database configuration
17
+ * How to run tests
18
+ * Deployment instructions
19
+
20
+ ### Contribution guidelines ###
21
+
22
+ * Writing tests
23
+ * Code review
24
+ * Other guidelines
25
+
26
+ ### Who do I talk to? ###
27
+
28
+ * Repo owner or admin
29
+ * Other community or team contact
package/index.js ADDED
@@ -0,0 +1,6 @@
1
+
2
+
3
+ import { traxDashboardRouter } from './src/routes/traxDashboard.routes.js';
4
+
5
+ export { traxDashboardRouter };
6
+
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "tango-app-api-trax",
3
+ "version": "1.0.0-alpha.0",
4
+ "description": "Trax",
5
+ "main": "index.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "start": "nodemon --exec \"eslint --fix . && node index.js\""
9
+ },
10
+ "engines": {
11
+ "node": ">=18.10.0"
12
+ },
13
+ "author": "praveenraj",
14
+ "license": "ISC",
15
+ "dependencies": {
16
+ "aws-sdk": "^2.1665.0",
17
+ "dayjs": "^1.11.13",
18
+ "dotenv": "^16.4.5",
19
+ "express": "^4.19.2",
20
+ "handlebars": "^4.7.8",
21
+ "lodash": "^4.17.21",
22
+ "mongodb": "^6.8.0",
23
+ "nodemon": "^3.1.4",
24
+ "tango-api-schema": "^2.1.45",
25
+ "tango-app-api-middleware": "^3.1.41",
26
+ "winston": "^3.13.1",
27
+ "winston-daily-rotate-file": "^5.0.0"
28
+ },
29
+ "devDependencies": {
30
+ "eslint": "^8.57.0",
31
+ "eslint-config-google": "^0.14.0",
32
+ "eslint-config-semistandard": "^17.0.0",
33
+ "eslint-config-standard": "^17.1.0",
34
+ "eslint-plugin-import": "^2.29.1",
35
+ "eslint-plugin-promise": "^6.6.0"
36
+ }
37
+ }
@@ -0,0 +1,402 @@
1
+ import { logger } from 'tango-app-api-middleware';
2
+ import * as processedchecklistService from '../services/processedchecklist.services.js';
3
+
4
+ export const welcome = async ( req, res ) => {
5
+ try {
6
+ let result = {
7
+ 'Message': 'Welcome',
8
+ };
9
+ return res.sendSuccess( result );
10
+ } catch ( error ) {
11
+ logger.error( { error: error, message: req.query, function: 'welcome' } );
12
+ return res.sendError( { error: error }, 500 );
13
+ }
14
+ };
15
+
16
+ export const overallCards = async ( req, res ) => {
17
+ try {
18
+ let reqestData = req.body;
19
+ let fromDate = new Date( reqestData.fromDate );
20
+ let toDate = new Date( reqestData.toDate );
21
+ let userTimezoneOffset = toDate.getTimezoneOffset() * 60000;
22
+ toDate = new Date( toDate.getTime() - userTimezoneOffset );
23
+ toDate.setUTCHours( 23, 59, 59, 59 );
24
+ let activeUnique = 0;
25
+ let total = 0;
26
+ let notSubmitted = 0;
27
+ let open = 0;
28
+ let inprogress = 0;
29
+ let submitted = 0;
30
+ let totalFlags = {
31
+ 'count': '',
32
+ 'comparisonData': '',
33
+ 'ComparisonFlag': '',
34
+ };
35
+ let completionScore = {
36
+ 'count': '',
37
+ 'comparisonData': '',
38
+ 'ComparisonFlag': '',
39
+ };
40
+ let complianceScore = {
41
+ 'count': '',
42
+ 'comparisonData': '',
43
+ 'ComparisonFlag': '',
44
+ };
45
+ let result = {};
46
+
47
+ let overallChecklistDataQuery = [
48
+ {
49
+ $match: {
50
+ client_id: reqestData.clientId,
51
+ $and: [
52
+ { store_id: { $in: reqestData.storeId } },
53
+ { date_iso: { $gte: fromDate } },
54
+ { date_iso: { $lte: toDate } },
55
+ ],
56
+ },
57
+ },
58
+ {
59
+ $project: {
60
+ sourceCheckList_id: 1,
61
+ checkListId: 1,
62
+ checklistStatus: 1,
63
+ timeFlag: 1,
64
+ questionFlag: 1,
65
+ mobileDetectionFlag: 1,
66
+ storeOpenCloseFlag: 1,
67
+ uniformDetectionFlag: 1,
68
+ markasread: 1,
69
+ checkListType: 1,
70
+ },
71
+ },
72
+ {
73
+ $group: {
74
+ _id: '',
75
+ totalChecklist: { $sum: 1 },
76
+ notSubmittedChecklist: {
77
+ $sum: {
78
+ $cond: [
79
+ {
80
+ $and: [
81
+ { $ne: [ '$checklistStatus', 'submit' ] },
82
+ ],
83
+ }, 1, 0 ],
84
+ },
85
+ },
86
+ openChecklist: {
87
+ $sum: {
88
+ $cond: [
89
+ {
90
+ $and: [
91
+ { $eq: [ '$checklistStatus', 'open' ] },
92
+ ],
93
+ }, 1, 0 ],
94
+ },
95
+ },
96
+ inprogressChecklist: {
97
+ $sum: {
98
+ $cond: [
99
+ {
100
+ $and: [
101
+ { $eq: [ '$checklistStatus', 'inprogress' ] },
102
+ ],
103
+ }, 1, 0 ],
104
+ },
105
+ },
106
+ submittedChecklist: {
107
+ $sum: {
108
+ $cond: [
109
+ {
110
+ $and: [
111
+ { $eq: [ '$checklistStatus', 'submit' ] },
112
+ ],
113
+ }, 1, 0 ],
114
+ },
115
+ },
116
+ flaggedChecklist: {
117
+ $sum: {
118
+ $cond: [ {
119
+ $or: [
120
+ { $gt: [ '$timeFlag', 0 ] },
121
+ { $gt: [ '$mobileDetectionFlag', 0 ] },
122
+ { $gt: [ '$storeOpenCloseFlag', 0 ] },
123
+ { $gt: [ '$uniformDetectionFlag', 0 ] },
124
+ ],
125
+ }, 1, 0 ],
126
+ },
127
+ },
128
+ },
129
+ },
130
+ ];
131
+ let getOverallChecklistData = await processedchecklistService.aggregate( overallChecklistDataQuery );
132
+ let uniqueChecklistDataQuery = [
133
+ {
134
+ $match: {
135
+ client_id: reqestData.clientId,
136
+ $and: [
137
+ { store_id: { $in: reqestData.storeId } },
138
+ { date_iso: { $gte: fromDate } },
139
+ { date_iso: { $lte: toDate } },
140
+ ],
141
+ },
142
+ },
143
+ {
144
+ $project: {
145
+ sourceCheckList_id: 1,
146
+ },
147
+ },
148
+ {
149
+ $group: {
150
+ _id: '$sourceCheckList_id',
151
+ },
152
+ },
153
+ {
154
+ $count: 'totalUniqueChecklist',
155
+ },
156
+ ];
157
+ let getUniqueChecklistData = await processedchecklistService.aggregate( uniqueChecklistDataQuery );
158
+ if ( !getUniqueChecklistData.length && !getOverallChecklistData.length ) {
159
+ return res.sendError( { error: 'No Data Found' }, 204 );
160
+ }
161
+
162
+ if ( getUniqueChecklistData.length && getUniqueChecklistData.length>0 ) {
163
+ if ( getUniqueChecklistData[0].totalUniqueChecklist ) {
164
+ activeUnique = getUniqueChecklistData[0]?.totalUniqueChecklist;
165
+ }
166
+ }
167
+
168
+ if ( getOverallChecklistData.length && getOverallChecklistData.length>0 ) {
169
+ if ( getOverallChecklistData[0].totalChecklist ) {
170
+ total = getOverallChecklistData[0]?.totalChecklist;
171
+ }
172
+ if ( getOverallChecklistData[0].notSubmittedChecklist ) {
173
+ notSubmitted = getOverallChecklistData[0]?.notSubmittedChecklist;
174
+ }
175
+ if ( getOverallChecklistData[0].openChecklist ) {
176
+ open = getOverallChecklistData[0]?.openChecklist;
177
+ }
178
+ if ( getOverallChecklistData[0].inprogressChecklist ) {
179
+ inprogress = getOverallChecklistData[0]?.inprogressChecklist;
180
+ }
181
+ if ( getOverallChecklistData[0].submittedChecklist ) {
182
+ submitted = getOverallChecklistData[0]?.submittedChecklist;
183
+ }
184
+ if ( getOverallChecklistData[0].flaggedChecklist ) {
185
+ totalFlags.count = getOverallChecklistData[0]?.flaggedChecklist;
186
+ }
187
+ }
188
+
189
+ result.overallCards = {
190
+ 'activeUnique': activeUnique,
191
+ 'total': total,
192
+ 'notSubmitted': notSubmitted,
193
+ 'open': open,
194
+ 'inprogress': inprogress,
195
+ 'submitted': submitted,
196
+ 'totalFlags': totalFlags,
197
+ 'completionScore': completionScore,
198
+ 'complianceScore': complianceScore,
199
+ };
200
+ return res.sendSuccess( result );
201
+ } catch ( error ) {
202
+ logger.error( { error: error, message: req.query, function: 'overallCards' } );
203
+ return res.sendError( { error: error }, 500 );
204
+ }
205
+ };
206
+
207
+ export const checklistPerformance = async ( req, res ) => {
208
+ try {
209
+ let reqestData = req.body;
210
+ let fromDate = new Date( reqestData.fromDate );
211
+ let toDate = new Date( reqestData.toDate );
212
+ let userTimezoneOffset = toDate.getTimezoneOffset() * 60000;
213
+ toDate = new Date( toDate.getTime() - userTimezoneOffset );
214
+ toDate.setUTCHours( 23, 59, 59, 59 );
215
+ let result = {};
216
+
217
+ let findQuery = [];
218
+ let findAndQuery = [];
219
+ findAndQuery.push(
220
+ { client_id: reqestData.clientId },
221
+ { store_id: { $in: reqestData.storeId } },
222
+ { date_iso: { $gte: fromDate } },
223
+ { date_iso: { $lte: toDate } },
224
+ );
225
+
226
+ findQuery.push( { $match: { $and: findAndQuery } } );
227
+
228
+ if ( reqestData.searchValue && reqestData.searchValue != '' ) {
229
+ findQuery.push( { $match: { $or: [ { checkListName: { $regex: reqestData.searchValue, $options: 'i' } } ] } } );
230
+ }
231
+
232
+ findQuery.push( {
233
+ $project: {
234
+ sourceCheckList_id: 1,
235
+ checkListId: 1,
236
+ checkListName: 1,
237
+ storeCount: 1,
238
+ createdBy: 1,
239
+ createdByName: 1,
240
+ checklistStatus: 1,
241
+ timeFlag: 1,
242
+ questionFlag: 1,
243
+ mobileDetectionFlag: 1,
244
+ storeOpenCloseFlag: 1,
245
+ uniformDetectionFlag: 1,
246
+ checkListType: 1,
247
+ scheduleRepeatedType: 1,
248
+ },
249
+ } );
250
+
251
+ findQuery.push( {
252
+ $group: {
253
+ _id: '$sourceCheckList_id',
254
+ sourceCheckList_id: { $last: '$sourceCheckList_id' },
255
+ checkListName: { $last: '$checkListName' },
256
+ checkListChar: { $last: { $substr: [ '$checkListName', 0, 2 ] } },
257
+ scheduleRepeatedType: { $last: '$scheduleRepeatedType' },
258
+ storeCount: { $max: '$storeCount' },
259
+ submittedChecklist: {
260
+ $sum: {
261
+ $cond: [ { $eq: [ '$checklistStatus', 'submit' ] }, 1, 0 ],
262
+ },
263
+ },
264
+ flaggedChecklist: {
265
+ $sum: {
266
+ $cond: [ {
267
+ $or: [
268
+ { $gt: [ '$timeFlag', 0 ] },
269
+ { $gt: [ '$questionFlag', 0 ] },
270
+ { $gt: [ '$mobileDetectionFlag', 0 ] },
271
+ { $gt: [ '$storeOpenCloseFlag', 0 ] },
272
+ { $gt: [ '$uniformDetectionFlag', 0 ] },
273
+ ],
274
+ }, 1, 0 ],
275
+ },
276
+ },
277
+ checkListType: { $last: '$checkListType' },
278
+ },
279
+ } );
280
+
281
+ let getTotalCount = await processedchecklistService.aggregate( findQuery );
282
+ if ( !getTotalCount.length ) {
283
+ return res.sendError( { error: 'No Data Found' }, 204 );
284
+ }
285
+
286
+ if ( reqestData.sortColumnName && reqestData.sortColumnName != '' && reqestData.sortBy && reqestData.sortBy !='' ) {
287
+ findQuery.push( { $sort: { [reqestData.sortColumnName]: reqestData.sortBy } } );
288
+ } else {
289
+ findQuery.push( { $sort: { ['submittedChecklist']: -1 } } );
290
+ }
291
+
292
+ let limit = parseInt( reqestData?.limit ) || 10;
293
+ let skip = limit * ( reqestData?.offset ) || 0;
294
+ findQuery.push( { $skip: skip }, { $limit: limit } );
295
+ let getChecklistPerformanceData = await processedchecklistService.aggregate( findQuery );
296
+
297
+ result.totalCount = getTotalCount.length;
298
+ result.checklistPerformance = getChecklistPerformanceData;
299
+ return res.sendSuccess( result );
300
+ } catch ( error ) {
301
+ console.log( 'error =>', error );
302
+ logger.error( { error: error, message: req.query, function: 'checklistPerformance' } );
303
+ return res.sendError( { error: error }, 500 );
304
+ }
305
+ };
306
+
307
+ export const storePerformance = async ( req, res ) => {
308
+ try {
309
+ let reqestData = req.body;
310
+ let fromDate = new Date( reqestData.fromDate );
311
+ let toDate = new Date( reqestData.toDate );
312
+ let userTimezoneOffset = toDate.getTimezoneOffset() * 60000;
313
+ toDate = new Date( toDate.getTime() - userTimezoneOffset );
314
+ toDate.setUTCHours( 23, 59, 59, 59 );
315
+ let result = {};
316
+
317
+ let checklistPerformanceQuery = [
318
+ {
319
+ $match: {
320
+ client_id: reqestData.clientId,
321
+ $and: [
322
+ { store_id: { $in: reqestData.storeId } },
323
+ { date_iso: { $gte: fromDate } },
324
+ { date_iso: { $lte: toDate } },
325
+ ],
326
+ },
327
+ },
328
+ {
329
+ $project: {
330
+ sourceCheckList_id: 1,
331
+ checkListId: 1,
332
+ checkListName: 1,
333
+ storeCount: 1,
334
+ createdBy: 1,
335
+ createdByName: 1,
336
+ checklistStatus: 1,
337
+ timeFlag: 1,
338
+ questionFlag: 1,
339
+ mobileDetectionFlag: 1,
340
+ storeOpenCloseFlag: 1,
341
+ uniformDetectionFlag: 1,
342
+ checkListType: 1,
343
+ scheduleRepeatedType: 1,
344
+ store_id: 1,
345
+ storeName: 1,
346
+ userEmail: 1,
347
+ },
348
+ },
349
+ {
350
+ $group: {
351
+ _id: '$store_id',
352
+ storeName: { $last: '$storeName' },
353
+ userEmail: { $last: '$userEmail' },
354
+ checkListCount: { $sum: '$store_id' },
355
+ flaggedChecklist: {
356
+ $sum: {
357
+ $cond: [ {
358
+ $or: [
359
+ { $gt: [ '$timeFlag', 0 ] },
360
+ { $gt: [ '$questionFlag', 0 ] },
361
+ { $gt: [ '$mobileDetectionFlag', 0 ] },
362
+ { $gt: [ '$storeOpenCloseFlag', 0 ] },
363
+ { $gt: [ '$uniformDetectionFlag', 0 ] },
364
+ ],
365
+ }, 1, 0 ],
366
+ },
367
+ },
368
+ submittedChecklist: {
369
+ $sum: {
370
+ $cond: [ { $eq: [ '$checklistStatus', 'submit' ] }, 1, 0 ],
371
+ },
372
+ },
373
+ checkListType: { $last: '$checkListType' },
374
+ },
375
+ },
376
+ ];
377
+
378
+ let getTotalCount = await processedchecklistService.aggregate( checklistPerformanceQuery );
379
+ if ( !getTotalCount.length ) {
380
+ return res.sendError( { error: 'No Data Found' }, 204 );
381
+ }
382
+
383
+ if ( reqestData.sortColumnName && reqestData.sortColumnName != '' && reqestData.sortBy && reqestData.sortBy !='' ) {
384
+ checklistPerformanceQuery.push( { $sort: { [reqestData.sortColumnName]: reqestData.sortBy } } );
385
+ } else {
386
+ checklistPerformanceQuery.push( { $sort: { ['submittedChecklist']: -1 } } );
387
+ }
388
+
389
+ let limit = parseInt( reqestData?.limit ) || 10;
390
+ let skip = limit * ( reqestData?.offset ) || 0;
391
+ checklistPerformanceQuery.push( { $skip: skip }, { $limit: limit } );
392
+ let getChecklistPerformanceData = await processedchecklistService.aggregate( checklistPerformanceQuery );
393
+
394
+ result.totalCount = getTotalCount.length;
395
+ result.checklistPerformance = getChecklistPerformanceData;
396
+ return res.sendSuccess( result );
397
+ } catch ( error ) {
398
+ console.log( 'error =>', error );
399
+ logger.error( { error: error, message: req.query, function: 'storePerformance' } );
400
+ return res.sendError( { error: error }, 500 );
401
+ }
402
+ };
@@ -0,0 +1,226 @@
1
+ import joi from 'joi';
2
+
3
+ // Base schema
4
+ const baseSchema = {
5
+ clientId: joi.string().required(),
6
+ storeId: joi.array().required().empty(),
7
+ fromDate: joi.string().required(),
8
+ toDate: joi.string().required(),
9
+ valueType: joi.string().optional().allow( '' ),
10
+ nob: joi.boolean().optional().allow( '' ),
11
+ };
12
+
13
+ // Schema for Card Funnel
14
+ export const validateCardFunnelSchema = joi.object( {
15
+ ...baseSchema,
16
+ } );
17
+
18
+ export const validateCardFunnelParams = {
19
+ body: validateCardFunnelSchema,
20
+ };
21
+
22
+ // Schema for Card Graph (extends baseSchema with additional fields)
23
+ export const validateCardGraphSchema = joi.object( {
24
+ ...baseSchema,
25
+ dateType: joi.string().required(),
26
+ } );
27
+
28
+ export const validateCardGraphParams = {
29
+ body: validateCardGraphSchema,
30
+ };
31
+
32
+ export const validateRecapVideoSchema = joi.object( {
33
+ clientId: joi.string().required(),
34
+ storeId: joi.array().required().empty(),
35
+ recapVideoDate: joi.string().required(),
36
+ valueType: joi.string().optional().allow( '' ),
37
+ nob: joi.boolean().optional().allow( '' ),
38
+ } );
39
+
40
+ export const validateRecapVideoParams = {
41
+ body: validateRecapVideoSchema,
42
+ };
43
+
44
+ export const validateDensityDwellSchema = joi.object( {
45
+ ...baseSchema,
46
+ dateRange: joi.number().required(),
47
+ } );
48
+
49
+ export const validateDensityDwellParams = {
50
+ body: validateDensityDwellSchema,
51
+ };
52
+
53
+ export const validateOverallCardsSchema = joi.object( {
54
+ ...baseSchema,
55
+ revenue: joi.number().required(),
56
+ processType: joi.string().required(),
57
+ } );
58
+
59
+ export const validateOverallCardsParams = {
60
+ body: validateOverallCardsSchema,
61
+ };
62
+
63
+ export const validateOverallHourlyChartSchema = joi.object( {
64
+ ...baseSchema,
65
+ processType: joi.string().required(),
66
+ } );
67
+
68
+ export const validateOverallHourlyChartParams = {
69
+ body: validateOverallHourlyChartSchema,
70
+ };
71
+
72
+ export const validateOverallCharSchema = joi.object( {
73
+ ...baseSchema,
74
+ limit: joi.number().required(),
75
+ offset: joi.number().required(),
76
+ processType: joi.string().required(),
77
+ } );
78
+
79
+ export const validateOverallCharParams = {
80
+ body: validateOverallCharSchema,
81
+ };
82
+
83
+ export const validateSingleStoreChartSchema = joi.object( {
84
+ ...baseSchema,
85
+ limit: joi.number().required(),
86
+ offset: joi.number().required(),
87
+ processType: joi.string().required(),
88
+ } );
89
+
90
+ export const validateSingleStoreChartParams = {
91
+ body: validateSingleStoreChartSchema,
92
+ };
93
+
94
+ export const validateDemographicChartSchema = joi.object( {
95
+ ...baseSchema,
96
+ processType: joi.string().required(),
97
+ } );
98
+
99
+ export const validateDemographicChartParams = {
100
+ body: validateDemographicChartSchema,
101
+ };
102
+
103
+ export const validateBuyerChartSchema = joi.object( {
104
+ ...baseSchema,
105
+ processType: joi.string().required(),
106
+ } );
107
+
108
+ export const validateBuyerChartParams = {
109
+ body: validateBuyerChartSchema,
110
+ };
111
+
112
+ export const validateFootfallDirectoryFoldersSchema = joi.object( {
113
+ clientId: joi.string().required(),
114
+ storeId: joi.array().required().empty(),
115
+ footfallDate: joi.string().required(),
116
+ processType: joi.string().required(),
117
+ valueType: joi.string().optional().allow( '' ),
118
+ nob: joi.boolean().optional().allow( '' ),
119
+ } );
120
+
121
+ export const validateFootfallDirectoryFoldersParams = {
122
+ body: validateFootfallDirectoryFoldersSchema,
123
+ };
124
+
125
+ export const validateFootfallDirectorySchema = joi.object( {
126
+ clientId: joi.string().required(),
127
+ storeId: joi.array().required().empty(),
128
+ footfallDate: joi.string().required(),
129
+ processType: joi.string().required(),
130
+ folderName: joi.string().required(),
131
+ valueType: joi.string().optional().allow( '' ),
132
+ nob: joi.boolean().optional().allow( '' ),
133
+ } );
134
+
135
+ export const validateFootfallDirectoryParams = {
136
+ body: validateFootfallDirectorySchema,
137
+ };
138
+
139
+ export const validateSummaryTableSchema = joi.object( {
140
+ ...baseSchema,
141
+ valueType: joi.string().required(),
142
+ search: joi.string().optional().allow( '' ),
143
+ sortBy: joi.number().optional().allow( '' ),
144
+ sort: joi.string().optional().allow( '' ),
145
+ limit: joi.number().required(),
146
+ offset: joi.number().required(),
147
+ export: joi.boolean().required(),
148
+ } );
149
+
150
+ export const validateSummaryTableParams = {
151
+ body: validateSummaryTableSchema,
152
+ };
153
+
154
+ export const validateFootfallTrendSchema = joi.object( {
155
+ ...baseSchema,
156
+ dateType: joi.string().required(),
157
+ filterBy: joi.string().required(),
158
+ processType: joi.string().optional().allow( '' ),
159
+ forecast: joi.boolean().optional(),
160
+ limit: joi.number().required(),
161
+ offset: joi.number().required(),
162
+ sortBy: joi.number().optional().allow( '' ),
163
+ sort: joi.string().optional().allow( '' ),
164
+ } );
165
+
166
+ export const validateFootfallTrendParams = {
167
+ body: validateFootfallTrendSchema,
168
+ };
169
+
170
+ export const validateStoreOperationSchema = joi.object( {
171
+ ...baseSchema,
172
+ } );
173
+
174
+ export const validateStoreOperationParams = {
175
+ body: validateStoreOperationSchema,
176
+ };
177
+
178
+ export const validateStoresMapSchema = joi.object( {
179
+ clientId: joi.string().required(),
180
+ storeId: joi.array().required().empty(),
181
+ storeDate: joi.string().required(),
182
+ nob: joi.boolean().optional().allow( '' ),
183
+ } );
184
+
185
+ export const validateStoresMapParams = {
186
+ body: validateStoresMapSchema,
187
+ };
188
+
189
+ export const validateperformanceMatrixSchema = joi.object( {
190
+ ...baseSchema,
191
+ processtype1: joi.string().required(),
192
+ processtype2: joi.string().required(),
193
+ } );
194
+
195
+ export const validateperformanceMatrixParams = {
196
+ body: validateperformanceMatrixSchema,
197
+ };
198
+
199
+ export const validateHeaderSchema = joi.object( {
200
+ clientId: joi.string().required(),
201
+ city: joi.array().required(),
202
+ group: joi.array().required(),
203
+ } );
204
+
205
+ export const validateHeaderParams = {
206
+ body: validateHeaderSchema,
207
+ };
208
+
209
+ export const getMyProductSchema = joi.object( {
210
+ clientId: joi.string().required(),
211
+ storeId: joi.array().optional().empty(),
212
+ } );
213
+
214
+ export const getMyProductParams = {
215
+ body: getMyProductSchema,
216
+ };
217
+
218
+ export const getStoreCameraImageSchema = joi.object( {
219
+ clientId: joi.string().required(),
220
+ storeId: joi.array().optional().empty(),
221
+ storeDate: joi.string().required(),
222
+ } );
223
+
224
+ export const getStoreCameraImageParams = {
225
+ body: getStoreCameraImageSchema,
226
+ };
@@ -0,0 +1,21 @@
1
+ import express from 'express';
2
+ // import { validate, isAllowedSessionHandler, authorize, isAllowedClient } from 'tango-app-api-middleware';
3
+ // import * as validationDtos from '../dtos/validation.dtos.js';
4
+
5
+ export const traxDashboardRouter = express.Router();
6
+
7
+ import {
8
+ welcome,
9
+ overallCards,
10
+ checklistPerformance,
11
+ storePerformance,
12
+ } from '../controllers/traxDashboard.controllers.js';
13
+
14
+ traxDashboardRouter
15
+ .get( '/welcome', welcome )
16
+ .post( '/overallCards', overallCards )
17
+ .post( '/checklistPerformance', checklistPerformance )
18
+ .post( '/storePerformance', storePerformance )
19
+ .post( '/userPerformance', overallCards );
20
+
21
+ export default traxDashboardRouter;
@@ -0,0 +1,23 @@
1
+ import model from 'tango-api-schema';
2
+
3
+ export const find = ( query = {}, record = {} ) => {
4
+ return model.clientModel.find( query, record );
5
+ };
6
+
7
+ export const findOne = ( query = {}, record = {} ) => {
8
+ return model.clientModel.findOne( query, record ).sort( { updatedAt: -1 } );
9
+ };
10
+
11
+ export const updateOne = ( query = {}, record = {} ) => {
12
+ return model.clientModel.updateOne( query, { $set: record } );
13
+ };
14
+
15
+ export const aggregate = ( query = [] ) => {
16
+ return model.clientModel.aggregate( query );
17
+ };
18
+
19
+ export const getClientCount = ( query = {} ) => {
20
+ return model.clientModel.count( query );
21
+ };
22
+
23
+
@@ -0,0 +1,23 @@
1
+ import model from 'tango-api-schema';
2
+
3
+ export const find = ( query = {}, record = {} ) => {
4
+ return model.processedchecklistModel.find( query, record );
5
+ };
6
+
7
+ export const findOne = ( query = {}, record = {} ) => {
8
+ return model.processedchecklistModel.findOne( query, record ).sort( { updatedAt: -1 } );
9
+ };
10
+
11
+ export const updateOne = ( query = {}, record = {} ) => {
12
+ return model.processedchecklistModel.updateOne( query, { $set: record } );
13
+ };
14
+
15
+ export const aggregate = ( query = [] ) => {
16
+ return model.processedchecklistModel.aggregate( query );
17
+ };
18
+
19
+ export const getClientCount = ( query = {} ) => {
20
+ return model.processedchecklistModel.count( query );
21
+ };
22
+
23
+
@@ -0,0 +1,23 @@
1
+ import model from 'tango-api-schema';
2
+
3
+ export const find = ( query = {}, record = {} ) => {
4
+ return model.processedchecklistconfigModel.find( query, record );
5
+ };
6
+
7
+ export const findOne = ( query = {}, record = {} ) => {
8
+ return model.processedchecklistconfigModel.findOne( query, record ).sort( { updatedAt: -1 } );
9
+ };
10
+
11
+ export const updateOne = ( query = {}, record = {} ) => {
12
+ return model.processedchecklistconfigModel.updateOne( query, { $set: record } );
13
+ };
14
+
15
+ export const aggregate = ( query = [] ) => {
16
+ return model.processedchecklistconfigModel.aggregate( query );
17
+ };
18
+
19
+ export const getClientCount = ( query = {} ) => {
20
+ return model.processedchecklistconfigModel.count( query );
21
+ };
22
+
23
+