feat(evidence): one function decides whether an entry needs evidence (P4)
Accounting reason: the receipt rule (Pub. 583, Rev. Proc. 98-25: the books must be demonstrably supported by the records) was decided in three places that could disagree: the server's post, the digest, and a string match on a journal-event origin in the viewer. ledger_core:: evidence::requirement is now the one decision: Required (with why) or Exempt (with the source). A reversal needs no receipt of its own (its evidence is its original's, D-47, D-12); neither do a closing entry, a schedule month's or a depreciation run's posting, a disposal, a document's entry, a payroll run or its remittance. The ledger learned the two origins it could not see (a disposal, a remittance) from the events that already name their entry, live and on replay. A split group counts for a draft only: a posted entry's decision was made when it posted. The policy moved with it (evidence::Policy; ReceiptPolicy in ledger-config keeps the words and delegates). Store::post_entry_checked refuses a covered draft with no receipt (StoreError::ReceiptRequired, which the MCP maps to the unchanged receipt_required error); Store::post_entry stays the primitive that commands and fixtures post through, since ~176 call sites post hand entries with no receipt. The viewer's missing_receipt calls requirement; its string match is gone. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HS8WZziDnyxunC23MUxrLp
This commit is contained in:
1 parent
28d46332e4
commit
7299cf90f2
6 files changed
+451
-132
No files matched your search
@@ -705,14 +705,13 @@ impl Books {
|
||||
.entry_vendor(id)
|
||||
.and_then(|v| ledger.get_vendor(v))
|
||||
.map(|v| v.name.clone());
|
||||
// The receipt policy covers what is posted by hand (journal
|
||||
// entries and recurring drafts); invoices, payments, closes,
|
||||
// depreciation, and schedules carry their own evidence, and a
|
||||
// reversal leans on its original's.
|
||||
let missing_receipt = matches!(origin, "Journal entry" | "Recurring")
|
||||
&& e.reversal_of().is_none()
|
||||
&& rec.is_empty()
|
||||
&& policy.receipt_required(&ledger, e);
|
||||
// The engine decides (plan P4, I-5): the receipt policy covers
|
||||
// what is posted by hand (journal entries, recurring drafts);
|
||||
// invoices, payments, closes, depreciation, and schedules carry
|
||||
// their own evidence, and a reversal leans on its original's.
|
||||
// The viewer asks the same function the server's gate asks.
|
||||
let missing_receipt = rec.is_empty()
|
||||
&& ledger_core::evidence::requirement(&ledger, e, ledger.settings()).is_required();
|
||||
let cash_effect = e
|
||||
.lines()
|
||||
.iter()
|
||||
|
||||
Reference in new issue
Block a user