# Feature Batch 2 Design - 16 Features Date: 2026-03-03 ## Overview 16 features sourced from Reddit community research on personal finance app wishlists, filtered against Outlay's existing feature set. ## Features ### 5. Custom Budget Cycle Users can choose how budget periods are defined: - **Calendar month** (default, current behavior): 1st to last day of month - **Payday offset**: budget runs from day X to day X-1 of next month (e.g. 15th to 14th) - **Rolling N-day**: budget period is a fixed window of N days from a configurable start date New settings: `budget_cycle_mode` (calendar/payday/rolling), `budget_cycle_start_day` (1-31), `budget_cycle_days` (e.g. 30). Affects: Budgets view period labels ("Mar 15 - Apr 14"), navigation step size, all budget queries, safe-to-spend calculation, and budget threshold notifications. Charts and History remain calendar-month based to avoid confusion. Cycle configuration accessible via a gear icon popover next to the month nav in Budgets view. ### 6. Bulk Transaction Operations Selection mode in History view: - "Select" button in header bar activates selection mode - Checkboxes appear on each transaction row - Long-press also enters selection mode - Action bar: "Delete (N)", "Recategorize", "Tag", "Select All", "Cancel" - Delete shows confirmation dialog with count - Recategorize opens a category picker, applies to all selected - Tag opens a multi-select tag picker, applies to all selected ### 7. Monthly/Yearly Recap Part of the new Insights view (see below). Toggle between "This Month" and "This Year". Monthly recap: total income, expenses, net, transaction count. Per-category rows showing amount, percentage of total, and change vs previous month with directional arrows. Yearly recap: month-by-month summary with sparklines, year-over-year comparison. "Share as PDF" button reuses existing PDF export. ### 8. Natural Language Entry Dedicated smart entry bar at the top of Log view and in Quick Add popup. `adw::EntryRow` titled "Quick entry" with placeholder "e.g. Coffee 4.50 at Starbucks". Parser (`outlay-core/src/nlp.rs`): - `parse_transaction(input, categories) -> Option` - Extracts amount (required), category (fuzzy match), note, payee (after "at"/"from"/"to") - Patterns: "Coffee 4.50", "Lunch 12.50 at Subway", "4.50 groceries milk", "$25 gas" Preview row shows parsed result below the entry. Press Enter to save. Existing detailed form remains below for manual entry. ### 9. Sankey Diagram New section in Charts view after existing charts. Title: "Money Flow". Cairo-drawn Sankey layout: - Left nodes: income categories - Right nodes: expense categories - Center node: "Available" (net) - Flow widths proportional to amounts - Income flows colored green, expense flows use category colors - Hover shows amount labels Layout computation in `outlay-core/src/sankey.rs`: - `compute_sankey_layout(income_sources, expense_categories) -> SankeyLayout` - Returns node positions and bezier curve control points Month navigation synced with other charts. ### 10. What-If / Sandbox Mode Toggle button in Budgets view header bar. When active: - Header tinted amber, label shows "Sandbox Mode" - All budget amounts become inline-editable - Changes stored in temporary `HashMap`, NOT written to DB - Progress bars and safe-to-spend recalculate live - Modified rows get a visual indicator - "Apply Changes" button writes sandbox values to DB - "Discard" button exits sandbox, reverts to real data ### 11. Tags UI Database tables already exist (`tags`, `transaction_tags`). Need GTK surfaces: - History view: tag chips in FlowBox alongside category chips (different visual style - outlined vs filled). Clicking a tag chip filters to transactions with that tag. - Log view: tags already have an entry field. Ensure it works with `get_or_create_tag()` and `set_transaction_tags()`. - Edit dialog: show and edit tags on existing transactions. - Bulk operations: "Tag" action in selection mode. ### 12. Transaction Splits UI Database tables already exist (`transaction_splits`). Need GTK surfaces: - Log view / Edit dialog: "Split" toggle button next to category row - When enabled: category row replaced by split list - Each split row: category dropdown + amount entry + optional note - "Add Split" button for more rows - Validation: split total must equal transaction amount ("Remaining: X.XX" label) - On save: `insert_splits()` called after transaction insert - Edit dialog: if `has_splits()`, pre-fills split rows ### 13. Transaction Templates UI Database tables already exist (`transaction_templates`). Need GTK surfaces: - Log view: "Templates" icon button in header opens a popover - Lists saved templates as `adw::ActionRow` items (name, amount, category icon, type badge) - Tapping a template fills the log form - "Save as Template" button at bottom of form when amount + category are filled - Opens dialog for template name, saves via `insert_template()` ### 14. Auto-Categorization Rules UI Database tables already exist (`categorization_rules`). Need GTK surface in Settings: - New "Categorization Rules" `adw::PreferencesGroup` between Categories and Import/Export - Each rule: `adw::ActionRow` showing field (Note/Payee), pattern, target category - "Add Rule" button opens dialog: field dropdown, pattern entry, category dropdown, priority spinner - Delete button per row - Rules applied during import and optionally during manual entry ### 15. Searchable Category Picker Replace all `adw::ComboRow` category dropdowns with a searchable version: - Custom `gtk::FilterListModel` backed by `gtk::StringFilter` - Search entry at top of dropdown popup - Typing filters category list in real-time - Shared utility: `fn make_searchable_category_combo(...) -> adw::ComboRow` - Used in: log view, edit dialog, budget dialog, quick add, split rows, rules dialog ### 16. PDF Bank Statement Import New "PDF" import button in Settings alongside existing importers. Two-phase extraction (`outlay-core/src/import_pdf.rs`): 1. Text extraction via `pdf-extract` crate - look for tabular date/description/amount patterns 2. If no extractable text found, fall back to existing Tesseract OCR pipeline Preview dialog shows extracted transactions in an editable list. Each row: date, description, amount, category (auto-matched via categorization rules, fallback "Uncategorized"). Import All / Import Selected buttons. Merge/replace mode toggle. New dependency: `pdf-extract` crate. ### 17. Spending Streaks / Gamification Dedicated Insights view (new sidebar item) with three sections: **Streaks:** - No-spend streak: consecutive days with zero expenses, flame icon, "Best: X days" - Under-budget streak: consecutive months staying under total budget cap - Savings streak: consecutive months with goal contributions **Achievements:** - Grid of achievement badges, earned ones colored, unearned dimmed - Starter set: "First Transaction", "7-Day No-Spend", "30-Day No-Spend", "Month Under Budget", "3 Months Under Budget", "First Goal Completed", "100 Transactions", "Budget Streak 6mo" - Checked and awarded on app launch New tables: `streaks`, `achievements`. ### 18. Financial Goal Projections Enhance existing Goals view: - Each active goal row gets subtitle: "At current rate, reachable by [date]" - Based on average monthly contributions over last 3 months - States: "On track - X months ahead", "Behind schedule - need X.XX/month", "Start contributing to see projection" - Expandable section per goal: mini line chart showing saved amount over time with projected line to target ### 19. Credit Card Billing Cycle Tracking Dedicated Credit Cards view (new sidebar item). **Summary card:** total balance, total limit, utilization bar, next due date. **Card list:** each card is `adw::ExpanderRow`: - Collapsed: name, balance, due countdown, utilization mini-bar - Expanded: statement close date, minimum payment, payment history (last 3 months) - Actions: "Record Payment" (creates expense transaction, reduces balance), Edit, Delete New table: `credit_cards` (name, credit_limit, statement_close_day, due_day, min_payment_pct, current_balance, currency, color, active). ### 24. Spending Anomaly Alerts in UI Surface existing `detect_anomalies()` in two places: - **History view:** `adw::Banner` at top when anomalies exist for the displayed month: "N spending insights for this month". Tapping navigates to Insights view. - **Insights view:** Anomaly Alerts section renders each anomaly as `adw::ActionRow` with warning/info icons. Clickable to navigate to category in History. - **Startup:** toast on first launch of the day if current month has insights. ## Schema Migration (v8 -> v9) New table: `credit_cards` - see feature #19 above. New table: `streaks` - see feature #17 above. New table: `achievements` - see feature #17 above. New settings: `budget_cycle_mode`, `budget_cycle_start_day`, `budget_cycle_days`. ## New Files - `outlay-core/src/nlp.rs` - natural language transaction parser - `outlay-core/src/import_pdf.rs` - PDF statement import - `outlay-core/src/sankey.rs` - Sankey layout computation - `outlay-gtk/src/insights_view.rs` - Insights view (streaks, achievements, recap, anomalies) - `outlay-gtk/src/credit_cards_view.rs` - Credit Cards view ## New Dependencies - `pdf-extract` crate for PDF text extraction ## Modified Files - `outlay-core/src/db.rs` - migration v9, new CRUD methods for credit cards / streaks / achievements / recap queries / budget period computation - `outlay-core/src/models.rs` - new structs (CreditCard, Achievement, Streak, ParsedTransaction, SankeyLayout, etc.) - `outlay-core/src/lib.rs` - register new modules - `outlay-gtk/src/main.rs` - register new views, startup achievement checks - `outlay-gtk/src/window.rs` - add Insights and Credit Cards to sidebar navigation - `outlay-gtk/src/history_view.rs` - bulk operations, tag chips, anomaly banner - `outlay-gtk/src/log_view.rs` - NL entry bar, templates button, split toggle - `outlay-gtk/src/edit_dialog.rs` - splits editing, tags editing - `outlay-gtk/src/budgets_view.rs` - custom cycle, what-if sandbox - `outlay-gtk/src/charts_view.rs` - Sankey diagram section - `outlay-gtk/src/goals_view.rs` - projection subtitles and mini charts - `outlay-gtk/src/settings_view.rs` - categorization rules section, PDF import button - `outlay-gtk/src/quick_add.rs` - NL entry bar, searchable category - `outlay-gtk/Cargo.toml` - add pdf-extract dependency