mirror of
https://github.com/we-promise/sure.git
synced 2026-04-26 07:24:11 +00:00
Fetch transaction counts during provider setup
Add transaction count validation for all banking providers (SimpleFIN, Lunch Flow, and Enable Banking) during the account setup process. This change fetches transaction data for each bank account immediately after provider credentials are configured, allowing users to see warnings about accounts with no transaction history before completing the setup. Key changes: - SimpleFIN: Fetch accounts and check transaction counts after token setup - Lunch Flow: Check transaction availability after API key configuration - Enable Banking: Validate transaction data after OAuth authorization - Display warning messages in provider panels when issues are detected - Warnings show accounts with 0 transactions in the last 90 days The warnings appear in the /settings/providers screen before the "Configured and ready to use" message, giving users early visibility into potential data availability issues.
This commit is contained in:
@@ -190,9 +190,17 @@ class EnableBankingItemsController < ApplicationController
|
||||
begin
|
||||
enable_banking_item.complete_authorization(code: code)
|
||||
|
||||
# Fetch transaction counts for validation
|
||||
transaction_warnings = fetch_transaction_counts(enable_banking_item)
|
||||
|
||||
# Trigger sync to process accounts
|
||||
enable_banking_item.sync_later
|
||||
|
||||
if transaction_warnings.any?
|
||||
# Store warnings in flash for display on accounts page
|
||||
flash[:warning] = "Connected successfully, but some issues were found: #{transaction_warnings.join('; ')}"
|
||||
end
|
||||
|
||||
redirect_to accounts_path, notice: t(".success", default: "Successfully connected to your bank. Your accounts are being synced.")
|
||||
rescue Provider::EnableBanking::EnableBankingError => e
|
||||
Rails.logger.error "Enable Banking session creation error: #{e.message}"
|
||||
@@ -419,6 +427,53 @@ class EnableBankingItemsController < ApplicationController
|
||||
)
|
||||
end
|
||||
|
||||
# Fetch transaction counts for all accounts in the Enable Banking item
|
||||
# Returns an array of warning messages if any accounts have issues
|
||||
def fetch_transaction_counts(enable_banking_item)
|
||||
warnings = []
|
||||
|
||||
begin
|
||||
provider = enable_banking_item.enable_banking_provider
|
||||
return warnings unless provider
|
||||
|
||||
accounts = enable_banking_item.enable_banking_accounts
|
||||
|
||||
if accounts.empty?
|
||||
warnings << "No bank accounts found after authorization."
|
||||
else
|
||||
# Check transaction counts for each account (last 90 days)
|
||||
accounts.each do |enable_banking_account|
|
||||
account_name = enable_banking_account.name || "Unknown Account"
|
||||
account_uid = enable_banking_account.uid
|
||||
|
||||
begin
|
||||
transactions_data = provider.get_account_transactions(
|
||||
account_id: account_uid,
|
||||
date_from: 90.days.ago,
|
||||
date_to: Date.today
|
||||
)
|
||||
transactions = transactions_data[:transactions] || []
|
||||
|
||||
if transactions.empty?
|
||||
warnings << "Account '#{account_name}' has 0 transactions available in the last 90 days."
|
||||
end
|
||||
rescue Provider::EnableBanking::EnableBankingError => e
|
||||
Rails.logger.warn("Enable Banking transaction count check failed for account #{account_uid}: #{e.message}")
|
||||
warnings << "Unable to fetch transactions for '#{account_name}': #{e.message}"
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue Provider::EnableBanking::EnableBankingError => e
|
||||
Rails.logger.warn("Enable Banking accounts fetch failed: #{e.message}")
|
||||
warnings << "Unable to fetch account information: #{e.message}"
|
||||
rescue => e
|
||||
Rails.logger.warn("Unexpected error checking Enable Banking transactions: #{e.message}")
|
||||
warnings << "Unable to verify transaction availability."
|
||||
end
|
||||
|
||||
warnings
|
||||
end
|
||||
|
||||
# Generate the callback URL for Enable Banking OAuth
|
||||
# In production, uses the standard Rails route
|
||||
# In development, uses DEV_WEBHOOKS_URL if set (e.g., ngrok URL)
|
||||
|
||||
@@ -411,6 +411,9 @@ class LunchflowItemsController < ApplicationController
|
||||
# Trigger initial sync to fetch accounts
|
||||
@lunchflow_item.sync_later
|
||||
|
||||
# Fetch transaction counts for validation
|
||||
@transaction_warnings = fetch_transaction_counts(@lunchflow_item)
|
||||
|
||||
if turbo_frame_request?
|
||||
flash.now[:notice] = t(".success")
|
||||
@lunchflow_items = Current.family.lunchflow_items.ordered
|
||||
@@ -418,7 +421,7 @@ class LunchflowItemsController < ApplicationController
|
||||
turbo_stream.replace(
|
||||
"lunchflow-providers-panel",
|
||||
partial: "settings/providers/lunchflow_panel",
|
||||
locals: { lunchflow_items: @lunchflow_items }
|
||||
locals: { lunchflow_items: @lunchflow_items, transaction_warnings: @transaction_warnings }
|
||||
),
|
||||
*flash_notification_stream_items
|
||||
]
|
||||
@@ -737,6 +740,54 @@ class LunchflowItemsController < ApplicationController
|
||||
params.require(:lunchflow_item).permit(:name, :sync_start_date, :api_key, :base_url)
|
||||
end
|
||||
|
||||
# Fetch transaction counts for all accounts in the Lunchflow item
|
||||
# Returns an array of warning messages if any accounts have issues
|
||||
def fetch_transaction_counts(lunchflow_item)
|
||||
warnings = []
|
||||
|
||||
begin
|
||||
provider = lunchflow_item.lunchflow_provider
|
||||
return warnings unless provider
|
||||
|
||||
accounts_data = provider.get_accounts
|
||||
accounts = accounts_data[:accounts] || []
|
||||
|
||||
if accounts.empty?
|
||||
warnings << "No bank accounts found. Please check your Lunch Flow configuration."
|
||||
else
|
||||
# Check transaction counts for each account (last 90 days)
|
||||
accounts.each do |account_data|
|
||||
account_name = account_data[:name] || "Unknown Account"
|
||||
account_id = account_data[:id]
|
||||
|
||||
begin
|
||||
transactions_data = provider.get_account_transactions(
|
||||
account_id,
|
||||
start_date: 90.days.ago,
|
||||
end_date: Date.today
|
||||
)
|
||||
transactions = transactions_data[:transactions] || []
|
||||
|
||||
if transactions.empty?
|
||||
warnings << "Account '#{account_name}' has 0 transactions available in the last 90 days."
|
||||
end
|
||||
rescue Provider::Lunchflow::LunchflowError => e
|
||||
Rails.logger.warn("Lunchflow transaction count check failed for account #{account_id}: #{e.message}")
|
||||
warnings << "Unable to fetch transactions for '#{account_name}': #{e.message}"
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue Provider::Lunchflow::LunchflowError => e
|
||||
Rails.logger.warn("Lunchflow accounts fetch failed: #{e.message}")
|
||||
warnings << "Unable to fetch account information: #{e.message}"
|
||||
rescue => e
|
||||
Rails.logger.warn("Unexpected error checking Lunchflow transactions: #{e.message}")
|
||||
warnings << "Unable to verify transaction availability."
|
||||
end
|
||||
|
||||
warnings
|
||||
end
|
||||
|
||||
# Sanitize return_to parameter to prevent XSS attacks
|
||||
# Only allow internal paths, reject external URLs and javascript: URIs
|
||||
def safe_return_to_path
|
||||
|
||||
@@ -92,6 +92,9 @@ class SimplefinItemsController < ApplicationController
|
||||
item_name: "SimpleFIN Connection"
|
||||
)
|
||||
|
||||
# Fetch transaction counts for validation
|
||||
@transaction_warnings = fetch_transaction_counts(@simplefin_item)
|
||||
|
||||
if turbo_frame_request?
|
||||
flash.now[:notice] = t(".success")
|
||||
@simplefin_items = Current.family.simplefin_items.ordered
|
||||
@@ -99,7 +102,7 @@ class SimplefinItemsController < ApplicationController
|
||||
turbo_stream.replace(
|
||||
"simplefin-providers-panel",
|
||||
partial: "settings/providers/simplefin_panel",
|
||||
locals: { simplefin_items: @simplefin_items }
|
||||
locals: { simplefin_items: @simplefin_items, transaction_warnings: @transaction_warnings }
|
||||
),
|
||||
*flash_notification_stream_items
|
||||
]
|
||||
@@ -439,6 +442,45 @@ class SimplefinItemsController < ApplicationController
|
||||
s.gsub(NAME_NORM_RE, " ")
|
||||
end
|
||||
|
||||
# Fetch transaction counts for all accounts in the SimpleFIN item
|
||||
# Returns an array of warning messages if any accounts have issues
|
||||
def fetch_transaction_counts(simplefin_item)
|
||||
warnings = []
|
||||
|
||||
begin
|
||||
# Fetch accounts with a reasonable date range (last 90 days)
|
||||
provider = simplefin_item.simplefin_provider
|
||||
accounts_data = provider.get_accounts(
|
||||
simplefin_item.access_url,
|
||||
start_date: 90.days.ago,
|
||||
end_date: Date.today
|
||||
)
|
||||
|
||||
accounts = accounts_data[:accounts] || []
|
||||
|
||||
if accounts.empty?
|
||||
warnings << "No bank accounts found. Please check your SimpleFIN Bridge setup."
|
||||
else
|
||||
accounts.each do |account_data|
|
||||
account_name = account_data[:name] || "Unknown Account"
|
||||
transactions = account_data[:transactions] || []
|
||||
|
||||
if transactions.empty?
|
||||
warnings << "Account '#{account_name}' has 0 transactions available in the last 90 days."
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue Provider::Simplefin::SimplefinError => e
|
||||
Rails.logger.warn("SimpleFin transaction count check failed: #{e.message}")
|
||||
warnings << "Unable to fetch transaction information: #{e.message}"
|
||||
rescue => e
|
||||
Rails.logger.warn("Unexpected error checking SimpleFin transactions: #{e.message}")
|
||||
warnings << "Unable to verify transaction availability."
|
||||
end
|
||||
|
||||
warnings
|
||||
end
|
||||
|
||||
def compute_relink_candidates
|
||||
# Best-effort dedup before building candidates
|
||||
@simplefin_item.dedup_simplefin_accounts! rescue nil
|
||||
|
||||
@@ -53,6 +53,19 @@
|
||||
<% end %>
|
||||
|
||||
<% items = local_assigns[:lunchflow_items] || @lunchflow_items || Current.family.lunchflow_items.where.not(api_key: [nil, ""]) %>
|
||||
|
||||
<% transaction_warnings = local_assigns[:transaction_warnings] %>
|
||||
<% if transaction_warnings&.any? %>
|
||||
<div class="p-3 rounded-md bg-warning/10 border border-warning/20 text-warning text-sm space-y-1">
|
||||
<p class="font-medium">Transaction Data Warnings:</p>
|
||||
<ul class="list-disc list-inside text-xs space-y-0.5">
|
||||
<% transaction_warnings.each do |warning| %>
|
||||
<li><%= warning %></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<% if items&.any? %>
|
||||
<div class="w-2 h-2 bg-success rounded-full"></div>
|
||||
|
||||
@@ -36,6 +36,18 @@
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% transaction_warnings = local_assigns[:transaction_warnings] %>
|
||||
<% if transaction_warnings&.any? %>
|
||||
<div class="p-3 rounded-md bg-warning/10 border border-warning/20 text-warning text-sm space-y-1">
|
||||
<p class="font-medium">Transaction Data Warnings:</p>
|
||||
<ul class="list-disc list-inside text-xs space-y-0.5">
|
||||
<% transaction_warnings.each do |warning| %>
|
||||
<li><%= warning %></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<% if @simplefin_items&.any? %>
|
||||
<div class="w-2 h-2 bg-success rounded-full"></div>
|
||||
|
||||
Reference in New Issue
Block a user