Merge pull request #10821 from demarches-simplifiees/revert_champs_refactor

Tech: Revert "Merge pull request #10771 from tchak/refactor-champs-revert"
This commit is contained in:
LeSim 2024-09-19 11:19:18 +02:00 committed by GitHub
commit 77a84358a0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 189 additions and 205 deletions

View file

@ -18,7 +18,6 @@ class API::V1::DossiersController < APIController
def show def show
dossier = @dossiers.for_api.find(params[:id]) dossier = @dossiers.for_api.find(params[:id])
DossierPreloader.load_one(dossier)
render json: { dossier: DossierSerializer.new(dossier).as_json } render json: { dossier: DossierSerializer.new(dossier).as_json }
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound

View file

@ -9,12 +9,8 @@ class Champs::ChampController < ApplicationController
def find_champ def find_champ
dossier = policy_scope(Dossier).includes(:champs, revision: [:types_de_champ]).find(params[:dossier_id]) dossier = policy_scope(Dossier).includes(:champs, revision: [:types_de_champ]).find(params[:dossier_id])
type_de_champ = dossier.find_type_de_champ_by_stable_id(params[:stable_id]) type_de_champ = dossier.find_type_de_champ_by_stable_id(params[:stable_id])
if type_de_champ.repetition?
dossier.project_champ(type_de_champ, nil)
else
dossier.champ_for_update(type_de_champ, params_row_id, updated_by: current_user.email) dossier.champ_for_update(type_de_champ, params_row_id, updated_by: current_user.email)
end end
end
def params_row_id def params_row_id
params[:row_id] params[:row_id]

View file

@ -87,13 +87,13 @@ class AttestationTemplate < ApplicationRecord
end end
def unspecified_champs_for_dossier(dossier) def unspecified_champs_for_dossier(dossier)
types_de_champ_by_tag_id = dossier.revision.types_de_champ.index_by { "tdc#{_1.stable_id}" } champs_by_stable_id = dossier.champs_for_revision(root: true).index_by { "tdc#{_1.stable_id}" }
used_tags.filter_map do |used_tag| used_tags.filter_map do |used_tag|
corresponding_type_de_champ = types_de_champ_by_tag_id[used_tag] corresponding_champ = champs_by_stable_id[used_tag]
if corresponding_type_de_champ && dossier.project_champ(corresponding_type_de_champ, nil).blank? if corresponding_champ && corresponding_champ.blank?
corresponding_type_de_champ corresponding_champ
end end
end end
end end

View file

@ -6,8 +6,6 @@ class Champ < ApplicationRecord
self.ignored_columns += [:type_de_champ_id] self.ignored_columns += [:type_de_champ_id]
attr_readonly :stable_id
belongs_to :dossier, inverse_of: false, touch: true, optional: false belongs_to :dossier, inverse_of: false, touch: true, optional: false
belongs_to :parent, class_name: 'Champ', optional: true belongs_to :parent, class_name: 'Champ', optional: true
has_many_attached :piece_justificative_file has_many_attached :piece_justificative_file
@ -95,7 +93,7 @@ class Champ < ApplicationRecord
end end
def child? def child?
row_id.present? parent_id.present?
end end
# used for the `required` html attribute # used for the `required` html attribute

View file

@ -37,7 +37,7 @@ class Champs::RepetitionChamp < Champ
end end
def blank? def blank?
row_ids.empty? champs.empty?
end end
def search_terms def search_terms

View file

@ -16,9 +16,9 @@ module ChampsValidateConcern
def validate_champ_value? def validate_champ_value?
case validation_context case validation_context
when :champs_public_value when :champs_public_value
public? && in_dossier_revision? && visible? public? && visible?
when :champs_private_value when :champs_private_value
private? && in_dossier_revision? && visible? private? && visible?
else else
false false
end end
@ -27,9 +27,5 @@ module ChampsValidateConcern
def validate_champ_value_or_prefill? def validate_champ_value_or_prefill?
validate_champ_value? || validation_context == :prefill validate_champ_value? || validation_context == :prefill
end end
def in_dossier_revision?
dossier.revision.types_de_champ.any? { _1.stable_id == stable_id }
end
end end
end end

View file

