Files
score/backend/app/models/member.py
2025-06-17 21:23:14 +02:00

192 lines
5.0 KiB
Python

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