refactor(dossier): explicitly build default values - less callbacks, less magic

This commit is contained in:
Paul Chavard 2024-09-27 14:44:07 +02:00
parent 5879d54145
commit 8fdf5cbe80
No known key found for this signature in database
6 changed files with 66 additions and 64 deletions

View file

@ -9,7 +9,7 @@ class API::Public::V1::DossiersController < API::Public::V1::BaseController
state: Dossier.states.fetch(:brouillon), state: Dossier.states.fetch(:brouillon),
prefilled: true prefilled: true
) )
dossier.build_default_individual dossier.build_default_values
if dossier.save if dossier.save
dossier.prefill!(PrefillChamps.new(dossier, params.to_unsafe_h).to_a, PrefillIdentity.new(dossier, params.to_unsafe_h).to_h) dossier.prefill!(PrefillChamps.new(dossier, params.to_unsafe_h).to_a, PrefillIdentity.new(dossier, params.to_unsafe_h).to_h)
render json: serialize_dossier(dossier), status: :created render json: serialize_dossier(dossier), status: :created

View file

@ -127,7 +127,7 @@ module Users
state: Dossier.states.fetch(:brouillon), state: Dossier.states.fetch(:brouillon),
prefilled: true prefilled: true
) )
@prefilled_dossier.build_default_individual @prefilled_dossier.build_default_values
if @prefilled_dossier.save if @prefilled_dossier.save
@prefilled_dossier.prefill!(PrefillChamps.new(@prefilled_dossier, params.to_unsafe_h).to_a, PrefillIdentity.new(@prefilled_dossier, params.to_unsafe_h).to_h) @prefilled_dossier.prefill!(PrefillChamps.new(@prefilled_dossier, params.to_unsafe_h).to_a, PrefillIdentity.new(@prefilled_dossier, params.to_unsafe_h).to_h)
end end

View file

@ -385,7 +385,7 @@ module Users
user: current_user, user: current_user,
state: Dossier.states.fetch(:brouillon) state: Dossier.states.fetch(:brouillon)
) )
dossier.build_default_individual dossier.build_default_values
dossier.save! dossier.save!
DossierMailer.with(dossier:).notify_new_draft.deliver_later DossierMailer.with(dossier:).notify_new_draft.deliver_later

View file

@ -413,7 +413,6 @@ class Dossier < ApplicationRecord
delegate :siret, :siren, to: :etablissement, allow_nil: true delegate :siret, :siren, to: :etablissement, allow_nil: true
delegate :france_connected_with_one_identity?, to: :user, allow_nil: true delegate :france_connected_with_one_identity?, to: :user, allow_nil: true
before_save :build_default_champs_for_new_dossier, if: Proc.new { revision_id_was.nil? && parent_dossier_id.nil? && editing_fork_origin_id.nil? }
after_save :send_web_hook after_save :send_web_hook
@ -471,29 +470,9 @@ class Dossier < ApplicationRecord
end end
end end
def build_default_champs_for_new_dossier def build_default_values
revision.build_champs_public(self).each do |champ| build_default_individual
champs_public << champ build_default_champs
end
revision.build_champs_private(self).each do |champ|
champs_private << champ
end
champs_public.filter { _1.repetition? && _1.mandatory? }.each do |champ|
champ.add_row(updated_by: nil)
end
champs_private.filter(&:repetition?).each do |champ|
champ.add_row(updated_by: nil)
end
end
def build_default_individual
if procedure.for_individual? && individual.blank?
self.individual = if france_connected_with_one_identity?
Individual.from_france_connect(user.france_connect_informations.first)
else
Individual.new
end
end
end end
def en_construction_ou_instruction? def en_construction_ou_instruction?
@ -1176,6 +1155,33 @@ class Dossier < ApplicationRecord
private private
def build_default_champs
build_default_champs_for(revision.types_de_champ_public) if !champs.any?(&:public?)
build_default_champs_for(revision.types_de_champ_private) if !champs.any?(&:private?)
end
def build_default_champs_for(types_de_champ)
self.champs << types_de_champ.flat_map do |type_de_champ|
if type_de_champ.repetition? && (type_de_champ.private? || type_de_champ.mandatory?)
row_id = ULID.generate
parent = type_de_champ.build_champ(dossier: self)
[parent] + revision.children_of(type_de_champ).map { _1.build_champ(dossier: self, parent:, row_id:) }
else
type_de_champ.build_champ(dossier: self)
end
end
end
def build_default_individual
if procedure.for_individual? && individual.blank?
self.individual = if france_connected_with_one_identity?
Individual.from_france_connect(user.france_connect_informations.first)
else
Individual.new
end
end
end
def create_missing_traitemets def create_missing_traitemets
if en_construction_at.present? && traitements.en_construction.empty? if en_construction_at.present? && traitements.en_construction.empty?
self.traitements.passer_en_construction(processed_at: en_construction_at) self.traitements.passer_en_construction(processed_at: en_construction_at)

View file

