* Fix trade drawer header width regression
Wrap the trade header partial in a grow/min-w-0 container inside the custom dialog header row so overview disclosure rows stretch to available width instead of shrinking to content.
Confirmed via git blame that this layout behavior predates PR #1248 and is tied to the custom header flex layout introduced in commit 7ae9077.
* Overlay trade drawer close button to preserve content width
Render the close button absolutely in the custom header instead of as a flex sibling of the full trades header partial. This prevents the button column from shrinking the overview section width and leaving a persistent right-side gutter.
* Fix demo refresh email config lookup
Use indifferent access when reading demo config so the refresh job works whether config keys are strings or symbols. Add a regression test covering symbol-keyed config_for output.
* Remove unnecessary blank line in test file
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
---------
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
* Binance as securities provider
* Disable twelve data crypto results
* Add logo support and new currency pairs
* FIX importer fallback
* Add price clamping and optiimize retrieval
* Review
* Update adding-a-securities-provider.md
* day gap miss fix
* New fixes
* Brandfetch doesn't support crypto. add new CDN
* Update _investment_performance.html.erb
* feat(mobile): render assistant messages as markdown, keep user text plain
Add flutter_markdown dependency and conditionally render chat bubbles:
- User messages use plain Text to avoid formatting markdown characters
- Assistant messages use MarkdownBody with styled headings, bold, italic,
lists and code blocks matching the existing color scheme
- Bump Dart SDK constraint to >=3.3.0 to satisfy flutter_markdown 0.7.2
* fix(mobile): address markdown rendering review comments
- Extract MarkdownStyleSheet into _markdownStyle() helper to avoid
rebuilding TextStyles on every message render
- Replace deprecated imageBuilder with sizedImageBuilder; block http/https
image URIs to prevent unsolicited remote fetches from AI-generated content
- Commit updated pubspec.lock with flutter_markdown 0.7.2 resolved
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix tests
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Juan José Mata <jjmata@jjmata.com>
* test push
* remove test file
* docs: add Yahoo Finance IPv6 troubleshooting note to compose.example.yml
In Podman/IPv6 environments, DNS may resolve fc.yahoo.com to an IPv6
address first. Since IPv6 is often not configured in containers, the
connection hangs instead of falling back to IPv4.
Thanks to @IndicareLeve for identifying and sharing the fix.
* Revise IPv6 connection notes in compose.example.yml
Light edits
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
---------
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: SureBot <sure-bot@we-promise.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
* Update _balance_sheet.html.erb
Update Balance Sheet to work on iPhone Pro Max without scrolling
Signed-off-by: Derek Brown <browndw4@gmail.com>
* Update _group_weight.html.erb
Make the % icon smaller (5 bars not 10) to fit better on smaller format devices
Signed-off-by: Derek Brown <browndw4@gmail.com>
* Update _group_weight.html.erb
Resolve Codex comment
Signed-off-by: Derek Brown <browndw4@gmail.com>
* Update _balance_sheet.html.erb
Increasing width of the weight column
Signed-off-by: Derek Brown <browndw4@gmail.com>
---------
Signed-off-by: Derek Brown <browndw4@gmail.com>
* feat(select): improve merchant dropdown behavior and placement controls
- add configurable menu_placement strategy to DS::Select (auto/down/up) with safe normalization
forward menu_placement through StyledFormBuilder#collection_select
- force Merchant dropdown to open downward in transaction create and editor forms
- fix select option/search text contrast by applying text-primary in DS select menu
- prevent form jump on open by scrolling only inside dropdown content instead of using scrollIntoView
- clamp internal dropdown scroll to valid bounds for stability
- refactor select controller placement logic for readability (placementMode, clamp) without changing behavior
* set menu_placement=auto for metchant selector
* feat: add Binance support (Items, Accounts, Importers, Processor, and Sync)
* refactor: deduplicate 'stablecoins' constant and push stale_rate filter to SQL
---------
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
* 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>
* fix: allow high precision for security prices in trade forms (to solve #1323)
* fix: prevent race conditions on currency selection in money field
* fix: silently ignore currency fetch errors in money field
* Add production-ready Polish localization and reusable locale audit tooling
- add and update Polish locale files across models, views, mailers, and shared translations
- add runtime rails-i18n dependency and Polish locale support in language helper
- add regression coverage for Polish pluralization and locale-aware money formatting
- introduce reusable locale audit script for any locale plus backward-compatible PL wrapper
- add localization audit docs and generated PL readiness/pluralization reports
- resolve one/few/many/other pluralization consistency for Polish locales
* Fix Polish locale review feedback
* Fix locale compatibility regressions
* Polish locale typo pass and wrapper cleanup
* Final language improvements and test isolation for Polish locales
- Improved partial_success wording in SnapTrade with proper noun inflection
- Fixed typos: Pomin → Pomiń in Mercury and LunchFlow items
- Isolated I18n backend state in polish_pluralization_test to prevent test coupling
* Fix code review comments in locale audit scripts
- Use RbConfig.ruby instead of 'ruby' to ensure consistent interpreter
- Remove Symbol from permitted_classes and explicitly allow CLDR plural symbols (one, few, many, other) in YAML loading
* Simplify i18n flow and align locale interpolation keys
* Remove locale audit scripts and localization docs
* feat: update translations for pt-BR
Add new translations and update existing ones
Signed-off-by: Jorge Victor Gamboa <gamboajorge49@gmail.com>
* Add Portuguese translations for admin invitations
Signed-off-by: Jorge Victor Gamboa <gamboajorge49@gmail.com>
* Add Portuguese translations for budget views
Signed-off-by: Jorge Victor Gamboa <gamboajorge49@gmail.com>
* Add unlock and protection messages in pt-BR.yml
Added unlock and protection messages in Portuguese.
Signed-off-by: Jorge Victor Gamboa <gamboajorge49@gmail.com>
* Fix translation key from 'provedores' to 'providers'
Signed-off-by: Jorge Victor Gamboa <gamboajorge49@gmail.com>
* Update config/locales/views/settings/pt-BR.yml
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Jorge Victor Gamboa <gamboajorge49@gmail.com>
* Translate account sharing strings to Portuguese
Signed-off-by: Jorge Victor Gamboa <gamboajorge49@gmail.com>
* Add Portuguese (Brazil) localization for components
Signed-off-by: Jorge Victor Gamboa <gamboajorge49@gmail.com>
* Add Portuguese translations for transaction model errors
Signed-off-by: Jorge Victor Gamboa <gamboajorge49@gmail.com>
* Translate user management strings to Portuguese
Signed-off-by: Jorge Victor Gamboa <gamboajorge49@gmail.com>
* Fix typo in Portuguese translation for 'member'
Signed-off-by: Jorge Victor Gamboa <gamboajorge49@gmail.com>
* Add appearance settings localization in pt-BR
Added localization for appearance settings and dashboard layout options in Portuguese.
Signed-off-by: Jorge Victor Gamboa <gamboajorge49@gmail.com>
* Remove theme options from preferences in pt-BR localization, these keys were moved to appearances.show.
* Adds translations for financial reports and investment performance in Brazilian Portuguese.
* fix: Corrects Portuguese translations for 'vender' (to sell), 'neste período' (in this period), and adjusts the formatting of 'saques' (withdrawals) in investment performance.
* Fix: Corrects the indentation of the print section in the pt-BR translation file.
* Fix: Corrects the translation of 'this period' to 'este período' in the pt-BR localization file.
---------
Signed-off-by: Jorge Victor Gamboa <gamboajorge49@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Fixed crypto and loan add menus
* Changed unspecified crypto account type to none for consistency
* Added default add message for loan subtype
* Made the short form of non-mortgage loans in loans.rb match the long form
* Edited the crypto tooltip to be country generic
* Update config/locales/views/loans/en.yml
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Geoffrey <79559478+CYBRXT@users.noreply.github.com>
* Update app/views/loans/_form.html.erb
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Geoffrey <79559478+CYBRXT@users.noreply.github.com>
* Following Dosu's comment on my issue for consistency
---------
Signed-off-by: Geoffrey <79559478+CYBRXT@users.noreply.github.com>
Co-authored-by: Geoffrey <geoffrey@github.worker>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.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>
* Update ruby-lsp-rails 0.4.6 → 0.4.8 and ruby-lsp 0.24.1 → 0.26.9
Relaxes the strict ruby-lsp dependency from (>= 0.24.0, < 0.25.0) to
(>= 0.26.0, < 0.27.0). Also drops the no-longer-needed sorbet-runtime
transitive dependency.
https://claude.ai/code/session_01JeygD1gvjJ4eh9SmpW7xGf
* Broad-ignore Pipelock check for now
---------
Co-authored-by: Claude <noreply@anthropic.com>
* collect transaction stats after sync in EnableBanking provider
* update logic to follow the pattern used by other bank providers
* fix n+1 issue
* fix N+1 issues
* feat: improve QIF import date format selection
- Added a reusable date format auto-detection method.
- Show a live preview of the first parsed date that updates client-side
as the user changes the dropdown selection, via a new
qif-date-format Stimulus controller.
- Show an error alert and disable the submit button when no supported
date format can parse the file's dates.
* A few polishing fixes:
- Missing return on redirects
Stale REASONABLE_DATE_RANGE constant.
- Replaced the frozen constant with a class method
Bare inline rescue — Replaced Date.strptime(s, fmt) rescue nil with an explicit begin/rescue catching.
- save!(validate: false) in controller — Changed to update_column(:column_mappings, ...) in qif_category_selections_controller.rb:22, matching the pattern used in detect_and_set_qif_date_format!.
- Unescaped JSON in HTML attribute — Replaced the raw <div> with tag.div ... do block in show.html.erb:16, letting Rails properly escape the data attribute value.
* fix: address review feedback for QIF date format feature
- Add missing `return` after redirect for non-QIF imports
- Pass date_format to parse_opening_balance in will_adjust_opening_anchor?
- Return empty array when no usable date sample exists for format preview
- Add sr-only label to date format select for accessibility
- Consolidate duplicate try_parse_date/parse_qif_date into single method
- Remove misleading ambiguity scoring comment from detect_date_format
- Skip redundant sync_mappings when date format already triggered a sync
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Use %{product_name} interpolation in locale strings
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Wait for the chat to fully load after click before triggering a page
refresh, ensuring last_viewed_chat is persisted server-side.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Make category selection menus opaque for excluded transactions
* Allow keyboard navigation in category selection menu
* Fix category transparency on mobile
* Make checkbox opaque
* Remove text-secondary from amount container
* Submit form directly
* Handle aria labels