envelope_cli/cli/
transfer.rs1use chrono::NaiveDate;
7
8use crate::error::{EnvelopeError, EnvelopeResult};
9use crate::models::Money;
10use crate::services::{AccountService, TransferService};
11use crate::storage::Storage;
12
13pub fn handle_transfer_command(
15 storage: &Storage,
16 from: &str,
17 to: &str,
18 amount: &str,
19 date: Option<&str>,
20 memo: Option<String>,
21) -> EnvelopeResult<()> {
22 let account_service = AccountService::new(storage);
23 let transfer_service = TransferService::new(storage);
24
25 let from_account = account_service
27 .find(from)?
28 .ok_or_else(|| EnvelopeError::account_not_found(from))?;
29
30 let to_account = account_service
32 .find(to)?
33 .ok_or_else(|| EnvelopeError::account_not_found(to))?;
34
35 if from_account.id == to_account.id {
37 return Err(EnvelopeError::Validation(
38 "Source and destination accounts cannot be the same.".to_string(),
39 ));
40 }
41
42 let amount = Money::parse(amount).map_err(|e| {
44 EnvelopeError::Validation(format!(
45 "Invalid amount format: '{}'. Use format like '100.00' or '100'. Error: {}",
46 amount, e
47 ))
48 })?;
49
50 let date = if let Some(date_str) = date {
52 NaiveDate::parse_from_str(date_str, "%Y-%m-%d").map_err(|_| {
53 EnvelopeError::Validation(format!(
54 "Invalid date format: '{}'. Use YYYY-MM-DD",
55 date_str
56 ))
57 })?
58 } else {
59 chrono::Local::now().date_naive()
60 };
61
62 let result =
63 transfer_service.create_transfer(from_account.id, to_account.id, amount, date, memo)?;
64
65 println!("Transfer created:");
66 println!(
67 " From: {} ({})",
68 from_account.name, result.from_transaction.amount
69 );
70 println!(
71 " To: {} ({})",
72 to_account.name, result.to_transaction.amount
73 );
74 println!(" Date: {}", date);
75
76 Ok(())
77}