QR-Typen je Gruppe freigeben #11

Closed
opened 2026-08-21 00:06:41 +00:00 by florian.wilde · 3 comments
Owner

Heute gilt die Freigabe eines Typs für die ganze Installation: Was abgeschaltet ist, ist für alle weg. Bei mehreren Gruppen ist das zu grob — die Marketingabteilung braucht Social Media, die Werkstatt nur Website und PDF.

Geplant: Die Freigabe bekommt eine zweite Dimension. Es bleibt eine globale Einstellung als Grundlage, und je Gruppe lässt sich davon abweichen. Wer in mehreren Gruppen ist, sieht auf der Startseite die Vereinigung; beim Anlegen entscheidet die gewählte Gruppe.

Zu klären ist der Fall, in dem ein Typ global aus, in einer Gruppe aber an ist — entweder die Gruppe darf das überstimmen, oder die globale Abschaltung gewinnt immer. Die zweite Lesart ist die weniger überraschende und wahrscheinlich die richtige.

Berührt: QrTypeSetting (zusammengesetzter Schlüssel aus Typ und Gruppe), src/lib/qr/availability.ts, die Startseite und die Typ-Verwaltung, die dann eine Gruppenauswahl bekommt.

Angelegt aus QR Code Generator in Nebula.

Heute gilt die Freigabe eines Typs für die ganze Installation: Was abgeschaltet ist, ist für alle weg. Bei mehreren Gruppen ist das zu grob — die Marketingabteilung braucht Social Media, die Werkstatt nur Website und PDF. Geplant: Die Freigabe bekommt eine zweite Dimension. Es bleibt eine globale Einstellung als Grundlage, und je Gruppe lässt sich davon abweichen. Wer in mehreren Gruppen ist, sieht auf der Startseite die Vereinigung; beim Anlegen entscheidet die gewählte Gruppe. Zu klären ist der Fall, in dem ein Typ global aus, in einer Gruppe aber an ist — entweder die Gruppe darf das überstimmen, oder die globale Abschaltung gewinnt immer. Die zweite Lesart ist die weniger überraschende und wahrscheinlich die richtige. Berührt: QrTypeSetting (zusammengesetzter Schlüssel aus Typ und Gruppe), src/lib/qr/availability.ts, die Startseite und die Typ-Verwaltung, die dann eine Gruppenauswahl bekommt. _Angelegt aus [QR Code Generator](https://nebula.wilde-ste.de/projects/cmss12yq702p6mm01ctlfe6nz) in Nebula._
florian.wilde added the in-arbeit label 2026-08-21 01:37:33 +00:00
florian.wilde started working 2026-08-21 01:37:45 +00:00
Author
Owner

🤖 Claude Code hat mit der Umsetzung begonnen.

  • Branch: feat/11-typen-je-gruppe
  • Verstanden als: Die Freigabe eines Typs bekommt eine zweite Dimension. Global bleibt die Grundlage, je Gruppe lässt sich davon abweichen.
  • Zur offenen Frage im Issue: Ich folge deiner eigenen Einschätzung — die globale Abschaltung gewinnt immer. Ein Typ, der global aus ist, lässt sich in keiner Gruppe einschalten; der Gruppenschalter steht dann sichtbar still und sagt warum. Das ist die weniger überraschende Lesart, und sie hält die Aussage „hier abgeschaltet heißt überall weg“ am Leben.
  • Geplantes Vorgehen:
    • Eine eigene Tabelle QrTypeGroupSetting mit zusammengesetztem Schlüssel aus Typ und Gruppe. Abweichung von deiner Skizze: nicht QrTypeSetting erweitern. Ein zusammengesetzter Schlüssel bräuchte dort eine leere Gruppe für den globalen Fall, und PostgreSQL lässt in einem eindeutigen Index beliebig viele NULL nebeneinander zu — die Eindeutigkeit der globalen Zeile wäre also gerade nicht gesichert. Zwei Tabellen sind hier die geradere Lösung.
    • src/lib/qr/availability.ts rechnet: freigegeben = global freigegeben und in dieser Gruppe nicht abgewählt.
    • Startseite zeigt die Vereinigung über die Gruppen des Anmeldenden; beim Anlegen entscheidet die gewählte Gruppe, und die Route prüft das noch einmal.
    • Die Typ-Verwaltung bekommt eine Gruppenauswahl: „Alle Gruppen (Grundeinstellung)“ oder eine einzelne Gruppe.
    • Prüfen mit einer eigenen Testreihe über API und Oberfläche, samt dem Fall „global aus, Gruppe an“.

Zeiterfassung läuft.

🤖 **Claude Code hat mit der Umsetzung begonnen.** - Branch: `feat/11-typen-je-gruppe` - Verstanden als: Die Freigabe eines Typs bekommt eine zweite Dimension. Global bleibt die Grundlage, je Gruppe lässt sich davon abweichen. - **Zur offenen Frage im Issue:** Ich folge deiner eigenen Einschätzung — **die globale Abschaltung gewinnt immer**. Ein Typ, der global aus ist, lässt sich in keiner Gruppe einschalten; der Gruppenschalter steht dann sichtbar still und sagt warum. Das ist die weniger überraschende Lesart, und sie hält die Aussage „hier abgeschaltet heißt überall weg“ am Leben. - Geplantes Vorgehen: - Eine eigene Tabelle `QrTypeGroupSetting` mit zusammengesetztem Schlüssel aus Typ und Gruppe. **Abweichung von deiner Skizze:** nicht `QrTypeSetting` erweitern. Ein zusammengesetzter Schlüssel bräuchte dort eine leere Gruppe für den globalen Fall, und PostgreSQL lässt in einem eindeutigen Index beliebig viele NULL nebeneinander zu — die Eindeutigkeit der globalen Zeile wäre also gerade nicht gesichert. Zwei Tabellen sind hier die geradere Lösung. - `src/lib/qr/availability.ts` rechnet: freigegeben = global freigegeben **und** in dieser Gruppe nicht abgewählt. - Startseite zeigt die Vereinigung über die Gruppen des Anmeldenden; beim Anlegen entscheidet die gewählte Gruppe, und die Route prüft das noch einmal. - Die Typ-Verwaltung bekommt eine Gruppenauswahl: „Alle Gruppen (Grundeinstellung)“ oder eine einzelne Gruppe. - Prüfen mit einer eigenen Testreihe über API und Oberfläche, samt dem Fall „global aus, Gruppe an“. Zeiterfassung läuft.
florian.wilde worked for 10 minutes 2026-08-21 01:48:28 +00:00
florian.wilde added zu-testen and removed in-arbeit labels 2026-08-21 01:49:12 +00:00
Author
Owner

✅ Umsetzung abgeschlossen — bereit zum Testen.

Die offene Frage, so beantwortet

Ich bin deiner eigenen Einschätzung gefolgt: Die globale Abschaltung gewinnt immer. Ein Typ, der in der Grundeinstellung aus ist, lässt sich in keiner Gruppe einschalten — der Schalter steht dort ausgegraut und daneben steht „In der Grundeinstellung abgeschaltet — für diese Gruppe nicht einschaltbar“. Andersherum wäre „hier abgeschaltet“ keine verlässliche Aussage mehr.

Ein Detail daraus: „an“ für eine Gruppe löscht die Abweichung, statt eine Zeile mit „an“ zu hinterlassen. So eine Zeile würde vortäuschen, sie könnte eine globale Abschaltung überstimmen.

Abweichung von deiner Skizze

Nicht QrTypeSetting erweitert, sondern eine eigene Tabelle QrTypeGroupSetting mit zusammengesetztem Schlüssel aus Typ und Gruppe. Grund: Ein zusammengesetzter Schlüssel in der bestehenden Tabelle bräuchte für den globalen Fall eine leere Gruppe, und PostgreSQL lässt in einem eindeutigen Index beliebig viele NULL nebeneinander zu — ausgerechnet die Eindeutigkeit der globalen Zeile wäre also nicht gesichert.

Was geändert wurde

  • Verwaltung → QR-Typen hat oben eine Auswahl Freigabe für: „Alle Gruppen (Grundeinstellung)“ oder eine einzelne Gruppe. In der Gruppensicht erklärt ein Hinweis, was das bedeutet, und jede Zeile sagt, ob sie für diese Gruppe gilt oder global gesperrt ist.
  • Startseite: die Vereinigung über die Gruppen des Anmeldenden. Wer in Werkstatt und Marketing ist, sieht beides.
  • Anlegen: Die gewählte Gruppe entscheidet. POST /api/codes prüft das mit und unterscheidet in der Meldung zwischen „für diese Gruppe abgeschaltet“ und „in der Verwaltung abgeschaltet“.
  • API: GET /api/admin/types?group={id}, PATCH mit optionalem groupId.
  • Mit einer gelöschten Gruppe verschwinden ihre Abweichungen mit (ON DELETE CASCADE).

Migration: 20260821030000_typen_je_gruppe

Geänderte Dateien

  • src/lib/qr/availability.ts — die Rechnung, getVisibleQrTypesForActor, setQrTypeEnabledForGroup
  • src/app/api/admin/types/route.ts, src/app/api/codes/route.ts
  • src/components/type-settings.tsx, src/app/(app)/verwaltung/typen/page.tsx
  • src/app/(app)/page.tsx, src/app/(app)/erstellen/[type]/page.tsx
  • prisma/schema.prisma + Migration, README.md, docs/funktionen.md

So testest du es

  1. git switch feat/11-typen-je-gruppe
  2. docker compose up -d --build app
  3. Zwei Gruppen anlegen, Verwaltung → QR-Typen öffnen, oben eine Gruppe wählen.
  4. Dort einen Typ abschalten. Erwartet: Nur diese Gruppe verliert ihn; die Grundeinstellung und die andere Gruppe bleiben unberührt.
  5. Denselben Typ in der Grundeinstellung abschalten, dann wieder eine Gruppe wählen. Erwartet: Der Schalter ist gesperrt und nennt den Grund.
  6. Als Mitglied nur der eingeschränkten Gruppe einen Code dieses Typs anlegen wollen — das wird mit einer passenden Meldung abgelehnt.

Geprüft mit einer eigenen Testreihe: 38 von 38 — Abweichung setzen und zurücknehmen, „global aus gewinnt“ über API und beim Anlegen, Anlegen je Gruppe, Vereinigung auf der Startseite, Oberfläche samt gesperrtem Schalter, Handy-Breite, keine Konsolenfehler.

Aufgewendete Zeit: 00:11
Pull Request: #17

Nach Freigabe: /issue-freigabe 11

✅ **Umsetzung abgeschlossen — bereit zum Testen.** <!-- claude-status branch: feat/11-typen-je-gruppe pr: 17 zeit_sekunden: 643 --> **Die offene Frage, so beantwortet** Ich bin deiner eigenen Einschätzung gefolgt: **Die globale Abschaltung gewinnt immer.** Ein Typ, der in der Grundeinstellung aus ist, lässt sich in keiner Gruppe einschalten — der Schalter steht dort ausgegraut und daneben steht „In der Grundeinstellung abgeschaltet — für diese Gruppe nicht einschaltbar“. Andersherum wäre „hier abgeschaltet“ keine verlässliche Aussage mehr. Ein Detail daraus: „an“ für eine Gruppe **löscht** die Abweichung, statt eine Zeile mit „an“ zu hinterlassen. So eine Zeile würde vortäuschen, sie könnte eine globale Abschaltung überstimmen. **Abweichung von deiner Skizze** Nicht `QrTypeSetting` erweitert, sondern eine eigene Tabelle `QrTypeGroupSetting` mit zusammengesetztem Schlüssel aus Typ und Gruppe. Grund: Ein zusammengesetzter Schlüssel in der bestehenden Tabelle bräuchte für den globalen Fall eine leere Gruppe, und PostgreSQL lässt in einem eindeutigen Index beliebig viele `NULL` nebeneinander zu — ausgerechnet die Eindeutigkeit der globalen Zeile wäre also nicht gesichert. **Was geändert wurde** - **Verwaltung → QR-Typen** hat oben eine Auswahl **Freigabe für**: „Alle Gruppen (Grundeinstellung)“ oder eine einzelne Gruppe. In der Gruppensicht erklärt ein Hinweis, was das bedeutet, und jede Zeile sagt, ob sie für diese Gruppe gilt oder global gesperrt ist. - **Startseite**: die Vereinigung über die Gruppen des Anmeldenden. Wer in Werkstatt und Marketing ist, sieht beides. - **Anlegen**: Die gewählte Gruppe entscheidet. `POST /api/codes` prüft das mit und unterscheidet in der Meldung zwischen „für diese Gruppe abgeschaltet“ und „in der Verwaltung abgeschaltet“. - **API**: `GET /api/admin/types?group={id}`, `PATCH` mit optionalem `groupId`. - Mit einer gelöschten Gruppe verschwinden ihre Abweichungen mit (`ON DELETE CASCADE`). **Migration:** `20260821030000_typen_je_gruppe` **Geänderte Dateien** - `src/lib/qr/availability.ts` — die Rechnung, `getVisibleQrTypesForActor`, `setQrTypeEnabledForGroup` - `src/app/api/admin/types/route.ts`, `src/app/api/codes/route.ts` - `src/components/type-settings.tsx`, `src/app/(app)/verwaltung/typen/page.tsx` - `src/app/(app)/page.tsx`, `src/app/(app)/erstellen/[type]/page.tsx` - `prisma/schema.prisma` + Migration, `README.md`, `docs/funktionen.md` **So testest du es** 1. `git switch feat/11-typen-je-gruppe` 2. `docker compose up -d --build app` 3. Zwei Gruppen anlegen, **Verwaltung → QR-Typen** öffnen, oben eine Gruppe wählen. 4. Dort einen Typ abschalten. Erwartet: Nur diese Gruppe verliert ihn; die Grundeinstellung und die andere Gruppe bleiben unberührt. 5. Denselben Typ in der **Grundeinstellung** abschalten, dann wieder eine Gruppe wählen. Erwartet: Der Schalter ist gesperrt und nennt den Grund. 6. Als Mitglied nur der eingeschränkten Gruppe einen Code dieses Typs anlegen wollen — das wird mit einer passenden Meldung abgelehnt. Geprüft mit einer eigenen Testreihe: **38 von 38** — Abweichung setzen und zurücknehmen, „global aus gewinnt“ über API und beim Anlegen, Anlegen je Gruppe, Vereinigung auf der Startseite, Oberfläche samt gesperrtem Schalter, Handy-Breite, keine Konsolenfehler. **Aufgewendete Zeit:** 00:11 **Pull Request:** #17 Nach Freigabe: `/issue-freigabe 11`
Author
Owner

🚀 Freigegeben und nach main übernommen.

  • Merge-Commit: c6891f6
  • Pull Request: #17 (gemergt)
  • Gesamtaufwand: 00:11

Nach den vorangegangenen fünf Merges habe ich main in den Zweig geholt — ohne Konflikt, obwohl prisma/schema.prisma, docs/funktionen.md, src/app/api/codes/route.ts und die Erstellen-Seite auch von #6, #7 und #8 angefasst wurden. Nachgesehen, dass alles nebeneinander steht: Gruppenfreigabe, Dublettenprüfung und Logo-Anhang in derselben Route; checkSecret, die Logo-Spalten und QrTypeGroupSetting im selben Schema.

Testreihen gegen den zusammengeführten Stand: Typen je Gruppe 38 von 38, Filter nach Art 28 von 28. Typprüfung, Linter und die Changelog-Prüfung auf main: grün.

Issue wird geschlossen.

🚀 **Freigegeben und nach `main` übernommen.** <!-- claude-status merge: c6891f6 pr: 17 zeit_sekunden: 643 --> - Merge-Commit: `c6891f6` - Pull Request: #17 (gemergt) - Gesamtaufwand: 00:11 Nach den vorangegangenen fünf Merges habe ich `main` in den Zweig geholt — **ohne Konflikt**, obwohl `prisma/schema.prisma`, `docs/funktionen.md`, `src/app/api/codes/route.ts` und die Erstellen-Seite auch von #6, #7 und #8 angefasst wurden. Nachgesehen, dass alles nebeneinander steht: Gruppenfreigabe, Dublettenprüfung und Logo-Anhang in derselben Route; `checkSecret`, die Logo-Spalten und `QrTypeGroupSetting` im selben Schema. Testreihen gegen den zusammengeführten Stand: Typen je Gruppe **38 von 38**, Filter nach Art **28 von 28**. Typprüfung, Linter und die Changelog-Prüfung auf `main`: grün. Issue wird geschlossen.
florian.wilde removed the zu-testen label 2026-08-21 09:01:02 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Total Time Spent: 10 minutes
florian.wilde
10 minutes
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: florian.wilde/qrcode-generator#11