use crate::types::{DirectiveData, PluginError, PluginInput, PluginOutput};
use super::super::NativePlugin;
pub struct LeafOnlyPlugin;
impl NativePlugin for LeafOnlyPlugin {
fn name(&self) -> &'static str {
"leafonly"
}
fn description(&self) -> &'static str {
"Error on postings to non-leaf accounts"
}
fn process(&self, input: PluginInput) -> PluginOutput {
use std::collections::HashSet;
let mut all_accounts: HashSet<String> = HashSet::new();
for wrapper in &input.directives {
if let DirectiveData::Transaction(txn) = &wrapper.data {
for posting in &txn.postings {
all_accounts.insert(posting.account.clone());
}
}
}
let parent_accounts: HashSet<&String> = all_accounts
.iter()
.filter(|acc| {
all_accounts
.iter()
.any(|other| other != *acc && other.starts_with(&format!("{acc}:")))
})
.collect();
let mut errors = Vec::new();
for wrapper in &input.directives {
if let DirectiveData::Transaction(txn) = &wrapper.data {
for posting in &txn.postings {
if parent_accounts.contains(&posting.account) {
errors.push(PluginError::error(format!(
"Posting to non-leaf account '{}' - has child accounts",
posting.account
)));
}
}
}
}
PluginOutput {
directives: input.directives,
errors,
}
}
}