From 9bfc0c4304cb319bb30755c10b3001910a27da0d Mon Sep 17 00:00:00 2001 From: thatscringebro Date: Thu, 12 Mar 2026 13:55:30 -0400 Subject: [PATCH] asset --- src/app.rs | 23 +++++- src/data_layer.rs | 38 ++++++++-- src/entities/account.rs | 7 +- src/entities/transaction.rs | 11 +++ src/entities/trxtable.rs | 2 +- src/enums.rs | 1 + src/main.rs | 145 +----------------------------------- src/ui.rs | 11 +++ 8 files changed, 83 insertions(+), 155 deletions(-) diff --git a/src/app.rs b/src/app.rs index ef4f858..702fdca 100644 --- a/src/app.rs +++ b/src/app.rs @@ -32,7 +32,7 @@ impl App { current_widget: CurrentWidget::AccountList, acc_list: AccountList::new(), trx_table: TrxTable::new(), - new_account: Account::new(0, String::new(), AccountType::Cash), + new_account: Account::new(0, String::new(), 0.0, AccountType::Cash), new_transaction: Transaction::new_empty(), selected_transaction_input: TransactionInput::Type, current_input: String::new(), @@ -68,7 +68,7 @@ impl App { pub fn save_new_account(&mut self) { let ac = data_layer::upsert_account(&self.connection, self.new_account.clone()); self.acc_list.add_account(ac); - self.new_account = Account::new(0, String::new(), AccountType::Cash); + self.new_account = Account::new(0, String::new(), 0.0, AccountType::Cash); } pub fn save_new_tr(&mut self) { @@ -108,8 +108,16 @@ impl App { .set_date(Local.from_utc_datetime(&NaiveDateTime::new(date, time))); } TransactionInput::Description => { + self.selected_transaction_input = TransactionInput::Asset; self.new_transaction.set_desc(self.current_input.clone()) } + TransactionInput::Asset => { + self.new_transaction.set_asset_amnt( + self.current_input + .parse::() + .expect("Failed to parse data"), + ); + } } self.set_current_input(); } @@ -143,6 +151,14 @@ impl App { self.selected_transaction_input = TransactionInput::Date; self.new_transaction.set_desc(self.current_input.clone()); } + TransactionInput::Asset => { + self.selected_transaction_input = TransactionInput::Description; + self.new_transaction.set_asset_amnt( + self.current_input + .parse::() + .expect("Failed to parse data"), + ); + } } self.set_current_input(); } @@ -162,6 +178,9 @@ impl App { .to_string() } TransactionInput::Description => self.current_input = self.new_transaction.get_desc(), + TransactionInput::Asset => { + self.current_input = self.new_transaction.get_asset_amnt().to_string() + } } } } diff --git a/src/data_layer.rs b/src/data_layer.rs index b2bbafc..531d911 100644 --- a/src/data_layer.rs +++ b/src/data_layer.rs @@ -28,6 +28,17 @@ pub fn setup(con: &Connection) { ); ", ); + let mut asset_stmt = con + .prepare("SELECT COUNT(*) FROM pragma_table_info('Accounts') WHERE name = 'asset_price'") + .unwrap(); + if let Ok(State::Row) = asset_stmt.next() { + let _ = con.execute( + " + ALTER TABLE Accounts ADD COLUMN asset_price FLOAT NOT NULL DEFAULT 0.0; + ALTER TABLE Transactions ADD COLUMN asset_amount FLOAT NOT NULL DEFAULT 0.0; + ", + ); + } } pub fn upsert_account(con: &Connection, ac: Account) -> Account { @@ -54,7 +65,12 @@ pub fn upsert_account(con: &Connection, ac: Account) -> Account { id = 0; } - return Account::new(id, ac.get_name(), ac_type.try_into().unwrap()); + return Account::new( + id, + ac.get_name(), + ac.get_asset_price(), + ac_type.try_into().unwrap(), + ); } pub fn get_account(con: &Connection, id: i64) -> Account { @@ -66,6 +82,7 @@ pub fn get_account(con: &Connection, id: i64) -> Account { return Account::new( statement.read::("id").unwrap(), statement.read::("name").unwrap(), + statement.read::("asset_price").unwrap(), statement .read::("type") .unwrap() @@ -73,7 +90,7 @@ pub fn get_account(con: &Connection, id: i64) -> Account { .unwrap(), ); } else { - return Account::new(0, "".to_string(), AccountType::Cash); + return Account::new(0, "".to_string(), 0.0, AccountType::Cash); } } @@ -101,12 +118,13 @@ pub fn get_accounts(con: &Connection) -> Vec { let mut statement = con.prepare(query).unwrap(); let mut vec = Vec::::new(); - vec.push(Account::new(0, "All".to_string(), AccountType::Cash)); + vec.push(Account::new(0, "All".to_string(), 0.0, AccountType::Cash)); while let Ok(State::Row) = statement.next() { vec.push(Account::new( statement.read::("id").unwrap(), statement.read::("name").unwrap(), + statement.read::("asset_price").unwrap(), statement .read::("type") .unwrap() @@ -174,16 +192,15 @@ pub fn get_transaction_types(con: &Connection) -> Vec { } pub fn upsert_transaction(con: &Connection, tr: Transaction) -> Transaction { - println!("{}", tr.get_desc()); let query; if tr.get_id() == 0 { query = "INSERT INTO Transactions - (account_id, type_id, amount, date, description) - VALUES (:ac_id, :type_id, :amnt, :date, :desc) + (account_id, type_id, amount, date, description, asset_amount) + VALUES (:ac_id, :type_id, :amnt, :date, :desc, :asset_amnt) RETURNING id;"; } else { query = "UPDATE Transactions - SET account_id = :ac_id, type_id = :type_id, amount = :amnt, date = :date, description = :desc + SET account_id = :ac_id, type_id = :type_id, amount = :amnt, date = :date, description = :desc, asset_amount = asset_amnt WHERE id = :id RETURNING id;"; } @@ -197,6 +214,9 @@ pub fn upsert_transaction(con: &Connection, tr: Transaction) -> Transaction { .bind((":date", tr.get_date().timestamp())) .unwrap(); statement.bind((":desc", &tr.get_desc() as &str)).unwrap(); + statement + .bind((":asset_amnt", tr.get_asset_amnt())) + .unwrap(); if tr.get_id() != 0 { statement.bind((":id", tr.get_id())).unwrap(); @@ -216,6 +236,7 @@ pub fn upsert_transaction(con: &Connection, tr: Transaction) -> Transaction { tr.get_date_utc(), tr.get_desc(), tr.get_type().get_id(), + tr.get_asset_amnt(), con, ); } @@ -233,6 +254,7 @@ pub fn get_transaction(con: &Connection, id: i64) -> Transaction { DateTime::from_timestamp(statement.read::("date").unwrap(), 0).unwrap(), statement.read::("description").unwrap(), statement.read::("type_id").unwrap(), + statement.read::("asset_amount").unwrap(), con, ); } else { @@ -258,6 +280,7 @@ pub fn get_account_transactions(con: &Connection, ac_id: i64) -> Vec("date").unwrap(), 0).unwrap(), statement.read::("description").unwrap(), statement.read::("type_id").unwrap(), + statement.read::("asset_amount").unwrap(), con, )); } @@ -278,6 +301,7 @@ pub fn get_transactions(con: &Connection) -> Vec { DateTime::from_timestamp(statement.read::("date").unwrap(), 0).unwrap(), statement.read::("description").unwrap(), statement.read::("type_id").unwrap(), + statement.read::("asset_amount").unwrap(), con, )); } diff --git a/src/entities/account.rs b/src/entities/account.rs index f212dc2..e7f62e0 100644 --- a/src/entities/account.rs +++ b/src/entities/account.rs @@ -8,14 +8,16 @@ use crate::data_layer; pub struct Account { id: i64, name: String, + asset_price: f64, ac_type: AccountType, } impl Account { - pub fn new(id: i64, name: String, ac_type: AccountType) -> Self { + pub fn new(id: i64, name: String, asset_price: f64, ac_type: AccountType) -> Self { Account { id: id, name: name, + asset_price: asset_price, ac_type: ac_type, } } @@ -25,6 +27,9 @@ impl Account { pub fn get_name(&self) -> String { return self.name.clone(); } + pub fn get_asset_price(&self) -> f64 { + return self.asset_price; + } pub fn get_ac_type(&self) -> AccountType { return AccountType::try_from(self.ac_type as i64).unwrap(); } diff --git a/src/entities/transaction.rs b/src/entities/transaction.rs index 5a28ad9..024734a 100644 --- a/src/entities/transaction.rs +++ b/src/entities/transaction.rs @@ -10,6 +10,7 @@ pub struct Transaction { date: DateTime, description: String, type_id: i64, + asset_amount: f64, tr_type: TransactionType, } @@ -22,6 +23,7 @@ impl Transaction { date: DateTime, desc: String, type_id: i64, + asset_amount: f64, con: &Connection, ) -> Self { Transaction { @@ -32,6 +34,7 @@ impl Transaction { description: desc, type_id: type_id, tr_type: data_layer::get_transaction_type(con, type_id), + asset_amount: asset_amount, } } @@ -44,6 +47,7 @@ impl Transaction { description: "".to_string(), type_id: 0, tr_type: TransactionType::new(0, "".to_string()), + asset_amount: 0.0, } } @@ -89,6 +93,13 @@ impl Transaction { self.type_id = tr_id; self.tr_type = data_layer::get_transaction_type(con, tr_id); } + + pub fn get_asset_amnt(&self) -> f64 { + return self.asset_amount; + } + pub fn set_asset_amnt(&mut self, amnt: f64) { + self.asset_amount = amnt; + } } #[derive(Clone)] diff --git a/src/entities/trxtable.rs b/src/entities/trxtable.rs index 11a4640..638ce87 100644 --- a/src/entities/trxtable.rs +++ b/src/entities/trxtable.rs @@ -31,6 +31,6 @@ impl TrxTable { } pub fn add_tr(&mut self, tr: Transaction) { - self.trx.push(tr); + self.trx.insert(0, tr); } } diff --git a/src/enums.rs b/src/enums.rs index 1b5ceaf..e23f813 100644 --- a/src/enums.rs +++ b/src/enums.rs @@ -15,4 +15,5 @@ pub enum TransactionInput { Amount, Date, Description, + Asset, } diff --git a/src/main.rs b/src/main.rs index 492ea54..849531a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -110,7 +110,7 @@ where } KeyCode::Esc => { app.current_screen = CurrentScreen::Main; - app.new_account = Account::new(0, String::new(), AccountType::Cash); + app.new_account = Account::new(0, String::new(), 0.0, AccountType::Cash); } _ => {} }, @@ -149,146 +149,3 @@ where } } } - -// fn main() { -// let connection = match Connection::open("ft_rs.db") { -// Ok(con) => con, -// Err(e) => { -// eprintln!("Error opening database: {}", e); -// return; -// } -// }; - -// data_layer::setup(&connection); - -// loop { -// println!("Please choose an option:"); -// println!("1. List accounts"); -// println!("2. Add an account"); -// println!("3. List transaction types"); -// println!("4. Add a transaction type"); -// println!("5. List transactions"); -// println!("6. Add a transaction"); -// println!("0. Exit"); - -// let mut choice = String::new(); -// io::stdin() -// .read_line(&mut choice) -// .expect("Failed to read line"); - -// let choice = choice.trim(); - -// match choice { -// "1" => { -// let accounts = data_layer::get_accounts)(&connection); -// let mut total = 0.0; -// for ac in accounts.iter() { -// let ac_total = ac.get_total(&connection); -// println!( -// "Id: {}, Name: {}, Total: {}", -// ac.get_id(), -// ac.get_name(), -// ac_total -// ); -// total += ac_total; -// } -// println!("Total: {}", total); -// } -// "2" => { -// println!("Please enter the account name:"); -// let mut ac_name = String::new(); -// io::stdin() -// .read_line(&mut ac_name) -// .expect("Failed to read line"); -// let ac_name = ac_name.trim(); -// let new_ac = Account::new(0, ac_name.to_string(), entities::AccountType::Cash); -// data_layer::upsert_account(&connection, new_ac); -// } -// "3" => { -// let types = data_layer::get_transaction_types(&connection); -// for t in types.iter() { -// println!("Name: {}", t.get_description()); -// } -// } -// "4" => { -// println!("Please enter the transaction type:"); -// let mut desc = String::new(); -// io::stdin() -// .read_line(&mut desc) -// .expect("Failed to read line"); -// let desc = desc.trim(); -// let tr_type = TransactionType::new(0, desc.to_string()); -// data_layer::upsert_transaction_type(&connection, tr_type); -// } -// "5" => { -// println!("Please enter the account id:"); -// let mut ac_id_str = String::new(); -// io::stdin() -// .read_line(&mut ac_id_str) -// .expect("Failed to read line"); -// ac_id_str = ac_id_str.trim().to_string(); -// let ac_id = ac_id_str.parse::().unwrap(); -// let trx: Vec = -// data_layer::get_account_transactions(&connection, ac_id); -// // .sort_by(|a, b| b.get_date().cmp(&a.get_date())) -// // .try_into() -// // .unwrap(); -// for t in trx.iter() { -// println!( -// "Date: {}, Type: {}, Description: {}, Amount: {}$", -// Local.from_utc_datetime(&t.get_date().naive_local()), -// t.get_type().get_description(), -// t.get_desc(), -// t.get_amount() -// ); -// } -// } -// "6" => { -// println!("Please enter the account id:"); -// let mut ac_id_str = String::new(); -// io::stdin() -// .read_line(&mut ac_id_str) -// .expect("Failed to read line"); -// ac_id_str = ac_id_str.trim().to_string(); -// let ac_id = ac_id_str.parse::().unwrap(); -// println!("Please enter the transaction type id:"); -// let mut tr_type_id_str = String::new(); -// io::stdin() -// .read_line(&mut tr_type_id_str) -// .expect("Failed to read line"); -// tr_type_id_str = tr_type_id_str.trim().to_string(); -// let type_id = tr_type_id_str.parse::().unwrap(); -// println!("Please enter the amount:"); -// let mut amnt_str = String::new(); -// io::stdin() -// .read_line(&mut amnt_str) -// .expect("Failed to read line"); -// amnt_str = amnt_str.trim().to_string(); -// let amount = amnt_str.parse::().unwrap(); -// println!("Please enter the description:"); -// let mut desc = String::new(); -// io::stdin() -// .read_line(&mut desc) -// .expect("Failed to read line"); -// desc = desc.trim().to_string(); -// let tr = Transaction::new( -// 0, -// ac_id, -// amount, -// chrono::offset::Utc::now(), -// desc, -// type_id, -// &connection, -// ); -// data_layer::upsert_transaction(&connection, tr); -// } -// "0" => { -// println!("Exiting..."); -// break; // Exit the loop -// } -// _ => { -// println!("Invalid choice."); -// } -// } -// } -// } diff --git a/src/ui.rs b/src/ui.rs index 7b880d5..080391b 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -132,6 +132,7 @@ pub fn ui(frame: &mut Frame, app: &mut App) { Constraint::Length(3), Constraint::Length(3), Constraint::Length(3), + Constraint::Length(3), ]) .split(area); @@ -158,6 +159,15 @@ pub fn ui(frame: &mut Frame, app: &mut App) { .title("Description"), ); frame.render_widget(desc, chunks[3]); + + let asset_amnt = Paragraph::new(tr_input_str(TransactionInput::Asset, app)) + .style(tr_input_style(TransactionInput::Asset, app)) + .block( + Block::default() + .borders(Borders::BOTTOM) + .title("Asset amount"), + ); + frame.render_widget(asset_amnt, chunks[4]); } if let CurrentScreen::Exiting = app.current_screen { @@ -220,6 +230,7 @@ fn tr_input_str(input: TransactionInput, app: &mut App) -> String { .format("%Y-%m-%d") .to_string(), TransactionInput::Description => app.new_transaction.get_desc(), + TransactionInput::Asset => app.new_transaction.get_asset_amnt().to_string(), } }