@ -33,7 +33,6 @@ module DossierChampsConcern
end end
def project_champ(type_de_champ, row_id) def project_champ(type_de_champ, row_id)
check_valid_row_id?(type_de_champ, row_id)
champ = champs_by_public_id[type_de_champ.public_id(row_id)] champ = champs_by_public_id[type_de_champ.public_id(row_id)]
if champ.nil? if champ.nil?
type_de_champ.build_champ(dossier: self, row_id:) type_de_champ.build_champ(dossier: self, row_id:)
@ -57,8 +56,8 @@ module DossierChampsConcern
revision revision
.types_de_champ .types_de_champ
.filter { _1.stable_id.in?(stable_ids) } .filter { _1.stable_id.in?(stable_ids) }
.filter { !_1.child?(revision) } .filter { !revision.child?(_1) }
.map { _1.repetition? ? project_champ(_1, nil) : champ_for_update(_1, nil, updated_by: nil) } .map { champ_for_update(_1, nil, updated_by: nil) }
end end
def champ_for_update(type_de_champ, row_id, updated_by:) def champ_for_update(type_de_champ, row_id, updated_by:)
@ -82,7 +81,6 @@ module DossierChampsConcern
end end
def champ_for_export(type_de_champ, row_id) def champ_for_export(type_de_champ, row_id)
check_valid_row_id?(type_de_champ, row_id)
champ = champs_by_public_id[type_de_champ.public_id(row_id)] champ = champs_by_public_id[type_de_champ.public_id(row_id)]
if champ.blank? || !champ.visible? if champ.blank? || !champ.visible?
nil nil
@ -98,7 +96,6 @@ module DossierChampsConcern
end end
def champ_with_attributes_for_update(type_de_champ, row_id, updated_by:) def champ_with_attributes_for_update(type_de_champ, row_id, updated_by:)
check_valid_row_id?(type_de_champ, row_id)
attributes = type_de_champ.params_for_champ attributes = type_de_champ.params_for_champ
# TODO: Once we have the right index in place, we should change this to use `create_or_find_by` instead of `find_or_create_by` # TODO: Once we have the right index in place, we should change this to use `create_or_find_by` instead of `find_or_create_by`
champ = champs champ = champs
@ -127,14 +124,4 @@ module DossierChampsConcern
[champ, attributes] [champ, attributes]
end end
def check_valid_row_id?(type_de_champ, row_id)
if type_de_champ.child?(revision)
if row_id.blank?
raise "type_de_champ #{type_de_champ.stable_id} must have a row_id because it is part of a repetition"
end
elsif row_id.present?
raise "type_de_champ #{type_de_champ.stable_id} can not have a row_id because it is not part of a repetition"
end
end
end end

View file

@ -19,7 +19,7 @@ module DossierSectionsConcern
end end
def auto_numbering_section_headers_for?(type_de_champ) def auto_numbering_section_headers_for?(type_de_champ)
return false if type_de_champ.child?(revision) return false if revision.child?(type_de_champ)
sections_for(type_de_champ)&.none? { _1.libelle =~ /^\d/ } sections_for(type_de_champ)&.none? { _1.libelle =~ /^\d/ }
end end

View file

