From 37917bbad2f5bc4e7daf34e713f7c310db5d8e5e Mon Sep 17 00:00:00 2001 From: scoobybejesus Date: Thu, 19 Oct 2023 17:05:32 -0400 Subject: [PATCH] Removed decimal in favor of rust_decimal. Point version bump. --- Cargo.lock | 403 +++++++++++++++++++++++-- Cargo.toml | 5 +- crptls/Cargo.toml | 5 +- crptls/src/account.rs | 73 ++--- crptls/src/create_lots_mvmts.rs | 216 ++++++------- crptls/src/csv_import_accts_txns.rs | 117 +++---- crptls/src/decimal_utils.rs | 14 +- crptls/src/import_cost_proceeds_etc.rs | 31 +- crptls/src/tests/test.rs | 55 ++-- crptls/src/transaction.rs | 15 +- src/export/export_csv.rs | 98 +++--- src/export/export_je.rs | 51 ++-- src/export/export_txt.rs | 27 +- 13 files changed, 737 insertions(+), 373 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9472552..4b462b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,28 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if 1.0.0", + "once_cell", + "version_check", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -26,6 +48,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + [[package]] name = "atty" version = "0.2.14" @@ -55,12 +83,97 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "borsh" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" +dependencies = [ + "borsh-derive", + "hashbrown 0.13.2", +] + +[[package]] +name = "borsh-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" +dependencies = [ + "borsh-derive-internal", + "borsh-schema-derive-internal", + "proc-macro-crate", + "proc-macro2 1.0.69", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" +dependencies = [ + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" +dependencies = [ + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 1.0.109", +] + [[package]] name = "bumpalo" version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +[[package]] +name = "bytecheck" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" +dependencies = [ + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + [[package]] name = "cassowary" version = "0.3.0" @@ -137,11 +250,12 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "crptls" -version = "0.2.0" +version = "0.2.1" dependencies = [ "chrono", "csv", - "decimal", + "rust_decimal", + "rust_decimal_macros", "serde", "serde_derive", "time", @@ -149,13 +263,14 @@ dependencies = [ [[package]] name = "cryptools" -version = "0.12.0" +version = "0.12.1" dependencies = [ "chrono", "crptls", "csv", - "decimal", "dotenv", + "rust_decimal", + "rust_decimal_macros", "rustyline", "structopt", "termion", @@ -183,20 +298,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "decimal" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a8ab77e91baeb15034c3be91e87bff4665c9036216148e4996d9a9f5792114d" -dependencies = [ - "bitflags 1.3.2", - "cc", - "libc", - "ord_subset", - "rustc-serialize", - "serde", -] - [[package]] name = "deranged" version = "0.3.9" @@ -255,6 +356,41 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.6", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.3", +] + [[package]] name = "heck" version = "0.3.1" @@ -397,18 +533,27 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" -[[package]] -name = "ord_subset" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ce14664caf5b27f5656ff727defd68ae1eb75ef3c4d95259361df1eb376bef" - [[package]] name = "powerfmt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] + [[package]] name = "proc-macro2" version = "0.4.30" @@ -427,6 +572,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 1.0.109", +] + [[package]] name = "quote" version = "0.6.13" @@ -445,6 +610,12 @@ dependencies = [ "proc-macro2 1.0.69", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "radix_trie" version = "0.2.1" @@ -455,6 +626,36 @@ dependencies = [ "nibble_vec", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "redox_syscall" version = "0.1.57" @@ -471,10 +672,67 @@ dependencies = [ ] [[package]] -name = "rustc-serialize" -version = "0.3.24" +name = "rend" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" +dependencies = [ + "bytecheck", +] + +[[package]] +name = "rkyv" +version = "0.7.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58" +dependencies = [ + "bitvec", + "bytecheck", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d" +dependencies = [ + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "rust_decimal" +version = "1.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c4216490d5a413bc6d10fa4742bd7d4955941d062c0ef873141d6b0e7b30fd" +dependencies = [ + "arrayvec", + "borsh", + "bytes", + "num-traits", + "rand", + "rkyv", + "serde", + "serde_json", +] + +[[package]] +name = "rust_decimal_macros" +version = "1.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86444b802de0b10ac5e563b5ddb43b541b9705de4e01a50e82194d2b183c1835" +dependencies = [ + "quote 1.0.33", + "rust_decimal", +] [[package]] name = "rustix" @@ -524,6 +782,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + [[package]] name = "serde" version = "1.0.189" @@ -544,6 +808,23 @@ dependencies = [ "syn 2.0.38", ] +[[package]] +name = "serde_json" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "simdutf8" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" + [[package]] name = "smallvec" version = "1.11.1" @@ -595,6 +876,17 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2 1.0.69", + "quote 1.0.33", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.38" @@ -606,6 +898,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "termion" version = "1.5.5" @@ -645,6 +943,30 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "tui" version = "0.8.0" @@ -691,12 +1013,30 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "uuid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" + [[package]] name = "vec_map" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wasm-bindgen" version = "0.2.87" @@ -847,3 +1187,12 @@ name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] diff --git a/Cargo.toml b/Cargo.toml index a9d8216..8b3a20a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cryptools" -version = "0.12.0" +version = "0.12.1" authors = ["scoobybejesus "] edition = "2018" description = "Command-line utility for processing cryptocurrency transactions into 'lots' and 'movements'." @@ -21,7 +21,8 @@ path = "src/main.rs" [dependencies] crptls = { path = "crptls" } csv = "1.3.0" -decimal = "2.1.0" +rust_decimal = "1.32" +rust_decimal_macros = "1.32" chrono = { version = "0.4.31", features = ["serde"] } structopt = "0.2.10" rustyline = "12.0.0" diff --git a/crptls/Cargo.toml b/crptls/Cargo.toml index 9211f25..c8e40fc 100644 --- a/crptls/Cargo.toml +++ b/crptls/Cargo.toml @@ -1,11 +1,12 @@ [package] name = "crptls" -version = "0.2.0" +version = "0.2.1" authors = ["scoobybejesus "] edition = "2018" [dependencies] -decimal = "2.1.0" +rust_decimal = "1.32" +rust_decimal_macros = "1.32" chrono = { version = "0.4.31", features = ["serde"] } csv = "1.3.0" serde = { version = "1.0.189", features = ["derive"] } diff --git a/crptls/src/account.rs b/crptls/src/account.rs index c92e404..cebfede 100644 --- a/crptls/src/account.rs +++ b/crptls/src/account.rs @@ -8,7 +8,8 @@ use std::collections::HashMap; use std::error::Error; use chrono::NaiveDate; -use decimal::d128; +use rust_decimal::Decimal; +use rust_decimal_macros::dec; use serde_derive::{Serialize, Deserialize}; use crate::transaction::{Transaction, ActionRecord, Polarity, TxType}; @@ -44,9 +45,9 @@ pub struct Account { impl Account { - pub fn get_sum_of_amts_in_lots(&self) -> d128 { + pub fn get_sum_of_amts_in_lots(&self) -> Decimal { let lots = self.list_of_lots.borrow(); - let mut total_amount = d128!(0); + let mut total_amount = dec!(0); for lot in lots.iter() { let sum = lot.get_sum_of_amts_in_lot(); total_amount += sum; @@ -54,9 +55,9 @@ impl Account { total_amount } - pub fn get_sum_of_lk_basis_in_lots(&self) -> d128 { + pub fn get_sum_of_lk_basis_in_lots(&self) -> Decimal { let lots = self.list_of_lots.borrow(); - let mut total_amount = d128!(0); + let mut total_amount = dec!(0); for lot in lots.iter() { let sum = lot.get_sum_of_lk_basis_in_lot(); total_amount += sum; @@ -64,9 +65,9 @@ impl Account { total_amount } - pub fn get_sum_of_orig_basis_in_lots(&self) -> d128 { + pub fn get_sum_of_orig_basis_in_lots(&self) -> Decimal { let lots = self.list_of_lots.borrow(); - let mut total_amount = d128!(0); + let mut total_amount = dec!(0); for lot in lots.iter() { let sum = lot.get_sum_of_orig_basis_in_lot(); total_amount += sum; @@ -79,7 +80,7 @@ impl Account { let mut count = 0; for lot in self.list_of_lots.borrow().iter() { - if lot.get_sum_of_amts_in_lot() > d128!(0) { + if lot.get_sum_of_amts_in_lot() > dec!(0) { count += 1 } } @@ -102,20 +103,20 @@ pub struct Lot { } impl Lot { - pub fn get_sum_of_amts_in_lot(&self) -> d128 { - let mut amts = d128!(0); + pub fn get_sum_of_amts_in_lot(&self) -> Decimal { + let mut amts = dec!(0); self.movements.borrow().iter().for_each(|movement| amts += movement.amount); amts } - pub fn get_sum_of_lk_basis_in_lot(&self) -> d128 { - let mut amts = d128!(0); + pub fn get_sum_of_lk_basis_in_lot(&self) -> Decimal { + let mut amts = dec!(0); self.movements.borrow().iter().for_each(|movement| amts += movement.cost_basis_lk.get()); amts } - pub fn get_sum_of_orig_basis_in_lot(&self) -> d128 { - let mut amts = d128!(0); + pub fn get_sum_of_orig_basis_in_lot(&self) -> Decimal { + let mut amts = dec!(0); self.movements.borrow().iter().for_each(|movement| amts += movement.cost_basis.get()); amts } @@ -123,18 +124,18 @@ impl Lot { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Movement { - pub amount: d128, + pub amount: Decimal, pub date_as_string: String, pub date: NaiveDate, pub transaction_key: u32, pub action_record_key: u32, - pub cost_basis: Cell, // Initialized with 0. Set in add_cost_basis_to_movements() - pub ratio_of_amt_to_incoming_mvmts_in_a_r: d128, // Set in process_multiple_incoming_lots_and_mvmts() and incoming flow dual actionrecord transactions - pub ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell, // Set in wrap_mvmt_and_push() + pub cost_basis: Cell, // Initialized with 0. Set in add_cost_basis_to_movements() + pub ratio_of_amt_to_incoming_mvmts_in_a_r: Decimal, // Set in process_multiple_incoming_lots_and_mvmts() and incoming flow dual actionrecord transactions + pub ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell, // Set in wrap_mvmt_and_push() pub lot_num: u32, - pub proceeds: Cell, // Initialized with 0. Set in add_proceeds_to_movements() - pub proceeds_lk: Cell, - pub cost_basis_lk: Cell, + pub proceeds: Cell, // Initialized with 0. Set in add_proceeds_to_movements() + pub proceeds_lk: Cell, + pub cost_basis_lk: Cell, } impl Movement { @@ -154,7 +155,7 @@ impl Movement { &self, acct_map: &HashMap, ar_map: &HashMap - ) -> d128 { + ) -> Decimal { let lot = self.get_lot(acct_map, ar_map); let list_of_lot_mvmts = lot.movements.borrow(); @@ -167,7 +168,7 @@ impl Movement { &self, acct_map: &HashMap, ar_map: &HashMap - ) -> d128 { + ) -> Decimal { let lot = self.get_lot(acct_map, ar_map); let list_of_lot_mvmts = lot.movements.borrow(); @@ -180,7 +181,7 @@ impl Movement { &self, acct_map: &HashMap, ar_map: &HashMap - ) -> d128 { + ) -> Decimal { let lot = self.get_lot(acct_map, ar_map); let list_of_lot_mvmts = lot.movements.borrow(); @@ -189,11 +190,11 @@ impl Movement { cost_basis } - pub fn get_lk_gain_or_loss(&self) -> d128 { + pub fn get_lk_gain_or_loss(&self) -> Decimal { self.proceeds_lk.get() + self.cost_basis_lk.get() } - pub fn get_orig_gain_or_loss(&self) -> d128 { + pub fn get_orig_gain_or_loss(&self) -> Decimal { self.proceeds.get() + self.cost_basis.get() } @@ -255,7 +256,7 @@ impl Movement { raw_accts: &HashMap, acct_map: &HashMap, txns_map: &HashMap, - )-> Result> { // Returns 0 or positive number + )-> Result> { // Returns 0 or positive number let txn = txns_map.get(&self.transaction_key).expect("Couldn't get txn. Tx num invalid?"); @@ -268,10 +269,10 @@ impl Movement { if ar.direction() == Polarity::Incoming { Ok(-self.proceeds_lk.get()) } - else { Ok(d128!(0)) } + else { Ok(dec!(0)) } } - TxType::Exchange => { Ok(d128!(0)) } - TxType::ToSelf => { Ok(d128!(0)) } + TxType::Exchange => { Ok(dec!(0)) } + TxType::ToSelf => { Ok(dec!(0)) } } } @@ -281,7 +282,7 @@ impl Movement { raw_accts: &HashMap, acct_map: &HashMap, txns_map: &HashMap, - )-> Result> { // Returns 0 or negative number + )-> Result> { // Returns 0 or negative number let txn = txns_map.get(&self.transaction_key).expect("Couldn't get txn. Tx num invalid?"); @@ -298,7 +299,7 @@ impl Movement { if raw_acct.is_margin { - Ok(d128!(0)) + Ok(dec!(0)) } else { @@ -306,10 +307,10 @@ impl Movement { Ok(expense) } } - else { Ok(d128!(0)) } + else { Ok(dec!(0)) } } - TxType::Exchange => { Ok(d128!(0)) } - TxType::ToSelf => { Ok(d128!(0)) } + TxType::Exchange => { Ok(dec!(0)) } + TxType::ToSelf => { Ok(dec!(0)) } } } @@ -325,7 +326,7 @@ impl Movement { let direction: String; - if self.amount > d128!(0) { + if self.amount > dec!(0) { direction = "In".to_string(); } else { direction = "Out".to_string() diff --git a/crptls/src/create_lots_mvmts.rs b/crptls/src/create_lots_mvmts.rs index 0075ae8..105618b 100644 --- a/crptls/src/create_lots_mvmts.rs +++ b/crptls/src/create_lots_mvmts.rs @@ -6,7 +6,8 @@ use std::cell::{RefCell, Ref, Cell}; use std::collections::HashMap; use std::error::Error; -use decimal::d128; +use rust_decimal::Decimal; +use rust_decimal_macros::dec; use crate::core_functions::ImportProcessParameters; use crate::transaction::{Transaction, ActionRecord, TxType, Polarity, TxHasMargin}; @@ -118,8 +119,8 @@ pub(crate) fn create_lots_and_movements( if !base_acct_lot_list.is_empty() && !quote_acct_lot_list.is_empty() { // Since we know there has been activity, we set the bool variable above according to whether the `account` // balances are both zero. - let base_balance_is_zero = base_acct_lot_list.last().unwrap().get_sum_of_amts_in_lot() == d128!(0); - let quote_balance_is_zero = quote_acct_lot_list.last().unwrap().get_sum_of_amts_in_lot() == d128!(0); + let base_balance_is_zero = base_acct_lot_list.last().unwrap().get_sum_of_amts_in_lot() == dec!(0); + let quote_balance_is_zero = quote_acct_lot_list.last().unwrap().get_sum_of_amts_in_lot() == dec!(0); if base_balance_is_zero && quote_balance_is_zero { acct_balances_are_zero = true } else { @@ -180,13 +181,13 @@ pub(crate) fn create_lots_and_movements( date: txn.date, transaction_key: txn_num, action_record_key: base_ar_idx, - cost_basis: Cell::new(d128!(0.0)), - ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0), - ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)), + cost_basis: Cell::new(dec!(0.0)), + ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0), + ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)), lot_num: base_lot.lot_number, - proceeds: Cell::new(d128!(0.0)), - proceeds_lk: Cell::new(d128!(0.0)), - cost_basis_lk: Cell::new(d128!(0.0)), + proceeds: Cell::new(dec!(0.0)), + proceeds_lk: Cell::new(dec!(0.0)), + cost_basis_lk: Cell::new(dec!(0.0)), }; let raw_base_acct = raw_acct_map.get(&base_acct.raw_key).unwrap(); wrap_mvmt_and_push( @@ -203,13 +204,13 @@ pub(crate) fn create_lots_and_movements( date: txn.date, transaction_key: txn_num, action_record_key: quote_ar_idx, - cost_basis: Cell::new(d128!(0.0)), - ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0), - ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)), + cost_basis: Cell::new(dec!(0.0)), + ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0), + ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)), lot_num: quote_lot.lot_number, - proceeds: Cell::new(d128!(0.0)), - proceeds_lk: Cell::new(d128!(0.0)), - cost_basis_lk: Cell::new(d128!(0.0)), + proceeds: Cell::new(dec!(0.0)), + proceeds_lk: Cell::new(dec!(0.0)), + cost_basis_lk: Cell::new(dec!(0.0)), }; let raw_quote_acct = raw_acct_map.get("e_acct.raw_key).unwrap(); wrap_mvmt_and_push( @@ -274,13 +275,13 @@ pub(crate) fn create_lots_and_movements( date: txn.date, transaction_key: txn_num, action_record_key: *ar_num, - cost_basis: Cell::new(d128!(0.0)), - ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0), - ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)), + cost_basis: Cell::new(dec!(0.0)), + ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0), + ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)), lot_num: lot.lot_number, - proceeds: Cell::new(d128!(0.0)), - proceeds_lk: Cell::new(d128!(0.0)), - cost_basis_lk: Cell::new(d128!(0.0)), + proceeds: Cell::new(dec!(0.0)), + proceeds_lk: Cell::new(dec!(0.0)), + cost_basis_lk: Cell::new(dec!(0.0)), }; wrap_mvmt_and_push( whole_mvmt, @@ -328,13 +329,13 @@ pub(crate) fn create_lots_and_movements( date: txn.date, transaction_key: txn_num, action_record_key: *ar_num, - cost_basis: Cell::new(d128!(0.0)), - ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0), - ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)), + cost_basis: Cell::new(dec!(0.0)), + ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0), + ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)), lot_num: lot.lot_number, - proceeds: Cell::new(d128!(0.0)), - proceeds_lk: Cell::new(d128!(0.0)), - cost_basis_lk: Cell::new(d128!(0.0)), + proceeds: Cell::new(dec!(0.0)), + proceeds_lk: Cell::new(dec!(0.0)), + cost_basis_lk: Cell::new(dec!(0.0)), }; wrap_mvmt_and_push( whole_mvmt, @@ -441,13 +442,13 @@ pub(crate) fn create_lots_and_movements( date: txn.date, transaction_key: txn_num, action_record_key: *ar_num, - cost_basis: Cell::new(d128!(0.0)), - ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0), - ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)), + cost_basis: Cell::new(dec!(0.0)), + ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0), + ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)), lot_num: lot_to_use.lot_number, - proceeds: Cell::new(d128!(0.0)), - proceeds_lk: Cell::new(d128!(0.0)), - cost_basis_lk: Cell::new(d128!(0.0)), + proceeds: Cell::new(dec!(0.0)), + proceeds_lk: Cell::new(dec!(0.0)), + cost_basis_lk: Cell::new(dec!(0.0)), }; // Just a last minute check that a home currency `action record` isn't being handled here @@ -507,13 +508,13 @@ pub(crate) fn create_lots_and_movements( date: txn.date, transaction_key: txn_num, action_record_key: *ar_num, - cost_basis: Cell::new(d128!(0.0)), - ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0), - ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)), + cost_basis: Cell::new(dec!(0.0)), + ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0), + ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)), lot_num: lot.lot_number, - proceeds: Cell::new(d128!(0.0)), - proceeds_lk: Cell::new(d128!(0.0)), - cost_basis_lk: Cell::new(d128!(0.0)), + proceeds: Cell::new(dec!(0.0)), + proceeds_lk: Cell::new(dec!(0.0)), + cost_basis_lk: Cell::new(dec!(0.0)), }; wrap_mvmt_and_push( mvmt, @@ -553,13 +554,13 @@ pub(crate) fn create_lots_and_movements( date: txn.date, transaction_key: txn_num, action_record_key: *ar_num, - cost_basis: Cell::new(d128!(0.0)), - ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0), - ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)), + cost_basis: Cell::new(dec!(0.0)), + ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0), + ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)), lot_num: lot.lot_number, - proceeds: Cell::new(d128!(0.0)), - proceeds_lk: Cell::new(d128!(0.0)), - cost_basis_lk: Cell::new(d128!(0.0)), + proceeds: Cell::new(dec!(0.0)), + proceeds_lk: Cell::new(dec!(0.0)), + cost_basis_lk: Cell::new(dec!(0.0)), }; // The more complicated case is the dual-`action record` `flow` `transaction`. @@ -582,7 +583,7 @@ pub(crate) fn create_lots_and_movements( // of the margin trade that is now ending in a profit. And `total_positive_amounts` accounts for the total // amount of those margin-buys. let mut positive_mvmt_list: Vec> = [].to_vec(); - let mut total_positive_amounts = d128!(0); + let mut total_positive_amounts = dec!(0); // This is necessary to find the base account, because the margin-buys are reflected in this account. let (base_acct_key, quote_acct_key) = get_base_and_quote_acct_for_dual_actionrecord_flow_tx( @@ -598,7 +599,7 @@ pub(crate) fn create_lots_and_movements( // It should be apparent that the relevant `lot` has been selected, and its `movement` are now iterated // over for capturing its `movement`s (for their date) and adding up their amounts. for base_acct_mvmt in base_acct_lot.movements.borrow().iter() { - if base_acct_mvmt.amount > d128!(0) { + if base_acct_mvmt.amount > dec!(0) { // println!("In lot# {}, positive mvmt amount: {} {},", // base_acct_lot.lot_number, // mvmt.borrow().amount, @@ -610,8 +611,8 @@ pub(crate) fn create_lots_and_movements( // These variables track relevant usage in the following for-loop. These are used after the for-loop // when creating the final `movement`. - let mut amounts_used = d128!(0); - let mut percentages_used = d128!(0); + let mut amounts_used = dec!(0); + let mut percentages_used = dec!(0); // Here, the margin-buys are iterated over while creating proportionally-sized new `movement`s. // Note that this for-loop excludes the final positive `movement` because rounding must be taken into @@ -637,13 +638,13 @@ pub(crate) fn create_lots_and_movements( date: txn.date, transaction_key: txn_num, action_record_key: *ar_num, - cost_basis: Cell::new(d128!(0.0)), + cost_basis: Cell::new(dec!(0.0)), ratio_of_amt_to_incoming_mvmts_in_a_r: percentage_used, - ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)), + ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)), lot_num: inner_lot.lot_number, - proceeds: Cell::new(d128!(0.0)), - proceeds_lk: Cell::new(d128!(0.0)), - cost_basis_lk: Cell::new(d128!(0.0)), + proceeds: Cell::new(dec!(0.0)), + proceeds_lk: Cell::new(dec!(0.0)), + cost_basis_lk: Cell::new(dec!(0.0)), }; wrap_mvmt_and_push( inner_mvmt, @@ -677,13 +678,13 @@ pub(crate) fn create_lots_and_movements( date: txn.date, transaction_key: txn_num, action_record_key: *ar_num, - cost_basis: Cell::new(d128!(0.0)), - ratio_of_amt_to_incoming_mvmts_in_a_r: round_d128_1e8(&(d128!(1.0) - percentages_used)), - ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)), + cost_basis: Cell::new(dec!(0.0)), + ratio_of_amt_to_incoming_mvmts_in_a_r: round_d128_1e8(&(dec!(1.0) - percentages_used)), + ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)), lot_num: lot.lot_number, - proceeds: Cell::new(d128!(0.0)), - proceeds_lk: Cell::new(d128!(0.0)), - cost_basis_lk: Cell::new(d128!(0.0)), + proceeds: Cell::new(dec!(0.0)), + proceeds_lk: Cell::new(dec!(0.0)), + cost_basis_lk: Cell::new(dec!(0.0)), }; // Back to "base case" style treatment, if this is an incoming dual-`action record` `flow` `transaction`, but either @@ -706,13 +707,13 @@ pub(crate) fn create_lots_and_movements( date: txn.date, transaction_key: txn_num, action_record_key: *ar_num, - cost_basis: Cell::new(d128!(0.0)), - ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0), - ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)), + cost_basis: Cell::new(dec!(0.0)), + ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0), + ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)), lot_num: lot.lot_number, - proceeds: Cell::new(d128!(0.0)), - proceeds_lk: Cell::new(d128!(0.0)), - cost_basis_lk: Cell::new(d128!(0.0)), + proceeds: Cell::new(dec!(0.0)), + proceeds_lk: Cell::new(dec!(0.0)), + cost_basis_lk: Cell::new(dec!(0.0)), }; } } @@ -781,13 +782,13 @@ pub(crate) fn create_lots_and_movements( date: txn.date, transaction_key: txn_num, action_record_key: *ar_num, - cost_basis: Cell::new(d128!(0.0)), - ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0), - ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)), + cost_basis: Cell::new(dec!(0.0)), + ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0), + ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)), lot_num: lot.lot_number, - proceeds: Cell::new(d128!(0.0)), - proceeds_lk: Cell::new(d128!(0.0)), - cost_basis_lk: Cell::new(d128!(0.0)), + proceeds: Cell::new(dec!(0.0)), + proceeds_lk: Cell::new(dec!(0.0)), + cost_basis_lk: Cell::new(dec!(0.0)), }; } } @@ -811,13 +812,13 @@ pub(crate) fn create_lots_and_movements( date: txn.date, transaction_key: txn_num, action_record_key: *ar_num, - cost_basis: Cell::new(d128!(0.0)), - ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0), - ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)), + cost_basis: Cell::new(dec!(0.0)), + ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0), + ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)), lot_num: lot.lot_number, - proceeds: Cell::new(d128!(0.0)), - proceeds_lk: Cell::new(d128!(0.0)), - cost_basis_lk: Cell::new(d128!(0.0)), + proceeds: Cell::new(dec!(0.0)), + proceeds_lk: Cell::new(dec!(0.0)), + cost_basis_lk: Cell::new(dec!(0.0)), }; } // The `lot` and `whole_mvmt` variables have been initialized/assigned @@ -960,7 +961,7 @@ fn wrap_mvmt_and_push( /// that was pushed to the previous `lot`), and recursively check... fn fit_into_lots( mvmt_to_fit: Movement, - amt_to_fit: d128, + amt_to_fit: Decimal, list_of_lots_to_use: RefCell>>, vec_of_ordered_index_values: Vec, index_position: usize, @@ -978,7 +979,7 @@ fn fit_into_lots( if vec_of_ordered_index_values.len() == current_index_position { println!("FATAL: Txn {} on {} spending {} {} has run out of lots to spend from.", mvmt_to_fit.transaction_key, mvmt_to_fit.date_as_string, ar.amount, raw_acct.ticker); - let bal = if acct.get_sum_of_amts_in_lots() == d128!(0) { "0.00000000".to_string() } + let bal = if acct.get_sum_of_amts_in_lots() == dec!(0) { "0.00000000".to_string() } else { acct.get_sum_of_amts_in_lots().to_string() }; println!("Account balance is only: {}", bal); std::process::exit(1); @@ -987,15 +988,15 @@ fn fit_into_lots( // Get the `lot`, and then get its balance to see how much room there is let lot_index = vec_of_ordered_index_values[current_index_position]; let lot = acct.list_of_lots.borrow()[lot_index].clone(); - let mut sum_of_mvmts_in_lot: d128 = d128!(0.0); + let mut sum_of_mvmts_in_lot: Decimal = dec!(0.0); for movement in lot.movements.borrow().iter() { sum_of_mvmts_in_lot += movement.amount; } - assert!(sum_of_mvmts_in_lot >= d128!(0.0)); + assert!(sum_of_mvmts_in_lot >= dec!(0.0)); // If the `lot` is "full", try the next. - if sum_of_mvmts_in_lot == d128!(0.0) { + if sum_of_mvmts_in_lot == dec!(0.0) { current_index_position += 1; @@ -1013,15 +1014,15 @@ fn fit_into_lots( return; } - assert!(sum_of_mvmts_in_lot > d128!(0.0)); + assert!(sum_of_mvmts_in_lot > dec!(0.0)); // If `remainder_amt_to_recurse` is positive, it means the `lot` balance exceeded `amt_to_fit`, // therefore, the amount completely fits in the `lot`. If negative, it is passed as the `amt_to_fit` // for the next round of recursion. - let remainder_amt_to_recurse = (amt_to_fit + sum_of_mvmts_in_lot).reduce(); + let remainder_amt_to_recurse = (amt_to_fit + sum_of_mvmts_in_lot).round_dp(8); // If the remainder fits, the `movement` is wrapped/pushed, and the recursion is complete. - if remainder_amt_to_recurse >= d128!(0.0) { + if remainder_amt_to_recurse >= dec!(0.0) { let remainder_mvmt_that_fits: Movement = Movement { amount: amt_to_fit, @@ -1040,7 +1041,7 @@ fn fit_into_lots( // The amt_to_fit doesn't completely fit in the present `lot`, but some does. Create a `movement` that will fit. let mvmt_that_fits_in_lot: Movement = Movement { - amount: (-sum_of_mvmts_in_lot).reduce(), + amount: (-sum_of_mvmts_in_lot).round_dp(8), lot_num: lot.lot_number, ..mvmt_to_fit.clone() }; @@ -1057,7 +1058,7 @@ fn fit_into_lots( // After applying some of the `amt_to_fit` to the `lot`, increment the index, take the remainder, and recurse fit_into_lots( mvmt_to_fit, - remainder_amt_to_recurse.reduce(), // This was updated before recursing + remainder_amt_to_recurse.round_dp(8), // This was updated before recursing list_of_lots_to_use, vec_of_ordered_index_values, current_index_position, // This was updated before recursing @@ -1082,13 +1083,12 @@ fn process_multiple_incoming_lots_and_mvmts( raw_acct: &RawAccount, ) { - let round_to_places = d128::from(1).scaleb(d128::from(-8)); let txn = txns_map.get(&txn_num).expect("Couldn't get txn. Tx num invalid?"); let acct_of_incoming_ar = acct_map.get(&incoming_ar.account_key).unwrap(); - let mut all_but_last_incoming_mvmt_amt = d128!(0.0); - let mut all_but_last_incoming_mvmt_ratio = d128!(0.0); + let mut all_but_last_incoming_mvmt_amt = dec!(0.0); + let mut all_but_last_incoming_mvmt_ratio = dec!(0.0); // println!("Txn date: {}. Outgoing mvmts: {}, Outgoing amount: {}", txn.date, outgoing_ar.movements.borrow().len(), outgoing_ar.amount); let list_of_mvmts_of_outgoing_ar = outgoing_ar.get_mvmts_in_ar_in_lot_date_order(acct_map, txns_map); let list_of_mvmts_of_outgoing_ar_len = list_of_mvmts_of_outgoing_ar.len(); @@ -1099,10 +1099,10 @@ fn process_multiple_incoming_lots_and_mvmts( // println!("Ratio of outgoing amt to total actionrecord amt: {:.8}", ratio_of_outgoing_to_total_ar); let tentative_incoming_amt = ratio_of_outgoing_mvmt_to_total_ar * incoming_ar.amount; // println!("Unrounded incoming amt: {}", tentative_incoming_amt); - let corresponding_incoming_amt = tentative_incoming_amt.quantize(round_to_places); + let corresponding_incoming_amt = tentative_incoming_amt.round_dp(8); // println!("Rounded incoming amt: {}", corresponding_incoming_amt); - if corresponding_incoming_amt == d128!(0) { continue } // Due to rounding, this could be zero. - assert!(corresponding_incoming_amt > d128!(0.0)); + if corresponding_incoming_amt == dec!(0) { continue } // Due to rounding, this could be zero. + assert!(corresponding_incoming_amt > dec!(0.0)); let this_acct = acct_of_incoming_ar; let length_of_list_of_lots: usize = this_acct.list_of_lots.borrow().len(); let inherited_date = outgoing_mvmt.get_lot(acct_map, ar_map).date_of_first_mvmt_in_lot; @@ -1119,18 +1119,18 @@ fn process_multiple_incoming_lots_and_mvmts( ) ; let incoming_mvmt = Movement { - amount: corresponding_incoming_amt.reduce(), + amount: corresponding_incoming_amt.round_dp(8), date_as_string: txn.date_as_string.clone(), date: txn.date, transaction_key: txn_num, action_record_key: incoming_ar.self_ar_key, - cost_basis: Cell::new(d128!(0.0)), + cost_basis: Cell::new(dec!(0.0)), ratio_of_amt_to_incoming_mvmts_in_a_r: round_d128_1e8(&ratio_of_outgoing_mvmt_to_total_ar), - ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)), + ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)), lot_num: inner_lot.lot_number, - proceeds: Cell::new(d128!(0.0)), - proceeds_lk: Cell::new(d128!(0.0)), - cost_basis_lk: Cell::new(d128!(0.0)), + proceeds: Cell::new(dec!(0.0)), + proceeds_lk: Cell::new(dec!(0.0)), + cost_basis_lk: Cell::new(dec!(0.0)), }; // println!("From first set of incoming movements, amount: {} {} to account: {}", // incoming_mvmt.amount, acct_incoming_ar.ticker, acct_incoming_ar.account_num); @@ -1147,7 +1147,7 @@ fn process_multiple_incoming_lots_and_mvmts( } // Second iteration, for final movement let corresponding_incoming_amt = incoming_ar.amount - all_but_last_incoming_mvmt_amt; - assert!(corresponding_incoming_amt > d128!(0.0)); + assert!(corresponding_incoming_amt > dec!(0.0)); let this_acct = acct_of_incoming_ar; let length_of_list_of_lots = this_acct.list_of_lots.borrow().len(); let inherited_date = final_og_mvmt.get_lot(acct_map, ar_map).date_of_first_mvmt_in_lot; @@ -1164,18 +1164,18 @@ fn process_multiple_incoming_lots_and_mvmts( ) ; let incoming_mvmt = Movement { - amount: corresponding_incoming_amt.reduce(), + amount: corresponding_incoming_amt.round_dp(8), date_as_string: txn.date_as_string.clone(), date: txn.date, transaction_key: txn_num, action_record_key: incoming_ar.self_ar_key, - cost_basis: Cell::new(d128!(0.0)), - ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0) - all_but_last_incoming_mvmt_ratio, - ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)), + cost_basis: Cell::new(dec!(0.0)), + ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0) - all_but_last_incoming_mvmt_ratio, + ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)), lot_num: lot.lot_number, - proceeds: Cell::new(d128!(0.0)), - proceeds_lk: Cell::new(d128!(0.0)), - cost_basis_lk: Cell::new(d128!(0.0)), + proceeds: Cell::new(dec!(0.0)), + proceeds_lk: Cell::new(dec!(0.0)), + cost_basis_lk: Cell::new(dec!(0.0)), }; // println!("Final incoming mvmt for this actionrecord, amount: {} {} to account: {}", // incoming_mvmt.amount, acct_incoming_ar.ticker, acct_incoming_ar.account_num); diff --git a/crptls/src/csv_import_accts_txns.rs b/crptls/src/csv_import_accts_txns.rs index 81fd826..fb2f00a 100644 --- a/crptls/src/csv_import_accts_txns.rs +++ b/crptls/src/csv_import_accts_txns.rs @@ -9,7 +9,8 @@ use std::collections::HashMap; use std::path::PathBuf; use chrono::NaiveDate; -use decimal::d128; +use rust_decimal::Decimal; +use rust_decimal_macros::dec; use crate::transaction::{Transaction, ActionRecord}; use crate::account::{Account, RawAccount}; @@ -193,24 +194,30 @@ fn import_transactions( let account_key = acct_idx as u16; let amount_str = field.replace(",", ""); - let mut amount = amount_str.parse::().unwrap(); + let amount = match amount_str.parse::() { + Ok(x) => x, + Err(e) => { + println!("FATAL: Couldn't convert amount to d128 for transaction:\n{:#?}", record); + println!("Error: {}", e); + std::process::exit(1);} + }; // When parsing to a d128, it won't error; rather it'll return a NaN. It must now check for NaN, // and, if found, attempt to sanitize. These checks will convert accounting/comma format to the expected // format by removing parentheses from negatives and adding a minus sign in the front. It will also // attempt to remove empty spaces and currency symbols or designations (e.g. $ or USD). - if amount.is_nan() { - let b = sanitize_string_for_d128_parsing_basic(field).parse::().unwrap(); - amount = b; - }; - if amount.is_nan() { - let c = sanitize_string_for_d128_parsing_full(field).parse::().unwrap(); - amount = c; - }; - if amount.is_nan() { - println!("FATAL: Couldn't convert amount to d128 for transaction:\n{:#?}", record); - std::process::exit(1); - } + // if amount.is_none() { + // let b = sanitize_string_for_d128_parsing_basic(field).parse::().unwrap(); + // amount = b; + // }; + // if amount.is_none() { + // let c = sanitize_string_for_d128_parsing_full(field).parse::().unwrap(); + // amount = c; + // }; + // if amount.is_none() { + // println!("FATAL: Couldn't convert amount to d128 for transaction:\n{:#?}", record); + // std::process::exit(1); + // } let amount_rounded = round_d128_1e8(&amount); if amount != amount_rounded { changed_action_records += 1; changed_txn_num.push(this_tx_number); } @@ -223,7 +230,7 @@ fn import_transactions( movements: RefCell::new([].to_vec()), }; - if amount > d128!(0.0) { + if amount > dec!(0.0) { incoming_ar = Some(action_record); incoming_ar_num = Some(this_ar_number); action_records_map_keys_vec.push(incoming_ar_num.unwrap()) @@ -255,52 +262,52 @@ fn import_transactions( // The Decimal::d128 implementation of FromStr calls into a C library, and that lib hasn't // been reviewed (by me), but it is thought/hoped to follow similar parsing conventions, // though there's no guarantee. Nevertheless, the above notes *appear* to hold true for d128. - fn sanitize_string_for_d128_parsing_basic(field: &str) -> String { + // fn sanitize_string_for_d128_parsing_basic(field: &str) -> String { - // First, remove commas. - let no_comma_string = field.replace(",", ""); - let almost_done = no_comma_string.replace(" ", ""); + // // First, remove commas. + // let no_comma_string = field.replace(",", ""); + // let almost_done = no_comma_string.replace(" ", ""); - // Next, if ASCII (better be), check for accounting formatting - if almost_done.is_ascii() { - if almost_done.as_bytes()[0] == "(".as_bytes()[0] { - let half_fixed = almost_done.replace("(", "-"); - let negative_with_minus = half_fixed.replace(")", ""); - return negative_with_minus - } - } - almost_done - } + // // Next, if ASCII (better be), check for accounting formatting + // if almost_done.is_ascii() { + // if almost_done.as_bytes()[0] == "(".as_bytes()[0] { + // let half_fixed = almost_done.replace("(", "-"); + // let negative_with_minus = half_fixed.replace(")", ""); + // return negative_with_minus + // } + // } + // almost_done + // } - fn sanitize_string_for_d128_parsing_full(field: &str) -> String { + // fn sanitize_string_for_d128_parsing_full(field: &str) -> String { - let mut near_done = "".to_string(); - // First, remove commas. - let no_comma_string = field.replace(",", ""); - let almost_done = no_comma_string.replace(" ", ""); + // let mut near_done = "".to_string(); + // // First, remove commas. + // let no_comma_string = field.replace(",", ""); + // let almost_done = no_comma_string.replace(" ", ""); - // Next, if ASCII (better be), check for accounting formating - if almost_done.is_ascii() { - if almost_done.as_bytes()[0] == "(".as_bytes()[0] { - let half_fixed = almost_done.replace("(", "-"); - let negative_with_minus = half_fixed.replace(")", ""); - near_done = negative_with_minus; - } else { - near_done = almost_done; - } - } else { - near_done = almost_done; - } + // // Next, if ASCII (better be), check for accounting formating + // if almost_done.is_ascii() { + // if almost_done.as_bytes()[0] == "(".as_bytes()[0] { + // let half_fixed = almost_done.replace("(", "-"); + // let negative_with_minus = half_fixed.replace(")", ""); + // near_done = negative_with_minus; + // } else { + // near_done = almost_done; + // } + // } else { + // near_done = almost_done; + // } - // Strip non-numeric and non-period characters - let all_done: String = near_done.chars() - .filter(|x| - x.is_numeric() | - (x == &(".".as_bytes()[0] as char)) | - (x == &("-".as_bytes()[0] as char))) - .collect(); - all_done - } + // // Strip non-numeric and non-period characters + // let all_done: String = near_done.chars() + // .filter(|x| + // x.is_numeric() | + // (x == &(".".as_bytes()[0] as char)) | + // (x == &("-".as_bytes()[0] as char))) + // .collect(); + // all_done + // } if let Some(incoming_ar) = incoming_ar { let x = incoming_ar_num.unwrap(); diff --git a/crptls/src/decimal_utils.rs b/crptls/src/decimal_utils.rs index 9047f00..4a5246b 100644 --- a/crptls/src/decimal_utils.rs +++ b/crptls/src/decimal_utils.rs @@ -1,20 +1,20 @@ // Copyright (c) 2017-2020, scoobybejesus // Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt -use decimal::d128; +use rust_decimal::Decimal; -pub fn round_d128_generalized(to_round: &d128, places_past_decimal: d128) -> d128 { - let rounded: d128 = ((to_round * d128!(10).scaleb(places_past_decimal)).quantize(d128!(1e1))) / d128!(10).scaleb(places_past_decimal); +pub fn round_d128_generalized(to_round: &Decimal, places_past_decimal: u32) -> Decimal { + let rounded: Decimal = to_round.round_dp(places_past_decimal); rounded//.reduce() } -pub fn round_d128_1e2(to_round: &d128) -> d128 { - let rounded: d128 = ((to_round * d128!(10).scaleb(d128!(2))).quantize(d128!(1e1))) / d128!(10).scaleb(d128!(2)); +pub fn round_d128_1e2(to_round: &Decimal) -> Decimal { + let rounded: Decimal = to_round.round_dp(2); rounded//.reduce() } -pub fn round_d128_1e8(to_round: &d128) -> d128 { - let rounded: d128 = ((to_round * d128!(10).scaleb(d128!(8))).quantize(d128!(1e1))) / d128!(10).scaleb(d128!(8)); +pub fn round_d128_1e8(to_round: &Decimal) -> Decimal { + let rounded: Decimal = to_round.round_dp(8); rounded//.reduce() // Note: quantize() rounds the number to the right of decimal and keeps it, discarding the rest to the right (it appears). See test. // In other words, it's off by one. If you raise 0.123456789 by 10e8, quantize to 1e1 (which is 10), it'll get 12345678.9, round off to 12345679, and end up .12345679 diff --git a/crptls/src/import_cost_proceeds_etc.rs b/crptls/src/import_cost_proceeds_etc.rs index db70732..94753ba 100644 --- a/crptls/src/import_cost_proceeds_etc.rs +++ b/crptls/src/import_cost_proceeds_etc.rs @@ -5,7 +5,8 @@ use std::collections::HashMap; use std::error::Error; use chrono::NaiveDate; -use decimal::d128; +use rust_decimal::Decimal; +use rust_decimal_macros::dec; use crate::transaction::{Transaction, TxType, ActionRecord, Polarity}; use crate::account::{Account, RawAccount}; @@ -66,8 +67,8 @@ pub(crate) fn add_cost_basis_to_movements( mvmt.cost_basis.set(rounded_basis); mvmt.cost_basis_lk.set(rounded_basis); } - assert!(mvmt.cost_basis.get() <= d128!(0)); - // assert!(mvmt.cost_basis_lk.get() <= d128!(0)); // Same as above assert. + assert!(mvmt.cost_basis.get() <= dec!(0)); + // assert!(mvmt.cost_basis_lk.get() <= dec!(0)); // Same as above assert. continue } @@ -102,7 +103,7 @@ pub(crate) fn add_cost_basis_to_movements( borrowed_mvmt.ratio_of_amt_to_incoming_mvmts_in_a_r; let txn_proceeds = txn.proceeds .to_string() - .parse::() + .parse::() .unwrap(); let unrounded_basis = txn_proceeds * ratio_of_amt_to_incoming_mvmts_in_a_r; let rounded_basis = round_d128_1e2(&unrounded_basis); @@ -133,7 +134,7 @@ pub(crate) fn add_cost_basis_to_movements( TxType::Flow => { - let txn_proceeds = txn.proceeds.to_string().parse::().unwrap(); + let txn_proceeds = txn.proceeds.to_string().parse::().unwrap(); let mvmt_proceeds = round_d128_1e2( &(txn_proceeds * borrowed_mvmt.ratio_of_amt_to_incoming_mvmts_in_a_r) @@ -144,8 +145,8 @@ pub(crate) fn add_cost_basis_to_movements( } } } - assert!(mvmt.cost_basis.get() >= d128!(0)); - // assert!(mvmt.cost_basis_lk.get() >= d128!(0)); // Same as above assert. + assert!(mvmt.cost_basis.get() >= dec!(0)); + // assert!(mvmt.cost_basis_lk.get() >= dec!(0)); // Same as above assert. continue } } @@ -162,7 +163,7 @@ pub(crate) fn add_cost_basis_to_movements( ars: &HashMap, txns_map: &HashMap, acct_map: &HashMap, - ) -> Vec { + ) -> Vec { let txn = txns_map.get(&txn_num).unwrap(); let other_ar_borrowed = &ars.get(&txn.action_record_idx_vec[0]).unwrap(); @@ -227,7 +228,7 @@ pub(crate) fn add_proceeds_to_movements( } let ratio = borrowed_mvmt.amount / ar.amount; - let proceeds_unrounded = txn.proceeds.to_string().parse::().unwrap() * ratio; + let proceeds_unrounded = txn.proceeds.to_string().parse::().unwrap() * ratio; let proceeds_rounded = round_d128_1e2(&proceeds_unrounded); mvmt.proceeds.set(proceeds_rounded); @@ -299,7 +300,7 @@ fn update_current_txn_for_prior_likekind_treatment( txns_map: &HashMap, ) -> Result<(), Box> { - let mut sum_of_outgoing_lk_cost_basis_in_ar = d128!(0); + let mut sum_of_outgoing_lk_cost_basis_in_ar = dec!(0); let txn = txns_map.get(&txn_num).unwrap(); for ar_num in txn.action_record_idx_vec.iter() { @@ -351,8 +352,8 @@ fn update_current_txn_for_prior_likekind_treatment( } TxType::Flow => { if txn.action_record_idx_vec.len() == 2 { - mvmt.cost_basis_lk.set(d128!(0)); - mvmt.proceeds_lk.set(d128!(0)); + mvmt.cost_basis_lk.set(dec!(0)); + mvmt.proceeds_lk.set(dec!(0)); } // Do nothing for non-margin txns. } @@ -398,7 +399,7 @@ fn perform_likekind_treatment_on_txn( if txn.both_exch_ars_are_non_home_curr(ars, raw_acct_map, acct_map, home_currency)? { - let mut sum_of_outgoing_lk_cost_basis_in_ar = d128!(0); + let mut sum_of_outgoing_lk_cost_basis_in_ar = dec!(0); for ar_num in txn.action_record_idx_vec.iter() { @@ -464,8 +465,8 @@ fn perform_likekind_treatment_on_txn( Polarity::Incoming => { // Reminder: May need extra logic here if margin exchange trades get cost_basis and proceeds - mvmt.cost_basis.set(d128!(0)); - mvmt.proceeds.set(d128!(0)); + mvmt.cost_basis.set(dec!(0)); + mvmt.proceeds.set(dec!(0)); } } } diff --git a/crptls/src/tests/test.rs b/crptls/src/tests/test.rs index 3d235ad..41e2099 100644 --- a/crptls/src/tests/test.rs +++ b/crptls/src/tests/test.rs @@ -2,11 +2,12 @@ // Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt use std::fs; -use std::collections::{HashMap}; +use std::collections::HashMap; -use decimal::d128; +use rust_decimal::Decimal; +use rust_decimal_macros::dec; -use crate::account::{Account}; +use crate::account::Account; use crate::transaction::{Transaction, ActionRecord}; use crate::decimal_utils::*; @@ -30,8 +31,8 @@ pub fn _run_tests( &account_map ); - _test_quantize_from_incoming_multiple_lots_fn(d128!(20), d128!(200), d128!(50)); - _test_quantize_from_incoming_multiple_lots_fn(d128!(1), d128!(6), d128!(1234567.1234567896)); + _test_quantize_from_incoming_multiple_lots_fn(dec!(20), dec!(200), dec!(50)); + _test_quantize_from_incoming_multiple_lots_fn(dec!(1), dec!(6), dec!(1234567.1234567896)); // test_dec_rounded("123456789.123456789"); // test_dec_rounded("123456.123456"); // test_dec_rounded("1234567891234.1234567891234"); @@ -68,7 +69,7 @@ fn _compare_movements_across_implementations( + &ar.amount.to_string() + &"\n".to_string() ); let mvmts = ar.get_mvmts_in_ar_in_lot_date_order(&account_map, &transactions_map); - let mut amts = d128!(0); + let mut amts = dec!(0); for mvmt in mvmts { amts += mvmt.amount; line += &("Movement ".to_string() + @@ -78,7 +79,7 @@ fn _compare_movements_across_implementations( &"\n".to_string()); } line += &("Amount total: ".to_string() + &amts.to_string() + &"\n".to_string()); - if amts - ar.amount != d128!(0) { + if amts - ar.amount != dec!(0) { line += &("&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&".to_string()); println!("Movement amounts via get_mvmts_in_ar() different from actionRecord.amount. Aborting."); use std::process::exit; exit(1) @@ -104,7 +105,7 @@ fn _compare_movements_across_implementations( + &"\n".to_string() ); // let mvmts = ar.get_mvmts_in_ar(&account_map); - let mut amts = d128!(0); + let mut amts = dec!(0); for mvmt in ar.movements.borrow().iter() { amts += mvmt.amount; line2 += &("Movement ".to_string() + @@ -114,7 +115,7 @@ fn _compare_movements_across_implementations( &"\n".to_string()); } line2 += &("Amount total: ".to_string() + &amts.to_string() + &"\n".to_string()); - if amts - ar.amount != d128!(0) { + if amts - ar.amount != dec!(0) { line2 += &("&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&".to_string()); println!("Movement amounts via ar.movements different from actionRecord.amount. Aborting."); use std::process::exit; exit(1) @@ -144,9 +145,9 @@ pub fn _test_action_records_amts_vs_mvmt_amts( account_map: &HashMap, ) { - let mut mvmt_amt_acct_lot: d128 = d128!(0); - let mut mvmt_amt_ar: d128 = d128!(0); - let mut ar_amts: d128 = d128!(0); + let mut mvmt_amt_acct_lot: Decimal = dec!(0); + let mut mvmt_amt_ar: Decimal = dec!(0); + let mut ar_amts: Decimal = dec!(0); for tx_num in 1..=transactions_map.len() { @@ -195,18 +196,18 @@ pub fn _test_action_records_amts_vs_mvmt_amts( } fn _test_quantize_from_incoming_multiple_lots_fn ( - outgoing_mvmt_amt: d128, - outgoing_ar_amt: d128, - incoming_ar_amt: d128, + outgoing_mvmt_amt: Decimal, + outgoing_ar_amt: Decimal, + incoming_ar_amt: Decimal, ) { - let rounded_example = d128::from(1).scaleb(d128::from(-8)); + let rounded_example = Decimal::new(1,8); // println!("Og mvmt amt: {:?}, Og ar amt: {:?}, Ic ar amt: {:?}", outgoing_mvmt_amt, outgoing_ar_amt, incoming_ar_amt); let ratio_of_outgoing_to_total_ar = outgoing_mvmt_amt / outgoing_ar_amt; // Negative divided by negative is positive println!("ratio_of_outgoing: {:.20}", ratio_of_outgoing_to_total_ar); let tentative_incoming_amt = ratio_of_outgoing_to_total_ar * incoming_ar_amt; println!("tentative_inc_amt: {:.20}", tentative_incoming_amt); - let corresponding_incoming_amt = tentative_incoming_amt.quantize(rounded_example); + let corresponding_incoming_amt = tentative_incoming_amt.round_dp(8); println!("corresponding_inc_amt: {}", corresponding_incoming_amt); } @@ -221,23 +222,23 @@ fn _test_quantize_from_incoming_multiple_lots_fn ( // corresponding_inc_amt: 205761.18724280 fn _test_dec_rounded(random_float_string: &str) { - let places_past_decimal = d128!(8); - let amt = random_float_string.parse::().unwrap(); + let places_past_decimal = 8; + let amt = random_float_string.parse::().unwrap(); let amt2 = round_d128_generalized(&amt, places_past_decimal); - println!("Float into d128: {:?}; d128 rounded to {}: {:?}", amt, places_past_decimal, amt2); - // Results of this test suggest that quantize() is off by one. round_d128_1e8() was adjusted accordingly. + println!("Float into dec: {:?}; dec rounded to {}: {:?}", amt, places_past_decimal, amt2); + // Results of this test suggest that quantize() is off by one. round_dec_1e8() was adjusted accordingly. } fn _test_dec_rounded_1e8(random_float_string: &str) { - let amt = random_float_string.parse::().unwrap(); + let amt = random_float_string.parse::().unwrap(); let amt2 = round_d128_1e8(&amt); - println!("Float into d128: {:?}; d128 rounded to 8 places: {:?}", amt, amt2); - // Results of this test suggest that quantize() is off by one. round_d128_1e8() was adjusted accordingly. + println!("Float into dec: {:?}; dec rounded to 8 places: {:?}", amt, amt2); + // Results of this test suggest that quantize() is off by one. round_dec_1e8() was adjusted accordingly. } fn _test_dec_rounded_1e2(random_float_string: &str) { - let amt = random_float_string.parse::().unwrap(); + let amt = random_float_string.parse::().unwrap(); let amt2 = round_d128_1e2(&amt); - println!("String into d128: {:?}; d128 rounded to 2 places: {:?}", amt, amt2); - // Results of this test suggest that quantize() is off by one. round_d128_1e8() was adjusted accordingly. + println!("String into dec: {:?}; dec rounded to 2 places: {:?}", amt, amt2); + // Results of this test suggest that quantize() is off by one. round_dec_1e8() was adjusted accordingly. } diff --git a/crptls/src/transaction.rs b/crptls/src/transaction.rs index f341a99..f182e58 100644 --- a/crptls/src/transaction.rs +++ b/crptls/src/transaction.rs @@ -8,7 +8,8 @@ use std::fmt; use std::collections::HashMap; use std::error::Error; -use decimal::d128; +use rust_decimal::Decimal; +use rust_decimal_macros::dec; use chrono::NaiveDate; use serde_derive::{Serialize, Deserialize}; @@ -297,7 +298,7 @@ impl Transaction { let raw_acct = raw_accts.get(&acct.raw_key).unwrap(); let ticker = &raw_acct.ticker; - if amt > d128!(0.0) { + if amt > dec!(0.0) { format!("Received {} {} valued at {:.2} {}.", amt, ticker, self.proceeds.to_string().as_str().parse::()?, home_currency) @@ -317,7 +318,7 @@ impl Transaction { #[derive(Clone, Debug)] pub struct ActionRecord { pub account_key: u16, - pub amount: d128, + pub amount: Decimal, pub tx_key: u32, pub self_ar_key: u32, pub movements: RefCell>>, @@ -326,13 +327,13 @@ pub struct ActionRecord { impl ActionRecord { pub fn direction(&self) -> Polarity { - if self.amount < d128!(0.0) { Polarity::Outgoing} + if self.amount < dec!(0.0) { Polarity::Outgoing} else { Polarity::Incoming } } - pub fn cost_basis_in_ar(&self) -> d128 { + pub fn cost_basis_in_ar(&self) -> Decimal { - let mut cb = d128!(0); + let mut cb = dec!(0); for mvmt in self.movements.borrow().iter() { cb += mvmt.cost_basis.get() @@ -373,7 +374,7 @@ impl ActionRecord { let acct = acct_map.get(&self.account_key).unwrap(); let target = self.amount; - let mut measure = d128!(0); + let mut measure = dec!(0); for lot in acct.list_of_lots.borrow().iter() { diff --git a/src/export/export_csv.rs b/src/export/export_csv.rs index 28066d7..5488f6d 100644 --- a/src/export/export_csv.rs +++ b/src/export/export_csv.rs @@ -6,7 +6,7 @@ use std::collections::HashMap; use std::path::PathBuf; use std::error::Error; -use decimal::d128; +use rust_decimal_macros::dec; use chrono::NaiveDate; use crptls::transaction::{ActionRecord, Polarity, Transaction, TxType}; @@ -47,7 +47,7 @@ pub fn _1_account_sums_to_csv( let balance: String; let tentative_balance = acct.get_sum_of_amts_in_lots(); - if tentative_balance == d128!(0) { + if tentative_balance == dec!(0) { balance = "0.00".to_string() } else { balance = tentative_balance.to_string() } @@ -56,7 +56,7 @@ pub fn _1_account_sums_to_csv( if raw_acct.is_margin { lk_cost_basis = "0.00".to_string() } else { let tentative_lk_cost_basis = acct.get_sum_of_lk_basis_in_lots(); - if tentative_lk_cost_basis == d128!(0) { + if tentative_lk_cost_basis == dec!(0) { lk_cost_basis = "0.00".to_string() } else { lk_cost_basis = tentative_lk_cost_basis.to_string() } } @@ -121,10 +121,10 @@ pub fn _2_account_sums_nonzero_to_csv( let name = raw_acct.name.to_string(); let balance: String; - let mut balance_d128 = d128!(0); + let mut balance_d128 = dec!(0); let tentative_balance = acct.get_sum_of_amts_in_lots(); - if tentative_balance == d128!(0) { + if tentative_balance == dec!(0) { balance = "0.00".to_string() } else { balance_d128 += tentative_balance; balance = tentative_balance.to_string() } @@ -132,7 +132,7 @@ pub fn _2_account_sums_nonzero_to_csv( if raw_acct.is_margin { lk_cost_basis = "0.00".to_string() } else { let tentative_lk_cost_basis = acct.get_sum_of_lk_basis_in_lots(); - if tentative_lk_cost_basis == d128!(0) { + if tentative_lk_cost_basis == dec!(0) { lk_cost_basis = "0.00".to_string() } else { lk_cost_basis = tentative_lk_cost_basis.to_string() } } @@ -142,7 +142,7 @@ pub fn _2_account_sums_nonzero_to_csv( let nonzero_lots = acct.get_num_of_nonzero_lots(); - if balance_d128 != d128!(0) { + if balance_d128 != dec!(0) { row.push(name); row.push(balance); row.push(raw_acct.ticker.to_string()); @@ -200,7 +200,7 @@ pub fn _3_account_sums_to_csv_with_orig_basis( let balance: String; let tentative_balance = acct.get_sum_of_amts_in_lots(); - if tentative_balance == d128!(0) { + if tentative_balance == dec!(0) { balance = "0.00".to_string() } else { balance = tentative_balance.to_string() } @@ -217,11 +217,11 @@ pub fn _3_account_sums_to_csv_with_orig_basis( let tentative_lk_cost_basis = acct.get_sum_of_lk_basis_in_lots(); let tentative_orig_cost_basis = acct.get_sum_of_orig_basis_in_lots(); - if tentative_lk_cost_basis == d128!(0) { + if tentative_lk_cost_basis == dec!(0) { lk_cost_basis = "0.00".to_string() } else { lk_cost_basis = tentative_lk_cost_basis.to_string() } - if tentative_orig_cost_basis == d128!(0) { + if tentative_orig_cost_basis == dec!(0) { orig_cost_basis = "0.00".to_string() } else { orig_cost_basis = tentative_orig_cost_basis.to_string() } } @@ -312,7 +312,7 @@ pub fn _4_transaction_mvmt_detail_to_csv( let tx_type = txn.transaction_type(&ars, &raw_acct_map, &acct_map)?; let tx_type_string = mvmt.friendly_tx_type(&tx_type); let memo = txn.user_memo.to_string(); - let mut amount = d128!(0); + let mut amount = dec!(0); amount += mvmt.amount; // To prevent printing -5E+1 instead of 50, for example let ticker = raw_acct.ticker.to_string(); let term = mvmt.get_term(acct_map, ars, txns_map).to_string(); @@ -323,10 +323,10 @@ pub fn _4_transaction_mvmt_detail_to_csv( let expense = mvmt.get_expense(ars, &raw_acct_map, &acct_map, &txns_map)?; - if tx_type == TxType::Flow && amount > d128!(0) { - proceeds_lk = d128!(0); - cost_basis_lk = d128!(0); - gain_loss = d128!(0); + if tx_type == TxType::Flow && amount > dec!(0) { + proceeds_lk = dec!(0); + cost_basis_lk = dec!(0); + gain_loss = dec!(0); } let mut row: Vec = Vec::with_capacity(total_columns); @@ -410,19 +410,19 @@ pub fn _5_transaction_mvmt_summaries_to_csv( let mut ticker: Option = None; let mut polarity: Option = None; - let mut amount_st = d128!(0); - let mut proceeds_st = d128!(0); - let mut cost_basis_st = d128!(0); + let mut amount_st = dec!(0); + let mut proceeds_st = dec!(0); + let mut cost_basis_st = dec!(0); - let mut income_st = d128!(0); - let mut expense_st = d128!(0); + let mut income_st = dec!(0); + let mut expense_st = dec!(0); - let mut amount_lt = d128!(0); - let mut proceeds_lt = d128!(0); - let mut cost_basis_lt = d128!(0); + let mut amount_lt = dec!(0); + let mut proceeds_lt = dec!(0); + let mut cost_basis_lt = dec!(0); - let mut income_lt = d128!(0); - let mut expense_lt = d128!(0); + let mut income_lt = dec!(0); + let mut expense_lt = dec!(0); let flow_or_outgoing_exchange_movements = txn.get_outgoing_exchange_and_flow_mvmts( &settings.home_currency, @@ -444,7 +444,7 @@ pub fn _5_transaction_mvmt_summaries_to_csv( if ticker.is_none() { ticker = Some(raw_acct.ticker.clone()) }; if polarity.is_none() { - polarity = if mvmt.amount > d128!(0) { + polarity = if mvmt.amount > dec!(0) { Some(Polarity::Incoming) } else { Some(Polarity::Outgoing) }; @@ -474,11 +474,11 @@ pub fn _5_transaction_mvmt_summaries_to_csv( &acct_map)? == TxType::Flow ) & (polarity == Some(Polarity::Incoming)) { income_st = -proceeds_st; // Proceeds are negative for incoming txns - proceeds_st = d128!(0); - cost_basis_st = d128!(0); + proceeds_st = dec!(0); + cost_basis_st = dec!(0); income_lt = -proceeds_lt; // Proceeds are negative for incoming txns - proceeds_lt = d128!(0); - cost_basis_lt = d128!(0); + proceeds_lt = dec!(0); + cost_basis_lt = dec!(0); } if (txn.transaction_type( @@ -620,7 +620,7 @@ pub fn _6_transaction_mvmt_detail_to_csv_w_orig( let tx_type_string = mvmt.friendly_tx_type(&tx_type); let user_memo = txn.user_memo.to_string(); let auto_memo = txn.get_auto_memo(ars, raw_acct_map,acct_map, &settings.home_currency)?; - let mut amount = d128!(0); + let mut amount = dec!(0); amount += mvmt.amount; // To prevent printing -5E+1 instead of 50, for example let ticker = raw_acct.ticker.to_string(); let term = mvmt.get_term(acct_map, ars, txns_map).to_string(); @@ -633,13 +633,13 @@ pub fn _6_transaction_mvmt_detail_to_csv_w_orig( let mut orig_cost = mvmt.cost_basis.get(); let mut orig_gain_loss = mvmt.get_orig_gain_or_loss(); - if tx_type == TxType::Flow && amount > d128!(0) { - proceeds_lk = d128!(0); - cost_basis_lk = d128!(0); - gain_loss = d128!(0); - orig_proc = d128!(0); - orig_cost = d128!(0); - orig_gain_loss = d128!(0); + if tx_type == TxType::Flow && amount > dec!(0) { + proceeds_lk = dec!(0); + cost_basis_lk = dec!(0); + gain_loss = dec!(0); + orig_proc = dec!(0); + orig_cost = dec!(0); + orig_gain_loss = dec!(0); } let mut row: Vec = Vec::with_capacity(total_columns); @@ -723,17 +723,17 @@ pub fn _7_gain_loss_8949_to_csv( let mut ticker: Option = None; let mut polarity: Option = None; - let mut amount_st = d128!(0); - let mut proceeds_st = d128!(0); - let mut cost_basis_st = d128!(0); + let mut amount_st = dec!(0); + let mut proceeds_st = dec!(0); + let mut cost_basis_st = dec!(0); - let mut expense_st = d128!(0); + let mut expense_st = dec!(0); - let mut amount_lt = d128!(0); - let mut proceeds_lt = d128!(0); - let mut cost_basis_lt = d128!(0); + let mut amount_lt = dec!(0); + let mut proceeds_lt = dec!(0); + let mut cost_basis_lt = dec!(0); - let mut expense_lt = d128!(0); + let mut expense_lt = dec!(0); let flow_or_outgoing_exchange_movements = txn.get_outgoing_exchange_and_flow_mvmts( &settings.home_currency, @@ -757,7 +757,7 @@ pub fn _7_gain_loss_8949_to_csv( if ticker.is_none() { ticker = Some(raw_acct.ticker.clone()) }; if polarity.is_none() { - polarity = if mvmt.amount > d128!(0) { + polarity = if mvmt.amount > dec!(0) { Some(Polarity::Incoming) } else { Some(Polarity::Outgoing) }; @@ -804,9 +804,9 @@ pub fn _7_gain_loss_8949_to_csv( // The only incoming flow transaction to report would be margin profit, which is a dual-`action record` `transaction` if txn.action_record_idx_vec.len() == 2 { proceeds_st = -proceeds_st; // Proceeds are negative for incoming txns - cost_basis_st = d128!(0); + cost_basis_st = dec!(0); proceeds_lt = -proceeds_lt; // Proceeds are negative for incoming txns - cost_basis_lt = d128!(0); + cost_basis_lt = dec!(0); } else { continue // Plain, old income isn't reported on form 8949 } diff --git a/src/export/export_je.rs b/src/export/export_je.rs index ff6083f..a1bd0fc 100644 --- a/src/export/export_je.rs +++ b/src/export/export_je.rs @@ -7,7 +7,8 @@ use std::path::PathBuf; use std::error::Error; use std::io::prelude::Write; -use decimal::d128; +use rust_decimal::Decimal; +use rust_decimal_macros::dec; use crptls::transaction::{Transaction, ActionRecord, Polarity, TxType}; use crptls::account::{Account, RawAccount, Term}; @@ -65,8 +66,8 @@ depending on the bookkeeping practices you employ."; writeln!(file, "\n====================================================================================================\n")?; - let mut cost_basis_ic: Option = None; - let mut cost_basis_og: Option = None; + let mut cost_basis_ic: Option = None; + let mut cost_basis_og: Option = None; let mut acct_string_ic = "".to_string(); let mut acct_string_og = "".to_string(); @@ -101,16 +102,16 @@ depending on the bookkeeping practices you employ."; let mut polarity: Option = None; - let mut amount_st = d128!(0); - let mut proceeds_st = d128!(0); - let mut cost_basis_st = d128!(0); + let mut amount_st = dec!(0); + let mut proceeds_st = dec!(0); + let mut cost_basis_st = dec!(0); - let mut amount_lt = d128!(0); - let mut proceeds_lt = d128!(0); - let mut cost_basis_lt = d128!(0); + let mut amount_lt = dec!(0); + let mut proceeds_lt = dec!(0); + let mut cost_basis_lt = dec!(0); - let mut income = d128!(0); - let mut expense = d128!(0); + let mut income = dec!(0); + let mut expense = dec!(0); let flow_or_outgoing_exchange_movements = txn.get_outgoing_exchange_and_flow_mvmts( &settings.home_currency, @@ -123,7 +124,7 @@ depending on the bookkeeping practices you employ."; for mvmt in flow_or_outgoing_exchange_movements.iter() { if polarity.is_none() { - polarity = if mvmt.amount > d128!(0) { + polarity = if mvmt.amount > dec!(0) { Some(Polarity::Incoming) } else { Some(Polarity::Outgoing) }; @@ -155,18 +156,18 @@ depending on the bookkeeping practices you employ."; &acct_map)? == TxType::Flow ) & (polarity == Some(Polarity::Incoming)) { - proceeds_st = d128!(0); - cost_basis_st = d128!(0); + proceeds_st = dec!(0); + cost_basis_st = dec!(0); - proceeds_lt = d128!(0); - cost_basis_lt = d128!(0); + proceeds_lt = dec!(0); + cost_basis_lt = dec!(0); } let lt_gain_loss = proceeds_lt + cost_basis_lt; let st_gain_loss = proceeds_st + cost_basis_st; - let mut debits = d128!(0); - let mut credits = d128!(0); + let mut debits = dec!(0); + let mut credits = dec!(0); if let Some(cb) = cost_basis_ic { debits += cb; @@ -190,9 +191,9 @@ depending on the bookkeeping practices you employ."; )?; } - if lt_gain_loss != d128!(0) { + if lt_gain_loss != dec!(0) { - if lt_gain_loss > d128!(0) { + if lt_gain_loss > dec!(0) { credits += lt_gain_loss.abs(); let ltg_string = format!("Long-term gain disposing {}", amount_lt.abs()); writeln!(file, "{:50}{:5}{:>20}{:5}{:>20.2}", @@ -215,9 +216,9 @@ depending on the bookkeeping practices you employ."; } } - if st_gain_loss != d128!(0) { + if st_gain_loss != dec!(0) { - if st_gain_loss > d128!(0) { + if st_gain_loss > dec!(0) { credits += st_gain_loss.abs(); let stg_string = format!("Short-term gain disposing {}", amount_st.abs()); writeln!(file, "{:50}{:5}{:>20}{:5}{:>20.2}", @@ -240,7 +241,7 @@ depending on the bookkeeping practices you employ."; } } - if income != d128!(0) { + if income != dec!(0) { credits += income; writeln!(file, "{:50}{:5}{:>20}{:5}{:>20.2}", "Income", @@ -251,7 +252,7 @@ depending on the bookkeeping practices you employ."; )?; } - if expense != d128!(0) { + if expense != dec!(0) { debits += expense.abs(); writeln!(file, "{:50}{:5}{:>20.2}{:5}{:>20}", "Expense", @@ -285,7 +286,7 @@ depending on the bookkeeping practices you employ."; auto_memo, )?; - // if (debits - credits) != d128!(0) { + // if (debits - credits) != dec!(0) { // println!("Rounding issue on transaction #{}", txn_num); // } diff --git a/src/export/export_txt.rs b/src/export/export_txt.rs index d4689a6..7d7ca76 100644 --- a/src/export/export_txt.rs +++ b/src/export/export_txt.rs @@ -7,7 +7,8 @@ use std::path::PathBuf; use std::error::Error; use std::io::prelude::Write; -use decimal::d128; +use rust_decimal::Decimal; +use rust_decimal_macros::dec; use crptls::transaction::{Transaction, ActionRecord}; use crptls::account::{Account, RawAccount}; @@ -129,14 +130,14 @@ Enable like-kind treatment: {}", let lk_lot_basis = lot.get_sum_of_lk_basis_in_lot(); let formatted_basis: String; - if lk_lot_basis == d128!(0) { + if lk_lot_basis == dec!(0) { formatted_basis = "0.00".to_string() } else { formatted_basis = lk_lot_basis.to_string() } let movements_sum = lot.get_sum_of_amts_in_lot(); let formatted_sum: String; - if movements_sum == d128!(0) { + if movements_sum == dec!(0) { formatted_sum = "0.00".to_string() } else { formatted_sum = movements_sum.to_string() } @@ -200,15 +201,15 @@ Enable like-kind treatment: {}", let lk_proceeds = mvmt.proceeds_lk.get(); let lk_cost_basis = mvmt.cost_basis_lk.get(); - let gain_loss: d128; + let gain_loss: Decimal; - // if mvmt.amount > d128!(0) { // Can't have a gain on an incoming txn - // gain_loss = d128!(0) + // if mvmt.amount > dec!(0) { // Can't have a gain on an incoming txn + // gain_loss = dec!(0) // } else if raw_acct.is_home_currency(home_currency) { // Can't have a gain disposing home currency - gain_loss = d128!(0) + gain_loss = dec!(0) // } else if tx_type == TxType::ToSelf { // Can't have a gain sending to yourself - // gain_loss = d128!(0) + // gain_loss = dec!(0) } else { gain_loss = lk_proceeds + lk_cost_basis; } @@ -305,14 +306,14 @@ Enable like-kind treatment: {}", let lk_lot_basis = lot.get_sum_of_lk_basis_in_lot(); let formatted_basis: String; - if lk_lot_basis == d128!(0) { + if lk_lot_basis == dec!(0) { formatted_basis = "0.00".to_string() } else { formatted_basis = lk_lot_basis.to_string() } let movements_sum = lot.get_sum_of_amts_in_lot(); let formatted_sum: String; - if movements_sum == d128!(0) { + if movements_sum == dec!(0) { formatted_sum = "0.00".to_string() } else { formatted_sum = movements_sum.to_string() } @@ -384,7 +385,7 @@ Enable like-kind treatment: {}", let amt_in_acct = acct.get_sum_of_amts_in_lots(); if acct.list_of_lots.borrow().len() > 0 { - if amt_in_acct > d128!(0) { + if amt_in_acct > dec!(0) { writeln!(file, "\n=====================================")?; writeln!(file, "{} {}", raw_acct.name, raw_acct.ticker)?; @@ -404,13 +405,13 @@ Enable like-kind treatment: {}", let lk_lot_basis = lot.get_sum_of_lk_basis_in_lot(); let formatted_basis: String; - if lk_lot_basis == d128!(0) { + if lk_lot_basis == dec!(0) { formatted_basis = "0.00".to_string() } else { formatted_basis = lk_lot_basis.to_string() } let movements_sum = lot.get_sum_of_amts_in_lot(); - if acct.list_of_lots.borrow().len() > 0 && movements_sum > d128!(0) { + if acct.list_of_lots.borrow().len() > 0 && movements_sum > dec!(0) { writeln!(file, " Lot {:>3} created {} w/ basis date {} • Σ: {:>12}, and cost basis of {:>10.2}", (lot_idx+1),