Feat: Add default user account and consolidate account actions in menu (#1130)

* feat: Add default account for manual transaction entries (#1061)

Allow users to designate a default account that auto-selects
in the transaction creation form. Also consolidates account list
actions (edit, link/unlink, enable/disable) into a meatball menu.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* - handle context menu width on mobile
- restrict default account to depository types only
- added FR, ES and DE i18n files

* - Add credit card accounts can also be used as default
- Moved logic into controller

* Scope context menu max-width to accounts menu only
- decouples the width constraint from the shared DS::Menu component by introducing an optional max_width param

* fix ci test and address issues raised by coderabbit and codex

* Address CodeRabbit review feedback

- Use .present? for institution_name guards to avoid empty UI artifacts
- Align "Set default" menu visibility with actual preselection eligibility
  (active + unlinked + supports_default?) to prevent drift between UI and model
- Keep disabled star visible when account is already default but now ineligible

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Add eligible_for_transaction_default? predicate to Account model

Consolidates active + unlinked + supports_default? checks into a single
shared predicate used by the controller, view, and user model guard,
preventing a direct PATCH from bypassing UI eligibility rules.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Added "Unset default" option
Added negative test for default account
Removed duplicated logic for account.eligible_for_transaction_default

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Serge L
2026-03-15 16:26:26 -04:00
committed by GitHub
parent 581d3684b2
commit 5aa808e668
17 changed files with 189 additions and 45 deletions

View File

@@ -310,6 +310,14 @@ class Account < ApplicationRecord
accountable_class.long_subtype_label_for(subtype) || accountable_class.display_name
end
def supports_default?
depository? || credit_card?
end
def eligible_for_transaction_default?
supports_default? && active? && !linked?
end
# Determines if this account supports manual trade entry
# Investment accounts always support trades; Crypto only if subtype is "exchange"
def supports_trades?

View File

@@ -24,6 +24,7 @@ class User < ApplicationRecord
belongs_to :family
belongs_to :last_viewed_chat, class_name: "Chat", optional: true
belongs_to :default_account, class_name: "Account", optional: true
has_many :sessions, dependent: :destroy
has_many :chats, dependent: :destroy
has_many :api_keys, dependent: :destroy
@@ -244,6 +245,15 @@ class User < ApplicationRecord
AccountOrder.find(default_account_order) || AccountOrder.default
end
def default_account_for_transactions
return nil unless default_account_id.present?
account = default_account
return nil unless account&.eligible_for_transaction_default? && account.family_id == family_id
account
end
# Dashboard preferences management
def dashboard_section_collapsed?(section_key)
preferences&.dig("collapsed_sections", section_key) == true