@ -51,6 +51,7 @@ class Dossier < ApplicationRecord
has_many :champs_to_destroy, -> { order(:parent_id) }, class_name: 'Champ', inverse_of: false, dependent: :destroy has_many :champs_to_destroy, -> { order(:parent_id) }, class_name: 'Champ', inverse_of: false, dependent: :destroy
has_many :champs_public, -> { root.public_only }, class_name: 'Champ', inverse_of: false has_many :champs_public, -> { root.public_only }, class_name: 'Champ', inverse_of: false
has_many :champs_private, -> { root.private_only }, class_name: 'Champ', inverse_of: false has_many :champs_private, -> { root.private_only }, class_name: 'Champ', inverse_of: false
has_many :prefilled_champs_public, -> { root.public_only.prefilled }, class_name: 'Champ', inverse_of: false
has_many :commentaires, inverse_of: :dossier, dependent: :destroy has_many :commentaires, inverse_of: :dossier, dependent: :destroy
has_many :preloaded_commentaires, -> { includes(:dossier_correction, piece_jointe_attachments: :blob) }, class_name: 'Commentaire', inverse_of: :dossier has_many :preloaded_commentaires, -> { includes(:dossier_correction, piece_jointe_attachments: :blob) }, class_name: 'Commentaire', inverse_of: :dossier
@ -269,9 +270,26 @@ class Dossier < ApplicationRecord
scope :en_cours, -> { not_archived.state_en_construction_ou_instruction } scope :en_cours, -> { not_archived.state_en_construction_ou_instruction }
scope :without_followers, -> { where.missing(:follows) } scope :without_followers, -> { where.missing(:follows) }
scope :with_followers, -> { left_outer_joins(:follows).where.not(follows: { id: nil }) } scope :with_followers, -> { left_outer_joins(:follows).where.not(follows: { id: nil }) }
scope :with_champs, -> {
includes(champs_public: [
:geo_areas,
piece_justificative_file_attachments: :blob,
champs: [piece_justificative_file_attachments: :blob]
])
}
scope :brouillons_recently_updated, -> { updated_since(2.days.ago).state_brouillon.order_by_updated_at } scope :brouillons_recently_updated, -> { updated_since(2.days.ago).state_brouillon.order_by_updated_at }
scope :with_annotations, -> {
includes(champs_private: [
:geo_areas,
piece_justificative_file_attachments: :blob,
champs: [piece_justificative_file_attachments: :blob]
])
}
scope :for_api, -> { scope :for_api, -> {
includes(commentaires: { piece_jointe_attachments: :blob }, with_champs
.with_annotations
.includes(commentaires: { piece_jointe_attachments: :blob },
justificatif_motivation_attachment: :blob, justificatif_motivation_attachment: :blob,
attestation: [], attestation: [],
avis: { piece_justificative_file_attachment: :blob }, avis: { piece_justificative_file_attachment: :blob },
@ -423,6 +441,8 @@ class Dossier < ApplicationRecord
validates :mandataire_last_name, presence: true, if: :for_tiers? validates :mandataire_last_name, presence: true, if: :for_tiers?
validates :for_tiers, inclusion: { in: [true, false] }, if: -> { revision&.procedure&.for_individual? } validates :for_tiers, inclusion: { in: [true, false] }, if: -> { revision&.procedure&.for_individual? }
validates_associated :prefilled_champs_public, on: :champs_public_value
def types_de_champ_public def types_de_champ_public
types_de_champ types_de_champ
end end
@ -929,7 +949,7 @@ class Dossier < ApplicationRecord
end end
def remove_titres_identite! def remove_titres_identite!
champs.filter(&:titre_identite?).map(&:piece_justificative_file).each(&:purge_later) champs_public.filter(&:titre_identite?).map(&:piece_justificative_file).each(&:purge_later)
end end
def remove_piece_justificative_file_not_visible! def remove_piece_justificative_file_not_visible!
@ -1144,7 +1164,7 @@ class Dossier < ApplicationRecord
end end
def has_annotations? def has_annotations?
revision.types_de_champ_private.present? revision.revision_types_de_champ_private.present?
end end
def hide_info_with_accuse_lecture? def hide_info_with_accuse_lecture?

View file

@ -37,12 +37,18 @@ class DossierPreloader
private private
def revisions(pj_template: false) def revisions
@revisions ||= ProcedureRevision.where(id: @dossiers.pluck(:revision_id).uniq) @revisions ||= ProcedureRevision.where(id: @dossiers.pluck(:revision_id).uniq)
.includes(types_de_champ: pj_template ? { piece_justificative_template_attachment: :blob } : []) .includes(types_de_champ: { piece_justificative_template_attachment: :blob })
.index_by(&:id) .index_by(&:id)
end end
# returns: { revision_id : { stable_id : position } }
def positions
@positions ||= revisions
.transform_values { |revision| revision.revision_types_de_champ.map { [_1.stable_id, _1.position] }.to_h }
end
def load_dossiers(dossiers, pj_template: false) def load_dossiers(dossiers, pj_template: false)
to_include = @includes_for_champ.dup to_include = @includes_for_champ.dup
to_include << [piece_justificative_file_attachments: :blob] to_include << [piece_justificative_file_attachments: :blob]
@ -52,10 +58,16 @@ class DossierPreloader
.where(dossier_id: dossiers) .where(dossier_id: dossiers)
.to_a .to_a
champs_by_dossier = all_champs.group_by(&:dossier_id) children_champs, root_champs = all_champs.partition(&:child?)
champs_by_dossier = root_champs.group_by(&:dossier_id)
champs_by_dossier_by_parent = children_champs
.group_by(&:dossier_id)
.transform_values do |champs|
champs.group_by(&:parent_id)
end
dossiers.each do |dossier| dossiers.each do |dossier|
load_dossier(dossier, champs_by_dossier[dossier.id] || [], pj_template:) load_dossier(dossier, champs_by_dossier[dossier.id] || [], champs_by_dossier_by_parent[dossier.id] || {})
end end
load_etablissements(all_champs) load_etablissements(all_champs)
@ -74,30 +86,17 @@ class DossierPreloader
end end
end end
def load_dossier(dossier, champs, pj_template: false) def load_dossier(dossier, champs, children_by_parent = {})
revision = revisions(pj_template:)[dossier.revision_id] revision = revisions[dossier.revision_id]
if revision.present? if revision.present?
dossier.association(:revision).target = revision dossier.association(:revision).target = revision
end end
dossier.association(:champs).target = champs
dossier.association(:champs_public).target = dossier.champs_for_revision(scope: :public, root: true)
dossier.association(:champs_private).target = dossier.champs_for_revision(scope: :private, root: true)
# remove once parent_id is deprecated champs_public, champs_private = champs.partition(&:public?)
champs_by_parent_id = champs.group_by(&:parent_id)
champs.each do |champ| dossier.association(:champs).target = []
champ.association(:dossier).target = dossier load_champs(dossier, :champs_public, champs_public, dossier, children_by_parent)
load_champs(dossier, :champs_private, champs_private, dossier, children_by_parent)
# remove once parent_id is deprecated
if champ.repetition?
children = champs_by_parent_id.fetch(champ.id, [])
children.each do |child|
child.association(:parent).target = champ
end
champ.association(:champs).target = children
end
end
# We need to do this because of the check on `Etablissement#champ` in # We need to do this because of the check on `Etablissement#champ` in
# `Etablissement#libelle_for_export`. By assigning `nil` to `target` we mark association # `Etablissement#libelle_for_export`. By assigning `nil` to `target` we mark association
@ -106,4 +105,33 @@ class DossierPreloader
dossier.etablissement.association(:champ).target = nil dossier.etablissement.association(:champ).target = nil
end end
end end
def load_champs(parent, name, champs, dossier, children_by_parent)
if champs.empty?
parent.association(name).target = [] # tells to Rails association has been loaded
return
end
champs.each do |champ|
champ.association(:dossier).target = dossier
if parent.is_a?(Champ)
champ.association(:parent).target = parent
end
end
dossier.association(:champs).target += champs
parent.association(name).target = champs
.filter { positions[dossier.revision_id][_1.stable_id].present? }
.sort_by { [_1.row_id, positions[dossier.revision_id][_1.stable_id]] }
# Load children champs
champs.filter(&:block?).each do |parent_champ|
champs = children_by_parent[parent_champ.id] || []
parent_champ.association(:dossier).target = dossier
load_champs(parent_champ, :champs, champs, dossier, children_by_parent)
end
end
end end

View file

@ -207,6 +207,20 @@ class Procedure < ApplicationRecord
includes(:draft_revision, :published_revision, administrateurs: :user) includes(:draft_revision, :published_revision, administrateurs: :user)
} }
scope :for_download, -> {
includes(
:groupe_instructeurs,
dossiers: {
champs_public: [
piece_justificative_file_attachments: :blob,
champs: [
piece_justificative_file_attachments: :blob
]
]
}
)
}
validates :libelle, presence: true, allow_blank: false, allow_nil: false validates :libelle, presence: true, allow_blank: false, allow_nil: false
validates :description, presence: true, allow_blank: false, allow_nil: false validates :description, presence: true, allow_blank: false, allow_nil: false
validates :administrateurs, presence: true validates :administrateurs, presence: true

View file

@ -219,6 +219,11 @@ class ProcedureRevision < ApplicationRecord
.find { _1.type_de_champ_id == tdc.id }.parent&.type_de_champ .find { _1.type_de_champ_id == tdc.id }.parent&.type_de_champ
end end
def child?(tdc)
revision_types_de_champ
.find { _1.type_de_champ_id == tdc.id }.child?
end
def remove_children_of(tdc) def remove_children_of(tdc)
children_of(tdc).each do |child| children_of(tdc).each do |child|
remove_type_de_champ(child.stable_id) remove_type_de_champ(child.stable_id)

View file

@ -32,8 +32,8 @@ class ProcedureRevisionTypeDeChamp < ApplicationRecord
end end
def siblings def siblings
if child? if parent_id.present?
revision.revision_types_de_champ.where(parent_id:).ordered revision.revision_types_de_champ.where(parent_id: parent_id).ordered
elsif private? elsif private?
revision.revision_types_de_champ_private revision.revision_types_de_champ_private
else else

View file

@ -456,10 +456,6 @@ class TypeDeChamp < ApplicationRecord
!private? !private?
end end
def child?(revision)
revision.revision_types_de_champ.find { _1.type_de_champ_id == id }&.child?
end
def filename_for_attachement(attachment_sym) def filename_for_attachement(attachment_sym)
attachment = send(attachment_sym) attachment = send(attachment_sym)
if attachment.attached? if attachment.attached?

View file

@ -12,7 +12,7 @@
- if unspecified_attestation_champs.present? - if unspecified_attestation_champs.present?
.warning .warning
Attention, les valeurs suivantes nont pas été renseignées mais sont nécessaires pour pouvoir envoyer une attestation valide : Attention, les valeurs suivantes nont pas été renseignées mais sont nécessaires pour pouvoir envoyer une attestation valide :
- unspecified_annotations_privees, unspecified_champs = unspecified_attestation_champs.partition(&:private?) - unspecified_annotations_privees, unspecified_champs = unspecified_attestation_champs.partition(&:private)
- if unspecified_champs.present? - if unspecified_champs.present?
%h4 Champs de la demande %h4 Champs de la demande

View file

@ -9,7 +9,7 @@ describe Champs::RepetitionController, type: :controller do
it 'removes repetition' do it 'removes repetition' do
rows, repetitions = dossier.champs.partition(&:child?) rows, repetitions = dossier.champs.partition(&:child?)
repetition = repetitions.first repetition = repetitions.first
expect { delete :remove, params: { dossier_id: dossier, stable_id: repetition.stable_id, row_id: rows.first.row_id }, format: :turbo_stream } expect { delete :remove, params: { dossier_id: repetition.dossier, stable_id: repetition.stable_id, row_id: rows.first.row_id }, format: :turbo_stream }
.to change { dossier.reload.champs.size }.from(3).to(1) .to change { dossier.reload.champs.size }.from(3).to(1)
end end
end end

View file

@ -8,8 +8,6 @@ describe Champ do
let(:champ) { Champ.new(value: value) } let(:champ) { Champ.new(value: value) }
let(:value) { '' } let(:value) { '' }
let(:mandatory) { true } let(:mandatory) { true }
context 'with champ' do
before { allow(champ).to receive(:type_de_champ).and_return(type_de_champ) } before { allow(champ).to receive(:type_de_champ).and_return(type_de_champ) }
context 'when mandatory and blank' do context 'when mandatory and blank' do
@ -32,11 +30,19 @@ describe Champ do
context 'when repetition blank' do context 'when repetition blank' do
let(:type_de_champ) { build(:type_de_champ_repetition) } let(:type_de_champ) { build(:type_de_champ_repetition) }
let(:champ) { Champs::RepetitionChamp.new(dossier: Dossier.new(revision: ProcedureRevision.new)) } let(:champ) { Champs::RepetitionChamp.new }
it { expect(champ.blank?).to be(true) } it { expect(champ.blank?).to be(true) }
end end
context 'when repetition not blank' do
let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :repetition, children: [{ type: :text }] }]) }
let(:dossier) { create(:dossier, :with_populated_champs, procedure:) }
let(:champ) { dossier.champs.find(&:repetition?) }
it { expect(champ.blank?).to be(false) }
end
context 'when not blank' do context 'when not blank' do
let(:value) { 'yop' } let(:value) { 'yop' }
it { expect(champ.mandatory_blank?).to be(false) } it { expect(champ.mandatory_blank?).to be(false) }
@ -54,15 +60,6 @@ describe Champ do
end end
end end
context 'when repetition not blank' do
let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :repetition, children: [{ type: :text }] }]) }
let(:dossier) { create(:dossier, :with_populated_champs, procedure:) }
let(:champ) { dossier.champs.find(&:repetition?) }
it { expect(champ.blank?).to be(false) }
end
end
describe "associations" do describe "associations" do
it { is_expected.to belong_to(:dossier) } it { is_expected.to belong_to(:dossier) }
end end
@ -128,7 +125,7 @@ describe Champ do
let(:standalone_champ) { build(:champ, type_de_champ: build(:type_de_champ), dossier: build(:dossier)) } let(:standalone_champ) { build(:champ, type_de_champ: build(:type_de_champ), dossier: build(:dossier)) }
let(:public_sections) { dossier.champs_public.filter(&:header_section?) } let(:public_sections) { dossier.champs_public.filter(&:header_section?) }
let(:private_sections) { dossier.champs_private.filter(&:header_section?) } let(:private_sections) { dossier.champs_private.filter(&:header_section?) }
let(:sections_in_repetition) { dossier.champs.filter(&:child?).filter(&:header_section?) } let(:sections_in_repetition) { champ_in_repetition.parent.champs.filter(&:header_section?) }
it 'returns the sibling sections of a champ' do it 'returns the sibling sections of a champ' do
expect(public_sections).not_to be_empty expect(public_sections).not_to be_empty

