diff --git a/crates/ledger-core/src/journal.rs b/crates/ledger-core/src/journal.rs index f885ed4..19ec9e0 100644 --- a/crates/ledger-core/src/journal.rs +++ b/crates/ledger-core/src/journal.rs @@ -4,7 +4,7 @@ //! total credits. Entries are born as drafts, validated, then posted. Posting //! is one-way; a posted entry can only be corrected by a reversing entry. -use crate::{AccountId, ChartOfAccounts, Currency, LedgerError, Money, Side}; +use crate::{AccountId, ChartOfAccounts, ClassId, Currency, LedgerError, Money, Side}; use chrono::NaiveDate; use rust_decimal::Decimal; use serde::{Deserialize, Serialize}; @@ -41,6 +41,12 @@ pub struct JournalLine { /// base-currency lines. #[serde(default, skip_serializing_if = "Option::is_none")] pub foreign_amount: Option, + /// Divisional tracking: which class (department, location, job) this + /// line belongs to. `None` means unclassified. Set on drafts only via + /// [`crate::Ledger::set_line_class`]; posted lines are immutable, so + /// their classes are frozen. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub class_id: Option, } /// A balanced set of journal lines with a date and a description. @@ -103,6 +109,12 @@ impl JournalEntry { self.lines.push(line); } + /// Tag a line with a class (or clear it). Only while drafted; only via + /// [`crate::Ledger::set_line_class`]. + pub(crate) fn set_line_class(&mut self, index: usize, class_id: Option) { + self.lines[index].class_id = class_id; + } + /// Mark posted. Only via [`crate::Ledger`], after [`Self::validate`]. pub(crate) fn mark_posted(&mut self) { self.status = EntryStatus::Posted;