Web: Obergruppen zuordnen, Mindestbestaende nach Lagerort

Mindestbestaende-Seite ist jetzt nach Lagerort gegliedert statt nach Artikel -
"Ueberall (egal wo)" zuerst, danach die Lagerorte. Es gibt keine automatische
Leerzeile je Artikel mehr; angelegt wird ueber "+ hinzufuegen" im jeweiligen
Abschnitt, dann steht der Ort schon fest und es fehlen nur Ziel und Menge.
Das Zeilenmodell faellt damit von vier Faellen auf zwei, und weil der Server
einheitlich Basiseinheiten liefert, bleibt genau eine Umrechnung uebrig statt
der drei gegenlaeufigen von vorher.

Gruppen: neue Spalte "Obergruppen" mit Mehrfachauswahl (GroupParentSelect).
Bewusst kein Baum - CategorySelect und die tree-Prop der DataTable koennen nur
einen Elternteil und wuerden eine Gruppe mit zwei Obergruppen doppelt anzeigen.
Die eigene Gruppe und ihre Untergruppen sind in der Auswahl gesperrt, damit die
Ringregel sichtbar wird, bevor der Server sie ablehnt. Produktzahl zeigt
transitiv und direkt ("12 (3 direkt)"), dazu Badges fuer Untergruppen und eine
Warnung, wenn eine Gruppe mit Untergruppen keine Einheit hat - sonst summiert
sie Gramm und Stueck zu einer sinnlosen Zahl.

Einkaufsliste: "Gesamt" heisst "Ueberall", Gruppen zeigen ihre mitgezaehlten
Untergruppen, und eine Fussnote benennt die eine Stelle, die sich nicht
verrechnen laesst (zwei Obergruppen mit gemeinsamer Untergruppe).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-08-15 23:56:18 +02:00
parent 54261b98c0
commit 0537a2b53f
9 changed files with 603 additions and 357 deletions

View File

@@ -345,6 +345,9 @@ function KarteEinkaufsliste({ props: karteProps }) {
<label>
<input type="checkbox" checked={!!erledigt[key]} onChange={(e) => abhaken(key, e.target.checked)} />
<span className="badge accent">Gruppe</span>
{it.subgroup_count > 0 && (
<span className="badge" title="Untergruppen sind mitgezählt.">+{it.subgroup_count}</span>
)}
<span className="item-name">{it.name}</span>
</label>
<span className="muted small">
@@ -374,7 +377,7 @@ function KarteEinkaufsliste({ props: karteProps }) {
<div className="card-stack">
{!gesamtLeer && (
<div>
<div className="muted small" style={{ fontWeight: 600 }}>Gesamt</div>
<div className="muted small" style={{ fontWeight: 600 }}>Überall</div>
{abschnitt(daten.gruppen, daten.produkte, "")}
</div>
)}