Commit Graph

14 Commits

Author SHA1 Message Date
Oscar
c6a240a183 feat(redbark): add australian bank sync (redbark) (#2794)
* add redbark provider integration

- per family api key provider, built like the lunchflow integration
- syncs accounts, balances and transactions from api.redbark.com
- account setup flow, settings panel, locales and routes
- tests and fixtures

* harden redbark integration based on prior provider pr feedback

- use DebugLogEntry.capture for sync/import/unlink failures
- retry 429s and 5xxs with backoff, raise on page cap instead of truncating
- keep raw response bodies out of logs and errors
- not null constraints on account columns, migration base 7.2
- persist ignored flag for skipped accounts so they stop nagging setup
- validate api key on every save, re-arm status on key rotation
- destroy aborts if unlink fails, atomic account create and link
- require_admin on mutating actions, see_other on error redirects
- single grouped query for item account counts
- i18n default connection name, blank password field value
- controller and provider tests

* fix issues found in second review sweep

- add missing syncable scope, without it every family sync raises
- kick off a sync on connection create and on key rotation
- setup dialog fetches accounts inline for fresh connections and shows api errors
- skip balance write when no balance has been fetched yet, never anchor a false zero
- exclude stale and non banking accounts from the batched balances call, per account fallback if the batch is rejected
- detect the server row ceiling and empty pages instead of silently truncating history
- user sync start date only governs the initial backfill, incremental after that
- fetch connections before the per account loop so auth errors propagate once
- drop untemplated index/show/new/edit routes and dead preload/link_accounts actions
- stable dom id on the settings panel so repeat turbo replaces keep working

* skip brokerage connections, found in live testing

- the transactions endpoint 400s for brokerage connections, they belong to /v1/trades
- only import accounts from banking and documents connections
- guard transaction fetches for any legacy linked non banking account

* address review feedback

- treat the truncation header as a pagination signal: split the date window and refetch instead of failing the account
- prune stale pending rows from the snapshot so settled pendings cant come back as duplicates
- block linking a sure account that already has another provider feed
- count setup failures separately from skips and surface an error instead of "all skipped"
- add not nulls on redbark_items name and api key
- enqueue the destroy job after the flag commits, not inside the transaction
- swap bg-gray-400 for bg-surface-inset, drop amounts from info logs, remove i18n default fallbacks
- tests for window splitting, pending pruning and encrypted payload round trip

* fix issues from convention review

- benign skips (unlinked account, blank id, unparseable rows) no longer count as failures, tracked separately so a clean batch reports success
- currency parsing goes through extract_currency so hash shaped payloads resolve instead of falling to the default
- merchant ids use truncated sha256 instead of md5
- debug log entries for import failures and account sync scheduling failures

* bound the raw transactions snapshot to the fetch window

- trim raw_transactions_payload to the current fetch window on merge, same as brex
- keep rows without a parseable date, drop settled pendings as before
- surface skipped rows in the aggregate debug log entry with imported/skipped counts
2026-07-26 07:40:25 +02:00
Jestin Palamuttam
5803023fa7 feat(provider): add native Questrade brokerage provider integration (#2534)
* Add native Questrade brokerage provider integration

Adds a per-family Questrade provider so users can sync their Questrade
investment accounts (TFSA, FHSA, RRSP, margin, etc.) directly via
Questrade's free personal API, with no paid aggregator.

- OAuth2 refresh-token flow with single-use token rotation, persisted
  under a row lock. Tokens self-renew on each sync; the connected panel
  lets users paste a fresh token if a connection goes stale (no need to
  disconnect and re-link).
- Imports accounts, balances, positions and activities; multi-currency
  holdings with per-currency cash holdings; Norbert's Gambit journals.
- New-account and link-existing-account flows, settings card with
  desktop-only setup steps, and connect/update/disconnect.
- Restricted to Investment account types. Registered in the provider
  connection-status registry with a syncable scope so it participates in
  nightly family sync.

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

* fix: linting error

* fix: refresh token encrypted

The OAuth token exchange passed the single-use refresh token as a GET
query parameter, so it could leak into URL-based logs (Sentry
breadcrumbs, APM spans, debug output). Switch to POST with a
form-encoded body (RFC 6749 3.2) so the credential stays out of URLs.
Verified Questrade's token endpoint accepts POST (returns 400 for a bad
token, not 405). Adds a test asserting the token travels in the body.

* Address PR review: authz, data integrity, retries, logging

Batch of fixes from the automated PR review:

- Require admin for all mutating/linking Questrade actions, and gate
  existing-account linking through accessible_accounts + write permission
  (was only Current.family scoped).
- Clear requires_update when a fresh token is accepted; use a real 302
  redirect (not 422) on full-page failures.
- Require refresh_token on all saves (not just create) unless the item is
  scheduled for deletion.
- Migrations target Rails 7.2; questrade_items state columns are NOT NULL.
- Background activity dedup keys on Questrade fields (matches the importer)
  so multiple activities no longer collapse to one.
- Persist the normalized account payload; date-scope synthetic cash
  holdings so daily history is not overwritten.
- Retry 429/5xx via a RetryableResponseError instead of hard-failing.
- Route provider error bodies to DebugLogEntry instead of Rails.logger /
  exception messages, so payloads do not leak into application logs.

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

* Address PR review: atomic linking, sync health, retry loop, USD cash

- Wrap account creation + provider linking (+ sync_start_date) in a
  transaction in both link paths so a link failure rolls back the orphan
  account.
- Surface per-account process/schedule failures in the item sync health
  instead of always reporting healthy.
- Always stamp last_activities_sync once the background fetch completes,
  so legitimately empty accounts stop being re-queued every sync.
- Treat only the account-currency (CAD) balance as primary cash; other
  currencies (e.g. USD) now surface as separate cash holdings instead of
  being hidden as primary.

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

* Address PR review: serialize token exchange, real processor tests

- Single-use token race: the SDK now wraps every token exchange (initial
  and 401 re-auth) in a model-supplied lock that reloads and spends the
  freshest persisted token (provided.rb#synchronize_exchange). Two
  concurrent syncs/jobs can no longer double-spend the same refresh token.
  Adds a test asserting the exchange runs inside the lock with the fresh
  token.
- Replace the all-skipped QuestradeAccount processor test stubs with real
  fixture-backed tests covering balance anchoring, holdings import, and
  Buy-trade import (plus blank-symbol / blank-type guards).

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

* Fix indentation of spliced Questrade schema blocks

The manually added questrade_accounts/questrade_items create_table blocks
sat at column 0 instead of the file 2-space indent, so rubocop flagged
them as inconsistent. Re-indent to match the rest of the schema.

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

* Include currency and type in the Questrade activity merge key

Two activities that differ only by currency or type could collapse to a
single row in merge_activities. Add both fields to activity_key in the
importer and the background fetch job so multi-currency imports dedup
correctly.

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

* Address review: infer account currency, Encryptable, safer flag clear

From @jjmata's review:

- Currency: QuestradeAccount#upsert_from_questrade! no longer hardcodes CAD
  for every account. upsert_balances! now infers the home currency from the
  per-currency balances (the currency holding the cash wins, ties broken by
  total equity, default CAD) so USD-denominated accounts are labelled USD and
  match the right combinedBalances anchor. Adds tests for USD and CAD cases.
- QuestradeItem now includes the shared Encryptable concern instead of
  reimplementing encryption_ready? inline.
- QuestradeActivitiesFetchJob#clear_pending_flag is now best-effort so it can
  never mask (and swallow) the original error in perform's rescue.

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

* Fix review issues: safe_return_to_path, DebugLogEntry, financial reset, turbo_prefetch, N+1 counts

- Add safe_return_to_path to QuestradeItemsController (blocks //evil.com
  protocol-relative open redirect; same 3-check guard as PR #2591 Wise provider)
- Pass return_to through select_accounts and complete_account_setup so
  users land back on the account they were linking from
- Replace Rails.logger.error/warn with DebugLogEntry.capture in controller
  and unlinking concern (surface errors in the app debug log UI)
- Add questrade_items to Family::FinancialDataReset::PROVIDER_ITEM_ASSOCIATIONS
  so Reset Financial Data actually removes Questrade data
- Add when "questrade" case to load_provider_items in providers_controller
  so the settings panel lazy-load refresh works
- Fix turbo_prefetch: false on non-lunchflow provider links in
  _method_selector.html.erb and select_provider.html.erb (prevents
  prefetch-cache blank-modal bug for all generic sync providers)
- Preload questrade_accounts: :account_provider and build
  @questrade_account_counts_map in AccountsController; read from map in
  partial instead of calling .count on associations (eliminates N+1)
- Localize default connection name via I18n.t(questrade_items.default_name)
- Add default_name key to questrade_items locale

Patterns and bugs surfaced during review of PR #2591 (Wise provider).

* Cross-apply Wise learnings to Questrade provider

Encryption (matched convention from Wise/jjmata review):
- Add deterministic: true to QuestradeItem#refresh_token
- Add encrypts :raw_payload + :raw_institution_payload to QuestradeItem
- Add Encryptable + encrypts :raw_payload, :raw_holdings_payload,
  :raw_activities_payload, :raw_balances_payload to QuestradeAccount
  (brokerage-specific columns; matches MercuryAccount/UpAccount pattern)

Bug fix:
- Add missing RetryableResponseError class to Provider::Questrade
  (used in with_retries rescue clause but never defined — would cause
  NameError on any rate-limited or 5xx response)

Logging:
- Replace Rails.logger.error with DebugLogEntry.capture in
  QuestradeItem#import_latest_questrade_data, #process_accounts,
  and #schedule_account_syncs to surface errors in the support UI

Consistency:
- Extract update_sync_status(sync, key, **i18n_options) helper in
  QuestradeItem::Syncer, replacing 5 inline sync.update! guard calls
- Use blank? instead of ||= for default name fallback in create action

Tests:
- Add QuestradeItemsControllerTest (18 tests: CRUD, sync, account
  linking/setup flows, admin guard enforcement)
- Add questrade fixtures: questrade_items.yml, questrade_accounts.yml
- Add retry/backoff tests to Provider::QuestradeTest (network error,
  429, 5xx — all verify MAX_RETRIES exhaustion raises Error)

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

---------

Signed-off-by: Jestin Palamuttam <34907800+jestinjoshi@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 09:00:49 +02:00
Jake
dc2a565b6a feat(up): add Up Bank (AU) provider integration (#2391)
* feat(up): add Up Bank (AU) provider integration

Adds Up Bank as a per-family, token-based bank sync provider, modelled on
the existing Akahu integration. Up uses a JSON:API REST API with a personal
access token (Bearer), cursor pagination via links.next, and returns both
HELD (pending) and SETTLED transactions from one endpoint.

New:
- Provider::Up client (JSON:API unwrap, links.next pagination, retries,
  typed errors, /util/ping) + Provider::UpAdapter (Factory-registered,
  Depository + Loan).
- UpItem / UpAccount models with Provided, Unlinking, Syncer,
  SyncCompleteEvent, Importer, Processor, Transactions::Processor, and
  UpEntry::Processor (amount sign flip, HELD->pending, foreignAmount FX,
  merchant from description, stale-pending pruning).
- Family::UpConnectable, UpItemsController, routes, settings panel + connect
  flow views, accounts index wiring, initializer, en locale, and model tests.

Core wiring:
- "up" added to Transaction::PENDING_PROVIDERS, the three pending-match SQL
  blocks in Account::ProviderImportAdapter, Provider::Metadata::REGISTRY,
  ProviderMerchant/DataEnrichment source enums, ProviderConnectionStatus,
  settings provider panels, and financial data reset.

Migration create_up_items_and_accounts must be run before use. No external
API endpoints added (no OpenAPI changes).

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

* fix(up): dump up tables to schema and make since filter TZ-safe

The feature commit added the up_items/up_accounts migration but never
re-dumped db/schema.rb, leaving the schema version and tables stale.
Add the two table definitions and foreign keys and bump the schema
version so a fresh DB load matches the migration.

Also format a bare Date `since` as UTC midnight instead of the server's
local zone, so `filter[since]` is deterministic regardless of where the
app runs (previously shifted by the local UTC offset).

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

* fix(up): address code review feedback

Behavior/correctness:
- Persist skipped accounts via a new up_accounts.ignored flag and a
  needs_setup scope, so skipped accounts stop resurfacing as "needs
  setup" on every sync. Linking clears the flag.
- destroy now checks unlink_all! per-account results and aborts deletion
  (alert) if any unlink failed, instead of swallowing failures.
- render_provider_panel_error redirect uses :see_other (was an invalid
  4xx redirect status).
- Up provider adapter falls back to item institution name/url when
  institution_metadata is absent (early return previously blocked it).

Resilience/security:
- fetch_all_resources guards against an API repeating the same
  links.next cursor (Set#add?), preventing infinite pagination.
- HTTP client validates absolute URLs (from links.next) against Up's
  HTTPS host before sending the bearer token, preventing credential
  leakage to untrusted hosts.

Diagnostics:
- Route provider sync/import failures through DebugLogEntry.capture
  (controller, UpItem, syncer, unlinking) with family/account context.
  Low-level HTTP client and currency-normalization warnings keep
  Rails.logger to match existing provider conventions.

Data integrity:
- up_accounts.name and currency are NOT NULL (align with model presence
  validations); account_id stays nullable (allow_nil uniqueness).

Forms:
- select_existing_account radio is required; controller guards a blank/
  unknown up_account_id with a friendly alert instead of RecordNotFound.

Tests:
- Add UpAccount needs_setup scope test, pagination loop guard test,
  untrusted-host rejection test; tighten filter[since] assertion to the
  exact UTC timestamp.

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

* fix(up): address second-round review feedback

- Capture sync/import failures via DebugLogEntry so swallowed errors in
  account/transaction fetching and transaction processing surface in
  /settings/debug instead of only Rails.logger.
- Gate UP_DEBUG_RAW raw payload dump to local envs to avoid leaking PII
  (merchant names, amounts, account IDs) in managed/production logs.
- Collapse linked/unlinked/total account counts into one memoized query
  instead of 3 separate COUNTs per rendered item.
- Rename "Set Up Up Accounts" locale title to "Link Up Accounts".

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

* docs(up): add method docstrings and align failed_result keys

Add docstrings to all Up provider source files (controller, models,
providers, concerns) to satisfy the 80% docstring coverage threshold.

Third-round review: failed_result now mirrors import's result shape
(accounts_updated/created/failed, transactions_imported/failed) instead
of the stale accounts_imported key, so failure results stay consistent.

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

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 20:33:09 +02:00
Brad
1b8b21760b feat(provider): Akahu integration (#1921)
* First pass of Akahu

* fix up sync all

* conflicts

* fix db migration issue? - fix auto selection of akahu account type

* Address Akahu PR feedback

* Complete provider metadata

* Fix PR 1921 CI tests

* PR feedback

* PR feedback

* post merge

---------

Co-authored-by: failing <failing@users.noreply.github.com>
Co-authored-by: Juan José Mata <jjmata@jjmata.com>
Co-authored-by: sure-admin <sure-admin@splashblot.com>
2026-06-02 21:44:57 +02:00
ghost
95f6451b39 feat(sync): add Brex provider connections (#1752)
* feat(sync): add Brex provider schema

Adds Brex item and account tables with per-family credentials, scoped upstream account uniqueness, encrypted token storage, and sanitized provider payload columns.

* feat(sync): add Brex provider core

Adds Brex item/account models, provider client and adapter support, family connection helpers, and provider enum registration for read-only Brex cash and card data.

* feat(sync): add Brex import pipeline

Adds Brex account discovery, linked-account sync, cash/card balance processors, transaction import, sanitized metadata handling, and idempotent provider entry processing.

* feat(sync): add Brex connection flows

Adds Mercury-style Brex connection management, explicit item-scoped account selection and linking, settings provider UI, account index visibility, localized copy, and per-item cache handling.

* test(sync): cover Brex provider workflows

Adds targeted coverage for Brex provider requests, adapter config, item/account guards, importer behavior, entry processing, and Mercury-style controller flows.

* fix(sync): align Brex API edge cases

Tightens Brex account fetching against the official card-account response shape, sends transaction start filters as RFC3339 date-times, and keeps provider error bodies out of user-facing messages while expanding provider client guard coverage.

* fix(sync): harden Brex provider integration

Restrict Brex API base URLs to official hosts, tighten account-selection UI behavior, and add tests for invalid credentials, cache scoping, and provider setup edge cases.

* test(sync): avoid Brex secret-shaped fixtures

* refactor(sync): extract Brex account flows

* fix(sync): address Brex provider review feedback

* fix(sync): address Brex review follow-ups

Move remaining Brex review cleanup into focused model behavior, tighten link/setup edge cases, localize summaries, and add regression coverage from CodeRabbit feedback.

Also records the security-review pass as no-findings after diff-scoped inspection and Brakeman validation.

* refactor(sync): split Brex account flow controllers

Route Brex account selection and setup actions through small namespaced controllers while keeping existing URLs and helpers stable.

Business flow remains in BrexItem::AccountFlow; the main Brex item controller now only handles connection CRUD, provider-panel rendering, destroy, and sync.

* fix(sync): address Brex CodeRabbit review

* fix(sync): address Brex follow-up review

* fix(sync): address Brex review follow-ups

* fix(sync): address Brex sync review findings

* fix(sync): polish Brex review copy and errors

* fix(sync): register Brex provider health

* fix(sync): polish Brex bank sync presentation

* fix(sync): address Brex review follow-ups

* fix(sync): tighten Brex setup params

* test(api): stabilize usage rate-limit window

* fix(sync): polish Brex setup flow nits

* fix(sync): harden Brex setup params

* fix(sync): finalize Brex review cleanup

---------

Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
2026-05-13 18:13:48 +02:00
Gian-Reto Tarnutzer
ce5d7dd736 Add Interactive Brokers Provider (#1722)
* Display multi-currency holdings correctly

* Implement IBKR provider

* Fix: Use historical exchange rate for historical prices

* Add brokerage exchange rate for trades

* Sync historical balances from IBKR

* Add logos in activity history

* Fix privacy mode blur in account view

* Improve IBKR XML Flex report parser errors
2026-05-12 23:45:19 +02:00
Sophtron Rocky
b32e9dbc45 Add Sophtron Provider (#596)
* Add Sophtron Provider

* fix syncer test issue

* fix schema  wrong merge

* sync #588

* sync code for #588

* fixed a view issue

* modified by comment

* modified

* modifed

* modified

* modified

* fixed a schema issue

* use global subtypes

* add some locales

* fix a safe_return_to_path

* fix exposing raw exception messages issue

* fix a merged issue

* update schema.rb

* fix a schema issue

* fix some issue

* Update bank sync controller to reflect beta status

Signed-off-by: Juan José Mata <jjmata@jjmata.com>

* Rename settings section title to 'Sophtron (alpha)'

Signed-off-by: Juan José Mata <jjmata@jjmata.com>

* Consistency in alpha/beta for Sophtron

* Good PR suggestions from CodeRabbit

---------

Signed-off-by: soky srm <sokysrm@gmail.com>
Signed-off-by: Sophtron Rocky <rocky@sophtron.com>
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Signed-off-by: Juan José Mata <jjmata@jjmata.com>
Co-authored-by: soky srm <sokysrm@gmail.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: Juan José Mata <jjmata@jjmata.com>
2026-04-19 11:16:04 +02:00
David Gil
ba442d5f26 Implement Indexa Capital provider with real API integration (#933)
* Add Indexa Capital provider scaffold

Generate Indexa Capital provider scaffolding and align credential fields with the API authentication requirements.

* Fix PR 926 lint and schema CI failures

* Implement Indexa Capital provider with real API integration

- Rewrite all broken view templates (were meta-ERB from code generator)
- Create missing select_accounts.html.erb template
- Implement real API calls: list_accounts via /users/me, get_holdings
  via /accounts/{number}/fiscal-results, get_account_balance via
  /accounts/{number}/performance
- Add API token auth support (stored token > env token > credentials)
- Add api_token column with encryption support
- Redesign settings panel: API token prominent, credentials collapsible
- Fix account balances display using performance endpoint portfolios
- Fix accounts index empty-state guard missing indexa_capital_items
- Simplify activities fetch job (no activities API endpoint exists)
- Fix i18n interpolation (%%{ -> %{) throughout locale file

* Add tests for Indexa Capital provider integration

- IndexaCapitalItemTest: validations, credentials, scopes, sync status
- IndexaCapitalAccountTest: upsert, holdings, account provider linking
- Provider::IndexaCapitalTest: auth modes, API stubs, error handling
- IndexaCapitalItemsControllerTest: CRUD, setup, linking, authorization
- Fixtures for items (token + credentials) and accounts (mutual + pension)

52 tests, 98 assertions, 0 failures

* Address code review feedback from PR #933

- Fix zero balance bug: use `nil?` instead of `present?` so 0 is stored
- Fix has_indexa_capital_credentials? to check api_token (was ignored)
- Fix build_provider to delegate to Provided concern (was ignoring token)
- Fix IndexaCapital section outside encryption_error guard in settings
- Add account_number sanitization to prevent path traversal in API URLs
- Replace all skipped processor tests with real working tests
- Add zero-balance and path-traversal test coverage

61 tests, 107 assertions, 0 failures

* Address code review round 2: credentials validation, RuboCop, test quality

- Fix RuboCop SpaceInsideArrayLiteralBrackets in credentials check
- Chain where.not calls so all three username/document/password must be present
- Require all three credentials (||) instead of any one (&&) in validate_configuration!
- Move attr_reader to private to avoid exposing credentials publicly
- Parse dates with Date.parse in extract_balance for robustness
- Remove stale TODO and Crypto from supported_account_types
- Order build_provider query deterministically by created_at
- Replace no-op holdings assertion with meaningful assert_difference

* Address code review round 3: JSON parse safety and test precision

- Rescue JSON::ParserError on 2xx responses for clearer error messages
- Fix weak balance assertion: set balance to 0 before processing, assert
  expected value (27093.01 = sum of holdings amounts)

* Include Indexa Capital in automatic family sync

Add indexa_capital_items to Family::Syncer#child_syncables so balances
and holdings refresh on daily auto-sync and login sync, not only on
manual sync button clicks.

---------

Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: Juan José Mata <jjmata@jjmata.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
2026-02-08 18:19:37 +01:00
soky srm
179552657c Mercury integration (#723)
* Initial mercury impl

* FIX both mercury and generator class

* Finish mercury integration and provider generator

* Fix schema

* Fix linter and tags

* Update routes.rb

* Avoid schema drift

---------

Signed-off-by: soky srm <sokysrm@gmail.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
2026-01-22 20:37:07 +01:00
Ethan
3b4ab735b0 Add (beta) CoinStats Crypto Wallet Integration with Balance and Transaction Syncing (#512)
* Feat(CoinStats): Scaffold implementation, not yet functional

* Feat(CoinStats): Implement crypto wallet balance and transactions

* Feat(CoinStats): Add tests, Minor improvements

* Feat(CoinStats): Utilize bulk fetch API endpoints

* Feat(CoinStats): Migrate strings to i8n

* Feat(CoinStats): Fix error handling in wallet link modal

* Feat(CoinStats): Implement hourly provider sync job

* Feat(CoinStats): Generate docstrings

* Fix(CoinStats): Validate API Key on provider update

* Fix(Providers): Safely handle race condition in merchance creation

* Fix(CoinStats): Don't catch system signals in account processor

* Fix(CoinStats): Preload before iterating accounts

* Fix(CoinStats): Add no opener / referrer to API dashboard link

* Fix(CoinStats): Use strict matching for symbols

* Fix(CoinStats): Remove dead code in transactions importer

* Fix(CoinStats): Avoid transaction fallback ID collisions

* Fix(CoinStats): Improve Blockchains fetch error handling

* Fix(CoinStats): Enforce NOT NULL constraint for API Key schema

* Fix(CoinStats): Migrate sync status strings to i8n

* Fix(CoinStats): Use class name rather than hardcoded string

* Fix(CoinStats): Use account currency rather than hardcoded USD

* Fix(CoinStats): Migrate from standalone to Provider class

* Fix(CoinStats): Fix test failures due to string changes
2026-01-07 15:59:04 +01:00
soky srm
4a29d030af Initial enable banking implementation (#382)
* Initial enable banking implementation

* Handle multiple connections

* Amount fixes

* Account type mapping

* Add option to skip accounts

* Update schema.rb

* Transaction fixes

* Provider fixes

* FIX account identifier

* FIX support unlinking

* UI style fixes

* FIX safe redirect and brakeman issue

* FIX

- pagination max fix
- wrap crud in transaction logic

* FIX api uid access

- The Enable Banking API expects the UUID (uid from the API response) to fetch balances/transactions, not the identification_hash

* FIX add new connection

* FIX erb code

* Alert/notice box overflow protection

* Give alert/notification boxes room to grow (3 lines max)

* Add "Enable Banking (beta)" to `/settings/bank_sync`

* Make Enable Banking section collapsible like all others

* Add callback hint to error message

---------

Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
2025-11-29 13:31:08 +01:00
soky srm
5eadfaad98 Lunchflow integration (#259)
* First pass lunch flow

* Fixes

- Fix apikey not being saved properly due to provider no reload support
- Fix proper messages if we try to link existing accounts.

* Fix better error handling

* Filter existing transactions and skip duplicates

* FIX messaging

* Branding :)

* Fix XSS and linter

* FIX provider concern

- also fix code duplication

* FIX md5 digest

* Updated determine_sync_start_date to be account-aware

* Review fixes

* Broaden error catch to not crash UI

* Fix buttons styling

* FIX process account error handling

* FIX account cap and url parsing

* Lunch Flow brand

* Found orphan i18n strings

* Remove per conversation with @sokie

---------

Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
2025-10-30 14:07:16 +01:00
Himmelschmidt
4cd737b5d9 Fix SimpleFin investment holdings and comprehensive integration improvements (#104)
* Remove skipped account functionality from SimpleFin

- Remove "Skip - don't add" option from account setup
- Simplify account setup flow to require all accounts be assigned types
- Update controller logic to handle all accounts without skipping
- Redirect to accounts page instead of SimpleFin items page
- Add I18N message support with t(".success")

* Simplify SimpleFin sync logic by removing skipped accounts

- Remove skipped account filtering from syncer
- All unlinked accounts now block sync until setup is complete
- Remove skipped account UI elements from setup view
- Streamline sync flow without complex skipped/non-skipped logic

* Fix cash balance calculation for SimpleFin investment accounts

- Update SimplefinAccount::Processor to recalculate balances during sync
- Properly calculate cash_balance for investment accounts using BalanceCalculator
- Handle negative balances for credit cards and loans correctly
- Ensure account balance and cash balance are updated from latest SimpleFin data

* Add I18N translations and edit view for SimpleFin

- Add comprehensive English translations for SimpleFin UI
- Create edit view for SimpleFin re-authentication
- Support status messages, errors, and user feedback
- Match translation structure with Plaid integration

* Add specialized SimpleFin data processors

- Add investment processors for transactions, holdings, and balance calculation
- Add liability processors for credit cards and loans
- Add transaction processor for standard account transactions
- Add account importer for SimpleFin account data
- Organize processors by account type for maintainable architecture

* Add loading button controller for SimpleFin forms

- Add Stimulus controller to show loading state during form submission
- Disable button and show loading text to prevent double submissions
- Improve user experience during SimpleFin account setup

* Add SimpleFin edit and update routes

- Add edit and update actions to SimpleFin items routes
- Enable re-authentication flow for expired SimpleFin connections
- Match route structure with Plaid items for consistency

* Add institution metadata fields to SimpleFin items

- Add institution_id, institution_name, institution_domain fields
- Add institution_url, institution_color for UI customization
- Add raw_institution_payload for complete institution data storage
- Enable better institution organization and display

* Enhance SimpleFin item with institution support and metadata

- Add institution summary and connected institutions methods
- Store and retrieve institution metadata from SimpleFin API
- Add institution-aware import functionality
- Support multiple institutions per SimpleFin connection

* Fix account creation and Plaid provider issues

- Fix cash balance calculation in Account.create_from_simplefin_account
- Add nil check for plaid_provider in remove_plaid_item method
- Ensure proper balance handling for investment accounts during creation

* Improve sync parent relationship handling

- Add parent sync assignment for existing syncs when parent_sync is provided
- Ensure sync hierarchy is maintained when expanding sync windows
- Fix sync relationship consistency in nested sync operations

* Update SimpleFin item view with enhanced UI

- Improve SimpleFin connection display and status information
- Add better visual styling and user feedback
- Match UI consistency with Plaid item views

* Update database schema with institution fields

- Add institution metadata fields to simplefin_items table
- Support institution tracking and organization features

* Update SimpleFin tests for new functionality

- Update controller tests for edit/update actions and removed skip functionality
- Update model tests for institution metadata and enhanced features
- Ensure test coverage for SimpleFin improvements

* Add migration to remove old institution fields

* Fix linting issues

* Apply suggestion from @coderabbitai[bot]

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Himmelschmidt <46351743+Himmelschmidt@users.noreply.github.com>

* Fix 2 failing tests

* Wrap SimpleFin account transfer in database transaction

* Make loading button controller more reusable

- Add loadingText Stimulus value for configurable loading text
- Remove unused originalText variable
- Update view to pass loading text via data attribute

* Remove unused SimplefinAccount::Importer class

This class was added in the PR but is never called anywhere in the codebase.
The actual SimpleFin account processing is handled by SimplefinAccount::Processor
and its specialized sub-processors.

* Fix SimpleFin account transfer bug during token updates

- Call import_latest_simplefin_data before account transfer to ensure
  new SimpleFin accounts exist with account_id populated
- Prevents silent failure where accounts become orphaned when
  refreshing expired SimpleFin tokens

* Fix SimpleFin error handling to render correct template and use i18n

- Update render_error method to accept context parameter for template selection
- Fix update action to render :edit template instead of :new on errors
- Replace hardcoded error messages with localized strings using t() calls
- Add comprehensive error message keys to SimpleFin locale file

* Improve loading button accessibility and HTML semantics

- Add aria-disabled and aria-busy attributes for screen readers
- Use semantic span elements instead of divs for button content
- Add aria-hidden to decorative spinner element

* Fix SimpleFin SSL verification to use OpenSSL constant

* Remove HTTParty streaming to prevent empty response body and PII logging

* Use BigDecimal zero for consistent numeric types in balance calculator

* Add investment account guard to holdings processor

* Remove duplicate balance normalization from SimpleFin loan processor

* Fix critical account deletion bug in SimpleFin token update

* Fix linting issues in SimpleFin controller tests

* Replace hardcoded colors with design system tokens in SimpleFin views

* Gate investment processors to Investment accounts only

Prevents investment processors from running on non-Investment account types,
matching the pattern used by liability processors.

* Localize hardcoded strings in SimpleFin edit form

* Adding the error message to a hover state.

* Use only 1 month for sync_start_date, new account restriction?

* Harden investment cash_balance calculation with error handling

- Add try/catch around SimplefinAccount::Investments::BalanceCalculator
- Fallback to zero on calculation errors or nil results
- Log warning with error details for debugging
- Prevents nil cash_balance that could cause downstream issues

* Fix SimpleFin institution fields migration and add DB constraints

- Remove destructive migration that dropped existing institution fields
- Add only new fields (institution_domain, institution_color)
- Add indexes on institution fields for query performance
- Add NOT NULL constraints on required fields (institution_id, institution_name)
- Fix schema jsonb consistency for raw_institution_payload

* Improve SimpleFin holdings error handling and BigDecimal consistency

* Add security attribute to external link in SimpleFin edit form

* Improve SimpleFin sync timing and add user-configurable date range

- Fix initial sync timing issue: change from 1 month to 7 days default lookback
- Add user-selectable sync start date in account setup UI
- Implement chunked historical sync that respects user-selected date range
- Add sync_start_date field to SimpleFin items
- Handle new accounts on existing connections with same date picker

This addresses SimpleFin API limitations and gives users control over
how much transaction history to sync during initial setup.

* Fix SimpleFin sync status to show detailed results instead of "Never synced"

- Modify sync completion logic to always complete even with unlinked accounts
- Add sync_stats column to track account sync statistics during sync process
- Update sync status display to show "X synced, Y need setup" instead of "Never synced"
- Store detailed sync statistics (total, linked, unlinked accounts) in sync record
- Add sync_status_summary method to provide meaningful status text
- Remove early return that prevented sync completion when accounts need setup

Resolves issue where successful account syncing still showed "Never synced" status.

* Fix Transaction persistence before Entry creation in SimpleFin processor

Persist Transaction with create! instead of new to ensure it has an ID before
creating Entry that references it as entryable. Prevents foreign key errors.

* Fix indifferent access for SimpleFin institution data extraction

The accounts_snapshot parameter comes from JSON with string keys, but the
code was accessing with symbol keys which could silently fail. Convert to
indifferent access to handle both string and symbol keys properly.

* Localize hardcoded deletion in progress string

Replace hardcoded "(deletion in progress...)" text with I18n translation
to maintain consistency with the rest of the view.

* Fix SimpleFin item update test to properly verify rebind/destroy behavior

The test now creates a different SimplefinItem instance and mocks
create_simplefin_item! to return it, ensuring the controller operates
on a new record instead of the same instance. This properly exercises
the rebind/destroy logic and verifies the original item is scheduled
for deletion.

* Fix potential transaction data loss in SimpleFin importer

Prevent wiping stored transactions when API omits transaction data by only
updating raw_transactions_payload when transactions are actually present
in the response, preserving existing transaction data when API doesn't
include transactions key.

* Fix SimpleFin sync chunking and enforce 3-year historical limit

- Fix SimpleFin's actual API limit from 365 days to 60 days per request
- Implement proper backward-walking chunked sync for historical data
- Enforce 3-year maximum historical data limit (60 days × 22 requests)
- Update date picker to reflect 3-year limit and better defaults
- Add comprehensive logging for debugging sync issues

* Add dedicated raw_holdings_payload storage for SimpleFin accounts

- Add raw_holdings_payload column to simplefin_accounts table
- Separates holdings data from general account data for cleaner processing
- Follows same pattern as raw_transactions_payload for consistency
- Enables proper SimpleFin holdings processing pipeline

* Enhance SimpleFin holdings storage with external ID tracking

- Add external_id and cost_basis columns to holdings table
- Update holdings processor to use external_id for precise matching
- Capture all available SimpleFin holdings data (shares, market_value, cost_basis, etc.)
- Use SimpleFin holding ID as external_id with "simplefin_" prefix
- Calculate price from market_value/shares when available
- Store raw holdings payload in simplefin_accounts for complete data retention

This enables better holdings tracking than composite key approach and ensures
we capture all SimpleFin data even if not immediately used in our models.

* Simplify SimpleFin transaction enrichment

- Add MerchantDetector that uses payee field directly for merchant creation
- Enhance SimpleFin entry name generation combining payee + description
- Remove transaction processor category matching logic
- Create dedicated SimpleFin entry processor

Uses SimpleFin's clean payee data without unnecessary filtering.

* Add source field to ProviderMerchant and fix data enrichment

- Add source field to ProviderMerchant model for provider-specific merchant tracking
- Fix DataEnrichment to handle string transaction IDs correctly with to_i conversion

Enables per-provider merchant deduplication and fixes transaction lookups.

* Fix SimpleFin controller parameter handling

- Convert string account_ids to integers for proper account lookup
- Ensure account selection works correctly with form submissions

Fixes account filtering when setting up SimpleFin sync.

* Fix linting issues - auto-corrected whitespace and formatting

* Derive institution domain from URL when missing in SimpleFin items

* Fix render_error to preserve persisted record for edit context

* Add unique index to prevent duplicate holdings

* Fix potential NameError in holdings processor rescue block

* Guard against missing SimpleFin transaction IDs

* Fix SimpleFin amount parsing error handling

Re-raise ArgumentError instead of silently returning BigDecimal("0")
to prevent misleading $0 transactions from invalid amount data.

* Fix SimpleFin chunked import data loss bug

Merge transaction arrays instead of overwriting to prevent data loss
during chunked imports. Preserve most recent holdings data only.

* Add external_id uniqueness validation to Holding model

* Fix holdings cost_basis precision and add external_id unique constraint

* Fix SimpleFin test mock expectations and remove debug statements

- Fixed SimplefinItemsControllerTest by properly mocking Provider::Simplefin
  instead of over-mocking the create_simplefin_item! method
- Removed DEBUG puts statements from SimplefinItem::Importer

* Fix linting issues - auto-corrected whitespace and formatting

---------

Signed-off-by: Himmelschmidt <46351743+Himmelschmidt@users.noreply.github.com>
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
2025-10-22 19:51:24 +02:00
Zach Gollwitzer
297a695d0f Transaction rules engine V1 (#1900)
* 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
2025-04-18 11:39:58 -04:00