envelope_cli/cli/
account.rs1use clap::Subcommand;
6
7use crate::display::account::{format_account_details, format_account_list};
8use crate::error::EnvelopeResult;
9use crate::models::{AccountType, Money};
10use crate::services::AccountService;
11use crate::storage::Storage;
12
13#[derive(Subcommand)]
15pub enum AccountCommands {
16 Create {
18 name: String,
20 #[arg(short = 't', long, default_value = "checking")]
22 account_type: String,
23 #[arg(short, long, default_value = "0")]
25 balance: String,
26 #[arg(long)]
28 off_budget: bool,
29 },
30 List {
32 #[arg(short, long)]
34 all: bool,
35 },
36 Show {
38 account: String,
40 },
41 Edit {
43 account: String,
45 #[arg(short, long)]
47 name: Option<String>,
48 },
49 Archive {
51 account: String,
53 },
54 Unarchive {
56 account: String,
58 },
59}
60
61pub fn handle_account_command(storage: &Storage, cmd: AccountCommands) -> EnvelopeResult<()> {
63 let service = AccountService::new(storage);
64
65 match cmd {
66 AccountCommands::Create {
67 name,
68 account_type,
69 balance,
70 off_budget,
71 } => {
72 let account_type = AccountType::parse(&account_type).ok_or_else(|| {
73 crate::error::EnvelopeError::Validation(format!(
74 "Invalid account type: '{}'. Valid types: checking, savings, credit, cash, investment, line_of_credit, other",
75 account_type
76 ))
77 })?;
78
79 let starting_balance = Money::parse(&balance).map_err(|e| {
80 crate::error::EnvelopeError::Validation(format!(
81 "Invalid balance format: '{}'. Use format like '1000.00' or '1000'. Error: {}",
82 balance, e
83 ))
84 })?;
85
86 let account = service.create(&name, account_type, starting_balance, !off_budget)?;
87
88 println!("Created account: {}", account.name);
89 println!(" Type: {}", account.account_type);
90 println!(" Starting Balance: {}", account.starting_balance);
91 println!(
92 " On Budget: {}",
93 if account.on_budget { "Yes" } else { "No" }
94 );
95 println!(" ID: {}", account.id);
96 }
97
98 AccountCommands::List { all } => {
99 let summaries = service.list_with_balances(all)?;
100 print!("{}", format_account_list(&summaries));
101 }
102
103 AccountCommands::Show { account } => {
104 let found = service
105 .find(&account)?
106 .ok_or_else(|| crate::error::EnvelopeError::account_not_found(&account))?;
107
108 let summary = service.get_summary(&found)?;
109 print!("{}", format_account_details(&summary));
110 }
111
112 AccountCommands::Edit { account, name } => {
113 let found = service
114 .find(&account)?
115 .ok_or_else(|| crate::error::EnvelopeError::account_not_found(&account))?;
116
117 if name.is_none() {
118 println!("No changes specified. Use --name to change the account name.");
119 return Ok(());
120 }
121
122 let updated = service.update(found.id, name.as_deref())?;
123 println!("Updated account: {}", updated.name);
124 }
125
126 AccountCommands::Archive { account } => {
127 let found = service
128 .find(&account)?
129 .ok_or_else(|| crate::error::EnvelopeError::account_not_found(&account))?;
130
131 let archived = service.archive(found.id)?;
132 println!("Archived account: {}", archived.name);
133 }
134
135 AccountCommands::Unarchive { account } => {
136 let found = service
137 .find(&account)?
138 .ok_or_else(|| crate::error::EnvelopeError::account_not_found(&account))?;
139
140 let unarchived = service.unarchive(found.id)?;
141 println!("Unarchived account: {}", unarchived.name);
142 }
143 }
144
145 Ok(())
146}