View file

@ -2,10 +2,7 @@
describe Champs::CnafChamp, type: :model do describe Champs::CnafChamp, type: :model do
let(:champ) { described_class.new(dossier: build(:dossier)) } let(:champ) { described_class.new(dossier: build(:dossier)) }
before do before { allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_cnaf)) }
allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_cnaf))
allow(champ).to receive(:in_dossier_revision?).and_return(true)
end
describe 'numero_allocataire and code_postal' do describe 'numero_allocataire and code_postal' do
before do before do
champ.numero_allocataire = '1234567' champ.numero_allocataire = '1234567'

View file

@ -6,7 +6,6 @@ describe Champs::DecimalNumberChamp do
before do before do
allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_decimal_number)) allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_decimal_number))
allow(champ).to receive(:visible?).and_return(true) allow(champ).to receive(:visible?).and_return(true)
allow(champ).to receive(:in_dossier_revision?).and_return(true)
champ.run_callbacks(:validation) champ.run_callbacks(:validation)
end end
subject { champ.validate(:champs_public_value) } subject { champ.validate(:champs_public_value) }

View file

@ -4,10 +4,7 @@ describe Champs::DepartementChamp, type: :model do
describe 'validations' do describe 'validations' do
describe 'external link' do describe 'external link' do
let(:champ) { described_class.new(external_id: external_id, dossier: build(:dossier)) } let(:champ) { described_class.new(external_id: external_id, dossier: build(:dossier)) }
before do before { allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_departements)) }
allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_departements))
allow(champ).to receive(:in_dossier_revision?).and_return(true)
end
subject { champ.validate(:champs_public_value) } subject { champ.validate(:champs_public_value) }
context 'when nil' do context 'when nil' do

