diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb index f1c63bd7..6544160c 100644 --- a/app/controllers/reports_controller.rb +++ b/app/controllers/reports_controller.rb @@ -1,9 +1,33 @@ class ReportsController < ApplicationController + def index + @reports = Report.all + end + def show @report = Report.find(params[:id]) end - def new; end + def new + start_date = parse_date(params[:start_date]) + end_date = parse_date(params[:end_date]) + + return unless start_date && end_date && start_date <= end_date + + @start_date = params[:start_date] + @end_date = params[:end_date] + + result = ReportFilterService.new.filter( + start_date: start_date, + end_date: end_date, + project_ids: Array(params[:project_ids]), + subproject_ids: Array(params[:subproject_ids]) + ) + + @projects = result.projects + @selected_project_ids = result.selected_project_ids + @subprojects = result.subprojects + @selected_subproject_ids = result.selected_subproject_ids + end def edit @report = Report.find(params[:id]) @@ -74,28 +98,14 @@ def update redirect_to report_path(@report), flash: { success: t(".success") } end - def filter - start_date = parse_date(params[:start_date]) - end_date = parse_date(params[:end_date]) - - if start_date && end_date && start_date <= end_date - @start_date = params[:start_date] - @end_date = params[:end_date] - - result = ReportFilterService.new.filter( - start_date: start_date, - end_date: end_date, - project_ids: Array(params[:project_ids]), - subproject_ids: Array(params[:subproject_ids]) - ) + def destroy + @report = Report.find(params[:id]) - @projects = result.projects - @selected_project_ids = result.selected_project_ids - @subprojects = result.subprojects - @selected_subproject_ids = result.selected_subproject_ids + if @report.destroy + redirect_to reports_path, flash: { success: t(".success") } + else + redirect_to reports_path, flash: { error: @report.errors.full_messages.to_sentence } end - - render :new end private diff --git a/app/views/reports/index.html.erb b/app/views/reports/index.html.erb new file mode 100644 index 00000000..2c2c925b --- /dev/null +++ b/app/views/reports/index.html.erb @@ -0,0 +1,28 @@ +
+
+

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

