docs(arap): B-41, the bookspec examples, and the four registers (P4b S7)
rules.md B-41 states the write-off: the direct method the owner chose (A-5), Dr 6990 / Cr 1200 with the receivable tagged, at most what is owed and at most the least owed from that day on (a partial write-off as §1.166-3(a) allows), refused on cash-basis books (§1.166-1(e)), its evidence filed in the same call (§1.166-2(a)); bills are never written off (ASC 405-20-40-1); and a recovery is not a new movement (D-49): the same year, reverse the write-off and record the payment; a later year, a plain entry to a bad-debt-recoveries revenue account, the invoice staying written off (IRC §111). bookspec states B-41 for the first time and gives B-38 its example: two new examples, bad-debt-direct-write-off (two partial write-offs of one invoice, the balances and the trial balance worked by hand) and arap-hand-control-posting-refused (a hand line an earlier version wrote replays, the same line written today is refused). The example schema gains the dated write_off event, lets a refused entry say so (an entry posts whole or not at all; older and refused never combine), and its refusal vocabulary gains untagged_control_line, B-38's control guard. The registers: docs/architecture.md names the new tool group; docs/receipt-store.md lists invoice.written_off and what replay does with it; docs/parity.md records the slice (no row changes status, the floor stands); docs/testing.md records every test and what P12 must mutate; docs/verification.md the two Lean theorems and what they cover. No figure moves: no golden file changed.
This commit is contained in:
1 parent
b731d7ed04
commit
0322778683
13 files changed
+547
-25
No files matched your search
@@ -3050,3 +3050,80 @@ and `BooksServer::new`'s copy (a dropped field must fail
|
||||
`isolation_label_is_enforced_under_the_unit`); the host's `server_flags`
|
||||
extension and `parse_args`' passthrough of `--isolation` and its optional
|
||||
`--http` value.
|
||||
|
||||
## P4b S7: bad debts (write-offs), 2026-10-27
|
||||
|
||||
The write-off (plan 8.2 S7; rules.md B-41): an invoice that will not be
|
||||
collected leaves the receivables as a deduction, with its evidence filed
|
||||
in the same call.
|
||||
|
||||
- **ledger-core, `tests/spec_documents.rs`:**
|
||||
`half_paid_rest_written_off_is_written_off` (B-38 SCENARIO 7: 50 paid,
|
||||
50 written off, one balanced entry Dr 6990 / Cr 1200, the receivable
|
||||
line tagged `WriteOff`, receivables down by exactly the write-off);
|
||||
`write_off_refused_on_cash_basis` (B-41 INVARIANT 3: refused, the
|
||||
snapshot unchanged, no draft left); `write_off_above_outstanding_refused`
|
||||
(the bound at the day, a zero and a negative amount, then the exact
|
||||
amount owed taken); `write_off_then_recovery_same_year` (D-49: the
|
||||
reversal re-instates the debt, the payment settles it, the invoice reads
|
||||
Paid and the write-off entry no longer stands). The first test's book
|
||||
is also the identity's: `control_check` agrees after the write-off.
|
||||
- **ledger-store, `tests/arap_standing.rs`:**
|
||||
`write_off_waits_for_documents_v2` (R-A: refused with
|
||||
`FormatUpgradePending`, journal and head unchanged, in the old-books
|
||||
fixture; taken after the upgrade; the evidence filed on the entry and
|
||||
linked to the invoice; replay equals live);
|
||||
`write_off_replays_and_projects` (the journal holds one
|
||||
`invoice.written_off` with its five facts, `receipt.attached` then
|
||||
`attachment.linked`; 6990 carries the expense, 1200 is zero, the
|
||||
control check agrees, `verify` passes and a reopened store has the same
|
||||
books and the same figures); `write_off_without_evidence_is_refused`
|
||||
(no evidence, and an attachment that isn't there, journal nothing; one
|
||||
already filed is linked to the entry and the invoice).
|
||||
`tests/arap_props.rs` gains `Op::WriteOff`: random write-offs (partial
|
||||
and over-large, refused ones included) run through the store, which is
|
||||
then reopened and read by a `Snapshot`; `status_is_a_function_of_journal_and_date`
|
||||
still holds at every date.
|
||||
- **Over the wire, `crates/ledger-cli/tests/documents.rs`:**
|
||||
`write_off_then_recovery` (an upload as the evidence, `confirmed`, the
|
||||
invoice reading written_off with its figures and its timeline, the
|
||||
receipt on the entry, the reversal and the payment, the control check
|
||||
agreeing) and `write_off_needs_evidence` (neither or both evidence
|
||||
arguments refused; an already-filed attachment linked to the entry and
|
||||
the invoice).
|
||||
- **The viewer, `crates/ledger-gui/tests/invoices.rs`:**
|
||||
`a_write_off_shows_on_the_timeline` (the shipped screenshot
|
||||
`invoice-written-off`: status Written off, still owed $0.00, the
|
||||
timeline's "Written off" row opening its entry).
|
||||
`crates/ledger-gui/tests/view_model.rs`: `a_write_off_is_flagged_for_the_cpa`
|
||||
(one item, "Write-off awaiting the CPA's note", the same through the
|
||||
server's read of the store and the viewer's snapshot).
|
||||
- **Lean, `Wanderbooks/Documents.lean`:** `Step.writeOff` (a tagged
|
||||
control line and an untagged expense line: a `Step.document` in shape),
|
||||
`Step.writeOff_unattached` (it moves nothing unattached, so
|
||||
`control_agrees` and `Reachable.control_is_documents` still hold),
|
||||
`through_append`, `docSum_writeOffLines`, and `writeOff_within_bounds`
|
||||
(a write-off of at most what is owed leaves nothing owed below zero over
|
||||
the date-sum). Both theorems are in `Audit.lean`. No kernel function
|
||||
was added, so no Kani harness.
|
||||
- **bookspec:** `bad-debt-direct-write-off` (B-41, CHOICE: invoice 100,
|
||||
two partial write-offs, the balances and the trial balance) and
|
||||
`arap-hand-control-posting-refused` (B-38: an entry an earlier version
|
||||
wrote on receivables replays, attempts the control guard now refuses,
|
||||
and the books still tie out). The example schema gained the `write_off`
|
||||
event and lets a refused `lines` event say so (an entry posts whole or
|
||||
not at all); the refusal vocabulary gained `untagged_control_line`,
|
||||
which belongs to B-38.
|
||||
|
||||
**For P12 (mutation targets, none run, D-33):** `Ledger::write_off_steps`'
|
||||
cash-basis comparison (the `eq_ignore_ascii_case`, the early return), its
|
||||
order of checks (amount before the day, the day before the room), the
|
||||
`amount > room` bound and its `room < owed` message arm, the `WriteOff`
|
||||
tag, `least_owed_from`'s `max` and its `min` over later days (the refactor
|
||||
`payment_room` now shares), `replay_invoice_write_off`'s movement, and
|
||||
`doc_state`'s `written_off` arm; `Store::write_off_invoice`'s evidence
|
||||
arms (the `check_linkable` call, the already-linked-to-the-invoice check,
|
||||
the blob-before-journal order, the `File`/`Existing` link steps) and the
|
||||
feature gate; the MCP handler's amount default, the exactly-one evidence
|
||||
check, and the preview's clone; attention's year comparison and its
|
||||
`stands_on` filter; the bookspec loader's `may_refuse` arm.
|
||||
Reference in new issue
Block a user