View file

@ -40,10 +40,7 @@ describe Champs::DgfipChamp, type: :model do
let(:numero_fiscal) { '1122299999092' } let(:numero_fiscal) { '1122299999092' }
let(:reference_avis) { 'FC22299999092' } let(:reference_avis) { 'FC22299999092' }
let(:champ) { described_class.new(dossier: build(:dossier)) } let(:champ) { described_class.new(dossier: build(:dossier)) }
before do before { allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_dgfip)) }
allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_dgfip))
allow(champ).to receive(:in_dossier_revision?).and_return(true)
end
let(:validation_context) { :champs_public_value } let(:validation_context) { :champs_public_value }
subject { champ.valid?(validation_context) } subject { champ.valid?(validation_context) }

View file

@ -42,7 +42,6 @@ describe Champs::DossierLinkChamp, type: :model do
before do before do
allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_dossier_link, mandatory:)) allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_dossier_link, mandatory:))
allow(champ).to receive(:in_dossier_revision?).and_return(true)
champ.run_callbacks(:validation) champ.run_callbacks(:validation)
end end

View file

@ -4,10 +4,7 @@ describe Champs::DropDownListChamp do
describe 'validations' do describe 'validations' do
describe 'inclusion' do describe 'inclusion' do
let(:champ) { described_class.new(other:, value:, dossier: build(:dossier)) } let(:champ) { described_class.new(other:, value:, dossier: build(:dossier)) }
before do before { allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_drop_down_list, drop_down_other: other)) }
allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_drop_down_list, drop_down_other: other))
allow(champ).to receive(:in_dossier_revision?).and_return(true)
end
subject { champ.validate(:champs_public_value) } subject { champ.validate(:champs_public_value) }
context 'when the other value is accepted' do context 'when the other value is accepted' do

