refactor(type_de_champ): improve and clean helper methods

This commit is contained in:
Paul Chavard 2024-11-04 15:59:58 +01:00
parent 5a2ab37049
commit 71009094a4
No known key found for this signature in database
8 changed files with 74 additions and 79 deletions

View file

@ -122,8 +122,8 @@ module ProcedurePublishConcern
end end
def cleanup_types_de_champ_children! def cleanup_types_de_champ_children!
draft_revision.types_de_champ.reject(&:repetition?).each do |type_de_champ| draft_revision.revision_types_de_champ
draft_revision.remove_children_of(type_de_champ) .filter(&:orphan?)
end .each { draft_revision.remove_type_de_champ(_1.stable_id) }
end end
end end

View file

@ -39,7 +39,7 @@ class DossierPreloader
def revisions(pj_template: false) def revisions(pj_template: false)
@revisions ||= ProcedureRevision.where(id: @dossiers.pluck(:revision_id).uniq) @revisions ||= ProcedureRevision.where(id: @dossiers.pluck(:revision_id).uniq)
.includes(procedure: [], revision_types_de_champ: { parent: :type_de_champ }, types_de_champ_public: [], types_de_champ_private: [], types_de_champ: pj_template ? { piece_justificative_template_attachment: :blob } : []) .includes(procedure: [], revision_types_de_champ: { parent_type_de_champ: [], types_de_champ: [] }, types_de_champ_public: [], types_de_champ_private: [], types_de_champ: pj_template ? { piece_justificative_template_attachment: :blob } : [])
.index_by(&:id) .index_by(&:id)
end end

View file

