Add feature batch 2, subscription/recurring sync, smooth charts, and app icon
- Implement subscriptions view with bidirectional recurring transaction sync - Add cascade delete/pause/resume between subscriptions and recurring - Fix foreign key constraints when deleting recurring transactions - Add cross-view instant refresh via callback pattern - Replace Bezier chart smoothing with Fritsch-Carlson monotone Hermite interpolation - Smooth budget sparklines using shared monotone_subdivide function - Add vertical spacing to budget rows - Add app icon (receipt on GNOME blue) in all sizes for desktop, web, and AppImage - Add calendar, credit cards, forecast, goals, insights, and wishlist views - Add date picker, numpad, quick-add, category combo, and edit dialog components - Add import/export for CSV, JSON, OFX, QIF formats - Add NLP transaction parsing, OCR receipt scanning, expression evaluator - Add notification support, Sankey chart, tray icon - Add demo data seeder with full DB wipe - Expand database schema with subscriptions, goals, credit cards, and more
This commit is contained in:
@@ -39,7 +39,7 @@ pub fn export_transactions_csv<W: Write>(
|
||||
let transactions = db.list_all_transactions(from, to)?;
|
||||
let mut wtr = Writer::from_writer(writer);
|
||||
|
||||
wtr.write_record(["Date", "Type", "Category", "Amount", "Currency", "Exchange Rate", "Note"])?;
|
||||
wtr.write_record(["Date", "Type", "Category", "Amount", "Currency", "Exchange Rate", "Note", "Payee"])?;
|
||||
|
||||
for txn in &transactions {
|
||||
let cat_name = db
|
||||
@@ -55,6 +55,7 @@ pub fn export_transactions_csv<W: Write>(
|
||||
txn.currency.clone(),
|
||||
format!("{:.4}", txn.exchange_rate),
|
||||
txn.note.clone().unwrap_or_default(),
|
||||
txn.payee.clone().unwrap_or_default(),
|
||||
])?;
|
||||
}
|
||||
|
||||
@@ -86,6 +87,7 @@ mod tests {
|
||||
note: Some("Lunch".to_string()),
|
||||
date: NaiveDate::from_ymd_opt(2026, 3, 1).unwrap(),
|
||||
recurring_id: None,
|
||||
payee: None,
|
||||
};
|
||||
db.insert_transaction(&txn).unwrap();
|
||||
|
||||
@@ -96,7 +98,7 @@ mod tests {
|
||||
let output = String::from_utf8(buf).unwrap();
|
||||
let lines: Vec<&str> = output.trim().lines().collect();
|
||||
assert_eq!(lines.len(), 2);
|
||||
assert_eq!(lines[0], "Date,Type,Category,Amount,Currency,Exchange Rate,Note");
|
||||
assert_eq!(lines[0], "Date,Type,Category,Amount,Currency,Exchange Rate,Note,Payee");
|
||||
assert!(lines[1].contains("2026-03-01"));
|
||||
assert!(lines[1].contains("expense"));
|
||||
assert!(lines[1].contains("42.50"));
|
||||
@@ -131,6 +133,7 @@ mod tests {
|
||||
note: None,
|
||||
date: NaiveDate::from_ymd_opt(2026, 1, day).unwrap(),
|
||||
recurring_id: None,
|
||||
payee: None,
|
||||
};
|
||||
db.insert_transaction(&txn).unwrap();
|
||||
}
|
||||
@@ -162,6 +165,7 @@ mod tests {
|
||||
note: None,
|
||||
date: NaiveDate::from_ymd_opt(2026, 2, 1).unwrap(),
|
||||
recurring_id: None,
|
||||
payee: None,
|
||||
};
|
||||
let txn2 = NewTransaction {
|
||||
amount: 1000.0,
|
||||
@@ -172,6 +176,7 @@ mod tests {
|
||||
note: Some("Salary".to_string()),
|
||||
date: NaiveDate::from_ymd_opt(2026, 2, 1).unwrap(),
|
||||
recurring_id: None,
|
||||
payee: None,
|
||||
};
|
||||
db.insert_transaction(&txn1).unwrap();
|
||||
db.insert_transaction(&txn2).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user