+ <%= render ActionButtonComponent.new(to: new_report_path, icon: "add", colour: :primary, size: :large) do %> + <%= t(".actions.create") %> + <% end %> +
+ <%= render ContentCardComponent.new do %> + <%= render Shared::IndexTableComponent.new(records: @reports) do |table| %> + <% table.column :start_date do |report| %> + <%= l(report.start_date) if report.start_date %> + <% end %> + <% table.column :end_date do |report| %> + <%= l(report.end_date) if report.end_date %> + <% end %> + <% table.column :created_at do |report| %> + <%= l(report.created_at) %> + <% end %> + <% table.column :actions, header: t("shared.index_table_component.actions"), col_size: "90px" do |report| %> +
+ <%= render ActionButtonComponent.new(to: report_path(report), icon: "view") %> + <%= render ActionButtonComponent.new(to: edit_report_path(report), icon: "edit", colour: :info) %> + <%= render ActionButtonComponent.new(to: report_path(report), method: :delete, icon: "delete", colour: :error, confirm: t("reports.destroy.confirm")) %> +
+ <% end %> + <% end %> + <% end %> +
diff --git a/app/views/reports/new.html.erb b/app/views/reports/new.html.erb index 387af156..ef0374dd 100644 --- a/app/views/reports/new.html.erb +++ b/app/views/reports/new.html.erb @@ -6,7 +6,7 @@
- <%= form_with url: filter_reports_path, method: :get, local: true, class: "space-y-4" do %> + <%= form_with url: new_report_path, method: :get, local: true, class: "space-y-4" do %>
<%= label_tag :start_date, t(".start_date"), class: "label font-semibold text-base-content" %> diff --git a/config/locales/en/reports.en.yml b/config/locales/en/reports.en.yml index 8dc09c1d..44bee8da 100644 --- a/config/locales/en/reports.en.yml +++ b/config/locales/en/reports.en.yml @@ -4,6 +4,9 @@ en: create: invalid: Please provide valid dates and select at least one subproject. success: Report was successfully generated. + destroy: + confirm: Are you sure you want to delete this report? + success: Report deleted successfully. edit: add_aggregated_datum: Add Aggregated Data Box add_journal: Add Journal @@ -18,6 +21,10 @@ en: save: Save Changes selected_journals: Selected Journals title: Edit Report + index: + actions: + create: Create Report + title: Reports journal_card_component: author: Author new: diff --git a/config/locales/es/reports.es.yml b/config/locales/es/reports.es.yml index 926811fb..58cb0af7 100644 --- a/config/locales/es/reports.es.yml +++ b/config/locales/es/reports.es.yml @@ -4,6 +4,9 @@ es: create: invalid: Por favor proporcione fechas válidas y seleccione al menos un subproyecto. success: El reporte fue generado exitosamente. + destroy: + confirm: "¿Está seguro de que desea eliminar este informe?" + success: Informe eliminado exitosamente. edit: add_aggregated_datum: Agregar Caja de Datos Agregados add_journal: Agregar Diario @@ -18,6 +21,10 @@ es: save: Guardar Cambios selected_journals: Diarios Seleccionados title: Editar Reporte + index: + actions: + create: Crear informe + title: Informes journal_card_component: author: Autor new: diff --git a/config/routes.rb b/config/routes.rb index 7eaa680c..a24da512 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -40,10 +40,6 @@ delete "/logout", to: "sessions#destroy" # Report routes - resources :reports, only: %i[show new create edit update] do - collection do - get :filter - end - end + resources :reports, only: %i[index show new create edit update destroy] end end diff --git a/test/controllers/reports_controller_test.rb b/test/controllers/reports_controller_test.rb index 1bcd0b64..e5f964e6 100644 --- a/test/controllers/reports_controller_test.rb +++ b/test/controllers/reports_controller_test.rb @@ -6,10 +6,10 @@ class ReportsControllerTest < ActionDispatch::IntegrationTest end [ + { route: "index", method: :get, url_helper: :reports_url, needs_report: false }, { route: "show", method: :get, url_helper: :report_url, needs_report: true }, { route: "new", method: :get, url_helper: :new_report_url, needs_report: false }, { route: "edit", method: :get, url_helper: :edit_report_url, needs_report: true }, - { route: "filter", method: :get, url_helper: :filter_reports_url, needs_report: false }, { route: "update", method: :patch, url_helper: :report_url, needs_report: true } ].each do |hash| test "##{hash[:route]} redirects to login route when a user is not authenticated" do @@ -64,20 +64,29 @@ class ReportsControllerTest < ActionDispatch::IntegrationTest assert_match aggregated_datum.additional_text, response.body end - test "#filter displays projects when valid dates are provided" do + test "#index displays reports" do + report = create(:report) + + get reports_path + assert_response :success + assert_match I18n.l(report.start_date.to_date), response.body + assert_match I18n.l(report.end_date.to_date), response.body + end + + test "#new displays projects when valid dates are provided" do subproject = create(:subproject) create(:log_entry, subproject: subproject, created_at: 1.day.ago) - get filter_reports_path, params: { start_date: 2.days.ago.to_date.to_s, end_date: Time.zone.today.to_s } + get new_report_path, params: { start_date: 2.days.ago.to_date.to_s, end_date: Time.zone.today.to_s } assert_response :success assert_match subproject.project.name, response.body end - test "#filter displays subprojects when projects are selected" do + test "#new displays subprojects when projects are selected" do subproject = create(:subproject) create(:log_entry, subproject: subproject, created_at: 1.day.ago) - get filter_reports_path, params: { + get new_report_path, params: { start_date: 2.days.ago.to_date.to_s, end_date: Time.zone.today.to_s, project_ids: [subproject.project.id] @@ -86,16 +95,16 @@ class ReportsControllerTest < ActionDispatch::IntegrationTest assert_match subproject.name, response.body end - test "#filter handles invalid dates gracefully" do - get filter_reports_path, params: { start_date: "invalid", end_date: "also-invalid" } + test "#new handles invalid dates gracefully" do + get new_report_path, params: { start_date: "invalid", end_date: "also-invalid" } assert_response :success end - test "#filter includes log entries from end date" do + test "#new includes log entries from end date" do subproject = create(:subproject) create(:log_entry, subproject: subproject, created_at: Time.zone.today.noon) - get filter_reports_path, params: { + get new_report_path, params: { start_date: 2.days.ago.to_date.to_s, end_date: Time.zone.today.to_s, project_ids: [subproject.project.id] @@ -168,6 +177,48 @@ class ReportsControllerTest < ActionDispatch::IntegrationTest assert_equal I18n.t("reports.create.invalid"), flash[:error] end + test "#create redirects with error when subproject_ids do not exist" do + assert_no_difference("Report.count") do + post reports_path, params: { + start_date: Time.zone.yesterday.to_s, + end_date: Time.zone.today.to_s, + subproject_ids: [0] + } + end + + assert_redirected_to new_report_path + assert_equal I18n.t("reports.create.invalid"), flash[:error] + end + + test "#destroy redirects to login route when a user is not authenticated" do + report = create(:report) + log_out_user + + delete report_path(report) + assert_response :redirect + assert_redirected_to login_path + end + + test "#destroy redirects to root route when a user is not authorized" do + report = create(:report) + create_logged_in_user + + delete report_path(report) + assert_response :redirect + assert_redirected_to root_path + end + + test "#destroy removes the report and redirects to index" do + report = create(:report) + + assert_difference("Report.count", -1) do + delete report_path(report) + end + + assert_redirected_to reports_path + assert_equal I18n.t("reports.destroy.success"), flash[:success] + end + test "#update replaces journals and aggregated data in one save" do report = create(:report) existing_journal = create(:journal)