tango-app-api-report 3.0.2-dev → 3.0.4-dev

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tango-app-api-report",
3
- "version": "3.0.2-dev",
3
+ "version": "3.0.4-dev",
4
4
  "description": "report",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -19,11 +19,12 @@
19
19
  "express": "^4.18.3",
20
20
  "express-fileupload": "^1.5.0",
21
21
  "handlebars": "^4.7.8",
22
+ "joi-to-swagger": "^6.2.0",
22
23
  "mongodb": "^6.5.0",
23
24
  "nodemon": "^3.1.0",
24
25
  "swagger-ui-express": "^5.0.0",
25
- "tango-api-schema": "^2.0.92",
26
- "tango-app-api-middleware": "^1.0.60-dev",
26
+ "tango-api-schema": "^2.0.103",
27
+ "tango-app-api-middleware": "^1.0.77-dev",
27
28
  "winston": "^3.12.0",
28
29
  "winston-daily-rotate-file": "^5.0.0"
29
30
  },
@@ -1,6 +1,9 @@
1
- import { reportCreate, reportGet, reportGetSingle, reportUpdate } from '../service/report.service.js';
2
- import { insertOpenSearchData, logger } from 'tango-app-api-middleware';
3
- import { getUserNameEmailById } from '../service/user.service.js';
1
+ import { findOneReport, findReport, reportCreate, reportGet, reportGetSingle, reportUpdate } from '../service/report.service.js';
2
+ import { appConfig, fileUpload, getObject, insertOpenSearchData, listFoldersByPath, logger, sendMessageToQueue } from 'tango-app-api-middleware';
3
+ import { findOneUser, getUserNameEmailById } from '../service/user.service.js';
4
+ import { updateOneBasePriceModel } from '../service/basePrice.service.js';
5
+ import { aggregateClient } from '../service/client.service.js';
6
+ // import basePricingModel from 'tango-api-schema/schema/basePricing.model.js';
4
7
 
5
8
 
6
9
  export async function createReport( req, res ) {
@@ -88,3 +91,391 @@ export async function updateReport( req, res ) {
88
91
  return res.sendError( error, 500 );
89
92
  }
90
93
  }
