diff options
| author | Joe Carstairs <me@joeac.net> | 2024-10-16 12:51:21 +0100 |
|---|---|---|
| committer | Joe Carstairs <me@joeac.net> | 2024-10-16 12:51:21 +0100 |
| commit | 27b95c9186bd45edd4c982a7cc89cf69cf2c5d46 (patch) | |
| tree | bf104ff9d64e601bfec5516eb51ef298f3095e9b /importers/actualbudget | |
| parent | 76974785294089965efc3f55b2a08d4089029c52 (diff) | |
All backend stuff lives in backend folder
Diffstat (limited to 'importers/actualbudget')
22 files changed, 0 insertions, 1133 deletions
diff --git a/importers/actualbudget/Cargo.lock b/importers/actualbudget/Cargo.lock deleted file mode 100644 index 63a53b9..0000000 --- a/importers/actualbudget/Cargo.lock +++ /dev/null @@ -1,356 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "actualbudget" -version = "0.1.0" -dependencies = [ - "chrono", - "sqlite", -] - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "autocfg" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "cc" -version = "1.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9d013ecb737093c0e86b151a7b837993cf9ec6c502946cfb44bedc392421e0b" -dependencies = [ - "shlex", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-targets", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "iana-time-zone" -version = "0.1.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "js-sys" -version = "0.3.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "libc" -version = "0.2.158" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" - -[[package]] -name = "log" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] -name = "proc-macro2" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "serde" -version = "1.0.210" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.210" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "sqlite" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfe6fb16f2bee6452feeb4d12bfa404fbcd3cfc121b2950e501d1ae9cae718e" -dependencies = [ - "sqlite3-sys", -] - -[[package]] -name = "sqlite3-src" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "174d4a6df77c27db281fb23de1a6d968f3aaaa4807c2a1afa8056b971f947b4a" -dependencies = [ - "cc", - "pkg-config", -] - -[[package]] -name = "sqlite3-sys" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3901ada7090c3c3584dc92ec7ef1b7091868d13bfe6d7de9f0bcaffee7d0ade5" -dependencies = [ - "sqlite3-src", -] - -[[package]] -name = "syn" -version = "2.0.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-ident" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" - -[[package]] -name = "wasm-bindgen" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" -dependencies = [ - "cfg-if", - "once_cell", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/importers/actualbudget/Cargo.toml b/importers/actualbudget/Cargo.toml deleted file mode 100644 index 7cc3e1b..0000000 --- a/importers/actualbudget/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "actualbudget" -version = "0.1.0" -edition = "2021" - -[dependencies] -sqlite = "0.36.1" -chrono = { version = "0.4.38", features = ["serde"] } diff --git a/importers/actualbudget/src/getters.rs b/importers/actualbudget/src/getters.rs deleted file mode 100644 index 88a660d..0000000 --- a/importers/actualbudget/src/getters.rs +++ /dev/null @@ -1,61 +0,0 @@ -use crate::models::actualbudget::{ - account::Account, category::Category, date::Date, transaction::Transaction, - zero_budget::ZeroBudget, -}; -use sqlite::Connection; - -pub fn get_first_transaction_date(connection: &Connection) -> Date { - let mut statement = connection - .prepare("select min(date) as min_date from transactions;") - .unwrap(); - match statement.next() { - Ok(sqlite::State::Row) => Date::from_date_row(&statement, "min_date"), - err => panic!("Could not find first transaction date: {:?}", err), - } -} - -pub fn get_accounts(connection: &Connection) -> Vec<Account> { - let mut statement = connection.prepare("select * from accounts;").unwrap(); - let mut accounts = Vec::<Account>::new(); - while let Ok(sqlite::State::Row) = statement.next() { - accounts.push(Account::from_row(&statement)); - } - accounts -} - -pub fn get_categories(connection: &Connection) -> Vec<Category> { - let mut statement = connection.prepare("select * from categories;").unwrap(); - let mut categories = Vec::<Category>::new(); - while let Ok(sqlite::State::Row) = statement.next() { - categories.push(Category::from_row(&statement)); - } - categories -} - -pub fn get_zero_budgets(connection: &Connection) -> Vec<ZeroBudget> { - let mut statement = connection.prepare("select * from zero_budgets;").unwrap(); - let mut zero_budgets = Vec::<ZeroBudget>::new(); - while let Ok(sqlite::State::Row) = statement.next() { - zero_budgets.push(ZeroBudget::from_row(&statement)); - } - zero_budgets -} - -pub fn get_category_transfers_account(connection: &Connection) -> Account { - let mut statement = connection - .prepare("select * from accounts where name = 'Category transfers';") - .unwrap(); - match statement.next() { - Ok(sqlite::State::Row) => Account::from_row(&statement), - _ => panic!("Could not determine category transfers account"), - } -} - -pub fn get_transactions(connection: &Connection) -> Vec<Transaction> { - let mut statement = connection.prepare("select * from transactions;").unwrap(); - let mut transactions = Vec::<Transaction>::new(); - while let Ok(sqlite::State::Row) = statement.next() { - transactions.push(Transaction::from_row(&statement)); - } - transactions -} diff --git a/importers/actualbudget/src/inserters.rs b/importers/actualbudget/src/inserters.rs deleted file mode 100644 index 179de97..0000000 --- a/importers/actualbudget/src/inserters.rs +++ /dev/null @@ -1,120 +0,0 @@ -use crate::models::budgeting_app::{ - account::Account, budget_update::BudgetUpdate, category::Category, - category_transfer::CategoryTransfer, transaction::Transaction, - transaction_categorisation::TransactionCategorisation, -}; -use sqlite::Connection; - -pub fn insert_accounts(connection: &Connection, accounts: &[Account]) { - for account in accounts { - let str = format!( - " - insert into - accounts(id, name, opening_balance, opening_date) - values({0}, '{1}', {2}, '{3}'); - ", - account.id, - escape_str(&account.name), - account.opening_balance, - account.opening_date - ); - connection.execute(str).unwrap(); - } -} - -pub fn insert_categories(connection: &Connection, categories: &[Category]) { - for category in categories { - let str = format!( - " - insert into - categories(id, name) - values({0}, '{1}'); - ", - category.id, - escape_str(&category.name), - ); - connection.execute(str).unwrap(); - } -} - -pub fn insert_budget_updates(connection: &Connection, budget_updates: &[BudgetUpdate]) { - for budget_update in budget_updates { - let str = format!( - " - insert into - budget_updates(id, category_id, date, new_budget, new_period) - values({0}, {1}, '{2}', {3}, {4}); - ", - budget_update.id, - budget_update.category_id, - budget_update.date, - budget_update.new_budget, - budget_update.new_period, - ); - connection.execute(str).unwrap(); - } -} - -pub fn insert_transactions(connection: &Connection, transactions: &[Transaction]) { - for transaction in transactions { - let str = format!( - " - insert into - transactions(id, description, payee, quantity, date, account_id) - values({0}, '{1}', '{2}', {3}, '{4}', {5}); - ", - transaction.id, - escape_str(&transaction.description), - escape_str(&transaction.payee), - transaction.quantity, - transaction.date, - transaction.account_id, - ); - connection - .execute(str.clone()) - .unwrap_or_else(|_| panic!("{}", &str.clone())); - } -} - -pub fn insert_transaction_categorisations( - connection: &Connection, - transaction_categorisations: &[TransactionCategorisation], -) { - for transaction_categorisation in transaction_categorisations { - let str = format!( - " - insert into - transaction_categorisations(id, description, quantity, transaction_id, category_id) - values({0}, '{1}', {2}, {3}, {4}); - ", - transaction_categorisation.id, - escape_str(&transaction_categorisation.description), - transaction_categorisation.quantity, - transaction_categorisation.transaction_id, - transaction_categorisation.category_id, - ); - connection.execute(str).unwrap(); - } -} - -pub fn insert_category_transfers(connection: &Connection, category_transfers: &[CategoryTransfer]) { - for category_transfer in category_transfers { - let str = format!( - " - insert into - category_transfers(id, description, quantity, from_category_id, to_category_id) - values({0}, '{1}', {2}, {3}, {4}); - ", - category_transfer.id, - escape_str(&category_transfer.description), - category_transfer.quantity, - category_transfer.from_category_id, - category_transfer.to_category_id, - ); - connection.execute(str).unwrap(); - } -} - -fn escape_str(str: &str) -> String { - str.replace("'", "''") -} diff --git a/importers/actualbudget/src/main.rs b/importers/actualbudget/src/main.rs deleted file mode 100644 index 495216e..0000000 --- a/importers/actualbudget/src/main.rs +++ /dev/null @@ -1,57 +0,0 @@ -pub mod getters; -pub mod inserters; -pub mod models; -pub mod transformers; - -use getters::*; -use inserters::*; -use sqlite::Connection; - -fn main() { - let connection_src = sqlite::open("in.sqlite").unwrap(); - let connection_dest = sqlite::open("out.sqlite").unwrap(); - - let actualbudget_first_transaction_date = get_first_transaction_date(&connection_src); - let actualbudget_accounts = get_accounts(&connection_src); - let actualbudget_categories = get_categories(&connection_src); - let actualbudget_zero_budgets = get_zero_budgets(&connection_src); - let actualbudget_category_transfers_account = get_category_transfers_account(&connection_src); - let actualbudget_transactions = get_transactions(&connection_src); - - let first_transaction_date = transformers::transform_date(&actualbudget_first_transaction_date); - let accounts = - transformers::transform_accounts(&actualbudget_accounts, &first_transaction_date); - let categories = transformers::transform_categories(&actualbudget_categories); - let budget_updates = transformers::transform_budget_updates(&actualbudget_zero_budgets); - let (transactions, transaction_categorisations) = transformers::transform_transactions( - &actualbudget_transactions, - &actualbudget_category_transfers_account, - ); - let category_transfers = transformers::transform_category_transfers( - &actualbudget_transactions, - &actualbudget_category_transfers_account, - ); - - clear_destination(&connection_dest); - insert_accounts(&connection_dest, &accounts); - insert_categories(&connection_dest, &categories); - insert_budget_updates(&connection_dest, &budget_updates); - insert_transactions(&connection_dest, &transactions); - insert_transaction_categorisations(&connection_dest, &transaction_categorisations); - insert_category_transfers(&connection_dest, &category_transfers); -} - -fn clear_destination(connection: &Connection) { - connection - .execute( - " - delete from accounts; - delete from budget_updates; - delete from categories; - delete from transaction_categorisations; - delete from category_transfers; - delete from transactions; - ", - ) - .unwrap(); -} diff --git a/importers/actualbudget/src/models/actualbudget/account.rs b/importers/actualbudget/src/models/actualbudget/account.rs deleted file mode 100644 index 727c082..0000000 --- a/importers/actualbudget/src/models/actualbudget/account.rs +++ /dev/null @@ -1,15 +0,0 @@ -use sqlite::Statement; - -pub struct Account { - pub id: String, - pub name: String, -} - -impl Account { - pub fn from_row(statement: &Statement) -> Account { - Account { - id: statement.read("id").unwrap(), - name: statement.read("name").unwrap(), - } - } -} diff --git a/importers/actualbudget/src/models/actualbudget/category.rs b/importers/actualbudget/src/models/actualbudget/category.rs deleted file mode 100644 index 21fdf80..0000000 --- a/importers/actualbudget/src/models/actualbudget/category.rs +++ /dev/null @@ -1,15 +0,0 @@ -use sqlite::Statement; - -pub struct Category { - pub id: String, - pub name: String, -} - -impl Category { - pub fn from_row(statement: &Statement) -> Category { - Category { - id: statement.read("id").unwrap(), - name: statement.read("name").unwrap(), - } - } -} diff --git a/importers/actualbudget/src/models/actualbudget/date.rs b/importers/actualbudget/src/models/actualbudget/date.rs deleted file mode 100644 index bd37c46..0000000 --- a/importers/actualbudget/src/models/actualbudget/date.rs +++ /dev/null @@ -1,69 +0,0 @@ -use sqlite::Statement; - -#[derive(Clone, PartialEq, Eq)] -pub struct Date { - value: i64, - last_date_part: DatePart, -} - -#[derive(Clone, PartialOrd, PartialEq, Eq)] -enum DatePart { - MonthOfYear, - DayOfMonth, -} - -// actualbudget represents dates as numbers which "look like" the corresponding -// ISO string when written in decimal. E.g. 20240901 represents 1 Sep 2024. It -// also uses month specifiers, e.g. 202409 to represent Sep 2024. In this case, -// we interpret this as the first day of the month, e.g. 2024-09-01. - -impl Date { - pub fn from_date_row(statement: &Statement, column: &str) -> Date { - Date { - value: statement.read::<i64, _>(column).unwrap(), - last_date_part: DatePart::DayOfMonth, - } - } - - pub fn from_month_row(statement: &Statement, column: &str) -> Date { - Date { - value: statement.read::<i64, _>(column).unwrap() * 100 + 1, - last_date_part: DatePart::MonthOfYear, - } - } - - pub fn to_iso(&self) -> String { - format!("{0}-{1}-{2}", self.year(), self.month(), self.day()) - } - - pub fn year(&self) -> String { - self.value.to_string()[0..4].to_string() - } - - pub fn month(&self) -> String { - self.value.to_string()[4..6].to_string() - } - - pub fn day(&self) -> String { - self.dayified_value().to_string()[6..8].to_string() - } - - fn dayified_value(&self) -> i64 { - match self.last_date_part { - DatePart::DayOfMonth => self.value, - DatePart::MonthOfYear => self.value * 100 + 1, - } - } -} - -impl Ord for Date { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.dayified_value().cmp(&other.dayified_value()) - } -} - -impl PartialOrd for Date { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - Some(self.cmp(other)) - } -} diff --git a/importers/actualbudget/src/models/actualbudget/mod.rs b/importers/actualbudget/src/models/actualbudget/mod.rs deleted file mode 100644 index 5ca472f..0000000 --- a/importers/actualbudget/src/models/actualbudget/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod account; -pub mod category; -pub mod date; -pub mod transaction; -pub mod zero_budget; diff --git a/importers/actualbudget/src/models/actualbudget/transaction.rs b/importers/actualbudget/src/models/actualbudget/transaction.rs deleted file mode 100644 index 0a21cfe..0000000 --- a/importers/actualbudget/src/models/actualbudget/transaction.rs +++ /dev/null @@ -1,43 +0,0 @@ -use sqlite::Statement; - -use super::date::Date; - -#[derive(Clone)] -pub struct Transaction { - pub id: String, - pub is_parent: bool, - pub is_child: bool, - pub account_id: String, - pub category_id: String, - pub amount: i64, - pub payee: String, - pub notes: String, - pub date: Date, - pub parent_id: Option<String>, -} - -impl Transaction { - pub fn from_row(statement: &Statement) -> Transaction { - Transaction { - id: statement.read("id").unwrap(), - is_parent: statement.read::<i64, &str>("isParent").unwrap() == 1, - is_child: statement.read::<i64, &str>("isChild").unwrap() == 1, - account_id: statement.read("acct").unwrap(), - category_id: statement - .read::<Option<String>, &str>("category") - .map(Option::<String>::unwrap_or_default) - .unwrap(), - amount: statement.read("amount").unwrap(), - payee: statement - .read::<Option<String>, &str>("description") - .map(Option::<String>::unwrap_or_default) - .unwrap(), - notes: statement - .read::<Option<String>, &str>("notes") - .map(Option::<String>::unwrap_or_default) - .unwrap(), - date: Date::from_date_row(statement, "date"), - parent_id: statement.read("parent_id").unwrap(), - } - } -} diff --git a/importers/actualbudget/src/models/actualbudget/zero_budget.rs b/importers/actualbudget/src/models/actualbudget/zero_budget.rs deleted file mode 100644 index 87c88e7..0000000 --- a/importers/actualbudget/src/models/actualbudget/zero_budget.rs +++ /dev/null @@ -1,30 +0,0 @@ -use sqlite::Statement; - -use super::date::Date; - -#[derive(Clone)] -pub struct ZeroBudget { - pub id: String, - pub month: Date, - pub category_id: String, - pub amount: i64, - pub do_carry_over: bool, -} - -impl ZeroBudget { - pub fn from_row(statement: &Statement) -> ZeroBudget { - ZeroBudget { - id: statement.read("id").unwrap(), - month: Date::from_month_row(statement, "month"), - category_id: statement.read("category").unwrap(), - amount: statement.read("amount").unwrap(), - do_carry_over: match statement.read::<i64, &str>("carryover").unwrap() { - 0 => false, - 1 => true, - carryover => { - panic!("carryover column was neither 0 nor 1, but instead {carryover}") - } - }, - } - } -} diff --git a/importers/actualbudget/src/models/budgeting_app/DateTimeUtc.rs b/importers/actualbudget/src/models/budgeting_app/DateTimeUtc.rs deleted file mode 100644 index e44fa8c..0000000 --- a/importers/actualbudget/src/models/budgeting_app/DateTimeUtc.rs +++ /dev/null @@ -1,57 +0,0 @@ -use chrono::{DateTime, Datelike, Utc}; -use diesel::{ - deserialize::{FromSql, FromSqlRow}, - expression::AsExpression, - serialize::ToSql, - sql_types::Text, - sqlite::Sqlite, -}; -use serde::{Deserialize, Serialize}; - -#[derive( - Eq, - PartialEq, - Ord, - PartialOrd, - Serialize, - Deserialize, - Copy, - Clone, - Debug, - AsExpression, - FromSqlRow, -)] -#[diesel(sql_type=Text)] -pub struct DateTimeUtc(DateTime<Utc>); - -impl DateTimeUtc { - pub fn day_diff(&self, other: &DateTimeUtc) -> u32 { - self.0 - .num_days_from_ce() - .abs_diff(other.0.num_days_from_ce()) - } - - pub fn new(date_time_utc: DateTime<Utc>) -> Self { - Self(date_time_utc) - } -} - -impl ToSql<Text, Sqlite> for DateTimeUtc { - fn to_sql<'b>( - &'b self, - out: &mut diesel::serialize::Output<'b, '_, Sqlite>, - ) -> diesel::serialize::Result { - out.set_value((*self).0.to_rfc3339()); - Ok(diesel::serialize::IsNull::No) - } -} - -impl FromSql<Text, Sqlite> for DateTimeUtc { - fn from_sql( - bytes: <Sqlite as diesel::backend::Backend>::RawValue<'_>, - ) -> diesel::deserialize::Result<Self> { - let str: String = FromSql::<Text, Sqlite>::from_sql(bytes)?; - let date_time = str.as_str().parse::<DateTime<Utc>>()?; - Ok(DateTimeUtc(date_time)) - } -} diff --git a/importers/actualbudget/src/models/budgeting_app/account.rs b/importers/actualbudget/src/models/budgeting_app/account.rs deleted file mode 100644 index 165b55c..0000000 --- a/importers/actualbudget/src/models/budgeting_app/account.rs +++ /dev/null @@ -1,8 +0,0 @@ -use super::date_time_utc::DateTimeUtc; - -pub struct Account { - pub id: i32, - pub name: String, - pub opening_balance: i32, - pub opening_date: DateTimeUtc, -} diff --git a/importers/actualbudget/src/models/budgeting_app/budget_update.rs b/importers/actualbudget/src/models/budgeting_app/budget_update.rs deleted file mode 100644 index 9958446..0000000 --- a/importers/actualbudget/src/models/budgeting_app/budget_update.rs +++ /dev/null @@ -1,10 +0,0 @@ -use super::date_time_utc::DateTimeUtc; - -#[derive(Clone)] -pub struct BudgetUpdate { - pub id: i32, - pub category_id: i32, - pub date: DateTimeUtc, - pub new_budget: i32, - pub new_period: i32, -} diff --git a/importers/actualbudget/src/models/budgeting_app/category.rs b/importers/actualbudget/src/models/budgeting_app/category.rs deleted file mode 100644 index 3f51dfd..0000000 --- a/importers/actualbudget/src/models/budgeting_app/category.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub struct Category { - pub id: i32, - pub name: String, -} diff --git a/importers/actualbudget/src/models/budgeting_app/category_transfer.rs b/importers/actualbudget/src/models/budgeting_app/category_transfer.rs deleted file mode 100644 index 0097429..0000000 --- a/importers/actualbudget/src/models/budgeting_app/category_transfer.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub struct CategoryTransfer { - pub id: i32, - pub description: String, - pub quantity: i32, - pub from_category_id: i32, - pub to_category_id: i32, -} diff --git a/importers/actualbudget/src/models/budgeting_app/date_time_utc.rs b/importers/actualbudget/src/models/budgeting_app/date_time_utc.rs deleted file mode 100644 index 69cdfe2..0000000 --- a/importers/actualbudget/src/models/budgeting_app/date_time_utc.rs +++ /dev/null @@ -1,20 +0,0 @@ -use std::{fmt::Display, str::FromStr}; - -use chrono::{DateTime, Utc}; - -#[derive(Clone)] -pub struct DateTimeUtc(DateTime<Utc>); - -impl DateTimeUtc { - pub fn new(date: &str) -> Self { - let mut date_time = String::from(date); - date_time.push_str("T00:00:00.000Z"); - Self(DateTime::<Utc>::from_str(&date_time).unwrap()) - } -} - -impl Display for DateTimeUtc { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.0.fmt(f) - } -} diff --git a/importers/actualbudget/src/models/budgeting_app/mod.rs b/importers/actualbudget/src/models/budgeting_app/mod.rs deleted file mode 100644 index bca0f99..0000000 --- a/importers/actualbudget/src/models/budgeting_app/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub mod account; -pub mod budget_update; -pub mod category; -pub mod category_transfer; -pub mod date_time_utc; -pub mod transaction; -pub mod transaction_categorisation; diff --git a/importers/actualbudget/src/models/budgeting_app/transaction.rs b/importers/actualbudget/src/models/budgeting_app/transaction.rs deleted file mode 100644 index e679e1e..0000000 --- a/importers/actualbudget/src/models/budgeting_app/transaction.rs +++ /dev/null @@ -1,11 +0,0 @@ -use super::date_time_utc::DateTimeUtc; - -#[derive(Clone)] -pub struct Transaction { - pub id: i32, - pub description: String, - pub payee: String, - pub quantity: i32, - pub date: DateTimeUtc, - pub account_id: i32, -} diff --git a/importers/actualbudget/src/models/budgeting_app/transaction_categorisation.rs b/importers/actualbudget/src/models/budgeting_app/transaction_categorisation.rs deleted file mode 100644 index ca7e7f5..0000000 --- a/importers/actualbudget/src/models/budgeting_app/transaction_categorisation.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub struct TransactionCategorisation { - pub id: i32, - pub description: String, - pub quantity: i32, - pub transaction_id: i32, - pub category_id: i32, -} diff --git a/importers/actualbudget/src/models/mod.rs b/importers/actualbudget/src/models/mod.rs deleted file mode 100644 index cf1b71a..0000000 --- a/importers/actualbudget/src/models/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod actualbudget; -pub mod budgeting_app; diff --git a/importers/actualbudget/src/transformers.rs b/importers/actualbudget/src/transformers.rs deleted file mode 100644 index 678ea05..0000000 --- a/importers/actualbudget/src/transformers.rs +++ /dev/null @@ -1,221 +0,0 @@ -use core::panic; -use std::hash::{DefaultHasher, Hash, Hasher}; - -use crate::models::{ - actualbudget, - budgeting_app::{ - account::Account, budget_update::BudgetUpdate, category::Category, - category_transfer::CategoryTransfer, date_time_utc::DateTimeUtc, transaction::Transaction, - transaction_categorisation::TransactionCategorisation, - }, -}; - -pub fn transform_date(actualbudget_date: &actualbudget::date::Date) -> DateTimeUtc { - DateTimeUtc::new(&actualbudget_date.to_iso()) -} - -pub fn transform_accounts( - actualbudget_accounts: &[actualbudget::account::Account], - first_transaction_date: &DateTimeUtc, -) -> Vec<Account> { - let mut accounts = Vec::<Account>::new(); - for account in actualbudget_accounts { - accounts.push(transform_account(account, first_transaction_date)); - } - accounts -} - -fn transform_account( - actualbudget_account: &actualbudget::account::Account, - opening_date: &DateTimeUtc, -) -> Account { - Account { - id: transform_id(&actualbudget_account.id.clone()), - name: actualbudget_account.name.clone(), - opening_balance: 0, - opening_date: opening_date.clone(), - } -} - -pub fn transform_categories( - actualbudget_categories: &[actualbudget::category::Category], -) -> Vec<Category> { - let mut categories = Vec::<Category>::new(); - for actualbudget_category in actualbudget_categories { - categories.push(Category { - id: transform_id(&actualbudget_category.id.clone()), - name: actualbudget_category.name.clone(), - }) - } - categories -} - -fn transform_id(actualbudget_id: &str) -> i32 { - let mut hasher = DefaultHasher::new(); - actualbudget_id.hash(&mut hasher); - (hasher.finish() % std::convert::TryInto::<u64>::try_into(i32::MAX).unwrap()) - .try_into() - .unwrap() -} - -pub fn transform_budget_updates( - actualbudget_zero_budgets: &[actualbudget::zero_budget::ZeroBudget], -) -> Vec<BudgetUpdate> { - let mut budget_updates = Vec::<BudgetUpdate>::new(); - for zero_budget in actualbudget_zero_budgets { - let first_zero_budget_in_category = get_first_zero_budget_in_category( - actualbudget_zero_budgets, - &zero_budget.category_id.clone(), - ); - if first_zero_budget_in_category.is_some_and(|zb| zb.id == zero_budget.id) { - continue; - } - budget_updates.push(BudgetUpdate { - id: transform_id(&zero_budget.id.clone()), - category_id: transform_id(&zero_budget.category_id.clone()), - date: transform_date(&zero_budget.month.clone()), - new_budget: zero_budget.amount.try_into().unwrap(), - new_period: 30, - }) - } - budget_updates -} - -fn get_first_zero_budget_in_category( - actualbudget_zero_budgets: &[actualbudget::zero_budget::ZeroBudget], - actualbudget_category_id: &str, -) -> Option<actualbudget::zero_budget::ZeroBudget> { - let mut category_zero_budgets = actualbudget_zero_budgets.to_vec(); - category_zero_budgets.retain(|zb| zb.category_id == actualbudget_category_id); - category_zero_budgets - .iter() - .min_by_key(|zb| zb.month.clone()) - .cloned() -} - -pub fn transform_transactions( - actualbudget_transactions: &[actualbudget::transaction::Transaction], - actualbudget_category_transfers_account: &actualbudget::account::Account, -) -> (Vec<Transaction>, Vec<TransactionCategorisation>) { - let mut transactions = Vec::<Transaction>::new(); - let mut transaction_categorisations = Vec::<TransactionCategorisation>::new(); - - let mut actualbudget_transactions = actualbudget_transactions.to_vec(); - actualbudget_transactions - .retain(|t| t.category_id.clone() != actualbudget_category_transfers_account.id.clone()); - let mut parent_actualbudget_transactions = actualbudget_transactions.to_vec(); - parent_actualbudget_transactions.retain(|t| t.is_parent); - let mut child_actualbudget_transactions = actualbudget_transactions.to_vec(); - child_actualbudget_transactions.retain(|t| t.is_child); - let mut atomic_actualbudget_transactions = actualbudget_transactions.to_vec(); - atomic_actualbudget_transactions.retain(|t| !t.is_parent && !t.is_child); - - for atomic_actualbudget_transaction in atomic_actualbudget_transactions { - let transaction_id = transform_id(&atomic_actualbudget_transaction.id); - - transactions.push(Transaction { - id: transaction_id, - description: atomic_actualbudget_transaction.notes, - payee: atomic_actualbudget_transaction.payee, - quantity: atomic_actualbudget_transaction.amount.try_into().unwrap(), - date: transform_date(&atomic_actualbudget_transaction.date), - account_id: transform_id(&atomic_actualbudget_transaction.account_id), - }); - - transaction_categorisations.push(TransactionCategorisation { - id: transaction_id, - description: String::new(), - quantity: atomic_actualbudget_transaction.amount.try_into().unwrap(), - transaction_id, - category_id: transform_id(&atomic_actualbudget_transaction.category_id), - }); - } - - for parent_actualbudget_transaction in parent_actualbudget_transactions { - let mut child_actualbudget_transactions = child_actualbudget_transactions.to_vec(); - child_actualbudget_transactions.retain(|t| { - t.parent_id - .clone() - .is_some_and(|parent_id| parent_id == parent_actualbudget_transaction.id.clone()) - }); - - let transaction_id = transform_id(&parent_actualbudget_transaction.id); - - transactions.push(Transaction { - id: transaction_id, - description: parent_actualbudget_transaction.notes, - payee: parent_actualbudget_transaction.payee, - quantity: parent_actualbudget_transaction.amount.try_into().unwrap(), - date: transform_date(&parent_actualbudget_transaction.date), - account_id: transform_id(&parent_actualbudget_transaction.account_id), - }); - - for child_actualbudget_transaction in child_actualbudget_transactions { - transaction_categorisations.push(TransactionCategorisation { - id: transform_id(&child_actualbudget_transaction.id), - description: child_actualbudget_transaction.notes, - quantity: child_actualbudget_transaction.amount.try_into().unwrap(), - transaction_id, - category_id: transform_id(&child_actualbudget_transaction.category_id), - }); - } - } - - (transactions, transaction_categorisations) -} - -pub fn transform_category_transfers( - actualbudget_transactions: &[actualbudget::transaction::Transaction], - actualbudget_category_transfers_account: &actualbudget::account::Account, -) -> Vec<CategoryTransfer> { - let mut category_transfers = Vec::<CategoryTransfer>::new(); - - let mut actualbudget_category_transfers = actualbudget_transactions.to_vec(); - actualbudget_category_transfers - .retain(|t| t.category_id.clone() == actualbudget_category_transfers_account.id.clone()); - let mut actualbudget_parent_category_transfers = actualbudget_category_transfers.to_vec(); - actualbudget_parent_category_transfers.retain(|t| t.is_parent); - let mut actualbudget_child_category_transfers = actualbudget_category_transfers.to_vec(); - actualbudget_child_category_transfers.retain(|t| t.is_child); - - for actualbudget_parent_category_transfer in actualbudget_parent_category_transfers { - let mut actualbudget_child_category_transfers = - actualbudget_child_category_transfers.to_vec(); - actualbudget_child_category_transfers.retain(|t| { - t.parent_id - .clone() - .is_some_and(|parent_id| parent_id == actualbudget_parent_category_transfer.id) - }); - - if actualbudget_child_category_transfers.len() != 2 { - panic!("Category transfers should always have exactly two children."); - } - - let category_1 = actualbudget_child_category_transfers[0].clone(); - let category_2 = actualbudget_child_category_transfers[1].clone(); - - // To avoid duplicates - if category_1.amount >= 0 { - continue; - } - - if actualbudget_child_category_transfers[0].amount - != -actualbudget_child_category_transfers[1].amount - { - panic!("Category transfer children should sum to zero."); - } - - category_transfers.push(CategoryTransfer { - id: transform_id(&actualbudget_parent_category_transfer.id), - description: actualbudget_parent_category_transfer.notes, - quantity: actualbudget_child_category_transfers[0] - .amount - .try_into() - .unwrap(), - from_category_id: transform_id(&category_1.id), - to_category_id: transform_id(&category_2.id), - }); - } - - category_transfers -} |
