192 lines
5.0 KiB
Python
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
|