fix(dossier): fix rebase with drop down options

This commit is contained in:
Paul Chavard 2023-01-06 12:57:15 +01:00
parent 06b8a0f734
commit 5a4cefc5c5
6 changed files with 160 additions and 16 deletions

View file

@ -71,4 +71,12 @@ class Champs::DropDownListChamp < Champ
def value_other
other_value_present? ? value : ""
end
def in?(options)
options.include?(value)
end
def remove_option(options)
update_column(:value, nil)
end
end

View file

@ -89,6 +89,14 @@ class Champs::LinkedDropDownListChamp < Champ
primary_value.present? && secondary_options[primary_value]&.any?(&:present?)
end
def in?(options)
options.include?(primary_value) || options.include?(secondary_value)
end
def remove_option(options)
update_column(:value, nil)
end
private
def pack_value(primary, secondary)

View file

@ -70,6 +70,14 @@ class Champs::MultipleDropDownListChamp < Champ
selected_options.blank?
end
def in?(options)
(selected_options - options).size != selected_options.size
end
def remove_option(options)
update_column(:value, (selected_options - options).to_json)
end
private
def format_before_save

View file

@ -26,6 +26,10 @@ module DossierRebaseConcern
!champs.filter { _1.stable_id == stable_id }.any?(&:blank?)
end
def can_rebase_drop_down_options_change?(stable_id, options)
!champs.filter { _1.stable_id == stable_id }.any? { _1.in?(options) }
end
private
def accepted_en_construction_changes?
@ -60,9 +64,11 @@ module DossierRebaseConcern
changes_by_op[:remove]
.each { delete_champs_for_revision(_1.stable_id) }
if brouillon?
changes_by_op[:update]
.map { |change| [change, champs.joins(:type_de_champ).where(type_de_champ: { stable_id: change.stable_id })] }
.each { |change, champs| apply(change, champs) }
end
# due to repetition tdc clone on update or erase
# we must reassign tdc to the latest version
@ -82,25 +88,23 @@ module DossierRebaseConcern
champs.each { purge_piece_justificative_file(_1) }
GeoArea.where(champ: champs).destroy_all
Etablissement.where(champ: champs).destroy_all
{
type: "Champs::#{change.to.classify}Champ",
champs.update_all(type: "Champs::#{change.to.classify}Champ",
value: nil,
value_json: nil,
external_id: nil,
data: nil
}
data: nil)
when :drop_down_options
{ value: nil }
# we are removing options, we need to remove the value if it contains one of the removed options
removed_options = change.from - change.to
if removed_options.present? && champs.any? { _1.in?(removed_options) }
champs.filter { _1.in?(removed_options) }.each { _1.remove_option(removed_options) }
end
when :carte_layers
# if we are removing cadastres layer, we need to remove cadastre geo areas
if change.from.include?(:cadastres) && !change.to.include?(:cadastres)
champs.each { _1.cadastres.each(&:destroy) }
end
nil
end
&.then { champs.update_all(_1) }
end
def add_new_champs_for_revision(target_coordinate)

View file

@ -62,7 +62,7 @@ class ProcedureRevisionChange
case attribute
when :drop_down_options
(from - to).empty?
(from - to).empty? || dossier&.can_rebase_drop_down_options_change?(stable_id, from - to)
when :drop_down_other
!from && to
when :mandatory

View file

