Skip to content

Commit

Permalink
chore: add AccountValues to velocity context
Browse files Browse the repository at this point in the history
  • Loading branch information
bodymindarts committed Oct 7, 2024
1 parent 234cc47 commit 56fe010
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 23 deletions.
19 changes: 19 additions & 0 deletions cala-ledger-core-types/src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,22 @@ pub struct AccountConfig {
pub is_account_set: bool,
pub eventually_consistent: bool,
}

mod cel {
use cel_interpreter::{CelMap, CelValue};

impl From<&super::AccountValues> for CelValue {
fn from(account: &super::AccountValues) -> Self {
let mut map = CelMap::new();
map.insert("id", account.id);
map.insert("code", account.code.clone());
map.insert("name", account.name.clone());
map.insert("externalId", account.code.clone());
map.insert("normalBalanceType", account.normal_balance_type);
if let Some(metadata) = &account.metadata {
map.insert("metadata", metadata.clone());
}
map.into()
}
}
}
2 changes: 1 addition & 1 deletion cala-ledger-core-types/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ mod cel {
fn from(entry: &super::EntryValues) -> Self {
let mut map = CelMap::new();
map.insert("id", entry.id);
map.insert("entry_type", entry.entry_type.clone());
map.insert("entryType", entry.entry_type.clone());
map.insert("sequence", CelValue::UInt(entry.sequence as u64));
map.insert("layer", entry.layer);
map.insert("direction", entry.direction);
Expand Down
6 changes: 3 additions & 3 deletions cala-ledger-core-types/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ mod cel {
fn from(tx: &super::TransactionValues) -> Self {
let mut map = CelMap::new();
map.insert("id", tx.id);
map.insert("journal_id", tx.journal_id);
map.insert("tx_template_id", tx.tx_template_id);
map.insert("journalId", tx.journal_id);
map.insert("txTemplateId", tx.tx_template_id);
map.insert("effective", tx.effective);
map.insert("correlation_id", tx.correlation_id.clone());
map.insert("correlationId", tx.correlation_id.clone());
if let Some(metadata) = &tx.metadata {
map.insert("metadata", metadata.clone());
}
Expand Down
9 changes: 7 additions & 2 deletions cala-ledger/src/velocity/account_control/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ use sqlx::PgPool;

use std::collections::HashMap;

use cala_types::{
account::AccountValues,
velocity::{VelocityControlValues, VelocityLimitValues},
};

use crate::{
atomic_operation::*,
param::Params,
primitives::{AccountId, DebitOrCredit, Layer},
};
use cala_types::velocity::{VelocityControlValues, VelocityLimitValues};

use super::error::VelocityError;

Expand Down Expand Up @@ -101,7 +105,8 @@ impl AccountControls {
&self,
op: &mut AtomicOperation<'_>,
account_ids: &[AccountId],
) -> Result<HashMap<AccountId, Vec<AccountVelocityControl>>, VelocityError> {
) -> Result<HashMap<AccountId, (AccountValues, Vec<AccountVelocityControl>)>, VelocityError>
{
self.repo.find_for_enforcement(op.tx(), account_ids).await
}
}
27 changes: 22 additions & 5 deletions cala-ledger/src/velocity/account_control/repo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use sqlx::{PgPool, Postgres, Transaction};

use std::collections::HashMap;

use cala_types::account::AccountValues;

use crate::primitives::{AccountId, VelocityControlId};

use super::{super::error::*, value::*};
Expand Down Expand Up @@ -39,21 +41,36 @@ impl AccountControlRepo {
&self,
db: &mut Transaction<'_, Postgres>,
account_ids: &[AccountId],
) -> Result<HashMap<AccountId, Vec<AccountVelocityControl>>, VelocityError> {
) -> Result<HashMap<AccountId, (AccountValues, Vec<AccountVelocityControl>)>, VelocityError>
{
let rows = sqlx::query!(
r#"SELECT values FROM cala_velocity_account_controls
WHERE data_source_id = '00000000-0000-0000-0000-000000000000' AND account_id = ANY($1)"#,
r#"SELECT values, latest_values
FROM cala_velocity_account_controls v
JOIN cala_accounts a
ON v.account_id = a.id
AND v.data_source_id = a.data_source_id
WHERE v.data_source_id = '00000000-0000-0000-0000-000000000000'
AND account_id = ANY($1)"#,
account_ids as &[AccountId],
)
.fetch_all(&mut **db)
.await?;

let mut res: HashMap<AccountId, Vec<AccountVelocityControl>> = HashMap::new();
let mut res: HashMap<AccountId, (AccountValues, Vec<_>)> = HashMap::new();

for row in rows {
let values: AccountVelocityControl =
serde_json::from_value(row.values).expect("Failed to deserialize control values");
res.entry(values.account_id).or_default().push(values);
res.entry(values.account_id)
.or_insert_with(|| {
(
serde_json::from_value(row.latest_values)
.expect("Failed to deserialize account values"),
Vec::new(),
)
})
.1
.push(values);
}

Ok(res)
Expand Down
14 changes: 8 additions & 6 deletions cala-ledger/src/velocity/balance/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use sqlx::PgPool;
use std::collections::HashMap;

use cala_types::{
account::AccountValues,
balance::BalanceSnapshot,
entry::EntryValues,
transaction::TransactionValues,
Expand Down Expand Up @@ -36,9 +37,10 @@ impl VelocityBalances {
created_at: DateTime<Utc>,
transaction: &TransactionValues,
entries: &[EntryValues],
controls: HashMap<AccountId, Vec<AccountVelocityControl>>,
controls: HashMap<AccountId, (AccountValues, Vec<AccountVelocityControl>)>,
) -> Result<(), VelocityError> {
let mut context = super::context::EvalContext::new(transaction);
let mut context =
super::context::EvalContext::new(transaction, controls.values().map(|v| &v.0));

let entries_to_enforce =
Self::determin_entries_to_enforce(&mut context, entries, &controls)?;

Check warning on line 46 in cala-ledger/src/velocity/balance/mod.rs

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"determin" should be "determine".
Expand All @@ -65,7 +67,7 @@ impl VelocityBalances {
fn determin_entries_to_enforce<'a>(

Check warning on line 67 in cala-ledger/src/velocity/balance/mod.rs

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"determin" should be "determine".
context: &mut super::context::EvalContext,
entries: &'a [EntryValues],
controls: &'a HashMap<AccountId, Vec<AccountVelocityControl>>,
controls: &'a HashMap<AccountId, (AccountValues, Vec<AccountVelocityControl>)>,
) -> Result<
HashMap<VelocityBalanceKey, Vec<(&'a AccountVelocityLimit, &'a EntryValues)>>,
VelocityError,
Expand All @@ -79,8 +81,8 @@ impl VelocityBalances {
Some(control) => control,
None => continue,
};
for control in controls {
let ctx = context.control_context(entry);
for control in controls.1.iter() {
let ctx = context.context_for_entry(entry);
let control_active = if let Some(condition) = &control.condition {
let control_active: bool = condition.try_evaluate(&ctx)?;
control_active
Expand Down Expand Up @@ -136,7 +138,7 @@ impl VelocityBalances {
let mut new_balances = Vec::new();

for (limit, entry) in entries {
let ctx = context.control_context(entry);
let ctx = context.context_for_entry(entry);
let balance = match (latest_balance.take(), current_balances.remove(key)) {
(Some(latest), _) => {
new_balances.push(latest.clone());
Expand Down
28 changes: 22 additions & 6 deletions cala-ledger/src/velocity/context.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,48 @@
use std::collections::HashMap;

use cala_types::{entry::EntryValues, transaction::TransactionValues};
use cala_types::{account::AccountValues, entry::EntryValues, transaction::TransactionValues};
use cel_interpreter::{CelMap, CelValue};

use crate::{cel_context::*, primitives::EntryId};
use crate::{
cel_context::*,
primitives::{AccountId, EntryId},
};

pub struct EvalContext {
transaction: CelValue,
entry_values: HashMap<EntryId, CelValue>,
account_values: HashMap<AccountId, CelValue>,
}

impl EvalContext {
pub fn new(transaction: &TransactionValues) -> Self {
pub fn new<'a>(
transaction: &TransactionValues,
accounts: impl Iterator<Item = &'a AccountValues>,
) -> Self {
let account_values = accounts.map(|a| (a.id, a.into())).collect();
Self {
transaction: transaction.into(),
entry_values: HashMap::new(),
account_values,
}
}

pub fn control_context(&mut self, entry: &EntryValues) -> CelContext {
let entry = self
pub fn context_for_entry(&mut self, entry: &EntryValues) -> CelContext {
let cel_entry = self
.entry_values
.entry(entry.id)
.or_insert_with(|| entry.into());

let mut vars = CelMap::new();
vars.insert("transaction", self.transaction.clone());
vars.insert("entry", entry.clone());
vars.insert("entry", cel_entry.clone());
vars.insert(
"account",
self.account_values
.get(&entry.account_id)
.expect("account values not set for context")
.clone(),
);

let mut context = CelMap::new();
context.insert("vars", vars);
Expand Down

0 comments on commit 56fe010

Please sign in to comment.