147 lines
5.3 KiB
Python
147 lines
5.3 KiB
Python
from __future__ import annotations # TODO: Remove if python requirement is >= 3.10
|
|
|
|
from datetime import datetime
|
|
from typing import Optional, Union, List
|
|
|
|
from sqlalchemy import UniqueConstraint
|
|
|
|
from flaschengeist.models import ModelSerializeMixin, UtcDateTime, Serial
|
|
from flaschengeist.models.user import User
|
|
from flaschengeist.database import db
|
|
|
|
#########
|
|
# Types #
|
|
#########
|
|
|
|
_table_prefix_ = "events_"
|
|
|
|
|
|
class EventType(db.Model, ModelSerializeMixin):
|
|
__allow_unmapped__ = True
|
|
__tablename__ = _table_prefix_ + "event_type"
|
|
id: int = db.Column(Serial, primary_key=True)
|
|
name: str = db.Column(db.String(30), nullable=False, unique=True)
|
|
|
|
|
|
class JobType(db.Model, ModelSerializeMixin):
|
|
__tablename__ = _table_prefix_ + "job_type"
|
|
id: int = db.Column(Serial, primary_key=True)
|
|
name: str = db.Column(db.String(30), nullable=False, unique=True)
|
|
|
|
|
|
########
|
|
# Jobs #
|
|
########
|
|
|
|
|
|
class Service(db.Model, ModelSerializeMixin):
|
|
__allow_unmapped__ = True
|
|
__tablename__ = _table_prefix_ + "service"
|
|
userid: str = ""
|
|
is_backup: bool = db.Column(db.Boolean, default=False)
|
|
value: float = db.Column(db.Numeric(precision=3, scale=2, asdecimal=False), nullable=False)
|
|
|
|
_job_id = db.Column(
|
|
"job_id",
|
|
Serial,
|
|
db.ForeignKey(f"{_table_prefix_}job.id"),
|
|
nullable=False,
|
|
primary_key=True,
|
|
)
|
|
_user_id = db.Column("user_id", Serial, db.ForeignKey("user.id"), nullable=False, primary_key=True)
|
|
|
|
user_: User = db.relationship("User")
|
|
job_: Job = db.relationship("Job")
|
|
|
|
@property
|
|
def userid(self):
|
|
return self.user_.userid
|
|
|
|
|
|
class Job(db.Model, ModelSerializeMixin):
|
|
__allow_unmapped__ = True
|
|
__tablename__ = _table_prefix_ + "job"
|
|
|
|
id: int = db.Column(Serial, primary_key=True)
|
|
start: datetime = db.Column(UtcDateTime, nullable=False)
|
|
end: Optional[datetime] = db.Column(UtcDateTime)
|
|
comment: Optional[str] = db.Column(db.String(256))
|
|
type: int = db.Column("type_id", Serial, db.ForeignKey(f"{_table_prefix_}job_type.id"), nullable=False)
|
|
locked: bool = db.Column(db.Boolean(), default=False, nullable=False)
|
|
services: List[Service] = db.relationship(
|
|
"Service", back_populates="job_", cascade="save-update, merge, delete, delete-orphan"
|
|
)
|
|
required_services: float = db.Column(db.Numeric(precision=4, scale=2, asdecimal=False), nullable=False)
|
|
|
|
type_: JobType = db.relationship("JobType")
|
|
event_ = db.relationship("Event", back_populates="jobs")
|
|
event_id_ = db.Column("event_id", Serial, db.ForeignKey(f"{_table_prefix_}event.id"), nullable=False)
|
|
|
|
invitations_ = db.relationship("Invitation", cascade="all,delete,delete-orphan", back_populates="job_")
|
|
|
|
__table_args__ = (UniqueConstraint("type_id", "start", "event_id", name="_type_start_uc"),)
|
|
|
|
|
|
##########
|
|
# Events #
|
|
##########
|
|
class Event(db.Model, ModelSerializeMixin):
|
|
"""Model for an Event"""
|
|
|
|
__allow_unmapped__ = True
|
|
__tablename__ = _table_prefix_ + "event"
|
|
id: int = db.Column(Serial, primary_key=True)
|
|
start: datetime = db.Column(UtcDateTime, nullable=False)
|
|
end: Optional[datetime] = db.Column(UtcDateTime)
|
|
name: Optional[str] = db.Column(db.String(255))
|
|
description: Optional[str] = db.Column(db.String(512))
|
|
type: Union[EventType, int] = db.relationship("EventType")
|
|
is_template: bool = db.Column(db.Boolean, default=False)
|
|
jobs: List[Job] = db.relationship(
|
|
"Job",
|
|
back_populates="event_",
|
|
cascade="all,delete,delete-orphan",
|
|
order_by="[Job.start, Job.end]",
|
|
)
|
|
# Protected for internal use
|
|
_type_id = db.Column(
|
|
"type_id",
|
|
Serial,
|
|
db.ForeignKey(f"{_table_prefix_}event_type.id", ondelete="CASCADE"),
|
|
nullable=False,
|
|
)
|
|
|
|
|
|
class Invitation(db.Model, ModelSerializeMixin):
|
|
__allow_unmapped__ = True
|
|
__tablename__ = _table_prefix_ + "invitation"
|
|
|
|
id: int = db.Column(Serial, primary_key=True)
|
|
time: datetime = db.Column(UtcDateTime, nullable=False, default=UtcDateTime.current_utc)
|
|
job_id: int = db.Column(Serial, db.ForeignKey(_table_prefix_ + "job.id"), nullable=False)
|
|
# Dummy properties for API export
|
|
invitee_id: str = None # User who was invited to take over
|
|
inviter_id: str = None # User who invited the invitee
|
|
transferee_id: Optional[str] = None # In case of a transfer: The user who is transfered out of the job
|
|
# Not exported properties for backend use
|
|
job_: Job = db.relationship(Job, foreign_keys="Invitation.job_id")
|
|
invitee_: User = db.relationship("User", foreign_keys="Invitation._invitee_id")
|
|
inviter_: User = db.relationship("User", foreign_keys="Invitation._inviter_id")
|
|
transferee_: User = db.relationship("User", foreign_keys="Invitation._transferee_id")
|
|
# Protected properties needed for internal use
|
|
_invitee_id = db.Column("invitee_id", Serial, db.ForeignKey("user.id"), nullable=False)
|
|
_inviter_id = db.Column("inviter_id", Serial, db.ForeignKey("user.id"), nullable=False)
|
|
_transferee_id = db.Column("transferee_id", Serial, db.ForeignKey("user.id"))
|
|
|
|
@property
|
|
def invitee_id(self):
|
|
return self.invitee_.userid
|
|
|
|
@property
|
|
def inviter_id(self):
|
|
return self.inviter_.userid
|
|
|
|
@property
|
|
def transferee_id(self):
|
|
return self.transferee_.userid if self.transferee_ else None
|