@@ -586,7 +586,7 @@ class NMA_SurfaceWaterData(Base):
586586
587587 # Legacy PK (for audit)
588588 surface_id : Mapped [uuid .UUID ] = mapped_column (
589- "SurfaceID" , UUID (as_uuid = True ), nullable = False
589+ "SurfaceID" , UUID (as_uuid = True ), nullable = False , unique = True
590590 )
591591
592592 # Legacy FK (for audit)
@@ -617,6 +617,12 @@ class NMA_SurfaceWaterData(Base):
617617
618618 # Relationships
619619 thing : Mapped ["Thing" ] = relationship ("Thing" , back_populates = "surface_water_data" )
620+ surface_water_photos : Mapped [list ["NMA_SurfaceWaterPhotos" ]] = relationship (
621+ "NMA_SurfaceWaterPhotos" ,
622+ back_populates = "surface_water_data" ,
623+ cascade = "all, delete-orphan" ,
624+ passive_deletes = True ,
625+ )
620626
621627 @validates ("thing_id" )
622628 def validate_thing_id (self , key , value ):
@@ -632,7 +638,7 @@ class NMA_SurfaceWaterPhotos(Base):
632638 """
633639 Legacy SurfaceWaterPhotos table from NM_Aquifer.
634640
635- Note: This table is OUT OF SCOPE for refactoring (not a Thing child) .
641+ Note: This table is a child of NMA_SurfaceWaterData via SurfaceID .
636642 """
637643
638644 __tablename__ = "NMA_SurfaceWaterPhotos"
@@ -643,21 +649,39 @@ class NMA_SurfaceWaterPhotos(Base):
643649 )
644650
645651 # FK
646- # FK not assigned.
652+ surface_id : Mapped [uuid .UUID ] = mapped_column (
653+ "SurfaceID" ,
654+ UUID (as_uuid = True ),
655+ ForeignKey ("NMA_SurfaceWaterData.SurfaceID" , ondelete = "CASCADE" ),
656+ nullable = False ,
657+ )
647658
648659 # Legacy PK (for audit)
649660 # Current `global_id` is also the original PK in the legacy DB
650661
651662 # Legacy FK (for audit)
652- surface_id : Mapped [Optional [uuid .UUID ]] = mapped_column (
653- "SurfaceID" , UUID (as_uuid = True )
654- )
663+ # surface_id is also the legacy FK in the source table.
655664
656665 # Additional columns
657666 point_id : Mapped [str ] = mapped_column ("PointID" , String (50 ), nullable = False )
658667 ole_path : Mapped [Optional [str ]] = mapped_column ("OLEPath" , String (50 ))
659668 object_id : Mapped [Optional [int ]] = mapped_column ("OBJECTID" , Integer , unique = True )
660669
670+ # Relationships
671+ surface_water_data : Mapped ["NMA_SurfaceWaterData" ] = relationship (
672+ "NMA_SurfaceWaterData" , back_populates = "surface_water_photos"
673+ )
674+
675+ @validates ("surface_id" )
676+ def validate_surface_id (self , key , value ):
677+ """Prevent orphan NMA_SurfaceWaterPhotos - must have a parent NMA_SurfaceWaterData."""
678+ if value is None :
679+ raise ValueError (
680+ "NMA_SurfaceWaterPhotos requires a parent NMA_SurfaceWaterData "
681+ "(surface_id cannot be None)"
682+ )
683+ return value
684+
661685
662686class NMA_WeatherData (Base ):
663687 """
@@ -678,7 +702,7 @@ class NMA_WeatherData(Base):
678702
679703 # Legacy PK (for audit)
680704 weather_id : Mapped [Optional [uuid .UUID ]] = mapped_column (
681- "WeatherID" , UUID (as_uuid = True )
705+ "WeatherID" , UUID (as_uuid = True ), unique = True
682706 )
683707
684708 # Legacy FK (for audit)
@@ -691,6 +715,12 @@ class NMA_WeatherData(Base):
691715
692716 # Relationships
693717 thing : Mapped ["Thing" ] = relationship ("Thing" , back_populates = "weather_data" )
718+ weather_photos : Mapped [list ["NMA_WeatherPhotos" ]] = relationship (
719+ "NMA_WeatherPhotos" ,
720+ back_populates = "weather_data" ,
721+ cascade = "all, delete-orphan" ,
722+ passive_deletes = True ,
723+ )
694724
695725 @validates ("thing_id" )
696726 def validate_thing_id (self , key , value ):
@@ -706,7 +736,7 @@ class NMA_WeatherPhotos(Base):
706736 """
707737 Legacy WeatherPhotos table from NM_Aquifer.
708738
709- Note: This table is OUT OF SCOPE for refactoring (not a Thing child) .
739+ Note: This table is a child of NMA_WeatherData via WeatherID .
710740 """
711741
712742 __tablename__ = "NMA_WeatherPhotos"
@@ -717,21 +747,39 @@ class NMA_WeatherPhotos(Base):
717747 )
718748
719749 # FK:
720- # FK not assigned.
750+ weather_id : Mapped [uuid .UUID ] = mapped_column (
751+ "WeatherID" ,
752+ UUID (as_uuid = True ),
753+ ForeignKey ("NMA_WeatherData.WeatherID" , ondelete = "CASCADE" ),
754+ nullable = False ,
755+ )
721756
722757 # Legacy PK (for audit):
723758 # Current `global_id` is also the original PK in the legacy DB
724759
725760 # Legacy FK (for audit):
726- weather_id : Mapped [Optional [uuid .UUID ]] = mapped_column (
727- "WeatherID" , UUID (as_uuid = True )
728- )
761+ # weather_id is also the legacy FK in the source table.
729762
730763 # Additional columns
731764 point_id : Mapped [str ] = mapped_column ("PointID" , String (50 ), nullable = False )
732765 ole_path : Mapped [Optional [str ]] = mapped_column ("OLEPath" , String (50 ))
733766 object_id : Mapped [Optional [int ]] = mapped_column ("OBJECTID" , Integer , unique = True )
734767
768+ # Relationships
769+ weather_data : Mapped ["NMA_WeatherData" ] = relationship (
770+ "NMA_WeatherData" , back_populates = "weather_photos"
771+ )
772+
773+ @validates ("weather_id" )
774+ def validate_weather_id (self , key , value ):
775+ """Prevent orphan NMA_WeatherPhotos - must have a parent NMA_WeatherData."""
776+ if value is None :
777+ raise ValueError (
778+ "NMA_WeatherPhotos requires a parent NMA_WeatherData "
779+ "(weather_id cannot be None)"
780+ )
781+ return value
782+
735783
736784class NMA_Soil_Rock_Results (Base ):
737785 """
0 commit comments