Files
sure/config/locales/views/simplefin_items/en.yml
LPW 0a96bf199d SimpleFIN: setup UX + same-provider relink + card-replacement detection (#1493)
* SimpleFIN: setup UX + same-provider relink + card-replacement detection

Fixes three bugs and adds auto-detection for credit-card fraud replacement.

Bugs:
- Importer: per-institution auth errors no longer flip the whole item to
  requires_update. Partial errors stay on sync_stats so other institutions
  keep syncing.
- Setup page: new activity badges (recent / dormant / empty / likely-closed)
  via SimplefinAccount::ActivitySummary. Likely-closed (dormant + near-zero
  balance + prior history) defaults to "skip" in the type picker.
- Relink: link_existing_account allows SimpleFIN to SimpleFIN swaps by
  atomically detaching the old AccountProvider inside a transaction. Adds
  "Change SimpleFIN account" menu item on linked-account dropdowns.

Feature (credit-card scope only):
- SimplefinItem::ReplacementDetector runs post-sync. Pairs a linked dormant
  zero-balance sfa with an unlinked active sfa at the same institution and
  account type. Persists suggestions on Sync#sync_stats.
- Inline banner on the SimpleFIN item card prompts relink via CustomConfirm.
  Per-pair dismiss button scoped to the current sync (resurfaces on next
  sync if still applicable). Auto-suppresses once the relink has landed.

Dev tooling:
- bin/rails simplefin:seed_fraud_scenario[email] creates a realistic broken
  pair for manual QA; cleanup_fraud_scenario reverses it.

* Address review feedback on #1493

- ReplacementDetector: symmetric one-to-one matching. Two dormant cards
  pointing at the same active card are now both skipped — previously the
  detector could emit two suggestions that would clobber each other if
  the user accepted both.
- ReplacementDetector: require non-blank institution names on both sides
  before matching. Blank-vs-blank was accidentally treated as equal,
  risking cross-provider false matches when SimpleFIN omitted org_data.
- ActivitySummary: fall back to "posted" when "transacted_at" is 0
  (SimpleFIN's "unknown" sentinel). Integer 0 is truthy in Ruby, so the
  previous `|| fallback` short-circuited and ignored posted.
- Controller: dismiss key is now the (dormant, active) pair so dismissing
  one candidate for a dormant card doesn't suppress others.
- Helper test: freeze time around "6.hours.ago" and "5.days.ago"
  assertions so they don't flake when the suite runs before 06:00.

* Address second review pass on #1493

- ReplacementDetector: canonicalize account_type in one place so filtering
  (supported_type?) and matching (type_matches?) agree on "credit card"
  vs "credit_card" variants.
- ReplacementDetector: skip candidates with nil current_balance. nil is
  "unknown," not "zero" — previously fell back to 0 and passed the near-
  zero gate, allowing suggestions without balance evidence.
2026-04-18 09:50:34 +02:00

133 lines
6.9 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
en:
simplefin_items:
new:
title: Connect SimpleFIN
setup_token: Setup token
setup_token_placeholder: paste your SimpleFIN setup token
connect: Connect
cancel: Cancel
create:
success: SimpleFIN connection added successfully! Your accounts will appear shortly as they sync in the background.
errors:
blank_token: Please enter a SimpleFIN setup token.
invalid_token: Invalid setup token. Please check that you copied the complete token from SimpleFIN Bridge.
token_compromised: The setup token may be compromised, expired, or already used. Please create a new one.
create_failed: "Failed to connect: %{message}"
unexpected: An unexpected error occurred. Please try again.
destroy:
success: SimpleFIN connection will be removed
update:
success: SimpleFIN connection updated successfully! Your accounts are being reconnected.
errors:
blank_token: Please enter a SimpleFIN setup token.
invalid_token: Invalid setup token. Please check that you copied the complete token from SimpleFIN Bridge.
token_compromised: The setup token may be compromised, expired, or already used. Please create a new one.
update_failed: "Failed to update connection: %{message}"
unexpected: An unexpected error occurred. Please try again.
edit:
setup_token:
label: "SimpleFIN Setup Token:"
placeholder: "Paste your SimpleFIN setup token here..."
help_text: "The token should be a long string starting with letters and numbers"
setup_accounts:
account_card:
balance: "Balance"
activity:
recent:
one: "1 transaction • latest %{when}"
other: "%{count} transactions • latest %{when}"
dormant: "No activity in %{days} days"
empty: "No transactions imported yet"
likely_closed: "No recent activity and zero balance — this may be a closed or replaced card"
today: "today"
yesterday: "yesterday"
days_ago:
one: "1 day ago"
other: "%{count} days ago"
stale_accounts:
title: "Accounts No Longer in SimpleFIN"
description: "These accounts exist in your database but are no longer provided by SimpleFIN. This can happen when account configurations change upstream."
action_prompt: "What would you like to do?"
action_delete: "Delete account and all transactions"
action_move: "Move transactions to:"
action_skip: "Skip for now"
transaction_count:
one: "%{count} transaction"
other: "%{count} transactions"
complete_account_setup:
all_skipped: "All accounts were skipped. No accounts were created."
no_accounts: "No accounts to set up."
success:
one: "Successfully created %{count} SimpleFIN account! Your transactions and holdings are being imported in the background."
other: "Successfully created %{count} SimpleFIN accounts! Your transactions and holdings are being imported in the background."
stale_accounts_processed: "Stale accounts: %{deleted} deleted, %{moved} moved."
stale_accounts_errors:
one: "%{count} stale account action failed. Check logs for details."
other: "%{count} stale account actions failed. Check logs for details."
simplefin_item:
add_new: Add new connection
confirm_accept: Delete connection
confirm_body: This will permanently delete all the accounts in this group and all associated data.
confirm_title: Delete SimpleFIN connection?
delete: Delete
deletion_in_progress: "(deletion in progress...)"
error: Error occurred while syncing data
no_accounts_description: This connection doesn't have any synchronized accounts yet.
no_accounts_title: No accounts found
requires_update: Reconnect
setup_needed: New accounts ready to set up
setup_description: Choose account types for your newly imported SimpleFIN accounts.
setup_action: Set Up New Accounts
setup_accounts_menu: Set Up Accounts
more_accounts_available:
one: "%{count} more account available to set up"
other: "%{count} more accounts available to set up"
accounts_skipped_tooltip: "Some accounts were skipped due to errors during sync"
accounts_skipped_label: "Skipped: %{count}"
rate_limited_ago: "Rate limited (%{time} ago)"
rate_limited_recently: "Rate limited recently"
status: Last synced %{timestamp} ago
status_never: Never synced
status_with_summary: "Last synced %{timestamp} ago • %{summary}"
syncing: Syncing...
update: Update
stale_pending_note: "(excluded from budgets)"
stale_pending_accounts: "in: %{accounts}"
reconciled_details_note: "(see sync summary for details)"
duplicate_accounts_skipped: "Some accounts were skipped as duplicates — use 'Link existing accounts' to merge."
select_existing_account:
title: "Link %{account_name} to SimpleFIN"
description: Select a SimpleFIN account to link to your existing account
cancel: Cancel
link_account: Link account
no_accounts_found: "No SimpleFIN accounts found for this %{moniker}."
wait_for_sync: If you just connected or synced, try again after the sync completes.
unlink_to_move: To move a link, first unlink it from the accounts actions menu.
all_accounts_already_linked: All SimpleFIN accounts appear to be linked already.
currently_linked_to: "Currently linked to: %{account_name}"
link_existing_account:
success: Account successfully linked to SimpleFIN
errors:
only_manual: Only manual accounts can be linked
different_provider: This account is linked to a different provider. Unlink it from that provider first, then link to SimpleFIN.
invalid_simplefin_account: Invalid SimpleFIN account selected
dismiss_replacement_suggestion:
dismissed: Replacement suggestion dismissed
replacement_prompt:
title: "Your %{institution} card may have been replaced"
description: "“%{account_name}” is linked to “%{old_name}”, which has had no recent activity and a zero balance. A new card, “%{new_name}”, is now active at the same institution. Relink to keep your history intact."
relink: Relink to new card
confirm_title: Relink to the new card?
confirm_body: "“%{account_name}” will be linked to “%{new_name}”. Your transaction history stays; future transactions come from the new card."
dismiss_aria: Dismiss replacement suggestion
reconciled_status:
message:
one: "%{count} duplicate pending transaction reconciled"
other: "%{count} duplicate pending transactions reconciled"
stale_pending_status:
message:
one: "%{count} pending transaction older than %{days} days"
other: "%{count} pending transactions older than %{days} days"