mod mem;
use core::fmt;
use time::Date;
use super::holds::HoldView;
use super::writeset::SealReceipt;
use crate::model::{
AccountHandle, AccountKind, AccountPath, AccountRegistration, Amount, Balance, BalanceLimit,
ClearingEvent, Currency, Dimensions, EntryId, EntryRecord, Fingerprint, IdempotencyKey, Label,
Layer, LedgerId, LedgerPolicy, PeriodId, PostingRef, Side,
};
pub(crate) use mem::{Line, MemState};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BalanceKey {
pub handle: AccountHandle,
pub currency: Currency,
pub layer: Layer,
}
impl fmt::Display for BalanceKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} {} {}", self.handle, self.currency, self.layer)
}
}
pub trait StateView<const P: u8> {
fn header(&self) -> Header<P>;
fn entry_by_key(&self, key: &IdempotencyKey) -> Option<EntryMeta>;
fn account_by_path(&self, path: &AccountPath) -> Option<AccountView>;
fn account(&self, handle: AccountHandle) -> Option<AccountView>;
fn account_terms(&self, handle: AccountHandle, on: Date) -> Option<Terms>;
fn currency(&self, code: Currency, on: Date) -> Option<u8>;
fn currency_latest(&self, code: Currency) -> Option<Versioned<u8>>;
fn policy(&self, on: Date) -> LedgerPolicy;
fn policy_latest(&self) -> Option<Versioned<LedgerPolicy>>;
fn period_at(&self, date: Date) -> Option<PeriodView<P>>;
fn period(&self, id: &PeriodId) -> Option<PeriodView<P>>;
fn first_unsealed(&self) -> Option<PeriodView<P>>;
fn entry(&self, id: EntryId) -> Option<EntryView<P>>;
fn reversed_by(&self, id: EntryId) -> Option<EntryId>;
fn hold(&self, id: EntryId) -> Option<HoldView<P>>;
fn outstanding_hold_debits(&self, handle: AccountHandle, currency: Currency) -> Amount<P>;
fn outstanding_hold_credits(&self, handle: AccountHandle, currency: Currency) -> Amount<P>;
fn balance(&self, key: BalanceKey) -> Balance<P>;
fn clearing_by_key(&self, key: &IdempotencyKey) -> Option<ClearingView<P>>;
fn clearing_at(&self, position: u64) -> Option<ClearingView<P>>;
fn applied(&self, posting: PostingRef) -> Amount<P>;
fn all_balances(&self) -> Vec<(BalanceKey, Balance<P>)>;
fn postings_after(&self, date: Date) -> Vec<Movement<P>>;
fn pnl_slices(&self, through: Date) -> Vec<Slice<P>>;
fn complete(&self) -> bool {
true
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Header<const P: u8> {
pub ledger: LedgerId,
pub size: u64,
pub accounts: u32,
pub entries: u64,
pub watermark: Option<Date>,
pub last_booking: Option<Date>,
pub last_period: Option<PeriodView<P>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct EntryMeta {
pub id: EntryId,
pub position: u64,
pub fingerprint: Option<Fingerprint>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Window {
pub open_from: Date,
pub open_to: Option<Date>,
}
impl Window {
#[must_use]
pub fn contains(&self, date: Date) -> bool {
self.open_from <= date && self.open_to.is_none_or(|open_to| date <= open_to)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AccountView {
pub registration: AccountRegistration,
pub latest: LatestTerms,
pub is_leaf: bool,
pub last_booked: Option<Date>,
}
impl AccountView {
#[must_use]
pub const fn handle(&self) -> AccountHandle {
self.registration.handle
}
#[must_use]
pub const fn path(&self) -> &AccountPath {
&self.registration.path
}
#[must_use]
pub const fn kind(&self) -> AccountKind {
self.registration.kind
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Terms {
pub class: Option<Label>,
pub window: Window,
pub limit: BalanceLimit,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LatestTerms {
pub window: Versioned<Window>,
pub limit: Versioned<BalanceLimit>,
pub class: Versioned<Option<Label>>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Versioned<T> {
pub value: T,
pub effective: Date,
pub position: u64,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PeriodView<const P: u8> {
pub id: PeriodId,
pub start: Date,
pub end: Date,
pub position: u64,
pub sealed: Option<SealReceipt<P>>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EntryView<const P: u8> {
pub position: u64,
pub record: EntryRecord<P>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ClearingView<const P: u8> {
pub position: u64,
pub event: ClearingEvent<P>,
pub reset_by: Option<u64>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Movement<const P: u8> {
pub key: BalanceKey,
pub side: Side,
pub amount: Amount<P>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Slice<const P: u8> {
pub handle: AccountHandle,
pub currency: Currency,
pub dimensions: Dimensions,
pub balance: Balance<P>,
}