Completes phase 5 — the ledger and chequera pages get the append+void
UI on top of the phase-5 API.
Web:
- Shared MovementForm (customer picker + línea + cargo/abono sign + amount
+ moneda + concepto facet + periodo/referencia/cheque/mensaje). Used by
both /estado-cuenta (cross-customer, picker) and /estado-cuenta/[id]
(customer prefilled).
- /estado-cuenta and /estado-cuenta/[id]: "Capturar movimiento" toggle
gated ledger:create; per-row "Anular" gated ledger:void; voided rows
struck-through. Save/void refresh the list + stats.
- /banco: inline BankCaptureForm (ingreso/egreso sign, cheque, operado,
transferencia, monto en letras) gated bank:create; per-row "Anular"
gated bank:void; voided rows struck-through.
- api.ts: createMovement/voidMovement, createBankMovement/voidBankMovement;
CreateMovementInput/CreateBankMovementInput types; `voided` on the
movement/statement/bank list items.
Also: lookups.controller.ts now audit-logs provider/policy-type/adjuster
create/update/delete (parity with the other write controllers).
API + web compile clean. This is the last piece of the feat/crud-rbac
branch — all five sections plus users are now full CRUD with role gating.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Policy header, all five child collections, and the insurance reference
catalogs become create/edit/delete-able on the RBAC foundation.
API:
- Policy gains archivedAt (soft-delete); list/browser default to
archivedAt=null with ?includeArchived opt-in.
- PoliciesService: header create/update/archive/restore (customer FK
validated for a clean 404); add/update/remove for installments,
vehicles, drivers, beneficiaries, claims — each scoped to its policy so
one policy's id can't touch another's rows; lookups CRUD for providers,
policy types, adjusters.
- PoliciesController write routes: header create/update need STAFF+
(policy:create/update), archive/restore need MANAGER+ (policy:delete),
every child route needs policy:update. New LookupsController at /lookups
(read open; mutate needs lookup:manage / MANAGER+). Mutations audited.
- DTOs (policy header, children, lookups); dates coerced; shared coerce.ts.
Web:
- Generic ChildCollection editor (config-driven add/edit/remove table),
reused by both the policy detail child editors and the catalogs screen.
- PolicyForm (header) with type/provider selects and a debounced
CustomerPicker; /polizas/nuevo (accepts ?customerId prefill) and
/polizas/[id]/editar. Policy detail: gated action bar (Editar/Archivar)
+ "Administrar detalles" child editors for all five collections.
- /catalogos admin screen (aseguradoras/tipos/ajustadores), nav-gated on
lookup:manage. "Nueva póliza" buttons on the list and on the customer
detail (prefilled). api.ts + types for all of the above.
Verified against dev: policy create (dates coerced, archivedAt null),
installment/vehicle add, VIEWER child-add 403, cross-policy child guard
404, lookups CRUD with VIEWER 403 / MANAGER 201, archive drops from the
default list and includeArchived surfaces it. Both apps compile clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>