rustledger_plugin/native/plugins/
check_closing.rs1use crate::types::{
4 AmountData, BalanceData, DirectiveData, DirectiveWrapper, MetaValueData, PluginInput,
5 PluginOutput, sort_directives,
6};
7
8use super::super::NativePlugin;
9use super::utils::increment_date;
10
11pub struct CheckClosingPlugin;
16
17impl NativePlugin for CheckClosingPlugin {
18 fn name(&self) -> &'static str {
19 "check_closing"
20 }
21
22 fn description(&self) -> &'static str {
23 "Zero balance assertion on account closing"
24 }
25
26 fn process(&self, input: PluginInput) -> PluginOutput {
27 let mut new_directives: Vec<DirectiveWrapper> = Vec::new();
28
29 for wrapper in &input.directives {
30 new_directives.push(wrapper.clone());
31
32 if let DirectiveData::Transaction(txn) = &wrapper.data {
33 for posting in &txn.postings {
34 let has_closing = posting.metadata.iter().any(|(key, val)| {
36 key == "closing" && matches!(val, MetaValueData::Bool(true))
37 });
38
39 if has_closing {
40 if let Some(next_date) = increment_date(&wrapper.date) {
42 let currency = posting
44 .units
45 .as_ref()
46 .map_or_else(|| "USD".to_string(), |u| u.currency.clone());
47
48 new_directives.push(DirectiveWrapper {
50 directive_type: "balance".to_string(),
51 date: next_date,
52 filename: None, lineno: None,
54 data: DirectiveData::Balance(BalanceData {
55 account: posting.account.clone(),
56 amount: AmountData {
57 number: "0".to_string(),
58 currency,
59 },
60 tolerance: None,
61 metadata: vec![],
62 }),
63 });
64 }
65 }
66 }
67 }
68 }
69
70 sort_directives(&mut new_directives);
72
73 PluginOutput {
74 directives: new_directives,
75 errors: Vec::new(),
76 }
77 }
78}