calternal_money::ledger
Projection: three kinds of Money file -> one validated Ledger.
Port of project_budget and its helpers in the #404 oracle. The files are
Budget.md (groups, categories, assignments, subscriptions),
Accounts.md (accounts, card rules) and one YYYY-MM.md per month
(transactions). The projection resolves every link by stable block ID and
checks every posting rule before any arithmetic runs, so a malformed row
is an error and never a silent gap in the totals (DESIGN §48).
Every amount is parsed to exact minor units here (scale checked). The written text is kept too, so writers can round-trip it.
Deliberate differences from the oracle (#462, listed for the break-the-numbers review):
- An
Accounts.mdwithout accounts is valid: a new budget has none yet. - A category kind must be one of the known kinds. The oracle accepted a
typo such as
kind:: expnseand then posted it like an expense. - Assignment currencies are checked even when there is no month file.
adjustmentis an import-only Category kind. A zero-value row with oneready to assign adjustment:: amount CURchild changes only Ready to Assign, so source-model reconciliation cannot alter Account or Category totals (#462, DESIGN §48).
#1130: optional closed, notes, cleared and reconciled properties preserve source state. Inert source rows are evidence only; arithmetic uses Details.
Source: crates/calternal-money/src/ledger.rs
Structs
Section titled “Structs”Account
Section titled “Account”pub struct AccountOne account from Accounts.md.
Fields
pub closed: bool: Closed Accounts retain every posting and balance (#1130).pub id: String: Stable block ID.pub name: String: Heading label.pub kind: AccountKind: Kind.pub currency: String: Account currency (its own, which may differ from the budget’s).pub payment_category: Option<String>: Linked card payment category ID (cards only).pub line: usize: Index of the heading line in theAccounts.mddocument.
Implements: Clone, Debug, Serialize
Source: crates/calternal-money/src/ledger.rs:165
Assignment
Section titled “Assignment”pub struct AssignmentOne - assigned, YYYY-MM, amount CUR ^id row under a category.
Fields
pub category_id: String: Category block ID.pub month: String: MonthYYYY-MM.pub amount: Minor: Exact amount in budget minor units.pub line: usize: Line index inBudget.md.
Implements: Clone, Debug, Serialize
Source: crates/calternal-money/src/ledger.rs:205
Category
Section titled “Category”pub struct CategoryOne category from Budget.md.
Fields
pub id: String: Stable block ID.pub name: String: Heading label.pub group: String: Group heading label (the##above it).pub kind: CategoryKind: Kind.pub visibility: String:visibleor another visibility value, as written (defaultvisible).pub target: Option<Minor>: Monthly target in budget minor units (always > 0 when present).pub line: usize: Index of the heading line in theBudget.mddocument.
Implements: Clone, Debug, Serialize
Source: crates/calternal-money/src/ledger.rs:185
Ledger
Section titled “Ledger”pub struct LedgerA fully validated budget, ready for exact arithmetic.
Fields
pub budget_id: String:budget-idfrom the frontmatter.pub currency: String: Budget currency.pub accounts: Vec<Account>: Accounts in file order.pub categories: Vec<Category>: Categories in file order (subscriptions excluded).pub assignments: Vec<Assignment>: Assignments in file order.pub months: Vec<MonthFile>: Month files, in input order (unique months).pub subscriptions: Vec<String>: Subscription block IDs.
Implements: Clone, Debug, Serialize
Ledger::account
Section titled “Ledger::account”pub fn account(&self, id: &str) -> Option<&Account>Find an account by ID.
Ledger::category
Section titled “Ledger::category”pub fn category(&self, id: &str) -> Option<&Category>Find a category by ID.
Source: crates/calternal-money/src/ledger.rs:417
pub struct Links<'a>The IDs a month file’s transactions may link to.
Fields
pub accounts: HashSet<&'a str>: Account IDs.pub categories: HashSet<&'a str>: Category IDs.pub subscriptions: HashSet<&'a str>: Subscription IDs.
Source: crates/calternal-money/src/ledger.rs:785
MonthFile
Section titled “MonthFile”pub struct MonthFileOne month file’s transactions.
Fields
pub month: String: MonthYYYY-MMfrom the frontmatter.pub transactions: Vec<Transaction>: Transactions in file order.
Implements: Clone, Debug, Serialize
Source: crates/calternal-money/src/ledger.rs:408
Transaction
Section titled “Transaction”pub struct TransactionOne posted transaction row with its resolved IDs and exact amounts.
Fields
pub notes: String: Separate source notes; JSON properties preserve line breaks (#1130).pub cleared: Option<bool>: Explicit cleared mark; old files fall back to #cleared (#1130).pub reconciled: bool: Source reconciliation mark, independent of cleared (#1130).pub source_rows: Vec<crate::import::SourceRow>: Original split/transfer rows; evidence never posts again (#1130).pub id: String: Stable block ID.pub date: String: Calendar dateYYYY-MM-DD.pub amount: Minor: Exact source amount incurrencyminor units.pub amount_text: String: Source amount text as written.pub currency: String: Source currency as written.pub account_id: String: Account ID.pub account_label: String: Account link label as written.pub category_id: String: Category ID (a Split or Transfer marker for those rows).pub category_label: String: Category link label as written.pub payee: String: Payee and memo.pub details: Vec<Detail>: Child rows in file order.pub line: usize: Line index in the month document.
Implements: Clone, Debug, Serialize
Transaction::fx_total
Section titled “Transaction::fx_total”pub fn fx_total(&self) -> Option<(Minor, &str)>The one fx total child, if present.
Transaction::transfer
Section titled “Transaction::transfer”pub fn transfer(&self) -> Option<(&str, Minor, &str)>The one transfer child, if present.
Transaction::transfer_category
Section titled “Transaction::transfer_category”pub fn transfer_category(&self) -> Option<&str>Category linked to the on-budget side of an off-budget transfer.
Transaction::ready_to_assign_adjustment
Section titled “Transaction::ready_to_assign_adjustment”pub fn ready_to_assign_adjustment(&self) -> Option<(Minor, &str)>The import-only source-model adjustment, if this row carries one.
Transaction::splits
Section titled “Transaction::splits”pub fn splits(&self) -> impl Iterator<Item = (&str, Minor)>Split children as (category ID, amount).
Transaction::is_simple
Section titled “Transaction::is_simple”pub fn is_simple(&self) -> boolTrue for a row with no split, transfer or FX children: the only kind the first Money screens can edit (#462).
Transaction::is_cleared
Section titled “Transaction::is_cleared”pub fn is_cleared(&self) -> boolUse the explicit imported mark, or the legacy #cleared tag when no
property exists. Reconciliation is independent of clearing (#1130).
Source: crates/calternal-money/src/ledger.rs:276
AccountKind
Section titled “AccountKind”pub enum AccountKindThe only account kinds accepted by Money and import adapters (DESIGN §48). A card carries debt and a payment Category; tracking balances stay outside the spendable pool. Source loan accounts map to tracking.
Variants
Cash: On-budget cash, checking, or savings account.Card: On-budget card account with an optional payment Category.Tracking: Off-budget balance, including loans and investments.
Implements: Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize
AccountKind::as_str
Section titled “AccountKind::as_str”pub const fn as_str(self) -> &'static strThe short kind name used in files and by the oracle.
AccountKind::is_on_budget
Section titled “AccountKind::is_on_budget”pub const fn is_on_budget(self) -> boolWhether this account contributes to the spendable Money pool.
AccountKind::is_cash
Section titled “AccountKind::is_cash”pub const fn is_cash(self) -> boolWhether this kind follows the debit-account posting rules.
AccountKind::is_card
Section titled “AccountKind::is_card”pub const fn is_card(self) -> boolWhether this kind follows the Credit-account and payment-Category rules.
AccountKind::is_tracking
Section titled “AccountKind::is_tracking”pub const fn is_tracking(self) -> boolWhether this account is off-budget and only updates its own balance.
Source: crates/calternal-money/src/ledger.rs:61
CategoryKind
Section titled “CategoryKind”pub enum CategoryKindCategory kinds (short names in files, DESIGN §48 F4).
Variants
Expense: Spending envelope; can receive assignments.Payment: Card payment envelope linked from one card; can receive assignments.Income: Income: inflows go to Ready to Assign.Balance: Opening balances: cash inflows go to Ready to Assign.Split: Marker for a split row; the children name the real categories.Transfer: Marker for a general transfer row.Adjustment: A zero-value import row that adjusts only Ready to Assign.
Implements: Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize
CategoryKind::as_str
Section titled “CategoryKind::as_str”pub const fn as_str(self) -> &'static strThe short kind name used in files and by the oracle.
CategoryKind::assignable
Section titled “CategoryKind::assignable”pub const fn assignable(self) -> boolTrue for the kinds that can receive assigned money.
Source: crates/calternal-money/src/ledger.rs:113
Detail
Section titled “Detail”pub enum DetailA child row under a transaction (#404: splits, transfers, FX evidence; #462: source Ready to Assign reconciliation).
Variants
Transfer { account_id: String, amount: Minor, currency: String, }:transfer:: [Account](Accounts.md#^id), amount CUR.TransferCategory { category_id: String, }:transfer category:: [Category](Budget.md#^id)on a cross-budget transfer. The Category posts the on-budget leg once.Split { category_id: String, amount: Minor, currency: String, }:split:: amount CUR, [Category](Budget.md#^id).FxTotal { amount: Minor, currency: String, }:fx total:: amount CURin the budget currency.Fx { amount: Minor, currency: String, }:fx:: amount CUR: the confirmed source amount.ReadyToAssignAdjustment { amount: Minor, currency: String, }:ready to assign adjustment:: amount CURon an import-only row.Subscription { id: String, }:subscription:: [Name](Budget.md#^id).
Implements: Clone, Debug, Serialize
Source: crates/calternal-money/src/ledger.rs:221
Functions
Section titled “Functions”accounts
Section titled “accounts”pub fn accounts(document: &Document, category_ids: &HashSet<&str>) -> Result<Vec<Account>>Read accounts: ## headings with an ID in Accounts.md.
Source: crates/calternal-money/src/ledger.rs:658
assignments
Section titled “assignments”pub fn assignments(document: &Document, currency: &str) -> Result<Vec<Assignment>>Read assignment rows under category headings. A row that starts with the
reserved assigned marker must be valid, so money never disappears.
Source: crates/calternal-money/src/ledger.rs:737
budget_metadata
Section titled “budget_metadata”pub fn budget_metadata(budget: &Document, accounts: &Document) -> Result<(String, String)>Read and cross-check the file identity of Budget.md and Accounts.md:
returns (budget ID, budget currency).
Source: crates/calternal-money/src/ledger.rs:489
categories
Section titled “categories”pub fn categories(document: &Document, currency: &str) -> Result<Vec<Category>>Read categories: ### headings with an ID under a ## group that is not
Subscriptions.
Source: crates/calternal-money/src/ledger.rs:548
file_month
Section titled “file_month”pub fn file_month(document: &Document) -> Result<(String, String)>Read the month of a month file from its frontmatter.
Source: crates/calternal-money/src/ledger.rs:514
has_tag
Section titled “has_tag”pub fn has_tag(text: &str, tag: &str) -> boolTrue when text contains #tag as a whole tag token.
Source: crates/calternal-money/src/ledger.rs:387
project
Section titled “project”pub fn project<D: std::borrow::Borrow<Document>>( budget: &Document, accounts_document: &Document, months: &[D],) -> Result<Ledger>Project Budget.md, Accounts.md and month files into a checked ledger.
Errors on any broken identity, link, amount or posting rule. The month files may come in any order but each month may appear only once.
Source: crates/calternal-money/src/ledger.rs:1131
project_with_check
Section titled “project_with_check”pub fn project_with_check<D: std::borrow::Borrow<Document>>( budget: &Document, accounts_document: &Document, months: &[D], mut check: impl FnMut() -> Result<()>,) -> Result<Ledger>Project Money files with bounded checkpoints for large import previews (#462, DESIGN §48). The checked and ordinary paths use the same rules.
Source: crates/calternal-money/src/ledger.rs:1141
subscriptions
Section titled “subscriptions”pub fn subscriptions(document: &Document) -> Result<Vec<(usize, String)>>Read subscription heading IDs (### under ## Subscriptions).
Source: crates/calternal-money/src/ledger.rs:629
trailing_id
Section titled “trailing_id”pub fn trailing_id(text: &str) -> Option<&str>Helper for callers that hold a transaction row’s source text: the block ID at the end of a line, if any.
Source: crates/calternal-money/src/ledger.rs:1265
transactions
Section titled “transactions”pub fn transactions( document: &Document, month: &str, links: &Links<'_>,) -> Result<Vec<Transaction>>Read and check one month file’s transaction rows (oracle _transactions).
Source: crates/calternal-money/src/ledger.rs:799
valid_date
Section titled “valid_date”pub fn valid_date(text: &str) -> boolValidate an ISO date string (ASCII YYYY-MM-DD, a real calendar day).
Source: crates/calternal-money/src/ledger.rs:1270
validate_month
Section titled “validate_month”pub fn validate_month(value: &str) -> Result<()>Validate a YYYY-MM month with ASCII digits and a real month number.
Source: crates/calternal-money/src/ledger.rs:447
Constants
Section titled “Constants”CARD_PROPERTIES
Section titled “CARD_PROPERTIES”pub const CARD_PROPERTIES: [&str; 11]Properties that only a card cycle or card payment plan reads (DESIGN §48).
Source: crates/calternal-money/src/ledger.rs:532
FORMAT
Section titled “FORMAT”pub const FORMAT: &strThe only Money format version this build reads.