pub struct PriceDatabase { /* private fields */ }Expand description
Database of currency prices.
Stores prices as a map from base currency to a list of (date, price, quote currency). Prices are kept sorted by date for efficient lookup.
Implementations§
Source§impl PriceDatabase
impl PriceDatabase
Sourcepub fn from_directives(directives: &[Directive]) -> Self
pub fn from_directives(directives: &[Directive]) -> Self
Build a price database from directives.
Two passes:
- Explicit
Pricedirectives — added unconditionally. - Implicit prices from transaction postings — added only
for
(base, quote, date)tuples that don’t already have an explicit Price entry from pass 1.
The two-pass design fixes issue #1006: when the user enables
the implicit_prices plugin, it emits Price directives for
each priced posting; pass 1 picks those up. Pre-fix, pass 2
would then ALSO walk the same transactions and re-emit the
same implicit prices, doubling every entry. Now pass 2 sees
the explicit entry already exists and skips, so the plugin’s
output is the single source of truth.
When the plugin is NOT enabled (the rustledger-extension case
from #567 / #593 — VALUE() should work on implicit-priced
transactions automatically), pass 1 adds nothing for those
dates and pass 2 fills them in. Net effect: implicit prices
are reachable from BQL without requiring the user to wire up
a plugin, but never doubled when the plugin IS wired up.
Behavior note: an explicit Price directive suppresses
any divergent transaction-derived implicit price on the same
(base, quote, date). This is intentional — explicit Price is
authoritative — but a behavior change vs pre-#1015, where a
user-written 2024-01-15 price ABC 1.40 EUR plus a transaction
emitting ABC@EUR with a different value on the same date would
have stored both. Now only the explicit value survives. In
practice this only surfaces with hand-authored conflicts.
Provenance tagging (issue #1048): each entry stores
explicit: bool. Pass-1 entries are true, pass-2
transaction-derived entries are false. The #prices BQL
table filters to explicit: true via iter_explicit_entries
to match bean-query, which only surfaces real Price
directives. Internal get_price / convert lookups see
both kinds — that’s how VALUE() keeps working without the
implicit_prices plugin being declared.
Sourcepub fn sort_prices(&mut self)
pub fn sort_prices(&mut self)
Sort all price entries by date.
Call this after adding prices to ensure lookups work correctly.
Sourcepub fn add_price(&mut self, price: &PriceDirective)
pub fn add_price(&mut self, price: &PriceDirective)
Add a price directive to the database.
Marks the entry as explicit: true — these entries surface in
the #prices BQL table.
Sourcepub fn get_price(
&self,
base: &str,
quote: &str,
date: NaiveDate,
) -> Option<Decimal>
pub fn get_price( &self, base: &str, quote: &str, date: NaiveDate, ) -> Option<Decimal>
Get the price of a currency on or before a given date.
Returns the most recent price for the base currency in terms of the quote currency. Tries direct lookup, inverse lookup, and chained lookup (A→B→C).
Sourcepub fn get_latest_price(&self, base: &str, quote: &str) -> Option<Decimal>
pub fn get_latest_price(&self, base: &str, quote: &str) -> Option<Decimal>
Get the latest price of a currency (most recent date).
Supports direct lookup, inverse lookup, and chained lookup (A→B→C).
Sourcepub fn convert(
&self,
amount: &Amount,
to_currency: &str,
date: NaiveDate,
) -> Option<Amount>
pub fn convert( &self, amount: &Amount, to_currency: &str, date: NaiveDate, ) -> Option<Amount>
Convert an amount to a target currency.
Returns the converted amount, or None if no price is available.
Sourcepub fn convert_latest(
&self,
amount: &Amount,
to_currency: &str,
) -> Option<Amount>
pub fn convert_latest( &self, amount: &Amount, to_currency: &str, ) -> Option<Amount>
Convert an amount using the latest available price.
Sourcepub fn currencies(&self) -> impl Iterator<Item = &str>
pub fn currencies(&self) -> impl Iterator<Item = &str>
Get all currencies that have prices defined.
Sourcepub fn has_prices(&self, currency: &str) -> bool
pub fn has_prices(&self, currency: &str) -> bool
Check if a currency has any prices defined.
Sourcepub fn iter_explicit_entries(
&self,
) -> impl Iterator<Item = (&str, NaiveDate, Decimal, &str)>
pub fn iter_explicit_entries( &self, ) -> impl Iterator<Item = (&str, NaiveDate, Decimal, &str)>
Iterate over explicit price entries only — those sourced from
Price directives (either user-written or plugin-emitted).
Excludes transaction-derived entries added by the executor’s
pass-2 fallback. Used by the #prices BQL table to match
bean-query’s behavior.
For internal price lookups (e.g. VALUE(), getprice()),
use get_price / convert / convert_latest — those walk
the underlying entries without filtering, which preserves the
rustledger UX extension where implicit prices are usable for
conversion without declaring the implicit_prices plugin.
Trait Implementations§
Source§impl Debug for PriceDatabase
impl Debug for PriceDatabase
Source§impl Default for PriceDatabase
impl Default for PriceDatabase
Source§fn default() -> PriceDatabase
fn default() -> PriceDatabase
Auto Trait Implementations§
impl Freeze for PriceDatabase
impl RefUnwindSafe for PriceDatabase
impl Send for PriceDatabase
impl Sync for PriceDatabase
impl Unpin for PriceDatabase
impl UnsafeUnpin for PriceDatabase
impl UnwindSafe for PriceDatabase
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> LayoutRaw for T
impl<T> LayoutRaw for T
Source§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
Source§impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
Source§unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
Source§fn resolve_niched(out: Place<NichedOption<T, N1>>)
fn resolve_niched(out: Place<NichedOption<T, N1>>)
out indicating that a T is niched.