1mod filter_definition;
13pub mod logic;
14pub mod posting;
15pub mod txn;
16
17pub use crate::filters::filter_definition::FilterDefZoned;
18pub use crate::filters::filter_definition::FilterDefinition;
19use jiff::tz::TimeZone;
20use rust_decimal::Decimal;
21use serde::{Deserialize, Serialize};
22use std::fmt::{Error, Formatter};
23
24use logic::TxnFilterAND;
25use logic::TxnFilterNOT;
26use logic::TxnFilterOR;
27
28use txn::TxnFilterBBoxLatLon;
29use txn::TxnFilterBBoxLatLonAlt;
30use txn::TxnFilterTxnCode;
31use txn::TxnFilterTxnComments;
32use txn::TxnFilterTxnDescription;
33use txn::TxnFilterTxnTSBegin;
34use txn::TxnFilterTxnTSEnd;
35use txn::TxnFilterTxnTags;
36use txn::TxnFilterTxnUUID;
37
38use posting::TxnFilterPostingAccount;
39use posting::TxnFilterPostingAmountEqual;
40use posting::TxnFilterPostingAmountGreater;
41use posting::TxnFilterPostingAmountLess;
42use posting::TxnFilterPostingComment;
43use posting::TxnFilterPostingCommodity;
44
45pub trait IndentDisplay {
48 fn i_fmt(&self, indent: &str, _tz: TimeZone, f: &mut Formatter<'_>) -> std::fmt::Result;
50}
51
52#[derive(Serialize, Deserialize, Clone, Debug)]
57pub enum TxnFilter {
58 #[doc(hidden)]
60 NullaryTRUE(NullaryTRUE),
61 #[doc(hidden)]
62 NullaryFALSE(NullaryFALSE),
63
64 #[doc(hidden)]
66 TxnFilterAND(TxnFilterAND),
67 #[doc(hidden)]
68 TxnFilterOR(TxnFilterOR),
69 #[doc(hidden)]
70 TxnFilterNOT(TxnFilterNOT),
71
72 #[doc(hidden)]
74 TxnFilterTxnTSBegin(TxnFilterTxnTSBegin),
75 #[doc(hidden)]
76 TxnFilterTxnTSEnd(TxnFilterTxnTSEnd),
77 #[doc(hidden)]
78 TxnFilterTxnCode(TxnFilterTxnCode),
79 #[doc(hidden)]
80 TxnFilterTxnDescription(TxnFilterTxnDescription),
81 #[doc(hidden)]
82 TxnFilterTxnUUID(TxnFilterTxnUUID),
83 #[doc(hidden)]
84 TxnFilterBBoxLatLon(TxnFilterBBoxLatLon),
85 #[doc(hidden)]
86 TxnFilterBBoxLatLonAlt(TxnFilterBBoxLatLonAlt),
87 #[doc(hidden)]
88 TxnFilterTxnTags(TxnFilterTxnTags),
89 #[doc(hidden)]
90 TxnFilterTxnComments(TxnFilterTxnComments),
91
92 #[doc(hidden)]
94 TxnFilterPostingAccount(TxnFilterPostingAccount),
95 #[doc(hidden)]
96 TxnFilterPostingComment(TxnFilterPostingComment),
97 #[doc(hidden)]
98 TxnFilterPostingAmountEqual(TxnFilterPostingAmountEqual),
99 #[doc(hidden)]
100 TxnFilterPostingAmountLess(TxnFilterPostingAmountLess),
101 #[doc(hidden)]
102 TxnFilterPostingAmountGreater(TxnFilterPostingAmountGreater),
103 #[doc(hidden)]
104 TxnFilterPostingCommodity(TxnFilterPostingCommodity),
105}
106
107impl IndentDisplay for TxnFilter {
115 fn i_fmt(&self, indent: &str, tz: TimeZone, f: &mut Formatter<'_>) -> std::fmt::Result {
116 match self {
117 TxnFilter::NullaryTRUE(tf) => tf.i_fmt(indent, tz, f),
119 TxnFilter::NullaryFALSE(tf) => tf.i_fmt(indent, tz, f),
120
121 TxnFilter::TxnFilterAND(tf) => tf.i_fmt(indent, tz, f),
123 TxnFilter::TxnFilterOR(tf) => tf.i_fmt(indent, tz, f),
124 TxnFilter::TxnFilterNOT(tf) => tf.i_fmt(indent, tz, f),
125
126 TxnFilter::TxnFilterTxnTSBegin(tf) => tf.i_fmt(indent, tz, f),
128 TxnFilter::TxnFilterTxnTSEnd(tf) => tf.i_fmt(indent, tz, f),
129 TxnFilter::TxnFilterTxnCode(tf) => tf.i_fmt(indent, tz, f),
130 TxnFilter::TxnFilterTxnDescription(tf) => tf.i_fmt(indent, tz, f),
131 TxnFilter::TxnFilterTxnUUID(tf) => tf.i_fmt(indent, tz, f),
132 TxnFilter::TxnFilterBBoxLatLon(tf) => tf.i_fmt(indent, tz, f),
133 TxnFilter::TxnFilterBBoxLatLonAlt(tf) => tf.i_fmt(indent, tz, f),
134 TxnFilter::TxnFilterTxnTags(tf) => tf.i_fmt(indent, tz, f),
135 TxnFilter::TxnFilterTxnComments(tf) => tf.i_fmt(indent, tz, f),
136
137 TxnFilter::TxnFilterPostingAccount(tf) => tf.i_fmt(indent, tz, f),
139 TxnFilter::TxnFilterPostingComment(tf) => tf.i_fmt(indent, tz, f),
140 TxnFilter::TxnFilterPostingAmountEqual(tf) => tf.i_fmt(indent, tz, f),
141 TxnFilter::TxnFilterPostingAmountLess(tf) => tf.i_fmt(indent, tz, f),
142 TxnFilter::TxnFilterPostingAmountGreater(tf) => tf.i_fmt(indent, tz, f),
143 TxnFilter::TxnFilterPostingCommodity(tf) => tf.i_fmt(indent, tz, f),
144 }
145 }
146}
147
148#[derive(Serialize, Deserialize, Clone, Debug)]
150pub struct NullaryTRUE {}
151
152impl IndentDisplay for NullaryTRUE {
153 fn i_fmt(&self, indent: &str, _tz: TimeZone, f: &mut Formatter<'_>) -> std::fmt::Result {
154 writeln!(f, "{indent}All pass")
155 }
156}
157
158#[derive(Serialize, Deserialize, Clone, Debug)]
160pub struct NullaryFALSE {}
161
162impl IndentDisplay for NullaryFALSE {
163 fn i_fmt(&self, indent: &str, _tz: TimeZone, f: &mut Formatter<'_>) -> std::fmt::Result {
164 writeln!(f, "{indent}None pass")
165 }
166}
167
168fn logic_filter_indent_fmt(
169 op: &str,
170 indent: &str,
171 tz: TimeZone,
172 filters: &[TxnFilter],
173 f: &mut Formatter<'_>,
174) -> std::fmt::Result {
175 let new_ident = format!("{indent} ");
176
177 writeln!(f, "{indent}{op}")?;
178 let result: Result<Vec<()>, Error> = filters
179 .iter()
180 .map(|tf| tf.i_fmt(&new_ident, tz.clone(), f))
181 .collect();
182
183 match result {
184 Ok(_) => Ok(()),
185 Err(err) => Err(err),
186 }
187}
188
189fn posting_filter_indent_fmt(
190 indent: &str,
191 target: &str,
192 regex: &str,
193 op: &str,
194 amount: &Decimal,
195 f: &mut Formatter<'_>,
196) -> std::fmt::Result {
197 let my_indent = format!("{indent} ");
198 writeln!(f, "{indent}{target}")?;
199 writeln!(f, "{my_indent}account: \"{regex}\"")?;
200 writeln!(f, "{my_indent}amount {op} {amount}")
201}