diff --git a/app/controllers/account/entries_controller.rb b/app/controllers/account/entries_controller.rb index fb02ffa8..fb394f2d 100644 --- a/app/controllers/account/entries_controller.rb +++ b/app/controllers/account/entries_controller.rb @@ -25,7 +25,7 @@ class Account::EntriesController < ApplicationController def destroy @entry.destroy! @entry.sync_account_later - redirect_back_or_to account_url(@entry.account), notice: t(".success") + redirect_to account_url(@entry.account), notice: t(".success") end private diff --git a/app/controllers/account/holdings_controller.rb b/app/controllers/account/holdings_controller.rb index 14e7e9ff..af0d3e6a 100644 --- a/app/controllers/account/holdings_controller.rb +++ b/app/controllers/account/holdings_controller.rb @@ -2,7 +2,7 @@ class Account::HoldingsController < ApplicationController layout :with_sidebar before_action :set_account - before_action :set_holding, only: :show + before_action :set_holding, only: %i[show destroy] def index @holdings = @account.holdings.current @@ -11,6 +11,11 @@ class Account::HoldingsController < ApplicationController def show end + def destroy + @holding.destroy_holding_and_entries! + redirect_back_or_to account_holdings_path(@account) + end + private def set_account diff --git a/app/controllers/account/trades_controller.rb b/app/controllers/account/trades_controller.rb index 26f370e7..b5b6092a 100644 --- a/app/controllers/account/trades_controller.rb +++ b/app/controllers/account/trades_controller.rb @@ -2,6 +2,7 @@ class Account::TradesController < ApplicationController layout :with_sidebar before_action :set_account + before_action :set_entry, only: :update def new @entry = @account.entries.account_trades.new(entryable_attributes: {}) @@ -23,15 +24,36 @@ class Account::TradesController < ApplicationController end end + def update + @entry.update!(entry_params) + + respond_to do |format| + format.html { redirect_to account_entry_path(@account, @entry), notice: t(".success") } + format.turbo_stream { render turbo_stream: turbo_stream.replace(@entry) } + end + end + private def set_account @account = Current.family.accounts.find(params[:account_id]) end + def set_entry + @entry = @account.entries.find(params[:id]) + end + def entry_params params.require(:account_entry) - .permit(:type, :date, :qty, :ticker, :price, :amount, :currency, :transfer_account_id) + .permit( + :type, :date, :qty, :ticker, :price, :amount, :notes, :excluded, :currency, :transfer_account_id, :entryable_type, + entryable_attributes: [ + :id, + :qty, + :ticker, + :price + ] + ) .merge(account: @account) end end diff --git a/app/controllers/account/transactions_controller.rb b/app/controllers/account/transactions_controller.rb index 0a0d88a2..2e3073e6 100644 --- a/app/controllers/account/transactions_controller.rb +++ b/app/controllers/account/transactions_controller.rb @@ -33,11 +33,9 @@ class Account::TransactionsController < ApplicationController def entry_params params.require(:account_entry) .permit( - :name, :date, :amount, :currency, :entryable_type, :nature, + :name, :date, :amount, :currency, :excluded, :notes, :entryable_type, :nature, entryable_attributes: [ :id, - :notes, - :excluded, :category_id, :merchant_id, { tag_ids: [] } diff --git a/app/helpers/styled_form_builder.rb b/app/helpers/styled_form_builder.rb index e9e27538..885509d6 100644 --- a/app/helpers/styled_form_builder.rb +++ b/app/helpers/styled_form_builder.rb @@ -39,11 +39,11 @@ class StyledFormBuilder < ActionView::Helpers::FormBuilder build_styled_field(label, field, options, remove_padding_right: true) end - def money_field(amount_method, currency_method, options = {}) + def money_field(amount_method, options = {}) @template.render partial: "shared/money_field", locals: { form: self, amount_method:, - currency_method:, + currency_method: options[:currency_method] || :currency, **options } end diff --git a/app/models/account/entry.rb b/app/models/account/entry.rb index 4c38ffbd..a789dcb0 100644 --- a/app/models/account/entry.rb +++ b/app/models/account/entry.rb @@ -109,8 +109,8 @@ class Account::Entry < ApplicationRecord def bulk_update!(bulk_update_params) bulk_attributes = { date: bulk_update_params[:date], + notes: bulk_update_params[:notes], entryable_attributes: { - notes: bulk_update_params[:notes], category_id: bulk_update_params[:category_id], merchant_id: bulk_update_params[:merchant_id] }.compact_blank diff --git a/app/models/account/holding.rb b/app/models/account/holding.rb index 34f6efe7..819cd5b2 100644 --- a/app/models/account/holding.rb +++ b/app/models/account/holding.rb @@ -37,6 +37,19 @@ class Account::Holding < ApplicationRecord @trend ||= calculate_trend end + def trades + account.entries.where(entryable: account.trades.where(security: security)).reverse_chronological + end + + def destroy_holding_and_entries! + transaction do + account.entries.where(entryable: account.trades.where(security: security)).destroy_all + destroy + end + + account.sync_later + end + private def calculate_trend diff --git a/app/models/account/trade.rb b/app/models/account/trade.rb index c6232b21..a594ee16 100644 --- a/app/models/account/trade.rb +++ b/app/models/account/trade.rb @@ -25,4 +25,15 @@ class Account::Trade < ApplicationRecord def buy? qty > 0 end + + def unrealized_gain_loss + return nil if sell? + current_price = security.current_price + return nil if current_price.nil? + + current_value = current_price * qty.abs + cost_basis = price_money * qty.abs + + TimeSeries::Trend.new(current: current_value, previous: cost_basis) + end end diff --git a/app/models/mint_import.rb b/app/models/mint_import.rb index 1d5c1ee6..66e3bb69 100644 --- a/app/models/mint_import.rb +++ b/app/models/mint_import.rb @@ -34,7 +34,8 @@ class MintImport < Import amount: row.signed_amount, name: row.name, currency: row.currency, - entryable: Account::Transaction.new(category: category, tags: tags, notes: row.notes), + notes: row.notes, + entryable: Account::Transaction.new(category: category, tags: tags), import: self entry.save! diff --git a/app/models/security.rb b/app/models/security.rb index 03d07bcf..784d0b68 100644 --- a/app/models/security.rb +++ b/app/models/security.rb @@ -5,6 +5,12 @@ class Security < ApplicationRecord validates :ticker, presence: true, uniqueness: { case_sensitive: false } + def current_price + @current_price ||= Security::Price.find_price(ticker:, date: Date.current) + return nil if @current_price.nil? + Money.new(@current_price.price, @current_price.currency) + end + private def upcase_ticker diff --git a/app/models/transaction_import.rb b/app/models/transaction_import.rb index 7e8cc4fb..e2b1c3d6 100644 --- a/app/models/transaction_import.rb +++ b/app/models/transaction_import.rb @@ -13,7 +13,8 @@ class TransactionImport < Import amount: row.signed_amount, name: row.name, currency: row.currency, - entryable: Account::Transaction.new(category: category, tags: tags, notes: row.notes), + notes: row.notes, + entryable: Account::Transaction.new(category: category, tags: tags), import: self entry.save! diff --git a/app/views/account/holdings/show.html.erb b/app/views/account/holdings/show.html.erb index 36412913..89328378 100644 --- a/app/views/account/holdings/show.html.erb +++ b/app/views/account/holdings/show.html.erb @@ -9,36 +9,103 @@ <%= render "shared/circle_logo", name: @holding.name %> -
+

<%= t(".overview") %>

<%= lucide_icon "chevron-down", class: "group-open:transform group-open:rotate-180 text-gray-500 w-5" %>
-
-

Coming soon...

+
+
+
+
<%= t(".ticker_label") %>
+
<%= @holding.ticker %>
+
+ +
+
<%= t(".current_market_price_label") %>
+
<%= @holding.security.current_price ? format_money(@holding.security.current_price) : t(".unknown") %>
+
+ +
+
<%= t(".portfolio_weight_label") %>
+
<%= @holding.weight ? number_to_percentage(@holding.weight, precision: 2) : t(".unknown") %>
+
+ +
+
<%= t(".avg_cost_label") %>
+
<%= @holding.avg_cost ? format_money(@holding.avg_cost) : t(".unknown") %>
+
+ +
+
<%= t(".trend_label") %>
+
+ <%= @holding.trend ? render("shared/trend_change", trend: @holding.trend) : t(".unknown") %> +
+
+
-
+

<%= t(".history") %>

<%= lucide_icon "chevron-down", class: "group-open:transform group-open:rotate-180 text-gray-500 w-5" %>
-
-

Coming soon...

+
+
+ <% if @holding.trades.any? %> +
    + <% @holding.trades.each_with_index do |trade_entry, index| %> +
  • +
    +
    + <% unless index == @holding.trades.length - 1 %> +
    + <% end %> +
    + +
    +

    <%= l(trade_entry.date, format: :long) %>

    + +

    <%= t( + ".trade_history_entry", + qty: trade_entry.account_trade.qty, + security: trade_entry.account_trade.security.ticker, + price: format_money(trade_entry.account_trade.price) + ) %>

    +
    +
  • + <% end %> +
+ + <% else %> +

No trade history available for this holding.

+ <% end %> +
-
+

<%= t(".settings") %>

<%= lucide_icon "chevron-down", class: "group-open:transform group-open:rotate-180 text-gray-500 w-5" %>
-
-

Coming soon...

+
+
+
+

<%= t(".delete_title") %>

+

<%= t(".delete_subtitle") %>

+
+ + <%= button_to t(".delete"), + account_holding_path(@holding.account, @holding), + method: :delete, + class: "rounded-lg px-3 py-2 text-red-500 text-sm font-medium border border-alpha-black-200", + data: { turbo_confirm: true, turbo_frame: "_top" } %> +
diff --git a/app/views/account/trades/_form.html.erb b/app/views/account/trades/_form.html.erb index 2e6e7881..e39c7b15 100644 --- a/app/views/account/trades/_form.html.erb +++ b/app/views/account/trades/_form.html.erb @@ -13,7 +13,7 @@ <%= form.date_field :date, label: true %>
- <%= form.money_field :price, :currency, label: t(".price"), disable_currency: true %> + <%= form.money_field :price, label: t(".price"), disable_currency: true %>
diff --git a/app/views/account/trades/show.html.erb b/app/views/account/trades/show.html.erb index 1bbea909..7293f731 100644 --- a/app/views/account/trades/show.html.erb +++ b/app/views/account/trades/show.html.erb @@ -1,29 +1,146 @@ -<% entry = @entry %> +<% entry, trade, account = @entry, @entry.account_trade, @entry.account %> <%= drawer do %> -
-
-
-

- <%= format_money -entry.amount_money %> - <%= entry.currency %> -

-
+
+
+

+ + <%= format_money -entry.amount_money %> + - <%= entry.date.strftime("%A %d %B") %> -

- -
-
- -

<%= t(".overview") %>

- <%= lucide_icon "chevron-down", class: "group-open:transform group-open:rotate-180 text-gray-500 w-5" %> -
- -
-

Details coming soon...

-
-
+ + <%= entry.currency %> + +
+ + + <%= I18n.l(entry.date, format: :long) %> + +
+ +
+ + <%= disclosure t(".overview") do %> +
+
+
+
<%= t(".symbol_label") %>
+
<%= trade.security.ticker %>
+
+ + <% if trade.buy? %> +
+
<%= t(".purchase_qty_label") %>
+
<%= trade.qty.abs %>
+
+ +
+
<%= t(".purchase_price_label") %>
+
<%= format_money trade.price_money %>
+
+ <% end %> + +
+
<%= t(".current_market_price_label") %>
+
<%= format_money trade.security.current_price %>
+
+ + <% if trade.buy? %> +
+
<%= t(".total_return_label") %>
+
+ <%= render "shared/trend_change", trend: trade.unrealized_gain_loss %> +
+
+ <% end %> +
+
+ <% end %> + + + <%= disclosure t(".details") do %> +
+ <%= styled_form_with model: [account, entry], + url: account_trade_path(account, entry), + class: "space-y-2", + data: { controller: "auto-submit-form" } do |f| %> + <%= f.date_field :date, + label: t(".date_label"), + max: Date.current, + "data-auto-submit-form-target": "auto" %> + + <%= f.fields_for :entryable do |ef| %> + <%= ef.number_field :qty, + label: t(".quantity_label"), + step: "any", + "data-auto-submit-form-target": "auto" %> + + <%= ef.money_field :price, + label: t(".cost_per_share_label"), + disable_currency: true, + auto_submit: true, + min: 0 %> + <% end %> + <% end %> +
+ <% end %> + + + <%= disclosure t(".additional") do %> +
+ <%= styled_form_with model: [account, entry], + url: account_trade_path(account, entry), + class: "space-y-2", + data: { controller: "auto-submit-form" } do |f| %> + <%= f.text_area :notes, + label: t(".note_label"), + placeholder: t(".note_placeholder"), + rows: 5, + "data-auto-submit-form-target": "auto" %> + <% end %> +
+ <% end %> + + + <%= disclosure t(".settings") do %> +
+ + <%= styled_form_with model: [account, entry], + url: account_trade_path(account, entry), + class: "p-3", + data: { controller: "auto-submit-form" } do |f| %> +
+
+

<%= t(".exclude_title") %>

+

<%= t(".exclude_subtitle") %>

+
+ +
+ <%= f.check_box :excluded, + class: "sr-only peer", + "data-auto-submit-form-target": "auto" %> + +
+
+ <% end %> + + +
+
+

<%= t(".delete_title") %>

+

<%= t(".delete_subtitle") %>

+
+ + <%= button_to t(".delete"), + account_entry_path(account, entry), + method: :delete, + class: "rounded-lg px-3 py-2 text-red-500 text-sm + font-medium border border-alpha-black-200", + data: { turbo_confirm: true, turbo_frame: "_top" } %> +
+
+ <% end %>
<% end %> diff --git a/app/views/account/transactions/show.html.erb b/app/views/account/transactions/show.html.erb index 6b08a663..ecf22131 100644 --- a/app/views/account/transactions/show.html.erb +++ b/app/views/account/transactions/show.html.erb @@ -47,7 +47,7 @@ { container_class: "w-1/3", label: t(".nature"), selected: entry.amount.negative? ? "income" : "expense" }, { data: { "auto-submit-form-target": "auto" } } %> - <%= f.money_field :amount, :currency, label: t(".amount"), + <%= f.money_field :amount, label: t(".amount"), container_class: "w-2/3", auto_submit: true, min: 0, @@ -104,7 +104,13 @@ }, { "data-auto-submit-form-target": "auto" } %> - <%= ef.text_area :notes, + <% end %> + + <%= styled_form_with model: [account, entry], + url: account_transaction_path(account, entry), + class: "space-y-2", + data: { controller: "auto-submit-form" } do |f| %> + <%= f.text_area :notes, label: t(".note_label"), placeholder: t(".note_placeholder"), rows: 5, @@ -122,22 +128,20 @@ url: account_transaction_path(account, entry), class: "p-3", data: { controller: "auto-submit-form" } do |f| %> - <%= f.fields_for :entryable do |ef| %> -
-
-

<%= t(".exclude_title") %>

-

<%= t(".exclude_subtitle") %>

-
+
+
+

<%= t(".exclude_title") %>

+

<%= t(".exclude_subtitle") %>

+
-
- <%= ef.check_box :excluded, +
+ <%= f.check_box :excluded, class: "sr-only peer", "data-auto-submit-form-target": "auto" %> - -
- <% end %> +
<% end %> diff --git a/app/views/account/transfers/_form.html.erb b/app/views/account/transfers/_form.html.erb index 7fc42d13..61fb9350 100644 --- a/app/views/account/transfers/_form.html.erb +++ b/app/views/account/transfers/_form.html.erb @@ -29,7 +29,7 @@ <%= f.text_field :name, value: transfer.name, label: t(".description"), placeholder: t(".description_placeholder"), required: true %> <%= f.collection_select :from_account_id, Current.family.accounts.alphabetically, :id, :name, { prompt: t(".select_account"), label: t(".from") }, required: true %> <%= f.collection_select :to_account_id, Current.family.accounts.alphabetically, :id, :name, { prompt: t(".select_account"), label: t(".to") }, required: true %> - <%= f.money_field :amount, :currency, label: t(".amount"), required: true, hide_currency: true %> + <%= f.money_field :amount, label: t(".amount"), required: true, hide_currency: true %> <%= f.date_field :date, value: transfer.date, label: t(".date"), required: true, max: Date.current %> diff --git a/app/views/accounts/_form.html.erb b/app/views/accounts/_form.html.erb index b1b157a5..af7c6033 100644 --- a/app/views/accounts/_form.html.erb +++ b/app/views/accounts/_form.html.erb @@ -5,7 +5,7 @@ <%= f.hidden_field :accountable_type %> <%= f.text_field :name, placeholder: t(".name_placeholder"), required: "required", label: t(".name_label"), autofocus: true %> <%= f.collection_select :institution_id, Current.family.institutions.alphabetically, :id, :name, { include_blank: t(".ungrouped"), label: t(".institution") } %> - <%= f.money_field :balance, :currency, label: t(".balance"), required: true, default_currency: Current.family.currency %> + <%= f.money_field :balance, label: t(".balance"), required: true, default_currency: Current.family.currency %> <% if account.new_record? %>
diff --git a/app/views/transactions/_form.html.erb b/app/views/transactions/_form.html.erb index cb761218..fd66fb67 100644 --- a/app/views/transactions/_form.html.erb +++ b/app/views/transactions/_form.html.erb @@ -13,7 +13,7 @@
<%= f.text_field :name, label: t(".description"), placeholder: t(".description_placeholder"), required: true %> <%= f.collection_select :account_id, Current.family.accounts.alphabetically, :id, :name, { prompt: t(".account_prompt"), label: t(".account") }, required: true %> - <%= f.money_field :amount, :currency, label: t(".amount"), required: true %> + <%= f.money_field :amount, label: t(".amount"), required: true %> <%= f.hidden_field :entryable_type, value: "Account::Transaction" %> <%= f.fields_for :entryable do |ef| %> <%= ef.collection_select :category_id, Current.family.categories.alphabetically, :id, :name, { prompt: t(".category_prompt"), label: t(".category") } %> diff --git a/config/locales/views/account/holdings/en.yml b/config/locales/views/account/holdings/en.yml index 500bdd87..ad5eafac 100644 --- a/config/locales/views/account/holdings/en.yml +++ b/config/locales/views/account/holdings/en.yml @@ -20,6 +20,17 @@ en: its returns or value. missing_data: Missing data show: + avg_cost_label: Average Cost + current_market_price_label: Current Market Price + delete: Delete + delete_subtitle: This will delete the holding and all your associated trades + on this account. This action cannot be undone. + delete_title: Delete holding history: History overview: Overview + portfolio_weight_label: Portfolio Weight settings: Settings + ticker_label: Ticker + trade_history_entry: "%{qty} shares of %{security} at %{price}" + trend_label: Trend + unknown: Unknown diff --git a/config/locales/views/account/trades/en.yml b/config/locales/views/account/trades/en.yml index bfd920bb..0db9db32 100644 --- a/config/locales/views/account/trades/en.yml +++ b/config/locales/views/account/trades/en.yml @@ -25,7 +25,25 @@ en: new: title: New transaction show: + additional: Additional + cost_per_share_label: Cost per Share + current_market_price_label: Current Market Price + date_label: Date + delete: Delete + delete_subtitle: This action cannot be undone + delete_title: Delete Trade + details: Details + exclude_subtitle: This trade will not be included in reports and calculations + exclude_title: Exclude from analytics + note_label: Note + note_placeholder: Add any additional notes here... overview: Overview + purchase_price_label: Purchase Price + purchase_qty_label: Purchase Quantity + quantity_label: Quantity + settings: Settings + symbol_label: Symbol + total_return_label: Unrealized gain/loss trade: buy: Buy deposit: Deposit @@ -33,3 +51,5 @@ en: outflow: Outflow sell: Sell withdrawal: Withdrawal + update: + success: Trade updated successfully. diff --git a/config/routes.rb b/config/routes.rb index d6ec8b7c..9a84ce22 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -63,12 +63,12 @@ Rails.application.routes.draw do scope module: :account do resource :logo, only: :show - resources :holdings, only: %i[index new show] + resources :holdings, only: %i[index new show destroy] resources :cashes, only: :index resources :transactions, only: %i[index update] resources :valuations, only: %i[index new create] - resources :trades, only: %i[index new create] + resources :trades, only: %i[index new create update] resources :entries, only: %i[edit update show destroy] end diff --git a/db/migrate/20241009132959_add_notes_to_entry.rb b/db/migrate/20241009132959_add_notes_to_entry.rb new file mode 100644 index 00000000..8523e40d --- /dev/null +++ b/db/migrate/20241009132959_add_notes_to_entry.rb @@ -0,0 +1,33 @@ +class AddNotesToEntry < ActiveRecord::Migration[7.2] + def change + add_column :account_entries, :notes, :text + add_column :account_entries, :excluded, :boolean, default: false + + reversible do |dir| + dir.up do + execute <<-SQL + UPDATE account_entries + SET notes = account_transactions.notes, + excluded = account_transactions.excluded + FROM account_transactions + WHERE account_entries.entryable_type = 'Account::Transaction' + AND account_entries.entryable_id = account_transactions.id + SQL + end + + dir.down do + execute <<-SQL + UPDATE account_transactions + SET notes = account_entries.notes, + excluded = account_entries.excluded + FROM account_entries + WHERE account_entries.entryable_type = 'Account::Transaction' + AND account_entries.entryable_id = account_transactions.id + SQL + end + end + + remove_column :account_transactions, :notes, :text + remove_column :account_transactions, :excluded, :boolean + end +end diff --git a/db/schema.rb b/db/schema.rb index 7e5e7c12..d58dcce0 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2024_10_08_122449) do +ActiveRecord::Schema[7.2].define(version: 2024_10_09_132959) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -45,6 +45,8 @@ ActiveRecord::Schema[7.2].define(version: 2024_10_08_122449) do t.uuid "transfer_id" t.boolean "marked_as_transfer", default: false, null: false t.uuid "import_id" + t.text "notes" + t.boolean "excluded", default: false t.index ["account_id"], name: "index_account_entries_on_account_id" t.index ["import_id"], name: "index_account_entries_on_import_id" t.index ["transfer_id"], name: "index_account_entries_on_transfer_id" @@ -90,8 +92,6 @@ ActiveRecord::Schema[7.2].define(version: 2024_10_08_122449) do t.datetime "created_at", null: false t.datetime "updated_at", null: false t.uuid "category_id" - t.boolean "excluded", default: false - t.text "notes" t.uuid "merchant_id" t.index ["category_id"], name: "index_account_transactions_on_category_id" t.index ["merchant_id"], name: "index_account_transactions_on_merchant_id" @@ -120,7 +120,7 @@ ActiveRecord::Schema[7.2].define(version: 2024_10_08_122449) do t.boolean "is_active", default: true, null: false t.date "last_sync_date" t.uuid "institution_id" - t.virtual "classification", type: :string, as: "\nCASE\n WHEN ((accountable_type)::text = ANY (ARRAY[('Loan'::character varying)::text, ('CreditCard'::character varying)::text, ('OtherLiability'::character varying)::text])) THEN 'liability'::text\n ELSE 'asset'::text\nEND", stored: true + t.virtual "classification", type: :string, as: "\nCASE\n WHEN ((accountable_type)::text = ANY ((ARRAY['Loan'::character varying, 'CreditCard'::character varying, 'OtherLiability'::character varying])::text[])) THEN 'liability'::text\n ELSE 'asset'::text\nEND", stored: true t.uuid "import_id" t.index ["accountable_type"], name: "index_accounts_on_accountable_type" t.index ["family_id"], name: "index_accounts_on_family_id" diff --git a/test/controllers/account/holdings_controller_test.rb b/test/controllers/account/holdings_controller_test.rb index c1b8bb2e..3a556908 100644 --- a/test/controllers/account/holdings_controller_test.rb +++ b/test/controllers/account/holdings_controller_test.rb @@ -17,4 +17,14 @@ class Account::HoldingsControllerTest < ActionDispatch::IntegrationTest assert_response :success end + + test "destroys holding and associated entries" do + assert_difference -> { Account::Holding.count } => -1, + -> { Account::Entry.count } => -1 do + delete account_holding_path(@account, @holding) + end + + assert_redirected_to account_holdings_path(@account) + assert_empty @account.entries.where(entryable: @account.trades.where(security: @holding.security)) + end end diff --git a/test/controllers/transactions_controller_test.rb b/test/controllers/transactions_controller_test.rb index 9dd63d37..09b31910 100644 --- a/test/controllers/transactions_controller_test.rb +++ b/test/controllers/transactions_controller_test.rb @@ -174,7 +174,7 @@ class TransactionsControllerTest < ActionDispatch::IntegrationTest assert_equal 1.day.ago.to_date, transaction.date assert_equal Category.second, transaction.account_transaction.category assert_equal Merchant.second, transaction.account_transaction.merchant - assert_equal "Updated note", transaction.account_transaction.notes + assert_equal "Updated note", transaction.notes end end end