+transaction into own file, pretty printing of results I
This commit is contained in:
parent
685538982d
commit
1d8eb970c6
335
Cargo.lock
generated
335
Cargo.lock
generated
|
@ -1,11 +1,81 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea"
|
||||
dependencies = [
|
||||
"backtrace-sys",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace-sys"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "blake2b_simd"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b83b7baab1e671718d78204225800d6b170e648188ac7dc992e9d6bddf87d0c0"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "0.2.8"
|
||||
|
@ -24,6 +94,18 @@ version = "1.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.10"
|
||||
|
@ -35,6 +117,31 @@ dependencies = [
|
|||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cloudabi"
|
||||
version = "0.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.6.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "csv"
|
||||
version = "1.1.1"
|
||||
|
@ -63,11 +170,28 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf5caf67ecbe612af35e1a9511e7959ecbc42b05f2c5145dbbf5f8fe817b1289"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"proc-macro2 0.4.30",
|
||||
"quote 0.6.13",
|
||||
"syn 0.15.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||
|
||||
[[package]]
|
||||
name = "encoding"
|
||||
version = "0.2.33"
|
||||
|
@ -132,6 +256,28 @@ version = "0.1.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"failure_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure_derive"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.6",
|
||||
"quote 1.0.2",
|
||||
"syn 1.0.11",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixed"
|
||||
version = "0.5.0"
|
||||
|
@ -141,6 +287,12 @@ dependencies = [
|
|||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-cprng"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.4"
|
||||
|
@ -218,13 +370,36 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
|
||||
[[package]]
|
||||
name = "prettytable-rs"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fd04b170004fa2daccf418a7f8253aaf033c27760b5f225889024cf66d7ac2e"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"csv",
|
||||
"encode_unicode",
|
||||
"lazy_static",
|
||||
"term",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
"unicode-xid 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27"
|
||||
dependencies = [
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -233,7 +408,45 @@ version = "0.6.13"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"proc-macro2 0.4.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||
dependencies = [
|
||||
"rand_core 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||
|
||||
[[package]]
|
||||
name = "rand_os"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
|
||||
dependencies = [
|
||||
"cloudabi",
|
||||
"fuchsia-cprng",
|
||||
"libc",
|
||||
"rand_core 0.4.2",
|
||||
"rdrand",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -244,8 +457,19 @@ dependencies = [
|
|||
"csv",
|
||||
"encoding",
|
||||
"fixed",
|
||||
"prettytable-rs",
|
||||
"readfilez",
|
||||
"string_cache",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rdrand"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -264,6 +488,18 @@ version = "0.1.56"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d"
|
||||
dependencies = [
|
||||
"failure",
|
||||
"rand_os",
|
||||
"redox_syscall",
|
||||
"rust-argon2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.1.8"
|
||||
|
@ -273,6 +509,23 @@ dependencies = [
|
|||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-argon2"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"blake2b_simd",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.2"
|
||||
|
@ -310,9 +563,63 @@ version = "0.15.44"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
"proc-macro2 0.4.30",
|
||||
"quote 0.6.13",
|
||||
"unicode-xid 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.6",
|
||||
"quote 1.0.2",
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.6",
|
||||
"quote 1.0.2",
|
||||
"syn 1.0.11",
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "term"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"dirs",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f357d1814b33bc2dc221243f8424104bfe72dbe911d5b71b3816a2dff1c977e"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb2e25d25307eb8436894f727aba8f65d07adf02e5b35a13cebed48bd282bfef"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.6",
|
||||
"quote 1.0.2",
|
||||
"syn 1.0.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -332,12 +639,24 @@ version = "1.11.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.8"
|
||||
|
|
|
@ -11,3 +11,5 @@ encoding = "0.2"
|
|||
fixed = "0.5"
|
||||
readfilez = "0.2"
|
||||
string_cache = "0.8"
|
||||
thiserror = "1.0"
|
||||
prettytable = { version = "0.8", package = "prettytable-rs" }
|
||||
|
|
183
src/main.rs
183
src/main.rs
|
@ -1,78 +1,12 @@
|
|||
use chrono::naive::NaiveDate;
|
||||
use std::collections::HashSet;
|
||||
use string_cache::DefaultAtom;
|
||||
|
||||
/// simple typed helper enums
|
||||
mod simple_enums;
|
||||
use simple_enums::*;
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
enum KontoDaten {
|
||||
None,
|
||||
Old { knr: u64, blz: u32 },
|
||||
New { iban: String, bic: String },
|
||||
}
|
||||
|
||||
type TransactionValue = fixed::types::U21F11;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
struct TransactionLine {
|
||||
d_buchungs: NaiveDate,
|
||||
d_valuta: NaiveDate,
|
||||
// ignore 3. column = "Auftraggeber/Zahlungsempfänger",
|
||||
// because that should be nearly equivalent for every row
|
||||
p_other: DefaultAtom,
|
||||
konto_data: KontoDaten,
|
||||
verwendungszw: String,
|
||||
kref: String,
|
||||
waehrung: Waehrung,
|
||||
umsatz: TransactionValue,
|
||||
direction: TransactionDirection,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||
struct Transactions {
|
||||
pothc: HashSet<DefaultAtom>,
|
||||
elems: Vec<TransactionLine>,
|
||||
}
|
||||
|
||||
impl std::ops::Deref for Transactions {
|
||||
type Target = [TransactionLine];
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &[TransactionLine] {
|
||||
&self.elems[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl Transactions {
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.elems.is_empty()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.elems.len()
|
||||
}
|
||||
|
||||
pub fn push(&mut self, mut tl: TransactionLine) {
|
||||
if let Some(x) = self.pothc.get(&tl.p_other) {
|
||||
tl.p_other = x.clone();
|
||||
} else {
|
||||
self.pothc.insert(tl.p_other.clone());
|
||||
}
|
||||
self.elems.push(tl);
|
||||
}
|
||||
}
|
||||
mod transaction;
|
||||
|
||||
fn main() {
|
||||
use encoding::types::Encoding;
|
||||
use prettytable::{cell, format, row, Cell, Row, Table};
|
||||
use std::collections::HashMap;
|
||||
|
||||
for i in std::env::args().skip(1) {
|
||||
println!("F = {}", i);
|
||||
|
@ -112,57 +46,72 @@ fn main() {
|
|||
]
|
||||
);
|
||||
|
||||
println!("\nData:");
|
||||
let mut tmp = transaction::TransactionColl::new();
|
||||
|
||||
for result in recsit {
|
||||
let record = result.expect("got invalid line");
|
||||
assert_eq!(record.len(), 13);
|
||||
if record[1].is_empty() {
|
||||
// finalizer line -> ignore
|
||||
break;
|
||||
let record_bak = record.clone();
|
||||
let pres: Result<transaction::TransactionLine, _> =
|
||||
std::convert::TryInto::try_into(record);
|
||||
|
||||
match pres {
|
||||
Ok(tl) => tmp.push(tl),
|
||||
Err(transaction::ParseError::Finalizer) => break,
|
||||
Err(x) => panic!("got error '{}' @ {:?}", x, record_bak),
|
||||
}
|
||||
|
||||
// decode KontoDaten
|
||||
let r_e: &[u8] = &[
|
||||
record[4].is_empty() as u8,
|
||||
record[5].is_empty() as u8,
|
||||
record[6].is_empty() as u8,
|
||||
record[7].is_empty() as u8,
|
||||
];
|
||||
let konto_data = match &*r_e {
|
||||
&[0, 1, 0, 1] => KontoDaten::Old {
|
||||
knr: record[4].parse().expect("invalid Konto-Nr."),
|
||||
blz: record[6].parse().expect("invalid BLZ"),
|
||||
},
|
||||
&[1, 0, 1, 0] => KontoDaten::New {
|
||||
iban: record[5].to_string(),
|
||||
bic: record[7].to_string(),
|
||||
},
|
||||
&[1, 1, 1, 1] => KontoDaten::None,
|
||||
_ => unimplemented!(
|
||||
"unsupported KontoData encoding: {:?} :in: {:?}",
|
||||
&r_e,
|
||||
&record
|
||||
),
|
||||
};
|
||||
|
||||
let tl = TransactionLine {
|
||||
d_buchungs: NaiveDate::parse_from_str(&record[0], "%d.%m.%Y")
|
||||
.expect("invalid date format"),
|
||||
d_valuta: NaiveDate::parse_from_str(&record[1], "%d.%m.%Y")
|
||||
.expect("invalid date format"),
|
||||
p_other: DefaultAtom::from(&record[3]),
|
||||
konto_data,
|
||||
verwendungszw: record[8].to_string(),
|
||||
kref: record[9].to_string(),
|
||||
waehrung: record[10].parse().unwrap(),
|
||||
umsatz: record[11]
|
||||
.replace('.', "")
|
||||
.replace(',', ".")
|
||||
.parse()
|
||||
.expect("invalid Umsatz"),
|
||||
direction: record[12].parse().unwrap(),
|
||||
};
|
||||
println!("{:?}", tl);
|
||||
}
|
||||
|
||||
let dat = tmp.finish();
|
||||
|
||||
let mut accu =
|
||||
HashMap::<string_cache::DefaultAtom, (usize, transaction::TransactionValue)>::new();
|
||||
|
||||
let mut i_skipped = 0usize;
|
||||
for i in dat {
|
||||
if i.direction != simple_enums::TransactionDirection::Haben
|
||||
|| i.waehrung != simple_enums::Waehrung::EUR
|
||||
|| i.p_other.is_empty()
|
||||
|| i.p_other.find(" ZINS BIS ").is_some()
|
||||
{
|
||||
i_skipped += 1;
|
||||
continue;
|
||||
}
|
||||
let mut ent = accu.entry(i.p_other.clone()).or_default();
|
||||
ent.0 += 1;
|
||||
ent.1 += i.umsatz;
|
||||
}
|
||||
|
||||
println!("skipped {} entries", i_skipped);
|
||||
|
||||
if accu.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let mut table = Table::new();
|
||||
table.set_format(
|
||||
format::FormatBuilder::new()
|
||||
.column_separator('│')
|
||||
.borders('│')
|
||||
.separator(
|
||||
format::LinePosition::Top,
|
||||
format::LineSeparator::new('─', '┬', '┌', '┐'),
|
||||
)
|
||||
.separator(
|
||||
format::LinePosition::Bottom,
|
||||
format::LineSeparator::new('─', '┴', '└', '┘'),
|
||||
)
|
||||
.padding(1, 1)
|
||||
.build(),
|
||||
);
|
||||
|
||||
table.add_row(row!["Einzahler", "Zahlungen", "Summe"]);
|
||||
for (k, v) in accu {
|
||||
table.add_row(Row::new(vec![
|
||||
Cell::new(&*k),
|
||||
Cell::new(&v.0.to_string()),
|
||||
Cell::new(&v.1.to_string()),
|
||||
]));
|
||||
}
|
||||
|
||||
table.printstd();
|
||||
}
|
||||
}
|
||||
|
|
161
src/transaction.rs
Normal file
161
src/transaction.rs
Normal file
|
@ -0,0 +1,161 @@
|
|||
use crate::simple_enums::{TransactionDirection, Waehrung};
|
||||
use chrono::naive::NaiveDate;
|
||||
use std::collections::HashSet;
|
||||
use string_cache::DefaultAtom;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub enum KontoDaten {
|
||||
None,
|
||||
Old { knr: u64, blz: u32 },
|
||||
New { iban: String, bic: String },
|
||||
}
|
||||
|
||||
pub type TransactionValue = fixed::types::U21F11;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct TransactionLine {
|
||||
pub d_buchungs: NaiveDate,
|
||||
pub d_valuta: NaiveDate,
|
||||
// ignore 3. column = "Auftraggeber/Zahlungsempfänger",
|
||||
// because that should be nearly equivalent for every row
|
||||
pub p_other: DefaultAtom,
|
||||
pub konto_data: KontoDaten,
|
||||
pub verwendungszw: String,
|
||||
pub kref: String,
|
||||
pub waehrung: Waehrung,
|
||||
pub umsatz: TransactionValue,
|
||||
pub direction: TransactionDirection,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct TransactionColl {
|
||||
pothc: HashSet<DefaultAtom>,
|
||||
elems: Vec<TransactionLine>,
|
||||
}
|
||||
|
||||
impl std::ops::Deref for TransactionColl {
|
||||
type Target = [TransactionLine];
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &[TransactionLine] {
|
||||
&self.elems[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl TransactionColl {
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.elems.is_empty()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.elems.len()
|
||||
}
|
||||
|
||||
pub fn push(&mut self, mut tl: TransactionLine) {
|
||||
if let Some(x) = self.pothc.get(&tl.p_other) {
|
||||
tl.p_other = x.clone();
|
||||
} else {
|
||||
self.pothc.insert(tl.p_other.clone());
|
||||
}
|
||||
self.elems.push(tl);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn finish(self) -> Vec<TransactionLine> {
|
||||
self.elems
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
pub enum ParseError {
|
||||
#[error("invalid date")]
|
||||
Chrono(#[from] chrono::format::ParseError),
|
||||
|
||||
#[error("invalid H/S")]
|
||||
Direction(#[from] crate::simple_enums::parser_error::TransactionDirection),
|
||||
|
||||
#[error("finalizer line")]
|
||||
Finalizer,
|
||||
|
||||
#[error("invalid fixed-point number")]
|
||||
Fixed(fixed::ParseFixedError),
|
||||
|
||||
#[error("invalid integer")]
|
||||
Integer(#[from] std::num::ParseIntError),
|
||||
|
||||
#[error("unsupported KontoDaten encoding")]
|
||||
KontoDaten([bool; 4]),
|
||||
|
||||
#[error("invalid currency")]
|
||||
Waehrung(#[from] crate::simple_enums::parser_error::Waehrung),
|
||||
}
|
||||
|
||||
/// This impl block can be dropped after
|
||||
/// https://gitlab.com/tspiteri/fixed/issues/11
|
||||
/// is fixed.
|
||||
impl From<fixed::ParseFixedError> for ParseError {
|
||||
#[inline]
|
||||
fn from(x: fixed::ParseFixedError) -> ParseError {
|
||||
ParseError::Fixed(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<csv::StringRecord> for TransactionLine {
|
||||
type Error = ParseError;
|
||||
|
||||
fn try_from(record: csv::StringRecord) -> Result<Self, ParseError> {
|
||||
assert_eq!(record.len(), 13);
|
||||
if record[1].is_empty() {
|
||||
// finalizer line
|
||||
return Err(ParseError::Finalizer);
|
||||
}
|
||||
|
||||
// decode KontoDaten
|
||||
let r_e: &[u8] = &[
|
||||
record[4].is_empty() as u8,
|
||||
record[5].is_empty() as u8,
|
||||
record[6].is_empty() as u8,
|
||||
record[7].is_empty() as u8,
|
||||
];
|
||||
let konto_data = match &*r_e {
|
||||
&[0, 1, 0, 1] => KontoDaten::Old {
|
||||
knr: record[4].parse()?,
|
||||
blz: record[6].parse()?,
|
||||
},
|
||||
&[1, 0, 1, 0] => KontoDaten::New {
|
||||
iban: record[5].to_string(),
|
||||
bic: record[7].to_string(),
|
||||
},
|
||||
&[1, 1, 1, 1] => KontoDaten::None,
|
||||
_ => {
|
||||
return Err(ParseError::KontoDaten([
|
||||
r_e[0] != 0,
|
||||
r_e[1] != 0,
|
||||
r_e[2] != 0,
|
||||
r_e[3] != 0,
|
||||
]))
|
||||
}
|
||||
};
|
||||
|
||||
// assemble
|
||||
Ok(TransactionLine {
|
||||
d_buchungs: NaiveDate::parse_from_str(&record[0], "%d.%m.%Y")?,
|
||||
d_valuta: NaiveDate::parse_from_str(&record[1], "%d.%m.%Y")?,
|
||||
p_other: DefaultAtom::from(&record[3]),
|
||||
konto_data,
|
||||
verwendungszw: record[8].to_string(),
|
||||
kref: record[9].to_string(),
|
||||
waehrung: record[10].parse()?,
|
||||
umsatz: record[11].replace('.', "").replace(',', ".").parse()?,
|
||||
direction: record[12].parse()?,
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue