from flask import Blueprint, request, jsonify from server.permissions import editor_or_higher from server.database import Session from models.models import EventException, Event from datetime import datetime, date event_exceptions_bp = Blueprint("event_exceptions", __name__, url_prefix="/api/event_exceptions") @event_exceptions_bp.route("", methods=["POST"]) @editor_or_higher def create_exception(): data = request.json session = Session() # required: event_id, exception_date required = ["event_id", "exception_date"] for f in required: if f not in data: return jsonify({"error": f"Missing field: {f}"}), 400 # Validate event exists event = session.query(Event).filter_by(id=data["event_id"]).first() if not event: session.close() return jsonify({"error": "Event not found"}), 404 exc_date = datetime.fromisoformat(data["exception_date"]).date() if isinstance(data["exception_date"], str) else data["exception_date"] # Check if an exception for this event and date already exists existing_exc = session.query(EventException).filter_by(event_id=event.id, exception_date=exc_date).first() if existing_exc: # Optionally, update the existing exception fields if needed existing_exc.is_skipped = bool(data.get("is_skipped", existing_exc.is_skipped)) existing_exc.override_title = data.get("override_title", existing_exc.override_title) existing_exc.override_description = data.get("override_description", existing_exc.override_description) existing_exc.override_start = datetime.fromisoformat(data["override_start"]) if data.get("override_start") else existing_exc.override_start existing_exc.override_end = datetime.fromisoformat(data["override_end"]) if data.get("override_end") else existing_exc.override_end session.commit() return jsonify({"success": True, "id": existing_exc.id, "updated": True}) # Otherwise, create a new exception exc = EventException( event_id=event.id, exception_date=exc_date, is_skipped=bool(data.get("is_skipped", False)), override_title=data.get("override_title"), override_description=data.get("override_description"), override_start=(datetime.fromisoformat(data["override_start"]) if data.get("override_start") else None), override_end=(datetime.fromisoformat(data["override_end"]) if data.get("override_end") else None), ) session.add(exc) session.commit() return jsonify({"success": True, "id": exc.id}) @event_exceptions_bp.route("/", methods=["PUT"]) @editor_or_higher def update_exception(exc_id): data = request.json session = Session() exc = session.query(EventException).filter_by(id=exc_id).first() if not exc: session.close() return jsonify({"error": "Exception not found"}), 404 if "exception_date" in data: exc.exception_date = datetime.fromisoformat(data["exception_date"]).date() if "is_skipped" in data: exc.is_skipped = bool(data["is_skipped"]) if "override_title" in data: exc.override_title = data.get("override_title") if "override_description" in data: exc.override_description = data.get("override_description") if "override_start" in data: exc.override_start = datetime.fromisoformat(data["override_start"]) if data.get("override_start") else None if "override_end" in data: exc.override_end = datetime.fromisoformat(data["override_end"]) if data.get("override_end") else None session.commit() session.close() return jsonify({"success": True}) @event_exceptions_bp.route("/", methods=["DELETE"]) @editor_or_higher def delete_exception(exc_id): session = Session() exc = session.query(EventException).filter_by(id=exc_id).first() if not exc: session.close() return jsonify({"error": "Exception not found"}), 404 session.delete(exc) session.commit() session.close() return jsonify({"success": True}) @event_exceptions_bp.route("", methods=["GET"]) def list_exceptions(): session = Session() event_id = request.args.get("event_id") q = session.query(EventException) if event_id: q = q.filter(EventException.event_id == int(event_id)) rows = q.all() out = [] for r in rows: out.append({ "id": r.id, "event_id": r.event_id, "exception_date": r.exception_date.isoformat(), "is_skipped": r.is_skipped, "override_title": r.override_title, "override_description": r.override_description, "override_start": r.override_start.isoformat() if r.override_start else None, "override_end": r.override_end.isoformat() if r.override_end else None, }) session.close() return jsonify(out)