fix(cli): Remove unwanted and unimplemented clear-cache

This commit is contained in:
2025-12-06 18:07:39 +01:00
parent 758a16bd73
commit 7034799926
7 changed files with 85 additions and 42 deletions

View File

@@ -78,7 +78,6 @@ Banks2FF uses a structured command-line interface with the following commands:
- `accounts link` - Manage account links between sources and destinations (with interactive and smart modes) - `accounts link` - Manage account links between sources and destinations (with interactive and smart modes)
- `transactions list [account] [--details] [--limit N]` - Show transaction summary or details for an account (interactive selection if no account specified) - `transactions list [account] [--details] [--limit N]` - Show transaction summary or details for an account (interactive selection if no account specified)
- `transactions cache-status` - Display cache status and statistics - `transactions cache-status` - Display cache status and statistics
- `transactions clear-cache` - Clear transaction cache
Use `cargo run -p banks2ff -- --help` for detailed command information. Use `cargo run -p banks2ff -- --help` for detailed command information.

View File

@@ -450,7 +450,12 @@ impl TransactionSource for GoCardlessAdapter {
} }
#[instrument(skip(self))] #[instrument(skip(self))]
async fn get_cached_transactions(&self, account_id: &str, start: NaiveDate, end: NaiveDate) -> Result<Vec<BankTransaction>> { async fn get_cached_transactions(
&self,
account_id: &str,
start: NaiveDate,
end: NaiveDate,
) -> Result<Vec<BankTransaction>> {
// Load or get transaction cache // Load or get transaction cache
let mut caches = self.transaction_caches.lock().await; let mut caches = self.transaction_caches.lock().await;
let cache = caches.entry(account_id.to_string()).or_insert_with(|| { let cache = caches.entry(account_id.to_string()).or_insert_with(|| {

View File

@@ -1,7 +0,0 @@
use crate::core::config::Config;
pub async fn handle_clear_cache(_config: Config) -> anyhow::Result<()> {
// TODO: Implement cache clearing
println!("Cache clearing not yet implemented");
Ok(())
}

View File

@@ -180,28 +180,37 @@ async fn show_transaction_details(
// Sort by date descending and take the limit // Sort by date descending and take the limit
let mut sorted_transactions = transactions.clone(); let mut sorted_transactions = transactions.clone();
sorted_transactions.sort_by(|a, b| b.date.cmp(&a.date)); sorted_transactions.sort_by(|a, b| b.date.cmp(&a.date));
let to_show = sorted_transactions.into_iter().take(limit).collect::<Vec<_>>(); let to_show = sorted_transactions
.into_iter()
.take(limit)
.collect::<Vec<_>>();
// Display as table with proper column constraints // Display as table with proper column constraints
use comfy_table::{Table, presets::UTF8_FULL, Width::*, ColumnConstraint::*}; use comfy_table::{presets::UTF8_FULL, ColumnConstraint::*, Table, Width::*};
let mut table = Table::new(); let mut table = Table::new();
table.load_preset(UTF8_FULL); table.load_preset(UTF8_FULL);
table.set_header(vec!["Date", "Amount", "Description", "Counterparty"]); table.set_header(vec!["Date", "Amount", "Description", "Counterparty"]);
// Set column constraints for proper width control // Set column constraints for proper width control
table.set_constraints(vec![ table.set_constraints(vec![
UpperBoundary(Fixed(12)), // Date - fixed width UpperBoundary(Fixed(12)), // Date - fixed width
UpperBoundary(Fixed(22)), // Amount - fixed width UpperBoundary(Fixed(22)), // Amount - fixed width
UpperBoundary(Fixed(60)), // Description - wider fixed width UpperBoundary(Fixed(60)), // Description - wider fixed width
UpperBoundary(Fixed(25)), // Counterparty - fixed width UpperBoundary(Fixed(25)), // Counterparty - fixed width
]); ]);
for tx in &to_show { for tx in &to_show {
table.add_row(vec![ table.add_row(vec![
tx.date.to_string(), tx.date.to_string(),
format_amount(&tx.amount, &tx.currency, tx.foreign_amount.as_ref(), tx.foreign_currency.as_deref()), format_amount(
&tx.amount,
&tx.currency,
tx.foreign_amount.as_ref(),
tx.foreign_currency.as_deref(),
),
mask_description(&tx.description), mask_description(&tx.description),
tx.counterparty_name.clone() tx.counterparty_name
.clone()
.unwrap_or_else(|| "Unknown".to_string()), .unwrap_or_else(|| "Unknown".to_string()),
]); ]);
} }
@@ -227,11 +236,21 @@ fn mask_description(description: &str) -> String {
} }
} }
fn format_amount(amount: &Decimal, currency: &str, foreign_amount: Option<&Decimal>, foreign_currency: Option<&str>) -> String { fn format_amount(
amount: &Decimal,
currency: &str,
foreign_amount: Option<&Decimal>,
foreign_currency: Option<&str>,
) -> String {
let primary = format!("{:.2} {}", amount, currency_symbol(currency)); let primary = format!("{:.2} {}", amount, currency_symbol(currency));
if let (Some(fx_amount), Some(fx_currency)) = (foreign_amount, foreign_currency) { if let (Some(fx_amount), Some(fx_currency)) = (foreign_amount, foreign_currency) {
format!("{} ({:.2} {})", primary, fx_amount, currency_symbol(fx_currency)) format!(
"{} ({:.2} {})",
primary,
fx_amount,
currency_symbol(fx_currency)
)
} else { } else {
primary primary
} }

View File

@@ -1,12 +1,10 @@
pub mod cache; pub mod cache;
pub mod clear;
pub mod list; pub mod list;
use crate::core::config::Config; use crate::core::config::Config;
use clap::Subcommand; use clap::Subcommand;
use self::cache::handle_cache_status; use self::cache::handle_cache_status;
use self::clear::handle_clear_cache;
use self::list::handle_list as handle_transaction_list; use self::list::handle_list as handle_transaction_list;
#[derive(Subcommand, Debug)] #[derive(Subcommand, Debug)]
@@ -24,8 +22,6 @@ pub enum TransactionCommands {
}, },
/// Show cache status /// Show cache status
CacheStatus, CacheStatus,
/// Clear transaction cache
ClearCache,
} }
pub async fn handle_transactions( pub async fn handle_transactions(
@@ -43,9 +39,6 @@ pub async fn handle_transactions(
TransactionCommands::CacheStatus => { TransactionCommands::CacheStatus => {
handle_cache_status(config).await?; handle_cache_status(config).await?;
} }
TransactionCommands::ClearCache => {
handle_clear_cache(config).await?;
}
} }
Ok(()) Ok(())
} }

View File

@@ -32,7 +32,12 @@ pub trait TransactionSource: Send + Sync {
async fn get_account_status(&self) -> Result<Vec<AccountStatus>>; async fn get_account_status(&self) -> Result<Vec<AccountStatus>>;
async fn get_transaction_info(&self, account_id: &str) -> Result<TransactionInfo>; async fn get_transaction_info(&self, account_id: &str) -> Result<TransactionInfo>;
async fn get_cache_info(&self) -> Result<Vec<CacheInfo>>; async fn get_cache_info(&self) -> Result<Vec<CacheInfo>>;
async fn get_cached_transactions(&self, account_id: &str, start: NaiveDate, end: NaiveDate) -> Result<Vec<BankTransaction>>; async fn get_cached_transactions(
&self,
account_id: &str,
start: NaiveDate,
end: NaiveDate,
) -> Result<Vec<BankTransaction>>;
/// Account discovery for linking /// Account discovery for linking
async fn discover_accounts(&self) -> Result<Vec<Account>>; async fn discover_accounts(&self) -> Result<Vec<Account>>;
@@ -70,8 +75,15 @@ impl<T: TransactionSource> TransactionSource for &T {
(**self).get_cache_info().await (**self).get_cache_info().await
} }
async fn get_cached_transactions(&self, account_id: &str, start: NaiveDate, end: NaiveDate) -> Result<Vec<BankTransaction>> { async fn get_cached_transactions(
(**self).get_cached_transactions(account_id, start, end).await &self,
account_id: &str,
start: NaiveDate,
end: NaiveDate,
) -> Result<Vec<BankTransaction>> {
(**self)
.get_cached_transactions(account_id, start, end)
.await
} }
async fn discover_accounts(&self) -> Result<Vec<Account>> { async fn discover_accounts(&self) -> Result<Vec<Account>> {

View File

@@ -4,6 +4,14 @@
This document outlines a phased plan to refactor the `banks2ff` CLI from a tightly coupled, single-purpose sync tool into a modular, multi-source financial synchronization application. The refactor maintains the existing hexagonal architecture while enabling inspection of accounts, transactions, and sync status, support for multiple data sources (GoCardless, CSV, CAMT.053, MT940), and preparation for web API exposure. This document outlines a phased plan to refactor the `banks2ff` CLI from a tightly coupled, single-purpose sync tool into a modular, multi-source financial synchronization application. The refactor maintains the existing hexagonal architecture while enabling inspection of accounts, transactions, and sync status, support for multiple data sources (GoCardless, CSV, CAMT.053, MT940), and preparation for web API exposure.
## Current Status Summary
- **Completed Phases**: 1, 2, 3, 4, 4.5, 9.5 (6/10 phases complete)
- **Partially Complete**: Phase 5 (Status/Cache Management - 50% done)
- **Remaining Phases**: 6, 7, 8, 10 (4 phases pending)
- **Core Functionality**: CLI structure, account linking, transaction inspection all working
- **Next Priority**: Fix cache-status to scan disk for all transaction caches
## Goals ## Goals
- **Decouple CLI Architecture**: Separate CLI logic from core business logic to enable multiple entry points (CLI, web API) - **Decouple CLI Architecture**: Separate CLI logic from core business logic to enable multiple entry points (CLI, web API)
@@ -42,6 +50,8 @@ COMMANDS:
**Objective**: Establish new subcommand architecture while preserving existing sync functionality. **Objective**: Establish new subcommand architecture while preserving existing sync functionality.
**Completion Date**: Early implementation
**Steps:** **Steps:**
1. ✅ Refactor `main.rs` to use `clap::Subcommand` with nested enums for commands and subcommands 1. ✅ Refactor `main.rs` to use `clap::Subcommand` with nested enums for commands and subcommands
2. ✅ Extract environment loading and client initialization into a `cli::setup` module 2. ✅ Extract environment loading and client initialization into a `cli::setup` module
@@ -142,7 +152,7 @@ COMMANDS:
4. ✅ Ensure sensitive data masking in all outputs 4. ✅ Ensure sensitive data masking in all outputs
5. Add progress indicators for long-running operations (pending) 5. Add progress indicators for long-running operations (pending)
6. ✅ Implement `accounts` command with `list` and `status` subcommands 6. ✅ Implement `accounts` command with `list` and `status` subcommands
7. ✅ Implement `transactions` command with `list`, `cache-status`, and `clear-cache` subcommands 7. ✅ Implement `transactions` command with `list` and `cache-status` subcommands
8. ✅ Add account and transaction inspection methods to adapter traits 8. ✅ Add account and transaction inspection methods to adapter traits
### Phase 4.5: Enhanced Transaction List UX ✅ COMPLETED ### Phase 4.5: Enhanced Transaction List UX ✅ COMPLETED
@@ -182,15 +192,20 @@ COMMANDS:
- Added `print_list_output` function for displaying collections of data - Added `print_list_output` function for displaying collections of data
- All code formatted with `cargo fmt` and linted with `cargo clippy` - All code formatted with `cargo fmt` and linted with `cargo clippy`
### Phase 5: Status and Cache Management ### Phase 5: Status and Cache Management 🔄 PARTIALLY COMPLETED
**Objective**: Implement status overview and cache management commands. **Objective**: Implement status overview and cache inspection commands.
**Steps:** **Steps:**
1. Implement `status` command aggregating data from all adapters 1. Implement `accounts status` command aggregating account data from adapters
2. Add cache inspection and clearing functionality to `transactions cache-status` and `transactions clear-cache` 2. Add cache inspection functionality to `transactions cache-status` (shows in-memory caches only)
3. Create status models for sync health metrics 3. ❌ Fix `transactions cache-status` to scan disk for all transaction caches (currently missing disk-based caches)
4. Integrate with existing debug logging infrastructure 4. ❌ Create status models for sync health metrics
5. ❌ Integrate with existing debug logging infrastructure
**Current Status:**
- `accounts status` works and shows account sync status
- `transactions cache-status` exists but only shows in-memory caches; needs disk scanning to be useful
**Testing:** **Testing:**
- Unit tests for status aggregation logic - Unit tests for status aggregation logic
@@ -313,10 +328,17 @@ COMMANDS:
## Success Criteria ## Success Criteria
- All existing sync functionality preserved - All existing sync functionality preserved
- New commands work with all supported sources/destinations - New commands work with all supported sources/destinations
- Core logic remains adapter-agnostic - Core logic remains adapter-agnostic
- Comprehensive test coverage maintained - Comprehensive test coverage maintained
- Performance meets or exceeds current benchmarks - Performance meets or exceeds current benchmarks
- Architecture supports future web API development</content> - Architecture supports future web API development
## Completion Notes
- **Phase 5 Fix Required**: Update `GoCardlessAdapter::get_cache_info()` to scan cache directory and load all transaction caches from disk (similar to `get_transaction_info()` fix)
- **Remove Cache Clearing**: ✅ COMPLETED - Removed `transactions clear-cache` command from CLI as it's not useful
- **Status Metrics**: Consider adding sync health metrics beyond account status
- **Multi-Source Ready**: Architecture supports adding CSV, CAMT.053, MT940 adapters when needed</content>
<parameter name="filePath">specs/cli-refactor-plan.md <parameter name="filePath">specs/cli-refactor-plan.md