94
+
95
+ export async function clientReportList( req, res ) {
96
+ try {
97
+ const inputData = req.body;
98
+ const limit = inputData.limit || 10;
99
+ const offset = inputData.offset? ( inputData.offset - 1 ) * inputData.limit : 0;
100
+ logger.info( { inputData: inputData } );
101
+ const daysDifference = Math.ceil( ( new Date( inputData.toDate ) - new Date( inputData.fromDate ) ) / ( 24 * 60 * 60 * 1000 ) );
102
+ logger.info( { daysDifference: daysDifference, value: ( new Date( inputData.toDate ) - new Date( inputData.fromDate ) ) / ( 24 * 60 * 60 * 1000 ), fromdate: inputData.fromDate, toDate: inputData.toDate } );
103
+ const query = [
104
+ {
105
+ $match: {
106
+ $and: [
107
+ { 'reportConfigs.report': { $eq: true } },
108
+ { clientId: { $in: inputData.clientId } },
109
+ ],
110
+
111
+ },
112
+ },
113
+ {
114
+ $project: {
115
+ clientId: 1,
116
+ tangoId: 1,
117
+ clientName: 1,
118
+ daysDifference: 1,
119
+ datesArray: {
120
+ $map: {
121
+ input: { $range: [ 0, { $toInt: daysDifference+1 } ] },
122
+ as: 'day',
123
+ in: { $add: [ new Date( inputData.fromDate ), { $multiply: [ '$$day', 1000 * 60 * 60 * 24 ] } ] },
124
+ },
125
+ },
126
+ },
127
+ },
128
+ {
129
+ $unwind: '$datesArray',
130
+ },
131
+ {
132
+ $sort: {
133
+ datesArray: -1,
134
+ },
135
+ },
136
+
137
+ {
138
+ $project: {
139
+ clientId: 1,
140
+ clientName: 1,
141
+ tangoId: 1,
142
+ fileDate: '$datesArray',
143
+ },
144
+ },
145
+ ];
146
+ if ( inputData.searchValue ) {
147
+ query.push(
148
+ {
149
+ $match: {
150
+ $or: [
151
+ {
152
+ clientName: { $regex: inputData.searchValue, $options: 'i' },
153
+ },
154
+ {
155
+ clientId: { $regex: inputData.searchValue, $options: 'i' },
156
+
157
+ },
158
+ ],
159
+ },
160
+ },
161
+ );
162
+ }
163
+ if ( inputData.sortColumnName ) {
164
+ const sortBy = inputData.sortBy || -1;
165
+ const sortColumnName =inputData.sortColumnName == 'clientId'? 'tangoId': inputData.sortColumnName;
166
+ query.push( {
167
+ $sort: { [sortColumnName]: sortBy },
168
+ } );
169
+ }
170
+ const count = await aggregateClient( query );
171
+ if ( count?.length == 0 ) {
172
+ return res.sendError( 'No Data Found', 204 );
173
+ }
174
+
175
+ query.push(
176
+ { $skip: offset },
177
+ { $limit: limit },
178
+ );
179
+ const result = await aggregateClient( query );
180
+ res.sendSuccess( { result: result, count: count?.length } );
181
+ } catch ( error ) {
182
+ logger.info( { error: error, message: req.body, function: 'clientReportList' } );
183
+ return res.sendError( 'Internal Server Error', 500 );
184
+ }
185
+ }
186
+
187
+ export async function generateReport( req, res ) {
188
+ try {
189
+ const inputData = req.body;
190
+ const sqsProduceQueue = {
191
+ QueueUrl: `${appConfig.cloud.aws.sqs.url}${appConfig.cloud.aws.sqs.generateReport}`,
192
+ MessageBody: JSON.stringify( {
193
+ file_date: inputData.fileDate,
194
+ client_name: inputData.getReportName?.reportName,
195
+ client_id: Number( inputData.clientId ),
196
+ message: 'good to trigger',
197
+ } ),
198
+ };
199
+ const sqsQueue = await sendMessageToQueue( sqsProduceQueue.QueueUrl, sqsProduceQueue.MessageBody );
200
+ if ( sqsQueue.MessageId ) {
201
+ const log = {
202
+ userName: req.user.userName,
203
+ Date: new Date(),
204
+ userId: req.user._id,
205
+ logType: 'report',
206
+ logSubType: 'generateReport',
207
+ logData: {
208
+ clientName: inputData.getReportName?.clientName,
209
+ fileDate: inputData.fileDate,
210
+ reportName: inputData.getReportName?.reportName,
211
+ clientId: inputData.ClientId,
212
+ sqsMessageId: sqsQueue.MessageId,
213
+ },
214
+ };
215
+ await insertOpenSearchData( 'tango-retail-activity-logs', log );
216
+
217
+ return res.sendSuccess( { result: 'Report has been Initiated Sucessfully' } );
218
+ }
219
+ } catch ( error ) {
220
+ const err = error.code || 'Internal Server Error';
221
+ logger.error( { error: error, message: req.body, function: 'generateReport' } );
222
+ return res.sendError( err, 500 );
223
+ }
224
+ }
225
+
226
+ export async function uploadManualReport( req, res ) {
227
+ try {
228
+ const inputData = req.body;
229
+ const name = inputData.fileName;
230
+ const regex = /^(\d{2}-\d{2}-\d{4})_(.*?)\.([a-zA-Z0-9]+)$/;
231
+ const matches = name.match( regex );
232
+ if ( matches ) {
233
+ const date = matches[1];
234
+ const filenameWithoutExtension = matches[2];
235
+ const extension = matches[3];
236
+ if ( inputData.fileDate !== date ) {
237
+ return res.sendError( 'File Date is Incorrect in the File Name', 400 );
238
+ }
239
+ const query = {
240
+ 'fileName': filenameWithoutExtension,
241
+ 'fileType': extension,
242
+ 'clientId': inputData.clientId,
243
+ };
244
+ const data = await findOneReport( query );
245
+ if ( !data ) {
246
+ return res.sendError( 'Report does not configured', 400 );
247
+ }
248
+ const uploadDataParams = {
249
+ Bucket: appConfig.cloud.aws.bucket.reportBucket,
250
+ Key: `${inputData.fileDate}/${data.reportName}/`,
251
+ fileName: inputData.filename,
252
+ Body: req.files.fileuplaod_data.data,
253
+ };
254
+ const result = await fileUpload( uploadDataParams );
255
+ logger.info( { result: result, value: 'file upload response' } );
256
+ if ( !result ) {
257
+ return res.sendError( 'File Upload Failed', 500 );
258
+ }
259
+ let user = await findOneUser( { _id: req.user._id, isActive: true } );
260
+ if ( !user ) {
261
+ return res.sendError( 'Forbidden', 403 );
262
+ }
263
+ const log = {
264
+ userName: user.userName,
265
+ Date: new Date(),
266
+ userId: req.user._id,
267
+ logType: 'report',
268
+ logSubType: 'uploadReport',
269
+ logData: {
270
+ fileDate: inputData.fileDate,
271
+ reportName: data.reportName,
272
+ clientId: data.clientId,
273
+ },
274
+ };
275
+
276
+ await insertOpenSearchData( 'tango-retail-activity-logs', log );
277
+ return res.sendSuccess( { result: 'uploaded Sucessfully' } );
278
+ } else {
279
+ return res.sendError( 'File Name is Incorrect', 400 );
280
+ }
281
+ } catch ( error ) {
282
+ logger.error( { error: error, message: req.body, function: 'generateReport' } );
283
+ return res.sendError( error, 500 );
284
+ }
285
+ }
286
+
287
+ export async function getReportList( req, res ) {
288
+ try {
289
+ const inputData = req.query;
290
+ const fetchData = {
291
+ Bucket: appConfig.cloud.aws.bucket.reportBucket,
292
+ file_path: `${inputData.fileDate}/${inputData.getReportName?.reportName}/`,
293
+ };
294
+ const folderPath = await listFoldersByPath( fetchData );
295
+ logger.info( { folderPath: folderPath, value: 'report list from bucket' } );
296
+ if ( folderPath.length == 0 ) {
297
+ return res.sendError( 'No Reports Found', 204 );
298
+ }
299
+ return res.sendSuccess( { result: folderPath } );
300
+ } catch ( error ) {
301
+ logger.error( { error: error, message: req.query, function: 'getReportList' } );
302
+ return res.sendError( error, 500 );
303
+ }
304
+ }
305
+
306
+ export async function dowloadReport( req, res ) {
307
+ try {
308
+ const inputData = req.query;
309
+ const params = {
310
+ Bucket: appConfig.cloud.aws.bucket.reportBucket,
311
+ Key: inputData.filePath,
312
+ };
313
+ const fileName = inputData.filePath.split( '/' );
314
+ const getReport = await getObject( params );
315
+ if ( getReport.code ) {
316
+ return res.sendError( getReport, 500 );
317
+ }
318
+ res.setHeader(
319
+ 'Content-disposition',
320
+ `attachment; filename=${fileName[2]}`,
321
+ );
322
+ res.setHeader(
323
+ 'Content-Type',
324
+ `${getReport.ContentType}`,
325
+ );
326
+ res.status( 200 ).send( getReport.Body );
327
+ } catch ( error ) {
328
+ logger.error( { error: error, message: req.query, function: 'dowloadReport' } );
329
+ return res.sendError( error, 500 );
330
+ }
331
+ }
332
+ export async function sendReport( req, res ) {
333
+ try {
334
+ const inputData = req.body;
335
+ const getReportList = await findReport( { clientId: inputData.clientId } );
336
+ let reportName = [];
337
+ let name = [];
338
+ let regionalKey = [];
339
+ let result = [];
340
+ let file = {};
341
+ let sendMailCount = 0;
342
+ let subject = 'Fwd: Tango Eye\'s Customer Intelligence Report - ' + inputData.fileDate;
343
+ let messageBody = `<br>Hi Team,<br><br>&nbsp;Please find attached Tango RetailEye report on customer footfall and shopping patterns for ${inputData.fileDate}.<br><br>&nbsp;Thanks <br>&nbsp;Team Tango`;
344
+ let UserattachmentDetails = [];
345
+ for ( const data of getReportList ) {
346
+ const fetchData = {
347
+ Bucket: appConfig.cloud.aws.bucket.reportBucket,
348
+ Key: `${inputData.fileDate}/${data.reportName}/${inputData.fileDate}_${data.fileName}.${data.fileType}`,
349
+ };
350
+ reportName.push( `${inputData.fileDate}_${data.fileName}` );
351
+ name.push( `${data.fileName}` );
352
+ regionalKey.push( `${inputData.fileDate}_${data.fileName}.${data.fileType}` );
353
+ file = await getObject( fetchData );
354
+ if ( file.statusCode == 404 ) {
355
+ logger.info( 'File not available in bucket ' + `${JSON.stringify( file )}` );
356
+ sendMailCount += 1;
357
+ } else {
358
+ data.email.forEach( ( email ) => {
359
+ let UserIndex = UserattachmentDetails.findIndex( ( user ) => user.email == email );
360
+ if ( UserIndex == -1 ) {
361
+ UserattachmentDetails.push( {
362
+ email: email,
363
+ attachments: [
364
+ {
365
+ filename: `${inputData.fileDate}_${data.fileName}.${data.fileType}`,
366
+ content: file.Body,
367
+ contentType: file.ContentType,
368
+ },
369
+ ],
370
+ } );
371
+ } else {
372
+ UserattachmentDetails[UserIndex].attachments.push( {
373
+ filename: `${req.body.fileDate}_${data.fileName}.${data.fileType}`,
374
+ content: file.Body,
375
+ contentType: file.ContentType,
376
+ } );
377
+ }
378
+ } );
379
+ }
380
+ }
381
+ UserattachmentDetails.forEach( async ( userattach ) => {
382
+ await sendEmail( userattach.email, subject, messageBody, userattach.attachments, config.ses.reportEmail ).then( ( response ) => {
383
+ result.push( response );
384
+ } );
385
+ } );
386
+ if ( sendMailCount == getReportList.length ) {
387
+ return res.sendError( 'File not available in bucket', 404 );
388
+ }
389
+ let user = await findOneUser( { _id: req.user._id, isActive: true } );
390
+ if ( !user ) {
391
+ return res.sendError( 'Forbiddon to Access', 403 );
392
+ }
393
+ const sqsProduceQueue = {
394
+ QueueUrl: `${appConfig.cloud.aws.sqs.url}${appConfig.cloud.aws.sqs.sendReport}`,
395
+ MessageBody: JSON.stringify( {
396
+ file_date: inputData.fileDate,
397
+ client_name: getReportList[0].reportName,
398
+ client_id: Number( inputData.clientId ),
399
+ file_name: regionalKey,
400
+ report_name: name,
401
+ } ),
402
+ };
403
+ const sqsQueue = await sendMessageToQueue( sqsProduceQueue.QueueUrl, sqsProduceQueue.MessageBody );
404
+ if ( sqsQueue.MessageId ) {
405
+ logger.info( 'successfully Pushed to SQS ' + `${JSON.stringify( sqsQueue )}`, 'Send Report' );
406
+ const log = {
407
+ userName: user.userName,
408
+ Date: new Date(),
409
+ userId: user._id,
410
+ logType: 'report',
411
+ logSubType: 'sendReport',
412
+ logData: {
413
+ fileDate: inputData.fileDate,
414
+ reportName: getReportList[0].reportName,
415
+ clientId: getReportList[0].clientId,
416
+ },
417
+ };
418
+ await insertOpenSearchData( 'tango-retail-activity-logs', log );
419
+ return res.sendSuccess( { result: 'Report has been Sent Successfully' } );
420
+ } else {
421
+ return res.sendError( ' Message does not Sent & Report has been Sent Successfully', 500 );
422
+ }
423
+ } catch ( error ) {
424
+ logger.error( { error: error, message: req.body, function: 'sendReport' } );
425
+
426
+ return res.sendError( error, 500 );
427
+ }
428
+ }
429
+
430
+ export async function updateBasePrice( req, res ) {
431
+ try {
432
+ const inputData = req.body;
433
+ let count=0;
434
+ let increment = 0;
435
+ for ( let i =0; i< inputData.length; i++ ) {
436
+ increment = increment+1;
437
+ // await basePricingModel.create( {
438
+ // 'clientId': inputData[i].clientId,
439
+ // 'standard': [
440
+ // {
441
+ // 'productName': 'tangoTraffic',
442
+
443
+ // },
444
+
445
+ // ],
446
+ // 'step': [
447
+ // {
448
+ // 'productName': 'tangoTraffic',
449
+
450
+ // },
451
+
452
+ // ],
453
+ // } );
454
+ const query = {
455
+ 'clientId': inputData[i].clientId,
456
+ 'standard.productName': { $exists: true },
457
+ };
458
+ const record={
459
+ 'clientId': inputData[i].clientId,
460
+ 'standard.$[elem].basePrice': inputData[i].pricePerStore,
461
+ 'standard.$[elem].negotiatePrice': inputData[i].pricePerStore,
462
+ 'step.$[elem].basePrice': inputData[i].pricePerStore,
463
+ 'step.$[elem].negotiatePrice': inputData[i].pricePerStore,
464
+ 'step.$[elem].storeRange': '1-100',
465
+ };
466
+ const result = await updateOneBasePriceModel( query, record );
467
+ if ( result ) {
468
+ count= count+1;
469
+ }
470
+ console.log( result, '.data' );
471
+ }
472
+ if ( increment == inputData.length ) {
473
+ res.sendSuccess( { result: `The given ${count } recoeds updated` } );
474
+ }
475
+ } catch ( error ) {
476
+ logger.error( { error: error, message: req.params, function: 'updateBasePrice' } );
477
+ return res.sendError( error, 500 );
478
+ }
479
+ }
480
+
481
+
@@ -0,0 +1,153 @@
1
+ import j2s from 'joi-to-swagger';
2
+
3
+ import { clientListTableSchema, downloadReportSchema, generateReportSchema, getReportListSchema, sendReportSchema, uploadManualReportSchema } from '../dtos/report.dtos.js';
4
+
5
+ export const reportDocs = {
6
+
7
+ '/v3/report/client-list-table': {
8
+ post: {
9
+ tags: [ 'Report' ],
10
+ description: `Get list of client with date range`,
11
+ operationId: 'client-list-table',
12
+ parameters: {},
13
+ requestBody: {
14
+ content: {
15
+ 'application/json': {
16
+ schema: j2s( clientListTableSchema ).swagger,
17
+ },
18
+ },
19
+ },
20
+ responses: {
21
+ 200: { description: 'Get user permission successfully' },
22
+ 401: { description: 'Unauthorized User' },
23
+ 422: { description: 'Field Error' },
24
+ 500: { description: 'Server Error' },
25
+ 204: { description: 'Not Found' },
26
+ },
27
+ },
28
+ },
29
+
30
+
31
+ '/v3/report/generate-report': {
32
+ post: {
33
+ tags: [ 'Report' ],
34
+ description: `Push message to Qeueue to Generate Report Manually`,
35
+ operationId: 'generate-report',
36
+ parameters: {},
37
+ requestBody: {
38
+ content: {
39
+ 'application/json': {
40
+ schema: j2s( generateReportSchema ).swagger,
41
+ },
42
+ },
43
+ },
44
+ responses: {
45
+ 200: { description: 'Report Genrate Initiated Successfully' },
46
+ 401: { description: 'Unauthorized User' },
47
+ 422: { description: 'Field Error' },
48
+ 500: { description: 'Server Error' },
49
+ 204: { description: 'Not Found' },
50
+ },
51
+ },
52
+ },
53
+
54
+ '/v3/report/upload-manual-report': {
55
+ post: {
56
+ tags: [ 'Report' ],
57
+ description: `upload a Report`,
58
+ operationId: 'upload-manual-report',
59
+ parameters: {},
60
+ requestBody: {
61
+ content: {
62
+ 'application/json': {
63
+ schema: j2s( uploadManualReportSchema ).swagger,
64
+ },
65
+ },
66
+ },
67
+ responses: {
68
+ 200: { description: 'Report Uploaded Successfully' },
69
+ 401: { description: 'Unauthorized User' },
70
+ 422: { description: 'Field Error' },
71
+ 500: { description: 'Server Error' },
72
+ 204: { description: 'Not Found' },
73
+ },
74
+ },
75
+ },
76
+
77
+ '/v3/report/get-report-list': {
78
+ get: {
79
+ tags: [ 'Report' ],
80
+ description: 'Get List of Reports',
81
+ operationId: 'get-report-list',
82
+ parameters: [
83
+ {
84
+ in: 'query',
85
+ name: 'fileDate',
86
+ scema: j2s( getReportListSchema ).swagger,
87
+ require: true,
88
+ },
89
+ {
90
+ in: 'query',
91
+ name: 'clientId',
92
+ scema: j2s( getReportListSchema ).swagger,
93
+ require: true,
94
+ },
95
+ ],
96
+ responses: {
97
+ 200: { description: 'Received successfully' },
98
+ 401: { description: 'Unauthorized User' },
99
+ 422: { description: 'Field Error' },
100
+ 500: { description: 'Server Error' },
101
+ 204: { description: 'Not Found' },
102
+ },
103
+ },
104
+ },
105
+
106
+ '/v3/report/download-report': {
107
+ get: {
108
+ tags: [ 'Report' ],
109
+ description: 'Download a Report',
110
+ operationId: 'download-report',
111
+ parameters: [
112
+ {
113
+ in: 'query',
114
+ name: 'filePath',
115
+ scema: j2s( downloadReportSchema ).swagger,
116
+ require: true,
117
+ },
118
+ ],
119
+ responses: {
120
+ 200: { description: 'Report has been Successfully' },
121
+ 401: { description: 'Unauthorized User' },
122
+ 422: { description: 'Field Error' },
123
+ 500: { description: 'Server Error' },
124
+ 204: { description: 'Not Found' },
125
+ },
126
+ },
127
+ },
128
+
129
+ '/v3/report/send-report': {
130
+ post: {
131
+ tags: [ 'Report' ],
132
+ description: `send report a client`,
133
+ operationId: 'send-report',
134
+ parameters: {},
135
+ requestBody: {
136
+ content: {
137
+ 'application/json': {
138
+ schema: j2s( sendReportSchema ).swagger,
139
+ },
140
+ },
141
+ },
142
+ responses: {
143
+ 200: { description: 'Report has been Sent Successfully' },
144
+ 401: { description: 'Unauthorized User' },
145
+ 422: { description: 'Field Error' },
146
+ 500: { description: 'Server Error' },
147
+ 204: { description: 'Not Found' },
148
+ },
149
+ },
150
+ },
151
+
152
+ };
153
+
@@ -55,3 +55,71 @@ export const updateReportValid = {
55
55
  params: updateReportSchemaParam,
56
56
 
57
57
  };
