use rust_decimal;
use rust_decimal::prelude::*;
pub fn add(left: u64, right: u64) -> u64 {
left + right
}
pub fn fund(howmuch: rust_decimal::Decimal) -> bool {
howmuch > dec!(0.0)
}
pub struct Account {
pub name: String,
pub balance: rust_decimal::Decimal,
pub id: String,
}
pub struct Transaction {
pub txid: String,
pub amount: rust_decimal::Decimal,
pub description: String,
pub account: Account,
pub date: String,
pub category: String,
pub tags: Vec<String>,
pub from: Account,
}
impl Account {
pub fn new(name: String, balance: rust_decimal::Decimal, id: String) -> Account {
Account { name, balance, id }
}
pub fn deposit(&mut self, amount: rust_decimal::Decimal) {
if amount > dec!(0.0) {
self.balance += amount;
}
}
pub fn withdraw(&mut self, amount: rust_decimal::Decimal) {
if amount > dec!(0.0) && self.balance >= amount{
self.balance -= amount;
}
}
}
impl Transaction {
pub fn new(
txid: String,
amount: rust_decimal::Decimal,
description: String,
account: Account,
date: String,
category: String,
tags: Vec<String>,
from: Account,
) -> Transaction {
Transaction {
txid,
amount,
description,
account,
date,
category,
tags,
from,
}
}
pub fn execute(&mut self) {
if self.amount > dec!(0.0) {
self.account.deposit(self.amount);
self.from.withdraw(self.amount);
}
}
pub fn revert(&mut self) {
if self.amount > dec!(0.0) {
self.account.withdraw(self.amount);
self.from.deposit(self.amount);
}
}
}
pub struct Mbl {
pub accounts: Vec<Account>,
pub transactions: Vec<Transaction>,
pub tags: Vec<String>,
pub categories: Vec<String>,
pub users: Vec<String>,
pub settings: Vec<String>,
}
impl Mbl {
pub fn new(
accounts: Vec<Account>,
transactions: Vec<Transaction>,
tags: Vec<String>,
categories: Vec<String>,
users: Vec<String>,
settings: Vec<String>,
) -> Self {
Self {
accounts,
transactions,
tags,
categories,
users,
settings,
}
}
pub fn add_account(&mut self, account: Account) {
self.accounts.push(account);
}
pub fn execute(&mut self) {
for t in self.transactions.iter_mut() {
if t.amount > dec!(0.0) {
t.execute();
}
}
}
pub fn add_transaction(&mut self, transaction: Transaction) {
if transaction.amount > dec!(0.0) {
self.transactions.push(transaction);
}
}
pub fn get_account_by_id(&self, id: String) -> Account {
let mut res: Account = Account {
name: ("first".to_string()),
balance: (dec!(0.0)),
id: ("1".to_string()),
};
let mut found = false;
for account in self.accounts.iter() {
if account.id == id {
found = true;
res = account.clone();
}
}
if !found {
panic!("No such account")
}
return res;
}
}
impl Clone for Account {
fn clone(&self) -> Self {
Self {
name: (self.name.clone()),
balance: (self.balance),
id: (self.id.clone()),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
#[test]
fn test_account() {
{
let mut account = Account::new("first".to_string(), dec!(0.0), "1".to_string());
assert_eq!(account.name, "first");
assert_eq!(account.balance, dec!(0.0));
assert_eq!(account.id, "1");
account.deposit(dec!(10.0));
assert_eq!(account.balance, dec!(10.0));
account.withdraw(dec!(11.0));
assert_eq!(account.balance, dec!(10.0));
account.withdraw(dec!(10.0));
assert_eq!(account.balance, dec!(0.0));
}
}
#[test]
fn test_transaction() {
{
let account = Account::new("first".to_string(), dec!(20.0), "1".to_string());
let account2 = Account::new("second".to_string(), dec!(20.0), "2".to_string());
let mut transaction = Transaction::new(
"1".to_string(),
dec!(10.0),
"buy".to_string(),
account,
"2025-01-01".to_string(),
"food".to_string(),
vec!["food".to_string()],
account2,
);
transaction.execute();
assert_eq!(transaction.account.balance, dec!(30.0));
}
}
}