Versionierung und Aenderungshistorie je Szenario
Deploy App / deploy (push) Successful in 1m48s

Version A.B: B automatisch je Bearbeitungssitzung (10-Minuten-Fenster,
unveraenderte Staende erzeugen keine), A manuell mit Pflichtkommentar.

Eine Version haelt den vollstaendigen Zustand als PlanInput-JSON -- dadurch
ist die Versionsauswahl in allen vier Analysewerkzeugen fast kostenlos,
bei Monte-Carlo je Szenario einzeln.

Wiederherstellen erhaelt die IDs (sonst verlieren Kind-Szenarien ihre
Diff-Basis) und legt den Stand selbst als neue Version an. Wo ein Bezug
trotzdem bricht, warnt der Dialog vorher namentlich.

Statischer Waechter-Test: jeder schreibende Endpunkt loest eine Version aus.
Migration gegen echtes Postgres verifiziert.

Spezifikation 0.19 (3.8 und 9.28 neu), 25 Tests (139 -> 164).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-19 22:09:10 +02:00
parent d04e07fdfb
commit d023534a03
28 changed files with 2021 additions and 13 deletions
+27
View File
@@ -59,5 +59,32 @@ describe("Datenbank-Migrationen", () => {
expect(scenCols, `Scenario.${c} fehlt`).toContain(c);
}
expect(scenCols).not.toContain("userId"); // Eigentümer hängt am Plan
// --- Versionierung ---
expect(tables, "Tabelle ScenarioVersion fehlt").toContain("ScenarioVersion");
expect(scenCols, "Scenario.currentMajor fehlt").toContain("currentMajor");
const verCols = await cols("ScenarioVersion");
for (const c of ["scenarioId", "major", "minor", "comment", "isMajor", "createdById", "snapshot"]) {
expect(verCols, `ScenarioVersion.${c} fehlt`).toContain(c);
}
// Bestehende Szenarien müssen nach der Migration eine gültige Hauptversion tragen --
// sonst stünde ein vor der Migration angelegter Plan ohne Version da.
const major = await db.query<{ column_default: string | null; is_nullable: string }>(
`SELECT column_default, is_nullable FROM information_schema.columns
WHERE table_name='Scenario' AND column_name='currentMajor'`
);
expect(major.rows[0].is_nullable).toBe("NO");
expect(major.rows[0].column_default).toContain("1");
// A.B muss je Szenario eindeutig sein, sonst kollidieren zwei Sitzungen auf derselben
// Nummer und die Historie wird mehrdeutig.
const idx = (
await db.query<{ indexname: string }>(
`SELECT indexname FROM pg_indexes WHERE tablename='ScenarioVersion'`
)
).rows.map((r) => r.indexname);
expect(idx).toContain("ScenarioVersion_scenarioId_major_minor_key");
}, 60000);
});