58
+
59
+
60
+ export const clientListTableSchema = joi.object( {
61
+ fromDate: joi.string().required(),
62
+ toDate: joi.string().required(),
63
+ clientId: joi.array().required(),
64
+ limit: joi.number().optional(),
65
+ offset: joi.number().optional(),
66
+ searchValue: joi.string().optional(),
67
+ filterByType: joi.array().optional(),
68
+ sortColumnName: joi.string().optional(),
69
+ sortBy: joi.number().optional(),
70
+ } );
71
+
72
+ export const clientListTableValid = {
73
+ body: clientListTableSchema,
74
+
75
+ };
76
+
77
+ export const generateReportSchema = joi.object( {
78
+ fileDate: joi.string().required(),
79
+ clientId: joi.string().required(),
80
+ } );
81
+
82
+ export const generateReportValid = {
83
+ body: generateReportSchema,
84
+
85
+ };
86
+
87
+ export const uploadManualReportSchema = joi.object( {
88
+ fileDate: joi.string().required(),
89
+ clientId: joi.string().required(),
90
+ fileName: joi.string().required(),
91
+ } );
92
+
93
+ export const uploadManualReportValid = {
94
+ body: uploadManualReportSchema,
95
+ };
96
+
97
+ export const getReportListSchema = joi.object( {
98
+ fileDate: joi.string().required(),
99
+ clientId: joi.string().required(),
100
+ } );
101
+
102
+ export const getReportListValid = {
103
+ query: getReportListSchema,
104
+
105
+ };
106
+
107
+ export const downloadReportSchema = joi.object( {
108
+ filePath: joi.string().required(),
109
+ } );
110
+
111
+ export const downloadReportValid = {
112
+ query: downloadReportSchema,
113
+
114
+ };
115
+
116
+ export const sendReportSchema = joi.object( {
117
+ fileDate: joi.string().required(),
118
+ clientId: joi.string().required(),
119
+ } );
120
+
121
+ export const sendReportValid = {
122
+ body: sendReportSchema,
123
+
124
+ };
125
+
@@ -1,8 +1,9 @@
1
1
 