@ -323,23 +323,139 @@ describe Dossier do
context 'with a procedure with a dropdown tdc' do
let!(:procedure) do
create(:procedure).tap do |p|
p.draft_revision.add_type_de_champ(type_champ: :drop_down_list, libelle: 'l1', drop_down_list_value: 'option')
p.draft_revision.add_type_de_champ(type_champ: :drop_down_list, libelle: 'l1', drop_down_list_value: "option\nv1\n")
p.publish!
end
end
let!(:dossier) { create(:dossier, procedure: procedure) }
context 'when a dropdown option is changed' do
context 'when a dropdown option is added' do
before do
dossier.champs_public.first.update(value: 'v1')
stable_id = procedure.draft_revision.types_de_champ.find_by(libelle: 'l1')
tdc_to_update = procedure.draft_revision.find_and_ensure_exclusive_use(stable_id)
tdc_to_update.update(drop_down_list_value: 'option updated')
tdc_to_update.update(drop_down_list_value: "option\nupdated\nv1")
end
it { expect { subject }.not_to change { dossier.champs_public.first.value } }
end
context 'when a dropdown option is removed' do
before do
dossier.champs_public.first.update(value: 'v1')
stable_id = procedure.draft_revision.types_de_champ.find_by(libelle: 'l1')
tdc_to_update = procedure.draft_revision.find_and_ensure_exclusive_use(stable_id)
tdc_to_update.update(drop_down_list_value: "option\nupdated")
end
it { expect { subject }.to change { dossier.champs_public.first.value }.from('v1').to(nil) }
end
context 'when a dropdown unused option is removed' do
before do
dossier.champs_public.first.update(value: 'v1')
stable_id = procedure.draft_revision.types_de_champ.find_by(libelle: 'l1')
tdc_to_update = procedure.draft_revision.find_and_ensure_exclusive_use(stable_id)
tdc_to_update.update(drop_down_list_value: "v1\nupdated")
end
it { expect { subject }.not_to change { dossier.champs_public.first.value } }
end
end
context 'with a procedure with a multiple dropdown tdc' do
let!(:procedure) do
create(:procedure).tap do |p|
p.draft_revision.add_type_de_champ(type_champ: :multiple_drop_down_list, libelle: 'l1', drop_down_list_value: "option\nv1\n")
p.publish!
end
end
let!(:dossier) { create(:dossier, procedure: procedure) }
context 'when a dropdown option is added' do
before do
dossier.champs_public.first.update(value: '["v1"]')
stable_id = procedure.draft_revision.types_de_champ.find_by(libelle: 'l1')
tdc_to_update = procedure.draft_revision.find_and_ensure_exclusive_use(stable_id)
tdc_to_update.update(drop_down_list_value: "option\nupdated\nv1")
end
it { expect { subject }.not_to change { dossier.champs_public.first.value } }
end
context 'when a dropdown option is removed' do
before do
dossier.champs_public.first.update(value: '["v1", "option"]')
stable_id = procedure.draft_revision.types_de_champ.find_by(libelle: 'l1')
tdc_to_update = procedure.draft_revision.find_and_ensure_exclusive_use(stable_id)
tdc_to_update.update(drop_down_list_value: "option\nupdated")
end
it { expect { subject }.to change { dossier.champs_public.first.value }.from('["v1", "option"]').to('["option"]') }
end
context 'when a dropdown unused option is removed' do
before do
dossier.champs_public.first.update(value: '["v1"]')
stable_id = procedure.draft_revision.types_de_champ.find_by(libelle: 'l1')
tdc_to_update = procedure.draft_revision.find_and_ensure_exclusive_use(stable_id)
tdc_to_update.update(drop_down_list_value: "v1\nupdated")
end
it { expect { subject }.not_to change { dossier.champs_public.first.value } }
end
end
context 'with a procedure with a linked dropdown tdc' do
let!(:procedure) do
create(:procedure).tap do |p|
p.draft_revision.add_type_de_champ(type_champ: :linked_drop_down_list, libelle: 'l1', drop_down_list_value: "--titre1--\noption\nv1\n--titre2--\noption2\nv2\n")
p.publish!
end
end
let!(:dossier) { create(:dossier, procedure: procedure) }
context 'when a dropdown option is added' do
before do
dossier.champs_public.first.update(value: '["v1",""]')
stable_id = procedure.draft_revision.types_de_champ.find_by(libelle: 'l1')
tdc_to_update = procedure.draft_revision.find_and_ensure_exclusive_use(stable_id)
tdc_to_update.update(drop_down_list_value: "--titre1--\noption\nv1\nupdated\n--titre2--\noption2\nv2\n")
end
it { expect { subject }.not_to change { dossier.champs_public.first.value } }
end
context 'when a dropdown option is removed' do
before do
dossier.champs_public.first.update(value: '["v1","option2"]')
stable_id = procedure.draft_revision.types_de_champ.find_by(libelle: 'l1')
tdc_to_update = procedure.draft_revision.find_and_ensure_exclusive_use(stable_id)
tdc_to_update.update(drop_down_list_value: "--titre1--\noption\nupdated\n--titre2--\noption2\nv2\n")
end
it { expect { subject }.to change { dossier.champs_public.first.value }.from('["v1","option2"]').to(nil) }
end
context 'when a dropdown unused option is removed' do
before do
dossier.champs_public.first.update(value: '["v1",""]')
stable_id = procedure.draft_revision.types_de_champ.find_by(libelle: 'l1')
tdc_to_update = procedure.draft_revision.find_and_ensure_exclusive_use(stable_id)
tdc_to_update.update(drop_down_list_value: "--titre1--\nv1\nupdated\n--titre2--\noption2\nv2\n")
end
it { expect { subject }.not_to change { dossier.champs_public.first.value } }
end
end
context 'with a procedure with a carte tdc' do