From 1eb6a52d53e960df872e69d6cf0f44c541044bbc Mon Sep 17 00:00:00 2001 From: Zach Gollwitzer Date: Mon, 16 Sep 2024 16:25:44 -0400 Subject: [PATCH 1/2] Add type filters to transaction search --- app/controllers/transactions_controller.rb | 5 +-- app/models/account/entry.rb | 10 +++++ .../transactions/searches/_menu.html.erb | 4 +- .../searches/filters/_badge.html.erb | 2 +- .../searches/filters/_type_filter.html.erb | 37 ++++++++++++++++++- config/routes.rb | 1 - test/system/transactions_test.rb | 3 +- 7 files changed, 52 insertions(+), 10 deletions(-) diff --git a/app/controllers/transactions_controller.rb b/app/controllers/transactions_controller.rb index 55bb8100..217e95f8 100644 --- a/app/controllers/transactions_controller.rb +++ b/app/controllers/transactions_controller.rb @@ -67,9 +67,6 @@ class TransactionsController < ApplicationController redirect_back_or_to transactions_url, notice: t(".success") end - def rules - end - private def amount @@ -93,7 +90,7 @@ class TransactionsController < ApplicationController end def search_params - params.fetch(:q, {}).permit(:start_date, :end_date, :search, accounts: [], account_ids: [], categories: [], merchants: []) + params.fetch(:q, {}).permit(:start_date, :end_date, :search, accounts: [], account_ids: [], categories: [], merchants: [], types: []) end def transaction_entry_params diff --git a/app/models/account/entry.rb b/app/models/account/entry.rb index 56754cb6..62598d05 100644 --- a/app/models/account/entry.rb +++ b/app/models/account/entry.rb @@ -148,6 +148,16 @@ class Account::Entry < ApplicationRecord query = query.where("account_entries.date >= ?", params[:start_date]) if params[:start_date].present? query = query.where("account_entries.date <= ?", params[:end_date]) if params[:end_date].present? + if params[:types].present? + query = query.where(marked_as_transfer: false) unless params[:types].include?("transfer") + + if params[:types].include?("income") && !params[:types].include?("expense") + query = query.where("account_entries.amount < 0") + elsif params[:types].include?("expense") && !params[:types].include?("income") + query = query.where("account_entries.amount >= 0") + end + end + if params[:accounts].present? || params[:account_ids].present? query = query.joins(:account) end diff --git a/app/views/transactions/searches/_menu.html.erb b/app/views/transactions/searches/_menu.html.erb index 2964ea1d..35cb482d 100644 --- a/app/views/transactions/searches/_menu.html.erb +++ b/app/views/transactions/searches/_menu.html.erb @@ -1,3 +1,5 @@ +<%# locals: (form:) %> +
-
+
<% transaction_search_filters.each do |filter| %>
<%= render partial: get_transaction_search_filter_partial_path(filter), locals: { form: form } %> diff --git a/app/views/transactions/searches/filters/_badge.html.erb b/app/views/transactions/searches/filters/_badge.html.erb index 14f1bf64..192e64aa 100644 --- a/app/views/transactions/searches/filters/_badge.html.erb +++ b/app/views/transactions/searches/filters/_badge.html.erb @@ -24,7 +24,7 @@
<% else %>
-

<%= param_value %>

+

<%= param_value.titleize %>

<% end %> diff --git a/app/views/transactions/searches/filters/_type_filter.html.erb b/app/views/transactions/searches/filters/_type_filter.html.erb index a273a374..671ef495 100644 --- a/app/views/transactions/searches/filters/_type_filter.html.erb +++ b/app/views/transactions/searches/filters/_type_filter.html.erb @@ -1,4 +1,37 @@ <%# locals: (form:) %> -
-

Filter by type coming soon...

