From 4e5b0957bff914bc3264e0fca4975a0e8749621a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 23 Nov 2025 10:45:52 +0000 Subject: [PATCH] Add validation and flash message for invalid date range in Reports Co-authored-by: jjmata <187772+jjmata@users.noreply.github.com> --- app/controllers/reports_controller.rb | 13 ++++++++ app/views/reports/index.html.erb | 7 +++++ config/locales/views/reports/en.yml | 1 + test/controllers/reports_controller_test.rb | 35 +++++++++++++++++++++ 4 files changed, 56 insertions(+) diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb index 57791639a..724b0b789 100644 --- a/app/controllers/reports_controller.rb +++ b/app/controllers/reports_controller.rb @@ -11,6 +11,13 @@ class ReportsController < ApplicationController @start_date = parse_date_param(:start_date) || default_start_date @end_date = parse_date_param(:end_date) || default_end_date + # Validate and fix date range if end_date is before start_date + if @start_date > @end_date + # Swap the dates to maintain user's intended date range + @start_date, @end_date = @end_date, @start_date + flash.now[:alert] = t("reports.invalid_date_range") + end + # Build the period @period = Period.custom(start_date: @start_date, end_date: @end_date) @previous_period = build_previous_period @@ -41,6 +48,12 @@ class ReportsController < ApplicationController @period_type = params[:period_type]&.to_sym || :monthly @start_date = parse_date_param(:start_date) || default_start_date @end_date = parse_date_param(:end_date) || default_end_date + + # Validate and fix date range if end_date is before start_date + if @start_date > @end_date + @start_date, @end_date = @end_date, @start_date + end + @period = Period.custom(start_date: @start_date, end_date: @end_date) # Build monthly breakdown data for export diff --git a/app/views/reports/index.html.erb b/app/views/reports/index.html.erb index 0ad469bec..13fd9d1fc 100644 --- a/app/views/reports/index.html.erb +++ b/app/views/reports/index.html.erb @@ -9,6 +9,13 @@

+ <%# Flash messages %> + <% if flash[:alert].present? %> +
+ <%= flash[:alert] %> +
+ <% end %> + <%# Period Navigation Tabs %>
<%= render DS::Link.new( diff --git a/config/locales/views/reports/en.yml b/config/locales/views/reports/en.yml index 87dd04b9a..b09c5b97d 100644 --- a/config/locales/views/reports/en.yml +++ b/config/locales/views/reports/en.yml @@ -15,6 +15,7 @@ en: from: From to: To showing_period: "Showing data from %{start} to %{end}" + invalid_date_range: "End date cannot be before start date. The dates have been swapped." summary: total_income: Total Income total_expenses: Total Expenses diff --git a/test/controllers/reports_controller_test.rb b/test/controllers/reports_controller_test.rb index 4c454bf6a..0b35a6bfd 100644 --- a/test/controllers/reports_controller_test.rb +++ b/test/controllers/reports_controller_test.rb @@ -92,6 +92,24 @@ class ReportsControllerTest < ActionDispatch::IntegrationTest assert_response :ok # Should not crash, uses defaults end + test "index swaps dates when end_date is before start_date" do + start_date = Date.current + end_date = 1.month.ago.to_date + + get reports_path( + period_type: :custom, + start_date: start_date.to_s, + end_date: end_date.to_s + ) + + assert_response :ok + # Should show flash message about invalid date range + assert flash[:alert].present?, "Flash alert should be present" + assert_match /End date cannot be before start date/, flash[:alert] + # Should display the swapped date range + assert_select ".text-sm.text-secondary", text: /Showing data from #{Regexp.escape(end_date.strftime("%b %-d, %Y"))} to #{Regexp.escape(start_date.strftime("%b %-d, %Y"))}/ + end + test "spending patterns returns data when expense transactions exist" do # Create expense category expense_category = @family.categories.create!( @@ -185,4 +203,21 @@ class ReportsControllerTest < ActionDispatch::IntegrationTest assert_response :ok, "Export should work with session auth. Response: #{@response.body}" assert_equal "text/csv", @response.media_type end + + test "export transactions swaps dates when end_date is before start_date" do + start_date = Date.current + end_date = 1.month.ago.to_date + + get export_transactions_reports_path( + format: :csv, + period_type: :custom, + start_date: start_date.to_s, + end_date: end_date.to_s + ) + + assert_response :ok + assert_equal "text/csv", @response.media_type + # Verify the CSV content is generated (should not crash) + assert_not_nil @response.body + end end