* Extract Entry.uncategorized_transactions scope, remove Family#uncategorized_transaction_count
Adds a single Entry.uncategorized_transactions scope containing the
shared conditions (transactions join, active accounts, category nil,
not transfer kinds, not excluded). All callers now use this scope:
- Entry.uncategorized_matching builds on it
- Transaction::Grouper::ByMerchantOrName#uncategorized_entries uses it
- categorizes_controller#uncategorized_entries_for uses it (also fixes
missing status/excluded filters that were silently absent before)
- Both controllers replace Current.family.uncategorized_transaction_count
with Current.accessible_entries.uncategorized_transactions.count so
the button count and wizard count both respect account sharing
Family#uncategorized_transaction_count removed as it is now unused and
was family-scoped rather than user-scoped.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Scope assign_entry write to Current.accessible_entries
Replaces unscoped Entry.where(id:) with Current.accessible_entries.where(id:)
so the write path is consistent with the find above it. Not exploitable
given the find would 404 first, but removes the pattern inconsistency.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add privacy-sensitive class to amounts in categorize wizard
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Extract uncategorized_count helper in CategorizesController
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix comment on uncategorized_transactions scope to mention draft accounts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Use uncategorized_count helper in assign_entry action
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add Quick Categorize Wizard (iteration 1)
Adds a step-by-step wizard for bulk-categorizing uncategorized transactions
and optionally creating auto-categorization rules, reducing friction after
connecting a new bank account.
New files:
- Transaction::Grouper abstraction + ByMerchantOrName strategy (groups by
merchant name when present, falls back to entry name; sorted by count desc)
- Transactions::CategorizesController (GET show / POST create)
- Wizard view at app/views/transactions/categorizes/show.html.erb
- Stimulus categorize_controller.js (Enter-key-to-select-first)
- Tests for grouper and controller
Modified files:
- routes.rb: resource :categorize inside namespace :transactions
- transactions_controller.rb: expose @uncategorized_count to index
- transactions/index.html.erb: Categorize (N) button in header
- family.rb: uncategorized_transaction_count query
- rules_controller.rb: return_to param support for wizard → rule editor flow
- rules/_form.html.erb, rules/new.html.erb: pass return_to through form
- i18n: categorizes show/create keys + rules.create.success
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Quick Categorize Wizard — iteration 2 polish
Six improvements from live testing:
- Breadcrumb: Home > Transactions > Categorize
- Layout: category picker + confirmation dialog above transaction list
- Inline confirmation dialog: clicking a category pill shows a <dialog>
summarising what will happen (N transactions → category, rule if checked)
with Confirm and Cancel buttons — no redirect to rule editor
- Direct rule creation: rule created with active: true in the controller
instead of redirecting to the rule editor; revert return_to plumbing from
RulesController, rules/_form, rules/new, rules/en.yml
- Individual row assignment: per-row category <select> submits via
PATCH /transactions/categorize/assign_entry and removes the row via
Turbo Stream (assign_entry action + route)
- Enter key guard: selectFirst only fires when exactly 1 pill is visible
after filtering
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Quick Categorize Wizard — iteration 3 reliability fixes and UX polish
- Fix Stimulus controller not loading: remove invalid `@hotwired/turbo` named
import (not in importmap); use global `Turbo.renderStreamMessage` instead
- Fix Enter key submitting form with wrong category when search field is
unfocused: move keydown listener to document so it fires regardless of focus
- Prevent Enter from submitting when multiple categories are visible
- Clear search filter after bulk category assignment (pill click or Enter),
but not after individual row dropdown assignment
- Update group transaction count and total amount live as entries are assigned
via row dropdown or partial bulk assignment
- Add turbo frames for remaining count and group summary so they update
without a full page reload
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Quick categorization polish
* refactoring
* Remove unused GROUPS_PER_BATCH constant, fix ERB self-closing tags
Wizard only ever uses one group at a time so limit: 1 is correct and
more honest than fetching 20 and discarding 19. ERB linter fixes are
whitespace/void-element corrections with no functional change.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Move Categorize button into ... menu on transactions index
Reduces header clutter by putting it in the overflow menu at the bottom,
where it only appears when there are uncategorized transactions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Scope categorize wizard to accessible entries only
Fixes a security issue where users with restricted account access via
account sharing could view and categorize transactions from accounts
they cannot access through normal transaction flows.
- Pass Current.accessible_entries to Transaction::Grouper so the wizard
only displays groups from accounts the user can see
- Use Current.accessible_entries on all write paths in create and
assign_entry, matching the pattern in TransactionCategoriesController
- Refactor Grouper to accept an entries scope instead of a family object,
keeping authorization concerns in the controller
- Add tests verifying inaccessible entries are hidden from the wizard
and cannot be categorized via forged POST/PATCH params
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Clamp position param to >= 0 to guard against negative offset
Prevents ArgumentError from Array#drop when a negative position is
passed via a tampered query string or form value.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Surface rule creation failure and add accessible names to entry row
- Capture Rule.create_from_grouping! return value; set flash[:alert] when
nil so users who checked "Create Rule" know it wasn't created (e.g. a
duplicate already exists); stream the notification for partial updates
- Add aria-label to the per-row checkbox and category select in
_entry_row so screen readers can identify which transaction each
control belongs to
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Localize breadcrumb labels in categorizes controller
Follows the pattern used by FamilyExportsController and ImportsController.
Adds 'transactions' and 'categorize' keys to the breadcrumbs locale file.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add error handling to categorize controller fetch calls
Check response.ok before parsing the body and add .catch handlers
so network failures and non-2xx responses are logged rather than
silently swallowed. On assignment failure the per-row select is
reset to empty so the user can retry.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Scope preview_rule to accessible entries only
Entry.uncategorized_matching now accepts an entries scope instead of a
family object, matching the same pattern used for Transaction::Grouper.
The preview_rule action passes Current.accessible_entries so rule
previews respect account sharing permissions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Scope remaining count to accessible entries
Adds Entry.uncategorized_count(entries) following the same pattern as
uncategorized_matching. Replaces all three uses of
Current.family.uncategorized_transaction_count in the categorize
controller so the remaining-count badge reflects only the transactions
the current user can actually access and categorize.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Comments got separated from their function
* Remove quick-categorize-wizard dev notes
This was a planning document used during development, not intended
for the final branch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Recompute remaining entries from server state after writes
Adds uncategorized_entries_for helper that reloads remaining entries
from the DB with a category_id IS NULL filter after each write, so
the partial-update Turbo Stream reflects server-side state rather than
trusting the client-provided remaining_ids. This handles the case where
a concurrent request has categorized one of the remaining entries
between page render and form submit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Rename create_from_grouping! to create_from_grouping
The method rescues RecordInvalid and returns nil, which contradicts
the bang convention. Dropping the ! correctly signals that callers
should check the return value.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Clamp offset in grouper to guard against negative values
The controller already clamps position before passing it as offset,
but clamping in the grouper itself prevents ArgumentError from
Array#drop if the grouper is ever called directly with a negative offset.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Juan José Mata <jjmata@jjmata.com>
* third party provider scoping
* Simplify logic and allow only admins to mange providers
* Broadcast fixes
* FIX tests and build
* Fixes
* Reviews
* Scope merchants
* DRY fixes
* Initial split transaction support
* Add support to unsplit and edit split
* Update show.html.erb
* FIX address reviews
* Improve UX
* Update show.html.erb
* Reviews
* Update edit.html.erb
* Add parent category to dialog
* Update en.yml
* Add UI indication to totals
* FIX ui update
* Add category select like rest of app
* Add split ui
* Add settings configuration for split transactions
- Adds a new settings section for appearance changes
- Also adds extra checks for delete and API calls
- Also adds checks for parent/child changes
* fixes
- split transactions dark mode fix
- add split transactions to context menu
* Update entry.rb
1. New validation split_child_date_matches_parent — prevents saving a split child with a date different from its parent. This is the root-cause fix that
protects all flows at once.
2. Bulk update guard — bulk_update! now strips :date from attributes when processing split children, preventing the validation from raising and silently
skipping the date change instead.
* N+1 fix for split_parent?
* Update entry.rb
Problem: In bulk_update!, when a split child has :date removed from attrs (line 432) and the remaining attrs is empty (e.g., the bulk update only
changed the date), entry.update! {} still ran as a no-op. But lock_saved_attributes! and mark_user_modified! at lines 443-444 executed unconditionally,
incorrectly marking untouched split children as user-modified and opting them out of future syncs.
Fix:
1. Added a changed flag to track whether any actual modification happened
2. Wrapped entry.update! in an if attrs.present? check so no-op updates are skipped
3. Gated lock_saved_attributes! and mark_user_modified! behind if changed, so they only run when the entry was actually modified (either via attribute
update or tag update)
* fixes
1. Indentation in show.html.erb Settings section — The split button block and delete block had extra indentation making them appear nested inside guard
blocks they weren't part of. Fixed to match actual nesting.
2. Skip @split_parents query when grouping is off — The controller now only loads split parent entries when show_split_grouped? is true, saving a query
with joins when the feature is disabled.
* Make categories global
This solves us A LOT of cash flow and budgeting problems.
* Update schema.rb
* Update auto_categorizer.rb
* Update income_statement.rb
* FIX budget sub-categories
* FIX sub-categories and tests
* Add 2 step migration
* feat: Move upcoming transactions in a dedicated tab
* Adjust formatting
* feat: adjust visibility on mobile
* feat: change translation label
* feat: show only upcoming transactions expected in the next 10 days
* feat: show upcoming transactions tab only when option enabled
* feat: render empty partial when there are no recurring transactions
* feat: align icon sizing and spacing between transactions and upcoming sections
* feat: add missing localitazion labels
* fix: move filter on upcoming transactions in controller
* fix: add missing localitazion labels
* feat: add protection indicator to entries and unlock functionality
- Introduced protection indicator component rendering on hover and in detail views.
- Added support to unlock entries, clearing protection flags (`user_modified`, `import_locked`, and locked attributes).
- Updated routes, controllers, and models to enable unlock functionality for trades and transactions.
- Refactored views and localized content to support the new feature.
- Added relevant tests for unlocking functionality and attribute handling.
* feat: improve sync protection and turbo stream updates for entries
- Added tests for turbo stream updates reflecting protection indicators.
- Ensured user-modified entries lock specific attributes to prevent overwrites.
- Updated controllers to mark entries as user-modified and reload for accurate rendering.
- Enhanced protection indicator rendering using turbo frames.
- Applied consistent lock state handling across trades and transactions.
* Address PR review comments for protection indicator
---------
Co-authored-by: luckyPipewrench <luckypipewrench@proton.me>
* Add security remapping support to holdings
- Introduced `provider_security` tracking for holdings with schema updates.
- Implemented security remap/reset workflows in `Holding` model and UI.
- Updated routes, controllers, and tests to support new functionality.
- Enhanced client-side interaction with Stimulus controller for remapping.
# Conflicts:
# app/components/UI/account/activity_feed.html.erb
# db/schema.rb
* Refactor "New transaction" to "New activity" across UI and tests
- Updated localized strings, button labels, and ARIA attributes.
- Improved error handling in holdings' current price display.
- Scoped fallback queries in `provider_import_adapter` to prevent overwrites.
- Added safeguard for offline securities in price fetching logic.
* Update security remapping to merge holdings on collision by deleting duplicates
- Removed error handling for collisions in `remap_security!`.
- Added logic to merge holdings by deleting duplicates on conflicting dates.
- Modified associated test to validate merging behavior.
* Update security remapping to merge holdings on collision by combining qty and amount
- Modified `remap_security!` to merge holdings by summing `qty` and `amount` on conflicting dates.
- Adjusted logic to calculate `price` for merged holdings.
- Updated test to validate new merge behavior.
* Improve DOM handling in Turbo redirect action & enhance holdings merge logic
- Updated Turbo's custom `redirect` action to use the "replace" option for cleaner DOM updates without clearing the cache.
- Enhanced holdings merge logic to calculate weighted average cost basis during security remapping, ensuring more accurate cost_basis updates.
* Track provider_security_id during security updates to support reset workflows
* Fix provider tracking: guard nil ticker lookups and preserve merge attrs
- Guard fallback 1b lookup when security.ticker is blank to avoid matching NULL tickers
- Preserve external_id, provider_security_id, account_provider_id during collision merge
* Fix schema.rb version after merge (includes tax_treatment migration)
* fix: Rename migration to run after schema version
The migration 20260117000001 was skipped in CI because it had a timestamp
earlier than the schema version (2026_01_17_200000). CI loads schema.rb
directly and only runs migrations with versions after the schema version.
Renamed to 20260119000001 so it runs correctly.
* Update schema: remove Coinbase tables, add new fields and indexes
* Update schema: add back `tax_treatment` field with default value "taxable"
* Improve Turbo redirect action: use "replace" to avoid form submission in history
* Lock merged holdings to prevent provider overwrites and fix activity feed template indentation
* Refactor holdings transfer logic: enforce currency checks during collisions and enhance merge handling
---------
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: luckyPipewrench <luckypipewrench@proton.me>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
* feat(settings): split imports and exports
* feat(security): sanitize pagination params to prevent abuse
* fix(settings): fix syntax in settings nav
* feat(settings): internationalize family_exports and imports UI strings
* fix(settings): fix coderabbit review
* fix(settings): fix coderabbit review
* fix(settings): fix coderabbit review
* Change default per_page value from 20 to 10
Signed-off-by: Juan José Mata <jjmata@jjmata.com>
* Add `/family_export` to navigation
* Consistency with old defaults
* Align `safe_per_page` even if not DRY
---------
Signed-off-by: Julien Orain <julien.orain@gmail.com>
Signed-off-by: Juan José Mata <jjmata@jjmata.com>
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: JulienOrain <your-github-email@example.com>
Co-authored-by: Juan José Mata <jjmata@jjmata.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
* Enhance security handling logic:
- Prioritize user's country in sorting securities and country codes.
- Add comprehensive mapping for MIC codes to user-friendly exchange names.
- Revamp combobox to consistently pull from a provider when available.
- Improve handling of custom ticker and exchange input fields.
* Localize securities combobox display and exchange labels.
---------
Co-authored-by: luckyPipewrench <luckypipewrench@proton.me>
- Updated resolution logic to support combobox-based ticker selection and validation.
- Added market price display with validation against entered prices to detect significant mismatches.
- Improved messaging and UI for custom ticker input and market price warnings.
Co-authored-by: luckyPipewrench <luckypipewrench@proton.me>
* Add `investment_activity_label` to trades and enhance activity label handling
- Introduced `investment_activity_label` column to the `trades` table with a migration.
- Backfilled existing `trades` with activity labels based on quantity (`Buy`, `Sell`, or `Other`).
- Replaced `category_id` in trades with `investment_activity_label` for better alignment with transaction labels.
- Updated views and controllers to display and manage activity labels for trades.
- Added localized badge components for displaying and editing labels dynamically.
- Enhanced `PlaidAccount::Investments::TransactionsProcessor` to assign and process activity labels automatically.
- Added investment flows section to reports for tracking contributions and withdrawals.
- Refactored related tests and models for consistency and to ensure proper validation and filtering.
* Improve handling of `investment_activity_label`, trade type, and security selection in trades and transactions
- Refined label assignment logic in `trades_controller` to default to `Buy`/`Sell` based on transaction nature.
- Simplified security selection in `transactions_controller` by resolving via unique IDs or custom tickers.
- Streamlined UI for trade and transaction forms by updating dropdown options and label text.
- Enabled quick-edit badges to open `convert_to_trade` modal when applicable, enhancing flexibility.
- Adjusted tests and views to align with updated workflows and ensure consistent behavior.
* Improve handling of `investment_activity_label`, trade type, and security selection in trades and transactions
- Refined label assignment logic in `trades_controller` to default to `Buy`/`Sell` based on transaction nature.
- Simplified security selection in `transactions_controller` by resolving via unique IDs or custom tickers.
- Streamlined UI for trade and transaction forms by updating dropdown options and label text.
- Enabled quick-edit badges to open `convert_to_trade` modal when applicable, enhancing flexibility.
- Adjusted tests and views to align with updated workflows and ensure consistent behavior.
* Improve handling of `investment_activity_label`, trade type, and security selection in trades and transactions
- Refined label assignment logic in `trades_controller` to default to `Buy`/`Sell` based on transaction nature.
- Simplified security selection in `transactions_controller` by resolving via unique IDs or custom tickers.
- Streamlined UI for trade and transaction forms by updating dropdown options and label text.
- Enabled quick-edit badges to open `convert_to_trade` modal when applicable, enhancing flexibility.
- Adjusted tests and views to align with updated workflows and ensure consistent behavior.
* Add safeguard for `dropdownTarget` existence in quick edit controller
- Prevent errors by ensuring `dropdownTarget` is present before toggling its visibility.
* Fix undefined method 'category' for Trade on mobile view
Trade model uses investment_activity_label, not category. The upstream
merge introduced a call to trade.category which doesn't exist. Use the
activity label badge on mobile instead.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix activity label logic for zero/blank quantity and sell inference
- Return `nil` for blank or zero quantity in `investment_activity_label_for`.
- Correct `is_sell` logic to use the amount’s sign properly in `transactions_controller`.
* Fix i18n key paths in transactions controller for convert_to_trade
- Update flash message translations to use full i18n paths.
- Use `BigDecimal` for quantity and price calculations to improve precision.
---------
Co-authored-by: Josh Waldrep <joshua.waldrep5+github@gmail.com>
Co-authored-by: luckyPipewrench <luckypipewrench@proton.me>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Implement entry protection flags for sync overwrites
- Added `user_modified` and `import_locked` flags to `entries` table to prevent provider sync from overwriting user-edited and imported data.
- Introduced backfill migration to mark existing entries based on conditions.
- Enhanced sync and processing logic to respect protection flags, track skipped entries, and log detailed stats.
- Updated UI to display skipped/protected entries and reasons in sync summaries.
* Localize error details summary text and adjust `sync_account_later` method placement
* Restored schema.rb
---------
Co-authored-by: luckyPipewrench <luckypipewrench@proton.me>
- Removed `exclude_from_cashflow` attribute across models, controllers, and views.
- Updated queries to rely solely on the `excluded` flag for filtering transactions and entries.
- Simplified migration by consolidating `exclude_from_cashflow` functionality into the existing `excluded` toggle.
- Refactored related tests to remove outdated logic and ensured compatibility with the updated implementation.
- Introduced `InvestmentActivityDetector` to mark internal investment activity as excluded from cashflow and assign appropriate labels.
- Added `exclude_from_cashflow` flag to `entries` and `investment_activity_label` to `transactions` with migrations.
- Implemented rake tasks to backfill and clear investment activity labels.
- Updated `PlaidAccount::Investments::TransactionsProcessor` to map Plaid transaction types to labels.
- Included comprehensive test coverage for new functionality.
* Add pending transaction handling and duplicate reconciliation logic
- Implemented logic to exclude pending transactions from budgets and analytics calculations.
- Introduced mechanisms for reconciling pending transactions with posted versions.
- Added duplicate detection with support for merging or dismissing matches.
- Updated transaction search filters to include a `status_filter` for pending/confirmed transactions.
- Introduced UI elements for reviewing and resolving duplicates.
- Enhanced `ProviderSyncSummary` with stats for reconciled and stale pending transactions.
* Refactor translation handling and enhance transaction and sync logic
- Moved hardcoded strings to locale files for improved translation support.
- Refined styling for duplicate transaction indicators and sync summaries.
- Improved logic for excluding stale pending transactions and updating timestamps on batch exclusion.
- Added unique IDs to status filters for better element targeting in UI.
- Optimized database queries to avoid N+1 issues in stale pending calculations.
* Add sync settings and enhance pending transaction handling
- Introduced a new "Sync Settings" section in hosting settings with UI to toggle inclusion of pending transactions.
- Updated handling of pending transactions with improved inference logic for `posted=0` and `transacted_at` in processors.
- Added priority order for pending transaction inclusion: explicit argument > environment variable > runtime configurable setting.
- Refactored settings and controllers to store updated sync preferences.
* Refactor sync settings and pending transaction reconciliation
- Extracted logic for pending transaction reconciliation, stale exclusion, and unmatched tracking into dedicated methods for better maintainability.
- Updated sync settings to infer defaults from multiple provider environment variables (`SIMPLEFIN_INCLUDE_PENDING`, `PLAID_INCLUDE_PENDING`).
- Refined UI and messaging to handle multi-provider configurations in sync settings.
# Conflicts:
# app/models/simplefin_item/importer.rb
* Debounce transaction reconciliation during imports
- Added per-run reconciliation debouncing to prevent repeated scans for the same account during chunked history imports.
- Trimmed size of reconciliation stats to retain recent details only.
- Introduced error tracking for reconciliation steps to improve UI visibility of issues.
* Apply ABS() in pending transaction queries and improve error handling
- Updated pending transaction logic to use ABS() for consistent handling of negative amounts.
- Adjusted amount bounds calculations to ensure accuracy for both positive and negative values.
- Refined exception handling in `merge_duplicate` to log failures and update user alert.
- Replaced `Date.today` with `Date.current` in tests to ensure timezone consistency.
- Minor optimization to avoid COUNT queries by loading limited records directly.
* Improve error handling in duplicate suggestion and dismissal logic
- Added exception handling for `store_duplicate_suggestion` to log failures and prevent crashes during fuzzy/low-confidence matches.
- Enhanced `dismiss_duplicate` action to handle `ActiveRecord::RecordInvalid` and display appropriate user alerts.
---------
Co-authored-by: Josh Waldrep <joshua.waldrep5+github@gmail.com>
* Fix record violation
and add toggle for recurring feature
* Run only once per sync cycle ( 30 sec )
* FIX params passing
* Add collapsible to recurring section
* FIX preferences error catch
* Implement recurring transactions support
* Amount fix
* Hide section when any filter is applied
* Add automatic identify feature
Automatic identification runs after:
- CSV Import completes (TransactionImport, TradeImport, AccountImport, MintImport)
- Plaid sync completes
- SimpleFIN sync completes
- LunchFlow sync completes
- Any new provider that we create.
* Fix linter and tests
* Fix address review
* FIX proper text sizing
* Fix further linter
Use circular distance to handle month-boundary wrapping
* normalize to a circular representation before computing the median
* Better tests validation
* Added some UI info
Fix pattern identification, last recurrent transaction needs to happened within the last 45 days.
* Fix styling
* Revert text subdued look
* Match structure of the other sections
* Styling
* Restore positive amounts styling
* Shorten label for UI styling
---------
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
* Separate exclude and one-time transaction handling
- Split transaction "exclude" and "one-time" toggles into separate controls in transaction detail view
- Updated Transaction::Search to show excluded transactions with grayed-out styling instead of filtering them out
- Modified IncomeStatement calculations to exclude both excluded and one_time transactions from totals
- Added migration to convert existing excluded transactions to also be one_time for backward compatibility
- Updated transaction list view to show asterisk for one_time transactions and gray out excluded ones
- Added controller support for kind parameter in transaction updates
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix linting issues
- Remove trailing whitespace from migration
- Fix ERB formatting throughout templates
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
- Implement caching for transaction totals to enhance performance, using a unique cache key based on family ID and search parameters.
- Adjust default date filter logic to use the user's preferred period when no explicit date filters are provided, reducing the load on the database for large datasets.
Changed transaction form to only display relevant categories based on transaction type (income or expense), improving usability and preventing misclassification. Created a shared transaction type tabs component for consistent navigation between expense, income, and transfer forms, providing a better user experience and reducing code duplication.
Signed-off-by: Zach Gollwitzer <zach@maybe.co>
Co-authored-by: Zach Gollwitzer <zach@maybe.co>
* Domain model sketch
* Scaffold out rules domain
* Migrations
* Remove existing data enrichment for clean slate
* Sketch out business logic and basic tests
* Simplify rule scope building and action executions
* Get generator working again
* Basic implementation + tests
* Remove manual merchant management (rules will replace)
* Revert "Remove manual merchant management (rules will replace)"
This reverts commit 83dcbd9ff0aa7bbee211796b71aa48b71df5e57e.
* Family and Provider merchants model
* Fix brakeman warnings
* Fix notification loader
* Update notification position
* Add Rule action and condition registries
* Rule form with compound conditions and tests
* Split out notification types, add CTA type
* Rules form builder and Stimulus controller
* Clean up rule registry domain
* Clean up rules stimulus controller
* CTA message for rule when user changes transaction category
* Fix tests
* Lint updates
* Centralize notifications in Notifiable concern
* Implement category rule prompts with auto backoff and option to disable
* Fix layout bug caused by merge conflict
* Initialize rule with correct action for category CTA
* Add rule deletions, get rules working
* Complete dynamic rule form, split Stimulus controllers by resource
* Fix failing tests
* Change test password to avoid chromium conflicts
* Update integration tests
* Centralize all test password references
* Add re-apply rule action
* Rule confirm modal
* Run migrations
* Trigger rule notification after inline category updates
* Clean up rule styles
* Basic attribute locking for rules
* Apply attribute locks on user edits
* Log data enrichments, only apply rules to unlocked attributes
* Fix merge errors
* Additional merge conflict fixes
* Form UI improvements, ignore attribute locks on manual rule application
* Batch AI auto-categorization of transactions
* Auto merchant detection, ai enrichment in batches
* Fix Plaid merchant assignments
* Plaid category matching
* Cleanup 1
* Test cleanup
* Remove stale route
* Fix desktop chat UI issues
* Fix mobile nav styling issues
* Add breadcrumbs support across application
Fixes#1896
* Potential fix for tests
* Simplify breadcrumbs implementation
Remove complex breadcrumbs logic from controllers and concern, replacing with a simpler default approach that sets a basic breadcrumb based on the current controller name
* Refactor page header and breadcrumbs rendering
Remove complex breadcrumbs helper method and update layout to use more flexible content_for approach for page headers and breadcrumbs
* Add fallback breadcrumbs rendering to settings layout
Since the very first 0.1.0-alpha.1 release, we've been moving quickly to add new features to the Maybe app. In doing so, some parts of the codebase have become outdated, unnecessary, or overly-complex as a natural result of this feature prioritization.
Now that "core" Maybe is complete, we're moving into a second phase of development where we'll be working hard to improve the accuracy of existing features and build additional features on top of "core". This PR is a quick overhaul of the existing codebase aimed to:
- Establish the brand new and simplified dashboard view (pictured above)
- Establish and move towards the conventions introduced in Cursor rules and project design overview #1788
- Consolidate layouts and improve the performance of layout queries
- Organize the core models of the Maybe domain (i.e. Account::Entry, Account::Transaction, etc.) and break out specific traits of each model into dedicated concerns for better readability
- Remove stale / dead code from codebase
- Remove overly complex code paths in favor of simpler ones
* Add scope to filter transactions from active accounts
* Add test for transfer match candidates with active accounts
* Refactor active account filtering for transactions and entries
* Transfer data model migration
* Transfers and payment modeling and UI improvements
* Fix CI
* Transfer matching flow
* Better UI for transfers
* Auto transfer matching, approve, reject flow
* Mark transfers created from form as confirmed
* Account filtering
* Excluded rejected transfers from calculations
* Calculation tweaks with transfer exclusions
* Clean up migration