mirror of
https://github.com/we-promise/sure.git
synced 2026-04-19 12:04:08 +00:00
Providers factory (#250)
* 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>
This commit is contained in:
66
app/models/provider/factory.rb
Normal file
66
app/models/provider/factory.rb
Normal file
@@ -0,0 +1,66 @@
|
||||
class Provider::Factory
|
||||
class << self
|
||||
# Register a provider adapter
|
||||
# @param provider_type [String] The provider account class name (e.g., "PlaidAccount")
|
||||
# @param adapter_class [Class] The adapter class (e.g., Provider::PlaidAdapter)
|
||||
def register(provider_type, adapter_class)
|
||||
registry[provider_type] = adapter_class
|
||||
end
|
||||
|
||||
# Creates an adapter for a given provider account
|
||||
# @param provider_account [PlaidAccount, SimplefinAccount] The provider-specific account
|
||||
# @param account [Account] Optional account reference
|
||||
# @return [Provider::Base] An adapter instance
|
||||
def create_adapter(provider_account, account: nil)
|
||||
return nil if provider_account.nil?
|
||||
|
||||
provider_type = provider_account.class.name
|
||||
adapter_class = registry[provider_type]
|
||||
|
||||
# If not registered, try to load the adapter
|
||||
if adapter_class.nil?
|
||||
ensure_adapters_loaded
|
||||
adapter_class = registry[provider_type]
|
||||
end
|
||||
|
||||
raise ArgumentError, "Unknown provider type: #{provider_type}. Did you forget to register it?" unless adapter_class
|
||||
|
||||
adapter_class.new(provider_account, account: account)
|
||||
end
|
||||
|
||||
# Creates an adapter from an AccountProvider record
|
||||
# @param account_provider [AccountProvider] The account provider record
|
||||
# @return [Provider::Base] An adapter instance
|
||||
def from_account_provider(account_provider)
|
||||
return nil if account_provider.nil?
|
||||
|
||||
create_adapter(account_provider.provider, account: account_provider.account)
|
||||
end
|
||||
|
||||
# Get list of registered provider types
|
||||
# @return [Array<String>] List of registered provider type names
|
||||
def registered_provider_types
|
||||
ensure_adapters_loaded
|
||||
registry.keys
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def registry
|
||||
@registry ||= {}
|
||||
end
|
||||
|
||||
# Ensures all provider adapters are loaded
|
||||
# This is needed for Rails autoloading in development/test environments
|
||||
def ensure_adapters_loaded
|
||||
return if @adapters_loaded
|
||||
|
||||
# Require all adapter files to trigger registration
|
||||
Dir[Rails.root.join("app/models/provider/*_adapter.rb")].each do |file|
|
||||
require_dependency file
|
||||
end
|
||||
|
||||
@adapters_loaded = true
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user