diff --git a/app/models/coinbase_item.rb b/app/models/coinbase_item.rb index f67aeb753..6641958e6 100644 --- a/app/models/coinbase_item.rb +++ b/app/models/coinbase_item.rb @@ -30,6 +30,7 @@ class CoinbaseItem < ApplicationRecord has_many :accounts, through: :coinbase_accounts scope :active, -> { where(scheduled_for_deletion: false) } + scope :syncable, -> { active } scope :ordered, -> { order(created_at: :desc) } scope :needs_update, -> { where(status: :requires_update) } diff --git a/app/models/coinstats_item.rb b/app/models/coinstats_item.rb index c2c9f51fd..6df76bf70 100644 --- a/app/models/coinstats_item.rb +++ b/app/models/coinstats_item.rb @@ -28,6 +28,7 @@ class CoinstatsItem < ApplicationRecord has_many :accounts, through: :coinstats_accounts scope :active, -> { where(scheduled_for_deletion: false) } + scope :syncable, -> { active } scope :ordered, -> { order(created_at: :desc) } scope :needs_update, -> { where(status: :requires_update) } diff --git a/app/models/enable_banking_item.rb b/app/models/enable_banking_item.rb index 7de761bde..d1e8684c9 100644 --- a/app/models/enable_banking_item.rb +++ b/app/models/enable_banking_item.rb @@ -23,6 +23,7 @@ class EnableBankingItem < ApplicationRecord has_many :accounts, through: :enable_banking_accounts scope :active, -> { where(scheduled_for_deletion: false) } + scope :syncable, -> { active } scope :ordered, -> { order(created_at: :desc) } scope :needs_update, -> { where(status: :requires_update) } diff --git a/app/models/family/syncer.rb b/app/models/family/syncer.rb index 80d910cc1..858ed9bc4 100644 --- a/app/models/family/syncer.rb +++ b/app/models/family/syncer.rb @@ -1,6 +1,25 @@ class Family::Syncer attr_reader :family + # Registry of item association names that participate in family sync. + # Each model must: + # 1. Include Syncable + # 2. Define a `syncable` scope (items ready for auto-sync) + # + # To add a new provider: add its association name here. + # The model handles its own "ready to sync" logic via the syncable scope. + SYNCABLE_ITEM_ASSOCIATIONS = %i[ + plaid_items + simplefin_items + lunchflow_items + enable_banking_items + indexa_capital_items + coinbase_items + coinstats_items + mercury_items + snaptrade_items + ].freeze + def initialize(family) @family = family end @@ -25,7 +44,15 @@ class Family::Syncer end private + + # Collects all syncable items from registered providers + manual accounts. + # Each provider model defines its own `syncable` scope that encapsulates + # the "ready to sync" business logic (active, configured, etc.) def child_syncables - family.plaid_items + family.simplefin_items.active + family.lunchflow_items.active + family.enable_banking_items.active + family.indexa_capital_items + family.accounts.manual + provider_items = SYNCABLE_ITEM_ASSOCIATIONS.flat_map do |association| + family.public_send(association).syncable + end + + provider_items + family.accounts.manual end end diff --git a/app/models/indexa_capital_item.rb b/app/models/indexa_capital_item.rb index 8272a256e..ccea401b4 100644 --- a/app/models/indexa_capital_item.rb +++ b/app/models/indexa_capital_item.rb @@ -30,6 +30,7 @@ class IndexaCapitalItem < ApplicationRecord has_many :accounts, through: :indexa_capital_accounts scope :active, -> { where(scheduled_for_deletion: false) } + scope :syncable, -> { active } scope :ordered, -> { order(created_at: :desc) } scope :needs_update, -> { where(status: :requires_update) } diff --git a/app/models/lunchflow_item.rb b/app/models/lunchflow_item.rb index 1165ba836..ba9830c6b 100644 --- a/app/models/lunchflow_item.rb +++ b/app/models/lunchflow_item.rb @@ -20,6 +20,7 @@ class LunchflowItem < ApplicationRecord has_many :accounts, through: :lunchflow_accounts scope :active, -> { where(scheduled_for_deletion: false) } + scope :syncable, -> { active } scope :ordered, -> { order(created_at: :desc) } scope :needs_update, -> { where(status: :requires_update) } diff --git a/app/models/mercury_item.rb b/app/models/mercury_item.rb index 2c781265a..eb062b2b9 100644 --- a/app/models/mercury_item.rb +++ b/app/models/mercury_item.rb @@ -27,6 +27,7 @@ class MercuryItem < ApplicationRecord has_many :accounts, through: :mercury_accounts scope :active, -> { where(scheduled_for_deletion: false) } + scope :syncable, -> { active } scope :ordered, -> { order(created_at: :desc) } scope :needs_update, -> { where(status: :requires_update) } diff --git a/app/models/plaid_item.rb b/app/models/plaid_item.rb index 4ac59d0cf..58e39bae2 100644 --- a/app/models/plaid_item.rb +++ b/app/models/plaid_item.rb @@ -23,6 +23,7 @@ class PlaidItem < ApplicationRecord has_many :legacy_accounts, through: :plaid_accounts, source: :account scope :active, -> { where(scheduled_for_deletion: false) } + scope :syncable, -> { active } scope :ordered, -> { order(created_at: :desc) } scope :needs_update, -> { where(status: :requires_update) } diff --git a/app/models/simplefin_item.rb b/app/models/simplefin_item.rb index 253b6098c..4483393f4 100644 --- a/app/models/simplefin_item.rb +++ b/app/models/simplefin_item.rb @@ -26,6 +26,7 @@ class SimplefinItem < ApplicationRecord has_many :legacy_accounts, through: :simplefin_accounts, source: :account scope :active, -> { where(scheduled_for_deletion: false) } + scope :syncable, -> { active } scope :ordered, -> { order(created_at: :desc) } scope :needs_update, -> { where(status: :requires_update) } diff --git a/app/models/snaptrade_item.rb b/app/models/snaptrade_item.rb index 0c627d7d3..f99c763f6 100644 --- a/app/models/snaptrade_item.rb +++ b/app/models/snaptrade_item.rb @@ -35,6 +35,9 @@ class SnaptradeItem < ApplicationRecord has_many :linked_accounts, through: :snaptrade_accounts scope :active, -> { where(scheduled_for_deletion: false) } + # Syncable = active + fully configured (user registered with SnapTrade API) + # Items without user registration will fail sync, so exclude them from auto-sync + scope :syncable, -> { active.where.not(snaptrade_user_id: [ nil, "" ]).where.not(snaptrade_user_secret: [ nil, "" ]) } scope :ordered, -> { order(created_at: :desc) } scope :needs_update, -> { where(status: :requires_update) }