tango-app-api-infra 3.8.1-beta.5 → 3.8.1-beta.7

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-infra",
3
- "version": "3.8.1-beta.5",
3
+ "version": "3.8.1-beta.7",
4
4
  "description": "infra",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -1,4 +1,4 @@
1
- import { download, logger } from 'tango-app-api-middleware';
1
+ import { download, logger, sendMessageToQueue } from 'tango-app-api-middleware';
2
2
  import { bulkUpdate, getOpenSearchCount, getOpenSearchData, insertWithId, updateOpenSearchData } from 'tango-app-api-middleware/src/utils/openSearch.js';
3
3
  import { findOneStore } from '../services/store.service.js';
4
4
  import dayjs from 'dayjs';
@@ -368,11 +368,11 @@ export async function getTickets( req, res ) {
368
368
  try {
369
369
  const openSearch = JSON.parse( process.env.OPENSEARCH );
370
370
  const inputData = req.query;
371
- const limit = inputData.limit || 10;
371
+ const limit = inputData.limit;
372
372
  const skip= inputData.offset == 0? 0:( inputData.offset - 1 ) *limit || 0;
373
373
  inputData.storeId = inputData.storeId.split( ',' ); // convert strig to array
374
374
  logger.info( { inputData: inputData, limit: limit, skip: skip } );
375
-
375
+ let source = [ 'storeId', 'dateString', 'ticketName', 'footfallCount', 'employeeCount', 'houseKeepingCount', 'duplicateCount', 'comments', 'employee', 'houseKeeping', 'duplicateImages', 'ticketId', 'clientId', 'storeName', 'createdAt', 'updatedAt', 'userName', 'role', 'status', 'employeeStatus', 'houseKeepingStatus', 'duplicateStatus' ];
376
376
  let filter =[
377
377
  { terms: { 'storeId.keyword': Array.isArray( inputData.storeId ) ?
378
378
  inputData.storeId :
@@ -405,6 +405,32 @@ export async function getTickets( req, res ) {
405
405
  field: inputData.revopsType,
406
406
  },
407
407
  } );
408
+ inputData.revopsType === 'employee'?
409
+ filter.push( {
410
+ range: {
411
+ employeeCount: {
412
+ gt: 0,
413
+ },
414
+ },
415
+ } ) :
416
+ inputData.revopsType === 'housekeeping'?
417
+ filter.push( {
418
+ range: {
419
+ housekeepingCount: {
420
+ gt: 0,
421
+ },
422
+ },
423
+ } ):
424
+ filter.push( {
425
+ range: {
426
+ duplicateCount: {
427
+ gt: 0,
428
+ },
429
+ },
430
+ } );
431
+ source= inputData.revopsType == 'employee' ?[ 'storeId', 'dateString', 'ticketName', 'footfallCount', 'employeeCount', 'comments', 'employee', 'ticketId', 'clientId', 'storeName', 'createdAt', 'updatedAt', 'userName', 'role', 'status', 'employeeStatus', 'houseKeepingStatus', 'duplicateStatus' ]:
432
+ inputData.revopsType == 'houseKeeping' ?[ 'storeId', 'dateString', 'ticketName', 'footfallCount', 'houseKeepingCount', 'comments', 'houseKeeping', 'ticketId', 'clientId', 'storeName', 'createdAt', 'updatedAt', 'userName', 'role', 'status', 'employeeStatus', 'houseKeepingStatus', 'duplicateStatus' ]:
433
+ inputData.revopsType == 'duplicateImages' ?[ 'storeId', 'dateString', 'ticketName', 'footfallCount', 'duplicateCount', 'comments', 'duplicateImages', 'ticketId', 'clientId', 'storeName', 'createdAt', 'updatedAt', 'userName', 'role', 'status', 'employeeStatus', 'houseKeepingStatus', 'duplicateStatus' ] : [];
408
434
  }
409
435
 
410
436
  if ( inputData.action ) {
@@ -431,7 +457,24 @@ export async function getTickets( req, res ) {
431
457
  },
432
458
  } );
433
459
  }
