tango-app-api-infra 3.9.5-vms.71 → 3.9.5-vms.73

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.9.5-vms.71",
3
+ "version": "3.9.5-vms.73",
4
4
  "description": "infra",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -27,7 +27,7 @@
27
27
  "mongodb": "^6.4.0",
28
28
  "nodemon": "^3.1.0",
29
29
  "swagger-ui-express": "^5.0.0",
30
- "tango-api-schema": "^2.4.28",
30
+ "tango-api-schema": "^2.5.1",
31
31
  "tango-app-api-infra": "^3.9.5-vms.56",
32
32
  "tango-app-api-middleware": "^3.1.93",
33
33
  "winston": "^3.12.0",
@@ -9,6 +9,7 @@ import timezone from 'dayjs/plugin/timezone.js';
9
9
  import { findOneClient } from '../services/client.service.js';
10
10
  import { findUser, findOneUser } from '../services/user.service.js';
11
11
  import { sendPushNotification } from 'tango-app-api-middleware';
12
+ import { findStoreAccuracIssues, upsertStoreAccuracIssues } from '../services/storeAccuracyIssues.service.js';
12
13
  dayjs.extend( utc );
13
14
  dayjs.extend( timezone );
14
15
 
@@ -302,7 +303,7 @@ export async function tangoReviewTicket( req, res ) {
302
303
  } else if ( revised < tangoReview ) {
303
304
  // If ticket is closed, do not proceed with revision mapping
304
305
 
305
- record.status = 'Closed - Accuracy Issue';
306
+ record.status = 'Open - Accuracy Issue';
306
307
  // Only keep or modify mappingInfo items with type "review"
307
308
  if ( Array.isArray( record.mappingInfo ) ) {
308
309
  const temp = record.mappingInfo
@@ -322,14 +323,14 @@ export async function tangoReviewTicket( req, res ) {
322
323
 
323
324
  record.mappingInfo = [ ...ticketData?.[0]?._source?.mappingInfo.slice( 0, -1 ),
324
325
  ...temp ];
325
- if ( Array.isArray( record.mappingInfo ) ) {
326
- record.mappingInfo = record.mappingInfo.map( ( item ) => {
327
- return {
328
- ...item,
329
- status: 'Closed',
330
- };
331
- } );
332
- }
326
+ // if ( Array.isArray( record.mappingInfo ) ) {
327
+ // record.mappingInfo = record.mappingInfo.map( ( item ) => {
328
+ // return {
329
+ // ...item,
330
+ // status: 'Closed',
331
+ // };
332
+ // } );
333
+ // }
333
334
  // If no review mapping existed, push a new one
334
335
  // if ( record.mappingInfo.length === 0 ) {
335
336
  // record.mappingInfo.push( {
@@ -445,7 +446,7 @@ export async function tangoReviewTicket( req, res ) {
445
446
  }
446
447
  } catch ( error ) {
447
448
  const err = error.message || 'Internal Server Error';
448
- logger.error( { error: err, funtion: 'tangoReviewTicket' } );
449
+ logger.error( { error: error, funtion: 'tangoReviewTicket' } );
449
450
  return res.sendError( err, 500 );
450
451
  }
451
452
  }
@@ -453,44 +454,8 @@ export async function tangoReviewTicket( req, res ) {
453
454
  export async function tangoReviewAccuracyClosedTicket( req, res ) {
454
455
  try {
455
456
  const inputData = req.body;
456
-
457
- // get store info by the storeId into mongo db
458
- const getstoreName = await findOneStore( { storeId: inputData.storeId, status: 'active' }, { storeId: 1, storeName: 1, clientId: 1 } );
459
-
460
- if ( !getstoreName || getstoreName == null ) {
461
- return res.sendError( 'The store ID is either inActive or not found', 400 );
462
- }
463
-
464
- // get the footfall count from opensearch
465
457
  const openSearch = JSON.parse( process.env.OPENSEARCH );
466
- const dateString = `${inputData.storeId}_${inputData.dateString}`;
467
- const getQuery = {
468
- query: {
469
- terms: {
470
- _id: [ dateString ],
471
- },
472
- },
473
- _source: [ 'footfall', 'date_string', 'store_id', 'down_time', 'footfall_count' ],
474
- sort: [
475
- {
476
- date_iso: {
477
- order: 'desc',
478
- },
479
- },
480
- ],
481
- };
482
458
 
483
- const getFootfallCount = await getOpenSearchData( openSearch.footfall, getQuery );
484
- const hits = getFootfallCount?.body?.hits?.hits || [];
485
- if ( hits?.[0]?._source?.footfall_count <= 0 ) {
486
- return res.sendError( 'You can’t create a ticket because this store has 0 footfall data' );
487
- }
488
-
489
- // get category details from the client level configuration
490
- const getConfig = await findOneClient( { clientId: getstoreName.clientId }, { footfallDirectoryConfigs: 1 } );
491
- if ( !getConfig || getConfig == null ) {
492
- return res.sendError( 'The Client ID is either not configured or not found', 400 );
493
- }
494
459
  let findQuery = {
495
460
  size: 10000,
496
461
  query: {
@@ -566,192 +531,61 @@ export async function tangoReviewAccuracyClosedTicket( req, res ) {
566
531
 
567
532
  const record = {
568
533
 
569
- status: parseInt( inputData?.mappingInfo?.[0]?.revicedPerc || 0 ) < parseInt( getConfig?.footfallDirectoryConfigs?.tangoReview|| 0 ) ? 'Open - Accuracy Issue' : 'Closed',
570
- revicedFootfall: inputData.mappingInfo?.[0]?.revicedFootfall,
571
- revicedPerc: inputData.mappingInfo?.[0]?.revicedPerc,
572
- mappingInfo: ticketData?.[0]?._source?.mappingInfo,
534
+ status: 'Closed - Accuracy Issue',
573
535
  createdByEmail: req?.user?.email,
574
536
  createdByUserName: req?.user?.userName,
575
537
  createdByRole: req?.user?.role,
576
-
538
+ mappingInfo: ticketData?.[0]?._source?.mappingInfo,
577
539
  };
578
540
 
579
-
580
- // Retrieve client footfallDirectoryConfigs revision
581
- let isAutoCloseEnable = getConfig.footfallDirectoryConfigs.isAutoCloseEnable;
582
- let autoCloseAccuracy = getConfig?.footfallDirectoryConfigs?.autoCloseAccuracy;
583
-
584
- const getNumber = autoCloseAccuracy.split( '%' )[0];
585
-
586
- let autoCloseAccuracyValue = parseFloat( ( autoCloseAccuracy || getNumber ).replace( '%', '' ) );
587
- let revisedPercentage = inputData.mappingInfo?.revicedPerc;
588
- const revised = Number( revisedPercentage?.split( '%' )[0] );
589
- const tangoReview = Number( getConfig?.footfallDirectoryConfigs?.tangoReview?.split( '%' )[0] );
590
541
  // If autoclose enabled and revisedPercentage meets/exceeds threshold, close ticket and skip revision
591
- if (
592
- isAutoCloseEnable === true &&
593
- revisedPercentage >= autoCloseAccuracyValue
594
- ) {
595
- record.status = 'Closed';
596
- // Only keep or modify mappingInfo items with type "review"
597
- if ( Array.isArray( record.mappingInfo ) ) {
598
- const temp = record.mappingInfo
599
- .filter( ( item ) => item.type === 'tangoreview' )
600
- .map( ( item ) => ( {
601
- ...item,
602
-
603
- mode: inputData.mappingInfo?.mode,
604
- revicedFootfall: inputData.mappingInfo?.revicedFootfall,
605
- revicedPerc: inputData.mappingInfo?.revicedPerc,
606
- count: inputData.mappingInfo?.count,
607
- revisedDetail: inputData.mappingInfo?.revisedDetail,
608
- status: 'Closed',
609
- createdByEmail: req?.user?.email,
610
- createdByUserName: req?.user?.userName,
611
- createdByRole: req?.user?.role,
612
- } ) );
613
542
 
614
- record.mappingInfo = [ ...ticketData?.[0]?._source?.mappingInfo.slice( 0, -1 ),
615
- ...temp ];
616
- // If updating the mapping config to mark [i].status as 'Closed'
617
- // Make sure all relevant mappingInfo items of type 'approve' are set to status 'Closed'
618
- if ( Array.isArray( record.mappingInfo ) ) {
619
- record.mappingInfo = record.mappingInfo.map( ( item ) => {
620
- return {
621
- ...item,
622
- status: 'Closed',
623
- };
624
- } );
625
- }
626
- // If no review mapping existed, push a new one
627
- // if ( record.mappingInfo.length === 0 ) {
628
- // record.mappingInfo.push( {
629
- // type: 'tangoreview',
630
- // mode: inputData.mappingInfo?.mode,
631
- // revicedFootfall: inputData.mappingInfo?.revicedFootfall,
632
- // revicedPerc: inputData.mappingInfo?.revicedPerc,
633
- // count: inputData.mappingInfo?.count,
634
- // revisedDetail: inputData.mappingInfo?.revisedDetail,
635
- // status: 'Closed',
636
- // createdByEmail: req?.user?.email,
637
- // createdByUserName: req?.user?.userName,
638
- // createdByRole: req?.user?.role,
639
- // } );
640
- // }
641
- }
642
- record.mappingInfo.push(
643
- {
644
- type: 'finalRevision',
645
- mode: inputData.mappingInfo?.mode,
646
- revicedFootfall: revisedFootfall,
647
- revicedPerc: inputData.mappingInfo?.revicedPerc,
648
- count: inputData.mappingInfo?.count,
649
- revisedDetail: inputData.mappingInfo?.revisedDetail,
543
+ if ( Array.isArray( record.mappingInfo ) ) {
544
+ const temp = record.mappingInfo
545
+ .filter( ( item ) => item.type === 'tangoreview' )
546
+ .map( ( item ) => ( {
547
+ ...item,
650
548
  status: 'Closed',
651
549
  createdByEmail: req?.user?.email,
652
550
  createdByUserName: req?.user?.userName,
653
551
  createdByRole: req?.user?.role,
654
- createdAt: new Date(),
655
- },
656
- );
657
- } else if ( revised < tangoReview ) {
658
- // If ticket is closed, do not proceed with revision mapping
552
+ } ) );
659
553
 
660
- record.status = 'Closed - Accuracy Issue';
661
- // Only keep or modify mappingInfo items with type "review"
554
+ record.mappingInfo = [ ...ticketData?.[0]?._source?.mappingInfo.slice( 0, -1 ),
555
+ ...temp ];
662
556
  if ( Array.isArray( record.mappingInfo ) ) {
663
- const temp = record.mappingInfo
664
- .filter( ( item ) => item.type === 'tangoreview' )
665
- .map( ( item ) => ( {
666
- ...item,
667
- mode: inputData.mappingInfo?.mode,
668
- revicedFootfall: inputData.mappingInfo?.revicedFootfall,
669
- revicedPerc: inputData.mappingInfo?.revicedPerc,
670
- count: inputData.mappingInfo?.count,
671
- revisedDetail: inputData.mappingInfo?.revisedDetail,
672
- status: 'Closed',
673
- createdByEmail: req?.user?.email,
674
- createdByUserName: req?.user?.userName,
675
- createdByRole: req?.user?.role,
676
- } ) );
677
-
678
- record.mappingInfo = [ ...ticketData?.[0]?._source?.mappingInfo.slice( 0, -1 ),
679
- ...temp ];
680
- if ( Array.isArray( record.mappingInfo ) ) {
681
- record.mappingInfo = record.mappingInfo.map( ( item ) => {
682
- return {
683
- ...item,
684
- status: 'Closed',
685
- };
686
- } );
687
- }
688
- // If no review mapping existed, push a new one
689
- // if ( record.mappingInfo.length === 0 ) {
690
- // record.mappingInfo.push( {
691
- // type: 'tangoreview',
692
- // mode: inputData.mappingInfo?.mode,
693
- // revicedFootfall: inputData.mappingInfo?.revicedFootfall,
694
- // revicedPerc: inputData.mappingInfo?.revicedPerc,
695
- // count: inputData.mappingInfo?.count,
696
- // revisedDetail: inputData.mappingInfo?.revisedDetail,
697
- // status: 'Closed',
698
- // createdByEmail: req?.user?.email,
699
- // createdByUserName: req?.user?.userName,
700
- // createdByRole: req?.user?.role,
701
- // } );
702
- // }
557
+ record.mappingInfo = record.mappingInfo.map( ( item ) => {
558
+ return {
559
+ ...item,
560
+ status: 'Closed',
561
+ };
562
+ } );
703
563
  }
704
- } else {
705
- if ( Array.isArray( record.mappingInfo ) ) {
706
- const temp = record.mappingInfo
707
- .filter( ( item ) => item.type === 'tangoreview' )
708
- .map( ( item ) => ( {
709
- ...item,
710
- mode: inputData.mappingInfo?.mode,
711
- revicedFootfall: inputData.mappingInfo?.revicedFootfall,
712
- revicedPerc: inputData.mappingInfo?.revicedPerc,
713
- count: inputData.mappingInfo?.count,
714
- revisedDetail: inputData.mappingInfo?.revisedDetail,
715
- status: 'Closed',
716
- createdByEmail: req?.user?.email,
717
- createdByUserName: req?.user?.userName,
718
- createdByRole: req?.user?.role,
719
- } ) );
720
564
 
721
- record.mappingInfo = [ ...ticketData?.[0]?._source?.mappingInfo.slice( 0, -1 ),
722
- ...temp ];
723
- if ( Array.isArray( record.mappingInfo ) ) {
724
- record.mappingInfo = record.mappingInfo.map( ( item ) => {
725
- return {
726
- ...item,
727
- status: 'Closed',
728
- };
729
- } );
730
- }
731
- // If no review mapping existed, push a new one
732
- // if ( record.mappingInfo.length === 0 ) {
733
- // record.mappingInfo.push( {
734
- // type: 'tangoreview',
735
- // mode: inputData.mappingInfo?.mode,
736
- // revicedFootfall: inputData.mappingInfo?.revicedFootfall,
737
- // revicedPerc: inputData.mappingInfo?.revicedPerc,
738
- // count: inputData.mappingInfo?.count,
739
- // revisedDetail: inputData.mappingInfo?.revisedDetail,
740
- // status: 'Closed',
741
- // createdByEmail: req?.user?.email,
742
- // createdByUserName: req?.user?.userName,
743
- // createdByRole: req?.user?.role,
744
- // } );
745
- // }
746
- }
565
+
566
+ // If no review mapping existed, push a new one
567
+ // if ( record.mappingInfo.length === 0 ) {
568
+ // record.mappingInfo.push( {
569
+ // type: 'tangoreview',
570
+ // mode: inputData.mappingInfo?.mode,
571
+ // revicedFootfall: temp?.mappingInfo?.revicedFootfall,
572
+ // revicedPerc: temp?.mappingInfo?.revicedPerc,
573
+ // count: temp?.mappingInfo?.count,
574
+ // revisedDetail: temp?.mappingInfo?.revisedDetail,
575
+ // status: 'Closed',
576
+ // createdByEmail: req?.user?.email,
577
+ // createdByUserName: req?.user?.userName,
578
+ // createdByRole: req?.user?.role,
579
+ // } );
580
+ // }
747
581
  record.mappingInfo.push(
748
582
  {
749
583
  type: 'finalRevision',
750
- mode: inputData.mappingInfo?.mode,
751
- revicedFootfall: inputData.mappingInfo?.revicedFootfall,
752
- revicedPerc: inputData.mappingInfo?.revicedPerc,
753
- count: inputData.mappingInfo?.count,
754
- revisedDetail: inputData.mappingInfo?.revisedDetail,
584
+ mode: 'web',
585
+ revicedFootfall: temp?.[0]?.revicedFootfall,
586
+ revicedPerc: temp?.[0].revicedPerc,
587
+ count: temp?.[0].count,
588
+ revisedDetail: temp?.[0]?.revisedDetail,
755
589
  status: 'Closed',
756
590
  createdByEmail: req?.user?.email,
757
591
  createdByUserName: req?.user?.userName,
@@ -761,35 +595,10 @@ export async function tangoReviewAccuracyClosedTicket( req, res ) {
761
595
  );
762
596
  }
763
597
 
764
- if ( Ticket[0]?._source?.type==='store' ) {
765
- let findTagging = Ticket[0]?._source?.mappingInfo.filter( ( data ) => data.type==='tagging' );
766
- if ( findTagging?.length>0&&findTagging[0].createdByEmail!='' ) {
767
- let userData = await findOneUser( { email: findTagging[0]?.createdByEmail } );
768
- let title = `Received response for the Footfall ticket raised.`;
769
- let createdOn = dayjs( Ticket[0]?._source?.dateString ).format( 'DD MMM YYYY' );
770
- let description = `Raised on ${createdOn}`;
771
598
 
772
- let Data = {
773
- 'title': title,
774
- 'body': description,
775
- 'type': 'closed',
776
- 'date': Ticket[0]?._source?.dateString,
777
- 'storeId': Ticket[0]?._source?.storeId,
778
- 'clientId': Ticket[0]?._source?.clientId,
779
- 'ticketId': Ticket[0]?._source?.ticketId,
780
- };
781
- if ( userData && userData.fcmToken ) {
782
- const fcmToken = userData.fcmToken;
783
- await sendPushNotification( title, description, fcmToken, Data );
784
- }
785
- }
786
- }
787
599
  // return;
788
600
 
789
601
  let id = `${inputData.storeId}_${inputData.dateString}_footfall-directory-tagging`;
790
- if ( inputData.ticketType === 'internal' ) {
791
- id = `${inputData.storeId}_${inputData.dateString}_internal_footfall-directory-tagging`;
792
- }
793
602
 
794
603
  const insertResult = await updateOpenSearchData( openSearch.footfallDirectory, id, { doc: record } );
795
604
 
@@ -800,7 +609,7 @@ export async function tangoReviewAccuracyClosedTicket( req, res ) {
800
609
  }
801
610
  } catch ( error ) {
802
611
  const err = error.message || 'Internal Server Error';
803
- logger.error( { error: err, funtion: 'tangoReviewTicket' } );
612
+ logger.error( { error: error, funtion: 'tangoReviewAccuracyClosedTicket' } );
804
613
  return res.sendError( err, 500 );
805
614
  }
806
615
  }
@@ -3414,3 +3223,36 @@ export async function checkTicketExists( req, res ) {
3414
3223
  return res.sendError( err, 500 );
3415
3224
  }
3416
3225
  }
3226
+
3227
+
3228
+ export async function getAccuracyIssues( req, res ) {
3229
+ try {
3230
+ const inputData = req.query;
3231
+
3232
+
3233
+ const getIsues = await findStoreAccuracIssues( { clientId: inputData.clientId, isActive: true }, { issueName: 1 } );
3234
+ // const mode = inputData.mode || '';
3235
+ res.sendSuccess( { result: getIsues|| [] } );
3236
+ // Return batch summary
3237
+ } catch ( error ) {
3238
+ const err = error.message;
3239
+ logger.info( { error: err, function: 'getAccuracyIssues' } );
3240
+ return res.sendError( err, 500 );
3241
+ }
3242
+ }
3243
+
3244
+ export async function updateAccuracyIssues( req, res ) {
3245
+ try {
3246
+ const inputData = req.query;
3247
+
3248
+
3249
+ const getIsues = await upsertStoreAccuracIssues( { clientId: inputData.clientId, issueName: inputData?.issueName }, { issueName: inputData?.issueName, isActive: true } );
3250
+ // const mode = inputData.mode || '';
3251
+ res.sendSuccess( { result: getIsues|| [] } );
3252
+ // Return batch summary
3253
+ } catch ( error ) {
3254
+ const err = error.message;
3255
+ logger.info( { error: err, function: 'putAccuracyIssues' } );
3256
+ return res.sendError( err, 500 );
3257
+ }
3258
+ }
@@ -589,3 +589,27 @@ export const multiCloseTicketSchema = Joi.object().keys( {
589
589
  export const multiCloseTicketValid = {
590
590
  body: multiCloseTicketSchema,
591
591
  };
592
+
593
+
594
+ export const getAccuracyIssuesSchema = Joi.object().keys( {
595
+
596
+
597
+ clientId: Joi.string().required(),
598
+
599
+ } );
600
+
601
+ export const getAccuracyIssuesValid = {
602
+ query: getAccuracyIssuesSchema,
603
+ };
604
+
605
+ export const updateAccuracyIssuesSchema = Joi.object().keys( {
606
+
607
+
608
+ clientId: Joi.string().required(),
609
+ issueName: Joi.string().required(),
610
+
611
+ } );
612
+
613
+ export const updateAccuracyIssuesValid = {
614
+ query: updateAccuracyIssuesSchema,
615
+ };
@@ -1,7 +1,7 @@
1
1
  import express from 'express';
2
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 } from '../controllers/footfallDirectory.controllers.js';
4
- import { createTicketValid, downloadTicketsValid, getTaggedStoresValid, getTicketsValid, openTicketListValid, reviewerListValid, ticketListValid, ticketSummaryValid, updateStatusValid, assignTicketValid, updateTempStatusValid, updateTicketStatusValid, tangoReviewTicketValid, multiCloseTicketValid, tangoReviewAccuracyClosedTicketValid } from '../dtos/footfallDirectory.dtos.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();
@@ -11,7 +11,7 @@ footfallDirectoryRouter.post( '/create-internalticket', isAllowedSessionHandler,
11
11
  footfallDirectoryRouter.post( '/checkTicketExists', isAllowedSessionHandler, checkTicketExists );
12
12
 
13
13
  footfallDirectoryRouter.post( '/tango-review-ticket', isAllowedSessionHandler, validate( tangoReviewTicketValid ), tangoReviewTicket );
14
- footfallDirectoryRouter.post( '/tango-review-ticket', isAllowedSessionHandler, validate( tangoReviewAccuracyClosedTicketValid ), tangoReviewAccuracyClosedTicket );
14
+ footfallDirectoryRouter.post( '/tango-review-accuracy-ticket', isAllowedSessionHandler, validate( tangoReviewAccuracyClosedTicketValid ), tangoReviewAccuracyClosedTicket );
15
15
 
16
16
  footfallDirectoryRouter.get( '/ticket-summary', isAllowedSessionHandler, bulkValidate( ticketSummaryValid ), ticketSummary );
17
17
 
@@ -28,4 +28,7 @@ footfallDirectoryRouter.post( '/update-temp-status', isAllowedSessionHandler, bu
28
28
  footfallDirectoryRouter.post( '/update-ticket-status', isAllowedSessionHandler, bulkValidate( updateTicketStatusValid ), updateUserTicketStatus );
29
29
  footfallDirectoryRouter.post( '/multi-close-tickets', isAllowedSessionHandler, bulkValidate( multiCloseTicketValid ), multiCloseTicket );
30
30
 
31
+ footfallDirectoryRouter.get( '/get-accuarcy-issues', isAllowedSessionHandler, bulkValidate( getAccuracyIssuesValid ), getAccuracyIssues );
32
+ footfallDirectoryRouter.put( '/update-accuarcy-issues', isAllowedSessionHandler, bulkValidate( updateAccuracyIssuesValid ), updateAccuracyIssues );
33
+
31
34
 
@@ -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
+ }