tango-app-api-infra 3.8.1-beta.13 → 3.8.1-beta.15

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.13",
3
+ "version": "3.8.1-beta.15",
4
4
  "description": "infra",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -1,5 +1,5 @@
1
1
  import { download, logger, sendMessageToQueue } from 'tango-app-api-middleware';
2
- import { bulkUpdate, getOpenSearchCount, getOpenSearchData, insertWithId, updateOpenSearchData } from 'tango-app-api-middleware/src/utils/openSearch.js';
2
+ import { bulkUpdate, getOpenSearchById, 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';
5
5
 
@@ -593,47 +593,94 @@ export async function updateTicketStatus( data, openSearch, temp ) {
593
593
  const splitId = id.split( '_' );
594
594
  const storeId = splitId[0];
595
595
  const dateString = splitId[1];
596
- if ( data?.duplicateStatus !== 'pending' && data?.employeeStatus !== 'pending' && data?.houseKeepingStatus !== 'pending' ) {
596
+ const {
597
+ duplicateStatus,
598
+ employeeStatus,
599
+ houseKeepingStatus,
600
+ } = data;
601
+ const statusList = [ duplicateStatus, employeeStatus, houseKeepingStatus ];
602
+ // Filter out undefined/null statuses
603
+ const existingStatuses = statusList.filter( ( status ) => status != null );
604
+
605
+ // Check if **none** of the existing statuses are 'pending'
606
+ const allNotPending = existingStatuses.every( ( status ) => status !== 'pending' );
607
+
608
+ if ( allNotPending && existingStatuses.length > 0 ) {
597
609
  data.status = 'closed';
598
610
  }
599
611
  let tempId = [];
600
612
  const { _id, ...updateData } = data;
601
- await updateOpenSearchData( openSearch.footfallDirectory, _id, { doc: updateData } );
613
+ const getExistingOne = await getOpenSearchById( openSearch.footfallDirectory, _id );
614
+ const source = getExistingOne?.body?._source;
602
615
  let bulkBody = [];
603
616
  if ( data?.duplicateImages?.length > 0 ) {
604
- for ( let duplicate of data.duplicateImages ) {
617
+ updateData.duplicateImages = await mergeDuplicateImagesWithUncheck( getExistingOne?.body?._source?.duplicateImages, data?.duplicateImages, data?.duplicateStatus );
618
+ logger.info( { updateData: updateData, existeg: getExistingOne?.body?._source?.duplicateImages, sttaus: data?.duplicateStatus } );
619
+ await updateOpenSearchData( openSearch.footfallDirectory, _id, { doc: updateData } );
620
+ for ( let duplicate of updateData?.duplicateImages ) {
605
621
  bulkBody.push(
606
622
  { update: { _index: openSearch.revop, _id: `${storeId}_${dateString}_${duplicate.timeRange}_${duplicate.tempId}` } },
607
- { doc: { duplicateImage: duplicate.duplicateImage } },
623
+ { doc: { duplicateImage: duplicate.duplicateImages } },
608
624
  );
609
625
  duplicate?.data?.map( ( item ) => {
610
626
  item.isChecked == true ? tempId.push( item.tempId ) : null;
611
627
  bulkBody.push(
612
628
  { update: { _index: openSearch.revop, _id: `${storeId}_${dateString}_${item.timeRange}_${item.tempId}` } },
613
- { doc: { isChecked: item.isChecked } },
629
+ { doc: { isChecked: item.isChecked, status: item?.isChecked == true? 'approved':'rejected' } },
614
630
  );
615
631
  } );
616
632
  }
633
+ logger.info( { tempId: tempId } );
634
+ await updateOpenSearchData( openSearch.footfallDirectory, _id, { doc: { duplicateACCount: tempId?.length || 0 } } );
617
635
  }
618
636
  if ( data?.employee?.length > 0 ) {
619
- for ( let employee of data.employee ) {
620
- employee.isChecked == true ? tempId.push( employee.tempId ) : null;
621
- bulkBody.push(
622
- { update: { _index: openSearch.revop, _id: `${storeId}_${dateString}_${employee.timeRange}_${employee.tempId}` } },
623
- { doc: { isChecked: employee.isChecked } },
624
- );
637
+ const updatedEmployee = updateEmployeeCheckFlags(
638
+ source.employee,
639
+ updateData.employee,
640
+ data.employeeStatus,
641
+ );
642
+ updateData.employee = updatedEmployee;
643
+ await updateOpenSearchData( openSearch.footfallDirectory, _id, { doc: updateData } );
644
+ for ( let employee of updateData?.employee ) {
645
+ ( employee.isChecked == true ) ? tempId.push( employee.tempId ) : null;
646
+ bulkBody.push(
647
+ { update: { _index: openSearch.revop, _id: `${storeId}_${dateString}_${employee.timeRange}_${employee.tempId}` } },
648
+ { doc: { isChecked: employee.isChecked, status: employee?.isChecked == true? 'approved':'rejected' } },
649
+ );
625
650
  }
651
+ await updateOpenSearchData( openSearch.footfallDirectory, _id, { doc: { employeeACCount: tempId?.length || 0 } } );
626
652
  }
627
653
  if ( data?.houseKeeping?.length > 0 ) {
628
- for ( let houseKeeping of data.houseKeeping ) {
654
+ const updatedHouseKeeping = updateEmployeeCheckFlags(
655
+ source?.houseKeeping,
656
+ updateData?.houseKeeping,
657
+ data.houseKeepingStatus,
658
+ );
659
+ updateData.houseKeeping = updatedHouseKeeping;
660
+
661
+ await updateOpenSearchData( openSearch.footfallDirectory, _id, { doc: updateData } );
662
+
663
+
664
+ for ( let houseKeeping of updateData?.houseKeeping ) {
629
665
  houseKeeping.isChecked == true ? tempId.push( houseKeeping.tempId ) : null;
630
666
  bulkBody.push(
631
667
  { update: { _index: openSearch.revop, _id: `${storeId}_${dateString}_${houseKeeping.timeRange}_${houseKeeping.tempId}` } },
632
- { doc: { isChecked: houseKeeping.isChecked } },
668
+ { doc: { isChecked: houseKeeping.isChecked, status: houseKeeping?.isChecked == true? 'approved':'rejected' } },
633
669
  );
634
670
  }
671
+ await updateOpenSearchData( openSearch.footfallDirectory, _id, { doc: { houseKeepingACCount: tempId?.length || 0 } } );
635
672
  }
636
673
  temp.push( storeId );
674
+ if ( bulkBody.length > 0 ) {
675
+ const res = await bulkUpdate( bulkBody );
676
+ if ( res?.errors ) {
677
+ logger.error( 'Bulk update errors:', res.items );
678
+ return { success: false, errors: res.items };
679
+ } else {
680
+ logger.error( 'Bulk status update successful.' );
681
+ return { success: true };
682
+ }
683
+ }
637
684
  // if ( inputData.status == 'closed' ) {
638
685
  // const isSendMessge = await sendSqsMessage( inputData, tempId );
639
686
  // if ( isSendMessge ==true ) {
@@ -647,6 +694,84 @@ export async function updateTicketStatus( data, openSearch, temp ) {
647
694
  // }
648
695
  }
649
696
 
697
+ function updateEmployeeCheckFlags( existingEmployees, inputEmployees, status ) {
698
+ // Step 1: Create a Set of tempIds from input (which are all isChecked: true)
699
+ const checkedTempIds = new Set( inputEmployees.map( ( emp ) => emp.tempId ) );
700
+
701
+ // Step 2: Loop through all existing and update isChecked accordingly
702
+ const updatedEmployees = existingEmployees.map( ( emp ) => ( {
703
+ ...emp,
704
+ isChecked: status === 'rejected'? !checkedTempIds.has( emp.tempId ):checkedTempIds.has( emp.tempId ),
705
+ } ) );
706
+
707
+ return updatedEmployees;
708
+ }
709
+
710
+
711
+ // function mergeDuplicateImagesWithUncheck( existingData, inputData, status ) {
712
+ // const inputImageMap = new Map();
713
+
714
+ // // Step 1: Build a Map of parentTempId -> Set of childTempId from input
715
+ // for ( const parent of inputData ) {
716
+ // inputImageMap.set( parent.tempId, new Set( ( parent.data || [] ).map( ( child ) => child.tempId ) ) );
717
+ // }
718
+
719
+ // // Step 2: Loop through existing data and update isChecked flags
720
+ // return existingData.map( ( existingParent ) => {
721
+ // const parentTempId = existingParent.tempId;
722
+ // const allowedCheckedChildIds = inputImageMap.get( parentTempId ) || new Set();
723
+
724
+ // const updatedData = ( existingParent.data || [] ).map( ( child ) => ( {
725
+ // ...child,
726
+ // isChecked: status === 'rejected'? !allowedCheckedChildIds.has( child.tempId ):allowedCheckedChildIds.has( child.tempId ),
727
+ // } ) );
728
+ // return {
729
+ // ...existingParent,
730
+ // data: updatedData,
731
+ // };
732
+ // } );
733
+ // }
734
+
735
+ function mergeDuplicateImagesWithUncheck( existingData, inputData, status ) {
736
+ const inputImageMap = new Map();
737
+
738
+ // Step 1: Build map of parentTempId -> Set of selected childTempIds
739
+ for ( const parent of inputData ) {
740
+ const selectedChildIds = new Set(
741
+ ( parent.data || [] )
742
+ .filter( ( child ) => child.selected )
743
+ .map( ( child ) => child.tempId ),
744
+ );
745
+ inputImageMap.set( parent.tempId, selectedChildIds );
746
+ }
747
+
748
+ // Step 2: Merge isChecked correctly per parent-child match
749
+ return existingData.map( ( existingParent ) => {
750
+ const parentTempId = existingParent.tempId;
751
+
752
+ // Get selected children for this specific parent
753
+ const selectedChildIds = inputImageMap.get( parentTempId ) || new Set();
754
+
755
+ const updatedData = ( existingParent.data || [] ).map( ( child ) => {
756
+ return {
757
+ ...child,
758
+ isChecked:
759
+ status === 'approved' ? selectedChildIds.has( child.tempId ) : false,
760
+ };
761
+ } );
762
+
763
+ // Also update the parent isChecked if all children are false
764
+ const anyChildChecked = updatedData.some( ( child ) => child.isChecked );
765
+
766
+ return {
767
+ ...existingParent,
768
+ isChecked: anyChildChecked,
769
+ data: updatedData,
770
+ };
771
+ } );
772
+ }
773
+
774
+
650
775
  export async function sendSqsMessage( inputData, tempId ) {
651
776
  const sqs = JSON.parse( process.env.sqs );
652
777
  const sqsProduceQueue = {
@@ -284,6 +284,7 @@ export const updateStatusSchemea =Joi.object().keys( {
284
284
  exitTime: Joi.string().required(),
285
285
  timeRange: Joi.string().required(),
286
286
  isChecked: Joi.boolean().required(),
287
+ selected: Joi.boolean().optional(),
287
288
  data: Joi.array().items(
288
289
  Joi.object( {
289
290
  tempId: Joi.number().required(),
@@ -292,6 +293,7 @@ export const updateStatusSchemea =Joi.object().keys( {
292
293
  exitTime: Joi.string().required(),
293
294
  timeRange: Joi.string().required(),
294
295
  isChecked: Joi.boolean().required(),
296
+ selected: Joi.boolean().optional(),
295
297
  } ),
296
298
  ).optional(),
297
299
  } ) ).optional(),
@@ -302,6 +304,7 @@ export const updateStatusSchemea =Joi.object().keys( {
302
304
  exitTime: Joi.string().required(),
303
305
  timeRange: Joi.string().required(),
304
306
  isChecked: Joi.boolean().required(),
307
+ selected: Joi.boolean().optional(),
305
308
 
306
309
  } ) ).optional(),
307
310
  employee: Joi.array().items( Joi.object( {
@@ -311,11 +314,12 @@ export const updateStatusSchemea =Joi.object().keys( {
311
314
  exitTime: Joi.string().required(),
312
315
  timeRange: Joi.string().required(),
313
316
  isChecked: Joi.boolean().required(),
317
+ selected: Joi.boolean().optional(),
314
318
 
315
319
  } ) ).optional(),
316
- duplicateStatus: Joi.string().required(),
317
- employeeStatus: Joi.string().required(),
318
- houseKeepingStatus: Joi.string().required(),
320
+ duplicateStatus: Joi.string().optional(),
321
+ employeeStatus: Joi.string().optional(),
322
+ houseKeepingStatus: Joi.string().optional(),
319
323
  } ) ).required(),
320
324
 
321
325
  } );
@@ -12,6 +12,5 @@ footfallDirectoryRouter.get( '/ticket-summary', isAllowedSessionHandler, bulkVal
12
12
  footfallDirectoryRouter.get( '/ticket-list', isAllowedSessionHandler, bulkValidate( ticketListValid ), ticketList );
13
13
  footfallDirectoryRouter.get( '/get-tickets', isAllowedSessionHandler, bulkValidate( getTicketsValid ), getTickets );
14
14
  footfallDirectoryRouter.get( '/get-tagged-stores', isAllowedSessionHandler, bulkValidate( getTaggedStoresValid ), getAssinedStore, getClusters, getTaggedStores );
15
-
16
15
  footfallDirectoryRouter.put( '/update-status', isAllowedSessionHandler, bulkValidate( updateStatusValid ), updateStatus );
17
16
 
@@ -47,7 +47,6 @@ export async function getClusters( req, res, next ) {
47
47
  // logger.info( { assignedStores, clusters } );
48
48
  let filter =[
49
49
  {
50
-
51
50
  clientId: inputData.clientId,
52
51
  },
53
52
  ];