The close zeroed every revenue and expense account's all-time movement, so closing a period after later entries were posted swept those too: close January in March and February's and March's income landed in January's closing entry. The preview had the same bug and never showed where the net went. Now: - close_period_to(id, to) zeroes balances as of the period end; entries dated later stay open for their own period. Periods must close in order (LedgerError::CloseOutOfOrder): a later close has already swept the earlier period. - CloseTo::Members: for a partnership (multi-member LLC) the net goes to each member's capital account by share, to the cent, the last member absorbing rounding, which is what K-1 capital accounts track. CloseTo::RetainedEarnings (3999) stays the default; close_period is shorthand for it. books.close_period picks Members when wanderbooks.toml lists members. - The journal records the close target; replay re-derives the closing entry and now compares every line with the journal, not just the id, so a change to closing math can never silently rewrite history. - The tool's preview is the real close run on a clone of the ledger (Ledger now derives Clone), so preview and post can't disagree. - Members' equity: closing entries into a capital account are income, not contributions. Balance sheet for a partnership: capital accounts (with allocated earnings), then only unallocated earnings — "Undistributed earnings, prior years" if any, and this year's unclosed net income (loss). periods::allocate is shared by the close and the statement. Tests: January closed after February is posted sweeps exactly Dr 4000 2,500 / Cr 6100 800 / Cr 3999 1,700 (mutation-checked: the old code gives 3,500/120/800/2,580); out-of-order close refused; a partnership close splits 666.67 into 333.34/333.33 with no 3999, and the members' equity statement reads correctly before and after; store replay of a members close (reopen, rebuild, verify); partnership and corporate balance sheet layouts; stdio close preview equals the posted lines. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MtYEaR6M6Ybdhm6X98BWNu
54 lines
2.3 KiB
Rust
54 lines
2.3 KiB
Rust
//! `ledger-core`: canonical double-entry bookkeeping semantics.
|
|
//!
|
|
//! This crate is the engine. Everything else in the workspace — persistence,
|
|
//! import, the oracle harness, the UI — builds on top of it and never
|
|
//! reimplements accounting logic.
|
|
//!
|
|
//! Design rules (see `AGENTS.md` at the repo root):
|
|
//!
|
|
//! * Money is [`Money`]: an exact [`rust_decimal::Decimal`] plus an ISO 4217
|
|
//! currency code. Binary floats never touch money paths.
|
|
//! * A [`Ledger`] is single-currency for now (see `docs/requirements.md` R-5).
|
|
//! * All mutations go through [`Ledger`] commands (`create_entry`, `add_line`,
|
|
//! `post_entry`, `reverse_entry`). Posted entries are immutable; corrections
|
|
//! are reversing entries.
|
|
//! * Reports ([`trial_balance`], [`balance_sheet`], [`profit_and_loss`]) are
|
|
//! pure functions of a ledger, which is what makes the semantic oracle
|
|
//! (`docs/oracle.md`) possible.
|
|
|
|
pub mod account;
|
|
pub mod arap;
|
|
pub mod assets;
|
|
pub mod classes;
|
|
pub mod error;
|
|
pub mod journal;
|
|
pub mod ledger;
|
|
pub mod money;
|
|
pub mod payroll;
|
|
pub mod periods;
|
|
pub mod reports;
|
|
|
|
pub use account::{Account, AccountId, AccountType, ChartOfAccounts, Side};
|
|
pub use arap::{
|
|
AgingRow, Bill, BillId, Customer, CustomerId, DocumentLine, DocumentStatus, Invoice, InvoiceId,
|
|
Vendor, VendorId,
|
|
};
|
|
pub use assets::{
|
|
Asset, AssetId, AssetStatus, DepreciationMethod, DisposalAmounts, NewAsset, ScheduleLine,
|
|
accumulated_depreciation, book_value, depreciation_schedule, disposal_amounts,
|
|
};
|
|
pub use classes::{Class, ClassId};
|
|
pub use error::LedgerError;
|
|
pub use journal::{EntryId, EntryStatus, JournalEntry, JournalLine};
|
|
pub use ledger::{Ledger, ReconciliationReport, UnclearedLine};
|
|
pub use money::{Currency, Money};
|
|
pub use payroll::{PayrollLine, PayrollRun, PayrollRunId};
|
|
pub use periods::{CloseTo, Period, PeriodId, PeriodStatus, RETAINED_EARNINGS_CODE};
|
|
pub use reports::{
|
|
BalanceSheet, BalanceSheetStatement, CashFlowLine, CashFlowParams, CashFlowStatement,
|
|
ClassProfitAndLoss, GeneralLedger, LedgerAccount, LedgerPosting, MemberCapital,
|
|
MemberEquityColumn, MembersEquityStatement, ProfitAndLoss, ProfitAndLossStatement,
|
|
StatementLine, TrialBalance, TrialBalanceLine, balance_sheet_as_of, cash_flow, general_ledger,
|
|
members_equity, profit_and_loss_for_period, trial_balance_as_of,
|
|
};
|