mirror of
https://github.com/we-promise/sure.git
synced 2026-04-17 02:54:10 +00:00
* Implement providers factory * Multiple providers sync support - Proper Multi-Provider Syncing: When you click sync on an account with multiple providers (e.g., both Plaid and SimpleFin), all provider items are synced - Better API: The existing account.providers method already returns all providers, and account.provider returns the first one for backward compatibility - Correct Holdings Deletion Logic: Holdings can only be deleted if ALL providers allow it, preventing accidental deletions that would be recreated on next sync TODO: validate this is the way we want to go? We would need to check holdings belong to which account, and then check provider allows deletion. More complex - Database Constraints: The existing validations ensure an account can have at most one provider of each type (one PlaidAccount, one SimplefinAccount, etc.) * Add generic provider_import_adapter * Finish unified import strategy * Update app/models/plaid_account.rb Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Signed-off-by: soky srm <sokysrm@gmail.com> * Update app/models/provider/factory.rb Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Signed-off-by: soky srm <sokysrm@gmail.com> * Fix account linked by plaid_id instead of external_id * Parse numerics to BigDecimal Parse numerics to BigDecimal before computing amount; guard nils. Avoid String * String and float drift; also normalize date. * Fix incorrect usage of assert_raises. * Fix linter * Fix processor test. * Update current_balance_manager.rb * Test fixes * Fix plaid linked account test * Add support for holding per account_provider * Fix proper account access Also fix account deletion for simpefin too * FIX match tests for consistency * Some more factory updates * Fix account schema for multipe providers Can do: - Account #1 → PlaidAccount + SimplefinAccount (multiple different providers) - Account #2 → PlaidAccount only - Account #3 → SimplefinAccount only Cannot do: - Account #1 → PlaidAccount + PlaidAccount (duplicate provider type) - PlaidAccount #123 → Account #1 + Account #2 (provider linked to multiple accounts) * Fix account setup - An account CAN have multiple providers (the schema shows account_providers with unique index on [account_id, provider_type]) - Each provider should maintain its own separate entries - We should NOT update one provider's entry when another provider syncs * Fix linter and guard migration * FIX linter issues. * Fixes - Remove duplicated index - Pass account_provider_id - Guard holdings call to avoid NoMethodError * Update schema and provider import fix * Plaid doesn't allow holdings deletion * Use ClimateControl for proper env setup * No need for this in .git --------- Signed-off-by: soky srm <sokysrm@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
106 lines
4.8 KiB
Plaintext
106 lines
4.8 KiB
Plaintext
<% content_for :title, @simplefin_item.name %>
|
|
|
|
<div class="mb-8">
|
|
<%= link_to simplefin_items_path, class: "text-secondary hover:text-primary" do %>
|
|
← Back to SimpleFin Connections
|
|
<% end %>
|
|
<h1 class="text-2xl font-bold mt-2"><%= @simplefin_item.name %></h1>
|
|
<div class="flex gap-3 mt-4">
|
|
<%= button_to sync_simplefin_item_path(@simplefin_item), method: :post, class: "inline-flex items-center gap-2 px-4 py-2 bg-surface border border-primary rounded-lg text-primary font-medium hover:bg-surface-hover focus:ring-2 focus:ring-primary focus:ring-offset-2" do %>
|
|
<%= icon "refresh-cw", size: "sm" %>
|
|
Sync
|
|
<% end %>
|
|
<%= button_to simplefin_item_path(@simplefin_item), method: :delete, data: { confirm: "Are you sure?" }, class: "inline-flex items-center gap-2 px-4 py-2 bg-destructive border border-destructive rounded-lg text-white font-medium hover:bg-destructive-hover focus:ring-2 focus:ring-destructive focus:ring-offset-2" do %>
|
|
<%= icon "trash", size: "sm" %>
|
|
Delete
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="space-y-6">
|
|
<% if @simplefin_item.syncing? %>
|
|
<div class="p-4 bg-surface border border-primary rounded-lg">
|
|
<div class="flex items-center">
|
|
<%= icon "loader-2", class: "w-5 h-5 text-primary animate-spin mr-2" %>
|
|
<p class="text-primary">Syncing accounts...</p>
|
|
</div>
|
|
</div>
|
|
<% end %>
|
|
|
|
<% if @simplefin_item.accounts.any? %>
|
|
<%= render "accounts/index/account_groups", accounts: @simplefin_item.accounts %>
|
|
<% elsif @simplefin_item.simplefin_accounts.any? %>
|
|
<div class="bg-container-inset p-1 rounded-xl">
|
|
<div class="flex items-center px-4 py-2 text-xs font-medium text-secondary">
|
|
<p>SimpleFin Accounts</p>
|
|
<span class="text-subdued mx-2">·</span>
|
|
<p><%= @simplefin_item.simplefin_accounts.count %></p>
|
|
</div>
|
|
<div class="bg-container rounded-lg shadow-border-xs">
|
|
<% @simplefin_item.simplefin_accounts.each_with_index do |simplefin_account, index| %>
|
|
<div class="p-4 flex items-center justify-between gap-3">
|
|
<div class="flex items-center gap-3">
|
|
<%= render DS::FilledIcon.new(
|
|
variant: :container,
|
|
text: simplefin_account.name.first.upcase,
|
|
size: "md"
|
|
) %>
|
|
<div>
|
|
<p class="text-sm font-medium text-primary">
|
|
<%= simplefin_account.name %>
|
|
<% if simplefin_account.org_data.present? && simplefin_account.org_data['name'].present? %>
|
|
<span class="text-secondary">• <%= simplefin_account.org_data["name"] %></span>
|
|
<% elsif @simplefin_item.institution_name.present? %>
|
|
<span class="text-secondary">• <%= @simplefin_item.institution_name %></span>
|
|
<% end %>
|
|
</p>
|
|
<p class="text-sm text-secondary">
|
|
<%= simplefin_account.account_type&.humanize || "Unknown Type" %>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center gap-8">
|
|
<p class="text-sm font-medium text-primary">
|
|
<%= number_to_currency(simplefin_account.current_balance || 0) %>
|
|
</p>
|
|
<% if simplefin_account.current_account %>
|
|
<%= render DS::Link.new(
|
|
text: "View Account",
|
|
href: account_path(simplefin_account.current_account),
|
|
variant: :outline
|
|
) %>
|
|
<% else %>
|
|
<%= render DS::Link.new(
|
|
text: "Set Up Account",
|
|
href: setup_accounts_simplefin_item_path(@simplefin_item),
|
|
variant: :primary,
|
|
icon: "settings"
|
|
) %>
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
<% unless index == @simplefin_item.simplefin_accounts.count - 1 %>
|
|
<%= render "shared/ruler" %>
|
|
<% end %>
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
<% else %>
|
|
<div class="text-center py-12">
|
|
<div class="space-y-3 text-center flex flex-col items-center">
|
|
<%= render DS::FilledIcon.new(
|
|
variant: :container,
|
|
icon: "building-2",
|
|
) %>
|
|
|
|
<p class="text-sm font-medium text-primary">No accounts found</p>
|
|
<p class="text-secondary text-sm">Try syncing again to import your accounts.</p>
|
|
<%= button_to sync_simplefin_item_path(@simplefin_item), method: :post, class: "inline-flex items-center gap-2 px-4 py-2 bg-primary border border-primary rounded-lg text-white font-medium hover:bg-primary-hover focus:ring-2 focus:ring-primary focus:ring-offset-2" do %>
|
|
<%= icon "refresh-cw", size: "sm" %>
|
|
Sync Now
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
<% end %>
|
|
</div>
|