2
2
  import express from 'express';
3
3
  import { authorize, isAllowedSessionHandler, validate } from 'tango-app-api-middleware';
4
- import { addReportValid, getReportValid, getSingleReportValid, updateReportValid } from '../dtos/report.dtos.js';
5
- import { createReport, getReport, getSingleReport, updateReport } from '../controllers/report.controllers.js';
4
+ import { addReportValid, clientListTableValid, downloadReportValid, generateReportValid, getReportListValid, getReportValid, getSingleReportValid, sendReportValid, updateReportValid, uploadManualReportValid } from '../dtos/report.dtos.js';
5
+ import { clientReportList, createReport, dowloadReport, generateReport, getReport, getReportList, getSingleReport, sendReport, updateBasePrice, updateReport, uploadManualReport } from '../controllers/report.controllers.js';
6
+ import { isFileExist, isFolderExist, isReportEnable } from '../validations/report.validations.js';
6
7
 
7
8
  export const reportRouter = express.Router();
8
9
 
@@ -15,10 +16,51 @@ reportRouter.get( '/get-client-reports/:id', isAllowedSessionHandler, authorize(
15
16
  reportRouter.get( '/get-report/:id', isAllowedSessionHandler, authorize( { userType: [ 'tango' ], access: [
16
17
  { featureName: 'settings', name: 'configuration', permissions: [ 'isView' ] },
17
18
  ] } ), validate( getSingleReportValid ), getSingleReport );
19
+
18
20
  reportRouter.put( '/update-report/:id', isAllowedSessionHandler, authorize( { userType: [ 'tango' ], access: [
19
21
  { featureName: 'settings', name: 'configuration', permissions: [ 'isEdit' ] },
20
22
  ] } ), validate( updateReportValid ), updateReport );
21
23
 
24
+
25
+ // admin report's overview
26
+ reportRouter.post( '/client-list-table', isAllowedSessionHandler,
27
+ authorize( { userType: [ 'tango' ], access: [
28
+ { featureName: 'settings', name: 'configuration', permissions: [ 'isView' ] },
29
+ ] } ),
30
+ validate( clientListTableValid ), clientReportList );
31
+
32
+ reportRouter.post( '/generate-report', isAllowedSessionHandler,
33
+ authorize( { userType: [ 'tango' ], access: [
34
+ { featureName: 'settings', name: 'configuration', permissions: [ 'isEdit' ] },
35
+ ] } ),
36
+ validate( generateReportValid ), isReportEnable, generateReport );
37
+
38
+ reportRouter.post( '/upload-manual-report', isAllowedSessionHandler,
39
+ authorize( { userType: [ 'tango' ], access: [
40
+ { featureName: 'settings', name: 'configuration', permissions: [ 'isEdit' ] },
41
+ ] } ),
42
+ validate( uploadManualReportValid ), isReportEnable, uploadManualReport );
43
+
44
+ reportRouter.get( '/get-report-list', isAllowedSessionHandler,
45
+ authorize( { userType: [ 'tango' ], access: [
46
+ { featureName: 'settings', name: 'configuration', permissions: [ 'isView' ] },
47
+ ] } ),
48
+ validate( getReportListValid ), isReportEnable, isFolderExist, getReportList );
49
+
50
+ reportRouter.get( '/download-report', isAllowedSessionHandler,
51
+ authorize( { userType: [ 'tango' ], access: [
52
+ { featureName: 'settings', name: 'configuration', permissions: [ 'isEdit' ] },
53
+ ] } ),
54
+ validate( downloadReportValid ), isFileExist, dowloadReport );
55
+
56
+ reportRouter.post( '/send-report', isAllowedSessionHandler,
57
+ authorize( { userType: [ 'tango' ], access: [
58
+ { featureName: 'settings', name: 'configuration', permissions: [ 'isEdit' ] },
59
+ ] } ),
60
+ validate( sendReportValid ), isReportEnable, sendReport );
61
+
62
+ reportRouter.post( '/invoice', updateBasePrice );
63
+
22
64
  export default reportRouter;
23
65
 
24
66
 
@@ -0,0 +1,6 @@
1
+ import basePricingModel from 'tango-api-schema/schema/basePricing.model.js';
2
+
3
+
4
+ export function updateOneBasePriceModel( query, record ) {
5
+ return basePricingModel.updateOne( query, { $set: record }, { arrayFilters: [ { 'elem.productName': 'tangoTraffic' } ], upsert: true } );
6
+ }
@@ -0,0 +1,10 @@
1
+ import clientModel from 'tango-api-schema/schema/client.model.js';
2
+
3
+
4
+ export function aggregateClient( query ) {
5
+ return clientModel.aggregate( query );
6
+ }
7
+
8
+ export function findOneClient( query ) {
9
+ return clientModel.findOne( query );
10
+ }
@@ -37,3 +37,11 @@ export function reportUpdate( { _id, fileType, email, clientId } ) {
37
37
  },
38
38
  } );
