From 308a4ab048d036d70756251202cfce6cf118e8e1 Mon Sep 17 00:00:00 2001 From: Josh Waldrep Date: Mon, 12 Jan 2026 16:04:53 -0500 Subject: [PATCH] Refactor Plaid transaction type mapping and improve label handling - Updated `PLAID_TYPE_TO_LABEL` in `TransactionsProcessor` to consolidate labels ("Cancel" and "Cash" now mapped to "Other"). - Adjusted `label_from_plaid_type` to return "Other" as the default fallback. - Enhanced tests to include additional valid activity labels and ensure label consistency. - Minor fixes to locale keys for transaction views. --- .../investments/transactions_processor.rb | 7 ++-- app/models/transaction.rb | 2 +- config/locales/views/transactions/en.yml | 35 +++++++++---------- test/models/transaction_test.rb | 6 ++++ 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/app/models/plaid_account/investments/transactions_processor.rb b/app/models/plaid_account/investments/transactions_processor.rb index ded2a473f..d90657ce6 100644 --- a/app/models/plaid_account/investments/transactions_processor.rb +++ b/app/models/plaid_account/investments/transactions_processor.rb @@ -2,11 +2,12 @@ class PlaidAccount::Investments::TransactionsProcessor SecurityNotFoundError = Class.new(StandardError) # Map Plaid investment transaction types to activity labels + # All values must be valid Transaction::ACTIVITY_LABELS PLAID_TYPE_TO_LABEL = { "buy" => "Buy", "sell" => "Sell", - "cancel" => "Cancelled", - "cash" => "Cash", + "cancel" => "Other", + "cash" => "Other", "fee" => "Fee", "transfer" => "Transfer", "dividend" => "Dividend", @@ -92,7 +93,7 @@ class PlaidAccount::Investments::TransactionsProcessor def label_from_plaid_type(transaction) plaid_type = transaction["type"]&.downcase - PLAID_TYPE_TO_LABEL[plaid_type] || plaid_type&.titleize + PLAID_TYPE_TO_LABEL[plaid_type] || "Other" end def transactions diff --git a/app/models/transaction.rb b/app/models/transaction.rb index d1f65a704..e1a86afb5 100644 --- a/app/models/transaction.rb +++ b/app/models/transaction.rb @@ -17,7 +17,7 @@ class Transaction < ApplicationRecord cc_payment: "cc_payment", # A CC payment, excluded from budget analytics (CC payments offset the sum of expense transactions) loan_payment: "loan_payment", # A payment to a Loan account, treated as an expense in budgets one_time: "one_time", # A one-time expense/income, excluded from budget analytics - investment_contribution: "investment_contribution" # Transfer to investment/crypto account, included in budget as investment expense + investment_contribution: "investment_contribution" # Transfer to investment/crypto account, excluded from budget analytics } # All valid investment activity labels (for UI dropdown) diff --git a/config/locales/views/transactions/en.yml b/config/locales/views/transactions/en.yml index 3b295b2f4..a53c28d85 100644 --- a/config/locales/views/transactions/en.yml +++ b/config/locales/views/transactions/en.yml @@ -51,25 +51,24 @@ en: withdrawal: Withdrawal exchange: Exchange other: Other - mark_recurring: Mark as Recurring - mark_recurring_subtitle: Track this as a recurring transaction. Amount variance is automatically calculated from past 6 months of similar transactions. - mark_recurring_title: Recurring Transaction - merchant_label: Merchant - name_label: Name - nature: Type - none: "(none)" - note_label: Notes - note_placeholder: Enter a note - overview: Overview - settings: Settings - tags_label: Tags - uncategorized: "(uncategorized)" - potential_duplicate_title: Possible duplicate detected - potential_duplicate_description: This pending transaction may be the same as the posted transaction below. If so, merge them to avoid double-counting. - merge_duplicate: Yes, merge them - keep_both: No, keep both loan_payment: Loan Payment - transfer: Transfer + mark_recurring: Mark as Recurring + mark_recurring_subtitle: Track this as a recurring transaction. Amount variance is automatically calculated from past 6 months of similar transactions. + mark_recurring_title: Recurring Transaction + merchant_label: Merchant + name_label: Name + nature: Type + none: "(none)" + note_label: Notes + note_placeholder: Enter a note + overview: Overview + settings: Settings + tags_label: Tags + uncategorized: "(uncategorized)" + potential_duplicate_title: Possible duplicate detected + potential_duplicate_description: This pending transaction may be the same as the posted transaction below. If so, merge them to avoid double-counting. + merge_duplicate: Yes, merge them + keep_both: No, keep both transaction: pending: Pending pending_tooltip: Pending transaction — may change when posted diff --git a/test/models/transaction_test.rb b/test/models/transaction_test.rb index 3f0f903b0..9064f6b97 100644 --- a/test/models/transaction_test.rb +++ b/test/models/transaction_test.rb @@ -41,7 +41,13 @@ class TransactionTest < ActiveSupport::TestCase assert_includes Transaction::ACTIVITY_LABELS, "Sweep In" assert_includes Transaction::ACTIVITY_LABELS, "Sweep Out" assert_includes Transaction::ACTIVITY_LABELS, "Dividend" + assert_includes Transaction::ACTIVITY_LABELS, "Reinvestment" assert_includes Transaction::ACTIVITY_LABELS, "Interest" assert_includes Transaction::ACTIVITY_LABELS, "Fee" + assert_includes Transaction::ACTIVITY_LABELS, "Transfer" + assert_includes Transaction::ACTIVITY_LABELS, "Contribution" + assert_includes Transaction::ACTIVITY_LABELS, "Withdrawal" + assert_includes Transaction::ACTIVITY_LABELS, "Exchange" + assert_includes Transaction::ACTIVITY_LABELS, "Other" end end