434
-
460
+ let getRevCount = {};
461
+ if ( inputData.revopsType ) {
462
+ getRevCount= {
463
+ size: 0,
464
+ query: {
465
+ bool: {
466
+ filter: filter,
467
+ },
468
+ },
469
+ aggs: {
470
+ totalCount: {
471
+ sum: {
472
+ field: inputData.revopsType == 'employee'? 'employeeCount':inputData.revopsType == 'houseKeeping'?'houseKeepingCount': 'duplicateCount',
473
+ },
474
+ },
475
+ },
476
+ };
477
+ }
435
478
  const getCount= {
436
479
  query: {
437
480
  bool: {
@@ -440,8 +483,12 @@ export async function getTickets( req, res ) {
440
483
  },
441
484
  };
442
485
 
486
+
443
487
  const geteDataCount = await getOpenSearchCount( openSearch.footfallDirectory, getCount );
444
- if ( !geteDataCount || geteDataCount?.body?.count == 0 ) {
488
+ const geteRevDataCount = inputData?.revopsType? await getOpenSearchData( openSearch.footfallDirectory, getRevCount ) : null;
489
+ const revCount = inputData?.revopsType? geteRevDataCount?.body?.aggregations?.totalCount?.value: 0;
490
+ const count = geteDataCount?.body?.count;
491
+ if ( !geteDataCount || count==0 ) {
445
492
  return res.sendError( 'No data found', 204 );
446
493
  }
447
494
 
@@ -453,10 +500,22 @@ export async function getTickets( req, res ) {
453
500
  filter: filter,
454
501
  },
455
502
  },
503
+ _source: source,
456
504
  };
457
505
 
458
506
  const getData = await getOpenSearchData( openSearch.footfallDirectory, getQuery );
459
507
  const response = getData?.body?.hits?.hits;
508
+ // let temp=[ response[0] ];
509
+ // logger.info( { temp: temp, response: response } );
510
+ // if ( inputData.revopsType ) {
511
+ // const key =inputData.revopsType == 'employee'? 'employeeCount':inputData.revopsType == 'houseKeeping'?'houseKeepingCount': 'duplicateCount';
512
+
513
+ // const type = inputData.revopsType;
514
+ // temp[0]._source[key] = revCount;
515
+ // for ( const doc of response.slice( 1 ) ) {
516
+ // inputData.revopsType == 'duplicateImages'? temp[0]._source[type].push( ...doc._source[type] ):temp[0]._source[type].push( doc._source[type] );
517
+ // }
518
+ // }
460
519
  logger.info( { response: response, body: getData?.body, getData: getData, geteDataCount: geteDataCount } );
461
520
 
462
521
 
@@ -480,7 +539,7 @@ export async function getTickets( req, res ) {
480
539
  return;
481
540
  }
482
541
 
483
- return res.sendSuccess( { result: response, count: geteDataCount?.body?.count } );
542
+ return res.sendSuccess( { result: inputData.revopsType? response: response, count: count, revopCount: revCount } );
484
543
  } catch ( error ) {
485
544
  const err = error.message || 'Internal Server Error';
486
545
  logger.error( { error: error, messgage: req.query } );
@@ -490,6 +549,7 @@ export async function getTickets( req, res ) {
490
549
 
491
550
  export async function updateStatus( req, res ) {
492
551
  try {
552
+ const openSearch = JSON.parse( process.env.OPENSEARCH );
493
553
  const inputData = req.body;
494
554
  const id = req.query._id;
495
555
  const splitId = id.split( '_' );
@@ -498,7 +558,8 @@ export async function updateStatus( req, res ) {
498
558
  if ( inputData.duplicateStatus === 'approved' && inputData.employeeStatus === 'approved' && inputData.houseKeepingStatus === 'approved' ) {
499
559
  inputData.status = 'closed';
500
560
  }
501
- await updateOpenSearchData( openSearch.footfallDirectory, id, { _doc: inputData } );
561
+ let tempId = [];
562
+ await updateOpenSearchData( openSearch.footfallDirectory, id, { doc: inputData } );
502
563
  let bulkBody = [];
503
564
  for ( let duplicate of inputData.duplicateImages ) {
504
565
  bulkBody.push(
@@ -506,6 +567,7 @@ export async function updateStatus( req, res ) {
506
567
  { doc: { duplicateImage: duplicate.duplicateImage } },
507
568
  );
508
569
  duplicate.map( ( item ) => {
570
+ item.isChecked == true? tempId.push( item.tempId ) : null;
509
571
  bulkBody.push(
510
572
  { update: { _index: openSearch.revop, _id: `${storeId}_${dateString}_${item.timeRange}_${item.tempId}` } },
511
573
  { doc: { isChecked: item.isChecked } },
@@ -513,18 +575,28 @@ export async function updateStatus( req, res ) {
513
575
  } );
514
576
  }
515
577
  for ( let employee of inputData.employee ) {
516
- bulkBody.push(
517
- { update: { _index: openSearch.revop, _id: `${storeId}_${dateString}_${employee.timeRange}_${employee.tempId}` } },
518
- { doc: { isChecked: employee.isChecked } },
519
- );
578
+ employee.isChecked == true? tempId.push( employee.tempId ) : null;
579
+ bulkBody.push(
580
+ { update: { _index: openSearch.revop, _id: `${storeId}_${dateString}_${employee.timeRange}_${employee.tempId}` } },
581
+ { doc: { isChecked: employee.isChecked } },
582
+ );
520
583
  }
521
584
  for ( let houseKeeping of inputData.houseKeeping ) {
522
- bulkBody.push(
523
- { update: { _index: openSearch.revop, _id: `${storeId}_${dateString}_${houseKeeping.timeRange}_${houseKeeping.tempId}` } },
524
- { doc: { isChecked: houseKeeping.isChecked } },
525
- );
585
+ houseKeeping.isChecked == true? tempId.push( houseKeeping.tempId ) : null;
586
+ bulkBody.push(
587
+ { update: { _index: openSearch.revop, _id: `${storeId}_${dateString}_${houseKeeping.timeRange}_${houseKeeping.tempId}` } },
588
+ { doc: { isChecked: houseKeeping.isChecked } },
589
+ );
526
590
  }
527
- return res.sendSuccess( 'ticket closed successfully' );
591
+ // if ( inputData.status == 'closed' ) {
592
+ // const isSendMessge = await sendSqsMessage( inputData, tempId );
593
+ // if ( isSendMessge ==true ) {
594
+ // return res.sendSuccess( 'Ticket has been updated successfully' );
595
+ // } else {
596
+ // return res.sendError( 'No SQS message sent', 500 );
597
+ // }
598
+ // }
599
+ return res.sendSuccess( 'Ticket has been updated successfully' );
528
600
  } catch ( error ) {
529
601
  const err = error.messgae || 'Internal Server Error';
530
602
  logger.error( { error: error, data: req.body, function: 'infra-footfallDirectory-updateStatus' } );
@@ -532,40 +604,80 @@ export async function updateStatus( req, res ) {
532
604
  }
533
605
  }
534
606
 
607
+ export async function sendSqsMessage( inputData, tempId ) {
608
+ const sqsProduceQueue = {
609
+ QueueUrl: `${sqs.url}${sqs.revopticket}`,
610
+ MessageBody: JSON.stringify( {
611
+ store_id: inputData.storeId,
612
+ store_date: inputData.dateString.split( '-' ).reverse().join( '-' ),
613
+ bucket_name: '',
614
+ zone_id: 'traffic_zone',
615
+ process_type: 'reduction',
616
+ revop_type: 'footfall',
617
+ temp_id: tempId,
618
+ } ),
619
+ };
620
+
621
+ const sqsQueue = await sendMessageToQueue(
622
+ sqsProduceQueue.QueueUrl,
623
+ sqsProduceQueue.MessageBody,
624
+ );
625
+
626
+ if ( sqsQueue.statusCode ) {
627
+ logger.error( {
628
+ error: `${sqsQueue}`,
629
+ type: 'UPLOAD_ERROR',
630
+ } );
631
+ return res.sendError( 'SQS not sent', 500 );
632
+ }
633
+ }
634
+
535
635
  export async function getTaggedStores( req, res ) {
536
636
  try {
537
637
  const openSearch = JSON.parse( process.env.OPENSEARCH );
538
638
  const inputData = req.query;
539
639
  logger.info( { inputData: inputData } );
640
+ let filter= [
641
+ {
642
+ term: { 'clientId.keyword': inputData.clientId },
643
+ },
644
+ {
645
+ range: {
646
+ dateString: {
647
+ gte: inputData.fromDate,
648
+ lte: inputData.toDate,
649
+ format: 'yyyy-MM-dd',
650
+ },
651
+ },
652
+ },
653
+
654
+ {
655
+ exists: {
656
+ field: 'storeId',
657
+ },
658
+ },
659
+ {
660
+ exists: {
661
+ field: 'storeName',
662
+ },
663
+ },
664
+ ];
665
+
666
+ if ( inputData.searchValue && inputData.searchValue !== '' ) {
667
+ filter.push( {
668
+ regexp: {
669
+ 'storeName': {
670
+ value: `.*${inputData.searchValue.toLowerCase()}.*`,
671
+ flags: 'ALL',
672
+ },
673
+ },
674
+ } );
675
+ }
540
676
  const getCount = {
541
677
  size: 0,
542
678
  query: {
543
679
  bool: {
544
- filter: [
545
- {
546
- term: { 'clientId.keyword': inputData.clientId },
547
- },
548
- {
549
- range: {
550
- dateString: {
551
- gte: inputData.fromDate,
552
- lte: inputData.toDate,
553
- format: 'yyyy-MM-dd',
554
- },
555
- },
556
- },
557
-
558
- {
559
- exists: {
560
- field: 'storeId',
561
- },
562
- },
563
- {
564
- exists: {
565
- field: 'storeName',
566
- },
567
- },
568
- ],
680
+ filter: filter,
569
681
  },
570
682
  },
571
683
  aggs: {
@@ -170,7 +170,7 @@ export const footfallDirectoryDocs = {
170
170
  in: 'query',
171
171
  name: 'limit',
172
172
  scema: j2s( getTicketsSchema ).swagger,
173
- required: false,
173
+ required: true,
174
174
  },
175
175
  {
176
176
  in: 'query',
@@ -243,6 +243,12 @@ export const footfallDirectoryDocs = {
243
243
  scema: j2s( getTaggedStoresSchema ).swagger,
244
244
  required: true,
245
245
  },
246
+ {
247
+ in: 'query',
248
+ name: 'searchValue',
249
+ scema: j2s( getTaggedStoresSchema ).swagger,
250
+ required: false,
251
+ },
246
252
  ],
247
253
  responses: {
248
254
  200: { description: 'Successful' },
@@ -224,7 +224,7 @@ export const getTicketsSchema = Joi.object().keys( {
224
224
  status: Joi.string().optional(),
225
225
  action: Joi.string().optional(),
226
226
  revopsType: Joi.string().optional(),
227
- limit: Joi.number().optional(),
227
+ limit: Joi.number().required(),
228
228
  offset: Joi.number().optional(),
229
229
 
230
230
  } ).custom( ( value, helpers ) => {
@@ -256,6 +256,22 @@ export const updateStatusQuerySchema =Joi.object().keys( {
256
256
  } );
257
257
 
258
258
  export const updateStatusSchemea =Joi.object().keys( {
259
+ dateString: Joi.string().required().custom( ( value, helpers ) => {
260
+ const inputDate = dayjs( value, 'YYYY-MM-DD', true );
261
+ const today = dayjs();
262
+
263
+ if ( !inputDate.isValid() ) {
264
+ return helpers.error( 'any.invalid' );
265
+ }
266
+
267
+ const diff = today.diff( inputDate, 'day' );
268
+
269
+ if ( diff > 10 ) {
270
+ return helpers.message( 'Approval is not allowed for a period exceeding 10 days' );
271
+ }
272
+
273
+ return value;
274
+ } ),
259
275
 
260
276
  duplicateACCount: Joi.number().required(),
261
277
  employeeACCount: Joi.number().required(),
@@ -311,7 +327,7 @@ export const updateStatusValid = {
311
327
 
312
328
  export const getTaggedStoresSchema = Joi.object().keys( {
313
329
  clientId: Joi.string().required(),
314
-
330
+ searchValue: Joi.string().optional().allow( '' ),
315
331
  fromDate: Joi.string()
316
332
  .pattern( /^\d{4}-\d{2}-\d{2}$/, 'YYYY-MM-DD format' )
317
333
  .required()