Backfill category for pre-#924 investment contribution transfers (#1111)

Transfers created before PR #924 have kind='investment_contribution'
but category_id=NULL because auto-categorization was only added to
Transfer::Creator, not the other code paths. PR #924 fixed it going
forward. This migration catches the old ones.

Only updates transactions where category_id IS NULL so it never
overwrites user choices. Skips families without the category.
This commit is contained in:
LPW
2026-03-03 15:10:53 -05:00
committed by GitHub
parent 69bb4f6944
commit 15eaf13b3e
2 changed files with 57 additions and 1 deletions

View File

@@ -0,0 +1,56 @@
# frozen_string_literal: true
class BackfillInvestmentContributionCategories < ActiveRecord::Migration[7.2]
def up
# PR #924 fixed auto-categorization of investment contributions going forward,
# but transfers created before that PR have kind = 'investment_contribution'
# with category_id NULL. This backfill assigns the correct category to those
# transactions using the family's existing "Investment Contributions" category.
#
# Safety:
# - Only updates transactions where category_id IS NULL (never overwrites user choices)
# - Only updates transactions that already have kind = 'investment_contribution'
# - Skips families that don't have an Investment Contributions category yet
# (it will be lazily created on their next new transfer)
# - If a family has duplicate locale-variant categories, picks the oldest one
# (matches Family#investment_contributions_category dedup behavior)
# Static snapshot of Category.all_investment_contributions_names at migration time.
# Inlined to avoid coupling to app code that may change after this migration ships.
locale_names = [
"Investment Contributions",
"Contributions aux investissements",
"Contribucions d'inversió",
"Investeringsbijdragen"
]
quoted_names = locale_names.map { |n| connection.quote(n) }.join(", ")
say_with_time "Backfilling category for investment_contribution transactions" do
execute <<-SQL.squish
UPDATE transactions
SET category_id = matched_category.id
FROM entries, accounts,
LATERAL (
SELECT c.id
FROM categories c
WHERE c.family_id = accounts.family_id
AND c.name IN (#{quoted_names})
ORDER BY c.created_at ASC
LIMIT 1
) AS matched_category
WHERE transactions.kind = 'investment_contribution'
AND transactions.category_id IS NULL
AND entries.entryable_id = transactions.id
AND entries.entryable_type = 'Transaction'
AND accounts.id = entries.account_id
SQL
end
end
def down
# No-op: we cannot distinguish backfilled records from ones that were
# categorized at creation time, so reverting would incorrectly clear
# legitimately assigned categories.
end
end

2
db/schema.rb generated
View File

@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.2].define(version: 2026_02_18_120001) do
ActiveRecord::Schema[7.2].define(version: 2026_03_03_120000) do
# These are extensions that must be enabled in order to support this database
enable_extension "pgcrypto"
enable_extension "plpgsql"