diff --git a/app/components/dossiers/user_filter_component.rb b/app/components/dossiers/user_filter_component.rb index 8f7d731c5..24061ec9a 100644 --- a/app/components/dossiers/user_filter_component.rb +++ b/app/components/dossiers/user_filter_component.rb @@ -15,9 +15,9 @@ class Dossiers::UserFilterComponent < ApplicationComponent def states_collection(statut) case statut when 'en-cours' - Dossier.states.values - Dossier::TERMINE + (Dossier.states.values - Dossier::TERMINE) << Dossier::A_CORRIGER when 'traites' Dossier::TERMINE - end + end.map { |state| [t("activerecord.attributes.dossier/state.#{state}"), state] } end end diff --git a/app/components/dossiers/user_filter_component/user_filter_component.en.yml b/app/components/dossiers/user_filter_component/user_filter_component.en.yml index bc72f08e2..bc722ebfe 100644 --- a/app/components/dossiers/user_filter_component/user_filter_component.en.yml +++ b/app/components/dossiers/user_filter_component/user_filter_component.en.yml @@ -1,8 +1,8 @@ en: legend: - states: States - created_at: Creation date - depose_at: Submission date + state: States + created_at: Creation date since + depose_at: Submission date since button: apply_filters: Apply filters reset_filters: Reset filters @@ -14,3 +14,5 @@ en: active_filters_link_title: one: Remove the active filter other: "Remove the %{count} active filters" + states: + prompt: Select a state diff --git a/app/components/dossiers/user_filter_component/user_filter_component.fr.yml b/app/components/dossiers/user_filter_component/user_filter_component.fr.yml index 6e42f40fb..e29878ceb 100644 --- a/app/components/dossiers/user_filter_component/user_filter_component.fr.yml +++ b/app/components/dossiers/user_filter_component/user_filter_component.fr.yml @@ -1,8 +1,8 @@ fr: legend: - states: États - created_at: Date de création - depose_at: Date de dépôt + state: Statut + created_at: Date de création depuis le + depose_at: Date de dépôt depuis le button: apply_filters: Appliquer les filtres reset_filters: Réinitialiser les filtres @@ -14,3 +14,5 @@ fr: active_filters_link_title: one: Retirer le filtre actif other: "Retirer les %{count} filtres actifs" + states: + prompt: Sélectionner un statut diff --git a/app/components/dossiers/user_filter_component/user_filter_component.html.haml b/app/components/dossiers/user_filter_component/user_filter_component.html.haml index 5a6c92e51..a2aa06cdd 100644 --- a/app/components/dossiers/user_filter_component/user_filter_component.html.haml +++ b/app/components/dossiers/user_filter_component/user_filter_component.html.haml @@ -9,15 +9,9 @@ = form_with(url: dossiers_path(), method: :get ) do |f| = f.hidden_field :statut, value: @statut - %fieldset#checkboxes.fr-fieldset{ "aria-labelledby" => "checkboxes-legend" } - %legend#checkboxes-legend.fr-fieldset__legend--regular.fr-fieldset__legend - = t('.legend.states') - = f.collection_check_boxes :states, states_collection(@statut), :to_s, :to_s, include_hidden: false do |b| - .fr-fieldset__element - .fr-checkbox-group.fr-ml-2w.fr-py-1w - = b.check_box(checked: filter.states_filtered?(b.value)) - = b.label(class: 'fr-label') { dossier_display_state(b.text) } - + .fr-input-group + = f.label :state, t('.legend.state'), class: 'fr-label' + = f.select :state, options_for_select(states_collection(@statut), params[:state]), {prompt: t('.states.prompt')}, {class: 'fr-select'} .fr-input-group = f.label 'from_created_at_date', t('.legend.created_at'), class: 'fr-label' diff --git a/app/models/concerns/dossier_correctable_concern.rb b/app/models/concerns/dossier_correctable_concern.rb index ee9dc09aa..721d19a76 100644 --- a/app/models/concerns/dossier_correctable_concern.rb +++ b/app/models/concerns/dossier_correctable_concern.rb @@ -2,8 +2,11 @@ module DossierCorrectableConcern extend ActiveSupport::Concern included do + A_CORRIGER = 'a_corriger' has_many :corrections, class_name: 'DossierCorrection', dependent: :destroy + scope :with_pending_corrections, -> { joins(:corrections).where(corrections: { resolved_at: nil }) } + def flag_as_pending_correction!(commentaire) return unless may_flag_as_pending_correction? diff --git a/app/models/dossiers_filter.rb b/app/models/dossiers_filter.rb index ab1c4deb1..66163b534 100644 --- a/app/models/dossiers_filter.rb +++ b/app/models/dossiers_filter.rb @@ -3,36 +3,33 @@ class DossiersFilter def initialize(user, params) @user = user - @params = params.permit(:page, :from_created_at_date, :from_depose_at_date, states: []) + @params = params.permit(:page, :from_created_at_date, :from_depose_at_date, :state) end def filter_params - params[:from_created_at_date].presence || params[:from_depose_at_date].presence || params[:states].presence + params[:from_created_at_date].presence || params[:from_depose_at_date].presence || params[:state].presence end def filter_params_count count = 0 count += 1 if params[:from_created_at_date].presence count += 1 if params[:from_depose_at_date].presence - count += params[:states].count if params[:states].presence + count += 1 if params[:state].presence count end def filter_procedures(dossiers) return dossiers if filter_params.blank? dossiers_result = dossiers - dossiers_result = dossiers_result.where(state: states) if states.present? - dossiers_result = dossiers_result.where('created_at >= ?', from_created_at_date) if from_created_at_date.present? - dossiers_result = dossiers_result.where('depose_at >= ?', from_depose_at_date) if from_depose_at_date.present? + dossiers_result = dossiers_result.where(state: state) if state.present? && state != Dossier::A_CORRIGER + dossiers_result = dossiers_result.with_pending_corrections if state.present? && state == Dossier::A_CORRIGER + dossiers_result = dossiers_result.where('dossiers.created_at >= ?', from_created_at_date) if from_created_at_date.present? + dossiers_result = dossiers_result.where('dossiers.depose_at >= ?', from_depose_at_date) if from_depose_at_date.present? dossiers_result end - def states - params[:states].compact_blank if params[:states].present? - end - - def states_filtered?(state) - states&.include?(state) + def state + params[:state] end def from_created_at_date diff --git a/app/views/users/dossiers/index.html.haml b/app/views/users/dossiers/index.html.haml index 3f15c71cd..152766561 100644 --- a/app/views/users/dossiers/index.html.haml +++ b/app/views/users/dossiers/index.html.haml @@ -63,6 +63,14 @@ badge: number_with_html_delimiter(@dossier_transfers.count)) .fr-container + - if @statut == "en-cours" + - if @first_brouillon_recently_updated.present? + = render Dsfr::CalloutComponent.new(title: t('users.dossiers.header.callout.first_brouillon_recently_updated_title'), heading_level: 'h2') do |c| + - c.with_body do + %p + = t('users.dossiers.header.callout.first_brouillon_recently_updated_text', time_ago: time_ago_in_words(@first_brouillon_recently_updated.created_at), libelle: @first_brouillon_recently_updated.procedure.libelle ) + = link_to t('users.dossiers.header.callout.first_brouillon_recently_updated_button'), url_for_dossier(@first_brouillon_recently_updated), class: 'fr-btn' + - if @search_terms.present? %h2.page-title Résultat de la recherche pour « #{@search_terms} » = render partial: "dossiers_list", locals: { dossiers: @dossiers } @@ -71,13 +79,6 @@ = render Dossiers::UserFilterComponent.new(statut: @statut, filter: @filter) - if @statut == "en-cours" - - if @first_brouillon_recently_updated.present? - = render Dsfr::CalloutComponent.new(title: t('users.dossiers.header.callout.first_brouillon_recently_updated_title'), heading_level: 'h2') do |c| - - c.with_body do - %p - = t('users.dossiers.header.callout.first_brouillon_recently_updated_text', time_ago: time_ago_in_words(@first_brouillon_recently_updated.created_at), libelle: @first_brouillon_recently_updated.procedure.libelle ) - = link_to t('users.dossiers.header.callout.first_brouillon_recently_updated_button'), url_for_dossier(@first_brouillon_recently_updated), class: 'fr-btn' - = render partial: "dossiers_list", locals: { dossiers: @dossiers, filter: @filter, statut: @statut } - if @statut == "traites" diff --git a/config/locales/models/dossier/en.yml b/config/locales/models/dossier/en.yml index d33baed61..ac3b34fbe 100644 --- a/config/locales/models/dossier/en.yml +++ b/config/locales/models/dossier/en.yml @@ -15,6 +15,7 @@ en: accepte: "Accepted" refuse: "Refused" sans_suite: "No further action" + a_corriger: To be corrected pending_correction: for_instructeur: "pending" for_user: "to be corrected" diff --git a/config/locales/models/dossier/fr.yml b/config/locales/models/dossier/fr.yml index cbfd9e4a8..4c5765e0f 100644 --- a/config/locales/models/dossier/fr.yml +++ b/config/locales/models/dossier/fr.yml @@ -19,6 +19,7 @@ fr: accepte: "Accepté" refuse: "Refusé" sans_suite: "Classé sans suite" + a_corriger: À corriger pending_correction: for_instructeur: "en attente" for_user: "à corriger" diff --git a/spec/system/users/list_dossiers_spec.rb b/spec/system/users/list_dossiers_spec.rb index c692f5279..109a01aac 100644 --- a/spec/system/users/list_dossiers_spec.rb +++ b/spec/system/users/list_dossiers_spec.rb @@ -1,11 +1,13 @@ describe 'user access to the list of their dossiers', js: true do let(:user) { create(:user) } - let!(:dossier_brouillon) { create(:dossier, user: user) } - let!(:dossier_en_construction) { create(:dossier, :with_populated_champs, :en_construction, user: user) } - let!(:dossier_en_instruction) { create(:dossier, :en_instruction, user: user) } - let!(:dossier_traite) { create(:dossier, :accepte, user: user) } - let!(:dossier_refuse) { create(:dossier, :refuse, user: user) } - let!(:dossier_archived) { create(:dossier, :en_instruction, :archived, user: user) } + let!(:dossier_brouillon) { create(:dossier, user: user) } + let!(:dossier_en_construction) { create(:dossier, :with_populated_champs, :en_construction, user: user) } + let!(:dossier_en_construction_2) { create(:dossier, :en_construction, user: user) } + let!(:dossier_en_instruction) { create(:dossier, :en_instruction, user: user) } + let!(:dossier_traite) { create(:dossier, :accepte, user: user) } + let!(:dossier_refuse) { create(:dossier, :refuse, user: user) } + let!(:dossier_a_corriger) { create(:dossier_correction, dossier: dossier_en_construction_2) } + let!(:dossier_archived) { create(:dossier, :en_instruction, :archived, user: user) } let(:dossiers_per_page) { 25 } let(:last_updated_dossier) { dossier_en_construction } @@ -28,7 +30,7 @@ describe 'user access to the list of their dossiers', js: true do expect(page).to have_content(dossier_en_construction.procedure.libelle) expect(page).to have_content(dossier_en_instruction.procedure.libelle) expect(page).to have_content(dossier_archived.procedure.libelle) - expect(page).to have_text('4 en cours') + expect(page).to have_text('5 en cours') expect(page).to have_text('2 traités') end @@ -51,83 +53,88 @@ describe 'user access to the list of their dossiers', js: true do expect(page).not_to have_content(dossier_en_instruction.procedure.libelle) page.click_link("Suivant") expect(page).to have_content(dossier_en_instruction.procedure.libelle) - expect(page).to have_text('4 en cours') + expect(page).to have_text('5 en cours') expect(page).to have_text('2 traités') end end context 'when user uses filter' do scenario 'user filters state on tab "en-cours"' do - expect(page).to have_text('4 en cours') + expect(page).to have_text('5 en cours') expect(page).to have_text('2 traités') - expect(page).to have_text('4 sur 4 dossiers') + expect(page).to have_text('5 sur 5 dossiers') + click_on('Sélectionner un filtre') - expect(page).to have_text('Brouillon') - expect(page).to have_text('En construction') - expect(page).to have_text('En instruction') - find("label", text: "Brouillon").click + expect(page).to have_select 'Statut', selected: 'Sélectionner un statut', options: ['Sélectionner un statut', 'Brouillon', 'En construction', 'En instruction', 'À corriger'] + select('Brouillon', from: 'Statut') click_on('Appliquer les filtres') + expect(page).to have_text('1 dossier') - expect(page).to have_checked_field('Brouillon') + expect(page).to have_select 'Statut', selected: 'Brouillon', options: ['Sélectionner un statut', 'Brouillon', 'En construction', 'En instruction', 'À corriger'] + + click_on('Sélectionner un filtre') + select('À corriger', from: 'Statut') + click_on('Appliquer les filtres') + + expect(page).to have_text('1 dossier') + expect(page).to have_select 'Statut', selected: 'À corriger', options: ['Sélectionner un statut', 'Brouillon', 'En construction', 'En instruction', 'À corriger'] end scenario 'user filters state on tab "traité"' do visit dossiers_path(statut: 'traites') - expect(page).to have_text('4 en cours') + expect(page).to have_text('5 en cours') expect(page).to have_text('2 traités') expect(page).to have_text('2 sur 2 dossiers') click_on('Sélectionner un filtre') - expect(page).to have_text('Accepté') - expect(page).to have_text('Refusé') - expect(page).to have_text('Classé sans suite') - find("label", text: "Refusé").click + expect(page).to have_select 'Statut', selected: 'Sélectionner un statut', options: ['Sélectionner un statut', 'Accepté', 'Refusé', 'Classé sans suite'] + select('Refusé', from: 'Statut') click_on('Appliquer les filtres') expect(page).to have_text('1 dossier') - expect(page).to have_checked_field('Refusé') + expect(page).to have_select 'Statut', selected: 'Refusé', options: ['Sélectionner un statut', 'Accepté', 'Refusé', 'Classé sans suite'] click_on('Sélectionner un filtre') click_on('Réinitialiser les filtres') expect(page).to have_text('2 sur 2 dossiers') - expect(page).to have_unchecked_field('Refusé') + expect(page).to have_select 'Statut', selected: 'Sélectionner un statut', options: ['Sélectionner un statut', 'Accepté', 'Refusé', 'Classé sans suite'] end scenario 'user filters by created_at' do dossier_en_construction.update!(created_at: Date.yesterday) - expect(page).to have_text('4 sur 4 dossiers') + expect(page).to have_text('5 sur 5 dossiers') click_on('Sélectionner un filtre') fill_in 'from_created_at_date', with: Date.today click_on('Appliquer les filtres') - expect(page).to have_text('3 sur 3 dossiers') + expect(page).to have_text('4 sur 4 dossiers') end scenario 'user uses multiple filters' do dossier_en_construction.update!(created_at: Date.yesterday) - dossier_en_instruction.update!(depose_at: Date.yesterday) - expect(page).to have_text('4 sur 4 dossiers') + expect(page).to have_select 'Statut', selected: 'Sélectionner un statut', options: ['Sélectionner un statut', 'Brouillon', 'En construction', 'En instruction', 'À corriger'] + + expect(page).to have_text('5 sur 5 dossiers') click_on('Sélectionner un filtre') fill_in 'from_created_at_date', with: Date.today click_on('Appliquer les filtres') - expect(page).to have_text('3 sur 3 dossiers') + expect(page).to have_text('4 sur 4 dossiers') expect(page).to have_text('1 filtre actif') click_on('Sélectionner un filtre') - find("label", text: "En construction").click - find("label", text: "En instruction").click + select('En construction', from: 'Statut') click_on('Appliquer les filtres') - expect(page).to have_text('2 sur 2 dossiers') - expect(page).to have_text('3 filtres actifs') + expect(page).to have_text('1 dossier') + expect(page).to have_text('2 filtres actifs') click_on('Sélectionner un filtre') fill_in 'from_depose_at_date', with: Date.today click_on('Appliquer les filtres') expect(page).to have_text('1 dossier') - expect(page).to have_text('4 filtres actifs') - click_on('4 filtres actifs') - expect(page).to have_text('4 sur 4 dossiers') - expect(page).not_to have_text('4 filtres actifs') + expect(page).to have_text('3 filtres actifs') + click_on('3 filtres actifs') + expect(page).to have_text('5 sur 5 dossiers') + expect(page).not_to have_text('5 filtres actifs') end end @@ -221,7 +228,6 @@ describe 'user access to the list of their dossiers', js: true do end context "when user search for something inside the dossier" do - let(:dossier_en_construction2) { create(:dossier, :with_populated_champs, :en_construction, user: user) } before do page.find_by_id('q').set(dossier_en_construction.champs_public.first.value) end @@ -236,15 +242,15 @@ describe 'user access to the list of their dossiers', js: true do end context 'when it matches multiple dossier' do + let!(:dossier_with_champs) { create(:dossier, :with_populated_champs, :en_construction, user: user) } before do - dossier_en_construction2.champs_public.first.update(value: dossier_en_construction.champs_public.first.value) find('.fr-search-bar .fr-btn').click end it "redirects to the search results" do expect(current_path).to eq(recherche_dossiers_path) expect(page).to have_content(dossier_en_construction.id) - expect(page).to have_content(dossier_en_construction2.id) + expect(page).to have_content(dossier_with_champs.id) end end end