Files
sure/lib/generators/provider/family/templates/syncer.rb.tt

93 lines
3.6 KiB
Plaintext

# frozen_string_literal: true
class <%= class_name %>Item::Syncer
include SyncStats::Collector
attr_reader :<%= file_name %>_item
def initialize(<%= file_name %>_item)
@<%= file_name %>_item = <%= file_name %>_item
end
def perform_sync(sync)
Rails.logger.info "<%= class_name %>Item::Syncer - Starting sync for item #{<%= file_name %>_item.id}"
# Phase 1: Import data from provider API
sync.update!(status_text: I18n.t("<%= file_name %>_items.sync.status.importing")) if sync.respond_to?(:status_text)
<%= file_name %>_item.import_latest_<%= file_name %>_data(sync: sync)
# Phase 2: Collect setup statistics
finalize_setup_counts(sync)
# Phase 3: Process data for linked accounts
linked_<%= file_name %>_accounts = <%= file_name %>_item.linked_<%= file_name %>_accounts.includes(account_provider: :account)
if linked_<%= file_name %>_accounts.any?
sync.update!(status_text: I18n.t("<%= file_name %>_items.sync.status.processing")) if sync.respond_to?(:status_text)
mark_import_started(sync)
<%= file_name %>_item.process_accounts
# Phase 4: Schedule balance calculations
sync.update!(status_text: I18n.t("<%= file_name %>_items.sync.status.calculating")) if sync.respond_to?(:status_text)
<%= file_name %>_item.schedule_account_syncs(
parent_sync: sync,
window_start_date: sync.window_start_date,
window_end_date: sync.window_end_date
)
# Phase 5: Collect statistics
account_ids = linked_<%= file_name %>_accounts.filter_map { |pa| pa.current_account&.id }
<% if investment_provider? -%>
collect_transaction_stats(sync, account_ids: account_ids, source: "<%= file_name %>")
collect_trades_stats(sync, account_ids: account_ids, source: "<%= file_name %>")
collect_holdings_stats(sync, holdings_count: count_holdings, label: "processed")
<% else -%>
collect_transaction_stats(sync, account_ids: account_ids, source: "<%= file_name %>")
<% end -%>
end
# Mark sync health
collect_health_stats(sync, errors: nil)
rescue Provider::<%= class_name %>::AuthenticationError => e
<%= file_name %>_item.update!(status: :requires_update)
collect_health_stats(sync, errors: [ { message: e.message, category: "auth_error" } ])
raise
rescue => e
collect_health_stats(sync, errors: [ { message: e.message, category: "sync_error" } ])
raise
end
# Public: called by Sync after finalization
def perform_post_sync
# Override for post-sync cleanup if needed
end
private
<% if investment_provider? -%>
def count_holdings
<%= file_name %>_item.<%= file_name %>_accounts.sum { |pa| Array(pa.raw_holdings_payload).size }
end
<% end -%>
def mark_import_started(sync)
# Mark that we're now processing imported data
sync.update!(status_text: I18n.t("<%= file_name %>_items.sync.status.importing_data")) if sync.respond_to?(:status_text)
end
def finalize_setup_counts(sync)
sync.update!(status_text: I18n.t("<%= file_name %>_items.sync.status.checking_setup")) if sync.respond_to?(:status_text)
unlinked_count = <%= file_name %>_item.unlinked_accounts_count
if unlinked_count > 0
<%= file_name %>_item.update!(pending_account_setup: true)
sync.update!(status_text: I18n.t("<%= file_name %>_items.sync.status.needs_setup", count: unlinked_count)) if sync.respond_to?(:status_text)
else
<%= file_name %>_item.update!(pending_account_setup: false)
end
# Collect setup stats
collect_setup_stats(sync, provider_accounts: <%= file_name %>_item.<%= file_name %>_accounts)
end
end