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 /backend/importers/actualbudget/src/models | |
| parent | 76974785294089965efc3f55b2a08d4089029c52 (diff) | |
All backend stuff lives in backend folder
Diffstat (limited to 'backend/importers/actualbudget/src/models')
16 files changed, 310 insertions, 0 deletions
diff --git a/backend/importers/actualbudget/src/models/actualbudget/account.rs b/backend/importers/actualbudget/src/models/actualbudget/account.rs new file mode 100644 index 0000000..727c082 --- /dev/null +++ b/backend/importers/actualbudget/src/models/actualbudget/account.rs @@ -0,0 +1,15 @@ +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/backend/importers/actualbudget/src/models/actualbudget/category.rs b/backend/importers/actualbudget/src/models/actualbudget/category.rs new file mode 100644 index 0000000..21fdf80 --- /dev/null +++ b/backend/importers/actualbudget/src/models/actualbudget/category.rs @@ -0,0 +1,15 @@ +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/backend/importers/actualbudget/src/models/actualbudget/date.rs b/backend/importers/actualbudget/src/models/actualbudget/date.rs new file mode 100644 index 0000000..bd37c46 --- /dev/null +++ b/backend/importers/actualbudget/src/models/actualbudget/date.rs @@ -0,0 +1,69 @@ +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/backend/importers/actualbudget/src/models/actualbudget/mod.rs b/backend/importers/actualbudget/src/models/actualbudget/mod.rs new file mode 100644 index 0000000..5ca472f --- /dev/null +++ b/backend/importers/actualbudget/src/models/actualbudget/mod.rs @@ -0,0 +1,5 @@ +pub mod account; +pub mod category; +pub mod date; +pub mod transaction; +pub mod zero_budget; diff --git a/backend/importers/actualbudget/src/models/actualbudget/transaction.rs b/backend/importers/actualbudget/src/models/actualbudget/transaction.rs new file mode 100644 index 0000000..0a21cfe --- /dev/null +++ b/backend/importers/actualbudget/src/models/actualbudget/transaction.rs @@ -0,0 +1,43 @@ +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/backend/importers/actualbudget/src/models/actualbudget/zero_budget.rs b/backend/importers/actualbudget/src/models/actualbudget/zero_budget.rs new file mode 100644 index 0000000..87c88e7 --- /dev/null +++ b/backend/importers/actualbudget/src/models/actualbudget/zero_budget.rs @@ -0,0 +1,30 @@ +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/backend/importers/actualbudget/src/models/budgeting_app/DateTimeUtc.rs b/backend/importers/actualbudget/src/models/budgeting_app/DateTimeUtc.rs new file mode 100644 index 0000000..e44fa8c --- /dev/null +++ b/backend/importers/actualbudget/src/models/budgeting_app/DateTimeUtc.rs @@ -0,0 +1,57 @@ +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/backend/importers/actualbudget/src/models/budgeting_app/account.rs b/backend/importers/actualbudget/src/models/budgeting_app/account.rs new file mode 100644 index 0000000..165b55c --- /dev/null +++ b/backend/importers/actualbudget/src/models/budgeting_app/account.rs @@ -0,0 +1,8 @@ +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/backend/importers/actualbudget/src/models/budgeting_app/budget_update.rs b/backend/importers/actualbudget/src/models/budgeting_app/budget_update.rs new file mode 100644 index 0000000..9958446 --- /dev/null +++ b/backend/importers/actualbudget/src/models/budgeting_app/budget_update.rs @@ -0,0 +1,10 @@ +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/backend/importers/actualbudget/src/models/budgeting_app/category.rs b/backend/importers/actualbudget/src/models/budgeting_app/category.rs new file mode 100644 index 0000000..3f51dfd --- /dev/null +++ b/backend/importers/actualbudget/src/models/budgeting_app/category.rs @@ -0,0 +1,4 @@ +pub struct Category { + pub id: i32, + pub name: String, +} diff --git a/backend/importers/actualbudget/src/models/budgeting_app/category_transfer.rs b/backend/importers/actualbudget/src/models/budgeting_app/category_transfer.rs new file mode 100644 index 0000000..0097429 --- /dev/null +++ b/backend/importers/actualbudget/src/models/budgeting_app/category_transfer.rs @@ -0,0 +1,7 @@ +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/backend/importers/actualbudget/src/models/budgeting_app/date_time_utc.rs b/backend/importers/actualbudget/src/models/budgeting_app/date_time_utc.rs new file mode 100644 index 0000000..69cdfe2 --- /dev/null +++ b/backend/importers/actualbudget/src/models/budgeting_app/date_time_utc.rs @@ -0,0 +1,20 @@ +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/backend/importers/actualbudget/src/models/budgeting_app/mod.rs b/backend/importers/actualbudget/src/models/budgeting_app/mod.rs new file mode 100644 index 0000000..bca0f99 --- /dev/null +++ b/backend/importers/actualbudget/src/models/budgeting_app/mod.rs @@ -0,0 +1,7 @@ +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/backend/importers/actualbudget/src/models/budgeting_app/transaction.rs b/backend/importers/actualbudget/src/models/budgeting_app/transaction.rs new file mode 100644 index 0000000..e679e1e --- /dev/null +++ b/backend/importers/actualbudget/src/models/budgeting_app/transaction.rs @@ -0,0 +1,11 @@ +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/backend/importers/actualbudget/src/models/budgeting_app/transaction_categorisation.rs b/backend/importers/actualbudget/src/models/budgeting_app/transaction_categorisation.rs new file mode 100644 index 0000000..ca7e7f5 --- /dev/null +++ b/backend/importers/actualbudget/src/models/budgeting_app/transaction_categorisation.rs @@ -0,0 +1,7 @@ +pub struct TransactionCategorisation { + pub id: i32, + pub description: String, + pub quantity: i32, + pub transaction_id: i32, + pub category_id: i32, +} diff --git a/backend/importers/actualbudget/src/models/mod.rs b/backend/importers/actualbudget/src/models/mod.rs new file mode 100644 index 0000000..cf1b71a --- /dev/null +++ b/backend/importers/actualbudget/src/models/mod.rs @@ -0,0 +1,2 @@ +pub mod actualbudget; +pub mod budgeting_app; |
