Skip to content

Commit 407425a

Browse files
committed
Implmenet Tackler-Mk1 (and JDK) comp. regex
Tackler-Mk1 (and JDK) regex is full haystack matching by default - implement the same logic and keep Account Selector Checksums the same closes GH-31 Signed-off-by: 35V LG84 <[email protected]>
1 parent 1f5a950 commit 407425a

15 files changed

+354
-72
lines changed

Cargo.lock

Lines changed: 0 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tackler-api/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,11 @@ regex = { workspace = true }
3737
rust_decimal = { workspace = true }
3838
serde = { workspace = true, features = [ "derive"] }
3939
serde_json = { workspace = true }
40-
serde_regex = "1.1.0"
40+
tackler-rs = { path = "../tackler-rs", version = "0.7.0-dev" }
4141
time = { workspace = true, features = [ "serde-human-readable", "formatting", "parsing" ] }
4242
time-tz = { workspace = true }
4343
uuid = { workspace = true }
4444

4545
[dev-dependencies]
4646
rust_decimal_macros = { workspace = true }
47-
tackler-rs = { path = "../tackler-rs", version = "0.7.0-dev" }
4847
indoc = { workspace = true }

tackler-api/src/filters/posting/posting_account.rs

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,30 @@
1515
*
1616
*/
1717

18+
use crate::filters::IndentDisplay;
1819
use regex::Regex;
1920
use serde::{Deserialize, Serialize};
2021
use std::fmt::Formatter;
21-
22-
use crate::filters::IndentDisplay;
22+
use tackler_rs::regex::peeled_pattern;
23+
use tackler_rs::regex::serde::full_haystack_matcher;
2324

2425
/// Txn Posting Account filter
2526
///
2627
/// Select the transaction, if any of its posting match `regex`
2728
#[derive(Serialize, Deserialize, Clone, Debug)]
2829
pub struct TxnFilterPostingAccount {
2930
#[doc(hidden)]
30-
#[serde(with = "serde_regex")]
31+
#[serde(with = "full_haystack_matcher")]
3132
pub regex: Regex,
3233
}
3334

3435
impl IndentDisplay for TxnFilterPostingAccount {
3536
fn i_fmt(&self, indent: &str, f: &mut Formatter<'_>) -> std::fmt::Result {
36-
writeln!(f, "{indent}Posting Account: \"{}\"", self.regex.as_str())
37+
writeln!(
38+
f,
39+
"{indent}Posting Account: \"{}\"",
40+
peeled_pattern(&self.regex)
41+
)
3742
}
3843
}
3944

