feat: Bestellungen ohne Geschaeftsvorfall lassen sich im Admin loeschen
Docker Image bauen und veroeffentlichen / build-and-push (push) Successful in 2m12s
Docker Image bauen und veroeffentlichen / build-and-push (push) Successful in 2m12s
Stornieren gab es bereits, Loeschen nicht — abgebrochene Checkouts und Testbestellungen blieben dauerhaft in der Liste stehen. Loeschbar ist bewusst nur, was nie ein Geschaeftsvorfall war: keine Zahlung erfasst, keine Rechnung erzeugt, Status NEU oder STORNIERT. Eine bezahlte Bestellung und ihre Rechnung sind Buchungsbelege (§ 147 AO, § 257 HGB) und muessen jahrelang vorgelegt werden koennen; ein Loeschknopf darauf wuerde nicht aufraeumen, sondern Unterlagen vernichten. Dafuer gibt es den Storno: er erstattet das Geld, bucht die Ware zurueck und laesst den Beleg stehen. Die Regel steht in lib/order-delete.ts als reine Logik ohne Datenbankzugriff — dieselbe Trennung wie bei shipping-calc.ts. Server Action und Admin-Seite teilen sie sich, statt die Bedingung zweimal zu formulieren und irgendwann auseinanderzulaufen, und sie laesst sich ohne DATABASE_URL testen (13 neue Faelle, u.a. dass bei Rechnung UND Zahlung die Rechnung als Grund gemeldet wird). Drei Dinge, die ein blosses delete() falsch gemacht haette: - LAGERBESTAND: bei NEU liegt die Ware reserviert und wird zurueckgebucht, bei STORNIERT ist das beim Stornieren bereits geschehen. Dort erneut gutzuschreiben wuerde den Bestand erhoehen, ohne dass je ein Glas zurueckkam. - ZAHLUNGSSITZUNG: eine Bestellung im Status NEU kann eine offene Stripe-Sitzung haben. Wird sie geloescht, ohne die Sitzung zu schliessen, kann Minuten spaeter noch bezahlt werden — der Webhook findet dann keine Bestellung mehr, und das Geld liegt bei Stripe, ohne dass im Shop etwas davon zu sehen waere. Die Sitzung wird deshalb VOR dem Loeschen geschlossen; gelingt das nicht sicher, wird gar nicht geloescht. Ist bei Stripe zwischenzeitlich bezahlt worden, verweigert die Aktion das Loeschen. - WETTLAUF: die Bedingungen stehen zusaetzlich in der WHERE-Klausel des DELETE. Zwischen Pruefung und Loeschen koennte der Webhook eine Zahlung eingetragen haben; die Pruefung sieht nur einen Schnappschuss, die WHERE-Klausel wird atomar gegen den aktuellen Zeilenstand ausgewertet. Der Audit-Log-Eintrag ist ausfuehrlicher als bei anderen Aktionen und traegt Bestellnummer, Status, Betrag, E-Mail und Positionsanzahl — der Datensatz ist danach weg, dieser Eintrag ist die einzige verbleibende Spur. Die Oberflaeche zeigt den Knopf am Seitenende in einem abgesetzten Bereich, damit er nicht neben dem Statusfeld liegt, mit Browser-Rueckfrage ueber ConfirmForm. Ist die Bestellung nicht loeschbar, steht dort statt des Knopfes der Grund und der Verweis auf den Storno. Die Bestellliste zeigt jetzt auch Erfolgsmeldungen, nicht nur Fehler. tsc: 0 Fehler. vitest: 372/372 gruen. eslint: 0 Warnungen. next build: gruen. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
1 parent
256e823c4f
commit
c35d61bfd6
8 files changed
+318
-2
No files matched your search
@@ -1123,6 +1123,14 @@ export const en: Dictionary = {
|
||||
dhlCreateButton: "Create shipping label",
|
||||
dhlAlreadyCreated: (trackingNumber) => `DHL shipping label already created: tracking number ${trackingNumber}`,
|
||||
dhlNotConfigured: "DHL isn't configured yet, see .env (DHL_API_KEY, DHL_API_SECRET, DHL_GKP_USERNAME, DHL_GKP_PASSWORD, DHL_ACCOUNT_NUMBER).",
|
||||
deleteHeading: "Delete order",
|
||||
deleteHint:
|
||||
"This order never became a business transaction: no payment, no invoice. It can therefore be removed without a trace. Reserved goods are credited back to stock.",
|
||||
deleteButton: "Delete permanently",
|
||||
deleteConfirm: (orderNumber) =>
|
||||
`Permanently delete order ${orderNumber}? This cannot be undone.`,
|
||||
deleteBlocked:
|
||||
"This order cannot be deleted — a payment or an invoice is attached to it, or it is already being processed. Invoices and payment records are subject to statutory retention. Cancel the order instead: that refunds the money, returns the goods to stock and keeps the record.",
|
||||
},
|
||||
adminOrdersPage: {
|
||||
backToDashboard: "Back to dashboard",
|
||||
|
||||
Reference in new issue
Block a user