Files
sure/app/models/simplefin_item/unlinking.rb
LPW e9dbf5f4e7 Fix Broken Account Re-linking Feature (#469)
* Update SimpleFIN relinking flow and enhance duplicate account handling

- Updated logic to allow relinking of SimpleFIN accounts while preserving legacy mappings.
- Introduced clean-up logic to hide orphaned duplicate accounts after relinking.
- Enhanced UI to display current mappings for linked accounts.
- Improved test coverage for relinking scenarios and SimpleFIN account visibility.

* Localize SimpleFIN account selection messages and remove hardcoded text

- Added translations for user-facing messages in `select_existing_account` flow (`pt-BR` and `en` locales).
- Replaced hardcoded strings in the view with localized keys.

* Localize Enable Banking and SimpleFIN account linking messages; add support for investment accounts.

- Added translations for Enable Banking and SimpleFIN account linking flows.
- Updated views and controllers to replace hardcoded strings with localized keys.
- Introduced support for investment accounts in `Provider::LunchflowAdapter`.
- Enhanced relinking logic for SimpleFIN accounts and improved test coverage for related scenarios.

---------

Co-authored-by: Josh Waldrep <joshua.waldrep5+github@gmail.com>
2025-12-20 21:18:55 +01:00

60 lines
2.0 KiB
Ruby

# frozen_string_literal: true
module SimplefinItem::Unlinking
# Concern that encapsulates unlinking logic for a SimpleFin item.
# Mirrors the previous SimplefinItem::Unlinker service behavior.
extend ActiveSupport::Concern
# Idempotently remove all connections between this SimpleFin item and local accounts.
# - Detaches any AccountProvider links for each SimplefinAccount
# - Nullifies legacy Account.simplefin_account_id backrefs
# - Detaches Holdings that point at the AccountProvider links
# Returns a per-SFA result payload for observability
def unlink_all!(dry_run: false)
results = []
simplefin_accounts.includes(:account).find_each do |sfa|
links = AccountProvider.where(provider_type: "SimplefinAccount", provider_id: sfa.id).to_a
link_ids = links.map(&:id)
result = {
sfa_id: sfa.id,
name: sfa.name,
account_id: sfa.account_id,
provider_link_ids: link_ids
}
results << result
next if dry_run
begin
ActiveRecord::Base.transaction do
# Detach holdings for any provider links found
if link_ids.any?
Holding.where(account_provider_id: link_ids).update_all(account_provider_id: nil)
end
# Destroy all provider links
links.each do |ap|
ap.destroy!
end
# Legacy FK fallback: ensure any legacy link is cleared
# NOTE: `SimplefinAccount#account_id` is the provider's external identifier.
# The legacy link is `Account.simplefin_account_id` (accessible via `sfa.account`).
if sfa.account.present?
sfa.account.update!(simplefin_account_id: nil)
end
end
rescue => e
Rails.logger.warn(
"Unlinker: failed to fully unlink SFA ##{sfa.id} (links=#{link_ids.inspect}): #{e.class} - #{e.message}"
)
# Record error for observability; continue with other SFAs
result[:error] = e.message
end
end
results
end
end