From 67e98f79c9eae9fc4aca106e2579859a126deab4 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Mon, 20 Sep 2021 16:24:40 +0200 Subject: [PATCH 1/3] feat(revisions): add stable_id to changes --- app/models/procedure_revision.rb | 27 ++++++---- spec/models/procedure_revision_spec.rb | 72 +++++++++++++++++--------- 2 files changed, 65 insertions(+), 34 deletions(-) diff --git a/app/models/procedure_revision.rb b/app/models/procedure_revision.rb index 75513d724..3660203cd 100644 --- a/app/models/procedure_revision.rb +++ b/app/models/procedure_revision.rb @@ -134,11 +134,11 @@ class ProcedureRevision < ApplicationRecord to_sids = to_h.keys removed = (from_sids - to_sids).map do |sid| - { op: :remove, label: from_h[sid].libelle, private: from_h[sid].private?, position: from_sids.index(sid) } + { op: :remove, label: from_h[sid].libelle, private: from_h[sid].private?, position: from_sids.index(sid), stable_id: sid } end added = (to_sids - from_sids).map do |sid| - { op: :add, label: to_h[sid].libelle, private: to_h[sid].private?, position: to_sids.index(sid) } + { op: :add, label: to_h[sid].libelle, private: to_h[sid].private?, position: to_sids.index(sid), stable_id: sid } end kept = from_sids.intersection(to_sids) @@ -147,7 +147,7 @@ class ProcedureRevision < ApplicationRecord .map { |sid| [sid, from_sids.index(sid), to_sids.index(sid)] } .filter { |_, from_index, to_index| from_index != to_index } .map do |sid, from_index, to_index| - { op: :move, label: from_h[sid].libelle, private: from_h[sid].private?, from: from_index, to: to_index, position: to_index } + { op: :move, label: from_h[sid].libelle, private: from_h[sid].private?, from: from_index, to: to_index, position: to_index, stable_id: sid } end changed = kept @@ -172,7 +172,8 @@ class ProcedureRevision < ApplicationRecord label: from_type_de_champ.libelle, private: from_type_de_champ.private?, from: from_type_de_champ.type_champ, - to: to_type_de_champ.type_champ + to: to_type_de_champ.type_champ, + stable_id: from_type_de_champ.stable_id } end if from_type_de_champ.libelle != to_type_de_champ.libelle @@ -182,7 +183,8 @@ class ProcedureRevision < ApplicationRecord label: from_type_de_champ.libelle, private: from_type_de_champ.private?, from: from_type_de_champ.libelle, - to: to_type_de_champ.libelle + to: to_type_de_champ.libelle, + stable_id: from_type_de_champ.stable_id } end if from_type_de_champ.description != to_type_de_champ.description @@ -192,7 +194,8 @@ class ProcedureRevision < ApplicationRecord label: from_type_de_champ.libelle, private: from_type_de_champ.private?, from: from_type_de_champ.description, - to: to_type_de_champ.description + to: to_type_de_champ.description, + stable_id: from_type_de_champ.stable_id } end if from_type_de_champ.mandatory? != to_type_de_champ.mandatory? @@ -202,7 +205,8 @@ class ProcedureRevision < ApplicationRecord label: from_type_de_champ.libelle, private: from_type_de_champ.private?, from: from_type_de_champ.mandatory?, - to: to_type_de_champ.mandatory? + to: to_type_de_champ.mandatory?, + stable_id: from_type_de_champ.stable_id } end if to_type_de_champ.drop_down_list? @@ -213,7 +217,8 @@ class ProcedureRevision < ApplicationRecord label: from_type_de_champ.libelle, private: from_type_de_champ.private?, from: from_type_de_champ.drop_down_list_options, - to: to_type_de_champ.drop_down_list_options + to: to_type_de_champ.drop_down_list_options, + stable_id: from_type_de_champ.stable_id } end elsif to_type_de_champ.carte? @@ -224,7 +229,8 @@ class ProcedureRevision < ApplicationRecord label: from_type_de_champ.libelle, private: from_type_de_champ.private?, from: from_type_de_champ.carte_optional_layers, - to: to_type_de_champ.carte_optional_layers + to: to_type_de_champ.carte_optional_layers, + stable_id: from_type_de_champ.stable_id } end elsif to_type_de_champ.piece_justificative? @@ -235,7 +241,8 @@ class ProcedureRevision < ApplicationRecord label: from_type_de_champ.libelle, private: from_type_de_champ.private?, from: from_type_de_champ.piece_justificative_template_filename, - to: to_type_de_champ.piece_justificative_template_filename + to: to_type_de_champ.piece_justificative_template_filename, + stable_id: from_type_de_champ.stable_id } end elsif to_type_de_champ.repetition? diff --git a/spec/models/procedure_revision_spec.rb b/spec/models/procedure_revision_spec.rb index c7280fb95..efdc05dc1 100644 --- a/spec/models/procedure_revision_spec.rb +++ b/spec/models/procedure_revision_spec.rb @@ -174,7 +174,8 @@ describe ProcedureRevision do { op: :add, label: "Un champ text", - private: false + private: false, + stable_id: new_type_de_champ.stable_id } ]) @@ -186,12 +187,14 @@ describe ProcedureRevision do label: type_de_champ_first.libelle, private: false, from: type_de_champ_first.libelle, - to: "modifier le libelle" + to: "modifier le libelle", + stable_id: type_de_champ_first.stable_id }, { op: :add, label: "Un champ text", - private: false + private: false, + stable_id: new_type_de_champ.stable_id } ]) expect(new_revision.types_de_champ.first.revision).to eq(new_revision) @@ -204,19 +207,22 @@ describe ProcedureRevision do label: type_de_champ_first.libelle, private: false, from: type_de_champ_first.libelle, - to: "modifier le libelle" + to: "modifier le libelle", + stable_id: type_de_champ_first.stable_id }, { op: :add, label: "Un champ text", - private: false + private: false, + stable_id: new_type_de_champ.stable_id }, { op: :move, label: type_de_champ_second.libelle, private: false, from: 1, - to: 2 + to: 2, + stable_id: type_de_champ_second.stable_id } ]) expect(new_revision.types_de_champ.last.revision).to eq(revision) @@ -226,12 +232,14 @@ describe ProcedureRevision do { op: :remove, label: type_de_champ_first.libelle, - private: false + private: false, + stable_id: type_de_champ_first.stable_id }, { op: :add, label: "Un champ text", - private: false + private: false, + stable_id: new_type_de_champ.stable_id } ]) @@ -241,12 +249,14 @@ describe ProcedureRevision do { op: :remove, label: type_de_champ_first.libelle, - private: false + private: false, + stable_id: type_de_champ_first.stable_id }, { op: :add, label: "Un champ text", - private: false + private: false, + stable_id: new_type_de_champ.stable_id }, { op: :update, @@ -254,7 +264,8 @@ describe ProcedureRevision do label: type_de_champ_second.libelle, private: false, from: type_de_champ_second.description, - to: "une description" + to: "une description", + stable_id: type_de_champ_second.stable_id }, { op: :update, @@ -262,7 +273,8 @@ describe ProcedureRevision do label: type_de_champ_second.libelle, private: false, from: false, - to: true + to: true, + stable_id: type_de_champ_second.stable_id } ]) @@ -272,12 +284,14 @@ describe ProcedureRevision do { op: :remove, label: type_de_champ_first.libelle, - private: false + private: false, + stable_id: type_de_champ_first.stable_id }, { op: :add, label: "Un champ text", - private: false + private: false, + stable_id: new_type_de_champ.stable_id }, { op: :update, @@ -285,7 +299,8 @@ describe ProcedureRevision do label: type_de_champ_second.libelle, private: false, from: type_de_champ_second.description, - to: "une description" + to: "une description", + stable_id: type_de_champ_second.stable_id }, { op: :update, @@ -293,7 +308,8 @@ describe ProcedureRevision do label: type_de_champ_second.libelle, private: false, from: false, - to: true + to: true, + stable_id: type_de_champ_second.stable_id }, { op: :update, @@ -301,7 +317,8 @@ describe ProcedureRevision do label: "sub type de champ", private: false, from: "text", - to: "drop_down_list" + to: "drop_down_list", + stable_id: new_revision.types_de_champ.last.types_de_champ.first.stable_id }, { op: :update, @@ -309,7 +326,8 @@ describe ProcedureRevision do label: "sub type de champ", private: false, from: [], - to: ["one", "two"] + to: ["one", "two"], + stable_id: new_revision.types_de_champ.last.types_de_champ.first.stable_id } ]) @@ -319,12 +337,14 @@ describe ProcedureRevision do { op: :remove, label: type_de_champ_first.libelle, - private: false + private: false, + stable_id: type_de_champ_first.stable_id }, { op: :add, label: "Un champ text", - private: false + private: false, + stable_id: new_type_de_champ.stable_id }, { op: :update, @@ -332,7 +352,8 @@ describe ProcedureRevision do label: type_de_champ_second.libelle, private: false, from: type_de_champ_second.description, - to: "une description" + to: "une description", + stable_id: type_de_champ_second.stable_id }, { op: :update, @@ -340,7 +361,8 @@ describe ProcedureRevision do label: type_de_champ_second.libelle, private: false, from: false, - to: true + to: true, + stable_id: type_de_champ_second.stable_id }, { op: :update, @@ -348,7 +370,8 @@ describe ProcedureRevision do label: "sub type de champ", private: false, from: "text", - to: "carte" + to: "carte", + stable_id: new_revision.types_de_champ.last.types_de_champ.first.stable_id }, { op: :update, @@ -356,7 +379,8 @@ describe ProcedureRevision do label: "sub type de champ", private: false, from: [], - to: [:cadastres, :znieff] + to: [:cadastres, :znieff], + stable_id: new_revision.types_de_champ.last.types_de_champ.first.stable_id } ]) end From 09a09d3fcf2fbfac0d92f043eeb0779745be7e14 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 20 Oct 2021 17:26:09 +0200 Subject: [PATCH 2/3] feat(revisions): add rebased_at to champs --- app/models/champ.rb | 1 + app/models/champs/address_champ.rb | 1 + app/models/champs/annuaire_education_champ.rb | 1 + app/models/champs/carte_champ.rb | 1 + app/models/champs/checkbox_champ.rb | 1 + app/models/champs/civilite_champ.rb | 1 + app/models/champs/commune_champ.rb | 1 + app/models/champs/date_champ.rb | 1 + app/models/champs/datetime_champ.rb | 1 + app/models/champs/decimal_number_champ.rb | 1 + app/models/champs/departement_champ.rb | 1 + app/models/champs/dossier_link_champ.rb | 1 + app/models/champs/drop_down_list_champ.rb | 1 + app/models/champs/email_champ.rb | 1 + app/models/champs/engagement_champ.rb | 1 + app/models/champs/explication_champ.rb | 1 + app/models/champs/header_section_champ.rb | 1 + app/models/champs/iban_champ.rb | 1 + app/models/champs/integer_number_champ.rb | 1 + app/models/champs/linked_drop_down_list_champ.rb | 1 + app/models/champs/multiple_drop_down_list_champ.rb | 1 + app/models/champs/number_champ.rb | 1 + app/models/champs/pays_champ.rb | 1 + app/models/champs/phone_champ.rb | 1 + app/models/champs/piece_justificative_champ.rb | 1 + app/models/champs/region_champ.rb | 1 + app/models/champs/repetition_champ.rb | 1 + app/models/champs/siret_champ.rb | 1 + app/models/champs/text_champ.rb | 1 + app/models/champs/textarea_champ.rb | 1 + app/models/champs/titre_identite_champ.rb | 1 + app/models/champs/yes_no_champ.rb | 1 + db/migrate/20211013131241_add_rebased_at_to_champs.rb | 5 +++++ db/schema.rb | 3 ++- 34 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20211013131241_add_rebased_at_to_champs.rb diff --git a/app/models/champ.rb b/app/models/champ.rb index 61930b3ab..5f7f66e44 100644 --- a/app/models/champ.rb +++ b/app/models/champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/address_champ.rb b/app/models/champs/address_champ.rb index 3e7870b50..c6298b99a 100644 --- a/app/models/champs/address_champ.rb +++ b/app/models/champs/address_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/annuaire_education_champ.rb b/app/models/champs/annuaire_education_champ.rb index 22141ca17..727a5a4bf 100644 --- a/app/models/champs/annuaire_education_champ.rb +++ b/app/models/champs/annuaire_education_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/carte_champ.rb b/app/models/champs/carte_champ.rb index 1e91e529e..7e3795925 100644 --- a/app/models/champs/carte_champ.rb +++ b/app/models/champs/carte_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/checkbox_champ.rb b/app/models/champs/checkbox_champ.rb index 82f009577..a500abb59 100644 --- a/app/models/champs/checkbox_champ.rb +++ b/app/models/champs/checkbox_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/civilite_champ.rb b/app/models/champs/civilite_champ.rb index ace32a968..cf5316ea0 100644 --- a/app/models/champs/civilite_champ.rb +++ b/app/models/champs/civilite_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/commune_champ.rb b/app/models/champs/commune_champ.rb index 349221cf1..4477da8e3 100644 --- a/app/models/champs/commune_champ.rb +++ b/app/models/champs/commune_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/date_champ.rb b/app/models/champs/date_champ.rb index 2e09bd29d..db0644ed7 100644 --- a/app/models/champs/date_champ.rb +++ b/app/models/champs/date_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/datetime_champ.rb b/app/models/champs/datetime_champ.rb index f7f5bd496..8899811b1 100644 --- a/app/models/champs/datetime_champ.rb +++ b/app/models/champs/datetime_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/decimal_number_champ.rb b/app/models/champs/decimal_number_champ.rb index f574c07ca..1bc48db23 100644 --- a/app/models/champs/decimal_number_champ.rb +++ b/app/models/champs/decimal_number_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/departement_champ.rb b/app/models/champs/departement_champ.rb index ac5c89633..b9b68db43 100644 --- a/app/models/champs/departement_champ.rb +++ b/app/models/champs/departement_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/dossier_link_champ.rb b/app/models/champs/dossier_link_champ.rb index 866f70197..55c8763e9 100644 --- a/app/models/champs/dossier_link_champ.rb +++ b/app/models/champs/dossier_link_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/drop_down_list_champ.rb b/app/models/champs/drop_down_list_champ.rb index 92f52e3f1..bf9e1b70d 100644 --- a/app/models/champs/drop_down_list_champ.rb +++ b/app/models/champs/drop_down_list_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/email_champ.rb b/app/models/champs/email_champ.rb index c8a1949b0..acdd6568c 100644 --- a/app/models/champs/email_champ.rb +++ b/app/models/champs/email_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/engagement_champ.rb b/app/models/champs/engagement_champ.rb index 986623136..bdd6ff0a6 100644 --- a/app/models/champs/engagement_champ.rb +++ b/app/models/champs/engagement_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/explication_champ.rb b/app/models/champs/explication_champ.rb index d20108393..bac3d0aff 100644 --- a/app/models/champs/explication_champ.rb +++ b/app/models/champs/explication_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/header_section_champ.rb b/app/models/champs/header_section_champ.rb index 0ff9c7659..2cc24c888 100644 --- a/app/models/champs/header_section_champ.rb +++ b/app/models/champs/header_section_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/iban_champ.rb b/app/models/champs/iban_champ.rb index 71ba23281..df94eac66 100644 --- a/app/models/champs/iban_champ.rb +++ b/app/models/champs/iban_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/integer_number_champ.rb b/app/models/champs/integer_number_champ.rb index 8272800e1..5187db3d9 100644 --- a/app/models/champs/integer_number_champ.rb +++ b/app/models/champs/integer_number_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/linked_drop_down_list_champ.rb b/app/models/champs/linked_drop_down_list_champ.rb index f7022d727..e013d1c24 100644 --- a/app/models/champs/linked_drop_down_list_champ.rb +++ b/app/models/champs/linked_drop_down_list_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/multiple_drop_down_list_champ.rb b/app/models/champs/multiple_drop_down_list_champ.rb index 87429b0ee..899dd0159 100644 --- a/app/models/champs/multiple_drop_down_list_champ.rb +++ b/app/models/champs/multiple_drop_down_list_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/number_champ.rb b/app/models/champs/number_champ.rb index fa2ec9b47..d43a6d3df 100644 --- a/app/models/champs/number_champ.rb +++ b/app/models/champs/number_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/pays_champ.rb b/app/models/champs/pays_champ.rb index 634391a31..2eb3eee76 100644 --- a/app/models/champs/pays_champ.rb +++ b/app/models/champs/pays_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/phone_champ.rb b/app/models/champs/phone_champ.rb index 15002fe60..baa032d5b 100644 --- a/app/models/champs/phone_champ.rb +++ b/app/models/champs/phone_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/piece_justificative_champ.rb b/app/models/champs/piece_justificative_champ.rb index 245750c01..5076f963a 100644 --- a/app/models/champs/piece_justificative_champ.rb +++ b/app/models/champs/piece_justificative_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/region_champ.rb b/app/models/champs/region_champ.rb index 255e4abb2..5fcbe8934 100644 --- a/app/models/champs/region_champ.rb +++ b/app/models/champs/region_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/repetition_champ.rb b/app/models/champs/repetition_champ.rb index b07fd0958..75451686b 100644 --- a/app/models/champs/repetition_champ.rb +++ b/app/models/champs/repetition_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/siret_champ.rb b/app/models/champs/siret_champ.rb index b9b5b27b5..8b7347235 100644 --- a/app/models/champs/siret_champ.rb +++ b/app/models/champs/siret_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/text_champ.rb b/app/models/champs/text_champ.rb index 1376cce48..9c48ba036 100644 --- a/app/models/champs/text_champ.rb +++ b/app/models/champs/text_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/textarea_champ.rb b/app/models/champs/textarea_champ.rb index 028950a5f..39570d81a 100644 --- a/app/models/champs/textarea_champ.rb +++ b/app/models/champs/textarea_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/titre_identite_champ.rb b/app/models/champs/titre_identite_champ.rb index 982ae7ae7..1d74c3245 100644 --- a/app/models/champs/titre_identite_champ.rb +++ b/app/models/champs/titre_identite_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/champs/yes_no_champ.rb b/app/models/champs/yes_no_champ.rb index fc8346cfb..293beaba2 100644 --- a/app/models/champs/yes_no_champ.rb +++ b/app/models/champs/yes_no_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/db/migrate/20211013131241_add_rebased_at_to_champs.rb b/db/migrate/20211013131241_add_rebased_at_to_champs.rb new file mode 100644 index 000000000..209b37992 --- /dev/null +++ b/db/migrate/20211013131241_add_rebased_at_to_champs.rb @@ -0,0 +1,5 @@ +class AddRebasedAtToChamps < ActiveRecord::Migration[6.1] + def change + add_column :champs, :rebased_at, :datetime + end +end diff --git a/db/schema.rb b/db/schema.rb index b8c245f1c..f5a4cc1ba 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_10_20_104237) do +ActiveRecord::Schema.define(version: 2021_10_20_114237) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -190,6 +190,7 @@ ActiveRecord::Schema.define(version: 2021_10_20_104237) do t.string "external_id" t.string "fetch_external_data_exceptions", array: true t.jsonb "value_json" + t.datetime "rebased_at" t.index ["dossier_id"], name: "index_champs_on_dossier_id" t.index ["etablissement_id"], name: "index_champs_on_etablissement_id" t.index ["parent_id"], name: "index_champs_on_parent_id" From 2a3a9dd822ce3d81400bdb14712750bfbc625fe7 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 13 Oct 2021 14:41:05 +0200 Subject: [PATCH 3/3] feat(revisions): rebase dossiers brouillons --- app/jobs/dossier_rebase_job.rb | 8 ++ app/models/concerns/dossier_rebase_concern.rb | 121 ++++++++++++++++++ app/models/dossier.rb | 1 + app/models/procedure.rb | 3 + .../_champ_label_content.html.haml | 4 + spec/models/dossier_spec.rb | 67 ++++++++++ 6 files changed, 204 insertions(+) create mode 100644 app/jobs/dossier_rebase_job.rb create mode 100644 app/models/concerns/dossier_rebase_concern.rb diff --git a/app/jobs/dossier_rebase_job.rb b/app/jobs/dossier_rebase_job.rb new file mode 100644 index 000000000..916d9d1e1 --- /dev/null +++ b/app/jobs/dossier_rebase_job.rb @@ -0,0 +1,8 @@ +class DossierRebaseJob < ApplicationJob + # If by the time the job runs the Dossier has been deleted, ignore the rebase + discard_on ActiveRecord::RecordNotFound + + def perform(dossier) + dossier.rebase! + end +end diff --git a/app/models/concerns/dossier_rebase_concern.rb b/app/models/concerns/dossier_rebase_concern.rb new file mode 100644 index 000000000..00e9aacc2 --- /dev/null +++ b/app/models/concerns/dossier_rebase_concern.rb @@ -0,0 +1,121 @@ +module DossierRebaseConcern + extend ActiveSupport::Concern + + def rebase! + if brouillon? && revision != procedure.published_revision + transaction do + rebase + end + end + end + + private + + def rebase + attachments_to_purge = [] + geo_areas_to_delete = [] + changes_by_type_de_champ = revision.compare(procedure.published_revision).group_by { |change| change[:stable_id] } + + changes_by_type_de_champ.each do |stable_id, changes| + type_de_champ = find_type_de_champ_by_stable_id(stable_id) + published_type_de_champ = find_type_de_champ_by_stable_id(stable_id, published: true) + + changes.each do |change| + case change[:op] + when :add + add_new_champs_for_revision(published_type_de_champ) + when :remove + delete_champs_for_revision(type_de_champ) + end + end + end + + flattened_all_champs.each do |champ| + changes_by_stable_id = (changes_by_type_de_champ[champ.stable_id] || []) + .filter { |change| change[:op] == :update } + + update_champ_for_revision(champ) do |update| + changes_by_stable_id.each do |change| + case change[:attribute] + when :type_champ + update[:type] = "Champs::#{change[:to].classify}Champ" + update[:value] = nil + update[:external_id] = nil + update[:data] = nil + geo_areas_to_delete += champ.geo_areas + if champ.piece_justificative_file.attached? + attachments_to_purge << champ.piece_justificative_file + end + when :drop_down_options + update[:value] = nil + when :carte_layers + geo_areas_to_delete += champ.geo_areas + end + update[:rebased_at] = Time.zone.now + end + end + end + + self.update_column(:revision_id, procedure.published_revision_id) + attachments_to_purge.each(&:purge_later) + geo_areas_to_delete.each(&:destroy) + end + + def add_new_champs_for_revision(published_type_de_champ) + if published_type_de_champ.parent + find_champs_by_stable_id(published_type_de_champ.parent.stable_id).each do |champ_repetition| + champ_repetition.rows.size.times do |row| + champ = published_type_de_champ.champ.build(row: row) + champ_repetition.champs << champ + end + end + else + champ = published_type_de_champ.build_champ + self.champs << champ + end + end + + def update_champ_for_revision(champ) + published_type_de_champ = find_type_de_champ_by_stable_id(champ.stable_id, published: true) + return if !published_type_de_champ + + update = {} + + yield update + + if champ.type_de_champ != published_type_de_champ + update[:type_de_champ_id] = published_type_de_champ.id + end + + if update.present? + champ.update_columns(update) + end + end + + def delete_champs_for_revision(published_type_de_champ) + Champ.where(id: find_champs_by_stable_id(published_type_de_champ.stable_id).map(&:id)) + .destroy_all + end + + def flattened_all_types_de_champ(published: false) + revision = published ? procedure.published_revision : self.revision + types_de_champ = revision.types_de_champ + revision.types_de_champ_private + (types_de_champ + types_de_champ.filter(&:repetition?).flat_map(&:types_de_champ)) + .index_by(&:stable_id) + end + + def flattened_all_champs + all_champs = (champs + champs_private) + all_champs + all_champs.filter(&:repetition?).flat_map(&:champs) + end + + def find_type_de_champ_by_stable_id(stable_id, published: false) + flattened_all_types_de_champ(published: published)[stable_id] + end + + def find_champs_by_stable_id(stable_id) + flattened_all_champs.filter do |champ| + champ.stable_id == stable_id + end + end +end diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 6a35c42d9..6dcffed7c 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -36,6 +36,7 @@ class Dossier < ApplicationRecord self.ignored_columns = [:en_construction_conservation_extension] include DossierFilteringConcern + include DossierRebaseConcern include Discard::Model self.discard_column = :hidden_at diff --git a/app/models/procedure.rb b/app/models/procedure.rb index df9aba673..ebd09ad1b 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -714,6 +714,9 @@ class Procedure < ApplicationRecord def publish_revision! update!(draft_revision: create_new_revision, published_revision: draft_revision) published_revision.touch(:published_at) + dossiers.state_brouillon.find_each do |dossier| + DossierRebaseJob.perform_later(dossier) + end end def cnaf_enabled? diff --git a/app/views/shared/dossiers/editable_champs/_champ_label_content.html.haml b/app/views/shared/dossiers/editable_champs/_champ_label_content.html.haml index 7174f7ee5..39902cb87 100644 --- a/app/views/shared/dossiers/editable_champs/_champ_label_content.html.haml +++ b/app/views/shared/dossiers/editable_champs/_champ_label_content.html.haml @@ -5,3 +5,7 @@ - if champ.updated_at.present? && seen_at.present? %span.updated-at{ class: highlight_if_unseen_class(seen_at, champ.updated_at) } = "modifié le #{try_format_datetime(champ.updated_at)}" + +- if champ.rebased_at.present? && champ.rebased_at > (seen_at || champ.updated_at) && current_user.owns_or_invite?(champ.dossier) + %span.updated-at.highlighted + Le type de ce champ où sa description a été modifiée par l'administration. Vérifier son contenu. diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index df75ca854..c9cd324b1 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -1459,4 +1459,71 @@ describe Dossier do it { expect(dossier.spreadsheet_columns(types_de_champ: [])).to include(["État du dossier", "Brouillon"]) } end + + describe "#rebase" do + let(:procedure) { create(:procedure, :with_type_de_champ_mandatory, :with_yes_no, :with_repetition, :with_datetime) } + let(:dossier) { create(:dossier, procedure: procedure) } + + let(:yes_no_type_de_champ) { procedure.types_de_champ.find { |tdc| tdc.type_champ == TypeDeChamp.type_champs.fetch(:yes_no) } } + + let(:text_type_de_champ) { procedure.types_de_champ.find(&:mandatory?) } + let(:text_champ) { dossier.champs.find(&:mandatory?) } + let(:rebased_text_champ) { dossier.champs.find { |c| c.type_champ == TypeDeChamp.type_champs.fetch(:text) } } + + let(:datetime_type_de_champ) { procedure.types_de_champ.find { |tdc| tdc.type_champ == TypeDeChamp.type_champs.fetch(:datetime) } } + let(:datetime_champ) { dossier.champs.find { |c| c.type_champ == TypeDeChamp.type_champs.fetch(:datetime) } } + let(:rebased_datetime_champ) { dossier.champs.find { |c| c.type_champ == TypeDeChamp.type_champs.fetch(:date) } } + + let(:repetition_type_de_champ) { procedure.types_de_champ.find { |tdc| tdc.type_champ == TypeDeChamp.type_champs.fetch(:repetition) } } + let(:repetition_text_type_de_champ) { repetition_type_de_champ.types_de_champ.find { |tdc| tdc.type_champ == TypeDeChamp.type_champs.fetch(:text) } } + let(:repetition_champ) { dossier.champs.find { |c| c.type_champ == TypeDeChamp.type_champs.fetch(:repetition) } } + let(:rebased_repetition_champ) { dossier.champs.find { |c| c.type_champ == TypeDeChamp.type_champs.fetch(:repetition) } } + + before do + procedure.publish! + procedure.draft_revision.add_type_de_champ({ + type_champ: TypeDeChamp.type_champs.fetch(:text), + libelle: "Un champ text" + }) + procedure.draft_revision.find_or_clone_type_de_champ(text_type_de_champ).update(mandatory: false, libelle: "nouveau libelle") + procedure.draft_revision.find_or_clone_type_de_champ(datetime_type_de_champ).update(type_champ: TypeDeChamp.type_champs.fetch(:date)) + procedure.draft_revision.find_or_clone_type_de_champ(repetition_text_type_de_champ).update(libelle: "nouveau libelle dans une repetition") + procedure.draft_revision.add_type_de_champ({ + type_champ: TypeDeChamp.type_champs.fetch(:checkbox), + libelle: "oui ou non", + parent_id: repetition_type_de_champ.stable_id + }) + procedure.draft_revision.remove_type_de_champ(yes_no_type_de_champ.stable_id) + + datetime_champ.update(value: Date.today.to_s) + text_champ.update(value: 'bonjour') + end + + it "updates the brouillon champs with the latest revision changes" do + revision_id = dossier.revision_id + libelle = text_type_de_champ.libelle + + expect(dossier.revision).to eq(procedure.published_revision) + expect(dossier.champs.size).to eq(4) + expect(repetition_champ.rows.size).to eq(1) + expect(repetition_champ.rows[0].size).to eq(1) + + procedure.publish_revision! + perform_enqueued_jobs + procedure.reload + dossier.reload + + expect(procedure.revisions.size).to eq(3) + expect(dossier.revision).to eq(procedure.published_revision) + expect(dossier.champs.size).to eq(4) + expect(rebased_text_champ.value).to eq(text_champ.value) + expect(rebased_text_champ.type_de_champ_id).not_to eq(text_champ.type_de_champ_id) + expect(rebased_datetime_champ.type_champ).to eq(TypeDeChamp.type_champs.fetch(:date)) + expect(rebased_datetime_champ.value).to be_nil + expect(rebased_repetition_champ.rows.size).to eq(1) + expect(rebased_repetition_champ.rows[0].size).to eq(2) + expect(rebased_text_champ.rebased_at).not_to be_nil + expect(rebased_datetime_champ.rebased_at).not_to be_nil + end + end end