use crate::types::{
CloseData, DirectiveData, DirectiveWrapper, PluginInput, PluginOp, PluginOutput,
};
use super::super::{NativePlugin, RegularPlugin};
pub struct CloseTreePlugin;
impl NativePlugin for CloseTreePlugin {
fn name(&self) -> &'static str {
"close_tree"
}
fn description(&self) -> &'static str {
"Close descendant accounts automatically"
}
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::Open(data) = &wrapper.data {
all_accounts.insert(data.account.clone());
}
if let DirectiveData::Transaction(txn) = &wrapper.data {
for posting in &txn.postings {
all_accounts.insert(posting.account.clone());
}
}
}
let mut closed_parents: Vec<(String, String)> = Vec::new(); for wrapper in &input.directives {
if let DirectiveData::Close(data) = &wrapper.data {
closed_parents.push((data.account.clone(), wrapper.date.clone()));
}
}
let mut already_closed: HashSet<String> = HashSet::new();
for wrapper in &input.directives {
if let DirectiveData::Close(data) = &wrapper.data {
already_closed.insert(data.account.clone());
}
}
let mut ops: Vec<PluginOp> = (0..input.directives.len()).map(PluginOp::Keep).collect();
let mut inserted_closes: HashSet<String> = HashSet::new();
for (parent, close_date) in &closed_parents {
let prefix = format!("{parent}:");
for account in &all_accounts {
if account.starts_with(&prefix)
&& !already_closed.contains(account)
&& !inserted_closes.contains(account)
{
inserted_closes.insert(account.clone());
ops.push(PluginOp::Insert(DirectiveWrapper {
directive_type: "close".to_string(),
date: close_date.clone(),
filename: None, lineno: None,
data: DirectiveData::Close(CloseData {
account: account.clone(),
metadata: vec![],
}),
}));
}
}
}
PluginOutput {
ops,
errors: Vec::new(),
}
}
}
impl RegularPlugin for CloseTreePlugin {}