View file

@ -2,10 +2,8 @@
describe Champs::EmailChamp do describe Champs::EmailChamp do
describe 'validation' do describe 'validation' do
let(:procedure) { create(:procedure, types_de_champ_public: [{}, { type: :email }, {}]) } let(:champ) { described_class.new(value:, dossier: build(:dossier)) }
let(:dossier) { create(:dossier, procedure:) } before { allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_email)) }
let(:champ) { dossier.champs.second }
before { champ.value = value }
subject { champ.validate(:champs_public_value) } subject { champ.validate(:champs_public_value) }
context 'when nil' do context 'when nil' do
@ -81,11 +79,5 @@ describe Champs::EmailChamp do
expect { subject }.to change { champ.value }.from(value).to('username@mailserver.domain') expect { subject }.to change { champ.value }.from(value).to('username@mailserver.domain')
end end
end end
context 'when type_de_champ is not in dossier revision anymore' do
before { dossier.revision.remove_type_de_champ(champ.stable_id) }
let(:value) { 'username' }
it { is_expected.to be_truthy }
end
end end
end end

View file

@ -6,10 +6,7 @@ describe Champs::EpciChamp, type: :model do
describe 'code_departement' do describe 'code_departement' do
let(:champ) { Champs::EpciChamp.new(code_departement: code_departement, dossier: build(:dossier)) } let(:champ) { Champs::EpciChamp.new(code_departement: code_departement, dossier: build(:dossier)) }
before do before { allow(champ).to receive(:visible?).and_return(true) }
allow(champ).to receive(:visible?).and_return(true)
allow(champ).to receive(:in_dossier_revision?).and_return(true)
end
context 'when nil' do context 'when nil' do
let(:code_departement) { nil } let(:code_departement) { nil }

View file

@ -3,10 +3,7 @@
describe Champs::IbanChamp do describe Champs::IbanChamp do
describe '#valid?' do describe '#valid?' do
let(:champ) { Champs::IbanChamp.new(dossier: build(:dossier)) } let(:champ) { Champs::IbanChamp.new(dossier: build(:dossier)) }
before do before { allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_iban)) }
allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_iban))
allow(champ).to receive(:in_dossier_revision?).and_return(true)
end
def with_value(value) def with_value(value)
champ.tap { _1.value = value } champ.tap { _1.value = value }
end end

View file

@ -2,10 +2,7 @@
describe Champs::IntegerNumberChamp do describe Champs::IntegerNumberChamp do
let(:champ) { Champs::IntegerNumberChamp.new(value:, dossier: build(:dossier)) } let(:champ) { Champs::IntegerNumberChamp.new(value:, dossier: build(:dossier)) }
before do before { allow(champ).to receive(:visible?).and_return(true) }
allow(champ).to receive(:visible?).and_return(true)
allow(champ).to receive(:in_dossier_revision?).and_return(true)
end
subject { champ.validate(:champs_public_value) } subject { champ.validate(:champs_public_value) }
describe '#valid?' do describe '#valid?' do

View file

@ -4,10 +4,7 @@ describe Champs::MultipleDropDownListChamp do
let(:type_de_champ) { build(:type_de_champ_multiple_drop_down_list, drop_down_list_value: "val1\r\nval2\r\nval3\r\n[brackets] val4") } let(:type_de_champ) { build(:type_de_champ_multiple_drop_down_list, drop_down_list_value: "val1\r\nval2\r\nval3\r\n[brackets] val4") }
let(:value) { nil } let(:value) { nil }
let(:champ) { Champs::MultipleDropDownListChamp.new(value:, dossier: build(:dossier)) } let(:champ) { Champs::MultipleDropDownListChamp.new(value:, dossier: build(:dossier)) }
before do before { allow(champ).to receive(:type_de_champ).and_return(type_de_champ) }
allow(champ).to receive(:type_de_champ).and_return(type_de_champ)
allow(champ).to receive(:in_dossier_revision?).and_return(true)
end
describe 'validations' do describe 'validations' do
subject { champ.validate(:champs_public_value) } subject { champ.validate(:champs_public_value) }

View file

@ -2,10 +2,7 @@
describe Champs::PhoneChamp do describe Champs::PhoneChamp do
let(:champ) { Champs::PhoneChamp.new(dossier: build(:dossier)) } let(:champ) { Champs::PhoneChamp.new(dossier: build(:dossier)) }
before do before { allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_phone)) }
allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_phone))
allow(champ).to receive(:in_dossier_revision?).and_return(true)
end
describe '#validate' do describe '#validate' do
it do it do
expect(champ_with_value(nil).validate(:champs_public_value)).to be_truthy expect(champ_with_value(nil).validate(:champs_public_value)).to be_truthy

