demarches-normaliennes/app/models/concerns/dossier_rebase_concern.rb
2021-10-28 13:27:53 +02:00

121 lines
3.7 KiB
Ruby

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.champs.map(&:row).uniq.each 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