From c0ad7853cb41fe0430083daf40824aafd3b43e2c Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 9 Feb 2023 14:39:33 +0100 Subject: [PATCH] fix(administrateur): procedure page n+1 --- .../administrateurs/procedures_controller.rb | 46 +++++++++++++++++-- .../concerns/tags_substitution_concern.rb | 4 +- app/models/procedure.rb | 15 +++--- app/models/procedure_revision.rb | 23 +++++++--- app/validators/tags_validator.rb | 22 ++++----- spec/models/type_de_champ_spec.rb | 2 +- 6 files changed, 83 insertions(+), 29 deletions(-) diff --git a/app/controllers/administrateurs/procedures_controller.rb b/app/controllers/administrateurs/procedures_controller.rb index c206b3724..e81a3a42c 100644 --- a/app/controllers/administrateurs/procedures_controller.rb +++ b/app/controllers/administrateurs/procedures_controller.rb @@ -96,8 +96,20 @@ module Administrateurs @procedure = current_administrateur .procedures .includes( - published_revision: :types_de_champ, - draft_revision: :types_de_champ + published_revision: { + types_de_champ: [], + revision_types_de_champ: { type_de_champ: { piece_justificative_template_attachment: :blob } } + }, + draft_revision: { + types_de_champ: [], + revision_types_de_champ: { type_de_champ: { piece_justificative_template_attachment: :blob } } + }, + attestation_template: [], + initiated_mail: [], + received_mail: [], + closed_mail: [], + refused_mail: [], + without_continuation_mail: [] ) .find(params[:id]) @@ -332,7 +344,35 @@ module Administrateurs end def champs - @procedure = Procedure.includes(draft_revision: { revision_types_de_champ_public: :type_de_champ }).find(@procedure.id) + @procedure = Procedure.includes(draft_revision: { + revision_types_de_champ: { + type_de_champ: { piece_justificative_template_attachment: :blob, revision: [], procedure: [] }, + revision: [], + procedure: [] + }, + revision_types_de_champ_public: { + type_de_champ: { piece_justificative_template_attachment: :blob, revision: [], procedure: [] }, + revision: [], + procedure: [] + }, + procedure: [] + }).find(@procedure.id) + end + + def annotations + @procedure = Procedure.includes(draft_revision: { + revision_types_de_champ: { + type_de_champ: { piece_justificative_template_attachment: :blob, revision: [], procedure: [] }, + revision: [], + procedure: [] + }, + revision_types_de_champ_private: { + type_de_champ: { piece_justificative_template_attachment: :blob, revision: [], procedure: [] }, + revision: [], + procedure: [] + }, + procedure: [] + }).find(@procedure.id) end def detail diff --git a/app/models/concerns/tags_substitution_concern.rb b/app/models/concerns/tags_substitution_concern.rb index 972882f5b..86f5f1100 100644 --- a/app/models/concerns/tags_substitution_concern.rb +++ b/app/models/concerns/tags_substitution_concern.rb @@ -270,12 +270,12 @@ module TagsSubstitutionConcern end def champ_public_tags(dossier: nil) - types_de_champ = (dossier || procedure.active_revision).types_de_champ_public.not_condition + types_de_champ = (dossier || procedure.active_revision).types_de_champ_public.filter { !_1.condition? } types_de_champ_tags(types_de_champ, Dossier::SOUMIS) end def champ_private_tags(dossier: nil) - types_de_champ = (dossier || procedure.active_revision).types_de_champ_private.not_condition + types_de_champ = (dossier || procedure.active_revision).types_de_champ_private.filter { !_1.condition? } types_de_champ_tags(types_de_champ, Dossier::INSTRUCTION_COMMENCEE) end diff --git a/app/models/procedure.rb b/app/models/procedure.rb index b6ef52750..8e8515bd6 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -173,12 +173,15 @@ class Procedure < ApplicationRecord types_de_champ_for_tags.private_only end - def revision_ids_with_pending_dossiers - dossiers - .where.not(revision_id: [draft_revision_id, published_revision_id].compact) - .state_en_construction_ou_instruction - .distinct(:revision_id) - .pluck(:revision_id) + def revisions_with_pending_dossiers + @revisions_with_pending_dossiers ||= begin + ids = dossiers + .where.not(revision_id: [draft_revision_id, published_revision_id].compact) + .state_en_construction_ou_instruction + .distinct(:revision_id) + .pluck(:revision_id) + ProcedureRevision.includes(revision_types_de_champ: [:type_de_champ]).where(id: ids) + end end has_many :administrateurs_procedures, dependent: :delete_all diff --git a/app/models/procedure_revision.rb b/app/models/procedure_revision.rb index 7e94d0595..ff3e587b5 100644 --- a/app/models/procedure_revision.rb +++ b/app/models/procedure_revision.rb @@ -132,7 +132,7 @@ class ProcedureRevision < ApplicationRecord end def draft? - procedure.draft_revision == self + procedure.draft_revision_id == id end def locked? @@ -172,11 +172,22 @@ class ProcedureRevision < ApplicationRecord end def children_of(tdc) - parent_coordinate_id = revision_types_de_champ.where(type_de_champ: tdc).select(:id) + if revision_types_de_champ.loaded? + parent_coordinate_id = revision_types_de_champ + .filter { _1.type_de_champ_id == tdc.id } + .map(&:id) - types_de_champ - .where(procedure_revision_types_de_champ: { parent_id: parent_coordinate_id }) - .order("procedure_revision_types_de_champ.position") + revision_types_de_champ + .filter { _1.parent_id.in?(parent_coordinate_id) } + .sort_by(&:position) + .map(&:type_de_champ) + else + parent_coordinate_id = revision_types_de_champ.where(type_de_champ: tdc).select(:id) + + types_de_champ + .where(procedure_revision_types_de_champ: { parent_id: parent_coordinate_id }) + .order("procedure_revision_types_de_champ.position") + end end def remove_children_of(tdc) @@ -380,7 +391,7 @@ class ProcedureRevision < ApplicationRecord public_tdcs .map.with_index - .filter_map { |tdc, i| tdc.condition.present? ? [tdc, i] : nil } + .filter_map { |tdc, i| tdc.condition? ? [tdc, i] : nil } .map { |tdc, i| [tdc, tdc.condition.errors(public_tdcs.take(i))] } .filter { |_tdc, errors| errors.present? } .each { |tdc, message| errors.add(:condition, message, type_de_champ: tdc) } diff --git a/app/validators/tags_validator.rb b/app/validators/tags_validator.rb index b8f3520aa..4b55c5cf9 100644 --- a/app/validators/tags_validator.rb +++ b/app/validators/tags_validator.rb @@ -7,18 +7,18 @@ class TagsValidator < ActiveModel::EachValidator tag if stable_id.nil? end - invalid_for_draft_revision = invalid_tags_for_revision(record, attribute, tags, procedure.draft_revision_id) + invalid_for_draft_revision = invalid_tags_for_revision(record, attribute, tags, procedure.draft_revision) invalid_for_published_revision = if procedure.published_revision_id.present? - invalid_tags_for_revision(record, attribute, tags, procedure.published_revision_id) + invalid_tags_for_revision(record, attribute, tags, procedure.published_revision) else [] end invalid_for_previous_revision = procedure - .revision_ids_with_pending_dossiers - .flat_map do |revision_id| - invalid_tags_for_revision(record, attribute, tags, revision_id) + .revisions_with_pending_dossiers + .flat_map do |revision| + invalid_tags_for_revision(record, attribute, tags, revision) end.uniq # champ is added in draft revision but not yet published @@ -48,12 +48,12 @@ class TagsValidator < ActiveModel::EachValidator end end - def invalid_tags_for_revision(record, attribute, tags, revision_id) - revision_stable_ids = TypeDeChamp - .joins(:revision_types_de_champ) - .where(procedure_revision_types_de_champ: { revision_id: revision_id, parent_id: nil }) - .distinct(:stable_id) - .pluck(:stable_id) + def invalid_tags_for_revision(record, attribute, tags, revision) + revision_stable_ids = revision + .revision_types_de_champ + .filter { !_1.child? } + .map(&:stable_id) + .uniq tags.filter_map do |(tag, stable_id)| if stable_id.present? && !stable_id.in?(revision_stable_ids) diff --git a/spec/models/type_de_champ_spec.rb b/spec/models/type_de_champ_spec.rb index 785cf9e8f..d7f5c5502 100644 --- a/spec/models/type_de_champ_spec.rb +++ b/spec/models/type_de_champ_spec.rb @@ -95,7 +95,7 @@ describe TypeDeChamp do let(:target_type_champ) { TypeDeChamp.type_champs.fetch(:text) } it 'removes the children types de champ' do - expect(procedure.draft_revision.children_of(tdc)).to be_empty + expect(procedure.draft_revision.reload.children_of(tdc)).to be_empty end end end