feat: 1099 tracking — vendor forms, payment tags, year-end worksheet

Vendors carry form_1099 (NEC/MISC) and tin_on_file (never the TIN).
Entries carry the vendor they paid; bills, bill payments, and reversals
are tagged automatically. books.vendor_1099 counts cash paid per vendor
per calendar year (card payments excluded) against $600 through 2025 and
$2,000 from 2026, or an override, and flags missing W-9s. Four new tools
(64), two journal events, schema v7. Docs: finished R-FUTURE work is no
longer listed as future.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtYEaR6M6Ybdhm6X98BWNu
This commit is contained in:
swaitsandClaude Opus 5.5 committed 2026-10-11 21:18:32 -07:00
1 parent d65f9aa840
commit b48addd0e0
15 files changed
+967 -8

No files matched your search

+22
View File
@@ -176,6 +176,28 @@ through the policy.
naming the difference. A draft: attach the payout statement, preview,
post. Platform-agnostic; format-specific statement parsers can feed it.
## Tools — 1099 tracking
Payments are counted as cash: credits minus debits to asset accounts on
entries tagged with the vendor. Card payments move no asset (the card
processor's 1099-K covers them), so they drop out; reversals of tagged
entries carry the tag and net out. Thresholds: $600 for payments through
2025, $2,000 from 2026 (indexed for inflation after 2026); always
overridable, always for the CPA to confirm. TINs are never stored, only
whether a W-9 is on file.
- `books.list_vendors {}` → `{ vendors: [{ id, name, form_1099?,
tin_on_file }] }`.
- `books.set_vendor_1099 { vendor, form_1099: "nec" | "misc" | "none",
tin_on_file? }` → the vendor. `vendor` is an id or a name.
- `books.set_entry_vendor { entry_id, vendor? }` → the entry (as
`books.get_entry`, which now shows `vendor`). Omitting `vendor` clears
the tag. Metadata only: posted entries may be tagged. `books.draft_entry`
takes `vendor` too; bills and their payments are tagged automatically.
- `books.vendor_1099 { year, threshold? }` → `{ year, threshold, vendors:
[{ vendor_id, name, form_1099?, tin_on_file, paid, reportable }],
missing_w9, notes }`.
## Tools — receipts & documents
- `books.attach_receipt { entry_id?, file_name, mime_type, content_base64 }`
+1 -1
View File
@@ -29,7 +29,6 @@ No other statuses.
| Canonical report snapshots (JSON) | — (our oracle format) | done | `reports::snapshot` |
| Fixed-asset register + straight-line depreciation | Fixed Asset register | done | `assets.rs`; golden-covered schedule; idempotent runs; disposal with gain/loss |
| Cash flow statement (indirect) | Reports → Cash Flow | done | R-FUTURE-3 |
| Period close / retained earnings | Close books | todo | R-FUTURE-2 |
| Foreign-currency lines (base + foreign stored) | Multi-currency accts | done | R-FUTURE-1 |
| Period close (closing entry to Retained Earnings) | Close books | done | R-FUTURE-2 |
| Bank reconciliation (cleared flags + report) | Reconcile | done | — |
@@ -43,6 +42,7 @@ No other statuses.
| Budgets | Budgets | todo | R-FUTURE-6 (declined as bloat) |
| Scheduled transactions (recurring entries → drafts) | Scheduled txns / Recurring transactions | partial | hand-verified fixture incl. month-end dates; drafts only, by design |
| Payout gross-up (deposit → revenue, fees, adjustments) | Bank deposit with fee lines; Xero/QBO Stripe & Shopify integrations | partial | hand-verified fixture incl. classes and a negative payout; no statement parsers yet |
| 1099 vendor tracking + year-end worksheet | Vendors → Track payments for 1099; 1099 report | partial | hand-verified fixture (bill payments, card exclusion, reversal, year boundary); no golden file yet |
| Prepaid expense + deferred revenue amortization | Amortization schedules (Xero/QBO add-ons) | partial | hand-verified fixture, to the cent; no golden file yet |
| Automated GnuCash diff harness | — (our `xtask oracle`) | todo | roadmap phase 3 |
+10 -3
View File
@@ -23,7 +23,8 @@ requirement conflict, the requirement wins.
organize the chart and reject postings.
- **R-5 — Single currency per ledger (day one).** Every account and every
journal line uses the ledger's base currency. Anything else is rejected,
not converted. Multi-currency with translation is R-FUTURE-1.
not converted, unless the line records its foreign currency, amount, and
rate (R-FUTURE-1, done: see below).
- **R-6 — Line hygiene.** Zero-amount lines are rejected, not ignored.
Unknown accounts are rejected. Single-line entries are rejected.
@@ -104,8 +105,8 @@ requirement conflict, the requirement wins.
## Explicitly future work
- **R-FUTURE-6 — Budgets and scheduled transactions.** (Budgets explicitly
declined as bloat; scheduled transactions remain future.)
- **R-FUTURE-6 — Budgets.** Explicitly declined as bloat. (Scheduled
transactions, the other half of R-FUTURE-6, are done: see below.)
## Promoted from future (done)
@@ -143,6 +144,12 @@ requirement conflict, the requirement wins.
- **R-? — Payout gross-up.** Platform deposits are recorded gross:
revenue, fees, and adjustments, reconciled to the deposit to the cent,
as a draft that carries the payout statement as its receipt.
- **R-? — 1099 tracking.** Vendors carry the information return they get
and whether a W-9 is on file (never the TIN). Entries carry the vendor
they paid; bills, bill payments, and reversals carry it automatically.
The year's worksheet counts cash paid (asset-account credits minus
debits), so card payments are excluded, against a year-dependent,
overridable threshold. Schema v7.
- **R-? — A/R and A/P workflows.** Was R-FUTURE-5.
`ledger-core::arap`: customers, vendors, invoices, bills, payments,
AR/AP aging. MCP tools for the full workflow.