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:
@@ -0,0 +1,19 @@
|
||||
import { IsBoolean, IsNumber, IsOptional, IsString, MinLength } from "class-validator";
|
||||
|
||||
/**
|
||||
* A new bank-register movement. `amount` is signed: positive = ingreso,
|
||||
* negative = egreso (the module's sign convention). Single currency (MXN).
|
||||
* Booked rows are never edited — a mistake is corrected by voiding + re-capture.
|
||||
*/
|
||||
export class CreateBankMovementDto {
|
||||
@IsNumber() amount!: number;
|
||||
@IsString() @MinLength(1) transactionDate!: string;
|
||||
|
||||
@IsOptional() @IsString() concept?: string;
|
||||
@IsOptional() @IsString() reference?: string;
|
||||
@IsOptional() @IsString() transactionType?: string;
|
||||
@IsOptional() @IsBoolean() cleared?: boolean;
|
||||
@IsOptional() @IsBoolean() transferred?: boolean;
|
||||
@IsOptional() @IsString() notes?: string;
|
||||
@IsOptional() @IsString() amountInWords?: string;
|
||||
}
|
||||
Reference in New Issue
Block a user