From 7f6fd9712bac1a5273b2868e68b3ef508498f4cf Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 18 Nov 2024 23:27:54 +0100 Subject: [PATCH 1/7] Trad: add unbreakable spaces in avis sum_up --- config/locales/models/avis/en.yml | 4 ++-- config/locales/models/avis/fr.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/locales/models/avis/en.yml b/config/locales/models/avis/en.yml index f69a17f45..adcba51fb 100644 --- a/config/locales/models/avis/en.yml +++ b/config/locales/models/avis/en.yml @@ -22,8 +22,8 @@ en: true: 'yes' false: 'no' question_answer_with_count: - true: "yes : %{count}" - false: "no : %{count}" + true: "yes : %{count}" + false: "no : %{count}" confirmation: revoke: "Would you like to revoke the opinion request to %{email} ?" remind: "Would you like to remind %{email} ?" diff --git a/config/locales/models/avis/fr.yml b/config/locales/models/avis/fr.yml index 996da890a..bb8124347 100644 --- a/config/locales/models/avis/fr.yml +++ b/config/locales/models/avis/fr.yml @@ -22,8 +22,8 @@ fr: true: oui false: non question_answer_with_count: - true: "oui : %{count}" - false: "non : %{count}" + true: "oui : %{count}" + false: "non : %{count}" confirmation: revoke: "Souhaitez-vous révoquer la demande d’avis à %{email} ?" remind: "Souhaitez-vous relancer %{email} ?" From fe0a396dc63927eaf50a9a4a3cf26da1306422ff Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Thu, 21 Nov 2024 10:55:11 +0100 Subject: [PATCH 2/7] refactor: remove unused individual prenom / nom load because of bb236f6c0d2703f51d353bb9952a6d01d80aab7e --- app/services/dossier_projection_service.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/app/services/dossier_projection_service.rb b/app/services/dossier_projection_service.rb index 3c3f2a438..65a531ed1 100644 --- a/app/services/dossier_projection_service.rb +++ b/app/services/dossier_projection_service.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class DossierProjectionService - class DossierProjection < Struct.new(:dossier_id, :state, :archived, :hidden_by_user_at, :hidden_by_administration_at, :hidden_by_reason, :for_tiers, :prenom, :nom, :batch_operation_id, :sva_svr_decision_on, :corrections, :columns) do + class DossierProjection < Struct.new(:dossier_id, :state, :archived, :hidden_by_user_at, :hidden_by_administration_at, :hidden_by_reason, :for_tiers, :batch_operation_id, :sva_svr_decision_on, :corrections, :columns) do def pending_correction? return false if corrections.blank? @@ -58,12 +58,10 @@ class DossierProjectionService hidden_by_administration_at_field = { TABLE => 'self', COLUMN => 'hidden_by_administration_at' } hidden_by_reason_field = { TABLE => 'self', COLUMN => 'hidden_by_reason' } for_tiers_field = { TABLE => 'self', COLUMN => 'for_tiers' } - individual_first_name = { TABLE => 'individual', COLUMN => 'prenom' } - individual_last_name = { TABLE => 'individual', COLUMN => 'nom' } sva_svr_decision_on_field = { TABLE => 'self', COLUMN => 'sva_svr_decision_on' } dossier_corrections = { TABLE => 'dossier_corrections', COLUMN => 'resolved_at' } - ([state_field, archived_field, sva_svr_decision_on_field, hidden_by_user_at_field, hidden_by_administration_at_field, hidden_by_reason_field, for_tiers_field, individual_first_name, individual_last_name, batch_operation_field, dossier_corrections] + fields) + ([state_field, archived_field, sva_svr_decision_on_field, hidden_by_user_at_field, hidden_by_administration_at_field, hidden_by_reason_field, for_tiers_field, batch_operation_field, dossier_corrections] + fields) .each { |f| f[:id_value_h] = {} } .group_by { |f| f[TABLE] } # one query per table .each do |table, fields| @@ -182,8 +180,6 @@ class DossierProjectionService hidden_by_administration_at_field[:id_value_h][dossier_id], hidden_by_reason_field[:id_value_h][dossier_id], for_tiers_field[:id_value_h][dossier_id], - individual_first_name[:id_value_h][dossier_id], - individual_last_name[:id_value_h][dossier_id], batch_operation_field[:id_value_h][dossier_id], sva_svr_decision_on_field[:id_value_h][dossier_id], dossier_corrections[:id_value_h][dossier_id], From c415b066b9274e5c6498587dfd8df62145b1bc13 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 13 Nov 2024 11:01:10 +0100 Subject: [PATCH 3/7] refactor: always load full dossier --- .../instructeurs/procedures_controller.rb | 2 +- app/services/dossier_projection_service.rb | 26 ++------ .../instructeurs/procedures/show.html.haml | 59 ++++++++++--------- .../dossier_projection_service_spec.rb | 20 +++---- 4 files changed, 47 insertions(+), 60 deletions(-) diff --git a/app/controllers/instructeurs/procedures_controller.rb b/app/controllers/instructeurs/procedures_controller.rb index 5c7e2011e..fad6c0056 100644 --- a/app/controllers/instructeurs/procedures_controller.rb +++ b/app/controllers/instructeurs/procedures_controller.rb @@ -105,7 +105,7 @@ module Instructeurs .per(ITEMS_PER_PAGE) @projected_dossiers = DossierProjectionService.project(@filtered_sorted_paginated_ids, procedure_presentation.displayed_columns) - @disable_checkbox_all = @projected_dossiers.all? { _1.batch_operation_id.present? } + @disable_checkbox_all = @projected_dossiers.all? { _1.dossier.batch_operation_id.present? } @batch_operations = BatchOperation.joins(:groupe_instructeurs) .where(groupe_instructeurs: current_instructeur.groupe_instructeurs.where(procedure_id: @procedure.id)) diff --git a/app/services/dossier_projection_service.rb b/app/services/dossier_projection_service.rb index 65a531ed1..8720a0797 100644 --- a/app/services/dossier_projection_service.rb +++ b/app/services/dossier_projection_service.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class DossierProjectionService - class DossierProjection < Struct.new(:dossier_id, :state, :archived, :hidden_by_user_at, :hidden_by_administration_at, :hidden_by_reason, :for_tiers, :batch_operation_id, :sva_svr_decision_on, :corrections, :columns) do + class DossierProjection < Struct.new(:dossier, :corrections, :columns) do def pending_correction? return false if corrections.blank? @@ -51,17 +51,9 @@ class DossierProjectionService end champ_value = champ_value_formatter(dossiers_ids, fields) - state_field = { TABLE => 'self', COLUMN => 'state' } - archived_field = { TABLE => 'self', COLUMN => 'archived' } - batch_operation_field = { TABLE => 'self', COLUMN => 'batch_operation_id' } - hidden_by_user_at_field = { TABLE => 'self', COLUMN => 'hidden_by_user_at' } - hidden_by_administration_at_field = { TABLE => 'self', COLUMN => 'hidden_by_administration_at' } - hidden_by_reason_field = { TABLE => 'self', COLUMN => 'hidden_by_reason' } - for_tiers_field = { TABLE => 'self', COLUMN => 'for_tiers' } - sva_svr_decision_on_field = { TABLE => 'self', COLUMN => 'sva_svr_decision_on' } dossier_corrections = { TABLE => 'dossier_corrections', COLUMN => 'resolved_at' } - ([state_field, archived_field, sva_svr_decision_on_field, hidden_by_user_at_field, hidden_by_administration_at_field, hidden_by_reason_field, for_tiers_field, batch_operation_field, dossier_corrections] + fields) + ([dossier_corrections] + fields) .each { |f| f[:id_value_h] = {} } .group_by { |f| f[TABLE] } # one query per table .each do |table, fields| @@ -89,7 +81,7 @@ class DossierProjectionService .each do |id, *columns| fields.zip(columns).each do |field, value| # SVA must remain a date: in other column we compute remaining delay with it - field[:id_value_h][id] = if value.respond_to?(:strftime) && field != sva_svr_decision_on_field + field[:id_value_h][id] = if value.respond_to?(:strftime) I18n.l(value.to_date) else value @@ -171,17 +163,11 @@ class DossierProjectionService end end + dossiers = Dossier.find(dossiers_ids) + dossiers_ids.map do |dossier_id| DossierProjection.new( - dossier_id, - state_field[:id_value_h][dossier_id], - archived_field[:id_value_h][dossier_id], - hidden_by_user_at_field[:id_value_h][dossier_id], - hidden_by_administration_at_field[:id_value_h][dossier_id], - hidden_by_reason_field[:id_value_h][dossier_id], - for_tiers_field[:id_value_h][dossier_id], - batch_operation_field[:id_value_h][dossier_id], - sva_svr_decision_on_field[:id_value_h][dossier_id], + dossiers.find { _1.id == dossier_id }, dossier_corrections[:id_value_h][dossier_id], fields.map { |f| f[:id_value_h][dossier_id] } ) diff --git a/app/views/instructeurs/procedures/show.html.haml b/app/views/instructeurs/procedures/show.html.haml index bc3bc3f31..6cb301ba6 100644 --- a/app/views/instructeurs/procedures/show.html.haml +++ b/app/views/instructeurs/procedures/show.html.haml @@ -110,70 +110,71 @@ = render Dossiers::BatchSelectMoreComponent.new(dossiers_count: @dossiers_count, filtered_sorted_ids: @filtered_sorted_ids) - @projected_dossiers.each do |p| - - path = instructeur_dossier_path(@procedure, p.dossier_id) - %tr{ class: class_names("file-hidden-by-user" => p.hidden_by_user_at.present?), id: "table-dossiers-row-#{p.dossier_id}", "aria-selected" => "false", "data-row-key" => p.dossier_id } + - dossier = p.dossier + - path = instructeur_dossier_path(@procedure, dossier.id) + %tr{ class: class_names("file-hidden-by-user" => dossier.hidden_by_user_at.present?), id: "table-dossiers-row-#{dossier.id}", "aria-selected" => "false", "data-row-key" => dossier.id } - if batch_operation_component.render? %th.fr-cell--fixed{ scope: 'row' } .fr-checkbox-group.fr-checkbox-group--sm - - if p.batch_operation_id.present? - = check_box_tag "batch_operation[dossier_ids][]", p.dossier_id, true, disabled: true, - id: dom_id(BatchOperation.new, "checkbox_#{p.dossier_id}"), - aria: { label: t('views.instructeurs.dossiers.batch_operation.disabled', dossier_id: p.dossier_id) }, + - if dossier.batch_operation_id.present? + = check_box_tag "batch_operation[dossier_ids][]", dossier.id, true, disabled: true, + id: dom_id(BatchOperation.new, "checkbox_#{dossier.id}"), + aria: { label: t('views.instructeurs.dossiers.batch_operation.disabled', dossier_id: dossier.id) }, data: { "fr-row-select" => "true" } - else - = check_box_tag "batch_operation[dossier_ids][]", p.dossier_id, false, - data: { batch_operation_target: "input", action: "batch-operation#onCheckOne", operations: batch_operation_component.operations_for_dossier(p).join(','), "fr-row-select" => "true" }, - form: dom_id(BatchOperation.new), id: dom_id(BatchOperation.new, "checkbox_#{p.dossier_id}"), - aria: { label: t('views.instructeurs.dossiers.batch_operation.enabled', dossier_id: p.dossier_id) } - = label_tag dom_id(BatchOperation.new, "checkbox_#{p.dossier_id}"), "Sélectionner le dossier #{p.dossier_id}", class: 'fr-label' + = check_box_tag "batch_operation[dossier_ids][]", dossier.id, false, + data: { batch_operation_target: "input", action: "batch-operation#onCheckOne", operations: batch_operation_component.operations_for_dossier(dossier).join(','), "fr-row-select" => "true" }, + form: dom_id(BatchOperation.new), id: dom_id(BatchOperation.new, "checkbox_#{dossier.id}"), + aria: { label: t('views.instructeurs.dossiers.batch_operation.enabled', dossier_id: dossier.id) } + = label_tag dom_id(BatchOperation.new, "checkbox_#{dossier.id}"), "Sélectionner le dossier #{dossier.id}", class: 'fr-label' %td.fr-cell--numeric - - if p.hidden_by_administration_at.present? - %span= p.dossier_id + - if dossier.hidden_by_administration_at.present? + %span= dossier.id - else %a.fr-link.relative{ href: path } - = p.dossier_id - - if @not_archived_notifications_dossier_ids.include?(p.dossier_id) + = dossier.id + - if @not_archived_notifications_dossier_ids.include?(dossier.id) %span.notifications{ 'aria-label': 'notifications' } - p.columns.each do |column| %td.fr-cell--multiline - - if p.hidden_by_administration_at.present? + - if dossier.hidden_by_administration_at.present? %span = column.is_a?(Hash) ? tags_label(column[:value]) : column - - if p.hidden_by_user_at.present? - = "- #{t("views.instructeurs.dossiers.deleted_reason.#{p.hidden_by_reason}")}" + - if dossier.hidden_by_user_at.present? + = "- #{t("views.instructeurs.dossiers.deleted_reason.#{dossier.hidden_by_reason}")}" - else %a{ href: path } = column.is_a?(Hash) ? tags_label(column[:value]) : column - = "- #{t("views.instructeurs.dossiers.deleted_reason.#{p.hidden_by_reason}")}" if p.hidden_by_user_at.present? + = "- #{t("views.instructeurs.dossiers.deleted_reason.#{dossier.hidden_by_reason}")}" if dossier.hidden_by_user_at.present? %td - - status = [status_badge(p.state)] + - status = [status_badge(dossier.state)] - if p.pending_correction? - status << pending_correction_badge(:for_instructeur, html_class: "fr-mt-1v") - - elsif p.state.to_sym == :en_construction && p.resolved_corrections? + - elsif dossier.state.to_sym == :en_construction && p.resolved_corrections? - status << correction_resolved_badge(html_class: "fr-mt-1v") - = link_to_if(p.hidden_by_administration_at.blank?, safe_join(status), path, class: "flex column") + = link_to_if(dossier.hidden_by_administration_at.blank?, safe_join(status), path, class: "flex column") - if @procedure.sva_svr_enabled? %td %span - = link_to_if p.hidden_by_administration_at.blank?, render(Instructeurs::SVASVRDecisionBadgeComponent.new(projection_or_dossier: p, procedure: @procedure)), path + = link_to_if dossier.hidden_by_administration_at.blank?, render(Instructeurs::SVASVRDecisionBadgeComponent.new(projection_or_dossier: dossier, procedure: @procedure)), path %td.follow-col %ul.fr-btns-group.fr-btns-group--sm.fr-btns-group--inline.fr-btns-group--icon-right = render partial: 'instructeurs/procedures/dossier_actions', locals: { procedure_id: @procedure.id, - dossier_id: p.dossier_id, - state: p.state, - archived: p.archived, - dossier_is_followed: @followed_dossiers_id.include?(p.dossier_id), + dossier_id: dossier.id, + state: dossier.state, + archived: dossier.archived, + dossier_is_followed: @followed_dossiers_id.include?(dossier.id), close_to_expiration: @statut == 'expirant', hidden_by_administration: @statut == 'supprimes', - hidden_by_expired: p.hidden_by_reason == 'expired', + hidden_by_expired: dossier.hidden_by_reason == 'expired', sva_svr: @procedure.sva_svr_enabled?, - has_blocking_pending_correction: @procedure.feature_enabled?(:blocking_pending_correction) && p.pending_correction?, + has_blocking_pending_correction: @procedure.feature_enabled?(:blocking_pending_correction) && dossier.pending_correction?, turbo: false, with_menu: false } diff --git a/spec/services/dossier_projection_service_spec.rb b/spec/services/dossier_projection_service_spec.rb index c9168eb39..e08743c0c 100644 --- a/spec/services/dossier_projection_service_spec.rb +++ b/spec/services/dossier_projection_service_spec.rb @@ -29,17 +29,17 @@ describe DossierProjectionService do it 'respects the dossiers_ids order, returns state, archived and nil for empty result' do expect(result.length).to eq(3) - expect(result[0].dossier_id).to eq(dossier_3.id) - expect(result[1].dossier_id).to eq(dossier_1.id) - expect(result[2].dossier_id).to eq(dossier_2.id) + expect(result[0].dossier.id).to eq(dossier_3.id) + expect(result[1].dossier.id).to eq(dossier_1.id) + expect(result[2].dossier.id).to eq(dossier_2.id) - expect(result[0].state).to eq('en_instruction') - expect(result[1].state).to eq('brouillon') - expect(result[2].state).to eq('en_construction') + expect(result[0].dossier.state).to eq('en_instruction') + expect(result[1].dossier.state).to eq('brouillon') + expect(result[2].dossier.state).to eq('en_construction') - expect(result[0].archived).to be false - expect(result[1].archived).to be false - expect(result[2].archived).to be true + expect(result[0].dossier.archived).to be false + expect(result[1].dossier.archived).to be false + expect(result[2].dossier.archived).to be true expect(result[0].columns[0]).to be nil expect(result[1].columns[0]).to eq('champ_1') @@ -66,7 +66,7 @@ describe DossierProjectionService do it 'returns champ value' do expect(result.length).to eq(1) - expect(result[0].dossier_id).to eq(dossier.id) + expect(result[0].dossier.id).to eq(dossier.id) expect(result[0].columns[0]).to eq('Châteldon (63290)') end end From bb198000fecff92f8da0f9116798c1c05168bb4a Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Thu, 21 Nov 2024 11:36:49 +0100 Subject: [PATCH 4/7] refactor: include corrections --- .../sva_svr_decision_badge_component.rb | 28 ++++++++----------- app/services/dossier_projection_service.rb | 21 ++------------ .../dossiers/_header_top.html.haml | 2 +- .../instructeurs/procedures/show.html.haml | 6 ++-- .../sva_svr_decision_badge_component_spec.rb | 20 +------------ .../dossier_projection_service_spec.rb | 28 ------------------- 6 files changed, 20 insertions(+), 85 deletions(-) diff --git a/app/components/instructeurs/sva_svr_decision_badge_component.rb b/app/components/instructeurs/sva_svr_decision_badge_component.rb index afc647749..cb8e63081 100644 --- a/app/components/instructeurs/sva_svr_decision_badge_component.rb +++ b/app/components/instructeurs/sva_svr_decision_badge_component.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true class Instructeurs::SVASVRDecisionBadgeComponent < ApplicationComponent - attr_reader :object + attr_reader :dossier attr_reader :procedure attr_reader :with_label - def initialize(projection_or_dossier:, procedure:, with_label: false) - @object = projection_or_dossier + def initialize(dossier:, procedure:, with_label: false) + @dossier = dossier @procedure = procedure @decision = procedure.sva_svr_configuration.decision.to_sym @with_label = with_label @@ -15,11 +15,11 @@ class Instructeurs::SVASVRDecisionBadgeComponent < ApplicationComponent def render? return false unless procedure.sva_svr_enabled? - [:en_construction, :en_instruction].include? object.state.to_sym + [:en_construction, :en_instruction].include? dossier.state.to_sym end def without_date? - object.sva_svr_decision_on.nil? + dossier.sva_svr_decision_on.nil? end def classes @@ -31,17 +31,17 @@ class Instructeurs::SVASVRDecisionBadgeComponent < ApplicationComponent end def soon? - return false if object.sva_svr_decision_on.nil? + return false if dossier.sva_svr_decision_on.nil? - object.sva_svr_decision_on < 7.days.from_now.to_date + dossier.sva_svr_decision_on < 7.days.from_now.to_date end def pending_correction? - object.pending_correction? + dossier.pending_correction? end def days_count - (object.sva_svr_decision_on - Date.current).to_i + (dossier.sva_svr_decision_on - Date.current).to_i end def sva? @@ -66,7 +66,7 @@ class Instructeurs::SVASVRDecisionBadgeComponent < ApplicationComponent elsif pending_correction? t(".dossier_terminated_x_days_after_correction", count: days_count) else - t(".dossier_terminated_on", date: helpers.l(object.sva_svr_decision_on)) + t(".dossier_terminated_on", date: helpers.l(dossier.sva_svr_decision_on)) end end @@ -75,14 +75,10 @@ class Instructeurs::SVASVRDecisionBadgeComponent < ApplicationComponent end def previously_termine? - return if !object.respond_to?(:previously_termine?) - - object.previously_termine? + dossier.previously_termine? end def depose_before_configuration? - return if !object.respond_to?(:sva_svr_decision_triggered_at) - - object.sva_svr_decision_on.nil? && object.sva_svr_decision_triggered_at.nil? + dossier.sva_svr_decision_on.nil? && dossier.sva_svr_decision_triggered_at.nil? end end diff --git a/app/services/dossier_projection_service.rb b/app/services/dossier_projection_service.rb index 8720a0797..b8d424e4f 100644 --- a/app/services/dossier_projection_service.rb +++ b/app/services/dossier_projection_service.rb @@ -1,19 +1,7 @@ # frozen_string_literal: true class DossierProjectionService - class DossierProjection < Struct.new(:dossier, :corrections, :columns) do - def pending_correction? - return false if corrections.blank? - - corrections.any? { _1[:resolved_at].nil? } - end - - def resolved_corrections? - return false if corrections.blank? - - corrections.all? { _1[:resolved_at].present? } - end - end + class DossierProjection < Struct.new(:dossier, :columns) end def self.for_tiers_translation(array) @@ -51,9 +39,7 @@ class DossierProjectionService end champ_value = champ_value_formatter(dossiers_ids, fields) - dossier_corrections = { TABLE => 'dossier_corrections', COLUMN => 'resolved_at' } - - ([dossier_corrections] + fields) + fields .each { |f| f[:id_value_h] = {} } .group_by { |f| f[TABLE] } # one query per table .each do |table, fields| @@ -163,12 +149,11 @@ class DossierProjectionService end end - dossiers = Dossier.find(dossiers_ids) + dossiers = Dossier.includes(:corrections, :pending_corrections).find(dossiers_ids) dossiers_ids.map do |dossier_id| DossierProjection.new( dossiers.find { _1.id == dossier_id }, - dossier_corrections[:id_value_h][dossier_id], fields.map { |f| f[:id_value_h][dossier_id] } ) end diff --git a/app/views/instructeurs/dossiers/_header_top.html.haml b/app/views/instructeurs/dossiers/_header_top.html.haml index f01fc0d4b..583021b7a 100644 --- a/app/views/instructeurs/dossiers/_header_top.html.haml +++ b/app/views/instructeurs/dossiers/_header_top.html.haml @@ -13,7 +13,7 @@ = pending_correction_badge(:for_instructeur) - elsif dossier.en_construction? && dossier.last_correction_resolved? = correction_resolved_badge - = render Instructeurs::SVASVRDecisionBadgeComponent.new(projection_or_dossier: dossier, procedure: dossier.procedure, with_label: true) + = render Instructeurs::SVASVRDecisionBadgeComponent.new(dossier:, procedure: dossier.procedure, with_label: true) .header-actions.fr-ml-auto diff --git a/app/views/instructeurs/procedures/show.html.haml b/app/views/instructeurs/procedures/show.html.haml index 6cb301ba6..dd6391901 100644 --- a/app/views/instructeurs/procedures/show.html.haml +++ b/app/views/instructeurs/procedures/show.html.haml @@ -152,16 +152,16 @@ %td - status = [status_badge(dossier.state)] - - if p.pending_correction? + - if dossier.pending_correction? - status << pending_correction_badge(:for_instructeur, html_class: "fr-mt-1v") - - elsif dossier.state.to_sym == :en_construction && p.resolved_corrections? + - elsif dossier.last_correction_resolved? - status << correction_resolved_badge(html_class: "fr-mt-1v") = link_to_if(dossier.hidden_by_administration_at.blank?, safe_join(status), path, class: "flex column") - if @procedure.sva_svr_enabled? %td %span - = link_to_if dossier.hidden_by_administration_at.blank?, render(Instructeurs::SVASVRDecisionBadgeComponent.new(projection_or_dossier: dossier, procedure: @procedure)), path + = link_to_if dossier.hidden_by_administration_at.blank?, render(Instructeurs::SVASVRDecisionBadgeComponent.new(dossier:, procedure: @procedure)), path %td.follow-col %ul.fr-btns-group.fr-btns-group--sm.fr-btns-group--inline.fr-btns-group--icon-right diff --git a/spec/components/instructeurs/sva_svr_decision_badge_component_spec.rb b/spec/components/instructeurs/sva_svr_decision_badge_component_spec.rb index 357ff17ba..3eb3901f0 100644 --- a/spec/components/instructeurs/sva_svr_decision_badge_component_spec.rb +++ b/spec/components/instructeurs/sva_svr_decision_badge_component_spec.rb @@ -10,7 +10,7 @@ RSpec.describe Instructeurs::SVASVRDecisionBadgeComponent, type: :component do context 'with dossier object' do subject do - render_inline(described_class.new(projection_or_dossier: dossier, procedure:, with_label:)) + render_inline(described_class.new(dossier:, procedure:, with_label:)) end let(:title) { subject.at_css("span")["title"] } @@ -54,22 +54,4 @@ RSpec.describe Instructeurs::SVASVRDecisionBadgeComponent, type: :component do it { expect(subject).to have_text("4 j. après correction") } end end - - context 'with projection object' do - subject do - render_inline(described_class.new(projection_or_dossier: projection, procedure:, with_label:)) - end - - context 'dossier en instruction' do - let(:projection) { DossierProjectionService::DossierProjection.new(dossier_id: 12, state: :en_instruction, sva_svr_decision_on: Date.new(2023, 9, 5)) } - - it { expect(subject).to have_text("dans 4 jours") } - end - - context 'dossier without sva decision date' do - let(:projection) { DossierProjectionService::DossierProjection.new(dossier_id: 12, state: :en_instruction) } - - it { expect(subject).to have_text("Instruction manuelle") } - end - end end diff --git a/spec/services/dossier_projection_service_spec.rb b/spec/services/dossier_projection_service_spec.rb index e08743c0c..0cf12fcef 100644 --- a/spec/services/dossier_projection_service_spec.rb +++ b/spec/services/dossier_projection_service_spec.rb @@ -249,34 +249,6 @@ describe DossierProjectionService do it { is_expected.to eq('38') } end - - context 'for dossier corrections table' do - let(:table) { 'dossier_corrections' } - let(:column) { 'resolved_at' } - let(:procedure) { create(:procedure) } - let(:columns) { [Column.new(procedure_id: procedure.id, table:, column:)] } # should somehow be present in column concern - let(:dossier) { create(:dossier, :en_construction, procedure:) } - subject { described_class.project(dossiers_ids, columns)[0] } - - context "when dossier has pending correction" do - before { create(:dossier_correction, dossier:) } - - it { expect(subject.pending_correction?).to be(true) } - it { expect(subject.resolved_corrections?).to eq(false) } - end - - context "when dossier has a resolved correction" do - before { create(:dossier_correction, :resolved, dossier:) } - - it { expect(subject.pending_correction?).to eq(false) } - it { expect(subject.resolved_corrections?).to eq(true) } - end - - context "when dossier has no correction at all" do - it { expect(subject.pending_correction?).to eq(false) } - it { expect(subject.resolved_corrections?).to eq(false) } - end - end end end end From 18a4ee450f7ec19ab36d98867790ccdc97af540c Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Thu, 21 Nov 2024 12:05:47 +0100 Subject: [PATCH 5/7] refactor: do not query for already load dossier table --- app/services/dossier_projection_service.rb | 26 ++++++++++------------ 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/app/services/dossier_projection_service.rb b/app/services/dossier_projection_service.rb index b8d424e4f..616ce055a 100644 --- a/app/services/dossier_projection_service.rb +++ b/app/services/dossier_projection_service.rb @@ -30,11 +30,13 @@ class DossierProjectionService # - the order of the intermediary query results are unknown # - some values can be missing (if a revision added or removed them) def self.project(dossiers_ids, columns) + dossiers = Dossier.includes(:corrections, :pending_corrections).find(dossiers_ids) + fields = columns.map do |c| if c.is_a?(Columns::ChampColumn) { TABLE => c.table, STABLE_ID => c.stable_id, original_column: c } else - { TABLE => c.table, COLUMN => c.column } + { TABLE => c.table, COLUMN => c.column, original_column: c } end end champ_value = champ_value_formatter(dossiers_ids, fields) @@ -61,19 +63,17 @@ class DossierProjectionService end end when 'self' - Dossier - .where(id: dossiers_ids) - .pluck(:id, *fields.map { |f| f[COLUMN].to_sym }) - .each do |id, *columns| - fields.zip(columns).each do |field, value| - # SVA must remain a date: in other column we compute remaining delay with it - field[:id_value_h][id] = if value.respond_to?(:strftime) - I18n.l(value.to_date) - else - value - end + dossiers.each do |dossier| + fields.each do |field| + column = field[:original_column] + value = column.value(dossier) + field[:id_value_h][dossier.id] = if value.respond_to?(:strftime) + I18n.l(value.to_date) + else + value end end + end when 'individual' Individual .where(dossier_id: dossiers_ids) @@ -149,8 +149,6 @@ class DossierProjectionService end end - dossiers = Dossier.includes(:corrections, :pending_corrections).find(dossiers_ids) - dossiers_ids.map do |dossier_id| DossierProjection.new( dossiers.find { _1.id == dossier_id }, From d287eac70682eaaa91acb2b4d5e01632777ee082 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Thu, 21 Nov 2024 18:38:28 +0100 Subject: [PATCH 6/7] refactor: fix n+1 --- app/models/dossier.rb | 2 +- app/models/traitement.rb | 2 ++ app/services/dossier_projection_service.rb | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/models/dossier.rb b/app/models/dossier.rb index f41be6147..35531a4b9 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -896,7 +896,7 @@ class Dossier < ApplicationRecord end def previously_termine? - traitements.termine.exists? + traitements.any?(&:termine?) end def remove_titres_identite! diff --git a/app/models/traitement.rb b/app/models/traitement.rb index 0a3929b57..95612dfd6 100644 --- a/app/models/traitement.rb +++ b/app/models/traitement.rb @@ -26,4 +26,6 @@ class Traitement < ApplicationRecord self.browser_supported = BrowserSupport.supported?(browser) end end + + def termine? = state.in?(Dossier::TERMINE) end diff --git a/app/services/dossier_projection_service.rb b/app/services/dossier_projection_service.rb index 616ce055a..cd4e9cea3 100644 --- a/app/services/dossier_projection_service.rb +++ b/app/services/dossier_projection_service.rb @@ -30,7 +30,7 @@ class DossierProjectionService # - the order of the intermediary query results are unknown # - some values can be missing (if a revision added or removed them) def self.project(dossiers_ids, columns) - dossiers = Dossier.includes(:corrections, :pending_corrections).find(dossiers_ids) + dossiers = Dossier.includes(:corrections, :pending_corrections, :traitements).find(dossiers_ids) fields = columns.map do |c| if c.is_a?(Columns::ChampColumn) From 96ee0650461f74ed3fd2dd94b90782b5fd485768 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 22 Nov 2024 12:39:27 +0100 Subject: [PATCH 7/7] adapt search page --- app/views/recherche/index.html.haml | 42 +++++++++---------- spec/controllers/recherche_controller_spec.rb | 10 ++--- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/app/views/recherche/index.html.haml b/app/views/recherche/index.html.haml index 81cae30c8..aa567505c 100644 --- a/app/views/recherche/index.html.haml +++ b/app/views/recherche/index.html.haml @@ -27,23 +27,24 @@ %th.follow-col %tbody - @projected_dossiers.each do |p| + - dossier = p.dossier - procedure_libelle, user_email, procedure_id = p.columns - - instructeur_dossier = @instructeur_dossiers_ids.include?(p.dossier_id) - - expert_dossier = @dossier_avis_ids_h[p.dossier_id].present? - - hidden_by_administration = p.hidden_by_administration_at.present? + - instructeur_dossier = @instructeur_dossiers_ids.include?(dossier.id) + - expert_dossier = @dossier_avis_ids_h[dossier.id].present? + - hidden_by_administration = dossier.hidden_by_administration_at.present? - instructeur_and_expert_dossier = instructeur_dossier && expert_dossier - - path = instructeur_dossier ? instructeur_dossier_path(procedure_id, p.dossier_id) : expert_avis_path(procedure_id, @dossier_avis_ids_h[p.dossier_id]) + - path = instructeur_dossier ? instructeur_dossier_path(procedure_id, dossier.id) : expert_avis_path(procedure_id, @dossier_avis_ids_h[dossier.id]) - %tr{ class: [p.hidden_by_administration_at.present? && "file-hidden-by-user"] } + %tr{ class: [dossier.hidden_by_administration_at.present? && "file-hidden-by-user"] } - if instructeur_and_expert_dossier %td.fr-cell--numeric .relative - = p.dossier_id - - if @notifications_dossier_ids.include?(p.dossier_id) + = dossier.id + - if @notifications_dossier_ids.include?(dossier.id) %span.notifications{ 'aria-label': 'notifications' } %td.fr-cell--multiline= procedure_libelle %td= user_email - %td.flex.column= status_badge(p.state) + %td.flex.column= status_badge(dossier.state) - elsif hidden_by_administration = render partial: "recherche/hidden_dossier", locals: {p: p, procedure_libelle: procedure_libelle, user_email: user_email} @@ -51,8 +52,8 @@ - else %td.fr-cell--numeric %a.fr-link.relative{ href: path } - = p.dossier_id - - if @notifications_dossier_ids.include?(p.dossier_id) + = dossier.id + - if @notifications_dossier_ids.include?(dossier.id) %span.notifications{ 'aria-label': 'notifications' } %td @@ -62,8 +63,7 @@ %a{ href: path }= user_email %td - %a.flex.column{ href: path }= status_badge(p.state) - + %a.flex.column{ href: path }= status_badge(dossier.state) - if instructeur_dossier && expert_dossier %td.follow-col @@ -72,13 +72,13 @@ Actions - menu.with_item do - = link_to(instructeur_dossier_path(procedure_id, p.dossier_id), role: 'menuitem') do + = link_to(instructeur_dossier_path(procedure_id, dossier.id), role: 'menuitem') do = dsfr_icon('fr-icon-file-text-fill', :sm) .dropdown-description Voir le dossier - menu.with_item do - = link_to(expert_avis_path(procedure_id, @dossier_avis_ids_h[p.dossier_id]), role: 'menuitem') do + = link_to(expert_avis_path(procedure_id, @dossier_avis_ids_h[dossier.id]), role: 'menuitem') do = dsfr_icon('fr-icon-chat-3-fill', :sm) .dropdown-description Donner mon avis @@ -86,7 +86,7 @@ - elsif instructeur_dossier - if hidden_by_administration %td.follow-col - = link_to restore_instructeur_dossier_path(procedure_id, p.dossier_id), method: :patch, class: "button primary" do + = link_to restore_instructeur_dossier_path(procedure_id, dossier.id), method: :patch, class: "button primary" do = t('views.instructeurs.dossiers.restore') - else @@ -94,15 +94,15 @@ %ul.fr-btns-group.fr-btns-group--sm.fr-btns-group--inline-lg.fr-btns-group--icon-right = render partial: "instructeurs/procedures/dossier_actions", locals: { procedure_id: procedure_id, - dossier_id: p.dossier_id, - state: p.state, - archived: p.archived, - dossier_is_followed: @followed_dossiers_id.include?(p.dossier_id), + dossier_id: dossier.id, + state: dossier.state, + archived: dossier.archived, + dossier_is_followed: @followed_dossiers_id.include?(dossier.id), close_to_expiration: nil, hidden_by_administration: nil, hidden_by_expired: nil, - sva_svr: p.sva_svr_decision_on.present?, - has_blocking_pending_correction: p.pending_correction? && Flipper.enabled?(:blocking_pending_correction, ProcedureFlipperActor.new(procedure_id)), + sva_svr: dossier.sva_svr_decision_on.present?, + has_blocking_pending_correction: dossier.pending_correction? && Flipper.enabled?(:blocking_pending_correction, ProcedureFlipperActor.new(procedure_id)), turbo: false, with_menu: false } diff --git a/spec/controllers/recherche_controller_spec.rb b/spec/controllers/recherche_controller_spec.rb index ec5c6910a..16562c728 100644 --- a/spec/controllers/recherche_controller_spec.rb +++ b/spec/controllers/recherche_controller_spec.rb @@ -48,7 +48,7 @@ describe RechercheController, type: :controller do it 'returns the expected dossier' do expect(assigns(:projected_dossiers).count).to eq(1) - expect(assigns(:projected_dossiers).first.dossier_id).to eq(dossier.id) + expect(assigns(:projected_dossiers).first.dossier).to eq(dossier) end end @@ -62,7 +62,7 @@ describe RechercheController, type: :controller do it 'returns the expected dossier' do expect(assigns(:projected_dossiers).count).to eq(1) - expect(assigns(:projected_dossiers).first.dossier_id).to eq(dossier_with_expert.id) + expect(assigns(:projected_dossiers).first.dossier).to eq(dossier_with_expert) end end @@ -146,7 +146,7 @@ describe RechercheController, type: :controller do it 'returns the expected dossier' do subject expect(assigns(:projected_dossiers).count).to eq(1) - expect(assigns(:projected_dossiers).first.dossier_id).to eq(dossier.id) + expect(assigns(:projected_dossiers).first.dossier).to eq(dossier) end context 'when dossier has notification' do @@ -170,7 +170,7 @@ describe RechercheController, type: :controller do it 'returns only the dossier available to the expert' do subject expect(assigns(:projected_dossiers).count).to eq(1) - expect(assigns(:projected_dossiers).first.dossier_id).to eq(dossier_with_expert.id) + expect(assigns(:projected_dossiers).first.dossier).to eq(dossier_with_expert) end end end @@ -184,7 +184,7 @@ describe RechercheController, type: :controller do it 'returns the expected dossier' do expect(assigns(:projected_dossiers).count).to eq(1) - expect(assigns(:projected_dossiers).first.dossier_id).to eq(dossier_with_expert.id) + expect(assigns(:projected_dossiers).first.dossier).to eq(dossier_with_expert) end context 'as an expert' do