feat(ledger,bank): append + void write API, voided excluded from totals (plan phase 5 API)
Transactions and the bank register become append-only with a void (reversal) action — never edited or hard-deleted. This is the API half of phase 5; the capture/void web UI is the remaining piece. Schema: - Transaction and BankTransaction gain voidedAt + voidedById. A non-null voidedAt reverses the row. Pushed to dev. Correctness (the high-stakes part): - Every aggregate excludes voided rows: billing movements totals, the raw balances SQL, stats (groupBy + the sides/crossLine raw subqueries + first/last), facets (types/sources/years); the statement's running balance freezes on a voided row and its per-currency/per-domain/per-type summaries skip them; customers.detail and property owner-ledger groupBy; and every bank total (totalsFor, stats counts/bounds, facets + summary raw SQL). List views still return voided rows with a `voided` flag so the UI can strike them through. - Bank's legacy zero-amount "void" cheques are unchanged and distinct from app voids (voidedAt). API: - POST /billing + POST /billing/:id/void (ledger:create / ledger:void); POST /bank + POST /bank/:id/void (bank:create / bank:void). Create needs STAFF+, void needs MANAGER+. Double-void -> 400, unknown id -> 404, bad date -> 400. Mutations audited. DTOs added. Verified against dev end-to-end: a -500 MXN charge moved a customer balance 31082.08 -> 30582.08, and voiding it returned it to 31082.08 to the cent; a +1234.56 bank ingreso moved net 899375.77 -> 900610.33 and voiding returned it to 899375.77. VIEWER create/void both 403, double-void 400. API compiles clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -409,6 +409,11 @@ model Transaction {
|
||||
checkNumber String?
|
||||
message String? @db.Text
|
||||
outstanding Boolean @default(false)
|
||||
// Append + void: booked rows are never edited or hard-deleted. A non-null
|
||||
// voidedAt reverses the movement — it MUST be excluded from every balance
|
||||
// and total (SUM/count) so a voided amount stops affecting the books.
|
||||
voidedAt DateTime?
|
||||
voidedById String?
|
||||
legacySourceDb String?
|
||||
legacySourceTable String?
|
||||
legacyId String?
|
||||
@@ -457,6 +462,9 @@ model BankTransaction {
|
||||
transferred Boolean @default(false)
|
||||
notes String? @db.Text
|
||||
amountInWords String?
|
||||
// Append + void (see Transaction.voidedAt): excluded from income/expense/net.
|
||||
voidedAt DateTime?
|
||||
voidedById String?
|
||||
legacySourceTable String?
|
||||
legacyId String?
|
||||
|
||||
|
||||
Reference in New Issue
Block a user