asset
This commit is contained in:
23
src/app.rs
23
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::<f64>()
|
||||
.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::<f64>()
|
||||
.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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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::<i64, _>("id").unwrap(),
|
||||
statement.read::<String, _>("name").unwrap(),
|
||||
statement.read::<f64, _>("asset_price").unwrap(),
|
||||
statement
|
||||
.read::<i64, _>("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<Account> {
|
||||
let mut statement = con.prepare(query).unwrap();
|
||||
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() {
|
||||
vec.push(Account::new(
|
||||
statement.read::<i64, _>("id").unwrap(),
|
||||
statement.read::<String, _>("name").unwrap(),
|
||||
statement.read::<f64, _>("asset_price").unwrap(),
|
||||
statement
|
||||
.read::<i64, _>("type")
|
||||
.unwrap()
|
||||
@@ -174,16 +192,15 @@ pub fn get_transaction_types(con: &Connection) -> Vec<TransactionType> {
|
||||
}
|
||||
|
||||
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::<i64, _>("date").unwrap(), 0).unwrap(),
|
||||
statement.read::<String, _>("description").unwrap(),
|
||||
statement.read::<i64, _>("type_id").unwrap(),
|
||||
statement.read::<f64, _>("asset_amount").unwrap(),
|
||||
con,
|
||||
);
|
||||
} 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(),
|
||||
statement.read::<String, _>("description").unwrap(),
|
||||
statement.read::<i64, _>("type_id").unwrap(),
|
||||
statement.read::<f64, _>("asset_amount").unwrap(),
|
||||
con,
|
||||
));
|
||||
}
|
||||
@@ -278,6 +301,7 @@ pub fn get_transactions(con: &Connection) -> Vec<Transaction> {
|
||||
DateTime::from_timestamp(statement.read::<i64, _>("date").unwrap(), 0).unwrap(),
|
||||
statement.read::<String, _>("description").unwrap(),
|
||||
statement.read::<i64, _>("type_id").unwrap(),
|
||||
statement.read::<f64, _>("asset_amount").unwrap(),
|
||||
con,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ pub struct Transaction {
|
||||
date: DateTime<Utc>,
|
||||
description: String,
|
||||
type_id: i64,
|
||||
asset_amount: f64,
|
||||
|
||||
tr_type: TransactionType,
|
||||
}
|
||||
@@ -22,6 +23,7 @@ impl Transaction {
|
||||
date: DateTime<Utc>,
|
||||
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)]
|
||||
|
||||
@@ -31,6 +31,6 @@ impl TrxTable {
|
||||
}
|
||||
|
||||
pub fn add_tr(&mut self, tr: Transaction) {
|
||||
self.trx.push(tr);
|
||||
self.trx.insert(0, tr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,4 +15,5 @@ pub enum TransactionInput {
|
||||
Amount,
|
||||
Date,
|
||||
Description,
|
||||
Asset,
|
||||
}
|
||||
|
||||
145
src/main.rs
145
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::<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.");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
11
src/ui.rs
11
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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user