envelope_cli/cli/
transfer.rs

1//! CLI command handler for account transfers
2//!
3//! Handles transferring funds between accounts, creating linked
4//! transaction pairs that maintain balance consistency.
5
6use chrono::NaiveDate;
7
8use crate::error::{EnvelopeError, EnvelopeResult};
9use crate::models::Money;
10use crate::services::{AccountService, TransferService};
11use crate::storage::Storage;
12
13/// Handle the transfer command
14pub 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    // Find source account
26    let from_account = account_service
27        .find(from)?
28        .ok_or_else(|| EnvelopeError::account_not_found(from))?;
29
30    // Find destination account
31    let to_account = account_service
32        .find(to)?
33        .ok_or_else(|| EnvelopeError::account_not_found(to))?;
34
35    // Validate source and destination are different accounts
36    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    // Parse amount
43    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    // Parse date (default to today)
51    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}