@ -45,22 +45,26 @@ class ProcedureRevision < ApplicationRecord
after_stable_id = params.delete(:after_stable_id) after_stable_id = params.delete(:after_stable_id)
after_coordinate, _ = coordinate_and_tdc(after_stable_id) after_coordinate, _ = coordinate_and_tdc(after_stable_id)
siblings = siblings_for(parent_coordinate:, private_tdc: params[:private]) type_de_champ = TypeDeChamp.new(params)
tdc = TypeDeChamp.new(params) if type_de_champ.save
if tdc.save siblings = siblings_for(type_de_champ:, parent_coordinate:)
position = next_position_for(after_coordinate:)
transaction do
# moving all the impacted tdc down # moving all the impacted tdc down
position = next_position_for(after_coordinate:, siblings:)
siblings.where("position >= ?", position).update_all("position = position + 1") siblings.where("position >= ?", position).update_all("position = position + 1")
# insertion of the new tdc # insertion of the new tdc
h = { type_de_champ: tdc, parent_id: parent_id, position: position } revision_types_de_champ.create!(type_de_champ:, parent_id:, position:)
revision_types_de_champ.create!(h)
end end
tdc revision_types_de_champ.reset
end
type_de_champ
rescue => e rescue => e
TypeDeChamp.new.tap { |tdc| tdc.errors.add(:base, e.message) } TypeDeChamp.new.tap { _1.errors.add(:base, e.message) }
end end
def find_and_ensure_exclusive_use(stable_id) def find_and_ensure_exclusive_use(stable_id)
@ -77,12 +81,17 @@ class ProcedureRevision < ApplicationRecord
coordinate, _ = coordinate_and_tdc(stable_id) coordinate, _ = coordinate_and_tdc(stable_id)
siblings = coordinate.siblings siblings = coordinate.siblings
transaction do
if position > coordinate.position if position > coordinate.position
siblings.where(position: coordinate.position..position).update_all("position = position - 1") siblings.where(position: coordinate.position..position).update_all("position = position - 1")
else else
siblings.where(position: position..coordinate.position).update_all("position = position + 1") siblings.where(position: position..coordinate.position).update_all("position = position + 1")
end end
coordinate.update_column(:position, position) coordinate.update_column(:position, position)
end
revision_types_de_champ.reset
coordinate.reload
coordinate coordinate
end end
@ -90,6 +99,7 @@ class ProcedureRevision < ApplicationRecord
coordinate, _ = coordinate_and_tdc(stable_id) coordinate, _ = coordinate_and_tdc(stable_id)
siblings = coordinate.siblings siblings = coordinate.siblings
transaction do
if position > coordinate.position if position > coordinate.position
siblings.where(position: coordinate.position..position).update_all("position = position - 1") siblings.where(position: coordinate.position..position).update_all("position = position - 1")
coordinate.update_column(:position, position) coordinate.update_column(:position, position)
@ -97,9 +107,10 @@ class ProcedureRevision < ApplicationRecord
siblings.where(position: (position + 1)...coordinate.position).update_all("position = position + 1") siblings.where(position: (position + 1)...coordinate.position).update_all("position = position + 1")
coordinate.update_column(:position, position + 1) coordinate.update_column(:position, position + 1)
end end
end
revision_types_de_champ.reset
coordinate.reload coordinate.reload
coordinate coordinate
end end
@ -110,13 +121,17 @@ class ProcedureRevision < ApplicationRecord
return nil if coordinate.nil? return nil if coordinate.nil?
children = children_of(tdc).to_a children = children_of(tdc).to_a
transaction do
coordinate.destroy coordinate.destroy
children.each(&:destroy_if_orphan) children.each(&:destroy_if_orphan)
tdc.destroy_if_orphan tdc.destroy_if_orphan
coordinate.siblings.where("position >= ?", coordinate.position).update_all("position = position - 1") coordinate.siblings.where("position >= ?", coordinate.position).update_all("position = position - 1")
end
revision_types_de_champ.reset
coordinate coordinate
end end
@ -181,33 +196,11 @@ class ProcedureRevision < ApplicationRecord
end end
def children_of(tdc) def children_of(tdc)
if revision_types_de_champ.loaded? coordinate_for(tdc).types_de_champ
parent_coordinate_id = revision_types_de_champ
.filter { _1.type_de_champ_id == tdc.id }
.map(&:id)
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 end
def parent_of(tdc) def parent_of(tdc)
revision_types_de_champ coordinate_for(tdc).parent_type_de_champ
.find { _1.type_de_champ_id == tdc.id }.parent&.type_de_champ
end
def remove_children_of(tdc)
children_of(tdc).each do |child|
remove_type_de_champ(child.stable_id)
end
end end
def dependent_conditions(tdc) def dependent_conditions(tdc)
@ -268,24 +261,17 @@ class ProcedureRevision < ApplicationRecord
end end
end end
def children_types_de_champ_as_json(tdcs_as_json, parent_tdcs) def siblings_for(type_de_champ:, parent_coordinate: nil)
parent_tdcs.each do |parent_tdc|
tdc_as_json = tdcs_as_json.find { |json| json["id"] == parent_tdc.stable_id }
tdc_as_json&.merge!(types_de_champ: children_of(parent_tdc).includes(piece_justificative_template_attachment: :blob).map(&:as_json_for_editor))
end
end
def siblings_for(parent_coordinate: nil, private_tdc: false)
if parent_coordinate if parent_coordinate
parent_coordinate.revision_types_de_champ parent_coordinate.revision_types_de_champ
elsif private_tdc elsif type_de_champ.private?
revision_types_de_champ_private revision_types_de_champ_private
else else
revision_types_de_champ_public revision_types_de_champ_public
end end
end end
def next_position_for(siblings:, after_coordinate: nil) def next_position_for(after_coordinate: nil)
# either we are at the beginning of the list or after another item # either we are at the beginning of the list or after another item
if after_coordinate.nil? # first element of the list, starts at 0 if after_coordinate.nil? # first element of the list, starts at 0
0 0
@ -477,10 +463,12 @@ class ProcedureRevision < ApplicationRecord
end end
def replace_type_de_champ_by_clone(coordinate) def replace_type_de_champ_by_clone(coordinate)
transaction do
cloned_type_de_champ = coordinate.type_de_champ.deep_clone do |original, kopy| cloned_type_de_champ = coordinate.type_de_champ.deep_clone do |original, kopy|
ClonePiecesJustificativesService.clone_attachments(original, kopy) ClonePiecesJustificativesService.clone_attachments(original, kopy)
end end
coordinate.update!(type_de_champ: cloned_type_de_champ) coordinate.update!(type_de_champ: cloned_type_de_champ)
cloned_type_de_champ cloned_type_de_champ
end end
end
end end

View file

