Energie-Bonus aufgeteilt in Sofort + Neukunden

EnergyContractDetails.bonus war ein einzelnes Feld. Strom-/Gas-
Verträge haben aber typischerweise zwei Boni (Sofort beim Wechsel
+ Neukunden-Bonus nach 12 Monaten), die getrennt verbucht werden
müssen.

Migration 20260524100000_split_energy_bonus:
- ADD COLUMN IF NOT EXISTS instantBonus, newCustomerBonus
- bestehende `bonus`-Werte → instantBonus (Annahme: Sofort)
- DROP COLUMN IF EXISTS bonus

UI:
- ContractForm zeigt zwei Input-Felder
- Detail-Ansicht zeigt beide einzeln + Gesamtbonus
- Kostenvorschau listet beide einzeln, dann Gesamt, dann effektive
  Jahreskosten

Cost-Calc: calculateCosts() bekommt beide Boni; CostCalculation
liefert instantBonus, newCustomerBonus, totalBonus.

PDF-Template: drei neue Variablen energyDetails.instantBonus,
.newCustomerBonus, .totalBonus.

Live-verifiziert auf dev: PUT mit beiden Werten → DB persistiert,
GET liefert zurueck.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-24 14:27:54 +02:00
parent 92c3b0dc95
commit 20d42c5270
10 changed files with 143 additions and 29 deletions
+27
View File
@@ -120,6 +120,33 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung
- **Live-verifiziert**: 4867 Datensätze + 1 Datei in 13.2s
wiederhergestellt, Log-Modal zeigt den vollständigen Verlauf.
- [x] **🆕 Bonus-Feld aufgeteilt: Sofort-Bonus + Neukunden-Bonus (Strom/Gas)**
- Bisher gab es ein einzelnes `bonus`-Feld auf `EnergyContractDetails`.
Jetzt zwei Felder `instantBonus` (Sofort) und `newCustomerBonus`
(Neukunden), die zusammen den Gesamtbonus ergeben.
- **Migration** `20260524100000_split_energy_bonus`:
`ADD COLUMN IF NOT EXISTS instantBonus`, `... newCustomerBonus`,
`UPDATE` kopiert bestehendes `bonus``instantBonus`
(Annahme: Bestandsverträge hatten primär Sofort-Bonus), dann
`DROP COLUMN IF EXISTS bonus`. Idempotent.
- **Form** (`ContractForm.tsx`): zwei Input-Felder „Sofort-Bonus (€)"
+ „Neukunden-Bonus (€)" statt einem.
- **Detail-Ansicht**: zeigt beide Felder einzeln und einen
aggregierten „Gesamtbonus" (fett) darunter.
- **Kostenvorschau**: listet Sofort + Neukunden einzeln auf
(jeweils grün), dann „Gesamtbonus" (mittel grün, fett), danach
Effektive Jahreskosten.
- **Cost-Calc** (`energyCalculations.ts`): `calculateCosts()` nimmt
jetzt beide Bonus-Werte; `CostCalculation` liefert `instantBonus`,
`newCustomerBonus` + `totalBonus`.
- **PDF-Template-Variablen**: drei neue Placeholder
`energyDetails.instantBonus`, `.newCustomerBonus`, `.totalBonus`
(alter `.bonus`-Placeholder entfernt).
- **Audit-Log** unterscheidet jetzt beide Felder.
- **Live-verifiziert** auf dev: PUT mit beiden Feldern → DB hat
`instantBonus=75, newCustomerBonus=125`, GET liefert beide
Werte zurück.
- [x] **🛡️ Pentest 2026-05-20 Pen-30-Befunde (MEDIUM+INFO)**
- **30.13 MIME-Extension-XSS** (MEDIUM): `GET /api/files/download`
lieferte hochgeladene Dateien via `res.sendFile` aus. Da multer