Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ rex-shared = "0.2.0"
rex-db = "0.2.2"
rex-app = "0.2.2"
chrono = "0.4.42"
diesel = { version = "2.3.2", default-features = false, features = [
diesel = { version = "2.3.3", default-features = false, features = [
"returning_clauses_for_sqlite_3_35",
"sqlite",
"chrono",
] }
anyhow = "1.0.100"
strum = "0.27"
strum_macros = "0.27"

# The profile that 'cargo dist' will build with
[profile.dist]
Expand Down
3 changes: 3 additions & 0 deletions app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ rex-shared.workspace = true
chrono.workspace = true
anyhow.workspace = true
diesel.workspace = true
strum.workspace = true
strum_macros.workspace = true
log = "0.4.28"
strsim = "0.11.1"
thiserror = "2.0.17"

Expand Down
6 changes: 3 additions & 3 deletions app/src/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ pub fn start_migration(mut old_db_conn: DbConn, db_conn: &mut DbConn) -> Result<
let mut skipped_activity_id = HashSet::new();

for row in rows {
let method = row.tx_method.to_string();
let method = row.tx_method.clone();

let from_method;
let mut to_method = String::new();
Expand Down Expand Up @@ -348,10 +348,10 @@ fn migrate_tx(

let mut tx_tags = Vec::new();

for tag in tag_list {
for (index, tag) in tag_list.into_iter().enumerate() {
let tag_data = NewTag::new(&tag).insert(db_conn)?;

let tx_tag = TxTag::new(added_tx.id, tag_data.id);
let tx_tag = TxTag::new(added_tx.id, tag_data.id, index == 0);

tx_tags.push(tx_tag);
}
Expand Down
6 changes: 3 additions & 3 deletions app/src/modifier/new_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ pub(crate) fn add_new_tx(

let mut tx_tags = Vec::new();

for tag in tag_list {
for (index, tag) in tag_list.into_iter().enumerate() {
if let Ok(tag_id) = db_conn.cache().get_tag_id(&tag) {
let tx_tag = TxTag::new(added_tx.id, tag_id);
let tx_tag = TxTag::new(added_tx.id, tag_id, index == 0);
tx_tags.push(tx_tag);
continue;
}
Expand All @@ -106,7 +106,7 @@ pub(crate) fn add_new_tx(

new_tags.push(tag_data.clone());

let tx_tag = TxTag::new(added_tx.id, tag_data.id);
let tx_tag = TxTag::new(added_tx.id, tag_data.id, index == 0);

tx_tags.push(tx_tag);
}
Expand Down
10 changes: 6 additions & 4 deletions app/src/modifier/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use anyhow::{Result, anyhow};
use chrono::{Days, Local, Months, NaiveDate, NaiveTime};
use rex_db::ConnCache;
use rex_db::models::{Balance, DateNature, FetchNature, NewSearch, NewTx, Tx, TxType};
use rex_shared::models::Dollar;
use rex_shared::models::{Dollar, LAST_POSSIBLE_TIME};

use crate::utils::parse_amount_nature_cent;

Expand Down Expand Up @@ -118,7 +118,7 @@ pub fn parse_search_fields<'a>(

let end_date = NaiveDate::from_ymd_opt(year + 1, 1, 1)
.ok_or_else(|| anyhow!("{year} is an invalid year"))?
.and_time(NaiveTime::MIN);
.and_time(LAST_POSSIBLE_TIME);

Some(DateNature::ByYear {
start_date,
Expand All @@ -130,11 +130,13 @@ pub fn parse_search_fields<'a>(
let month = split_date[1].parse::<u32>()?;

let start_date = NaiveDate::from_ymd_opt(year, month, 1)
.ok_or_else(|| anyhow!("{year} or {month} value is invalid"))?
.and_time(NaiveTime::MIN);
.ok_or_else(|| anyhow!("{year} or {month} value is invalid"))?;

let end_date = start_date + Months::new(1) - Days::new(1);

let start_date = start_date.and_time(NaiveTime::MIN);
let end_date = end_date.and_time(LAST_POSSIBLE_TIME);

Some(DateNature::ByMonth {
start_date,
end_date,
Expand Down
56 changes: 30 additions & 26 deletions app/src/ui_helper/autofiller.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use rex_db::ConnCache;
use rex_db::models::TxType;
use strum::IntoEnumIterator;

use crate::conn::MutDbConn;
use crate::ui_helper::get_best_match;
Expand All @@ -8,8 +9,6 @@ pub struct Autofiller<'a> {
conn: MutDbConn<'a>,
}

pub(crate) const TX_TYPES: [&str; 3] = ["Income", "Expense", "Transfer"];

impl<'a> Autofiller<'a> {
pub(crate) fn new(conn: MutDbConn<'a>) -> Self {
Self { conn }
Expand Down Expand Up @@ -50,43 +49,48 @@ impl<'a> Autofiller<'a> {
return String::new();
}

let tx_type = if lowercase.starts_with('t') {
TxType::Transfer
} else if lowercase.starts_with('e') {
TxType::Expense
} else if lowercase.starts_with('i') {
TxType::Income
} else if lowercase.starts_with("br") {
TxType::BorrowRepay
} else if lowercase.starts_with("lr") {
TxType::LendRepay
} else if lowercase.starts_with('b') {
TxType::Borrow
} else if lowercase.starts_with('l') {
TxType::Lend
} else {
let tx_types = TX_TYPES
.iter()
.map(|s| (*s).to_string())
let return_best_match = || {
let tx_types = TxType::iter()
.map(|s| s.to_string())
.collect::<Vec<String>>();

let best_match = get_best_match(user_input, &tx_types);

let to_return = if best_match == trimmed_input {
if best_match == trimmed_input {
String::new()
} else {
best_match
}
};

let best_match = if lowercase.len() <= 2 {
let tx_type = if lowercase.starts_with('t') {
TxType::Transfer.to_string()
} else if lowercase.starts_with('e') {
TxType::Expense.to_string()
} else if lowercase.starts_with('i') {
TxType::Income.to_string()
} else if lowercase.starts_with("br") {
TxType::BorrowRepay.to_string()
} else if lowercase.starts_with("lr") {
TxType::LendRepay.to_string()
} else if lowercase.starts_with('b') {
TxType::Borrow.to_string()
} else if lowercase.starts_with('l') {
TxType::Lend.to_string()
} else {
return_best_match()
};

return to_return;
tx_type.clone()
} else {
return_best_match()
};

let to_return = tx_type.to_string();

if to_return == trimmed_input {
if best_match == trimmed_input {
String::new()
} else {
to_return
best_match
}
}

Expand Down
4 changes: 3 additions & 1 deletion app/src/ui_helper/outputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ pub enum VerifierError {
AmountBelowZero,
#[error("TX Method: Transaction Method not found")]
InvalidTxMethod,
#[error("TX Type: Transaction Type not acceptable. Values: Expense/Income/E/I")]
#[error(
"TX Type: Transaction Type not acceptable. Values: Expense/Income/Transfer/Borrow/Borrow Repay/Lend/Lend Repay/I/E/T/B/BR/L/LR"
)]
InvalidTxType,
#[error("{0}: Error acquired while validating input")]
ParsingError(Field),
Expand Down
2 changes: 1 addition & 1 deletion app/src/ui_helper/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub(crate) fn get_best_match(data: &str, matching_set: &[String]) -> String {
best_score = new_score;
}
}
best_match.to_string()
best_match.clone()
}

#[derive(Copy, Clone)]
Expand Down
37 changes: 17 additions & 20 deletions app/src/ui_helper/stepper.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use chrono::{Duration, Months, NaiveDate};
use rex_db::ConnCache;
use rex_db::models::TxType;
use strum::IntoEnumIterator;

use crate::conn::MutDbConn;
use crate::ui_helper::{
DateType, Field, Output, StepType, SteppingError, TX_TYPES, VerifierError, get_best_match,
DateType, Field, Output, StepType, SteppingError, VerifierError, get_best_match,
};

pub struct Stepper<'a> {
Expand Down Expand Up @@ -184,27 +186,22 @@ impl<'a> Stepper<'a> {
) -> Result<(), SteppingError> {
let verify_status = self.conn.verify().tx_type(user_type);

if !user_type.is_empty() {
let mut current_index: usize =
match user_type.chars().next().unwrap().to_ascii_lowercase() {
'e' => 1,
't' => 2,
// 'I' is 0
_ => 0,
};

match step_type {
StepType::StepUp => current_index = (current_index + 1) % TX_TYPES.len(),
StepType::StepDown => {
current_index = (current_index + TX_TYPES.len() - 1) % TX_TYPES.len();
}
}
*user_type = TX_TYPES[current_index].to_string();
}

match verify_status {
Ok(data) => match data {
Output::Accepted(_) => {}
Output::Accepted(_) => {
let tx_types: Vec<String> = TxType::iter().map(|s| s.to_string()).collect();

let mut current_index = tx_types.iter().position(|t| t == user_type).unwrap();

match step_type {
StepType::StepUp => current_index = (current_index + 1) % tx_types.len(),
StepType::StepDown => {
current_index = (current_index + tx_types.len() - 1) % tx_types.len();
}
}

*user_type = tx_types[current_index].clone();
}
Output::Nothing(_) => {
*user_type = "Income".to_string();
}
Expand Down
Loading
Loading