diff --git a/app/lib/data_fixer/dossier_champs_missing.rb b/app/lib/data_fixer/dossier_champs_missing.rb new file mode 100644 index 000000000..2769821ad --- /dev/null +++ b/app/lib/data_fixer/dossier_champs_missing.rb @@ -0,0 +1,40 @@ +# some race condition (regarding double submit of dossier.passer_en_construction!) might remove champs +# until now we haven't decided to push a stronger fix than an UI change +# so we might have to recreate some deleted champs and notify administration +class DataFixer::DossierChampsMissing + def fix + fixed_on_origin = apply_fix(@original_dossier) + + fixed_on_other = Dossier.where(editing_fork_origin_id: @original_dossier.id) + .map(&method(:apply_fix)) + + [fixed_on_origin, fixed_on_other.sum].sum + end + + private + + attr_reader :original_dossier + + def initialize(dossier:) + @original_dossier = dossier + end + + def apply_fix(dossier) + dossier_champs = dossier.champs_public.includes(:type_de_champ) + revision_type_de_champ = TypeDeChamp.joins(:revision_type_de_champ).where(revision_type_de_champ: { revision: dossier.revision }) + + dossier_tdc_stable_ids = dossier_champs.map(&:type_de_champ).map(&:stable_id) + + missing_tdcs = revision_type_de_champ.filter { !dossier_tdc_stable_ids.include?(_1.stable_id) } + missing_tdcs.map do |missing_champ| + dossier.champs_public << missing_champ.build_champ + end + + if !missing_tdcs.empty? + dossier.save! + missing_tdcs.size + else + 0 + end + end +end diff --git a/spec/lib/data_fixer/dossier_champs_missing_spec.rb b/spec/lib/data_fixer/dossier_champs_missing_spec.rb new file mode 100644 index 000000000..f1ee2cf90 --- /dev/null +++ b/spec/lib/data_fixer/dossier_champs_missing_spec.rb @@ -0,0 +1,36 @@ +describe DataFixer::DossierChampsMissing do + describe '#fix' do + let(:procedure) { create(:procedure, :with_datetime, :with_dossier_link) } + let(:dossier) { create(:dossier, procedure:) } + + context 'when dossier does not have a fork' do + before { dossier.champs_public.first.destroy } + subject { described_class.new(dossier:).fix } + + it 'add missing champs to the dossier' do + expect { subject }.to change { dossier.champs_public.count }.from(1).to(2) + end + + it 'returns number of added champs' do + expect(subject).to eq(1) + end + end + + context 'when dossier have a fork' do + before { dossier.champs_public.first.destroy } + let(:create_fork) { dossier.find_or_create_editing_fork(dossier.user) } + subject do + create_fork + described_class.new(dossier:).fix + end + + it 'add missing champs to the fork too' do + expect { subject }.to change { create_fork.champs_public.count }.from(1).to(2) + end + + it 'sums number of added champs for dossier and editing_fork_origin_id' do + expect(subject).to eq(2) + end + end + end +end