View file

@ -2,10 +2,7 @@
describe Champs::RNAChamp do describe Champs::RNAChamp do
let(:champ) { Champs::RNAChamp.new(value: "W182736273", dossier: build(:dossier)) } let(:champ) { Champs::RNAChamp.new(value: "W182736273", dossier: build(:dossier)) }
before do before { allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_rna)) }
allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_rna))
allow(champ).to receive(:in_dossier_revision?).and_return(true)
end
def with_value(value) def with_value(value)
champ.tap { _1.value = value } champ.tap { _1.value = value }
end end

View file

@ -35,6 +35,7 @@ RSpec.describe DossierChampsConcern do
let(:type_de_champ_repetition) { dossier.find_type_de_champ_by_stable_id(993) } let(:type_de_champ_repetition) { dossier.find_type_de_champ_by_stable_id(993) }
let(:type_de_champ_public) { dossier.find_type_de_champ_by_stable_id(99) } let(:type_de_champ_public) { dossier.find_type_de_champ_by_stable_id(99) }
let(:type_de_champ_private) { dossier.find_type_de_champ_by_stable_id(995) } let(:type_de_champ_private) { dossier.find_type_de_champ_by_stable_id(995) }
let(:row_ids) { dossier.project_champ(type_de_champ_repetition, nil).row_ids }
context "public champ" do context "public champ" do
let(:row_id) { nil } let(:row_id) { nil }
@ -44,20 +45,13 @@ RSpec.describe DossierChampsConcern do
context "in repetition" do context "in repetition" do
let(:type_de_champ_public) { dossier.find_type_de_champ_by_stable_id(994) } let(:type_de_champ_public) { dossier.find_type_de_champ_by_stable_id(994) }
let(:row_id) { dossier.project_champ(type_de_champ_repetition, nil).row_ids.first } let(:row_id) { row_ids.first }
it { it {
expect(subject.persisted?).to be_truthy expect(subject.persisted?).to be_truthy
expect(subject.row_id).to eq(row_id) expect(subject.row_id).to eq(row_id)
expect(subject.parent_id).not_to be_nil expect(subject.parent_id).not_to be_nil
} }
context "invalid row_id" do
let(:type_de_champ_public) { dossier.find_type_de_champ_by_stable_id(99) }
it {
expect { subject }.to raise_error("type_de_champ #{type_de_champ_public.stable_id} can not have a row_id because it is not part of a repetition")
}
end
end end
context "missing champ" do context "missing champ" do
@ -70,20 +64,13 @@ RSpec.describe DossierChampsConcern do
context "in repetition" do context "in repetition" do
let(:type_de_champ_public) { dossier.find_type_de_champ_by_stable_id(994) } let(:type_de_champ_public) { dossier.find_type_de_champ_by_stable_id(994) }
let(:row_id) { ULID.generate } let(:row_id) { row_ids.first }
it { it {
expect(subject.new_record?).to be_truthy expect(subject.new_record?).to be_truthy
expect(subject.is_a?(Champs::TextChamp)).to be_truthy expect(subject.is_a?(Champs::TextChamp)).to be_truthy
expect(subject.row_id).to eq(row_id) expect(subject.row_id).to eq(row_id)
} }
context "invalid row_id" do
let(:type_de_champ_public) { dossier.find_type_de_champ_by_stable_id(99) }
it {
expect { subject }.to raise_error("type_de_champ #{type_de_champ_public.stable_id} can not have a row_id because it is not part of a repetition")
}
end
end end
end end
end end
@ -135,6 +122,7 @@ RSpec.describe DossierChampsConcern do
let(:type_de_champ_repetition) { dossier.find_type_de_champ_by_stable_id(993) } let(:type_de_champ_repetition) { dossier.find_type_de_champ_by_stable_id(993) }
let(:type_de_champ_public) { dossier.find_type_de_champ_by_stable_id(99) } let(:type_de_champ_public) { dossier.find_type_de_champ_by_stable_id(99) }
let(:type_de_champ_private) { dossier.find_type_de_champ_by_stable_id(995) } let(:type_de_champ_private) { dossier.find_type_de_champ_by_stable_id(995) }
let(:row_ids) { dossier.project_champ(type_de_champ_repetition, nil).row_ids }
let(:row_id) { nil } let(:row_id) { nil }
context "public champ" do context "public champ" do
@ -147,7 +135,7 @@ RSpec.describe DossierChampsConcern do
context "in repetition" do context "in repetition" do
let(:type_de_champ_public) { dossier.find_type_de_champ_by_stable_id(994) } let(:type_de_champ_public) { dossier.find_type_de_champ_by_stable_id(994) }
let(:row_id) { ULID.generate } let(:row_id) { row_ids.first }
it { it {
expect(subject.persisted?).to be_truthy expect(subject.persisted?).to be_truthy
@ -166,7 +154,7 @@ RSpec.describe DossierChampsConcern do
context "in repetition" do context "in repetition" do
let(:type_de_champ_public) { dossier.find_type_de_champ_by_stable_id(994) } let(:type_de_champ_public) { dossier.find_type_de_champ_by_stable_id(994) }
let(:row_id) { ULID.generate } let(:row_id) { row_ids.first }
it { it {
expect(subject.persisted?).to be_truthy expect(subject.persisted?).to be_truthy
@ -190,7 +178,8 @@ RSpec.describe DossierChampsConcern do
describe "#update_champs_attributes(public)" do describe "#update_champs_attributes(public)" do
let(:type_de_champ_repetition) { dossier.find_type_de_champ_by_stable_id(993) } let(:type_de_champ_repetition) { dossier.find_type_de_champ_by_stable_id(993) }
let(:row_id) { ULID.generate } let(:row_ids) { dossier.project_champ(type_de_champ_repetition, nil).row_ids }
let(:row_id) { row_ids.first }
let(:attributes) do let(:attributes) do
{ {

View file

@ -38,8 +38,10 @@ describe DossierSearchableConcern do
end end
it "update columns en construction" do it "update columns en construction" do
dossier.update_champs_attributes({ champ_public.public_id => { value: 'nouvelle valeur publique' } }, :public, updated_by: 'test') dossier.update(
dossier.update_champs_attributes({ champ_private.public_id => { value: 'nouvelle valeur privee' } }, :private, updated_by: 'test') champs_public_attributes: [{ id: champ_public.id, value: 'nouvelle valeur publique' }],
champs_private_attributes: [{ id: champ_private.id, value: 'nouvelle valeur privee' }]
)
assert_enqueued_jobs(1, only: DossierIndexSearchTermsJob) do assert_enqueued_jobs(1, only: DossierIndexSearchTermsJob) do
dossier.passer_en_construction dossier.passer_en_construction

View file

@ -50,12 +50,12 @@ describe DossierSectionsConcern do
describe '#index_for_section_header' do describe '#index_for_section_header' do
include Logic include Logic
let(:number_stable_id) { 99 } let(:number_stable_id) { 99 }
let(:types_de_champ) do let(:types_de_champ) {
[ [
{ type: :header_section, libelle: "Infos" }, { type: :integer_number, stable_id: number_stable_id }, { type: :header_section, libelle: "Infos" }, { type: :integer_number, stable_id: number_stable_id },
{ type: :header_section, libelle: "Details", condition: ds_eq(champ_value(99), constant(5)) }, { type: :header_section, libelle: "Conclusion" } { type: :header_section, libelle: "Details", condition: ds_eq(champ_value(99), constant(5)) }, { type: :header_section, libelle: "Conclusion" }
] ]
end }
let(:procedure) { create(:procedure, :for_individual, types_de_champ_public: types_de_champ) } let(:procedure) { create(:procedure, :for_individual, types_de_champ_public: types_de_champ) }
let(:dossier) { create(:dossier, procedure: procedure) } let(:dossier) { create(:dossier, procedure: procedure) }

View file

@ -7,10 +7,7 @@ describe Champs::EngagementJuridiqueChamp do
.new(dossier: build(:dossier)) .new(dossier: build(:dossier))
.tap { _1.value = value } .tap { _1.value = value }
end end
before { before { allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_engagement_juridique)) }
allow(champ).to receive(:type_de_champ).and_return(build(:type_de_champ_engagement_juridique))
allow(champ).to receive(:in_dossier_revision?).and_return(true)
}
subject { champ.validate(:champs_public_value) } subject { champ.validate(:champs_public_value) }
context 'with [A-Z]' do context 'with [A-Z]' do

View file

@ -390,11 +390,11 @@ describe ProcedureExportService do
context 'with long libelle composed of utf8 characteres' do context 'with long libelle composed of utf8 characteres' do
before do before do
procedure.active_revision.types_de_champ_public.each do |type_de_champ| procedure.active_revision.types_de_champ_public.each do |c|
type_de_champ.update!(libelle: "#{type_de_champ.id} - ?/[] ééé ééé ééééééé ééééééé éééééééé. ééé éé éééééééé éé ééé. ééééé éééééééé ééé ééé.") c.update!(libelle: "#{c.id} - ?/[] ééé ééé ééééééé ééééééé éééééééé. ééé éé éééééééé éé ééé. ééééé éééééééé ééé ééé.")
end end
procedure.active_revision.children_of(champ_repetition.type_de_champ).each do |type_de_champ| champ_repetition.champs.each do |c|
type_de_champ.update!(libelle: "#{type_de_champ.id} - Quam rem nam maiores numquam dolorem nesciunt. Cum et possimus et aut. Fugit voluptas qui qui.") c.type_de_champ.update!(libelle: "#{c.id} - Quam rem nam maiores numquam dolorem nesciunt. Cum et possimus et aut. Fugit voluptas qui qui.")
end end
end end
@ -417,7 +417,7 @@ describe ProcedureExportService do
context 'with empty repetition' do context 'with empty repetition' do
before do before do
dossiers.flat_map { |dossier| dossier.champs_public.filter(&:repetition?) }.each do |champ| dossiers.flat_map { |dossier| dossier.champs_public.filter(&:repetition?) }.each do |champ|
Champ.where(row_id: champ.row_ids).destroy_all champ.champs.destroy_all
end end
end end