[Plugin] schedule: Working Event, EventSlot, EventType and JobType
This commit is contained in:
parent
363ec6530b
commit
4da4c1ee01
|
@ -2,24 +2,25 @@
|
||||||
|
|
||||||
Provides duty schedule / duty roster functions
|
Provides duty schedule / duty roster functions
|
||||||
"""
|
"""
|
||||||
import http
|
from datetime import datetime, timedelta, timezone
|
||||||
|
from http.client import NO_CONTENT, CREATED
|
||||||
from dateutil import parser
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
from flask import Blueprint, request, jsonify
|
from flask import Blueprint, request, jsonify
|
||||||
from werkzeug.exceptions import BadRequest, NotFound
|
from werkzeug.exceptions import BadRequest, NotFound
|
||||||
|
from backports.datetime_fromisoformat import MonkeyPatch
|
||||||
|
|
||||||
from flaschengeist.database import db
|
|
||||||
from flaschengeist.plugins import Plugin
|
from flaschengeist.plugins import Plugin
|
||||||
from flaschengeist.decorator import login_required
|
from flaschengeist.decorator import login_required
|
||||||
|
|
||||||
from . import event_controller, permissions
|
from . import event_controller, permissions
|
||||||
from .models import EventType
|
from . import models
|
||||||
|
|
||||||
|
MonkeyPatch.patch_fromisoformat()
|
||||||
schedule_bp = Blueprint("schedule", __name__, url_prefix="/schedule")
|
schedule_bp = Blueprint("schedule", __name__, url_prefix="/schedule")
|
||||||
|
|
||||||
|
|
||||||
class SchedulePlugin(Plugin):
|
class SchedulePlugin(Plugin):
|
||||||
|
models = models
|
||||||
|
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
blueprint=schedule_bp,
|
blueprint=schedule_bp,
|
||||||
|
@ -63,7 +64,7 @@ def new_event_type(current_session):
|
||||||
if "name" not in data:
|
if "name" not in data:
|
||||||
raise BadRequest
|
raise BadRequest
|
||||||
event_controller.create_event_type(data["name"])
|
event_controller.create_event_type(data["name"])
|
||||||
return "", http.HTTPStatus.CREATED
|
return "", CREATED
|
||||||
|
|
||||||
|
|
||||||
@schedule_bp.route("/event-types/<name>", methods=["PUT", "DELETE"])
|
@schedule_bp.route("/event-types/<name>", methods=["PUT", "DELETE"])
|
||||||
|
@ -89,7 +90,7 @@ def modify_event_type(name, current_session):
|
||||||
if "name" not in data:
|
if "name" not in data:
|
||||||
raise BadRequest("Parameter missing in data")
|
raise BadRequest("Parameter missing in data")
|
||||||
event_controller.rename_event_type(name, data["name"])
|
event_controller.rename_event_type(name, data["name"])
|
||||||
return "", http.HTTPStatus.NO_CONTENT
|
return "", NO_CONTENT
|
||||||
|
|
||||||
|
|
||||||
@schedule_bp.route("/job-types", methods=["GET"])
|
@schedule_bp.route("/job-types", methods=["GET"])
|
||||||
|
@ -128,7 +129,7 @@ def new_job_type(current_session):
|
||||||
if "name" not in data:
|
if "name" not in data:
|
||||||
raise BadRequest
|
raise BadRequest
|
||||||
event_controller.create_job_type(data["name"])
|
event_controller.create_job_type(data["name"])
|
||||||
return "", http.HTTPStatus.CREATED
|
return "", CREATED
|
||||||
|
|
||||||
|
|
||||||
@schedule_bp.route("/job-types/<name>", methods=["PUT", "DELETE"])
|
@schedule_bp.route("/job-types/<name>", methods=["PUT", "DELETE"])
|
||||||
|
@ -154,10 +155,9 @@ def modify_job_type(name, current_session):
|
||||||
if "name" not in data:
|
if "name" not in data:
|
||||||
raise BadRequest("Parameter missing in data")
|
raise BadRequest("Parameter missing in data")
|
||||||
event_controller.rename_name_type(name, data["name"])
|
event_controller.rename_name_type(name, data["name"])
|
||||||
return "", http.HTTPStatus.NO_CONTENT
|
return "", NO_CONTENT
|
||||||
|
|
||||||
|
|
||||||
########### TODO: Ab hier ############
|
|
||||||
@schedule_bp.route("/events/<int:event_id>", methods=["GET"])
|
@schedule_bp.route("/events/<int:event_id>", methods=["GET"])
|
||||||
@login_required()
|
@login_required()
|
||||||
def get_event(event_id, current_session):
|
def get_event(event_id, current_session):
|
||||||
|
@ -173,8 +173,6 @@ def get_event(event_id, current_session):
|
||||||
JSON encoded event object
|
JSON encoded event object
|
||||||
"""
|
"""
|
||||||
event = event_controller.get_event(event_id)
|
event = event_controller.get_event(event_id)
|
||||||
if not event:
|
|
||||||
raise NotFound
|
|
||||||
return jsonify(event)
|
return jsonify(event)
|
||||||
|
|
||||||
|
|
||||||
|
@ -196,9 +194,6 @@ def get_events(current_session, year=datetime.now().year, month=datetime.now().m
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
JSON encoded list containing events found or HTTP-error
|
JSON encoded list containing events found or HTTP-error
|
||||||
|
|
||||||
Raises:
|
|
||||||
BadRequest: If date is invalid
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
begin = datetime(year=year, month=month, day=1)
|
begin = datetime(year=year, month=month, day=1)
|
||||||
|
@ -217,88 +212,169 @@ def get_events(current_session, year=datetime.now().year, month=datetime.now().m
|
||||||
raise BadRequest("Invalid date given")
|
raise BadRequest("Invalid date given")
|
||||||
|
|
||||||
|
|
||||||
|
def _event_slot_from_data(data):
|
||||||
|
try:
|
||||||
|
start = datetime.fromisoformat(data["start"]).replace(tzinfo=timezone.utc)
|
||||||
|
end = datetime.fromisoformat(data["end"]).replace(tzinfo=timezone.utc) if "end" in data else None
|
||||||
|
# jobs = ...
|
||||||
|
except (NotFound, KeyError, ValueError):
|
||||||
|
raise BadRequest("Missing POST parameter")
|
||||||
|
return {"start": start, "end": end}
|
||||||
|
|
||||||
|
|
||||||
@schedule_bp.route("/events", methods=["POST"])
|
@schedule_bp.route("/events", methods=["POST"])
|
||||||
@login_required(permission=permissions.CREATE)
|
@login_required(permission=permissions.CREATE)
|
||||||
def __new_event(**kwargs):
|
def create_event(current_session):
|
||||||
|
"""Create an new event
|
||||||
|
|
||||||
|
Route: ``/events`` | Method: ``POST``
|
||||||
|
|
||||||
|
POST-data: See interfaces for Event, can already contain slots
|
||||||
|
|
||||||
|
Args:
|
||||||
|
current_session: Session sent with Authorization Header
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
JSON encoded Event object or HTTP-error
|
||||||
|
"""
|
||||||
|
data = request.get_json()
|
||||||
|
try:
|
||||||
|
start = datetime.fromisoformat(data["start"]).replace(tzinfo=timezone.utc)
|
||||||
|
event_type = event_controller.get_event_type(data["type"])
|
||||||
|
except (NotFound, KeyError, ValueError):
|
||||||
|
raise BadRequest("Missing POST parameter")
|
||||||
|
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
event = event_controller.create_event(
|
event = event_controller.create_event(
|
||||||
begin=parser.isoparse(data["begin"]),
|
start=start, event_type=event_type, description=data["description"] if "description" in data else None
|
||||||
end=parser.isoparse(data["end"]),
|
|
||||||
description=data["description"],
|
|
||||||
type=EventType.query.get(data["kind"]),
|
|
||||||
)
|
)
|
||||||
return jsonify({"ok": "ok", "id": event.id})
|
if "slots" in data:
|
||||||
|
for slot in data["slots"]:
|
||||||
|
event_controller.add_event_slot(event, **_event_slot_from_data(slot))
|
||||||
|
return jsonify(event)
|
||||||
|
|
||||||
|
|
||||||
|
@schedule_bp.route("/events/<int:event_id>", methods=["PUT"])
|
||||||
|
@login_required(permission=permissions.EDIT)
|
||||||
|
def modify_event(event_id, current_session):
|
||||||
|
"""Modify an event
|
||||||
|
|
||||||
|
Route: ``/events/<event_id>`` | Method: ``PUT``
|
||||||
|
|
||||||
|
POST-data: See interfaces for Event, can already contain slots
|
||||||
|
|
||||||
|
Args:
|
||||||
|
event_id: Identifier of the event
|
||||||
|
current_session: Session sent with Authorization Header
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
JSON encoded Event object or HTTP-error
|
||||||
|
"""
|
||||||
|
event = event_controller.get_event(event_id)
|
||||||
|
data = request.get_json()
|
||||||
|
if "start" in data:
|
||||||
|
event.start = datetime.fromisoformat(data["start"]).replace(tzinfo=timezone.utc)
|
||||||
|
if "description" in data:
|
||||||
|
event.description = data["description"]
|
||||||
|
if "type" in data:
|
||||||
|
event_type = event_controller.get_event_type(data["type"])
|
||||||
|
event.type = event_type
|
||||||
|
event_controller.update()
|
||||||
|
return jsonify(event)
|
||||||
|
|
||||||
|
|
||||||
@schedule_bp.route("/events/<int:event_id>", methods=["DELETE"])
|
@schedule_bp.route("/events/<int:event_id>", methods=["DELETE"])
|
||||||
@login_required(permission=permissions.DELETE)
|
@login_required(permission=permissions.DELETE)
|
||||||
def __delete_event(event_id, **kwargs):
|
def delete_event(event_id, current_session):
|
||||||
if not event_controller.delete_event(event_id):
|
"""Delete an event
|
||||||
raise NotFound
|
|
||||||
db.session.commit()
|
|
||||||
return jsonify({"ok": "ok"})
|
|
||||||
|
|
||||||
|
Route: ``/events/<event_id>`` | Method: ``DELETE``
|
||||||
|
|
||||||
@schedule_bp.route("/events/<int:event_id>/slots", methods=["GET"])
|
Args:
|
||||||
@login_required()
|
event_id: Identifier of the event
|
||||||
def __get_slots(event_id, **kwargs):
|
current_session: Session sent with Authorization Header
|
||||||
event = event_controller.get_event(event_id)
|
|
||||||
if not event:
|
|
||||||
raise NotFound
|
|
||||||
return jsonify({event.slots})
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
@schedule_bp.route("/events/<int:event_id>/slots/<int:slot_id>", methods=["GET"])
|
HTTP-NoContent or HTTP-error
|
||||||
@login_required()
|
"""
|
||||||
def __get_slot(event_id, slot_id, **kwargs):
|
event_controller.delete_event(event_id)
|
||||||
slot = event_controller.get_event_slot(slot_id, event_id)
|
return "", NO_CONTENT
|
||||||
if slot:
|
|
||||||
return jsonify(slot)
|
|
||||||
raise NotFound
|
|
||||||
|
|
||||||
|
|
||||||
@schedule_bp.route("/events/<int:event_id>/slots/<int:slot_id>", methods=["DELETE"])
|
|
||||||
@login_required(permission=permissions.DELETE)
|
|
||||||
def __delete_slot(event_id, slot_id, **kwargs):
|
|
||||||
if event_controller.delete_event_slot(slot_id, event_id):
|
|
||||||
return jsonify({"ok": "ok"})
|
|
||||||
raise NotFound
|
|
||||||
|
|
||||||
|
|
||||||
@schedule_bp.route("/events/<int:event_id>/slots/<int:slot_id>", methods=["PUT"])
|
|
||||||
@login_required(permission=permissions.EDIT)
|
|
||||||
def __update_slot(event_id, slot_id, **kwargs):
|
|
||||||
data = request.get_json()
|
|
||||||
if not data:
|
|
||||||
raise BadRequest
|
|
||||||
|
|
||||||
for job in data["jobs"]:
|
|
||||||
event_controller.add_job(job.kind, job.user)
|
|
||||||
if event_controller.delete_event_slot(slot_id, event_id):
|
|
||||||
return jsonify({"ok": "ok"})
|
|
||||||
raise NotFound
|
|
||||||
|
|
||||||
|
|
||||||
@schedule_bp.route("/events/<int:event_id>/slots", methods=["POST"])
|
@schedule_bp.route("/events/<int:event_id>/slots", methods=["POST"])
|
||||||
@login_required(permission=permissions.EDIT)
|
@login_required(permission=permissions.EDIT)
|
||||||
def __add_slot(event_id, **kwargs):
|
def add_event_slot(event_id, current_session):
|
||||||
|
"""Add an new EventSlot to an Event
|
||||||
|
|
||||||
|
Route: ``/events/<event_id>/slots`` | Method: ``POST``
|
||||||
|
|
||||||
|
POST-data: See TS interface for EventSlot
|
||||||
|
|
||||||
|
Args:
|
||||||
|
event_id: Identifier of the event
|
||||||
|
current_session: Session sent with Authorization Header
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
JSON encoded Event object or HTTP-error
|
||||||
|
"""
|
||||||
event = event_controller.get_event(event_id)
|
event = event_controller.get_event(event_id)
|
||||||
if not event:
|
|
||||||
raise NotFound
|
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
attr = {"job_slots": []}
|
if not data:
|
||||||
try:
|
raise BadRequest("Missing POST parameters")
|
||||||
if "start" in data:
|
|
||||||
attr["start"] = parser.isoparse(data["start"])
|
event_controller.add_event_slot(event, **_event_slot_from_data(data))
|
||||||
if "end" in data:
|
return jsonify(event)
|
||||||
attr["end"] = parser.isoparse(data["end"])
|
|
||||||
for job in data["jobs"]:
|
|
||||||
attr["job_slots"].append({"needed_persons": job["needed_persons"], "kind": job["kind"]})
|
|
||||||
except KeyError:
|
|
||||||
raise BadRequest("Missing data in request")
|
|
||||||
event_controller.add_slot(event, **attr)
|
|
||||||
return jsonify({"ok": "ok"})
|
|
||||||
|
|
||||||
|
|
||||||
def __edit_event():
|
@schedule_bp.route("/events/<int:event_id>/slots/<int:slot_id>", methods=["PUT"])
|
||||||
...
|
@login_required(permission=permissions.EDIT)
|
||||||
|
def update_event_slot(event_id, slot_id, current_session):
|
||||||
|
"""Update an EventSlot
|
||||||
|
|
||||||
|
Route: ``/events/<event_id>/slots/<slot_id>`` | Method: ``PUT``
|
||||||
|
|
||||||
|
POST-data: See TS interface for EventSlot
|
||||||
|
|
||||||
|
Args:
|
||||||
|
event_id: Identifier of the event
|
||||||
|
slot_id: Identifier of the slot
|
||||||
|
current_session: Session sent with Authorization Header
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
JSON encoded Event object or HTTP-error
|
||||||
|
"""
|
||||||
|
event = event_controller.get_event(event_id)
|
||||||
|
slot = event_controller.get_event_slot(slot_id)
|
||||||
|
if slot not in event.slots:
|
||||||
|
raise NotFound
|
||||||
|
|
||||||
|
data = _event_slot_from_data(request.get_json())
|
||||||
|
slot.start = data["start"]
|
||||||
|
if "end" in data:
|
||||||
|
slot.end = data["end"]
|
||||||
|
event_controller.update()
|
||||||
|
return jsonify(event)
|
||||||
|
|
||||||
|
|
||||||
|
@schedule_bp.route("/events/<int:event_id>/slots/<int:slot_id>", methods=["DELETE"])
|
||||||
|
@login_required(permission=permissions.EDIT)
|
||||||
|
def delete_event_slot(event_id, slot_id, current_session):
|
||||||
|
"""Delete an EventSlot
|
||||||
|
|
||||||
|
Route: ``/events/<event_id>/slots/<slot_id>`` | Method: ``DELETE``
|
||||||
|
|
||||||
|
Args:
|
||||||
|
event_id: Identifier of the event
|
||||||
|
slot_id: Identifier of the slot
|
||||||
|
current_session: Session sent with Authorization Header
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
JSON encoded Event object or HTTP-error
|
||||||
|
"""
|
||||||
|
event = event_controller.get_event(event_id)
|
||||||
|
event_controller.remove_event_slot(event, slot_id)
|
||||||
|
return jsonify(event)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: JobSlot, Job!
|
||||||
|
# TODO: JobTransfer
|
||||||
|
|
|
@ -6,6 +6,10 @@ from flaschengeist.database import db
|
||||||
from flaschengeist.plugins.schedule.models import EventType, Event, EventSlot, JobSlot, JobType
|
from flaschengeist.plugins.schedule.models import EventType, Event, EventSlot, JobSlot, JobType
|
||||||
|
|
||||||
|
|
||||||
|
def update():
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
def get_event_types():
|
def get_event_types():
|
||||||
return EventType.query.all()
|
return EventType.query.all()
|
||||||
|
|
||||||
|
@ -84,34 +88,41 @@ def delete_job_type(name):
|
||||||
raise BadRequest("Type still in use")
|
raise BadRequest("Type still in use")
|
||||||
|
|
||||||
|
|
||||||
def get_event(id):
|
def get_event(event_id):
|
||||||
return Event.query.get(id)
|
event = Event.query.get(event_id)
|
||||||
|
if event is None:
|
||||||
|
raise NotFound
|
||||||
|
return event
|
||||||
|
|
||||||
|
|
||||||
def get_events(begin, end):
|
def get_events(start, end):
|
||||||
"""Query events which start from begin until end
|
"""Query events which start from begin until end
|
||||||
Args:
|
Args:
|
||||||
begin (datetime): Earliest start
|
start (datetime): Earliest start
|
||||||
end (datetime): Latest start
|
end (datetime): Latest start
|
||||||
|
|
||||||
Returns: collection of Event objects
|
Returns: collection of Event objects
|
||||||
"""
|
"""
|
||||||
return Event.query.filter((begin <= Event.begin), (Event.begin < end))
|
return Event.query.filter((start <= Event.start), (Event.start < end)).all()
|
||||||
|
|
||||||
|
|
||||||
def delete_event(id):
|
def delete_event(event_id):
|
||||||
"""Delete event with given ID
|
"""Delete event with given ID
|
||||||
Args:
|
Args:
|
||||||
id: id of Event to delete
|
event_id: id of Event to delete
|
||||||
|
|
||||||
Returns: True if successful, False if Event is not found
|
Raises:
|
||||||
|
NotFound if not found
|
||||||
"""
|
"""
|
||||||
return Event.query.filter(Event.id == id).delete() == 1
|
event = get_event(event_id)
|
||||||
|
db.session.delete(event)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
def create_event(begin, kind, end=None, description=None):
|
def create_event(event_type, start, slots=[], description=None):
|
||||||
try:
|
try:
|
||||||
event = Event(begin=begin, end=end, description=description, kind=kind)
|
logger.debug(event_type)
|
||||||
|
event = Event(start=start, description=description, type=event_type, slots=slots)
|
||||||
db.session.add(event)
|
db.session.add(event)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return event
|
return event
|
||||||
|
@ -120,24 +131,25 @@ def create_event(begin, kind, end=None, description=None):
|
||||||
raise BadRequest
|
raise BadRequest
|
||||||
|
|
||||||
|
|
||||||
def create_job_kind(name):
|
def get_event_slot(slot_id):
|
||||||
try:
|
slot = EventSlot.query.get(slot_id)
|
||||||
kind = JobKind(name=name)
|
if slot is None:
|
||||||
db.session.add(kind)
|
raise NotFound
|
||||||
db.session.commit()
|
return slot
|
||||||
return kind
|
|
||||||
except IntegrityError:
|
|
||||||
logger.debug("IntegrityError: Looks like there is a name collision", exc_info=True)
|
|
||||||
raise BadRequest("Name already exists")
|
|
||||||
|
|
||||||
|
|
||||||
|
def add_event_slot(event, start, end=None):
|
||||||
|
event_slot = EventSlot(start=start, end=end, event_=event)
|
||||||
def add_slot(event, job_slots, needed_persons, start=None, end=None):
|
if start < event.start:
|
||||||
event_slot = EventSlot(start=start, end=end)
|
raise BadRequest("Start before event start")
|
||||||
for slot in job_slots:
|
db.session.add(event_slot)
|
||||||
kind = JobKind.query.get(slot.id)
|
db.session.commit()
|
||||||
job_slot = JobSlot(kind=kind, needed_persons=slot.needed_persons)
|
|
||||||
event_slot.add_slot(job_slot)
|
|
||||||
event.add_slot(event_slot)
|
def remove_event_slot(event, slot_id):
|
||||||
|
slot = get_event_slot(slot_id)
|
||||||
|
if slot in event.slots:
|
||||||
|
event.slots.remove(slot)
|
||||||
|
else:
|
||||||
|
raise NotFound
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from flaschengeist.models import ModelSerializeMixin
|
from flaschengeist.models import ModelSerializeMixin, UtcDateTime
|
||||||
from flaschengeist.models.user import User
|
from flaschengeist.models.user import User
|
||||||
from flaschengeist.database import db
|
from flaschengeist.database import db
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ class JobType(db.Model, ModelSerializeMixin):
|
||||||
id_ = db.Column("id", db.Integer, primary_key=True)
|
id_ = db.Column("id", db.Integer, primary_key=True)
|
||||||
name: str = db.Column(db.String(30), nullable=False, unique=True)
|
name: str = db.Column(db.String(30), nullable=False, unique=True)
|
||||||
|
|
||||||
|
|
||||||
########
|
########
|
||||||
# Jobs #
|
# Jobs #
|
||||||
########
|
########
|
||||||
|
@ -55,6 +56,7 @@ class JobSlot(db.Model, ModelSerializeMixin):
|
||||||
|
|
||||||
event_slot_ = db.relationship("EventSlot", back_populates="jobs")
|
event_slot_ = db.relationship("EventSlot", back_populates="jobs")
|
||||||
|
|
||||||
|
|
||||||
##########
|
##########
|
||||||
# Events #
|
# Events #
|
||||||
##########
|
##########
|
||||||
|
@ -62,12 +64,13 @@ class JobSlot(db.Model, ModelSerializeMixin):
|
||||||
|
|
||||||
class EventSlot(db.Model, ModelSerializeMixin):
|
class EventSlot(db.Model, ModelSerializeMixin):
|
||||||
"""Model for an EventSlot"""
|
"""Model for an EventSlot"""
|
||||||
|
|
||||||
__tablename__ = "event_slot"
|
__tablename__ = "event_slot"
|
||||||
_event_id = db.Column("event_id", db.Integer, db.ForeignKey("event.id"), nullable=False)
|
_event_id = db.Column("event_id", db.Integer, db.ForeignKey("event.id"), nullable=False)
|
||||||
|
|
||||||
id: int = db.Column(db.Integer, primary_key=True)
|
id: int = db.Column(db.Integer, primary_key=True)
|
||||||
start: datetime = db.Column(db.DateTime)
|
start: datetime = db.Column(UtcDateTime)
|
||||||
end: Optional[datetime] = db.Column(db.DateTime)
|
end: Optional[datetime] = db.Column(UtcDateTime)
|
||||||
jobs: [JobSlot] = db.relationship("JobSlot", back_populates="event_slot_")
|
jobs: [JobSlot] = db.relationship("JobSlot", back_populates="event_slot_")
|
||||||
|
|
||||||
event_ = db.relationship("Event", back_populates="slots")
|
event_ = db.relationship("Event", back_populates="slots")
|
||||||
|
@ -75,12 +78,14 @@ class EventSlot(db.Model, ModelSerializeMixin):
|
||||||
|
|
||||||
class Event(db.Model, ModelSerializeMixin):
|
class Event(db.Model, ModelSerializeMixin):
|
||||||
"""Model for an Event"""
|
"""Model for an Event"""
|
||||||
|
|
||||||
__tablename__ = "event"
|
__tablename__ = "event"
|
||||||
_type_id = db.Column("type_id", db.Integer, db.ForeignKey("event_type.id", ondelete="CASCADE"), nullable=False)
|
_type_id = db.Column("type_id", db.Integer, db.ForeignKey("event_type.id", ondelete="CASCADE"), nullable=False)
|
||||||
|
|
||||||
id: int = db.Column(db.Integer, primary_key=True)
|
id: int = db.Column(db.Integer, primary_key=True)
|
||||||
begin: datetime = db.Column(db.DateTime, nullable=False)
|
start: datetime = db.Column(UtcDateTime, nullable=False)
|
||||||
end: datetime = db.Column(db.DateTime)
|
description: Optional[str] = db.Column(db.String(240))
|
||||||
description: str = db.Column(db.String(240))
|
|
||||||
type: EventType = db.relationship("EventType")
|
type: EventType = db.relationship("EventType")
|
||||||
slots: [EventSlot] = db.relationship("EventSlot", back_populates="event_", cascade="all, delete")
|
slots: [EventSlot] = db.relationship(
|
||||||
|
"EventSlot", back_populates="event_", cascade="all,delete,delete-orphan", order_by="EventSlot.start"
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue