forked from maybe-finance/maybe
-
Notifications
You must be signed in to change notification settings - Fork 94
Simplefin enhancements v2 #267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
jjmata
merged 69 commits into
we-promise:main
from
luckyPipewrench:simplefin-enhancements-v2
Nov 17, 2025
+2,916
−406
Merged
Changes from all commits
Commits
Show all changes
69 commits
Select commit
Hold shift + click to select a range
7c4356d
SimpleFin: metadata + merge fixes; holdings (incl. crypto) + Day Chan…
d9ce476
fix testing
32c1081
fix linting
5632619
xfix linting x2
94b5b98
Review PR #267 on we-promise/sure (SimpleFin enhancements v2). Addres…
3766d79
SimpleFin: address CodeRabbit comments (batch 1)
e32345e
Linter noise
jjmata 3966909
removed filed commited by mistake.
64e7328
manual relink flow and tighten composite matching
81f6568
enforce manual relink UI; fix adapter keywords; guarantee extra.simp…
d5d534a
refactor(simplefin): extract relink service; enforce manual relink UI…
ee939d9
add provider date parser; refactor rake; move view queries; partial r…
8d1efca
run balances-only import in background job. make update flow enqueue …
9fc755a
persists across all update redirects and initialize
2a971d6
SimpleFin: metadata + merge fixes; holdings (incl. crypto) + Day Chan…
5142630
Fixed failed test after rebase.
6f4d2f3
scan_ruby fix
c6e5908
Calming the rabbit:
10eceb8
FIX SimpleFIN new account modal
sokie ff72c1b
Remove SimpleFin legacy UI components, migrate schema, and refine lin…
e446621
Extract SimpleFin-related logic to `prepare_show_context` helper and …
789ca42
Remove unused SimpleFin maps from prepare_show_context; select IDs to…
6d8707c
Remove unnecessary blank lines
DeathCamel58 b6b1abb
Reduce unnecessary changes
DeathCamel58 2c3e512
Simplefin Account Setup: Display in modal
DeathCamel58 01ef5d2
Removed unnecessary comment.
84cf949
removed unnecessary function.
cd1868c
fixed broken links
ca3902d
Removed unnecessary file
d51700f
changed to database query
9f79d2b
set to use UTC and gaurd against null
0c99819
set dry_run=true
ca92e3a
Fixed comment
6982322
Changed to use a database-level query
097fe30
matched test name to test behavior.
1af9b12
Eliminate code duplication and Time.zone dependency
2d30a6d
make final summary surface failures
f3ea9bd
lint fix
310f317
Revised timezone comment. better handle missing selectors.
2019e33
sanitized LIKE wildcards
7d67e47
Fixed SimpleFin import to avoid “Currency can’t be blank” validation …
0ab8f21
Added helper methods for admin and self-hosted checks
b34e1ac
Specify exception types in rescue clauses.
bc13100
Refined logic to determine transaction dates for credit accounts.
c26f2d2
Refined stats calculation for `total_accounts` to track the maximum u…
0443b2c
Moved `unlink_all!` logic to `SimplefinItem::Unlinking` concern and d…
b8b840a
Refined legacy unlinking logic, improved `current_holdings` formattin…
f9b8d7a
Enhanced `unlink_all!` with explicit error handling, improved transac…
d4e216d
Improved currency assignment logic by adding fallback to `current_acc…
919dac7
Enhanced error tracking during SimpleFin account imports by adding ca…
d2dac04
typo fix
3b07f98
Didn't realize rabbit was still mad...
65beaa5
Dang rabbit never stops... Centralized SimpleFin maps logic into `Map…
daa1a5c
Persistent rabbit. Optimized SimpleFin maps logic by implementing bat…
0ab481e
Lost a commit somehow, resolved here. Refactored transaction extra de…
033bbec
Refactored sensitive data redaction in `simplefin_unlink` task for re…
bcc979c
Lint fix
1ec19b2
Removed per PR comments.
jjmata 07b28c8
Also removing per PR comment.
jjmata 3f3c62c
git commit -m "SimpleFIN polish: preserve #manual-accounts wrapper, u…
297670a
Extend unlinked account check to include "Investment" type
a7a081d
set SimpleFIN item for `balances`, remove redundant unpacking, and im…
344f3d6
SimpleFIN: add `errors` action + modal; do not reintroduce legacy rel…
eb089cd
FIX simpleFIN linking
sokie 27a0d90
Merge branch 'main' into simplefin-enhancements-v2
sokie 6b44808
Add delay back, tests benefit from it
jjmata 485b3e3
Put cache back in
jjmata afbc140
Remove empty `rake` task
jjmata 1b8b364
Small spelling fixes.
jjmata File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| module SimplefinItems | ||
| module MapsHelper | ||
| extend ActiveSupport::Concern | ||
|
|
||
| # Build per-item maps consumed by the simplefin_item partial. | ||
| # Accepts a single SimplefinItem or a collection. | ||
| def build_simplefin_maps_for(items) | ||
| items = Array(items).compact | ||
| return if items.empty? | ||
|
|
||
| @simplefin_sync_stats_map ||= {} | ||
| @simplefin_has_unlinked_map ||= {} | ||
| @simplefin_unlinked_count_map ||= {} | ||
| @simplefin_duplicate_only_map ||= {} | ||
| @simplefin_show_relink_map ||= {} | ||
|
|
||
| # Batch-check if ANY family has manual accounts (same result for all items from same family) | ||
| family_ids = items.map { |i| i.family_id }.uniq | ||
| families_with_manuals = Account | ||
| .visible_manual | ||
| .where(family_id: family_ids) | ||
| .distinct | ||
| .pluck(:family_id) | ||
| .to_set | ||
|
|
||
| # Batch-fetch unlinked counts for all items in one query | ||
| unlinked_counts = SimplefinAccount | ||
| .where(simplefin_item_id: items.map(&:id)) | ||
| .left_joins(:account, :account_provider) | ||
| .where(accounts: { id: nil }, account_providers: { id: nil }) | ||
| .group(:simplefin_item_id) | ||
| .count | ||
|
|
||
| items.each do |item| | ||
| # Latest sync stats (avoid N+1; rely on includes(:syncs) where appropriate) | ||
| latest_sync = if item.syncs.loaded? | ||
| item.syncs.max_by(&:created_at) | ||
| else | ||
| item.syncs.ordered.first | ||
| end | ||
| stats = (latest_sync&.sync_stats || {}) | ||
| @simplefin_sync_stats_map[item.id] = stats | ||
|
|
||
| # Whether the family has any manual accounts available to link (from batch query) | ||
| @simplefin_has_unlinked_map[item.id] = families_with_manuals.include?(item.family_id) | ||
|
|
||
| # Count from batch query (defaults to 0 if not found) | ||
| @simplefin_unlinked_count_map[item.id] = unlinked_counts[item.id] || 0 | ||
|
|
||
| # Whether all reported errors for this item are duplicate-account warnings | ||
| @simplefin_duplicate_only_map[item.id] = compute_duplicate_only_flag(stats) | ||
|
|
||
| # Compute CTA visibility: show relink only when there are zero unlinked SFAs, | ||
| # there exist manual accounts to link, and the item has at least one SFA | ||
| begin | ||
| unlinked_count = @simplefin_unlinked_count_map[item.id] || 0 | ||
| manuals_exist = @simplefin_has_unlinked_map[item.id] | ||
| sfa_any = if item.simplefin_accounts.loaded? | ||
| item.simplefin_accounts.any? | ||
| else | ||
| item.simplefin_accounts.exists? | ||
| end | ||
| @simplefin_show_relink_map[item.id] = (unlinked_count.to_i == 0 && manuals_exist && sfa_any) | ||
| rescue StandardError => e | ||
| Rails.logger.warn("SimpleFin card: CTA computation failed for item #{item.id}: #{e.class} - #{e.message}") | ||
| @simplefin_show_relink_map[item.id] = false | ||
| end | ||
| end | ||
|
|
||
| # Ensure maps are hashes even when items empty | ||
| @simplefin_sync_stats_map ||= {} | ||
| @simplefin_has_unlinked_map ||= {} | ||
| @simplefin_unlinked_count_map ||= {} | ||
| @simplefin_duplicate_only_map ||= {} | ||
| @simplefin_show_relink_map ||= {} | ||
| end | ||
|
|
||
| private | ||
| def compute_duplicate_only_flag(stats) | ||
| errs = Array(stats && stats["errors"]).map do |e| | ||
| if e.is_a?(Hash) | ||
| e["message"] || e[:message] | ||
| else | ||
| e.to_s | ||
| end | ||
| end | ||
| errs.present? && errs.all? { |m| m.to_s.downcase.include?("duplicate upstream account detected") } | ||
| rescue | ||
| false | ||
| end | ||
| end | ||
| end | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.