feat(vorlage): Vorlage direkt editierbar ohne Versionszwang (Nutzer-Vorgabe)
Bisher wurde die Sollmenge einer Objektposition live aus der Vorlagenposition
gelesen (objekt.vorlage_id -> vorlagenposition.sollmenge), Bearbeiten der
Vorlage erzeugte deshalb zwingend eine neue Version - sonst hätte sich jede
Änderung rückwirkend auf alle Objekte ausgewirkt, die diese Vorlage nutzen.
- Neue Spalte objektposition.sollmenge_vorlage (Migration 0020): kopiert die
Sollmenge fest bei Anlage/Duplizieren statt live nachzuschlagen
- sollmenge_effektiv(position) liest jetzt nur noch override/sollmenge_vorlage,
kein DB-Lookup mehr nötig (sollmenge_map() entfernt)
- Neuer Endpoint PUT /vorlagen/{id}/positionen: ersetzt Positionen direkt,
ohne neue Version. Bestehende Objekte unbetroffen, nur neu angelegte nutzen
die aktualisierten Werte (Test: test_aktualisiere_positionen_wirkt_nicht_
rueckwirkend_auf_bestehendes_objekt)
- POST /vorlagen/{id}/neue-version bleibt zusätzlich bestehen (nicht entfernt)
- Frontend: "Neue Version speichern" -> "Positionen speichern" (PUT statt POST)
- 140 Tests grün
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
This commit is contained in:
@@ -45,17 +45,20 @@ export function VorlageSection({ vorlagen, objekttypen, materialien, faecher, on
|
||||
setNeueVersionZeilen((bisherige) => bisherige.map((z, i) => (i === index ? { ...z, ...zeile } : z)));
|
||||
}
|
||||
|
||||
async function neueVersionSpeichern(vorlageId: number) {
|
||||
async function positionenSpeichern(vorlageId: number) {
|
||||
const positionen = neueVersionZeilen
|
||||
.filter((z) => z.materialId !== "")
|
||||
.map((z) => ({ material_id: z.materialId, fach: z.fach || null, sollmenge: z.sollmenge }));
|
||||
setWirdVersioniert(true);
|
||||
try {
|
||||
await apiRequest(`/vorlagen/${vorlageId}/neue-version`, { method: "POST", body: { positionen } });
|
||||
// Nutzer-Vorgabe 2026-09-05: Vorlage muss keine Versionen haben - ersetzt
|
||||
// die Positionen direkt (PUT), keine "neue Version" mehr. Bereits
|
||||
// angelegte Objekte sind unbetroffen (Sollmenge fest kopiert, Backend).
|
||||
await apiRequest(`/vorlagen/${vorlageId}/positionen`, { method: "PUT", body: { positionen } });
|
||||
setAusgeklapptId(null);
|
||||
await onGeaendert();
|
||||
} catch {
|
||||
onFehler("Neue Version konnte nicht angelegt werden.");
|
||||
onFehler("Positionen konnten nicht gespeichert werden.");
|
||||
} finally {
|
||||
setWirdVersioniert(false);
|
||||
}
|
||||
@@ -164,14 +167,15 @@ export function VorlageSection({ vorlagen, objekttypen, materialien, faecher, on
|
||||
{v.name} <span className="badge badge-neutral">v{v.version}</span>
|
||||
</span>
|
||||
<button className="btn btn-secondary" onClick={() => versionBearbeiten(v)}>
|
||||
{ausgeklapptId === v.id ? "Schließen" : "Positionen / neue Version"}
|
||||
{ausgeklapptId === v.id ? "Schließen" : "Positionen bearbeiten"}
|
||||
</button>
|
||||
</div>
|
||||
{ausgeklapptId === v.id && (
|
||||
<div className="stack" style={{ marginTop: "0.6rem" }}>
|
||||
<p className="text-muted" style={{ marginBottom: 0 }}>
|
||||
Änderungen erzeugen eine neue Version – die aktuelle v{v.version} bleibt unverändert
|
||||
erhalten.
|
||||
Änderungen wirken direkt auf diese Vorlage, ohne neue Version. Bereits angelegte
|
||||
Objekte behalten ihre bisherige Sollmenge – nur neu angelegte Objekte nutzen die
|
||||
aktualisierten Werte.
|
||||
</p>
|
||||
{neueVersionZeilen.map((zeile, i) => (
|
||||
<div className="row" key={i}>
|
||||
@@ -211,10 +215,10 @@ export function VorlageSection({ vorlagen, objekttypen, materialien, faecher, on
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
onClick={() => neueVersionSpeichern(v.id)}
|
||||
onClick={() => positionenSpeichern(v.id)}
|
||||
disabled={wirdVersioniert}
|
||||
>
|
||||
Neue Version speichern
|
||||
Positionen speichern
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user