Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
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
10 changes: 9 additions & 1 deletion app/src/conn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ impl DbConn {
Ok(())
})?;

if let Some(details) = tx.details {
self.cache.new_details(details.to_string());
}

Ok(())
}

Expand Down Expand Up @@ -172,10 +176,14 @@ impl DbConn {
Ok(())
})?;

if let Some(details) = new_tx.details {
self.cache.new_details(details.to_string());
}

Ok(())
}

pub fn add_new_methods(&mut self, method_list: &Vec<String>) -> Result<()> {
pub fn add_new_methods(&mut self, method_list: &[String]) -> Result<()> {
self.conn.transaction::<_, Error, _>(|conn| {
let mut db_conn = MutDbConn::new(conn, &self.cache);

Expand Down
2 changes: 1 addition & 1 deletion app/src/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub fn start_migration(mut old_db_conn: DbConn, db_conn: &mut DbConn) -> Result<
columns.remove(0);
}

let tx_methods = columns.into_iter().map(|c| c.name).collect();
let tx_methods = columns.into_iter().map(|c| c.name).collect::<Vec<String>>();

let new_methods = add_new_tx_methods(&tx_methods, db_conn)?;
db_conn.cache.new_tx_methods(new_methods);
Expand Down
9 changes: 3 additions & 6 deletions app/src/modifier/new_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,16 @@ use rex_db::ConnCache;
use rex_db::models::{Balance, NewTxMethod, TxMethod};

pub(crate) fn add_new_tx_methods(
method_list: &Vec<String>,
method_list: &[String],
db_conn: &mut impl ConnCache,
) -> Result<Vec<TxMethod>> {
let mut last_position = TxMethod::get_last_position(db_conn)?;

let mut methods = Vec::new();

for method in method_list {
for (last_position, method) in (TxMethod::get_last_position(db_conn)?..).zip(method_list.iter())
{
let new_method = NewTxMethod::new(method, last_position + 1);

methods.push(new_method);

last_position += 1;
}

let mut new_methods = Vec::new();
Expand Down
141 changes: 141 additions & 0 deletions app/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,144 @@ pub fn compare_change_opt(current: Dollar, previous: Option<Dollar>) -> String {
},
}
}

#[cfg(test)]
mod tests {
use super::*;
use rex_db::models::AmountNature;
use rex_shared::models::{Cent, Dollar};

#[test]
fn test_month_name_to_num_all_months() {
assert_eq!(month_name_to_num("January"), 1);
assert_eq!(month_name_to_num("February"), 2);
assert_eq!(month_name_to_num("March"), 3);
assert_eq!(month_name_to_num("April"), 4);
assert_eq!(month_name_to_num("May"), 5);
assert_eq!(month_name_to_num("June"), 6);
assert_eq!(month_name_to_num("July"), 7);
assert_eq!(month_name_to_num("August"), 8);
assert_eq!(month_name_to_num("September"), 9);
assert_eq!(month_name_to_num("October"), 10);
assert_eq!(month_name_to_num("November"), 11);
assert_eq!(month_name_to_num("December"), 12);
}

#[test]
#[should_panic(expected = "Invalid month name")]
fn test_month_name_to_num_invalid_panics() {
month_name_to_num("NotAMonth");
}

#[test]
fn test_month_year_to_unique() {
assert_eq!(month_year_to_unique(6, 2024), 202406);
assert_eq!(month_year_to_unique(12, 2024), 202412);
assert_eq!(month_year_to_unique(1, 2000), 200001);
}

#[test]
fn test_get_percentages_normal() {
let (p1, p2) = get_percentages(30.0, 70.0);
assert!((p1 - 30.0).abs() < 0.001);
assert!((p2 - 70.0).abs() < 0.001);
}

#[test]
fn test_get_percentages_equal() {
let (p1, p2) = get_percentages(50.0, 50.0);
assert!((p1 - 50.0).abs() < 0.001);
assert!((p2 - 50.0).abs() < 0.001);
}

#[test]
fn test_get_percentages_both_zero() {
let (p1, p2) = get_percentages(0.0, 0.0);
assert_eq!(p1, 0.0);
assert_eq!(p2, 0.0);
}

#[test]
fn test_get_percentages_one_zero() {
let (p1, p2) = get_percentages(0.0, 100.0);
assert_eq!(p1, 0.0);
assert!((p2 - 100.0).abs() < 0.001);
}

#[test]
fn test_parse_amount_nature_exact() {
let result = parse_amount_nature_cent("50.00").unwrap().unwrap();
assert!(matches!(result, AmountNature::Exact(c) if c == Cent::new(5000)));
}

#[test]
fn test_parse_amount_nature_more_than() {
let result = parse_amount_nature_cent(">100").unwrap().unwrap();
assert!(matches!(result, AmountNature::MoreThan(c) if c == Cent::new(10000)));
}

#[test]
fn test_parse_amount_nature_less_than() {
let result = parse_amount_nature_cent("<50").unwrap().unwrap();
assert!(matches!(result, AmountNature::LessThan(c) if c == Cent::new(5000)));
}

#[test]
fn test_parse_amount_nature_more_than_equal() {
let result = parse_amount_nature_cent(">=25.50").unwrap().unwrap();
assert!(matches!(result, AmountNature::MoreThanEqual(c) if c == Cent::new(2550)));
}

#[test]
fn test_parse_amount_nature_less_than_equal() {
let result = parse_amount_nature_cent("<=10.00").unwrap().unwrap();
assert!(matches!(result, AmountNature::LessThanEqual(c) if c == Cent::new(1000)));
}

#[test]
fn test_parse_amount_nature_empty() {
let result = parse_amount_nature_cent(" ").unwrap();
assert!(result.is_none());
}

#[test]
fn test_parse_amount_nature_invalid() {
assert!(parse_amount_nature_cent("abc").is_err());
}

#[test]
fn test_compare_change_increase() {
let result = compare_change(Dollar::new(150.0), Dollar::new(100.0));
assert_eq!(result, "↑50.00");
}

#[test]
fn test_compare_change_decrease() {
let result = compare_change(Dollar::new(50.0), Dollar::new(100.0));
assert_eq!(result, "↓50.00");
}

#[test]
fn test_compare_change_zero_previous() {
let result = compare_change(Dollar::new(100.0), Dollar::new(0.0));
assert_eq!(result, "∞");
}

#[test]
fn test_compare_change_opt_some() {
let result = compare_change_opt(Dollar::new(200.0), Some(Dollar::new(100.0)));
assert_eq!(result, "↑100.00");
}

#[test]
fn test_compare_change_opt_none() {
let result = compare_change_opt(Dollar::new(100.0), None);
assert_eq!(result, "∞");
}

#[test]
fn test_compare_change_opt_previous_zero() {
let result = compare_change_opt(Dollar::new(100.0), Some(Dollar::new(0.0)));
assert_eq!(result, "∞");
}
}
54 changes: 30 additions & 24 deletions app/src/views/tx_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -489,37 +489,43 @@ impl TxViewGroup {
index_2: usize,
db_conn: &mut impl ConnCache,
) -> Result<bool> {
let tx_1 = self.0.get(index_1).unwrap();
let tx_2 = self.0.get(index_2).unwrap();
let target_date = {
let tx_1 = self.0.get(index_1).unwrap();
let tx_2 = self.0.get(index_2).unwrap();

// Can't switch index if not in the same date
if tx_1.tx.date.date() != tx_2.tx.date.date() {
return Ok(false);
}

let tx_1_order = tx_1.tx.display_order;
let tx_2_order = tx_2.tx.display_order;
if tx_1.tx.date.date() != tx_2.tx.date.date() {
return Ok(false);
}

let new_tx_1_order = if tx_2_order == 0 {
tx_2.tx.id
} else {
tx_2_order
};
let new_tx_2_order = if tx_1_order == 0 {
tx_1.tx.id
} else {
tx_1_order
tx_1.tx.date.date()
};

let tx_1 = self.0.get_mut(index_1).unwrap();
tx_1.tx.display_order = new_tx_1_order;
// If has unset/display order = 0, set display order from 1 to N.
// Once order has been set, only then switch display order and commit
let has_unset = self
.0
.iter()
.any(|tv| tv.tx.date.date() == target_date && tv.tx.display_order == 0);

if has_unset {
let mut order = 1i32;
for tx_view in &mut self.0 {
if tx_view.tx.date.date() == target_date {
tx_view.tx.display_order = order;
tx_view.tx.set_display_order(db_conn)?;
order += 1;
}
}
}

tx_1.tx.set_display_order(db_conn)?;
let tx_1_order = self.0[index_1].tx.display_order;
let tx_2_order = self.0[index_2].tx.display_order;

let tx_2 = self.0.get_mut(index_2).unwrap();
tx_2.tx.display_order = new_tx_2_order;
self.0[index_1].tx.display_order = tx_2_order;
self.0[index_1].tx.set_display_order(db_conn)?;

tx_2.tx.set_display_order(db_conn)?;
self.0[index_2].tx.display_order = tx_1_order;
self.0[index_2].tx.set_display_order(db_conn)?;

Ok(true)
}
Expand Down
Loading
Loading