This commit is contained in:
thatscringebro
2026-03-12 13:55:30 -04:00
parent bf1de016cd
commit 9bfc0c4304
8 changed files with 83 additions and 155 deletions

View File

@@ -32,7 +32,7 @@ impl App {
current_widget: CurrentWidget::AccountList, current_widget: CurrentWidget::AccountList,
acc_list: AccountList::new(), acc_list: AccountList::new(),
trx_table: TrxTable::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(), new_transaction: Transaction::new_empty(),
selected_transaction_input: TransactionInput::Type, selected_transaction_input: TransactionInput::Type,
current_input: String::new(), current_input: String::new(),
@@ -68,7 +68,7 @@ impl App {
pub fn save_new_account(&mut self) { pub fn save_new_account(&mut self) {
let ac = data_layer::upsert_account(&self.connection, self.new_account.clone()); let ac = data_layer::upsert_account(&self.connection, self.new_account.clone());
self.acc_list.add_account(ac); 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) { pub fn save_new_tr(&mut self) {
@@ -108,8 +108,16 @@ impl App {
.set_date(Local.from_utc_datetime(&NaiveDateTime::new(date, time))); .set_date(Local.from_utc_datetime(&NaiveDateTime::new(date, time)));
} }
TransactionInput::Description => { TransactionInput::Description => {
self.selected_transaction_input = TransactionInput::Asset;
self.new_transaction.set_desc(self.current_input.clone()) self.new_transaction.set_desc(self.current_input.clone())
} }
TransactionInput::Asset => {
self.new_transaction.set_asset_amnt(
self.current_input
.parse::<f64>()
.expect("Failed to parse data"),
);
}
} }
self.set_current_input(); self.set_current_input();
} }
@@ -143,6 +151,14 @@ impl App {
self.selected_transaction_input = TransactionInput::Date; self.selected_transaction_input = TransactionInput::Date;
self.new_transaction.set_desc(self.current_input.clone()); 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::<f64>()
.expect("Failed to parse data"),
);
}
} }
self.set_current_input(); self.set_current_input();
} }
@@ -162,6 +178,9 @@ impl App {
.to_string() .to_string()
} }
TransactionInput::Description => self.current_input = self.new_transaction.get_desc(), TransactionInput::Description => self.current_input = self.new_transaction.get_desc(),
TransactionInput::Asset => {
self.current_input = self.new_transaction.get_asset_amnt().to_string()
}
} }
} }
} }

View File

@@ -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 { pub fn upsert_account(con: &Connection, ac: Account) -> Account {
@@ -54,7 +65,12 @@ pub fn upsert_account(con: &Connection, ac: Account) -> Account {
id = 0; 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 { 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( return Account::new(
statement.read::<i64, _>("id").unwrap(), statement.read::<i64, _>("id").unwrap(),
statement.read::<String, _>("name").unwrap(), statement.read::<String, _>("name").unwrap(),
statement.read::<f64, _>("asset_price").unwrap(),
statement statement
.read::<i64, _>("type") .read::<i64, _>("type")
.unwrap() .unwrap()
@@ -73,7 +90,7 @@ pub fn get_account(con: &Connection, id: i64) -> Account {
.unwrap(), .unwrap(),
); );
} else { } 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<Account> {
let mut statement = con.prepare(query).unwrap(); let mut statement = con.prepare(query).unwrap();
let mut vec = Vec::<Account>::new(); let mut vec = Vec::<Account>::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() { while let Ok(State::Row) = statement.next() {
vec.push(Account::new( vec.push(Account::new(
statement.read::<i64, _>("id").unwrap(), statement.read::<i64, _>("id").unwrap(),
statement.read::<String, _>("name").unwrap(), statement.read::<String, _>("name").unwrap(),
statement.read::<f64, _>("asset_price").unwrap(),
statement statement
.read::<i64, _>("type") .read::<i64, _>("type")
.unwrap() .unwrap()
@@ -174,16 +192,15 @@ pub fn get_transaction_types(con: &Connection) -> Vec<TransactionType> {
} }
pub fn upsert_transaction(con: &Connection, tr: Transaction) -> Transaction { pub fn upsert_transaction(con: &Connection, tr: Transaction) -> Transaction {
println!("{}", tr.get_desc());
let query; let query;
if tr.get_id() == 0 { if tr.get_id() == 0 {
query = "INSERT INTO Transactions query = "INSERT INTO Transactions
(account_id, type_id, amount, date, description) (account_id, type_id, amount, date, description, asset_amount)
VALUES (:ac_id, :type_id, :amnt, :date, :desc) VALUES (:ac_id, :type_id, :amnt, :date, :desc, :asset_amnt)
RETURNING id;"; RETURNING id;";
} else { } else {
query = "UPDATE Transactions 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;"; WHERE id = :id RETURNING id;";
} }
@@ -197,6 +214,9 @@ pub fn upsert_transaction(con: &Connection, tr: Transaction) -> Transaction {
.bind((":date", tr.get_date().timestamp())) .bind((":date", tr.get_date().timestamp()))
.unwrap(); .unwrap();
statement.bind((":desc", &tr.get_desc() as &str)).unwrap(); statement.bind((":desc", &tr.get_desc() as &str)).unwrap();
statement
.bind((":asset_amnt", tr.get_asset_amnt()))
.unwrap();
if tr.get_id() != 0 { if tr.get_id() != 0 {
statement.bind((":id", tr.get_id())).unwrap(); 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_date_utc(),
tr.get_desc(), tr.get_desc(),
tr.get_type().get_id(), tr.get_type().get_id(),
tr.get_asset_amnt(),
con, con,
); );
} }
@@ -233,6 +254,7 @@ pub fn get_transaction(con: &Connection, id: i64) -> Transaction {
DateTime::from_timestamp(statement.read::<i64, _>("date").unwrap(), 0).unwrap(), DateTime::from_timestamp(statement.read::<i64, _>("date").unwrap(), 0).unwrap(),
statement.read::<String, _>("description").unwrap(), statement.read::<String, _>("description").unwrap(),
statement.read::<i64, _>("type_id").unwrap(), statement.read::<i64, _>("type_id").unwrap(),
statement.read::<f64, _>("asset_amount").unwrap(),
con, con,
); );
} else { } else {
@@ -258,6 +280,7 @@ pub fn get_account_transactions(con: &Connection, ac_id: i64) -> Vec<Transaction
DateTime::from_timestamp(statement.read::<i64, _>("date").unwrap(), 0).unwrap(), DateTime::from_timestamp(statement.read::<i64, _>("date").unwrap(), 0).unwrap(),
statement.read::<String, _>("description").unwrap(), statement.read::<String, _>("description").unwrap(),
statement.read::<i64, _>("type_id").unwrap(), statement.read::<i64, _>("type_id").unwrap(),
statement.read::<f64, _>("asset_amount").unwrap(),
con, con,
)); ));
} }
@@ -278,6 +301,7 @@ pub fn get_transactions(con: &Connection) -> Vec<Transaction> {
DateTime::from_timestamp(statement.read::<i64, _>("date").unwrap(), 0).unwrap(), DateTime::from_timestamp(statement.read::<i64, _>("date").unwrap(), 0).unwrap(),
statement.read::<String, _>("description").unwrap(), statement.read::<String, _>("description").unwrap(),
statement.read::<i64, _>("type_id").unwrap(), statement.read::<i64, _>("type_id").unwrap(),
statement.read::<f64, _>("asset_amount").unwrap(),
con, con,
)); ));
} }