+ +
+
+ <%= form.check_box :types, + { + multiple: true, + checked: @q[:types]&.include?('income'), + class: "maybe-checkbox maybe-checkbox--light" + }, + 'income', + nil %> + <%= form.label :types, 'Income', value: 'income', class: "text-sm text-gray-900" %> +
+
+ <%= form.check_box :types, + { + multiple: true, + checked: @q[:types]&.include?('expense'), + class: "maybe-checkbox maybe-checkbox--light" + }, + 'expense', + nil %> + <%= form.label :types, 'Expense', value: 'expense', class: "text-sm text-gray-900" %> +
+
+ <%= form.check_box :types, + { + multiple: true, + checked: @q[:types]&.include?('transfer'), + class: "maybe-checkbox maybe-checkbox--light" + }, + 'transfer', + nil %> + <%= form.label :types, 'Transfer', value: 'transfer', class: "text-sm text-gray-900" %> +
diff --git a/config/routes.rb b/config/routes.rb index 13469d26..2dfcd4da 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -91,7 +91,6 @@ Rails.application.routes.draw do post "bulk_update" post "mark_transfers" post "unmark_transfers" - get "rules" end end diff --git a/test/system/transactions_test.rb b/test/system/transactions_test.rb index 8b31372b..eac2902c 100644 --- a/test/system/transactions_test.rb +++ b/test/system/transactions_test.rb @@ -77,7 +77,7 @@ class TransactionsTest < ApplicationSystemTestCase fill_in "q_end_date", with: 1.day.ago.to_date click_button "Type" - assert_text "Filter by type coming soon..." + check("Income") click_button "Amount" assert_text "Filter by amount coming soon..." @@ -102,6 +102,7 @@ class TransactionsTest < ApplicationSystemTestCase find("li", text: account.name).first("a").click find("li", text: "on or after #{10.days.ago.to_date}").first("a").click find("li", text: "on or before #{1.day.ago.to_date}").first("a").click + find("li", text: "Income").first("a").click find("li", text: category.name).first("a").click find("li", text: merchant.name).first("a").click end -- 2.53.0 From 6c12589cef6b3157f637125c4027f8da9c6fbb30 Mon Sep 17 00:00:00 2001 From: Zach Gollwitzer Date: Mon, 16 Sep 2024 18:13:26 -0400 Subject: [PATCH 2/2] Add amount filter --- app/controllers/transactions_controller.rb | 3 +- app/helpers/transactions_helper.rb | 12 +++---- app/models/account/entry.rb | 11 +++++++ .../transactions/searches/_menu.html.erb | 21 +++++++++---- .../transactions/searches/_search.html.erb | 20 ++++++++++-- .../searches/filters/_amount_filter.html.erb | 15 +++++++-- .../searches/filters/_badge.html.erb | 21 ++++++++++--- .../searches/filters/_type_filter.html.erb | 18 +++++------ config/locales/views/transactions/en.yml | 31 +++++++++++++++++++ test/system/transactions_test.rb | 4 ++- 10 files changed, 124 insertions(+), 32 deletions(-) diff --git a/app/controllers/transactions_controller.rb b/app/controllers/transactions_controller.rb index 217e95f8..accdeab3 100644 --- a/app/controllers/transactions_controller.rb +++ b/app/controllers/transactions_controller.rb @@ -90,7 +90,8 @@ class TransactionsController < ApplicationController end def search_params - params.fetch(:q, {}).permit(:start_date, :end_date, :search, accounts: [], account_ids: [], categories: [], merchants: [], types: []) + params.fetch(:q, {}) + .permit(:start_date, :end_date, :search, :amount, :amount_operator, accounts: [], account_ids: [], categories: [], merchants: [], types: []) end def transaction_entry_params diff --git a/app/helpers/transactions_helper.rb b/app/helpers/transactions_helper.rb index eab4bce1..23bbede6 100644 --- a/app/helpers/transactions_helper.rb +++ b/app/helpers/transactions_helper.rb @@ -1,12 +1,12 @@ module TransactionsHelper def transaction_search_filters [ - { key: "account_filter", name: "Account", icon: "layers" }, - { key: "date_filter", name: "Date", icon: "calendar" }, - { key: "type_filter", name: "Type", icon: "shapes" }, - { key: "amount_filter", name: "Amount", icon: "hash" }, - { key: "category_filter", name: "Category", icon: "tag" }, - { key: "merchant_filter", name: "Merchant", icon: "store" } + { key: "account_filter", icon: "layers" }, + { key: "date_filter", icon: "calendar" }, + { key: "type_filter", icon: "shapes" }, + { key: "amount_filter", icon: "hash" }, + { key: "category_filter", icon: "tag" }, + { key: "merchant_filter", icon: "store" } ] end diff --git a/app/models/account/entry.rb b/app/models/account/entry.rb index 62598d05..9bedbab0 100644 --- a/app/models/account/entry.rb +++ b/app/models/account/entry.rb @@ -158,6 +158,17 @@ class Account::Entry < ApplicationRecord end end + if params[:amount].present? && params[:amount_operator].present? + case params[:amount_operator] + when "equal" + query = query.where("ABS(ABS(account_entries.amount) - ?) <= 0.01", params[:amount].to_f.abs) + when "less" + query = query.where("ABS(account_entries.amount) < ?", params[:amount].to_f.abs) + when "greater" + query = query.where("ABS(account_entries.amount) > ?", params[:amount].to_f.abs) + end + end + if params[:accounts].present? || params[:account_ids].present? query = query.joins(:account) end diff --git a/app/views/transactions/searches/_menu.html.erb b/app/views/transactions/searches/_menu.html.erb index 35cb482d..d474ca55 100644 --- a/app/views/transactions/searches/_menu.html.erb +++ b/app/views/transactions/searches/_menu.html.erb @@ -16,7 +16,7 @@ data-tabs-target="btn" data-action="tabs#select"> <%= lucide_icon(filter[:icon], class: "w-5 h-5") %> - <%= filter[:name] %> + <%= t(".#{filter[:key]}") %> <% end %>
@@ -29,11 +29,20 @@
<% end %>
-
- <%= button_tag type: "reset", data: { action: "menu#close" }, class: "py-2 px-3 bg-gray-50 rounded-lg text-sm text-gray-900 font-medium" do %> - Cancel - <% end %> - <%= form.submit "Apply", name: nil, class: "py-2 px-3 bg-gray-900 hover:bg-gray-700 rounded-lg text-sm text-white font-medium cursor-pointer" %> + +
+
+ <% if @q.present? %> + <%= link_to t(".clear_filters"), transactions_path, class: "text-sm underline text-gray-500" %> + <% end %> +
+ +
+ <%= button_tag type: "reset", data: { action: "menu#close" }, class: "py-2 px-3 bg-gray-50 rounded-lg text-sm text-gray-900 font-medium" do %> + <%= t(".cancel") %> + <% end %> + <%= form.submit t(".apply"), name: nil, class: "py-2 px-3 bg-gray-900 hover:bg-gray-700 rounded-lg text-sm text-white font-medium cursor-pointer" %> +
diff --git a/app/views/transactions/searches/_search.html.erb b/app/views/transactions/searches/_search.html.erb index 506444ea..0108d95a 100644 --- a/app/views/transactions/searches/_search.html.erb +++ b/app/views/transactions/searches/_search.html.erb @@ -1,10 +1,24 @@ <%= render "transactions/searches/form" %>
<%= form.check_box :types, { multiple: true, - checked: @q[:types]&.include?('expense'), + checked: @q[:types]&.include?("expense"), class: "maybe-checkbox maybe-checkbox--light" }, - 'expense', + "expense", nil %> - <%= form.label :types, 'Expense', value: 'expense', class: "text-sm text-gray-900" %> + <%= form.label :types, t(".expense"), value: "expense", class: "text-sm text-gray-900" %>
<%= form.check_box :types, { multiple: true, - checked: @q[:types]&.include?('transfer'), + checked: @q[:types]&.include?("transfer"), class: "maybe-checkbox maybe-checkbox--light" }, - 'transfer', + "transfer", nil %> - <%= form.label :types, 'Transfer', value: 'transfer', class: "text-sm text-gray-900" %> + <%= form.label :types, t(".transfer"), value: "transfer", class: "text-sm text-gray-900" %>
diff --git a/config/locales/views/transactions/en.yml b/config/locales/views/transactions/en.yml index 6b9490c5..5089fad5 100644 --- a/config/locales/views/transactions/en.yml +++ b/config/locales/views/transactions/en.yml @@ -44,5 +44,36 @@ en: success: Marked as transfer new: new_transaction: New transaction + searches: + filters: + amount_filter: + equal_to: Equal to + greater_than: Greater than + less_than: Less than + placeholder: '0' + badge: + expense: Expense + income: Income + on_or_after: on or after %{date} + on_or_before: on or before %{date} + transfer: Transfer + type_filter: + expense: Expense + income: Income + transfer: Transfer + menu: + account_filter: Account + amount_filter: Amount + apply: Apply + cancel: Cancel + category_filter: Category + clear_filters: Clear filters + date_filter: Date + merchant_filter: Merchant + type_filter: Type + search: + equal_to: equal to + greater_than: greater than + less_than: less than unmark_transfers: success: Transfer removed diff --git a/test/system/transactions_test.rb b/test/system/transactions_test.rb index eac2902c..4544c6c4 100644 --- a/test/system/transactions_test.rb +++ b/test/system/transactions_test.rb @@ -80,7 +80,8 @@ class TransactionsTest < ApplicationSystemTestCase check("Income") click_button "Amount" - assert_text "Filter by amount coming soon..." + select "Less than" + fill_in "q_amount", with: 200 click_button "Category" check(category.name) @@ -103,6 +104,7 @@ class TransactionsTest < ApplicationSystemTestCase find("li", text: "on or after #{10.days.ago.to_date}").first("a").click find("li", text: "on or before #{1.day.ago.to_date}").first("a").click find("li", text: "Income").first("a").click + find("li", text: "less than 200").first("a").click find("li", text: category.name).first("a").click find("li", text: merchant.name).first("a").click end -- 2.53.0