@@ -42,9 +47,32 @@ mod tests {
4247
use super::*;
4348
use crate::filters::{logic::TxnFilterAND, FilterDefinition, NullaryTRUE, TxnFilter};
4449
use indoc::indoc;
45-
use regex::Regex;
50+
51+
use tackler_rs::regex::new_full_haystack_regex;
4652
use tackler_rs::IndocUtils;
4753

54+
#[test]
55+
// test: fdb5c728-1354-4905-8bc0-42c17cc6d948
56+
// desc: PostingAccount, full haystack match
57+
fn posting_account_full_haystack() {
58+
let filter_json_str = r#"{"txnFilter":{"TxnFilterPostingAccount":{"regex":"o.a"}}}"#;
59+
60+
let tf_res = serde_json::from_str::<FilterDefinition>(filter_json_str);
61+
assert!(tf_res.is_ok());
62+
let tf = tf_res.unwrap(/*:test:*/);
63+
64+
match &tf.txn_filter {
65+
TxnFilter::TxnFilterPostingAccount(f) => {
66+
assert!(!f.regex.is_match("foobar"));
67+
assert!(!f.regex.is_match("obar"));
68+
assert!(!f.regex.is_match("ooba"));
69+
70+
assert!(f.regex.is_match("oba"));
71+
}
72+
_ => panic!(/*:test:*/),
73+
}
74+
}
75+
4876
#[test]
4977
// test: 44d80d6d-b2cf-47a0-a228-bb2ea068f9f5
5078
// desc: PostingAccount, JSON
@@ -92,12 +120,12 @@ mod tests {
92120
txn_filter: TxnFilter::TxnFilterAND(TxnFilterAND {
93121
txn_filters: vec![
94122
TxnFilter::TxnFilterPostingAccount(TxnFilterPostingAccount {
95-
regex: Regex::new("(abc.*)|(def.*)").unwrap(/*:test:*/),
123+
regex: new_full_haystack_regex("(abc.*)|(def.*)").unwrap(/*:test:*/),
96124
}),
97125
TxnFilter::TxnFilterAND(TxnFilterAND {
98126
txn_filters: vec![
99127
TxnFilter::TxnFilterPostingAccount(TxnFilterPostingAccount {
100-
regex: Regex::new("xyz").unwrap(/*:test:*/),
128+
regex: new_full_haystack_regex("xyz").unwrap(/*:test:*/),
101129
}),
102130
TxnFilter::NullaryTRUE(NullaryTRUE {}),
103131
],

tackler-api/src/filters/posting/posting_amount_equal.rs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ use regex::Regex;
1919
use rust_decimal::Decimal;
2020
use serde::{Deserialize, Serialize};
2121
use std::fmt::Formatter;
22+
use tackler_rs::regex::peeled_pattern;
23+
use tackler_rs::regex::serde::full_haystack_matcher;
2224

2325
use crate::filters::{posting_filter_indent_fmt, IndentDisplay};
2426

@@ -32,7 +34,7 @@ use crate::filters::{posting_filter_indent_fmt, IndentDisplay};
3234
#[derive(Serialize, Deserialize, Clone, Debug)]
3335
pub struct TxnFilterPostingAmountEqual {
3436
#[doc(hidden)]
35-
#[serde(with = "serde_regex")]
37+
#[serde(with = "full_haystack_matcher")]
3638
pub regex: Regex,
3739
#[doc(hidden)]
3840
#[serde(with = "rust_decimal::serde::arbitrary_precision")]
@@ -44,7 +46,7 @@ impl IndentDisplay for TxnFilterPostingAmountEqual {
4446
posting_filter_indent_fmt(
4547
indent,
4648
"Posting Amount",
47-
self.regex.as_str(),
49+
peeled_pattern(&self.regex),
4850
"==",
4951
&self.amount,
5052
f,
@@ -57,9 +59,33 @@ mod tests {
5759
use super::*;
5860
use crate::filters::{logic::TxnFilterAND, FilterDefinition, NullaryTRUE, TxnFilter};
5961
use indoc::indoc;
60-
use regex::Regex;
62+
63+
use tackler_rs::regex::new_full_haystack_regex;
6164
use tackler_rs::IndocUtils;
6265

66+
#[test]
67+
// test: c63d9ff7-6039-474b-8b8a-be6b8927510f
68+
// desc: PostingAmountEqual, full haystack match
69+
fn posting_amount_equal_full_haystack() {
70+
let filter_json_str =
71+
r#"{"txnFilter":{"TxnFilterPostingAmountEqual":{"regex":"o.a","amount":1}}}"#;
72+
73+
let tf_res = serde_json::from_str::<FilterDefinition>(filter_json_str);
74+
assert!(tf_res.is_ok());
75+
let tf = tf_res.unwrap(/*:test:*/);
76+
77+
match &tf.txn_filter {
78+
TxnFilter::TxnFilterPostingAmountEqual(f) => {
79+
assert!(!f.regex.is_match("foobar"));
80+
assert!(!f.regex.is_match("obar"));
81+
assert!(!f.regex.is_match("ooba"));
82+
83+
assert!(f.regex.is_match("oba"));
84+
}
85+
_ => panic!(/*:test:*/),
86+
}
87+
}
88+
6389
#[test]
6490
// test: b7b4543d-2ffa-488f-b251-af5a7ba7204f
6591
// desc: PostingAmountEqual, JSON
@@ -112,13 +138,13 @@ mod tests {
112138
txn_filter: TxnFilter::TxnFilterAND(TxnFilterAND {
113139
txn_filters: vec![
114140
TxnFilter::TxnFilterPostingAmountEqual(TxnFilterPostingAmountEqual {
115-
regex: Regex::new("(abc.*)|(def.*)").unwrap(/*:test:*/),
141+
regex: new_full_haystack_regex("(abc.*)|(def.*)").unwrap(/*:test:*/),
116142
amount: Decimal::from(1),
117143
}),
118144
TxnFilter::TxnFilterAND(TxnFilterAND {
119145
txn_filters: vec![
120146
TxnFilter::TxnFilterPostingAmountEqual(TxnFilterPostingAmountEqual {
121-
regex: Regex::new("xyz").unwrap(/*:test:*/),
147+
regex: new_full_haystack_regex("xyz").unwrap(/*:test:*/),
122148
amount: Decimal::from(2),
123149
}),
124150
TxnFilter::NullaryTRUE(NullaryTRUE {}),

tackler-api/src/filters/posting/posting_amount_greater.rs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ use regex::Regex;
1919
use rust_decimal::Decimal;
2020
use serde::{Deserialize, Serialize};
2121
use std::fmt::Formatter;
22+
use tackler_rs::regex::peeled_pattern;
23+
use tackler_rs::regex::serde::full_haystack_matcher;
2224

2325
use crate::filters::{posting_filter_indent_fmt, IndentDisplay};
2426

@@ -38,7 +40,7 @@ use crate::filters::{posting_filter_indent_fmt, IndentDisplay};
3840
#[derive(Serialize, Deserialize, Clone, Debug)]
3941
pub struct TxnFilterPostingAmountGreater {
4042
#[doc(hidden)]
41-
#[serde(with = "serde_regex")]
43+
#[serde(with = "full_haystack_matcher")]
4244
pub regex: Regex,
4345
#[doc(hidden)]
4446
#[serde(with = "rust_decimal::serde::arbitrary_precision")]
@@ -50,7 +52,7 @@ impl IndentDisplay for TxnFilterPostingAmountGreater {
5052
posting_filter_indent_fmt(
5153
indent,
5254
"Posting Amount",
53-
self.regex.as_str(),
55+
peeled_pattern(&self.regex),
5456
">",
5557
&self.amount,
5658
f,
@@ -63,9 +65,33 @@ mod tests {
6365
use super::*;
6466
use crate::filters::{logic::TxnFilterAND, FilterDefinition, NullaryTRUE, TxnFilter};
6567
use indoc::indoc;
66-
use regex::Regex;
68+
69+
use tackler_rs::regex::new_full_haystack_regex;
6770
use tackler_rs::IndocUtils;
6871

72+
#[test]
73+
// test: 8609eb58-f600-42d1-a20a-c7de2c57e6e2
74+
// desc: PostingAmountGreater, full haystack match
75+
fn posting_amount_greater_full_haystack() {
76+
let filter_json_str =
77+
r#"{"txnFilter":{"TxnFilterPostingAmountGreater":{"regex":"o.a","amount":1}}}"#;
78+
79+
let tf_res = serde_json::from_str::<FilterDefinition>(filter_json_str);
80+
assert!(tf_res.is_ok());
81+
let tf = tf_res.unwrap(/*:test:*/);
82+
83+
match &tf.txn_filter {
84+
TxnFilter::TxnFilterPostingAmountGreater(f) => {
85+
assert!(!f.regex.is_match("foobar"));
86+
assert!(!f.regex.is_match("obar"));
87+
assert!(!f.regex.is_match("ooba"));
88+
89+
assert!(f.regex.is_match("oba"));
90+
}
91+
_ => panic!(/*:test:*/),
92+
}
93+
}
94+
6995
#[test]
7096
// test: 66d6ee10-a18e-4615-9e7a-1569c793fe46
7197
// desc: PostingAmountGreater, JSON
@@ -118,14 +144,14 @@ mod tests {
118144
txn_filter: TxnFilter::TxnFilterAND(TxnFilterAND {
119145
txn_filters: vec![
120146
TxnFilter::TxnFilterPostingAmountGreater(TxnFilterPostingAmountGreater {
121-
regex: Regex::new("(abc.*)|(def.*)").unwrap(/*:test:*/),
147+
regex: new_full_haystack_regex("(abc.*)|(def.*)").unwrap(/*:test:*/),
122148
amount: Decimal::from(1),
123149
}),
124150
TxnFilter::TxnFilterAND(TxnFilterAND {
125151
txn_filters: vec![
126152
TxnFilter::TxnFilterPostingAmountGreater(
127153
TxnFilterPostingAmountGreater {
128-
regex: Regex::new("xyz").unwrap(/*:test:*/),
154+
regex: new_full_haystack_regex("xyz").unwrap(/*:test:*/),
129155
amount: Decimal::from(2),
130156
},
131157
),

tackler-api/src/filters/posting/posting_amount_less.rs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ use regex::Regex;
1919
use rust_decimal::Decimal;
2020
use serde::{Deserialize, Serialize};
2121
use std::fmt::Formatter;
22+
use tackler_rs::regex::peeled_pattern;
23+
use tackler_rs::regex::serde::full_haystack_matcher;
2224

2325
use crate::filters::{posting_filter_indent_fmt, IndentDisplay};
2426

@@ -38,7 +40,7 @@ use crate::filters::{posting_filter_indent_fmt, IndentDisplay};
3840
#[derive(Serialize, Deserialize, Clone, Debug)]
3941
pub struct TxnFilterPostingAmountLess {
4042
#[doc(hidden)]
41-
#[serde(with = "serde_regex")]
43+
#[serde(with = "full_haystack_matcher")]
4244
pub regex: Regex,
4345
#[doc(hidden)]
4446
#[serde(with = "rust_decimal::serde::arbitrary_precision")]
@@ -50,7 +52,7 @@ impl IndentDisplay for TxnFilterPostingAmountLess {
5052
posting_filter_indent_fmt(
5153
indent,
5254
"Posting Amount",
53-
self.regex.as_str(),
55+
peeled_pattern(&self.regex),
5456
"<",
5557
&self.amount,
5658
f,
@@ -63,9 +65,33 @@ mod tests {
6365
use super::*;
6466
use crate::filters::{logic::TxnFilterAND, FilterDefinition, NullaryTRUE, TxnFilter};
6567
use indoc::indoc;
66-
use regex::Regex;
68+
69+
use tackler_rs::regex::new_full_haystack_regex;
6770
use tackler_rs::IndocUtils;
6871

72+
#[test]
73+
// test: 2d01669b-b051-4550-9436-ac31e84dd892
74+
// desc: PostingAmountLess, full haystack match
75+
fn posting_amount_less_full_haystack() {
76+
let filter_json_str =
77+
r#"{"txnFilter":{"TxnFilterPostingAmountLess":{"regex":"o.a","amount":1}}}"#;
78+
79+
let tf_res = serde_json::from_str::<FilterDefinition>(filter_json_str);
80+
assert!(tf_res.is_ok());
81+
let tf = tf_res.unwrap(/*:test:*/);
82+
83+
match &tf.txn_filter {
84+
TxnFilter::TxnFilterPostingAmountLess(f) => {
85+
assert!(!f.regex.is_match("foobar"));
86+
assert!(!f.regex.is_match("obar"));
87+
assert!(!f.regex.is_match("ooba"));
88+
89+
assert!(f.regex.is_match("oba"));
90+
}
91+
_ => panic!(/*:test:*/),
92+
}
93+
}
94+
6995
#[test]
7096
// test: 3dbd4103-66ee-4747-8eae-75d6b13bdb29
7197
// desc: PostingAmountLess, JSON
@@ -118,13 +144,13 @@ mod tests {
118144
txn_filter: TxnFilter::TxnFilterAND(TxnFilterAND {
119145
txn_filters: vec![
120146
TxnFilter::TxnFilterPostingAmountLess(TxnFilterPostingAmountLess {
121-
regex: Regex::new("(abc.*)|(def.*)").unwrap(/*:test:*/),
147+
regex: new_full_haystack_regex("(abc.*)|(def.*)").unwrap(/*:test:*/),
122148
amount: Decimal::from(1),
123149
}),
124150
TxnFilter::TxnFilterAND(TxnFilterAND {
125151
txn_filters: vec![
126152
TxnFilter::TxnFilterPostingAmountLess(TxnFilterPostingAmountLess {
127-
regex: Regex::new("xyz").unwrap(/*:test:*/),
153+
regex: new_full_haystack_regex("xyz").unwrap(/*:test:*/),
128154
amount: Decimal::from(2),
129155
}),
130156
TxnFilter::NullaryTRUE(NullaryTRUE {}),

0 commit comments

Comments
 (0)