diff --git a/dashboard/src/appointments.tsx b/dashboard/src/appointments.tsx index 1d700ab..781d31f 100644 --- a/dashboard/src/appointments.tsx +++ b/dashboard/src/appointments.tsx @@ -55,7 +55,7 @@ const Appointments: React.FC = () => { diff --git a/server/alembic/versions/d490cbfdea65_migrate_events_to_use_group_id_instead_.py b/server/alembic/versions/d490cbfdea65_migrate_events_to_use_group_id_instead_.py new file mode 100644 index 0000000..c5b0da4 --- /dev/null +++ b/server/alembic/versions/d490cbfdea65_migrate_events_to_use_group_id_instead_.py @@ -0,0 +1,91 @@ +"""Migrate events to use group_id instead of client_uuid + +Revision ID: d490cbfdea65 +Revises: 8a45ec34f84d +Create Date: 2025-06-30 19:16:29.138440 + +ACHTUNG: +Ein Downgrade dieser Migration ist NICHT verlustfrei möglich, wenn mehrere Clients einer Gruppe zugeordnet sind. +Beim Downgrade wird jedem Event willkürlich ein (der erste gefundene) Client der Gruppe zugeordnet. +Die ursprüngliche Zuordnung von Events zu Clients kann dadurch NICHT wiederhergestellt werden! +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = 'd490cbfdea65' +down_revision: Union[str, None] = '8a45ec34f84d' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Upgrade schema.""" + # 1. Neue Spalte group_id (vorübergehend nullable) + op.add_column('events', sa.Column('group_id', sa.Integer(), nullable=True)) + op.create_foreign_key( + 'fk_events_group_id_client_groups', + 'events', 'client_groups', + ['group_id'], ['id'] + ) + op.create_index('ix_events_group_id', 'events', ['group_id']) + + # 2. group_id für alle Events anhand client_uuid setzen + op.execute(""" + UPDATE events + SET group_id = ( + SELECT group_id FROM clients WHERE clients.uuid = events.client_uuid + ) + """) + + # 3. client_uuid entfernen + op.drop_constraint('events_ibfk_1', 'events', + type_='foreignkey') # Name ggf. anpassen! + # Name ggf. anpassen! + op.drop_index('ix_events_client_uuid', table_name='events') + op.drop_column('events', 'client_uuid') + + # 4. group_id auf NOT NULL setzen + op.alter_column( + 'events', + 'group_id', + existing_type=sa.Integer(), + nullable=False + ) + + +def downgrade() -> None: + """Downgrade schema. + + ACHTUNG: + Ein Downgrade ist nicht verlustfrei möglich, wenn mehrere Clients pro Gruppe existieren. + Es wird jeweils ein beliebiger (erster) Client der Gruppe für die Zuordnung gewählt. + """ + # 1. client_uuid wieder hinzufügen + op.add_column('events', sa.Column( + 'client_uuid', sa.String(length=36), nullable=True)) + op.create_foreign_key( + 'fk_events_client_uuid_clients', + 'events', 'clients', + ['client_uuid'], ['uuid'] + ) + op.create_index('ix_events_client_uuid', 'events', ['client_uuid']) + + # 2. client_uuid anhand group_id zurücksetzen (nur möglich, wenn 1:1-Beziehung!) + # Falls mehrere Clients pro Gruppe: Datenverlust möglich! + # Hier ggf. eine Strategie überlegen oder leerlassen. + op.execute(""" + UPDATE events + SET client_uuid = ( + SELECT uuid FROM clients WHERE clients.group_id = events.group_id LIMIT 1 + ) + """) + + # 3. group_id entfernen + op.drop_constraint('fk_events_group_id_client_groups', + 'events', type_='foreignkey') + op.drop_index('ix_events_group_id', table_name='events') + op.drop_column('events', 'group_id') diff --git a/server/models.py b/server/models.py index 675d188..155e00d 100644 --- a/server/models.py +++ b/server/models.py @@ -62,8 +62,8 @@ class EventType(enum.Enum): class Event(Base): __tablename__ = 'events' id = Column(Integer, primary_key=True, autoincrement=True) - client_uuid = Column(String(36), ForeignKey( - 'clients.uuid'), nullable=False, index=True) + group_id = Column(Integer, ForeignKey( + 'client_groups.id'), nullable=False, index=True) title = Column(String(100), nullable=False) description = Column(Text, nullable=True) start = Column(TIMESTAMP(timezone=True), nullable=False, index=True) diff --git a/server/routes/events.py b/server/routes/events.py index 393d750..c34335c 100644 --- a/server/routes/events.py +++ b/server/routes/events.py @@ -1,9 +1,9 @@ +from database import Session +from sqlalchemy import and_ +from models import Event +from flask import Blueprint, request, jsonify import sys sys.path.append('/workspace') -from flask import Blueprint, request, jsonify -from models import Event -from sqlalchemy import and_ -from database import Session events_bp = Blueprint("events", __name__, url_prefix="/api/events") @@ -13,17 +13,20 @@ def get_events(): session = Session() start = request.args.get("start") end = request.args.get("end") - client_uuid = request.args.get("client_uuid") + # geändert: jetzt group_id statt client_uuid + group_id = request.args.get("group_id") query = session.query(Event).filter(Event.is_active == True) if start and end: query = query.filter(and_(Event.start < end, Event.end > start)) - if client_uuid: - query = query.filter(Event.client_uuid == client_uuid) + if group_id: + # geändert: filter auf group_id + query = query.filter(Event.group_id == int(group_id)) events = query.all() result = [] for e in events: result.append({ "Id": str(e.id), + "GroupId": e.group_id, # geändert: gibt group_id zurück "Subject": e.title, "StartTime": e.start.isoformat() if e.start else None, "EndTime": e.end.isoformat() if e.end else None,