mirror of
https://github.com/we-promise/sure.git
synced 2026-06-04 10:19:03 +00:00
Closes #1590. Implements Option A (the proper fix), replacing the interim skip. A recurring transfer's name is seeded as "Transfer to {dest}", but future occurrences carry arbitrary names (user free-text, importer wording, the auto-matcher), so the name-based matching_transactions returned [] and the Cleaner retired still-active transfers at the 6-month threshold. main worked around this by skipping transfer rows entirely (Option B) — which also meant a genuinely-stopped transfer never got retired. matching_transactions now detects the Transfer *pair* for transfer rows: an outflow on the source account paired with an inflow on the destination account, within the usual amount/cadence window. The Cleaner no longer skips transfers: - a transfer whose pair still occurs keeps surfacing recent matches → stays active - a transfer whose pair has stopped → correctly retired The amount / day-of-month scopes are extracted and shared between the name-based and pair-based paths. The Identifier's separate transfer skip (auto-identifying pairs from history) is intentionally untouched — that's the out-of-scope feature the issue defers.
52 lines
1.7 KiB
Ruby
52 lines
1.7 KiB
Ruby
class RecurringTransaction
|
|
class Cleaner
|
|
attr_reader :family
|
|
|
|
def initialize(family)
|
|
@family = family
|
|
end
|
|
|
|
# Mark recurring transactions as inactive if they haven't occurred recently
|
|
# Uses 2 months for automatic recurring, 6 months for manual recurring.
|
|
#
|
|
# Transfer rows (destination_account_id present) are included: as of issue
|
|
# #1590, `matching_transactions` detects the Transfer pair, so a still-active
|
|
# transfer keeps surfacing recent matches and stays active, while one whose
|
|
# pair has genuinely stopped is correctly retired.
|
|
def cleanup_stale_transactions
|
|
stale_count = 0
|
|
|
|
family.recurring_transactions
|
|
.active
|
|
.find_each do |recurring_transaction|
|
|
next unless recurring_transaction.should_be_inactive?
|
|
|
|
# Determine threshold based on manual flag
|
|
threshold = recurring_transaction.manual? ? 6.months.ago.to_date : 2.months.ago.to_date
|
|
|
|
# Double-check if there are any recent matching transactions
|
|
recent_matches = recurring_transaction.matching_transactions.select { |entry| entry.date >= threshold }
|
|
|
|
if recent_matches.empty?
|
|
recurring_transaction.mark_inactive!
|
|
stale_count += 1
|
|
end
|
|
end
|
|
|
|
stale_count
|
|
end
|
|
|
|
# Remove inactive recurring transactions that have been inactive for 6+ months
|
|
# Manual recurring transactions are never automatically deleted
|
|
def remove_old_inactive_transactions
|
|
six_months_ago = 6.months.ago
|
|
|
|
family.recurring_transactions
|
|
.inactive
|
|
.where(manual: false)
|
|
.where("updated_at < ?", six_months_ago)
|
|
.destroy_all
|
|
end
|
|
end
|
|
end
|