Pläne: Hinweise aus dem Review von Plan 1 (Livegang-Prüfung, Rechnungszeilen, lookup_keys)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-09-27 15:47:02 +00:00
1 parent 47c1af7015
commit f016ad0326
2 files changed
+7

No files matched your search

@@ -62,6 +62,7 @@
- `contractEvents.type` ist `abschluss`, `wechsel`, `speicher`, `kuendigung` oder `widerruf`. `status` ist `offen`, `erledigt` oder `widerrufen`.
- Stripe-Metadaten am Abo: `webklarCustomerId`, `email`, `productKey`, `termStartAt`, `termsVersion`, `termsAcceptedAt`, `earlyStartConsentAt`, `consentIp`, `consentUserAgent`, `switchedFrom`, `switchedAt`.
- Testrabatte: `WEBKLAR-TEST-050` (Wartung, amount_off 4950, besteht schon) und `WEBKLAR-TEST-050-HOSTING` (Hosting, amount_off 1450).
- lookup_keys werden in Stripe nie übertragen (`transfer_lookup_key`). Ein neuer Preis bekommt einen neuen lookup_key im Katalog, denn Zuordnung und Stundenregel hängen am lookup_key (Plan 1).
**Deploy und Produktion**
@@ -629,6 +630,9 @@ test('Widerrufsfristen aus den Ereignissen', async () => {
- Es entsteht das Ereignis `speicher`: Status `offen`, `dueAt` = jetzt (Plus) bzw. `currentPeriodEnd` (Minus), `details: { fromUnits, toUnits }`.
- Danach gehen K13 an den Kunden (beim Plus mit PDF) und T13 ans Team.
- **`recordPaidStorage(freshInvoice)`:** Hat die Rechnung eine reguläre Zusatzspeicher-Zeile (nicht anteilig), setzt die Funktion `storagePaidUnits` auf deren `quantity` und `storagePaidPeriodEnd` auf `line.period.end`.
- **Alle Rechnungszeilen laden** (Hinweis aus dem Review von Plan 1): `invoices.retrieve` bettet höchstens 10 Zeilen ein. Anteilige Zeilen stehen vor den Abo-Zeilen, und mehrere Speicheränderungen in einem Monat können die Wartungs-Zeile hinausschieben.
- `grantCreditForInvoice` und `recordPaidStorage` laden deshalb bei `lines.has_more` alle Zeilen per `invoices.listLineItems(id, { limit: 100 })`.
- Test: Rechnung mit 11 Zeilen, die Wartungs-Zeile ist die elfte. Ergebnis: 60 Minuten.
- **Routen:**
- `POST /api/abo/storage/preview` mit dem Body `{ units }`
- `POST /api/abo/storage` mit dem Body `{ units, acceptTerms, termsVersion }`, dabei ist `acceptTerms` beim Plus Pflicht