# An invoice's or bill's lines count toward the projects they name. # # wanderbooks: rules.md B-37 item 8 (journal feature # `document_line_projects`); regression tests in ledger-core # `tests/spec_document_projects.rs`, ledger-store # `tests/document_projects.rs`, ledger-cli `tests/spec_projects.rs` # (`invoice_and_bill_lines_count_toward_their_projects`). # # Expected values worked by hand. Invoice 1 bills 3,000.00 + 500.00 of # Zeta's design (3,500.00), 200.00 of Harbor's hosting and an untagged # 100.00 rush fee: 3,800.00, all Revenue (4000), the receivable untagged. # Bill 1 is 1,200.00 of Zeta's illustration and 50.00 of untagged # postage: 1,250.00 of General Expenses (6999). Bill 2, 300.00, names no # project. The customer's payment and the bill's payment move cash and # the receivable or payable only: no project figure. So Zeta nets # 3,500.00 - 1,200.00 = 2,300.00; Harbor 200.00 (both are client work, # so neither has an unrecovered cost: on spec, a hoped-for payment is no # receivable, B-37 item 4); the untagged lines 100.00 - 50.00 - 300.00 # - 1,500.00 (rent) = -1,750.00; together 750.00, the P&L's net # (3,800.00 - 1,550.00 - 1,500.00). Dana was paid 1,250.00 from the bank, # whatever the bill's projects; the second bill is still owed. id = "projects-invoice-and-bill-lines-count-by-project" title = "An invoice's or bill's lines count toward the projects they name" rule = "Each line of an invoice or bill MAY name a project; its revenue (an invoice's) or cost (a bill's) MUST then count toward that project's figures exactly as a tagged line of a hand-built entry would, the receivable, the payable and their payments MUST count toward none, and every figure that is not a project's (the P&L, a payee's 1099 payments) MUST be what it would be with no project named." status = "CONVENTION" sources = [ "Job-order costing: a job cost sheet accumulates the revenue and the direct costs identified with one job, a supplier's invoice and the job's billing among them (management-accounting convention; wanderbooks docs/spec/rules.md B-37 items 3 and 8)", "wanderbooks docs/spec/rules.md B-11 and B-14: a period's net income is its revenue less its expenses", "Treas. Reg. ยง1.6041-1(a)(1)(iv) (docs/spec/sources/irs-1099-payment-method.md): a 1099 counts payments made, not how the books classify them", ] tags = ["projects", "classes", "job-costing", "accrual", "invoices", "bills"] [setup] currency = "USD" fiscal_year_start = "01-01" basis = "accrual" rounding = "half-even" cash_accounts = ["1000"] [[setup.accounts]] code = "1000" name = "Bank" type = "asset" [[setup.accounts]] code = "1200" name = "Accounts Receivable" type = "asset" [[setup.accounts]] code = "2000" name = "Accounts Payable" type = "liability" [[setup.accounts]] code = "4000" name = "Revenue" type = "revenue" [[setup.accounts]] code = "6200" name = "Rent" type = "expense" [[setup.accounts]] code = "6999" name = "General Expenses" type = "expense" [[setup.projects]] name = "Zeta" kind = "client" [[setup.projects]] name = "Harbor" kind = "client" [[setup.payees]] name = "Dana Illustration" form = "1099-NEC" [[events]] date = "2026-03-02" description = "Invoice to Cedar" invoice = { customer = "Cedar Client", lines = [ { description = "Design", amount = "3000.00", project = "Zeta" }, { description = "Hosting", amount = "200.00", project = "Harbor" }, { description = "Rush fee", amount = "100.00" }, { description = "Revisions", amount = "500.00", project = "Zeta" }, ] } [[events]] date = "2026-03-09" description = "Dana's bill" bill = { vendor = "Dana Illustration", lines = [ { description = "Illustration", amount = "1200.00", project = "Zeta" }, { description = "Postage", amount = "50.00" }, ] } [[events]] date = "2026-03-20" description = "Cedar pays invoice 1" older = true lines = [ { account = "1000", side = "debit", amount = "3800.00" }, { account = "1200", side = "credit", amount = "3800.00" }, ] [[events]] date = "2026-03-30" description = "Pay Dana's bill" older = true payee = "Dana Illustration" lines = [ { account = "2000", side = "debit", amount = "1250.00" }, { account = "1000", side = "credit", amount = "1250.00" }, ] [[events]] date = "2026-03-31" description = "Studio rent" lines = [ { account = "6200", side = "debit", amount = "1500.00" }, { account = "1000", side = "credit", amount = "1500.00" }, ] [[events]] date = "2026-04-02" description = "Dana's second bill" bill = { vendor = "Dana Illustration", amount = "300.00" } [[expect]] query = "entry" entry = 1 [expect.values] "1200.debit" = "3800.00" "4000.credit" = "3800.00" [[expect]] query = "entry" entry = 2 [expect.values] "6999.debit" = "1250.00" "2000.credit" = "1250.00" [[expect]] query = "project" project = "Zeta" from = "2026-01-01" to = "2026-12-31" [expect.values] revenue = "3500.00" expenses = "1200.00" net = "2300.00" "to_date.revenue" = "3500.00" "to_date.expenses" = "1200.00" "to_date.net" = "2300.00" unrecovered_cost = "none" [[expect]] query = "project" project = "Harbor" from = "2026-01-01" to = "2026-12-31" [expect.values] revenue = "200.00" expenses = "0.00" net = "200.00" "to_date.revenue" = "200.00" "to_date.expenses" = "0.00" "to_date.net" = "200.00" unrecovered_cost = "none" [[expect]] query = "profit_and_loss" from = "2026-01-01" to = "2026-12-31" [expect.values] "4000" = "3800.00" "6200" = "1500.00" "6999" = "1550.00" net_income = "750.00" [[expect]] query = "vendor_1099_paid" from = "2026-01-01" to = "2026-12-31" [expect.values] "Dana Illustration" = "1250.00"