cala_server/graphql/
balance.rs

1use async_graphql::*;
2
3use super::{convert::ToGlobalId, primitives::*};
4use cala_ledger::primitives::{AccountId, Currency, JournalId};
5
6#[derive(SimpleObject)]
7pub(super) struct Money {
8    pub units: Decimal,
9    pub currency: CurrencyCode,
10}
11
12impl From<(rust_decimal::Decimal, Currency)> for Money {
13    fn from((units, currency): (rust_decimal::Decimal, Currency)) -> Self {
14        Self {
15            units: units.into(),
16            currency: currency.into(),
17        }
18    }
19}
20
21#[derive(SimpleObject)]
22pub(super) struct BalanceAmount {
23    pub dr_balance: Money,
24    pub cr_balance: Money,
25    pub normal_balance: Money,
26    pub entry_id: UUID,
27}
28
29#[derive(SimpleObject)]
30#[graphql(complex)]
31pub(super) struct Balance {
32    pub id: ID,
33    pub journal_id: UUID,
34    pub account_id: UUID,
35    pub entry_id: UUID,
36    pub currency: CurrencyCode,
37    pub settled: BalanceAmount,
38    pub pending: BalanceAmount,
39    pub encumbrance: BalanceAmount,
40    pub version: u32,
41    #[graphql(skip)]
42    pub(super) balance: cala_ledger::balance::AccountBalance,
43}
44
45#[ComplexObject]
46impl Balance {
47    async fn available(&self, layer: Layer) -> BalanceAmount {
48        let amount = self.balance.details.available(layer);
49        let currency = self.balance.details.currency;
50        BalanceAmount {
51            dr_balance: (amount.dr_balance, currency).into(),
52            cr_balance: (amount.cr_balance, currency).into(),
53            normal_balance: (self.balance.available(layer), currency).into(),
54            entry_id: amount.entry_id.into(),
55        }
56    }
57}
58
59impl ToGlobalId for (JournalId, AccountId, Currency) {
60    fn to_global_id(&self) -> async_graphql::types::ID {
61        async_graphql::types::ID::from(format!("balance:{}:{}:{}", self.0, self.1, self.2))
62    }
63}
64
65impl From<cala_ledger::balance::AccountBalance> for Balance {
66    fn from(balance: cala_ledger::balance::AccountBalance) -> Self {
67        let currency = balance.details.currency;
68        Self {
69            id: (
70                balance.details.journal_id,
71                balance.details.account_id,
72                balance.details.currency,
73            )
74                .to_global_id(),
75            journal_id: balance.details.journal_id.into(),
76            account_id: balance.details.account_id.into(),
77            entry_id: balance.details.entry_id.into(),
78            currency: balance.details.currency.into(),
79            version: balance.details.version,
80            settled: BalanceAmount {
81                dr_balance: (balance.details.settled.dr_balance, currency).into(),
82                cr_balance: (balance.details.settled.cr_balance, currency).into(),
83                normal_balance: (balance.settled(), currency).into(),
84                entry_id: balance.details.settled.entry_id.into(),
85            },
86            pending: BalanceAmount {
87                dr_balance: (balance.details.pending.dr_balance, currency).into(),
88                cr_balance: (balance.details.pending.cr_balance, currency).into(),
89                normal_balance: (balance.pending(), currency).into(),
90                entry_id: balance.details.pending.entry_id.into(),
91            },
92            encumbrance: BalanceAmount {
93                dr_balance: (balance.details.encumbrance.dr_balance, currency).into(),
94                cr_balance: (balance.details.encumbrance.cr_balance, currency).into(),
95                normal_balance: (balance.encumbrance(), currency).into(),
96                entry_id: balance.details.encumbrance.entry_id.into(),
97            },
98            balance,
99        }
100    }
101}