diff --git a/crates/ledger-cli/tests/documents.rs b/crates/ledger-cli/tests/documents.rs index b4d5cab..fc95e22 100644 --- a/crates/ledger-cli/tests/documents.rs +++ b/crates/ledger-cli/tests/documents.rs @@ -87,7 +87,12 @@ fn write_off_then_recovery() { }), ); // The write-off's evidence, uploaded as an agent uploads it (D-46). - let upload = wire.upload(LETTER, "collection-letter.pdf", "application/pdf", "document"); + let upload = wire.upload( + LETTER, + "collection-letter.pdf", + "application/pdf", + "document", + ); let out = ok( &mut wire, "books.write_off_invoice", @@ -110,7 +115,10 @@ fn write_off_then_recovery() { // invoice: get_entry shows the one, the document's timeline the other. let got = ok(&mut wire, "books.get_entry", json!({ "entry_id": entry })); assert_eq!(got["receipts"].as_array().map(Vec::len), Some(1), "{got}"); - assert_eq!(got["receipts"][0]["file_name"], json!("collection-letter.pdf")); + assert_eq!( + got["receipts"][0]["file_name"], + json!("collection-letter.pdf") + ); let doc = ok( &mut wire, "books.document", @@ -225,6 +233,12 @@ fn write_off_needs_evidence() { json!({ "attachment_id": attachment }), ); let links = receipt["links"].as_array().cloned().unwrap_or_default(); - assert!(links.iter().any(|l| l["kind"] == json!("invoice")), "{receipt}"); - assert!(links.iter().any(|l| l["kind"] == json!("entry")), "{receipt}"); + assert!( + links.iter().any(|l| l["kind"] == json!("invoice")), + "{receipt}" + ); + assert!( + links.iter().any(|l| l["kind"] == json!("entry")), + "{receipt}" + ); } diff --git a/crates/ledger-core/src/ledger.rs b/crates/ledger-core/src/ledger.rs index b1b52d0..4e4dfb4 100644 --- a/crates/ledger-core/src/ledger.rs +++ b/crates/ledger-core/src/ledger.rs @@ -6329,9 +6329,9 @@ impl Ledger { /// §1.166-2(a) (worthlessness on all the pertinent evidence), /// §1.166-3(a) (a partial write-off, to the extent charged /// off); docs/spec/rules.md B-41; plan/served.md P4b S7, - /// A-5 (direct write-off), A-6; ASC 326-20 noted (an allowance - /// is the GAAP preference; a small company's CPA accepts the - /// direct method, stated). + /// A-5 (the direct write-off method); ASC 326-20 noted (an + /// allowance is the GAAP preference; a small company's CPA + /// accepts the direct method, stated). /// INVARIANTS: /// 1. MUST post one balanced entry: Dr the bad_debts role (6990 Bad /// Debt Expense), Cr receivables, for the amount, dated the diff --git a/crates/ledger-core/tests/bookspec.rs b/crates/ledger-core/tests/bookspec.rs index d881306..643c24f 100644 --- a/crates/ledger-core/tests/bookspec.rs +++ b/crates/ledger-core/tests/bookspec.rs @@ -1171,13 +1171,14 @@ impl<'a> Books<'a> { .unwrap_or_else(|| panic!("{what}: event {} posted no invoice", w.invoice)); let amount = match &w.amount { Some(a) => exact(a, what), - None => self - .store - .ledger() - .invoice_state(invoice, day()) - .expect("the invoice's figures") - .expect("dated by its own day") - .outstanding, + None => { + self.store + .ledger() + .invoice_state(invoice, day()) + .expect("the invoice's figures") + .expect("dated by its own day") + .outstanding + } }; self.store .write_off_invoice( diff --git a/crates/ledger-gui/tests/invoices.rs b/crates/ledger-gui/tests/invoices.rs index d0d1b3f..dcba52e 100644 --- a/crates/ledger-gui/tests/invoices.rs +++ b/crates/ledger-gui/tests/invoices.rs @@ -252,8 +252,7 @@ fn a_write_off_shows_on_the_timeline() { let mut h = open(&dir, Route::Invoice(inv)); shot(&mut h, "invoice-written-off"); assert!( - h.query_by_label_contains("Written off, entry #") - .is_some(), + h.query_by_label_contains("Written off, entry #").is_some(), "the timeline shows the write-off" ); // The status chip reads its label ("Written off"), not "late". diff --git a/crates/ledger-gui/tests/view_model.rs b/crates/ledger-gui/tests/view_model.rs index 0781605..d6c0c4d 100644 --- a/crates/ledger-gui/tests/view_model.rs +++ b/crates/ledger-gui/tests/view_model.rs @@ -892,10 +892,12 @@ fn a_write_off_is_flagged_for_the_cpa() { }, ); let want = format!("Write-off awaiting the CPA's note: Invoice {inv}"); - let said = server - .iter() - .find(|a| a.title == want) - .unwrap_or_else(|| panic!("the server's list has no {want:?}: {:?}", server.iter().map(|a| &a.title).collect::>())); + let said = server.iter().find(|a| a.title == want).unwrap_or_else(|| { + panic!( + "the server's list has no {want:?}: {:?}", + server.iter().map(|a| &a.title).collect::>() + ) + }); assert_eq!(said.severity, ledger_package::Severity::Todo); assert!(said.prompt.contains("wanderbooks"), "{}", said.prompt); assert!(said.detail.contains("100.00"), "{}", said.detail); @@ -910,14 +912,15 @@ fn a_write_off_is_flagged_for_the_cpa() { .attention .iter() .find(|a| a.title == want) - .unwrap_or_else(|| panic!("the viewer shows no {want:?}: {:?}", books.attention.iter().map(|a| &a.title).collect::>())); + .unwrap_or_else(|| { + panic!( + "the viewer shows no {want:?}: {:?}", + books.attention.iter().map(|a| &a.title).collect::>() + ) + }); assert_eq!(shown.target, Some(ledger_gui::nav::Route::Documents)); // The viewer reads the same figures from the journal it replayed. - let st = books - .ledger - .invoice_state(inv, today) - .unwrap() - .unwrap(); + let st = books.ledger.invoice_state(inv, today).unwrap().unwrap(); assert_eq!(st.status, ledger_core::DocStatus::WrittenOff); assert!(books.ledger.get_entry(entry).is_some()); } diff --git a/crates/ledger-mcp/src/tools/write_offs.rs b/crates/ledger-mcp/src/tools/write_offs.rs index eda005e..62b137b 100644 --- a/crates/ledger-mcp/src/tools/write_offs.rs +++ b/crates/ledger-mcp/src/tools/write_offs.rs @@ -128,10 +128,6 @@ impl BooksServer { entry_id } }; - Ok(Json(write_off_out( - store.ledger(), - p.invoice, - entry_id, - )?)) + Ok(Json(write_off_out(store.ledger(), p.invoice, entry_id)?)) } } diff --git a/crates/ledger-store/src/lib.rs b/crates/ledger-store/src/lib.rs index 625890c..95fb2c9 100644 --- a/crates/ledger-store/src/lib.rs +++ b/crates/ledger-store/src/lib.rs @@ -49,6 +49,6 @@ pub use snapshot::{DiskCheck, Snapshot}; pub use store::{ Attachment, BillPreview, DepreciationRun, DisposalPreview, EntryRow, EventRow, InvoicePreview, JOURNAL_FILE, LEGACY_DB_FILE, LOCK_FILE, MAX_RECURRING_RUN, PayrollLineInput, Reconciliation, - Statement, Store, Subject, VerifyReport, WriteOffEvidence, database_in_use, db_file, db_file_for, - is_database_file, + Statement, Store, Subject, VerifyReport, WriteOffEvidence, database_in_use, db_file, + db_file_for, is_database_file, }; diff --git a/crates/ledger-store/src/store.rs b/crates/ledger-store/src/store.rs index 87154b6..1c9d50a 100644 --- a/crates/ledger-store/src/store.rs +++ b/crates/ledger-store/src/store.rs @@ -3747,13 +3747,8 @@ impl Store { let description = format!("Write off invoice {invoice}: {}", reason.trim()); let (entry_id, mut journaled) = self.journal_auto_entry(date, &description, bad, ar, amount)?; - let written_off = crate::meta::invoice_written_off( - invoice, - entry_id, - date, - amount, - reason.trim(), - ); + let written_off = + crate::meta::invoice_written_off(invoice, entry_id, date, amount, reason.trim()); journaled.push(self.append_journal("invoice.written_off", written_off)?); let live = self.ledger.write_off(invoice, date, amount, reason)?; debug_assert_eq!(live, entry_id, "id allocator diverged from journal"); diff --git a/crates/ledger-store/tests/arap_standing.rs b/crates/ledger-store/tests/arap_standing.rs index 8bff100..62b6eaf 100644 --- a/crates/ledger-store/tests/arap_standing.rs +++ b/crates/ledger-store/tests/arap_standing.rs @@ -1100,10 +1100,7 @@ fn write_off_waits_for_documents_v2() { .unwrap(); s.verify().unwrap(); let live = s.ledger().clone(); - let st = live - .invoice_state(1, d(2026, 12, 31)) - .unwrap() - .unwrap(); + let st = live.invoice_state(1, d(2026, 12, 31)).unwrap().unwrap(); assert_eq!(st.status, ledger_core::DocStatus::WrittenOff); assert_eq!(st.written_off, cents(10_000)); // The evidence is on the write-off's entry and on its invoice. @@ -1135,7 +1132,12 @@ fn write_off_replays_and_projects() { .unwrap(); let c = s.add_customer("Fernhill Labs").unwrap(); let inv = s - .create_invoice(c, d(2026, 4, 1), d(2026, 5, 1), vec![line("Design", 10_000)]) + .create_invoice( + c, + d(2026, 4, 1), + d(2026, 5, 1), + vec![line("Design", 10_000)], + ) .unwrap(); // Half paid, the rest written off: the invoice reads Written off with // 50 paid and 50 written off (B-38 SCENARIO 7). @@ -1175,10 +1177,16 @@ fn write_off_replays_and_projects() { assert!(got.iter().any(|(t, v)| t == "receipt.attached" && v["attachment_id"] == json!(attachment) && v["entry_id"] == json!(entry))); - assert!(got.iter().any(|(t, v)| t == "attachment.linked" - && v["attachment_id"] == json!(attachment))); + assert!( + got.iter() + .any(|(t, v)| t == "attachment.linked" && v["attachment_id"] == json!(attachment)) + ); // The figures, live. - let st = s.ledger().invoice_state(inv, d(2026, 5, 1)).unwrap().unwrap(); + let st = s + .ledger() + .invoice_state(inv, d(2026, 5, 1)) + .unwrap() + .unwrap(); assert_eq!(st.status, ledger_core::DocStatus::WrittenOff); assert_eq!( (st.paid, st.written_off, st.outstanding), @@ -1206,7 +1214,11 @@ fn write_off_replays_and_projects() { "{:?}", live.differs_from(s.ledger()) ); - let replayed = s.ledger().invoice_state(inv, d(2026, 5, 1)).unwrap().unwrap(); + let replayed = s + .ledger() + .invoice_state(inv, d(2026, 5, 1)) + .unwrap() + .unwrap(); assert_eq!(replayed, st); s.verify().unwrap(); } @@ -1220,7 +1232,12 @@ fn write_off_without_evidence_is_refused() { let mut s = Store::create(&dir.0, Currency::USD).unwrap(); let c = s.add_customer("Fernhill Labs").unwrap(); let inv = s - .create_invoice(c, d(2026, 4, 1), d(2026, 5, 1), vec![line("Design", 10_000)]) + .create_invoice( + c, + d(2026, 4, 1), + d(2026, 5, 1), + vec![line("Design", 10_000)], + ) .unwrap(); let head = s.head(); let len = journal_len(&dir.0);