Files
provisioning-server/migrations/0050_workspace_versionen_oe_kundengruppen.sql
T
adminandClaude Opus 5.5 3ac7485179 Migration 0050: Workspace-Versionen, Distro am Workspace, OE-Workspace, Kundengruppen
Rein additiv mit Rueckfuellung: jeder Workspace bekommt Version 1 mit
seinem bisherigen Inhalt, alle Organisationen die Kundengruppe Schule.
Neu: Sichtbarkeit/Freigaben fuer Vorlagen, Workspace an der OE mit
gepinnter Version und Auto-Haken, Gruppen-Webapps, Org-Berechtigung
darf_eigene_workspaces. Workspace-Creator neu, Schritt C.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 11:54:23 +02:00

130 lines
6.0 KiB
PL/PgSQL

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;