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