diff --git a/migrations/0050_workspace_versionen_oe_kundengruppen.sql b/migrations/0050_workspace_versionen_oe_kundengruppen.sql new file mode 100644 index 0000000..6678735 --- /dev/null +++ b/migrations/0050_workspace_versionen_oe_kundengruppen.sql @@ -0,0 +1,129 @@ +BEGIN; + +-- Workspace-Creator neu, Schritt C (07.10.2026, siehe +-- platform-docs/roadmap/workspace-creator-neu.md): Datenmodell für +-- Distro am Workspace, Versionen, Workspace an der OE, Kundengruppen und +-- Gruppen-Webapps. Rein additiv mit Rückfüllung - der bisherige Inhalt +-- jedes Workspace wird zu Version 1, am Soll-Zustand eines Geräts ändert +-- sich nichts. Die alten Strukturen (workspace_merkmale, +-- gruppen.workspace_id) entfernt erst 0051, nachdem der neue Code läuft. + +-- Kundengruppen: steuern, welche Vorlagen eine Organisation sieht (eine +-- Schule braucht keine KMU-Vorlagen und umgekehrt). +CREATE TABLE kundengruppen ( + id UUID PRIMARY KEY, + key TEXT NOT NULL UNIQUE, + name TEXT NOT NULL, + sort_order INTEGER NOT NULL DEFAULT 0 +); + +INSERT INTO kundengruppen (id, key, name, sort_order) VALUES + (gen_random_uuid(), 'schule', 'Schule', 10), + (gen_random_uuid(), 'unternehmen', 'Unternehmen', 20); + +ALTER TABLE organizations ADD COLUMN kundengruppe_id UUID + REFERENCES kundengruppen(id) ON DELETE SET NULL; + +-- Alle bisherigen Organisationen sind Schulen bzw. Schul-Testumgebungen. +UPDATE organizations SET kundengruppe_id = (SELECT id FROM kundengruppen WHERE key = 'schule'); + +-- "Eigene Workspaces" als buchbare Leistung je Organisation (Kunden-Admin +-- bekommt dann einen eingeschränkten Assistenten, Schritt G). +ALTER TABLE organizations ADD COLUMN darf_eigene_workspaces BOOLEAN NOT NULL DEFAULT FALSE; + +-- Workspace: Distro (fest, NULL nur für Bestand, der noch mehrere Distros +-- bedient - wird in der Bestandsmigration aufgeteilt), Vorlagen-Kennzeichen +-- und Sichtbarkeit. organization_id bleibt der Eigentümer (NULL = Tuxflotte). +ALTER TABLE workspaces ADD COLUMN backend_id UUID REFERENCES backends(id) ON DELETE RESTRICT; +ALTER TABLE workspaces ADD COLUMN ist_vorlage BOOLEAN NOT NULL DEFAULT FALSE; +ALTER TABLE workspaces ADD COLUMN sichtbarkeit TEXT NOT NULL DEFAULT 'organisation' + CHECK (sichtbarkeit IN ('global', 'kundengruppe', 'organisation')); + +UPDATE workspaces SET sichtbarkeit = 'global', ist_vorlage = TRUE WHERE organization_id IS NULL; + +-- Bei sichtbarkeit = 'kundengruppe' bzw. 'organisation': für wen genau. +-- Ein Workspace, der einer Organisation gehört, ist für sie immer sichtbar. +CREATE TABLE workspace_freigabe_kundengruppen ( + workspace_id UUID NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE, + kundengruppe_id UUID NOT NULL REFERENCES kundengruppen(id) ON DELETE CASCADE, + PRIMARY KEY (workspace_id, kundengruppe_id) +); + +CREATE TABLE workspace_freigabe_organisationen ( + workspace_id UUID NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE, + organization_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE, + PRIMARY KEY (workspace_id, organization_id) +); + +-- Versionen: Inhalt (Merkmale, Webapps) hängt an einer Version. Höchstens +-- ein Entwurf je Workspace; Veröffentlichen friert den Inhalt ein. +CREATE TABLE workspace_versionen ( + id UUID PRIMARY KEY, + workspace_id UUID NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE, + nummer INTEGER NOT NULL, + status TEXT NOT NULL CHECK (status IN ('entwurf', 'veroeffentlicht')), + notiz TEXT, + erstellt_am TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + veroeffentlicht_am TIMESTAMPTZ, + UNIQUE (workspace_id, nummer) +); + +CREATE UNIQUE INDEX workspace_versionen_ein_entwurf + ON workspace_versionen (workspace_id) WHERE status = 'entwurf'; + +CREATE TABLE workspace_version_merkmale ( + workspace_version_id UUID NOT NULL REFERENCES workspace_versionen(id) ON DELETE CASCADE, + merkmal_id UUID NOT NULL REFERENCES merkmale(id) ON DELETE CASCADE, + PRIMARY KEY (workspace_version_id, merkmal_id) +); + +-- Bestand wird Version 1 (veröffentlicht), Inhalt 1:1 übernommen. +INSERT INTO workspace_versionen (id, workspace_id, nummer, status, notiz, erstellt_am, veroeffentlicht_am) +SELECT gen_random_uuid(), w.id, 1, 'veroeffentlicht', 'Übernommen aus dem Bestand (Migration 0050)', + w.created_at, CURRENT_TIMESTAMP +FROM workspaces w; + +INSERT INTO workspace_version_merkmale (workspace_version_id, merkmal_id) +SELECT v.id, wm.merkmal_id +FROM workspace_merkmale wm +JOIN workspace_versionen v ON v.workspace_id = wm.workspace_id AND v.nummer = 1; + +-- Webapps gehören künftig zu einer Version (workspace_id bleibt als +-- Abkürzung erhalten). Eine Webapp-Zeile gibt es je Version; beim Anlegen +-- einer neuen Version werden die Zeilen kopiert (Icon-Datei wird geteilt). +ALTER TABLE workspace_webapps ADD COLUMN workspace_version_id UUID + REFERENCES workspace_versionen(id) ON DELETE CASCADE; + +UPDATE workspace_webapps ww SET workspace_version_id = v.id +FROM workspace_versionen v +WHERE v.workspace_id = ww.workspace_id AND v.nummer = 1; + +ALTER TABLE workspace_webapps ALTER COLUMN workspace_version_id SET NOT NULL; + +-- Workspace an der OE (vererbt den Baum hinunter): gepinnte Version und +-- Haken "künftige Versionen automatisch übernehmen". +ALTER TABLE organisationseinheiten ADD COLUMN workspace_id UUID + REFERENCES workspaces(id) ON DELETE RESTRICT; +ALTER TABLE organisationseinheiten ADD COLUMN workspace_version_id UUID + REFERENCES workspace_versionen(id) ON DELETE RESTRICT; +ALTER TABLE organisationseinheiten ADD COLUMN automatisch_aktualisieren BOOLEAN NOT NULL DEFAULT TRUE; +ALTER TABLE organisationseinheiten ADD CONSTRAINT oe_workspace_version_nur_mit_workspace + CHECK (workspace_version_id IS NULL OR workspace_id IS NOT NULL); + +-- Gruppen ergänzen künftig auch Webapps (Merkmale schon über gruppen_merkmale). +CREATE TABLE gruppen_webapps ( + id UUID PRIMARY KEY, + gruppe_id UUID NOT NULL REFERENCES gruppen(id) ON DELETE CASCADE, + name TEXT NOT NULL, + url TEXT NOT NULL, + icon_filename TEXT, + icon_content_type TEXT, + kategorie_id UUID REFERENCES kategorien(id) ON DELETE SET NULL, + kiosk_modus BOOLEAN NOT NULL DEFAULT FALSE, + template_id UUID REFERENCES webapp_templates(id) ON DELETE SET NULL, + sort_order INTEGER NOT NULL DEFAULT 0, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +COMMIT;