From 41c991384ac7eb66bd72fca0ef4b4d9c44648c01 Mon Sep 17 00:00:00 2001 From: Zach Gollwitzer Date: Wed, 22 May 2024 10:02:03 -0400 Subject: [PATCH] Fix duplicate category creation on import (#791) * Repro * Fix * Update signage --- app/models/import.rb | 6 +++++- test/fixtures/imports.yml | 16 ++++++++++------ test/models/import_test.rb | 5 ++++- test/support/import_test_helper.rb | 9 +++++---- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/app/models/import.rb b/app/models/import.rb index af11d214..d545b074 100644 --- a/app/models/import.rb +++ b/app/models/import.rb @@ -110,9 +110,13 @@ class Import < ApplicationRecord def generate_transactions transactions = [] + category_cache = {} csv.table.each do |row| - category = account.family.transaction_categories.find_or_initialize_by(name: row["category"]) if row["category"].present? + category_name = row["category"] + + category = category_cache[category_name] ||= account.family.transaction_categories.find_or_initialize_by(name: category_name) if row["category"].present? + txn = account.transactions.build \ name: row["name"].presence || FALLBACK_TRANSACTION_NAME, date: Date.iso8601(row["date"]), diff --git a/test/fixtures/imports.yml b/test/fixtures/imports.yml index b0c30b4a..118f03f4 100644 --- a/test/fixtures/imports.yml +++ b/test/fixtures/imports.yml @@ -6,12 +6,16 @@ loaded_import: account: checking raw_csv_str: | date,name,category,amount - 2024-01-01,Starbucks drink,Food,20 - 2024-01-02,Amazon stuff,Shopping,200 + 2024-01-01,Starbucks drink,Food & Drink,-8.55 + 2024-01-01,Etsy,Shopping,-80.98 + 2024-01-02,Amazon stuff,Shopping,-200 + 2024-01-03,Paycheck,Income,1000 normalized_csv_str: | date,name,category,amount - 2024-01-01,Starbucks drink,Food,20 - 2024-01-02,Amazon stuff,Shopping,200 + 2024-01-01,Starbucks drink,Food & Drink,-8.55 + 2024-01-01,Etsy,Shopping,-80.98 + 2024-01-02,Amazon stuff,Shopping,-200 + 2024-01-03,Paycheck,Income,1000 created_at: <%= 2.days.ago %> completed_import: @@ -23,10 +27,10 @@ completed_import: amount: amount raw_csv_str: | date,name,category,amount - 2024-01-01,Starbucks drink,Food,20 + 2024-01-01,Starbucks drink,Food & Drink,-20 normalized_csv_str: | date,name,category,amount - 2024-01-01,Starbucks drink,Food,20 + 2024-01-01,Starbucks drink,Food & Drink,-20 created_at: <%= 2.days.ago %> diff --git a/test/models/import_test.rb b/test/models/import_test.rb index e04fb527..3b8322a0 100644 --- a/test/models/import_test.rb +++ b/test/models/import_test.rb @@ -39,7 +39,10 @@ class ImportTest < ActiveSupport::TestCase end test "publishes a valid import" do - assert_difference -> { Transaction::Category.count } => 2, -> { Transaction.count } => 2 do + # Import has 3 unique categories: "Food & Drink", "Income", and "Shopping" (x2) + # Fixtures already define "Food & Drink" and "Income", so these should not be created + # "Shopping" is a new category, but should only be created 1x during import + assert_difference -> { Transaction.count } => 4, -> { Transaction::Category.count } => 1 do @loaded_import.publish end diff --git a/test/support/import_test_helper.rb b/test/support/import_test_helper.rb index 85888570..c8cfc19b 100644 --- a/test/support/import_test_helper.rb +++ b/test/support/import_test_helper.rb @@ -2,8 +2,9 @@ module ImportTestHelper def valid_csv_str <<-ROWS date,name,category,amount - 2024-01-01,Starbucks drink,Food,20 - 2024-01-02,Amazon stuff,Shopping,200 + 2024-01-01,Starbucks drink,Food,-20 + 2024-01-02,Amazon stuff,Shopping,-200 + 2024-01-03,Paycheck,Income,1000 ROWS end @@ -17,8 +18,8 @@ module ImportTestHelper def valid_csv_with_missing_data <<-ROWS date,name,category,"optional id",amount - 2024-01-01,Drink,Food,1234,200 - 2024-01-02,,,,100 + 2024-01-01,Drink,Food,1234,-200 + 2024-01-02,,,,-100 ROWS end