Merge pull request #7368 from betagouv/refactor-revision-rebase-v2
Refactor on rebase
This commit is contained in:
commit
72c22e3a2d
6 changed files with 527 additions and 345 deletions
|
@ -50,6 +50,7 @@ class Champ < ApplicationRecord
|
||||||
:dossier_link?,
|
:dossier_link?,
|
||||||
:titre_identite?,
|
:titre_identite?,
|
||||||
:header_section?,
|
:header_section?,
|
||||||
|
:stable_id,
|
||||||
to: :type_de_champ
|
to: :type_de_champ
|
||||||
|
|
||||||
scope :updated_since?, -> (date) { where('champs.updated_at > ?', date) }
|
scope :updated_since?, -> (date) { where('champs.updated_at > ?', date) }
|
||||||
|
@ -157,10 +158,6 @@ class Champ < ApplicationRecord
|
||||||
"#{html_id}-description" if description.present?
|
"#{html_id}-description" if description.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
def stable_id
|
|
||||||
type_de_champ.stable_id
|
|
||||||
end
|
|
||||||
|
|
||||||
def log_fetch_external_data_exception(exception)
|
def log_fetch_external_data_exception(exception)
|
||||||
exceptions = self.fetch_external_data_exceptions ||= []
|
exceptions = self.fetch_external_data_exceptions ||= []
|
||||||
exceptions << exception.inspect
|
exceptions << exception.inspect
|
||||||
|
|
|
@ -50,114 +50,102 @@ module DossierRebaseConcern
|
||||||
end
|
end
|
||||||
|
|
||||||
def rebase
|
def rebase
|
||||||
attachments_to_purge = []
|
# revision we are rebasing to
|
||||||
geo_areas_to_delete = []
|
target_revision = procedure.published_revision
|
||||||
changes_by_type_de_champ = pending_changes
|
|
||||||
|
# index published types de champ coordinates by stable_id
|
||||||
|
target_coordinates_by_stable_id = target_revision
|
||||||
|
.revision_types_de_champ
|
||||||
|
.includes(:type_de_champ, :parent)
|
||||||
|
.index_by(&:stable_id)
|
||||||
|
|
||||||
|
changes_by_op = pending_changes
|
||||||
.filter { |change| change[:model] == :type_de_champ }
|
.filter { |change| change[:model] == :type_de_champ }
|
||||||
.group_by { |change| change[:stable_id] }
|
.group_by { |change| change[:op] }
|
||||||
|
.tap { |h| h.default = [] }
|
||||||
|
|
||||||
changes_by_type_de_champ.each do |stable_id, changes|
|
# add champ
|
||||||
type_de_champ = find_type_de_champ_by_stable_id(stable_id)
|
changes_by_op[:add]
|
||||||
published_type_de_champ = find_type_de_champ_by_stable_id(stable_id, published: true)
|
.map { |change| change[:stable_id] }
|
||||||
|
.map { |stable_id| target_coordinates_by_stable_id[stable_id] }
|
||||||
|
.each { |coordinate| add_new_champs_for_revision(coordinate) }
|
||||||
|
|
||||||
changes.each do |change|
|
# remove champ
|
||||||
case change[:op]
|
changes_by_op[:remove]
|
||||||
when :add
|
.each { |change| delete_champs_for_revision(change[:stable_id]) }
|
||||||
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_op[:update]
|
||||||
changes_by_stable_id = (changes_by_type_de_champ[champ.stable_id] || [])
|
.map { |change| [change, Champ.joins(:type_de_champ).where(dossier: self, type_de_champ: { stable_id: change[:stable_id] })] }
|
||||||
.filter { |change| change[:op] == :update }
|
.each { |change, champs| apply(change, champs) }
|
||||||
|
|
||||||
update_champ_for_revision(champ) do |update|
|
# due to repetition tdc clone on update or erase
|
||||||
changes_by_stable_id.each do |change|
|
# we must reassign tdc to the latest version
|
||||||
case change[:attribute]
|
Champ
|
||||||
when :type_champ
|
.includes(:type_de_champ)
|
||||||
update[:type] = "Champs::#{change[:to].classify}Champ"
|
.where(dossier: self)
|
||||||
update[:value] = nil
|
.map { |c| [c, target_coordinates_by_stable_id[c.stable_id].type_de_champ] }
|
||||||
update[:external_id] = nil
|
.each { |c, target_tdc| c.update_columns(type_de_champ_id: target_tdc.id, rebased_at: Time.zone.now) }
|
||||||
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
|
|
||||||
if change[:from].include?(:cadastres) && !change[:to].include?(:cadastres)
|
|
||||||
geo_areas_to_delete += champ.cadastres
|
|
||||||
end
|
|
||||||
end
|
|
||||||
update[:rebased_at] = Time.zone.now
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
self.update_column(:revision_id, procedure.published_revision_id)
|
# update dossier revision
|
||||||
attachments_to_purge.each(&:purge_later)
|
self.update_column(:revision_id, target_revision.id)
|
||||||
geo_areas_to_delete.each(&:destroy)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_new_champs_for_revision(published_type_de_champ)
|
def apply(change, champs)
|
||||||
if published_type_de_champ.parent
|
case change[:attribute]
|
||||||
find_champs_by_stable_id(published_type_de_champ.parent.stable_id).each do |champ_repetition|
|
when :type_champ
|
||||||
|
champs.each { |champ| champ.piece_justificative_file.purge_later } # FIX ME: change updated_at
|
||||||
|
GeoArea.where(champ: champs).destroy_all
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "Champs::#{change[:to].classify}Champ",
|
||||||
|
value: nil,
|
||||||
|
external_id: nil,
|
||||||
|
data: nil
|
||||||
|
}
|
||||||
|
when :drop_down_options
|
||||||
|
{ value: nil }
|
||||||
|
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 { |champ| champ.cadastres.each(&:destroy) }
|
||||||
|
end
|
||||||
|
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
&.then { |update_params| champs.update_all(update_params) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_new_champs_for_revision(target_coordinate)
|
||||||
|
if target_coordinate.child?
|
||||||
|
# If this type de champ is a child, we create a new champ for each row of the parent
|
||||||
|
parent_stable_id = target_coordinate.parent.stable_id
|
||||||
|
champs_repetition = Champ
|
||||||
|
.includes(:champs, :type_de_champ)
|
||||||
|
.where(dossier: self, type_de_champ: { stable_id: parent_stable_id })
|
||||||
|
|
||||||
|
champs_repetition.each do |champ_repetition|
|
||||||
champ_repetition.champs.map(&:row).uniq.each do |row|
|
champ_repetition.champs.map(&:row).uniq.each do |row|
|
||||||
champ = published_type_de_champ.champ.build(row: row)
|
create_champ(target_coordinate, champ_repetition, row: row)
|
||||||
champ_repetition.champs << champ
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
champ = published_type_de_champ.build_champ(revision: procedure.published_revision)
|
create_champ(target_coordinate, self)
|
||||||
self.champs << champ
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_champ_for_revision(champ)
|
def create_champ(target_coordinate, parent, row: nil)
|
||||||
published_type_de_champ = find_type_de_champ_by_stable_id(champ.stable_id, published: true)
|
params = { revision: target_coordinate.revision }
|
||||||
return if !published_type_de_champ
|
params[:row] = row if row
|
||||||
|
champ = target_coordinate
|
||||||
update = {}
|
.type_de_champ
|
||||||
|
.build_champ(params)
|
||||||
yield update
|
parent.champs << champ
|
||||||
|
|
||||||
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
|
end
|
||||||
|
|
||||||
def delete_champs_for_revision(published_type_de_champ)
|
def delete_champs_for_revision(stable_id)
|
||||||
Champ.where(id: find_champs_by_stable_id(published_type_de_champ.stable_id).map(&:id))
|
Champ
|
||||||
|
.joins(:type_de_champ)
|
||||||
|
.where(dossier: self, types_de_champ: { stable_id: stable_id })
|
||||||
.destroy_all
|
.destroy_all
|
||||||
end
|
end
|
||||||
|
|
||||||
def flattened_all_types_de_champ(published: false)
|
|
||||||
revision = published ? procedure.published_revision : self.revision
|
|
||||||
types_de_champ = revision.types_de_champ_public + 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
|
end
|
||||||
|
|
|
@ -18,7 +18,7 @@ class ProcedureRevision < ApplicationRecord
|
||||||
|
|
||||||
has_many :dossiers, inverse_of: :revision, foreign_key: :revision_id
|
has_many :dossiers, inverse_of: :revision, foreign_key: :revision_id
|
||||||
|
|
||||||
has_many :revision_types_de_champ, class_name: 'ProcedureRevisionTypeDeChamp', foreign_key: :revision_id, dependent: :destroy, inverse_of: :revision
|
has_many :revision_types_de_champ, -> { order(:position, :id) }, class_name: 'ProcedureRevisionTypeDeChamp', foreign_key: :revision_id, dependent: :destroy, inverse_of: :revision
|
||||||
has_many :revision_types_de_champ_public, -> { root.public_only.ordered }, class_name: 'ProcedureRevisionTypeDeChamp', foreign_key: :revision_id, dependent: :destroy, inverse_of: :revision
|
has_many :revision_types_de_champ_public, -> { root.public_only.ordered }, class_name: 'ProcedureRevisionTypeDeChamp', foreign_key: :revision_id, dependent: :destroy, inverse_of: :revision
|
||||||
has_many :revision_types_de_champ_private, -> { root.private_only.ordered }, class_name: 'ProcedureRevisionTypeDeChamp', foreign_key: :revision_id, dependent: :destroy, inverse_of: :revision
|
has_many :revision_types_de_champ_private, -> { root.private_only.ordered }, class_name: 'ProcedureRevisionTypeDeChamp', foreign_key: :revision_id, dependent: :destroy, inverse_of: :revision
|
||||||
has_many :types_de_champ, through: :revision_types_de_champ, source: :type_de_champ
|
has_many :types_de_champ, through: :revision_types_de_champ, source: :type_de_champ
|
||||||
|
@ -125,14 +125,13 @@ class ProcedureRevision < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def different_from?(revision)
|
def different_from?(revision)
|
||||||
types_de_champ != revision.types_de_champ ||
|
revision_types_de_champ != revision.revision_types_de_champ ||
|
||||||
attestation_template != revision.attestation_template
|
attestation_template != revision.attestation_template
|
||||||
end
|
end
|
||||||
|
|
||||||
def compare(revision)
|
def compare(revision)
|
||||||
changes = []
|
changes = []
|
||||||
changes += compare_types_de_champ(types_de_champ_public, revision.types_de_champ_public)
|
changes += compare_revision_types_de_champ(revision_types_de_champ, revision.revision_types_de_champ)
|
||||||
changes += compare_types_de_champ(types_de_champ_private, revision.types_de_champ_private)
|
|
||||||
changes += compare_attestation_template(attestation_template, revision.attestation_template)
|
changes += compare_attestation_template(attestation_template, revision.attestation_template)
|
||||||
changes
|
changes
|
||||||
end
|
end
|
||||||
|
@ -266,43 +265,43 @@ class ProcedureRevision < ApplicationRecord
|
||||||
changes
|
changes
|
||||||
end
|
end
|
||||||
|
|
||||||
def compare_types_de_champ(from_tdc, to_tdc)
|
def compare_revision_types_de_champ(from_coordinates, to_coordinates)
|
||||||
if from_tdc == to_tdc
|
if from_coordinates == to_coordinates
|
||||||
[]
|
[]
|
||||||
else
|
else
|
||||||
from_h = from_tdc.index_by(&:stable_id)
|
from_h = from_coordinates.index_by(&:stable_id)
|
||||||
to_h = to_tdc.index_by(&:stable_id)
|
to_h = to_coordinates.index_by(&:stable_id)
|
||||||
|
|
||||||
from_sids = from_h.keys
|
from_sids = from_h.keys
|
||||||
to_sids = to_h.keys
|
to_sids = to_h.keys
|
||||||
|
|
||||||
removed = (from_sids - to_sids).map do |sid|
|
removed = (from_sids - to_sids).map do |sid|
|
||||||
{ model: :type_de_champ, op: :remove, label: from_h[sid].libelle, private: from_h[sid].private?, position: from_sids.index(sid), stable_id: sid }
|
{ model: :type_de_champ, op: :remove, label: from_h[sid].libelle, private: from_h[sid].private?, _position: from_sids.index(sid), stable_id: sid }
|
||||||
end
|
end
|
||||||
|
|
||||||
added = (to_sids - from_sids).map do |sid|
|
added = (to_sids - from_sids).map do |sid|
|
||||||
{ model: :type_de_champ, op: :add, label: to_h[sid].libelle, private: to_h[sid].private?, position: to_sids.index(sid), stable_id: sid }
|
{ model: :type_de_champ, op: :add, label: to_h[sid].libelle, private: to_h[sid].private?, _position: to_sids.index(sid), stable_id: sid }
|
||||||
end
|
end
|
||||||
|
|
||||||
kept = from_sids.intersection(to_sids)
|
kept = from_sids.intersection(to_sids)
|
||||||
|
|
||||||
moved = kept
|
moved = kept
|
||||||
.map { |sid| [sid, from_sids.index(sid), to_sids.index(sid)] }
|
.map { |sid| [sid, from_h[sid], to_h[sid]] }
|
||||||
.filter { |_, from_index, to_index| from_index != to_index }
|
.filter { |_, from, to| from.position != to.position }
|
||||||
.map do |sid, from_index, to_index|
|
.map do |sid, from, to|
|
||||||
{ model: :type_de_champ, op: :move, label: from_h[sid].libelle, private: from_h[sid].private?, from: from_index, to: to_index, position: to_index, stable_id: sid }
|
{ model: :type_de_champ, op: :move, label: from.libelle, private: from.private?, from: from.position, to: to.position, _position: to_sids.index(sid), stable_id: sid }
|
||||||
end
|
end
|
||||||
|
|
||||||
changed = kept
|
changed = kept
|
||||||
.map { |sid| [sid, from_h[sid], to_h[sid]] }
|
.map { |sid| [sid, from_h[sid], to_h[sid]] }
|
||||||
.flat_map do |sid, from, to|
|
.flat_map do |sid, from, to|
|
||||||
compare_type_de_champ(from, to)
|
compare_type_de_champ(from.type_de_champ, to.type_de_champ)
|
||||||
.each { |h| h[:position] = to_sids.index(sid) }
|
.each { |h| h[:_position] = to_sids.index(sid) }
|
||||||
end
|
end
|
||||||
|
|
||||||
(removed + added + moved + changed)
|
(removed + added + moved + changed)
|
||||||
.sort_by { |h| h[:position] }
|
.sort_by { |h| h[:_position] }
|
||||||
.each { |h| h.delete(:position) }
|
.each { |h| h.delete(:_position) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -431,10 +430,6 @@ class ProcedureRevision < ApplicationRecord
|
||||||
stable_id: from_type_de_champ.stable_id
|
stable_id: from_type_de_champ.stable_id
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
elsif to_type_de_champ.repetition?
|
|
||||||
if from_type_de_champ.types_de_champ != to_type_de_champ.types_de_champ
|
|
||||||
changes += compare_types_de_champ(from_type_de_champ.types_de_champ, to_type_de_champ.types_de_champ)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
changes
|
changes
|
||||||
end
|
end
|
||||||
|
|
428
spec/models/dossier_rebase_concern_spec.rb
Normal file
428
spec/models/dossier_rebase_concern_spec.rb
Normal file
|
@ -0,0 +1,428 @@
|
||||||
|
describe Dossier do
|
||||||
|
describe '#can_rebase?' do
|
||||||
|
let(:procedure) { create(:procedure, :with_type_de_champ_mandatory, :with_yes_no, attestation_template: build(:attestation_template)) }
|
||||||
|
let(:attestation_template) { procedure.draft_revision.attestation_template.find_or_revise! }
|
||||||
|
let(:type_de_champ) { procedure.types_de_champ.find { |tdc| !tdc.mandatory? } }
|
||||||
|
let(:mandatory_type_de_champ) { procedure.types_de_champ.find(&:mandatory?) }
|
||||||
|
|
||||||
|
before { Flipper.enable(:procedure_revisions, procedure) }
|
||||||
|
|
||||||
|
context 'en_construction' do
|
||||||
|
let(:dossier) { create(:dossier, :en_construction, procedure: procedure) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
procedure.publish!
|
||||||
|
procedure.reload
|
||||||
|
dossier
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with added type de champ' do
|
||||||
|
before do
|
||||||
|
procedure.draft_revision.add_type_de_champ({
|
||||||
|
type_champ: TypeDeChamp.type_champs.fetch(:text),
|
||||||
|
libelle: "Un champ text"
|
||||||
|
})
|
||||||
|
procedure.publish_revision!
|
||||||
|
dossier.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should be false' do
|
||||||
|
expect(dossier.pending_changes).not_to be_empty
|
||||||
|
expect(dossier.can_rebase?).to be_falsey
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with type de champ made optional' do
|
||||||
|
before do
|
||||||
|
procedure.draft_revision.find_or_clone_type_de_champ(mandatory_type_de_champ.stable_id).update(mandatory: false)
|
||||||
|
procedure.publish_revision!
|
||||||
|
dossier.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should be true' do
|
||||||
|
expect(dossier.pending_changes).not_to be_empty
|
||||||
|
expect(dossier.can_rebase?).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with type de champ made mandatory' do
|
||||||
|
before do
|
||||||
|
procedure.draft_revision.find_or_clone_type_de_champ(type_de_champ.stable_id).update(mandatory: true)
|
||||||
|
procedure.publish_revision!
|
||||||
|
dossier.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should be false' do
|
||||||
|
expect(dossier.pending_changes).not_to be_empty
|
||||||
|
expect(dossier.can_rebase?).to be_falsey
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with removed type de champ' do
|
||||||
|
before do
|
||||||
|
procedure.draft_revision.remove_type_de_champ(type_de_champ.stable_id)
|
||||||
|
procedure.publish_revision!
|
||||||
|
dossier.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should be true' do
|
||||||
|
expect(dossier.pending_changes).not_to be_empty
|
||||||
|
expect(dossier.can_rebase?).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with attestation template changes' do
|
||||||
|
before do
|
||||||
|
attestation_template.update(title: "Test")
|
||||||
|
procedure.publish_revision!
|
||||||
|
dossier.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should be true' do
|
||||||
|
expect(dossier.pending_changes).not_to be_empty
|
||||||
|
expect(dossier.can_rebase?).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'en_instruction' do
|
||||||
|
let(:dossier) { create(:dossier, :en_instruction, procedure: procedure) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
procedure.publish!
|
||||||
|
procedure.reload
|
||||||
|
dossier
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with added type de champ' do
|
||||||
|
before do
|
||||||
|
procedure.draft_revision.add_type_de_champ({
|
||||||
|
type_champ: TypeDeChamp.type_champs.fetch(:text),
|
||||||
|
libelle: "Un champ text"
|
||||||
|
})
|
||||||
|
procedure.publish_revision!
|
||||||
|
dossier.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should be false' do
|
||||||
|
expect(dossier.pending_changes).not_to be_empty
|
||||||
|
expect(dossier.can_rebase?).to be_falsey
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with removed type de champ' do
|
||||||
|
before do
|
||||||
|
procedure.draft_revision.remove_type_de_champ(type_de_champ.stable_id)
|
||||||
|
procedure.publish_revision!
|
||||||
|
dossier.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should be false' do
|
||||||
|
expect(dossier.pending_changes).not_to be_empty
|
||||||
|
expect(dossier.can_rebase?).to be_falsey
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with attestation template changes' do
|
||||||
|
before do
|
||||||
|
attestation_template.update(title: "Test")
|
||||||
|
procedure.publish_revision!
|
||||||
|
dossier.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should be true' do
|
||||||
|
expect(dossier.pending_changes).not_to be_empty
|
||||||
|
expect(dossier.can_rebase?).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with type de champ made optional' do
|
||||||
|
before do
|
||||||
|
procedure.draft_revision.find_or_clone_type_de_champ(mandatory_type_de_champ.stable_id).update(mandatory: false)
|
||||||
|
procedure.publish_revision!
|
||||||
|
dossier.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should be false' do
|
||||||
|
expect(dossier.pending_changes).not_to be_empty
|
||||||
|
expect(dossier.can_rebase?).to be_falsey
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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) { procedure.active_revision.children_of(repetition_type_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')
|
||||||
|
# Add two rows then remove previous to last row in order to create a "hole" in the sequence
|
||||||
|
repetition_champ.add_row(repetition_champ.dossier.revision)
|
||||||
|
repetition_champ.add_row(repetition_champ.dossier.revision)
|
||||||
|
repetition_champ.champs.where(row: repetition_champ.champs.last.row - 1).destroy_all
|
||||||
|
repetition_champ.reload
|
||||||
|
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(2)
|
||||||
|
expect(repetition_champ.rows[0].size).to eq(1)
|
||||||
|
expect(repetition_champ.rows[1].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(2)
|
||||||
|
expect(rebased_repetition_champ.rows[0].size).to eq(2)
|
||||||
|
expect(rebased_repetition_champ.rows[1].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
|
||||||
|
|
||||||
|
context 'small grained' do
|
||||||
|
subject do
|
||||||
|
procedure.publish_revision!
|
||||||
|
perform_enqueued_jobs
|
||||||
|
|
||||||
|
dossier.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
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.publish!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
let!(:dossier) { create(:dossier, procedure: procedure) }
|
||||||
|
|
||||||
|
context 'when a dropdown option is changed' do
|
||||||
|
before do
|
||||||
|
dossier.champs.first.update(value: 'v1')
|
||||||
|
|
||||||
|
stable_id = procedure.draft_revision.types_de_champ.find_by(libelle: 'l1')
|
||||||
|
tdc_to_update = procedure.draft_revision.find_or_clone_type_de_champ(stable_id)
|
||||||
|
tdc_to_update.update(drop_down_list_value: 'option updated')
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to change { dossier.champs.first.value }.from('v1').to(nil) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a procedure with a carte tdc' do
|
||||||
|
let!(:procedure) do
|
||||||
|
create(:procedure).tap do |p|
|
||||||
|
champ = p.draft_revision.add_type_de_champ(type_champ: :carte, libelle: 'l1', cadastres: true)
|
||||||
|
p.publish!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
let!(:dossier) { create(:dossier, procedure: procedure) }
|
||||||
|
|
||||||
|
context 'and the cadastre are removed' do
|
||||||
|
before do
|
||||||
|
dossier.champs.first.update(value: 'v1', geo_areas: [create(:geo_area, :cadastre)])
|
||||||
|
|
||||||
|
stable_id = procedure.draft_revision.types_de_champ.find_by(libelle: 'l1')
|
||||||
|
tdc_to_update = procedure.draft_revision.find_or_clone_type_de_champ(stable_id)
|
||||||
|
tdc_to_update.update(cadastres: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to change { dossier.champs.first.cadastres.count }.from(1).to(0) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a procedure with 2 tdc' do
|
||||||
|
let!(:procedure) do
|
||||||
|
create(:procedure).tap do |p|
|
||||||
|
p.draft_revision.add_type_de_champ(type_champ: :text, libelle: 'l1')
|
||||||
|
p.draft_revision.add_type_de_champ(type_champ: :text, libelle: 'l2')
|
||||||
|
p.publish!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
let!(:dossier) { create(:dossier, procedure: procedure) }
|
||||||
|
|
||||||
|
def champ_libelles = dossier.champs.map(&:libelle)
|
||||||
|
|
||||||
|
context 'when a tdc is added in the middle' do
|
||||||
|
before do
|
||||||
|
added_tdc = procedure.draft_revision.add_type_de_champ(type_champ: :text, libelle: 'l3')
|
||||||
|
procedure.draft_revision.move_type_de_champ(added_tdc.stable_id, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to change { champ_libelles }.from(['l1', 'l2']).to(['l1', 'l3', 'l2']) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the first tdc is removed' do
|
||||||
|
before do
|
||||||
|
stable_id = procedure.draft_revision.types_de_champ.find_by(libelle: 'l1')
|
||||||
|
tdc_to_remove = procedure.draft_revision.find_or_clone_type_de_champ(stable_id)
|
||||||
|
procedure.draft_revision.remove_type_de_champ(tdc_to_remove.stable_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to change { champ_libelles }.from(['l1', 'l2']).to(['l2']) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the second tdc is moved at the first place' do
|
||||||
|
before do
|
||||||
|
stable_id = procedure.draft_revision.types_de_champ.find_by(libelle: 'l2')
|
||||||
|
procedure.draft_revision.move_type_de_champ(stable_id, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to change { champ_libelles }.from(['l1', 'l2']).to(['l2', 'l1']) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the first tdc libelle is updated' do
|
||||||
|
before do
|
||||||
|
stable_id = procedure.draft_revision.types_de_champ.find_by(libelle: 'l1')
|
||||||
|
tdc_to_update = procedure.draft_revision.find_or_clone_type_de_champ(stable_id)
|
||||||
|
tdc_to_update.update(libelle: 'l1 updated')
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to change { champ_libelles }.from(['l1', 'l2']).to(['l1 updated', 'l2']) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the first tdc type is updated' do
|
||||||
|
def first_champ = dossier.champs.first
|
||||||
|
|
||||||
|
before do
|
||||||
|
first_champ.update(value: 'v1', external_id: '123', geo_areas: [create(:geo_area)])
|
||||||
|
first_champ.update(data: { a: 1 })
|
||||||
|
|
||||||
|
first_champ.piece_justificative_file.attach(
|
||||||
|
io: StringIO.new("toto"),
|
||||||
|
filename: "toto.txt",
|
||||||
|
content_type: "text/plain",
|
||||||
|
# we don't want to run virus scanner on this file
|
||||||
|
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||||
|
)
|
||||||
|
|
||||||
|
first_champ.update_column('updated_at', Time.zone.parse('01/01/1901'))
|
||||||
|
|
||||||
|
stable_id = procedure.draft_revision.types_de_champ.find_by(libelle: 'l1')
|
||||||
|
tdc_to_update = procedure.draft_revision.find_or_clone_type_de_champ(stable_id)
|
||||||
|
tdc_to_update.update(type_champ: :integer_number)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to change { dossier.champs.map(&:type_champ) }.from(['text', 'text']).to(['integer_number', 'text']) }
|
||||||
|
it { expect { subject }.to change { first_champ.class }.from(Champs::TextChamp).to(Champs::IntegerNumberChamp) }
|
||||||
|
it { expect { subject }.to change { first_champ.value }.from('v1').to(nil) }
|
||||||
|
it { expect { subject }.to change { first_champ.external_id }.from('123').to(nil) }
|
||||||
|
it { expect { subject }.to change { first_champ.data }.from({ 'a' => 1 }).to(nil) }
|
||||||
|
it { expect { subject }.to change { first_champ.geo_areas.count }.from(1).to(0) }
|
||||||
|
it { expect { subject }.to change { first_champ.piece_justificative_file.attached? }.from(true).to(false) }
|
||||||
|
# pb with pj.purge_later
|
||||||
|
xit { expect { subject }.not_to change { first_champ.updated_at }.from(Time.zone.parse('01/01/1901')) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a procedure with a repetition' do
|
||||||
|
let!(:procedure) do
|
||||||
|
create(:procedure).tap do |p|
|
||||||
|
repetition = p.draft_revision.add_type_de_champ(type_champ: :repetition, libelle: 'p1')
|
||||||
|
p.draft_revision.add_type_de_champ(type_champ: :text, libelle: 'c1', parent_id: repetition.stable_id)
|
||||||
|
p.draft_revision.add_type_de_champ(type_champ: :text, libelle: 'c2', parent_id: repetition.stable_id)
|
||||||
|
p.publish!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
let!(:dossier) { create(:dossier, procedure: procedure) }
|
||||||
|
let(:repetition_stable_id) { procedure.draft_revision.types_de_champ.find(&:repetition?) }
|
||||||
|
|
||||||
|
def child_libelles = dossier.champs[0].champs.map(&:libelle)
|
||||||
|
|
||||||
|
context 'when a child tdc is added in the middle' do
|
||||||
|
before do
|
||||||
|
added_tdc = procedure.draft_revision.add_type_de_champ(type_champ: :text, libelle: 'c3', parent_id: repetition_stable_id)
|
||||||
|
procedure.draft_revision.move_type_de_champ(added_tdc.stable_id, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to change { child_libelles }.from(['c1', 'c2']).to(['c1', 'c3', 'c2']) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the first child tdc is removed' do
|
||||||
|
before do
|
||||||
|
tdc_to_remove = procedure.draft_revision.types_de_champ.find_by(libelle: 'c1')
|
||||||
|
procedure.draft_revision.remove_type_de_champ(tdc_to_remove.stable_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to change { child_libelles }.from(['c1', 'c2']).to(['c2']) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the first child libelle tdc is updated' do
|
||||||
|
before do
|
||||||
|
stable_id = procedure.draft_revision.types_de_champ.find_by(libelle: 'c1')
|
||||||
|
tdc_to_update = procedure.draft_revision.find_or_clone_type_de_champ(stable_id)
|
||||||
|
tdc_to_update.update(libelle: 'c1 updated')
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to change { child_libelles }.from(['c1', 'c2']).to(['c1 updated', 'c2']) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the first child tdc type is updated' do
|
||||||
|
before do
|
||||||
|
stable_id = procedure.draft_revision.types_de_champ.find_by(libelle: 'c1')
|
||||||
|
tdc_to_update = procedure.draft_revision.find_or_clone_type_de_champ(stable_id)
|
||||||
|
tdc_to_update.update(type_champ: :integer_number)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to change { dossier.champs[0].champs.map(&:type_champ) }.from(['text', 'text']).to(['integer_number', 'text']) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the parents type is changed' do
|
||||||
|
before do
|
||||||
|
stable_id = procedure.draft_revision.types_de_champ.find_by(libelle: 'p1')
|
||||||
|
parent = procedure.draft_revision.find_or_clone_type_de_champ(stable_id)
|
||||||
|
parent.update(type_champ: :integer_number)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to change { dossier.champs[0].champs.count }.from(2).to(0) }
|
||||||
|
it { expect { subject }.to change { Champ.count }.from(3).to(1) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1575,232 +1575,6 @@ describe Dossier do
|
||||||
it { expect(dossier.spreadsheet_columns(types_de_champ: [])).to include(["État du dossier", "Brouillon"]) }
|
it { expect(dossier.spreadsheet_columns(types_de_champ: [])).to include(["État du dossier", "Brouillon"]) }
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#can_rebase?' do
|
|
||||||
let(:procedure) { create(:procedure, :with_type_de_champ_mandatory, :with_yes_no, attestation_template: build(:attestation_template)) }
|
|
||||||
let(:attestation_template) { procedure.draft_revision.attestation_template.find_or_revise! }
|
|
||||||
let(:type_de_champ) { procedure.types_de_champ.find { |tdc| !tdc.mandatory? } }
|
|
||||||
let(:mandatory_type_de_champ) { procedure.types_de_champ.find(&:mandatory?) }
|
|
||||||
|
|
||||||
before { Flipper.enable(:procedure_revisions, procedure) }
|
|
||||||
|
|
||||||
context 'en_construction' do
|
|
||||||
let(:dossier) { create(:dossier, :en_construction, procedure: procedure) }
|
|
||||||
|
|
||||||
before do
|
|
||||||
procedure.publish!
|
|
||||||
procedure.reload
|
|
||||||
dossier
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with added type de champ' do
|
|
||||||
before do
|
|
||||||
procedure.draft_revision.add_type_de_champ({
|
|
||||||
type_champ: TypeDeChamp.type_champs.fetch(:text),
|
|
||||||
libelle: "Un champ text"
|
|
||||||
})
|
|
||||||
procedure.publish_revision!
|
|
||||||
dossier.reload
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should be false' do
|
|
||||||
expect(dossier.pending_changes).not_to be_empty
|
|
||||||
expect(dossier.can_rebase?).to be_falsey
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with type de champ made optional' do
|
|
||||||
before do
|
|
||||||
procedure.draft_revision.find_or_clone_type_de_champ(mandatory_type_de_champ.stable_id).update(mandatory: false)
|
|
||||||
procedure.publish_revision!
|
|
||||||
dossier.reload
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should be true' do
|
|
||||||
expect(dossier.pending_changes).not_to be_empty
|
|
||||||
expect(dossier.can_rebase?).to be_truthy
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with type de champ made mandatory' do
|
|
||||||
before do
|
|
||||||
procedure.draft_revision.find_or_clone_type_de_champ(type_de_champ.stable_id).update(mandatory: true)
|
|
||||||
procedure.publish_revision!
|
|
||||||
dossier.reload
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should be false' do
|
|
||||||
expect(dossier.pending_changes).not_to be_empty
|
|
||||||
expect(dossier.can_rebase?).to be_falsey
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with removed type de champ' do
|
|
||||||
before do
|
|
||||||
procedure.draft_revision.remove_type_de_champ(type_de_champ.stable_id)
|
|
||||||
procedure.publish_revision!
|
|
||||||
dossier.reload
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should be true' do
|
|
||||||
expect(dossier.pending_changes).not_to be_empty
|
|
||||||
expect(dossier.can_rebase?).to be_truthy
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with attestation template changes' do
|
|
||||||
before do
|
|
||||||
attestation_template.update(title: "Test")
|
|
||||||
procedure.publish_revision!
|
|
||||||
dossier.reload
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should be true' do
|
|
||||||
expect(dossier.pending_changes).not_to be_empty
|
|
||||||
expect(dossier.can_rebase?).to be_truthy
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'en_instruction' do
|
|
||||||
let(:dossier) { create(:dossier, :en_instruction, procedure: procedure) }
|
|
||||||
|
|
||||||
before do
|
|
||||||
procedure.publish!
|
|
||||||
procedure.reload
|
|
||||||
dossier
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with added type de champ' do
|
|
||||||
before do
|
|
||||||
procedure.draft_revision.add_type_de_champ({
|
|
||||||
type_champ: TypeDeChamp.type_champs.fetch(:text),
|
|
||||||
libelle: "Un champ text"
|
|
||||||
})
|
|
||||||
procedure.publish_revision!
|
|
||||||
dossier.reload
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should be false' do
|
|
||||||
expect(dossier.pending_changes).not_to be_empty
|
|
||||||
expect(dossier.can_rebase?).to be_falsey
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with removed type de champ' do
|
|
||||||
before do
|
|
||||||
procedure.draft_revision.remove_type_de_champ(type_de_champ.stable_id)
|
|
||||||
procedure.publish_revision!
|
|
||||||
dossier.reload
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should be false' do
|
|
||||||
expect(dossier.pending_changes).not_to be_empty
|
|
||||||
expect(dossier.can_rebase?).to be_falsey
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with attestation template changes' do
|
|
||||||
before do
|
|
||||||
attestation_template.update(title: "Test")
|
|
||||||
procedure.publish_revision!
|
|
||||||
dossier.reload
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should be true' do
|
|
||||||
expect(dossier.pending_changes).not_to be_empty
|
|
||||||
expect(dossier.can_rebase?).to be_truthy
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with type de champ made optional' do
|
|
||||||
before do
|
|
||||||
procedure.draft_revision.find_or_clone_type_de_champ(mandatory_type_de_champ.stable_id).update(mandatory: false)
|
|
||||||
procedure.publish_revision!
|
|
||||||
dossier.reload
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should be false' do
|
|
||||||
expect(dossier.pending_changes).not_to be_empty
|
|
||||||
expect(dossier.can_rebase?).to be_falsey
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
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) { procedure.active_revision.children_of(repetition_type_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')
|
|
||||||
# Add two rows then remove previous to last row in order to create a "hole" in the sequence
|
|
||||||
repetition_champ.add_row(repetition_champ.dossier.revision)
|
|
||||||
repetition_champ.add_row(repetition_champ.dossier.revision)
|
|
||||||
repetition_champ.champs.where(row: repetition_champ.champs.last.row - 1).destroy_all
|
|
||||||
repetition_champ.reload
|
|
||||||
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(2)
|
|
||||||
expect(repetition_champ.rows[0].size).to eq(1)
|
|
||||||
expect(repetition_champ.rows[1].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(2)
|
|
||||||
expect(rebased_repetition_champ.rows[0].size).to eq(2)
|
|
||||||
expect(rebased_repetition_champ.rows[1].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
|
|
||||||
|
|
||||||
describe '#processed_in_month' do
|
describe '#processed_in_month' do
|
||||||
include ActiveSupport::Testing::TimeHelpers
|
include ActiveSupport::Testing::TimeHelpers
|
||||||
|
|
||||||
|
|
|
@ -300,7 +300,7 @@ describe ProcedureRevision do
|
||||||
let(:first_tdc) { draft.types_de_champ_public.first }
|
let(:first_tdc) { draft.types_de_champ_public.first }
|
||||||
let(:new_draft) { procedure.create_new_revision }
|
let(:new_draft) { procedure.create_new_revision }
|
||||||
|
|
||||||
subject { procedure.active_revision.compare(new_draft) }
|
subject { procedure.active_revision.compare(new_draft.reload) }
|
||||||
|
|
||||||
context 'when a type de champ is added' do
|
context 'when a type de champ is added' do
|
||||||
let(:procedure) { create(:procedure) }
|
let(:procedure) { create(:procedure) }
|
||||||
|
|
Loading…
Add table
Reference in a new issue