@@ -617,6 +617,44 @@ def has_existing_stint(
617617 return True
618618 return False
619619
620+ def is_blocked_by_deleted_row (
621+ self ,
622+ deleted_rows : list [dict ],
623+ organization_id : str ,
624+ date_start : date | None ,
625+ date_end : date | None ,
626+ ) -> bool :
627+ """True when a soft-deleted stint should not be re-created from the file."""
628+ incoming_undated = date_start is None and date_end is None
629+ for row in deleted_rows :
630+ if str (row ["organizationId" ]) != organization_id :
631+ continue
632+
633+ existing_start = row .get ("dateStart" )
634+ existing_end = row .get ("dateEnd" )
635+ if isinstance (existing_start , datetime ):
636+ existing_start = existing_start .date ()
637+ if isinstance (existing_end , datetime ):
638+ existing_end = existing_end .date ()
639+
640+ if incoming_undated :
641+ if existing_start is None and existing_end is None :
642+ return True
643+ if self .is_undated_or_open_ended (existing_start , existing_end ):
644+ return True
645+ continue
646+
647+ if existing_start is None and existing_end is None :
648+ continue
649+
650+ min_date = date .min
651+ max_date = date .max
652+ if (existing_start or min_date ) <= (date_end or max_date ) and (
653+ existing_end or max_date
654+ ) >= (date_start or min_date ):
655+ return True
656+ return False
657+
620658 @staticmethod
621659 def affiliation_stint_key (
622660 contributor : AffiliationContributor ,
@@ -801,27 +839,47 @@ async def apply_affiliations(
801839 return
802840
803841 member_ids_to_fetch = list ({member_id for member_id , _ , _ in resolved_stints })
804- member_organizations = await fetch_member_organizations (member_ids_to_fetch )
805- segment_affiliations = await fetch_segment_affiliations (member_ids_to_fetch , segment_id )
842+ all_member_organizations = await fetch_member_organizations (member_ids_to_fetch )
843+ all_segment_affiliations = await fetch_segment_affiliations (
844+ member_ids_to_fetch , segment_id
845+ )
806846
807847 member_organizations_by_member : dict [str , list [dict ]] = {}
808- for row in member_organizations :
809- member_organizations_by_member .setdefault (str (row ["memberId" ]), []).append (row )
848+ deleted_member_organizations_by_member : dict [str , list [dict ]] = {}
849+ for row in all_member_organizations :
850+ member_id = str (row ["memberId" ])
851+ if row .get ("deletedAt" ):
852+ if row .get ("source" ) != "project-registry" :
853+ continue
854+ deleted_member_organizations_by_member .setdefault (member_id , []).append (row )
855+ else :
856+ member_organizations_by_member .setdefault (member_id , []).append (row )
810857
811858 segment_affiliations_by_member : dict [str , list [dict ]] = {}
812- for row in segment_affiliations :
813- segment_affiliations_by_member .setdefault (str (row ["memberId" ]), []).append (row )
859+ deleted_segment_affiliations_by_member : dict [str , list [dict ]] = {}
860+ for row in all_segment_affiliations :
861+ member_id = str (row ["memberId" ])
862+ if row .get ("deletedAt" ):
863+ deleted_segment_affiliations_by_member .setdefault (member_id , []).append (row )
864+ else :
865+ segment_affiliations_by_member .setdefault (member_id , []).append (row )
814866
815867 mo_inserts : list [dict ] = []
816868 msa_inserts : list [dict ] = []
817869
818870 for member_id , organization_id , organization in resolved_stints :
819871 existing_mos = member_organizations_by_member .get (member_id , [])
820872 existing_msas = segment_affiliations_by_member .get (member_id , [])
873+ deleted_mos = deleted_member_organizations_by_member .get (member_id , [])
874+ deleted_msas = deleted_segment_affiliations_by_member .get (member_id , [])
821875 date_start = organization .date_start
822876 date_end = organization .date_end
823877
824- if not self .has_existing_stint (existing_mos , organization_id , date_start , date_end ):
878+ if not self .has_existing_stint (
879+ existing_mos , organization_id , date_start , date_end
880+ ) and not self .is_blocked_by_deleted_row (
881+ deleted_mos , organization_id , date_start , date_end
882+ ):
825883 mo_inserts .append (
826884 {
827885 "member_id" : member_id ,
@@ -832,7 +890,11 @@ async def apply_affiliations(
832890 }
833891 )
834892
835- if not self .has_existing_stint (existing_msas , organization_id , date_start , date_end ):
893+ if not self .has_existing_stint (
894+ existing_msas , organization_id , date_start , date_end
895+ ) and not self .is_blocked_by_deleted_row (
896+ deleted_msas , organization_id , date_start , date_end
897+ ):
836898 msa_inserts .append (
837899 {
838900 "member_id" : member_id ,
0 commit comments