View File

@@ -8,14 +8,16 @@ use crate::data_layer;
pub struct Account { pub struct Account {
id: i64, id: i64,
name: String, name: String,
asset_price: f64,
ac_type: AccountType, ac_type: AccountType,
} }
impl Account { 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 { Account {
id: id, id: id,
name: name, name: name,
asset_price: asset_price,
ac_type: ac_type, ac_type: ac_type,
} }
} }
@@ -25,6 +27,9 @@ impl Account {
pub fn get_name(&self) -> String { pub fn get_name(&self) -> String {
return self.name.clone(); return self.name.clone();
} }
pub fn get_asset_price(&self) -> f64 {
return self.asset_price;
}
pub fn get_ac_type(&self) -> AccountType { pub fn get_ac_type(&self) -> AccountType {
return AccountType::try_from(self.ac_type as i64).unwrap(); return AccountType::try_from(self.ac_type as i64).unwrap();
} }

View File

@@ -10,6 +10,7 @@ pub struct Transaction {
date: DateTime<Utc>, date: DateTime<Utc>,
description: String, description: String,
type_id: i64, type_id: i64,
asset_amount: f64,
tr_type: TransactionType, tr_type: TransactionType,
} }
@@ -22,6 +23,7 @@ impl Transaction {
date: DateTime<Utc>, date: DateTime<Utc>,
desc: String, desc: String,
type_id: i64, type_id: i64,
asset_amount: f64,
con: &Connection, con: &Connection,
) -> Self { ) -> Self {
Transaction { Transaction {
@@ -32,6 +34,7 @@ impl Transaction {
description: desc, description: desc,
type_id: type_id, type_id: type_id,
tr_type: data_layer::get_transaction_type(con, 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(), description: "".to_string(),
type_id: 0, type_id: 0,
tr_type: TransactionType::new(0, "".to_string()), tr_type: TransactionType::new(0, "".to_string()),
asset_amount: 0.0,
} }
} }
@@ -89,6 +93,13 @@ impl Transaction {
self.type_id = tr_id; self.type_id = tr_id;
self.tr_type = data_layer::get_transaction_type(con, 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)] #[derive(Clone)]

View File

@@ -31,6 +31,6 @@ impl TrxTable {
} }
pub fn add_tr(&mut self, tr: Transaction) { pub fn add_tr(&mut self, tr: Transaction) {
self.trx.push(tr); self.trx.insert(0, tr);
} }
} }

View File

@@ -15,4 +15,5 @@ pub enum TransactionInput {
Amount, Amount,
Date, Date,
Description, Description,
Asset,
} }

View File

@@ -110,7 +110,7 @@ where
} }
KeyCode::Esc => { KeyCode::Esc => {
app.current_screen = CurrentScreen::Main; 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::<i64>().unwrap();
// let trx: Vec<entities::Transaction> =
// 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::<i64>().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::<i64>().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::<f64>().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.");
// }
// }
// }
// }

View File

@@ -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),
Constraint::Length(3), Constraint::Length(3),
Constraint::Length(3),
]) ])
.split(area); .split(area);
@@ -158,6 +159,15 @@ pub fn ui(frame: &mut Frame, app: &mut App) {
.title("Description"), .title("Description"),
); );
frame.render_widget(desc, chunks[3]); 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 { 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") .format("%Y-%m-%d")
.to_string(), .to_string(),
TransactionInput::Description => app.new_transaction.get_desc(), TransactionInput::Description => app.new_transaction.get_desc(),
TransactionInput::Asset => app.new_transaction.get_asset_amnt().to_string(),
} }
} }