store journals payroll.taxes_remitted; viewer tests for the numbers mutation found unchecked
check / check (push) Canceled after 0s

A payroll tax remittance was journaled as a plain entry, so the viewer
labeled it "Journal entry" and, at a 0.00 threshold, flagged it as
missing a receipt (the server posts it without one, like a payroll
run). The store now names it with payroll.taxes_remitted, as it names
runs with payroll.run; replay and the projection pass over it, and the
viewer's journal page describes it.

tests/view_model.rs: the cash history is never empty when cash moved
and ends on the last day it did; the prior month runs to the same day;
burn averages over only the months the books cover, half away from
zero; cash accounts found by name when the settings name none; card
accounts; each entry's accounts debits first, once each; only what
arrived since the last refresh is fresh; integrity counts files again
without rereading them; the invoice's customer, the bill payment's
vendor, payroll and remittance origins.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GWVo7x3UHw5kwCUaWxiejX
This commit is contained in:
swaitsandClaude Opus 5.5 committed 2026-10-14 18:03:10 -06:00
1 parent f0fc725ca2
commit c1f92ed3e8
5 files changed
+341 -1

No files matched your search

+18
View File
@@ -1755,6 +1755,17 @@ impl Store {
"lines": plan.iter().map(|(a, s, m)| plain_line_json(*a, *s, *m)).collect::<Vec<_>>(),
}),
)?);
// Name the entry as a remittance, as payroll.run names a run's
// (readers like the viewer tell it from a hand-made entry by this).
let total: Decimal = plan
.iter()
.filter(|(_, s, _)| *s == Side::Debit)
.map(|(_, _, m)| m.amount)
.sum();
journaled.push(self.append_journal(
"payroll.taxes_remitted",
json!({"entry_id": entry_id, "date": date.to_string(), "total": total.to_string()}),
)?);
let live = self.ledger.remit_payroll_taxes(date, cash_account)?;
debug_assert_eq!(live, entry_id, "id allocator diverged from journal");
for line in &journaled {
@@ -3294,6 +3305,10 @@ pub(crate) fn replay_line_into_ledger(
| "attachment.withdrawn" => {
// Not accounting state; the projection records them.
}
"payroll.taxes_remitted" => {
// Names the remittance entry (rebuilt by the entry events just
// before it) for readers; no ledger state of its own.
}
"asset.registered" => {
let want = get_u64(p, "id")?;
let got = ledger.register_asset(NewAsset {
@@ -3758,6 +3773,9 @@ fn apply_line_rows(conn: &Connection, line: &JournalLine) -> Result<(), StoreErr
)?;
}
}
"payroll.taxes_remitted" => {
// The entry was projected by its own events; this only names it.
}
"receipt.attached" | "document.filed" => {
conn.execute(
"INSERT OR IGNORE INTO blobs(sha256, size_bytes, mime_type, original_name, created_at) VALUES (?,?,?,?,?)",