from typing import TYPE_CHECKING, Optional from sqlmodel import ( Session, Field, Relationship, ) from . import mixin from .base import ( BaseSQLModel, DocumentedIntFlag, auto_enum, RowId, ) if TYPE_CHECKING: from .user import User from .team import Team # region # Member / Teams ###################################################### class MemberRank(DocumentedIntFlag): TEAM_MEMBER = auto_enum() TEAM_ASSISTANT_LEADER = auto_enum() TEAM_LEADER = auto_enum() DIVISION_LEADER = auto_enum() VOLUNTEER = auto_enum() # ############################################################################## # Shared properties class MemberTeamLinkBase(BaseSQLModel): rank: MemberRank = Field(default=MemberRank.TEAM_MEMBER, nullable=False) # Properties to receive via API on creation class MemberTeamLinkCreate(MemberTeamLinkBase): member_id: RowId = Field(default=None, nullable=False) # Properties to receive via API on update, all are optional class MemberTeamLinkUpdate(MemberTeamLinkBase): pass # Database model, database table inferred from class name class MemberTeamLink(MemberTeamLinkBase, table=True): # --- database only items -------------------------------------------------- # --- read only items ------------------------------------------------------ # --- back_populates links ------------------------------------------------- member_id: RowId = Field( foreign_key="member.id", primary_key=True, nullable=False, ondelete="CASCADE", ) team_id: RowId = Field( foreign_key="team.id", primary_key=True, nullable=False, ondelete="CASCADE", ) member: "Member" = Relationship(back_populates="team_links") team: "Team" = Relationship(back_populates="member_links") # --- CRUD actions --------------------------------------------------------- @classmethod def create(cls, *, session: Session, create_obj: MemberTeamLinkCreate, team: "Team") -> "MemberTeamLink": data_obj = create_obj.model_dump(exclude_unset=True) db_obj = cls.model_validate(data_obj, update={"team_id": team.id}) session.add(db_obj) session.commit() session.refresh(db_obj) return db_obj @classmethod def update( cls, *, session: Session, db_obj: "MemberTeamLink", in_obj: MemberTeamLinkUpdate ) -> "MemberTeamLink": data_obj = in_obj.model_dump(exclude_unset=True) db_obj.sqlmodel_update(data_obj) session.add(db_obj) session.commit() session.refresh(db_obj) return db_obj # Properties to return via API class MemberTeamLinkPublic(MemberTeamLinkBase): member_id: RowId team_id: RowId class MemberTeamLinksPublic(BaseSQLModel): data: list[MemberTeamLinkPublic] count: int # endregion # region # Member ############################################################## # Shared properties class MemberBase( mixin.Name, mixin.Contact, mixin.ScoutingId, mixin.Comment, mixin.Allergy, mixin.Birthday, mixin.Canceled, BaseSQLModel, ): pass # Properties to receive via API on creation class MemberCreate(MemberBase): pass # Properties to receive via API on update, all are optional class MemberUpdate(MemberBase): pass # Database model, database table inferred from class name class Member(mixin.RowId, mixin.Created, MemberBase, table=True): # --- database only items -------------------------------------------------- # --- read only items ------------------------------------------------------ # --- back_populates links ------------------------------------------------- user: Optional["User"] = Relationship( back_populates="member", sa_relationship_kwargs={"foreign_keys": "User.member_id"}, ) team_links: list["MemberTeamLink"] = Relationship(back_populates="member", cascade_delete=True) # --- CRUD actions --------------------------------------------------------- @classmethod def create(cls, *, session: Session, create_obj: MemberCreate, user: Optional["User"] = None) -> "Member": data_obj = create_obj.model_dump(exclude_unset=True) extra_fields = {} if user: extra_fields["created_by"] = user.id db_obj = cls.model_validate(data_obj, update=extra_fields) session.add(db_obj) session.commit() session.refresh(db_obj) return db_obj @classmethod def update( cls, *, session: Session, db_obj: "Member", in_obj: MemberUpdate ) -> "Member": data_obj = in_obj.model_dump(exclude_unset=True) db_obj.sqlmodel_update(data_obj) session.add(db_obj) session.commit() session.refresh(db_obj) return db_obj # Properties to return via API, id is always required class MemberPublic(mixin.RowIdPublic, MemberBase): # TODO: Return user_id pass class MembersPublic(BaseSQLModel): data: list[MemberPublic] count: int # endregion