flaschengeist/flaschengeist/plugins/events/models.py

118 lines
4.2 KiB
Python

from __future__ import annotations # TODO: Remove if python requirement is >= 3.10
import enum
from datetime import datetime
from typing import Optional, Union
from sqlalchemy import UniqueConstraint
from flaschengeist.models import ModelSerializeMixin, UtcDateTime
from flaschengeist.models.user import User
from flaschengeist.database import db
#########
# Types #
#########
_table_prefix_ = "events_"
class EventType(db.Model, ModelSerializeMixin):
__tablename__ = _table_prefix_ + "event_type"
id: int = db.Column(db.Integer, 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(db.Integer, primary_key=True)
name: str = db.Column(db.String(30), nullable=False, unique=True)
########
# Jobs #
########
class Service(db.Model, ModelSerializeMixin):
__tablename__ = _table_prefix_ + "service"
userid: str = ""
value: float = db.Column(db.Numeric(precision=3, scale=2, asdecimal=False), nullable=False)
_job_id = db.Column(
"job_id", db.Integer, db.ForeignKey(f"{_table_prefix_}job.id"), nullable=False, primary_key=True
)
_user_id = db.Column("user_id", db.Integer, 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):
__tablename__ = _table_prefix_ + "job"
_type_id = db.Column("type_id", db.Integer, db.ForeignKey(f"{_table_prefix_}job_type.id"), nullable=False)
id: int = db.Column(db.Integer, primary_key=True)
start: datetime = db.Column(UtcDateTime, nullable=False)
end: Optional[datetime] = db.Column(UtcDateTime)
type: Union[JobType, int] = db.relationship("JobType")
comment: Optional[str] = db.Column(db.String(256))
services: list[Service] = db.relationship("Service", back_populates="job_")
required_services: float = db.Column(db.Numeric(precision=4, scale=2, asdecimal=False), nullable=False)
event_ = db.relationship("Event", back_populates="jobs")
event_id_ = db.Column("event_id", db.Integer, db.ForeignKey(f"{_table_prefix_}event.id"), nullable=False)
__table_args__ = (UniqueConstraint("type_id", "start", "event_id", name="_type_start_uc"),)
##########
# Events #
##########
class Event(db.Model, ModelSerializeMixin):
"""Model for an Event"""
__tablename__ = _table_prefix_ + "event"
id: int = db.Column(db.Integer, 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", db.Integer, db.ForeignKey(f"{_table_prefix_}event_type.id", ondelete="CASCADE"), nullable=False
)
class Invite(db.Model, ModelSerializeMixin):
__tablename__ = _table_prefix_ + "invite"
id: int = db.Column(db.Integer, primary_key=True)
job_id: int = db.Column(db.Integer, db.ForeignKey(_table_prefix_ + "job.id"), nullable=False)
# Dummy properties for API export
invitee_id: str = None
sender_id: str = None
# Not exported properties for backend use
invitee_: User = db.relationship("User", foreign_keys="Invite._invitee_id")
sender_: User = db.relationship("User", foreign_keys="Invite._sender_id")
# Protected properties needed for internal use
_invitee_id = db.Column("invitee_id", db.Integer, db.ForeignKey("user.id"), nullable=False)
_sender_id = db.Column("sender_id", db.Integer, db.ForeignKey("user.id"), nullable=False)
@property
def invitee_id(self):
return self.invitee_.userid
@property
def sender_id(self):
return self.sender_.userid