@ -5,7 +5,9 @@ class ProcedureRevisionTypeDeChamp < ApplicationRecord
belongs_to :type_de_champ belongs_to :type_de_champ
belongs_to :parent, class_name: 'ProcedureRevisionTypeDeChamp', optional: true belongs_to :parent, class_name: 'ProcedureRevisionTypeDeChamp', optional: true
has_one :parent_type_de_champ, through: :parent, source: :type_de_champ
has_many :revision_types_de_champ, -> { ordered }, foreign_key: :parent_id, class_name: 'ProcedureRevisionTypeDeChamp', inverse_of: :parent, dependent: :destroy has_many :revision_types_de_champ, -> { ordered }, foreign_key: :parent_id, class_name: 'ProcedureRevisionTypeDeChamp', inverse_of: :parent, dependent: :destroy
has_many :types_de_champ, through: :revision_types_de_champ, source: :type_de_champ
has_one :procedure, through: :revision has_one :procedure, through: :revision
scope :root, -> { where(parent: nil) } scope :root, -> { where(parent: nil) }
scope :ordered, -> { order(:position, :id) } scope :ordered, -> { order(:position, :id) }
@ -19,6 +21,10 @@ class ProcedureRevisionTypeDeChamp < ApplicationRecord
parent_id.present? parent_id.present?
end end
def orphan?
child? && !parent_type_de_champ.repetition?
end
def first? def first?
position == 0 position == 0
end end
@ -33,7 +39,7 @@ class ProcedureRevisionTypeDeChamp < ApplicationRecord
def siblings def siblings
if child? if child?
revision.revision_types_de_champ.where(parent_id:).ordered parent.revision_types_de_champ
elsif private? elsif private?
revision.revision_types_de_champ_private revision.revision_types_de_champ_private
else else

View file

@ -336,7 +336,7 @@ class TypeDeChamp < ApplicationRecord
end end
def child?(revision) def child?(revision)
revision.revision_types_de_champ.find { _1.stable_id == stable_id }&.child? revision.coordinate_for(self)&.child?
end end
def filename_for_attachement(attachment_sym) def filename_for_attachement(attachment_sym)
@ -403,10 +403,10 @@ class TypeDeChamp < ApplicationRecord
end end
def level_for_revision(revision) def level_for_revision(revision)
rtdc = revision.revision_types_de_champ.find { |rtdc| rtdc.stable_id == stable_id } parent_type_de_champ = revision.parent_of(self)
if rtdc.child? if parent_type_de_champ.present?
header_section_level_value.to_i + rtdc.parent.type_de_champ.current_section_level(revision) header_section_level_value.to_i + parent_type_de_champ.current_section_level(revision)
elsif header_section_level_value elsif header_section_level_value
header_section_level_value.to_i header_section_level_value.to_i
else else

View file

@ -31,8 +31,9 @@ describe Champ do
end end
context 'when repetition blank' do context 'when repetition blank' do
let(:type_de_champ) { build(:type_de_champ_repetition) } let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :repetition, mandatory: false, children: [{ type: :text }] }]) }
let(:champ) { Champs::RepetitionChamp.new(dossier: Dossier.new(revision: ProcedureRevision.new)) } let(:dossier) { create(:dossier, procedure:) }
let(:champ) { dossier.project_champs_public.find(&:repetition?) }
it { expect(champ.blank?).to be(true) } it { expect(champ.blank?).to be(true) }
end end

View file

@ -830,6 +830,7 @@ describe ProcedureRevision do
.revision_types_de_champ .revision_types_de_champ
.where(type_de_champ: first_child) .where(type_de_champ: first_child)
.update(type_de_champ: new_child) .update(type_de_champ: new_child)
new_draft.revision_types_de_champ.reload
end end
it 'returns the children regarding the revision' do it 'returns the children regarding the revision' do

View file

@ -398,9 +398,8 @@ describe Procedure do
expect(procedure.errors.messages_for(:draft_types_de_champ_public)).to include(invalid_repetition_error_message) expect(procedure.errors.messages_for(:draft_types_de_champ_public)).to include(invalid_repetition_error_message)
new_draft = procedure.draft_revision new_draft = procedure.draft_revision
repetition = procedure.draft_revision.types_de_champ_public.find(&:repetition?) repetition = new_draft.types_de_champ_public.find(&:repetition?)
parent_coordinate = new_draft.revision_types_de_champ.find_by(type_de_champ: repetition) new_draft.add_type_de_champ(type_champ: :text, libelle: 'Nom', parent_stable_id: repetition.stable_id)
new_draft.revision_types_de_champ.create(type_de_champ: create(:type_de_champ), position: 0, parent: parent_coordinate)
procedure.validate(:publication) procedure.validate(:publication)
expect(procedure.errors.messages_for(:draft_types_de_champ_public)).not_to include(invalid_repetition_error_message) expect(procedure.errors.messages_for(:draft_types_de_champ_public)).not_to include(invalid_repetition_error_message)