diff options
| author | Joe Carstairs <me@joeac.net> | 2024-11-17 12:16:19 +0000 |
|---|---|---|
| committer | Joe Carstairs <me@joeac.net> | 2024-11-17 12:20:48 +0000 |
| commit | 99fa72e2b9d572e00cd232bd55a3fa24722c3134 (patch) | |
| tree | 6b50ce600fffa07a0c21b7f14d2447fe5ac3c2ed /rust/actualbudget_importer/src | |
| parent | 10f071447594f2bdcec84a461df9ad648f71f44b (diff) | |
Refactors workspace
Diffstat (limited to 'rust/actualbudget_importer/src')
20 files changed, 0 insertions, 508 deletions
diff --git a/rust/actualbudget_importer/src/main.rs b/rust/actualbudget_importer/src/main.rs deleted file mode 100644 index 78c64f4..0000000 --- a/rust/actualbudget_importer/src/main.rs +++ /dev/null @@ -1,45 +0,0 @@ -pub mod models; -pub mod queries; -pub mod schema; -pub mod transformers; - -use anyhow::Result; -use schist_core::queries as schist_queries; -use diesel::{Connection, SqliteConnection}; -use queries::{actualbudget_accounts::{get_all_actualbudget_accounts, get_category_transfers_account}, actualbudget_categories::get_all_actualbudget_categories, actualbudget_transactions::{get_all_actualbudget_transactions, get_first_actualbudget_transaction_date}, actualbudget_zero_budgets::get_all_actualbudget_zero_budgets}; - -fn main() -> Result<()> { - let connection_src = &mut SqliteConnection::establish("in.sqlite").unwrap(); - let connection_dest = &mut SqliteConnection::establish("out.sqlite").unwrap(); - - let actualbudget_first_transaction_date = get_first_actualbudget_transaction_date(connection_src)?; - let actualbudget_accounts = get_all_actualbudget_accounts(connection_src)?; - let actualbudget_categories = get_all_actualbudget_categories(connection_src)?; - let actualbudget_zero_budgets = get_all_actualbudget_zero_budgets(connection_src)?; - let actualbudget_category_transfers_account = get_category_transfers_account(connection_src)?; - let actualbudget_transactions = get_all_actualbudget_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, - ); - - schist_queries::clear::clear(connection_dest)?; - schist_queries::accounts::insert_accounts(&accounts, connection_dest)?; - schist_queries::categories::insert_categories(&categories, connection_dest)?; - schist_queries::budget_updates::insert_budget_updates(&budget_updates, connection_dest)?; - schist_queries::transactions::insert_transactions(&transactions, connection_dest)?; - schist_queries::transaction_categorisations::insert_transaction_categorisations(&transaction_categorisations, connection_dest)?; - schist_queries::category_transfers::insert_category_transfers(&category_transfers, connection_dest)?; - - Ok(()) -} diff --git a/rust/actualbudget_importer/src/models/actualbudget_account.rs b/rust/actualbudget_importer/src/models/actualbudget_account.rs deleted file mode 100644 index b3d00ac..0000000 --- a/rust/actualbudget_importer/src/models/actualbudget_account.rs +++ /dev/null @@ -1,8 +0,0 @@ -use diesel::prelude::{Queryable, Selectable}; - -#[derive(Queryable, Selectable)] -#[diesel(table_name = crate::schema::accounts)] -pub struct ActualbudgetAccount { - pub id: String, - pub name: String, -} diff --git a/rust/actualbudget_importer/src/models/actualbudget_category.rs b/rust/actualbudget_importer/src/models/actualbudget_category.rs deleted file mode 100644 index cbea99b..0000000 --- a/rust/actualbudget_importer/src/models/actualbudget_category.rs +++ /dev/null @@ -1,8 +0,0 @@ -use diesel::{prelude::Queryable, Selectable}; - -#[derive(Queryable, Selectable)] -#[diesel(table_name = crate::schema::categories)] -pub struct ActualbudgetCategory { - pub id: String, - pub name: String, -} diff --git a/rust/actualbudget_importer/src/models/actualbudget_date.rs b/rust/actualbudget_importer/src/models/actualbudget_date.rs deleted file mode 100644 index bef160c..0000000 --- a/rust/actualbudget_importer/src/models/actualbudget_date.rs +++ /dev/null @@ -1,75 +0,0 @@ -use diesel::{backend::Backend, deserialize::{FromSql, FromSqlRow}, expression::AsExpression, sql_types::Integer, sqlite::Sqlite}; - -#[derive(Clone, PartialEq, Eq, Debug, AsExpression, FromSqlRow)] -#[diesel(sql_type=Integer)] -pub struct ActualbudgetDate(i32); - -#[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 ActualbudgetDate { - pub fn to_iso(&self) -> String { - format!("{0}-{1}-{2}", self.year(), self.month(), self.day()) - } - - pub fn year(&self) -> String { - self.0.to_string()[0..4].to_string() - } - - pub fn month(&self) -> String { - self.0.to_string()[4..6].to_string() - } - - pub fn day(&self) -> String { - match self.date_part() { - DatePart::DayOfMonth => self.0.to_string()[6..8].to_string(), - DatePart::MonthOfYear => String::from("01"), - } - } - - pub fn from_i32(i: i32) -> Self { - ActualbudgetDate(i) - } - - fn date_part(&self) -> DatePart { - if self.0 < 10000000 { - DatePart::MonthOfYear - } else { - DatePart::DayOfMonth - } - } - - fn dayified_value(&self) -> i32 { - match self.date_part() { - DatePart::DayOfMonth => self.0, - DatePart::MonthOfYear => self.0 * 100 + 1, - } - } -} - -impl Ord for ActualbudgetDate { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.dayified_value().cmp(&other.dayified_value()) - } -} - -impl PartialOrd for ActualbudgetDate { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - Some(self.cmp(other)) - } -} - -impl FromSql<Integer, Sqlite> for ActualbudgetDate { - fn from_sql(bytes: <Sqlite as Backend>::RawValue<'_>) -> diesel::deserialize::Result<Self> { - let int: i32 = FromSql::<Integer, Sqlite>::from_sql(bytes)?; - Ok(ActualbudgetDate(int)) - } -} diff --git a/rust/actualbudget_importer/src/models/actualbudget_transaction.rs b/rust/actualbudget_importer/src/models/actualbudget_transaction.rs deleted file mode 100644 index be2ca1a..0000000 --- a/rust/actualbudget_importer/src/models/actualbudget_transaction.rs +++ /dev/null @@ -1,18 +0,0 @@ -use diesel::prelude::{Identifiable, Queryable, QueryableByName, Selectable}; - -use crate::models::actualbudget_date::ActualbudgetDate; - -#[derive(Identifiable, QueryableByName, Queryable, Selectable, Clone)] -#[diesel(table_name = crate::schema::transactions)] -pub struct ActualbudgetTransaction { - pub id: String, - pub is_parent: bool, - pub is_child: bool, - pub account_id: String, - pub category_id: String, - pub amount: i32, - pub payee: String, - pub notes: String, - pub date: ActualbudgetDate, - pub parent_id: Option<String>, -} diff --git a/rust/actualbudget_importer/src/models/actualbudget_zero_budget.rs b/rust/actualbudget_importer/src/models/actualbudget_zero_budget.rs deleted file mode 100644 index 6478d34..0000000 --- a/rust/actualbudget_importer/src/models/actualbudget_zero_budget.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::models::actualbudget_date::ActualbudgetDate; -use diesel::{prelude::{Identifiable, Queryable, QueryableByName, Selectable}, sqlite::Sqlite}; - -#[derive(Identifiable, QueryableByName, Queryable, Selectable, Clone)] -#[diesel(table_name = crate::schema::zero_budgets)] -#[diesel(check_for_backend(Sqlite))] -pub struct ActualbudgetZeroBudget { - pub id: String, - pub month: ActualbudgetDate, - pub category_id: String, - pub amount: i32, - pub do_carry_over: i32, -} diff --git a/rust/actualbudget_importer/src/models/mod.rs b/rust/actualbudget_importer/src/models/mod.rs deleted file mode 100644 index 1c97c65..0000000 --- a/rust/actualbudget_importer/src/models/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod actualbudget_account; -pub mod actualbudget_category; -pub mod actualbudget_date; -pub mod actualbudget_transaction; -pub mod actualbudget_zero_budget; diff --git a/rust/actualbudget_importer/src/queries/actualbudget_accounts/get_all.rs b/rust/actualbudget_importer/src/queries/actualbudget_accounts/get_all.rs deleted file mode 100644 index 6f667de..0000000 --- a/rust/actualbudget_importer/src/queries/actualbudget_accounts/get_all.rs +++ /dev/null @@ -1,6 +0,0 @@ -use crate::{models::actualbudget_account::ActualbudgetAccount, schema::accounts::dsl::accounts}; -use diesel::{result::Error, QueryDsl, RunQueryDsl, SelectableHelper, SqliteConnection}; - -pub fn get_all_actualbudget_accounts(connection: &mut SqliteConnection) -> Result<Vec<ActualbudgetAccount>, Error> { - accounts.select(ActualbudgetAccount::as_select()).load(connection) -} diff --git a/rust/actualbudget_importer/src/queries/actualbudget_accounts/get_category_transfers_account.rs b/rust/actualbudget_importer/src/queries/actualbudget_accounts/get_category_transfers_account.rs deleted file mode 100644 index f05dc78..0000000 --- a/rust/actualbudget_importer/src/queries/actualbudget_accounts/get_category_transfers_account.rs +++ /dev/null @@ -1,13 +0,0 @@ -use diesel::{result::Error, ExpressionMethods, QueryDsl, RunQueryDsl, SelectableHelper, SqliteConnection}; - -use crate::{models::actualbudget_account::ActualbudgetAccount, schema::accounts::{ - self as accounts_schema, - dsl::accounts as accounts_table, -}}; - -pub fn get_category_transfers_account(connection: &mut SqliteConnection) -> Result<ActualbudgetAccount, Error> { - accounts_table - .filter(accounts_schema::name.eq("Category transfers")) - .select(ActualbudgetAccount::as_select()) - .first(connection) -} diff --git a/rust/actualbudget_importer/src/queries/actualbudget_accounts/mod.rs b/rust/actualbudget_importer/src/queries/actualbudget_accounts/mod.rs deleted file mode 100644 index c6d6015..0000000 --- a/rust/actualbudget_importer/src/queries/actualbudget_accounts/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod get_all; -mod get_category_transfers_account; - -pub use get_all::get_all_actualbudget_accounts; -pub use get_category_transfers_account::get_category_transfers_account; diff --git a/rust/actualbudget_importer/src/queries/actualbudget_categories/get_all.rs b/rust/actualbudget_importer/src/queries/actualbudget_categories/get_all.rs deleted file mode 100644 index 4cb7ebc..0000000 --- a/rust/actualbudget_importer/src/queries/actualbudget_categories/get_all.rs +++ /dev/null @@ -1,6 +0,0 @@ -use crate::{models::actualbudget_category::ActualbudgetCategory, schema::categories::dsl::categories}; -use diesel::{result::Error, QueryDsl, RunQueryDsl, SelectableHelper, SqliteConnection}; - -pub fn get_all_actualbudget_categories(connection: &mut SqliteConnection) -> Result<Vec<ActualbudgetCategory>, Error> { - categories.select(ActualbudgetCategory::as_select()).load(connection) -} diff --git a/rust/actualbudget_importer/src/queries/actualbudget_categories/mod.rs b/rust/actualbudget_importer/src/queries/actualbudget_categories/mod.rs deleted file mode 100644 index 0c04e53..0000000 --- a/rust/actualbudget_importer/src/queries/actualbudget_categories/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod get_all; - -pub use get_all::get_all_actualbudget_categories; diff --git a/rust/actualbudget_importer/src/queries/actualbudget_transactions/get_all.rs b/rust/actualbudget_importer/src/queries/actualbudget_transactions/get_all.rs deleted file mode 100644 index 84c8d08..0000000 --- a/rust/actualbudget_importer/src/queries/actualbudget_transactions/get_all.rs +++ /dev/null @@ -1,6 +0,0 @@ -use crate::{models::actualbudget_transaction::ActualbudgetTransaction, schema::transactions::dsl::transactions}; -use diesel::{result::Error, QueryDsl, RunQueryDsl, SelectableHelper, SqliteConnection}; - -pub fn get_all_actualbudget_transactions(connection: &mut SqliteConnection) -> Result<Vec<ActualbudgetTransaction>, Error> { - transactions.select(ActualbudgetTransaction::as_select()).load(connection) -} diff --git a/rust/actualbudget_importer/src/queries/actualbudget_transactions/get_first_date.rs b/rust/actualbudget_importer/src/queries/actualbudget_transactions/get_first_date.rs deleted file mode 100644 index b958c37..0000000 --- a/rust/actualbudget_importer/src/queries/actualbudget_transactions/get_first_date.rs +++ /dev/null @@ -1,14 +0,0 @@ -use anyhow::Result; -use crate::{models::actualbudget_date::ActualbudgetDate, schema::transactions::{ - self as transactions_schema, - dsl::transactions as transactions_table, -}}; -use diesel::{dsl::min, result::Error, QueryDsl, RunQueryDsl, SqliteConnection}; - -pub fn get_first_actualbudget_transaction_date(connection: &mut SqliteConnection) -> Result<ActualbudgetDate> { - let date_as_int = transactions_table - .select(min(transactions_schema::date)) - .first::<Option<i32>>(connection) - .map_or_else(|e| Err(e), |o| o.map_or_else(|| Err(Error::NotFound), |i| Ok(i)))?; - Ok(ActualbudgetDate::from_i32(date_as_int)) -} diff --git a/rust/actualbudget_importer/src/queries/actualbudget_transactions/mod.rs b/rust/actualbudget_importer/src/queries/actualbudget_transactions/mod.rs deleted file mode 100644 index b4ed0dd..0000000 --- a/rust/actualbudget_importer/src/queries/actualbudget_transactions/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod get_all; -mod get_first_date; - -pub use get_all::get_all_actualbudget_transactions; -pub use get_first_date::get_first_actualbudget_transaction_date; diff --git a/rust/actualbudget_importer/src/queries/actualbudget_zero_budgets/get_all.rs b/rust/actualbudget_importer/src/queries/actualbudget_zero_budgets/get_all.rs deleted file mode 100644 index 0c3f695..0000000 --- a/rust/actualbudget_importer/src/queries/actualbudget_zero_budgets/get_all.rs +++ /dev/null @@ -1,6 +0,0 @@ -use crate::{models::actualbudget_zero_budget::ActualbudgetZeroBudget, schema::zero_budgets::dsl::zero_budgets}; -use diesel::{result::Error, QueryDsl, RunQueryDsl, SelectableHelper, SqliteConnection}; - -pub fn get_all_actualbudget_zero_budgets(connection: &mut SqliteConnection) -> Result<Vec<ActualbudgetZeroBudget>, Error> { - zero_budgets.select(ActualbudgetZeroBudget::as_select()).load(connection) -} diff --git a/rust/actualbudget_importer/src/queries/actualbudget_zero_budgets/mod.rs b/rust/actualbudget_importer/src/queries/actualbudget_zero_budgets/mod.rs deleted file mode 100644 index ba7e21b..0000000 --- a/rust/actualbudget_importer/src/queries/actualbudget_zero_budgets/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod get_all; - -pub use get_all::get_all_actualbudget_zero_budgets; diff --git a/rust/actualbudget_importer/src/queries/mod.rs b/rust/actualbudget_importer/src/queries/mod.rs deleted file mode 100644 index e16dafc..0000000 --- a/rust/actualbudget_importer/src/queries/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod actualbudget_accounts; -pub mod actualbudget_categories; -pub mod actualbudget_transactions; -pub mod actualbudget_zero_budgets; diff --git a/rust/actualbudget_importer/src/schema.rs b/rust/actualbudget_importer/src/schema.rs deleted file mode 100644 index a872231..0000000 --- a/rust/actualbudget_importer/src/schema.rs +++ /dev/null @@ -1,47 +0,0 @@ -diesel::table! { - accounts (id) { - id -> Text, - name -> Text, - } -} - -diesel::table! { - categories (id) { - id -> Text, - name -> Text, - } -} - -diesel::table! { - transactions (id) { - id -> Text, - #[sql_name = "isParent"] - is_parent -> Bool, - #[sql_name = "isChild"] - is_child -> Bool, - #[sql_name = "acct"] - account_id -> Text, - #[sql_name = "category"] - category_id -> Text, - amount -> Integer, - #[sql_name = "description"] - payee -> Text, - notes -> Text, - date -> Integer, - parent_id -> Nullable<Text>, - } -} - -diesel::table! { - zero_budgets (id) { - id -> Text, - month -> Integer, - #[sql_name = "category"] - category_id -> Text, - amount -> Integer, - #[sql_name = "carryover"] - do_carry_over -> Integer, - // goal -> Integer, - // long_goal -> Integer, - } -} diff --git a/rust/actualbudget_importer/src/transformers.rs b/rust/actualbudget_importer/src/transformers.rs deleted file mode 100644 index 7e8141a..0000000 --- a/rust/actualbudget_importer/src/transformers.rs +++ /dev/null @@ -1,218 +0,0 @@ -use anyhow::Result; -use schist_core::models::{ - account::Account, budget_update::BudgetUpdate, category::Category, category_transfer::CategoryTransfer, date_utc::DateUtc, datetime_utc::DatetimeUtc, transaction::Transaction, transaction_categorisation::TransactionCategorisation -}; -use core::panic; -use std::hash::{DefaultHasher, Hash, Hasher}; - -use crate::models::{actualbudget_account::ActualbudgetAccount, actualbudget_category::ActualbudgetCategory, actualbudget_date::ActualbudgetDate, actualbudget_transaction::ActualbudgetTransaction, actualbudget_zero_budget::ActualbudgetZeroBudget}; - -pub fn transform_date(actualbudget_date: &ActualbudgetDate) -> Result<DatetimeUtc> { - actualbudget_date.to_iso().parse() -} - -pub fn transform_accounts( - actualbudget_accounts: &[ActualbudgetAccount], - 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: &ActualbudgetAccount, - 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: &[ActualbudgetCategory], -) -> 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: &[ActualbudgetZeroBudget], -) -> Result<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: DateUtc::from(transform_date(&zero_budget.month.clone())?), - new_budget: zero_budget.amount.try_into().unwrap(), - new_period: 30, - }) - } - Ok(budget_updates) -} - -fn get_first_zero_budget_in_category( - actualbudget_zero_budgets: &[ActualbudgetZeroBudget], - actualbudget_category_id: &str, -) -> Option<ActualbudgetZeroBudget> { - 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: &[ActualbudgetTransaction], - actualbudget_category_transfers_account: &ActualbudgetAccount, -) -> Result<(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), - }); - } - } - - Ok((transactions, transaction_categorisations)) -} - -pub fn transform_category_transfers( - actualbudget_transactions: &[ActualbudgetTransaction], - actualbudget_category_transfers_account: &ActualbudgetAccount, -) -> 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 -} |