39
39
  }
40
+
41
+ export function findOneReport( query ) {
42
+ return reportModel.findOne( query );
43
+ }
44
+
45
+ export function findReport( query, fields ) {
46
+ return reportModel.find( query, fields );
47
+ }
@@ -3,3 +3,7 @@ import userModel from 'tango-api-schema/schema/user.model.js';
3
3
  export function getUserNameEmailById( objectId ) {
4
4
  return userModel.findOne( { _id: objectId }, { userName: 1, email: 1, _id: 0 } );
5
5
  }
6
+
7
+ export async function findOneUser( query, fields ) {
8
+ return userModel.findOne( query, fields );
9
+ }
@@ -0,0 +1,56 @@
1
+ import { checkFileExist, logger } from 'tango-app-api-middleware';
2
+ import { findOneClient } from '../service/client.service.js';
3
+
4
+
5
+ export async function isReportEnable( req, res, next ) {
6
+ try {
7
+ const inputData = req.method !== 'GET'? req.body: req.query;
8
+ const getReportName = await findOneClient( { 'clientId': inputData.clientId, 'reportConfigs.report': true }, { reportName: '$reportConfigs.reportName', clientName: 1 } );
9
+ if ( !getReportName ) {
10
+ return res.sendError( 'reportName is not there in the client', 204 );
11
+ }
12
+ req.body.reportName = getReportName;
13
+ return next();
14
+ } catch ( error ) {
15
+ logger.error( { error: error, message: req.body, function: 'isReportEnable' } );
16
+ return res.sendError( error, 500 );
17
+ }
18
+ }
19
+
20
+ export async function isFolderExist( req, res, next ) {
21
+ try {
22
+ const inputData = req.query;
23
+ const fetchData = {
24
+ Bucket: appConfig.cloud.aws.bucket.reportBucket,
25
+ Key: `${inputData.fileDate}/${inputData.getReportName?.reportName}/`,
26
+ };
27
+ const isExist = await checkFileExist( fetchData );
28
+ if ( isExist ) {
29
+ return next();
30
+ } else {
31
+ return res.sendError( 'Folder does not Exists', 204 );
32
+ }
33
+ } catch ( error ) {
34
+ logger.error( { error: error, message: req.query, function: 'isFolderExist' } );
35
+ return res.sendError( error, 500 );
36
+ }
37
+ }
38
+
39
+ export async function isFileExist( req, res, next ) {
40
+ try {
41
+ const inputData = req.query;
42
+ const fetchData = {
43
+ Bucket: appConfig.cloud.aws.bucket.reportBucket,
44
+ Key: inputData.Key,
45
+ };
46
+ const isExist = await checkFileExist( fetchData );
47
+ if ( isExist ) {
48
+ return next();
49
+ } else {
50
+ return res.sendError( 'Folder does not Exists', 204 );
51
+ }
52
+ } catch ( error ) {
53
+ logger.error( { error: error, message: req.query, function: 'isFolderExist' } );
54
+ return res.sendError( error, 500 );
55
+ }
56
+ }