mirror of
https://github.com/we-promise/sure.git
synced 2026-05-24 13:04:56 +00:00
* Extract hardcoded strings to i18n
Replace numerous hardcoded English strings with I18n lookups (t / I18n.t) across controllers, views, helpers, and components, and convert model validation error messages to symbol keys. Added multiple locale files under config/locales for models and views. This centralizes user-facing notices/alerts, UI text, import/validation messages, and prepares the app for localization and easier translation maintenance.
* Update en.yml
* Update preview-cleanup.yml
* Revert "Update preview-cleanup.yml"
This reverts commit 1ba6d3c34c.
* test: align i18n assertions with translated messages
* Standardize balance error key and tweak locales
Replace SophtronAccount's :requires_balance error key with :no_balance and update related locale strings for sophtron, plaid, and simplefin accounts to use the new key and clearer copy. Also switch the QIF upload redirect notice to use a relative translation key (t('.qif_uploaded')), remove an unused SSO providers help line, and fix a trailing-newline/whitespace issue in the subscriptions locale. These changes standardize validation keys and improve translation consistency and messaging.
---------
Co-authored-by: KiloClaw <kiloclaw@openclaw.ai>
89 lines
3.4 KiB
Ruby
89 lines
3.4 KiB
Ruby
class PendingDuplicateMergesController < ApplicationController
|
|
before_action :set_transaction
|
|
|
|
def new
|
|
@limit = 10
|
|
# Ensure offset is non-negative to prevent abuse
|
|
@offset = [ (params[:offset] || 0).to_i, 0 ].max
|
|
|
|
# Fetch one extra to determine if there are more results
|
|
candidates = @transaction.pending_duplicate_candidates(limit: @limit + 1, offset: @offset).to_a
|
|
@has_more = candidates.size > @limit
|
|
@potential_duplicates = candidates.first(@limit)
|
|
|
|
# Calculate range for display (e.g., "1-10", "11-20")
|
|
@range_start = @offset + 1
|
|
@range_end = @offset + @potential_duplicates.count
|
|
end
|
|
|
|
def create
|
|
return unless require_account_permission!(@transaction.entry.account, :annotate, redirect_path: transactions_path)
|
|
|
|
# Manually merge the pending transaction with the selected posted transaction
|
|
unless merge_params[:posted_entry_id].present?
|
|
redirect_back_or_to transactions_path, alert: t(".no_posted_selected")
|
|
return
|
|
end
|
|
|
|
# Validate the posted entry is an eligible candidate (same account, currency, not pending)
|
|
posted_entry = find_eligible_posted_entry(merge_params[:posted_entry_id])
|
|
|
|
unless posted_entry
|
|
redirect_back_or_to transactions_path, alert: t(".invalid_transaction")
|
|
return
|
|
end
|
|
|
|
# Store the merge suggestion and immediately execute it
|
|
@transaction.update!(
|
|
extra: (@transaction.extra || {}).merge(
|
|
"potential_posted_match" => {
|
|
"entry_id" => posted_entry.id,
|
|
"reason" => "manual_match",
|
|
"posted_amount" => posted_entry.amount.to_s,
|
|
"confidence" => "high", # Manual matches are high confidence
|
|
"detected_at" => Date.current.to_s
|
|
}
|
|
)
|
|
)
|
|
|
|
# Immediately merge
|
|
if @transaction.merge_with_duplicate!
|
|
redirect_back_or_to transactions_path, notice: t(".merge_success")
|
|
else
|
|
redirect_back_or_to transactions_path, alert: t(".merge_failed")
|
|
end
|
|
rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotDestroyed,
|
|
ActiveRecord::Deadlocked, ActiveRecord::LockWaitTimeout => e
|
|
Rails.logger.error("Failed to manually merge pending transaction: #{e.message}")
|
|
redirect_back_or_to transactions_path, alert: t("transactions.merge_duplicate.failure")
|
|
end
|
|
|
|
private
|
|
def set_transaction
|
|
entry = Current.accessible_entries.find(params[:transaction_id])
|
|
@transaction = entry.entryable
|
|
|
|
unless @transaction.is_a?(Transaction) && @transaction.pending?
|
|
redirect_to transactions_path, alert: t("pending_duplicate_merges.set_transaction.pending_only")
|
|
end
|
|
end
|
|
|
|
def find_eligible_posted_entry(entry_id)
|
|
# Constrain to same account, currency, and ensure it's a posted transaction
|
|
# Use the same logic as pending_duplicate_candidates to ensure consistency
|
|
conditions = Transaction::PENDING_PROVIDERS.map { |provider| "(transactions.extra -> '#{provider}' ->> 'pending')::boolean IS NOT TRUE" }
|
|
|
|
@transaction.entry.account.entries
|
|
.joins("INNER JOIN transactions ON transactions.id = entries.entryable_id AND entries.entryable_type = 'Transaction'")
|
|
.where(id: entry_id)
|
|
.where(currency: @transaction.entry.currency)
|
|
.where.not(id: @transaction.entry.id)
|
|
.where(conditions.join(" AND "))
|
|
.first
|
|
end
|
|
|
|
def merge_params
|
|
params.require(:pending_duplicate_merges).permit(:posted_entry_id)
|
|
end
|
|
end
|