Skip to content

Commit

Permalink
feat: add trial_balance query function with balances
Browse files Browse the repository at this point in the history
  • Loading branch information
vindard committed Jan 23, 2025
1 parent 6bc7b8d commit ba8ff87
Show file tree
Hide file tree
Showing 4 changed files with 227 additions and 9 deletions.
6 changes: 5 additions & 1 deletion lana/app/src/trial_balance/ledger/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ pub enum TrialBalanceLedgerError {
Sqlx(#[from] sqlx::Error),
#[error("TrialBalanceLedgerError - CalaLedger: {0}")]
CalaLedger(#[from] cala_ledger::error::LedgerError),
#[error("TrialBalanceLedgerError - CalaAccountSetError: {0}")]
#[error("TrialBalanceLedgerError - CalaAccountSet: {0}")]
CalaAccountSet(#[from] cala_ledger::account_set::error::AccountSetError),
#[error("TrialBalanceLedgerError - CalaBalance: {0}")]
CalaBalance(#[from] cala_ledger::balance::error::BalanceError),
#[error("TrialBalanceLedgerError - NonAccountSetMemberTypeFound")]
NonAccountSetMemberTypeFound,
}
91 changes: 84 additions & 7 deletions lana/app/src/trial_balance/ledger/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
pub mod error;

pub(super) use cala_ledger::balance::AccountBalance;
use cala_ledger::{
account_set::{AccountSet, AccountSetsByCreatedAtCursor, NewAccountSet},
CalaLedger, DebitOrCredit, JournalId,
account_set::{
AccountSet, AccountSetMemberId, AccountSetValues, AccountSetsByCreatedAtCursor,
NewAccountSet,
},
AccountSetId, CalaLedger, Currency, DebitOrCredit, JournalId, LedgerOperation,
};

use crate::primitives::LedgerAccountSetId;

use error::*;

#[derive(Clone)]
Expand All @@ -15,6 +17,17 @@ pub struct TrialBalanceLedger {
journal_id: JournalId,
}

pub struct LedgerAccountSetDetails {
pub values: AccountSetValues,
pub balance: AccountBalance,
}

pub struct LedgerAccountSetDetailsWithAccounts {
pub values: AccountSetValues,
pub balance: AccountBalance,
pub accounts: Vec<LedgerAccountSetDetails>,
}

impl TrialBalanceLedger {
pub fn new(cala: &CalaLedger, journal_id: JournalId) -> Self {
Self {
Expand All @@ -26,7 +39,7 @@ impl TrialBalanceLedger {
pub async fn create(
&self,
op: es_entity::DbOp<'_>,
statement_id: impl Into<LedgerAccountSetId>,
statement_id: impl Into<AccountSetId>,
name: &str,
) -> Result<(), TrialBalanceLedgerError> {
let mut op = self.cala.ledger_operation_from_db_op(op);
Expand Down Expand Up @@ -62,8 +75,8 @@ impl TrialBalanceLedger {
pub async fn add_member(
&self,
op: es_entity::DbOp<'_>,
statement_id: impl Into<LedgerAccountSetId>,
member: LedgerAccountSetId,
statement_id: impl Into<AccountSetId>,
member: AccountSetId,
) -> Result<(), TrialBalanceLedgerError> {
let statement_id = statement_id.into();

Expand All @@ -76,4 +89,68 @@ impl TrialBalanceLedger {
op.commit().await?;
Ok(())
}

async fn get_account_set(
&self,
op: &mut LedgerOperation<'_>,
id: impl Into<AccountSetId> + Copy,
currency: Currency,
) -> Result<LedgerAccountSetDetails, TrialBalanceLedgerError> {
let id = id.into();

let values = self.cala.account_sets().find(id).await?.into_values();
let balance = self
.cala
.balances()
.find_in_op(op, self.journal_id, id, currency)
.await?;

Ok(LedgerAccountSetDetails { values, balance })
}

async fn get_member_account_sets(
&self,
op: &mut LedgerOperation<'_>,
id: impl Into<AccountSetId> + Copy,
currency: Currency,
) -> Result<Vec<LedgerAccountSetDetails>, TrialBalanceLedgerError> {
let id = id.into();

let member_ids = self
.cala
.account_sets()
.list_members_in_op(op, id, Default::default())
.await?
.entities
.into_iter()
.map(|m| match m.id {
AccountSetMemberId::AccountSet(id) => Ok(id),
_ => Err(TrialBalanceLedgerError::NonAccountSetMemberTypeFound),
})
.collect::<Result<Vec<AccountSetId>, TrialBalanceLedgerError>>()?;

let mut accounts: Vec<LedgerAccountSetDetails> = vec![];
for id in member_ids {
accounts.push(self.get_account_set(op, id, currency).await?);
}

Ok(accounts)
}

pub async fn get_trial_balance(
&self,
op: &mut LedgerOperation<'_>,
id: impl Into<AccountSetId> + Copy,
currency: Currency,
) -> Result<LedgerAccountSetDetailsWithAccounts, TrialBalanceLedgerError> {
let trial_balance_set = self.get_account_set(op, id, currency).await?;

let accounts = self.get_member_account_sets(op, id, currency).await?;

Ok(LedgerAccountSetDetailsWithAccounts {
values: trial_balance_set.values,
balance: trial_balance_set.balance,
accounts,
})
}
}
55 changes: 54 additions & 1 deletion lana/app/src/trial_balance/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod error;
pub mod ledger;
mod statement;

use audit::AuditSvc;
use authz::PermissionCheck;
Expand All @@ -8,16 +9,18 @@ use rbac_types::TrialBalanceAction;

use crate::{
authorization::{Authorization, Object},
primitives::{LedgerAccountSetId, TrialBalanceId},
primitives::{Currency, LedgerAccountSetId, TrialBalanceId},
};

use error::*;
use ledger::*;
use statement::*;

#[derive(Clone)]
pub struct TrialBalances {
pool: sqlx::PgPool,
authz: Authorization,
cala: CalaLedger,
trial_balance_ledger: TrialBalanceLedger,
}

Expand All @@ -34,6 +37,7 @@ impl TrialBalances {
pool: pool.clone(),
trial_balance_ledger,
authz: authz.clone(),
cala: cala.clone(),
})
}

Expand Down Expand Up @@ -101,4 +105,53 @@ impl TrialBalances {

Ok(())
}

pub async fn trial_balance(
&self,
trial_balance_id: impl Into<TrialBalanceId>,
currency: Currency,
) -> Result<TrialBalance, TrialBalanceError> {
let trial_balance_id = trial_balance_id.into();

let mut op = es_entity::DbOp::init(&self.pool).await?;

self.authz
.audit()
.record_system_entry_in_tx(op.tx(), Object::TrialBalance, TrialBalanceAction::List)
.await?;

let mut op = self.cala.ledger_operation_from_db_op(op);

let trial_balance_details = self
.trial_balance_ledger
.get_trial_balance(&mut op, trial_balance_id, currency)
.await?;

op.commit().await?;
Ok(TrialBalance::from(trial_balance_details))
}
}

pub struct TrialBalance {
id: TrialBalanceId,
name: String,
description: Option<String>,
balance: StatementAccountSetBalance,
accounts: Vec<StatementAccountSet>,
}

impl From<LedgerAccountSetDetailsWithAccounts> for TrialBalance {
fn from(details: LedgerAccountSetDetailsWithAccounts) -> Self {
Self {
id: details.values.id.into(),
name: details.values.name,
description: details.values.description,
balance: details.balance.into(),
accounts: details
.accounts
.into_iter()
.map(StatementAccountSet::from)
.collect(),
}
}
}
84 changes: 84 additions & 0 deletions lana/app/src/trial_balance/statement.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use crate::primitives::{Currency, LedgerAccountSetId};

use super::{
ledger::{AccountBalance, LedgerAccountSetDetails},
LedgerAccountSetDetailsWithAccounts,
};

pub struct StatementAccountSet {
pub id: LedgerAccountSetId,
pub name: String,
pub description: Option<String>,
pub balance: StatementAccountSetBalance,
}

impl From<LedgerAccountSetDetails> for StatementAccountSet {
fn from(details: LedgerAccountSetDetails) -> Self {
Self {
id: details.values.id,
name: details.values.name,
description: details.values.description,
balance: details.balance.into(),
}
}
}

pub struct StatementAccountSetWithAccounts {
pub id: LedgerAccountSetId,
pub name: String,
pub description: Option<String>,
pub balance: StatementAccountSetBalance,
pub accounts: Vec<StatementAccountSet>,
}

impl From<LedgerAccountSetDetailsWithAccounts> for StatementAccountSetWithAccounts {
fn from(details: LedgerAccountSetDetailsWithAccounts) -> Self {
Self {
id: details.values.id,
name: details.values.name,
description: details.values.description,
balance: details.balance.into(),
accounts: details
.accounts
.into_iter()
.map(StatementAccountSet::from)
.collect(),
}
}
}

pub struct StatementAccountSetBalance {
currency: Currency,
settled: StatementBalanceAmount,
pending: StatementBalanceAmount,
encumbrance: StatementBalanceAmount,
}

impl From<AccountBalance> for StatementAccountSetBalance {
fn from(balance: AccountBalance) -> Self {
Self {
currency: balance.details.currency,
settled: StatementBalanceAmount {
normal_balance: balance.settled().to_string(),
dr_balance: balance.details.settled.dr_balance.to_string(),
cr_balance: balance.details.settled.cr_balance.to_string(),
},
pending: StatementBalanceAmount {
normal_balance: balance.pending().to_string(),
dr_balance: balance.details.pending.dr_balance.to_string(),
cr_balance: balance.details.pending.cr_balance.to_string(),
},
encumbrance: StatementBalanceAmount {
normal_balance: balance.encumbrance().to_string(),
dr_balance: balance.details.encumbrance.dr_balance.to_string(),
cr_balance: balance.details.encumbrance.cr_balance.to_string(),
},
}
}
}

pub struct StatementBalanceAmount {
pub normal_balance: String, // TODO: change?
pub dr_balance: String, // TODO: change?
pub cr_balance: String, // TODO: change?
}

0 comments on commit ba8ff87

Please sign in to comment.