From b60c405f76ea73ff6ff5e740bfa6665c9b5c1cd1 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Sun, 21 Mar 2021 00:55:50 +0100 Subject: [PATCH] [events] Improved event plugin --- flaschengeist/plugins/events/__init__.py | 48 ++++++++++++------- .../plugins/events/event_controller.py | 40 +++++++--------- flaschengeist/plugins/events/models.py | 33 ++----------- 3 files changed, 54 insertions(+), 67 deletions(-) diff --git a/flaschengeist/plugins/events/__init__.py b/flaschengeist/plugins/events/__init__.py index 5b1b772..0194c7a 100644 --- a/flaschengeist/plugins/events/__init__.py +++ b/flaschengeist/plugins/events/__init__.py @@ -30,6 +30,12 @@ class EventPlugin(Plugin): ) +@schedule_bp.route("/templates", methods=["GET"]) +@login_required() +def get_templates(current_session): + return jsonify(event_controller.get_templates()) + + @schedule_bp.route("/event-types", methods=["GET"]) @schedule_bp.route("/event-types/", methods=["GET"]) @login_required() @@ -185,6 +191,19 @@ def get_event(event_id, current_session): @schedule_bp.route("/events", methods=["GET"]) +@login_required() +def get_filtered_events(current_session): + begin = request.args.get('from') + if begin is not None: + begin = from_iso_format(begin) + end = request.args.get('to') + if end is not None: + end = from_iso_format(end) + if begin is None and end is None: + begin = datetime.now() + return jsonify(event_controller.get_events(begin, end)) + + @schedule_bp.route("/events//", methods=["GET"]) @schedule_bp.route("/events///", methods=["GET"]) @login_required() @@ -221,21 +240,20 @@ def get_events(current_session, year=datetime.now().year, month=datetime.now().m def _add_job(event, data): - end = None try: start = from_iso_format(data["start"]) + end = None + if "end" in data: + end = from_iso_format(data["end"]) + required_services = data["required_services"] + job_type = data["type"] + if isinstance(job_type, dict): + job_type = data["type"]["id"] except (KeyError, ValueError): - raise BadRequest("Missing POST parameter") - if "end" in data: - end = from_iso_format(data["end"]) + raise BadRequest("Missing or invalid POST parameter") - if "required_services" not in data: - raise BadRequest - job_type = data["type"] - if isinstance(job_type, dict): - job_type = data["type"]["id"] job_type = event_controller.get_job_type(job_type) - event_controller.add_job(event, job_type, data["required_services"], start, end, comment=data.get("comment")) + event_controller.add_job(event, job_type, required_services, start, end, comment=data.get("comment", None)) @schedule_bp.route("/events", methods=["POST"]) @@ -268,15 +286,13 @@ def create_event(current_session): except (NotFound, ValueError): raise BadRequest("Invalid parameter") - recurrence_rule = None - if "recurrence_rule" in data: - recurrence_rule = event_controller.create_recurrence(data=data["recurrence_rule"]) event = event_controller.create_event( start=start, end=end, + name=data.get("name", None), + is_template=data.get("is_template", None), event_type=event_type, description=data.get("description", None), - recurrence_rule=recurrence_rule, ) if "jobs" in data: for job in data["jobs"]: @@ -390,7 +406,7 @@ def update_job(event_id, job_id, current_session: Session): current_session: Session sent with Authorization Header Returns: - JSON encoded Event object or HTTP-error + JSON encoded Job object or HTTP-error """ job = event_controller.get_job(job_id, event_id) @@ -419,7 +435,7 @@ def update_job(event_id, job_id, current_session: Session): job.type = event_controller.get_job_type(data["type"]) event_controller.update() - return jsonify(job.event_) + return jsonify(job) # TODO: JobTransfer diff --git a/flaschengeist/plugins/events/event_controller.py b/flaschengeist/plugins/events/event_controller.py index 3432e29..84e2887 100644 --- a/flaschengeist/plugins/events/event_controller.py +++ b/flaschengeist/plugins/events/event_controller.py @@ -1,9 +1,13 @@ +from datetime import datetime +from typing import Optional + +from sqlalchemy import or_, and_ from werkzeug.exceptions import BadRequest, NotFound from sqlalchemy.exc import IntegrityError from flaschengeist import logger from flaschengeist.database import db -from flaschengeist.plugins.events.models import EventType, Event, Job, JobType, Service, RecurrenceRule +from flaschengeist.plugins.events.models import EventType, Event, Job, JobType, Service from flaschengeist.utils.datetime import from_iso_format @@ -105,7 +109,11 @@ def get_event(event_id) -> Event: return event -def get_events(start, end): +def get_templates(): + return Event.query.filter(Event.is_template == True).all() + + +def get_events(start: Optional[datetime] = None, end=None): """Query events which start from begin until end Args: start (datetime): Earliest start @@ -113,7 +121,12 @@ def get_events(start, end): Returns: collection of Event objects """ - return Event.query.filter((start <= Event.start), (Event.start < end)).all() + query = Event.query.filter(Event.is_template.__eq__(False)) + if start is not None: + query = query.filter(start <= Event.start) + if end is not None: + query = query.filter(Event.start < end) + return query.all() def delete_event(event_id): @@ -129,15 +142,13 @@ def delete_event(event_id): db.session.commit() -def create_event(event_type, start, end=None, jobs=[], description=None, recurrence_rule=None): +def create_event(event_type, start, end=None, jobs=[], is_template=None, name=None, description=None): try: logger.debug(event_type) event = Event( - start=start, end=end, description=description, type=event_type, jobs=jobs, recurrence_rule=recurrence_rule + start=start, end=end, name=name, description=description, type=event_type, is_template=is_template, jobs=jobs ) db.session.add(event) - if recurrence_rule is not None: - event = Event(start=start, end=end, description=description, type=event_type, jobs=jobs, template_=event) db.session.commit() return event except IntegrityError: @@ -185,18 +196,3 @@ def assign_to_job(job: Job, user, value): service = Service(user_=user, value=value, job_=job) db.session.add(service) db.session.commit() - - -def create_recurrence(data=None, count=None, end_date=None, frequency=None, interval=None): - if data is not None: - if "frequency" not in data: - raise BadRequest("Missing POST parameter") - frequency = data["frequency"] - if "end_date" in data: - end_date = from_iso_format(data["end_date"]) - if "count" in data: - count = data["count"] - if "interval" in data: - interval = data["interval"] - recurrence = RecurrenceRule(frequency=frequency, end_date=end_date, count=count, interval=interval) - db.session.add(recurrence) diff --git a/flaschengeist/plugins/events/models.py b/flaschengeist/plugins/events/models.py index d645d7c..7479df0 100644 --- a/flaschengeist/plugins/events/models.py +++ b/flaschengeist/plugins/events/models.py @@ -67,32 +67,12 @@ class Job(db.Model, ModelSerializeMixin): 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", name="_type_start_uc"),) + __table_args__ = (UniqueConstraint("type_id", "start", "event_id", name="_type_start_uc"),) ########## # Events # ########## - - -class _Frequency(enum.Enum): - daily = 1 - weekly = 2 - monthly = 3 - yearly = 4 - - -class RecurrenceRule(db.Model, ModelSerializeMixin): - __tablename__ = _table_prefix_ + "recurrence_rule" - - frequency: str = db.Column(db.Enum(_Frequency)) - until: Optional[datetime] = db.Column(UtcDateTime) - count: Optional[int] = db.Column(db.Integer) - interval: int = db.Column(db.Integer, nullable=False, default=1) - - id_: int = db.Column("id", db.Integer, primary_key=True) - - class Event(db.Model, ModelSerializeMixin): """Model for an Event""" @@ -100,19 +80,14 @@ class Event(db.Model, ModelSerializeMixin): id: int = db.Column(db.Integer, primary_key=True) start: datetime = db.Column(UtcDateTime, nullable=False) end: Optional[datetime] = db.Column(UtcDateTime) - description: Optional[str] = db.Column(db.String(255)) + 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]" ) - recurrence_rule: Optional[RecurrenceRule] = db.relationship("RecurrenceRule") - template_id: Optional[int] = db.Column("template_id", db.Integer, db.ForeignKey(f"{_table_prefix_}event.id")) - # Not exported properties for backend use - template_ = db.relationship("Event") # Protected for internal use - _recurrence_rule_id = db.Column( - "recurrence_rule_id", db.Integer, db.ForeignKey(f"{_table_prefix_}recurrence_rule.id") - ) _type_id = db.Column( "type_id", db.Integer, db.ForeignKey(f"{_table_prefix_}event_type.id", ondelete="CASCADE"), nullable=False )