Change object model and add crate Error type

This commit is contained in:
2026-05-03 14:17:50 +02:00
parent a9de66a49f
commit fa4cc722e2
12 changed files with 283 additions and 247 deletions
+43 -49
View File
@@ -1,14 +1,8 @@
use clap::{Parser, Subcommand};
use std::{
error::Error,
fs::File,
io::{Read, stdin, stdout},
path::PathBuf,
};
use std::{io::stdout, path::PathBuf};
use ynabmunger::Transaction;
use ynabmunger::csv::{output_csv, read_transactions};
use ynabmunger::ynab::{Lookup, Ynab};
use ynabmunger::csv::{output_csv, read_transactions_from};
use ynabmunger::ynab::Client;
#[derive(Subcommand)]
enum Command {
@@ -103,33 +97,13 @@ struct Cli {
command: Command,
}
fn read_transactions_from(
inputs: &[PathBuf],
format: &str,
) -> Result<Vec<Transaction>, Box<dyn Error>> {
Ok(if inputs.is_empty() {
vec![Box::new(stdin()) as Box<dyn Read>]
} else {
inputs
.into_iter()
.map(|p| -> Result<Box<dyn Read>, _> { Ok(Box::new(File::open(p)?)) })
.collect::<Result<Vec<_>, std::io::Error>>()?
}
.iter_mut()
.map(|s| read_transactions(s, format))
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.flatten()
.collect())
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
async fn main() -> anyhow::Result<()> {
let cli = Cli::parse();
match cli.command {
Command::Plans { token } => {
let plans = Ynab::new(&token).list_plans().await?;
let plans = Client::new(&token).list_plans().await?;
println!("Available plans:");
for plan in plans {
println!(" - {}", plan);
@@ -141,8 +115,14 @@ async fn main() -> Result<(), Box<dyn Error>> {
plan,
plan_id,
} => {
let plan = Lookup::from_options(plan, plan_id)?;
let accounts = Ynab::list_accounts(&Ynab::new(&token), plan).await?;
let client = Client::new(&token);
let plan = match (plan, plan_id) {
(_, Some(id)) => Ok(client.plan_from_id(&id)),
(Some(name), _) => Ok(client.plan_from_name(&name).await?),
_ => Err(ynabmunger::Error::Text("no plan given".to_string())),
}?;
let accounts = plan.list_accounts().await?;
println!("Available accounts in plan:");
for account in accounts {
println!(" - {}", account);
@@ -156,21 +136,24 @@ async fn main() -> Result<(), Box<dyn Error>> {
account,
account_id,
} => {
let plan = Lookup::from_options(plan, plan_id)?;
let client = Client::new(&token);
let plan = match (plan, plan_id) {
(_, Some(id)) => Ok(client.plan_from_id(&id)),
(Some(name), _) => Ok(client.plan_from_name(&name).await?),
_ => Err(ynabmunger::Error::Text("no plan given".to_string())),
}?;
// Account is optional here
let accountstr: &str;
let account = match (account, account_id) {
(None, None) => {
accountstr = "";
None
}
(name, id) => {
accountstr = " for account";
Some(Lookup::from_options(name, id)?)
}
let (account, accountstr) = match (account, account_id) {
(_, Some(id)) => (Some(plan.account_from_id(&id)), " for account"),
(Some(name), _) => (Some(plan.account_from_name(&name).await?), " for account"),
_ => (None, ""),
};
let transactions = match account {
Some(account) => account.list_transactions().await?,
None => plan.list_transactions(None).await?,
};
let transactions = Ynab::new(&token).list_transactions(plan, account).await?;
println!("Transactions{} in the last 30 days:", accountstr);
for t in transactions {
println!("{},{},{}", t.date, t.payee, t.amount);
@@ -187,16 +170,27 @@ async fn main() -> Result<(), Box<dyn Error>> {
format,
inputs,
} => {
let plan = Lookup::from_options(plan, plan_id)?;
let account = Lookup::from_options(account, account_id)?;
let client = Client::new(&token);
let plan = match (plan, plan_id) {
(_, Some(id)) => Ok(client.plan_from_id(&id)),
(Some(name), _) => Ok(client.plan_from_name(&name).await?),
_ => Err(ynabmunger::Error::Text("no plan given".to_string())),
}?;
let account = match (account, account_id) {
(_, Some(id)) => Ok(plan.account_from_id(&id)),
(Some(name), _) => Ok(plan.account_from_name(&name).await?),
_ => Err(ynabmunger::Error::Text("no account given".to_string())),
}?;
let transactions = read_transactions_from(&inputs, &format)?;
Ynab::new(&token).upload(&transactions, plan, account).await
account.upload(&transactions).await?;
Ok(())
}
Command::Convert { format, inputs } => {
let transactions = read_transactions_from(&inputs, &format)?;
output_csv(stdout(), &transactions)
output_csv(stdout(), &transactions)?;
Ok(())
}
}
}