- Oeffentliche Kuendigung: exakte Identifikation, Limits je Vertrag und
Adresse, Bestaetigung nur an die Kontoadresse mit Ruecknahme-Link (HMAC)
- Vorschau: Body-Grenze beim Lesen, Parallelitaets- und Minutenlimit, Cache
- Rabatte gelten nicht fuer Patenschaftspositionen
- Abo aktiv erst nach bestaetigter Zahlung, offene Abschluesse zaehlen
zum Kontingent und werden nach 24 h aufgeraeumt, Sitzung 58 Minuten
- Konto-Loeschung nur ohne laufendes Abo, Urkunden-Dateien werden entfernt
- Abo-Lieferungen mit Zahlungszeile (DHL-Marke moeglich)
- Shop zeigt freien Bestand nach Abo-Reservierung
- Storno/volle Erstattung widerruft die Patenschaft (Status WIDERRUFEN)
- Umsatzsteuer der Patenschaft per VAT_RATE_PERCENT_PATENSCHAFT (19 %)
- Digitale Bestellungen archivieren sich, Kalendertage in Europe/Berlin,
Monatsenden begrenzt, Datenauskunft um Patenschaften ergaenzt
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Cancelled orders:
- Moving an order out of STORNIERT is possible again, but only after a
warning is confirmed in the status form (OrderStatusForm); without
the confirmation the server changes nothing.
- Reopening books the counter-entry to the cancellation: goods that the
cancellation restocked are deducted again (atomically, only if enough
stock is left, otherwise the order stays cancelled). A later second
cancellation therefore restocks +1 again instead of leaving +2.
- The warning states that no new payment is collected.
Dashboard figures:
- One definition of a counted sale (lib/sales.ts): not unpaid (NEU),
not cancelled, no refunded return. Used for revenue today/month, sold
glasses, average cart, top products/categories, revenue trend and
repeat customers.
- "Verkaufte Gläser" previously summed every order item, including
cancelled orders and refunded returns.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
After refund + cancellation the stock rose by 2 instead of 1. Cause:
the status form allowed moving an order out of STORNIERT. Cancelling
restocks the goods and refunds the payment; reopening did neither in
reverse, and the next cancellation passed the "not already cancelled"
claim again and restocked a second time (the refund was not repeated
because the payment was already REFUNDED, so only the stock showed it).
STORNIERT is now a final state:
- isOrderStatusChangeAllowed() in lib/inventory.ts next to the other
cancel rules, with tests
- updateOrderStatusAction rejects the change up front with a clear
message and moves non-cancel statuses with an atomic
"status <> STORNIERT" update, so a cancellation from a second tab
cannot be undone in between
- the order list and detail page no longer offer the status select for
cancelled orders
Existing stock that was restocked twice has to be corrected by hand.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Das Speichern schrieb den Formularwert immer fest in den Lagerbestand.
Wurde zwischen Oeffnen und Speichern ein Glas verkauft, kam es dadurch
wieder in den Bestand, ohne dass es je zurueckkam.
- Das Formular schickt den Bestand beim Oeffnen mit (quantityLoaded)
- Feld unveraendert: Bestand wird nicht angefasst
- Feld geaendert: Schreiben nur, wenn der Bestand noch dem geladenen Stand
entspricht (Bedingung atomar im UPDATE); sonst wird nichts gespeichert
und der aktuelle Wert angezeigt
- Fehlt quantityLoaded (alter Tab), muss neu geladen werden
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Wurde eine Retoure erstattet und die Bestellung danach auf "STORNIERT"
gesetzt, buchten beide Schritte die Ware zurueck. Bei einer Testbestellung
stieg der Bestand so von 105 auf 106 Glaeser.
- Stornieren bucht nur noch zurueck, wenn keine Retoure erstattet ist
(needsRestockOnCancel in lib/inventory.ts)
- Retoure einer bereits stornierten Bestellung laesst sich nicht mehr
erstatten, auch nicht im Wettlauf (Bedingung im atomaren Claim)
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>