@ -37,16 +37,6 @@ class ProcedureRevision < ApplicationRecord
serialize :ineligibilite_rules, LogicSerializer serialize :ineligibilite_rules, LogicSerializer
def build_champs_public(dossier)
# reload: it can be out of sync in test if some tdcs are added wihtout using add_tdc
types_de_champ_public.reload.map { _1.build_champ(dossier:) }
end
def build_champs_private(dossier)
# reload: it can be out of sync in test if some tdcs are added wihtout using add_tdc
types_de_champ_private.reload.map { _1.build_champ(dossier:) }
end
def add_type_de_champ(params) def add_type_de_champ(params)
parent_stable_id = params.delete(:parent_stable_id) parent_stable_id = params.delete(:parent_stable_id)
parent_coordinate, _ = coordinate_and_tdc(parent_stable_id) parent_coordinate, _ = coordinate_and_tdc(parent_stable_id)
@ -172,7 +162,7 @@ class ProcedureRevision < ApplicationRecord
.find_or_initialize_by(revision: self, user: user, for_procedure_preview: true, state: Dossier.states.fetch(:brouillon)) .find_or_initialize_by(revision: self, user: user, for_procedure_preview: true, state: Dossier.states.fetch(:brouillon))
if dossier.new_record? if dossier.new_record?
dossier.build_default_individual dossier.build_default_values
dossier.save! dossier.save!
end end

View file

@ -11,6 +11,8 @@ FactoryBot.define do
individual { association(:individual, :empty, dossier: instance, strategy: :build) if procedure.for_individual? } individual { association(:individual, :empty, dossier: instance, strategy: :build) if procedure.for_individual? }
transient do transient do
populate_champs { false }
populate_annotations { false }
for_individual? { false } for_individual? { false }
# For now a dossier must use a `create`d procedure, even if the dossier is only built (and not created). # For now a dossier must use a `create`d procedure, even if the dossier is only built (and not created).
# This is because saving the dossier fails when the procedure has not been saved beforehand # This is because saving the dossier fails when the procedure has not been saved beforehand
@ -19,6 +21,34 @@ FactoryBot.define do
procedure { create(:procedure, :published, :with_type_de_champ, :with_type_de_champ_private, for_individual: for_individual?) } procedure { create(:procedure, :published, :with_type_de_champ, :with_type_de_champ_private, for_individual: for_individual?) }
end end
after(:create) do |dossier, evaluator|
if evaluator.populate_champs
dossier.revision.types_de_champ_public.each do |type_de_champ|
value = if type_de_champ.simple_drop_down_list?
type_de_champ.drop_down_options.first
elsif type_de_champ.multiple_drop_down_list?
type_de_champ.drop_down_options.first(2).to_json
end
attrs = { stable_id: type_de_champ.stable_id, dossier:, value: }.compact
create(:"champ_do_not_use_#{type_de_champ.type_champ}", **attrs)
end
end
if evaluator.populate_annotations
dossier.revision.types_de_champ_private.each do |type_de_champ|
value = if type_de_champ.simple_drop_down_list?
type_de_champ.drop_down_options.first
elsif type_de_champ.multiple_drop_down_list?
type_de_champ.drop_down_options.first(2).to_json
end
attrs = { stable_id: type_de_champ.stable_id, dossier:, private: true, value: }.compact
create(:"champ_do_not_use_#{type_de_champ.type_champ}", **attrs)
end
end
dossier.build_default_values
end
trait :with_entreprise do trait :with_entreprise do
transient do transient do
as_degraded_mode { false } as_degraded_mode { false }
@ -259,35 +289,11 @@ FactoryBot.define do
end end
trait :with_populated_champs do trait :with_populated_champs do
after(:create) do |dossier, _evaluator| populate_champs { true }
dossier.champs_to_destroy.where(private: false).destroy_all
dossier.types_de_champ.each do |type_de_champ|
value = if type_de_champ.simple_drop_down_list?
type_de_champ.drop_down_options.first
elsif type_de_champ.multiple_drop_down_list?
type_de_champ.drop_down_options.first(2).to_json
end
attrs = { stable_id: type_de_champ.stable_id, dossier:, value: }.compact
create(:"champ_do_not_use_#{type_de_champ.type_champ}", **attrs)
end
dossier.reload
end
end end
trait :with_populated_annotations do trait :with_populated_annotations do
after(:create) do |dossier, _evaluator| populate_annotations { true }
dossier.champs_to_destroy.where(private: true).destroy_all
dossier.types_de_champ_private.each do |type_de_champ|
value = if type_de_champ.simple_drop_down_list?
type_de_champ.drop_down_options.first
elsif type_de_champ.multiple_drop_down_list?
type_de_champ.drop_down_options.first(2).to_json
end
attrs = { stable_id: type_de_champ.stable_id, dossier:, private: true, value: }.compact
create(:"champ_do_not_use_#{type_de_champ.type_champ}", **attrs)
end
dossier.reload
end
end end
trait :prefilled do trait :prefilled do