2024-04-29 00:17:15 +02:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2021-10-13 14:41:05 +02:00
|
|
|
module DossierRebaseConcern
|
|
|
|
extend ActiveSupport::Concern
|
|
|
|
|
2023-05-12 17:53:40 +02:00
|
|
|
def rebase!(force: false)
|
2024-01-31 16:38:58 +01:00
|
|
|
ProcedureRevisionPreloader.new([procedure.published_revision, revision].compact).all
|
2023-05-22 13:50:58 +02:00
|
|
|
return if procedure.published_revision.blank?
|
|
|
|
|
2023-05-12 17:53:40 +02:00
|
|
|
if force || can_rebase?
|
2021-10-13 14:41:05 +02:00
|
|
|
transaction do
|
|
|
|
rebase
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-12-14 09:17:09 +01:00
|
|
|
def rebase_later
|
|
|
|
DossierRebaseJob.perform_later(self)
|
|
|
|
end
|
|
|
|
|
2022-02-11 18:23:46 +01:00
|
|
|
def can_rebase?
|
2023-02-01 17:33:23 +01:00
|
|
|
procedure.published_revision.present? && revision != procedure.published_revision &&
|
2022-02-11 18:23:46 +01:00
|
|
|
(brouillon? || accepted_en_construction_changes? || accepted_en_instruction_changes?)
|
|
|
|
end
|
|
|
|
|
|
|
|
def pending_changes
|
2024-06-05 17:30:33 +02:00
|
|
|
procedure.published_revision.present? ? revision.compare_types_de_champ(procedure.published_revision) : []
|
2022-02-11 18:23:46 +01:00
|
|
|
end
|
|
|
|
|
2022-12-23 13:01:18 +01:00
|
|
|
def can_rebase_mandatory_change?(stable_id)
|
|
|
|
!champs.filter { _1.stable_id == stable_id }.any?(&:blank?)
|
|
|
|
end
|
|
|
|
|
2023-01-06 12:57:15 +01:00
|
|
|
def can_rebase_drop_down_options_change?(stable_id, options)
|
|
|
|
!champs.filter { _1.stable_id == stable_id }.any? { _1.in?(options) }
|
|
|
|
end
|
|
|
|
|
2021-10-13 14:41:05 +02:00
|
|
|
private
|
|
|
|
|
2022-02-11 18:23:46 +01:00
|
|
|
def accepted_en_construction_changes?
|
2022-12-23 13:01:18 +01:00
|
|
|
en_construction? && pending_changes.all? { _1.can_rebase?(self) }
|
2022-02-11 18:23:46 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def accepted_en_instruction_changes?
|
2022-12-23 13:01:18 +01:00
|
|
|
en_instruction? && pending_changes.all? { _1.can_rebase?(self) }
|
2022-02-11 18:23:46 +01:00
|
|
|
end
|
|
|
|
|
2021-10-13 14:41:05 +02:00
|
|
|
def rebase
|
2022-05-18 15:47:52 +02:00
|
|
|
# revision we are rebasing to
|
|
|
|
target_revision = procedure.published_revision
|
|
|
|
|
2022-05-20 11:56:09 +02:00
|
|
|
# index published types de champ coordinates by stable_id
|
2022-05-20 14:20:26 +02:00
|
|
|
target_coordinates_by_stable_id = target_revision
|
2022-05-18 15:47:52 +02:00
|
|
|
.revision_types_de_champ
|
2024-07-01 15:31:32 +02:00
|
|
|
.includes(:parent)
|
2022-05-18 15:47:52 +02:00
|
|
|
.index_by(&:stable_id)
|
|
|
|
|
2022-05-23 11:23:14 +02:00
|
|
|
changes_by_op = pending_changes
|
2022-12-23 13:01:18 +01:00
|
|
|
.group_by(&:op)
|
|
|
|
.tap { _1.default = [] }
|
2021-10-13 14:41:05 +02:00
|
|
|
|
2023-01-30 11:30:50 +01:00
|
|
|
champs_by_stable_id = champs
|
|
|
|
.group_by(&:stable_id)
|
|
|
|
.transform_values { Champ.where(id: _1) }
|
2023-02-02 09:59:03 +01:00
|
|
|
.tap { _1.default = Champ.none }
|
2023-01-30 11:30:50 +01:00
|
|
|
|
2022-05-23 11:23:14 +02:00
|
|
|
# remove champ
|
2024-03-08 15:55:50 +01:00
|
|
|
children_champ, root_champ = changes_by_op[:remove].partition(&:child?)
|
2024-03-12 11:36:30 +01:00
|
|
|
children_champ.each { champs_by_stable_id[_1.stable_id].destroy_all }
|
|
|
|
root_champ.each { champs_by_stable_id[_1.stable_id].destroy_all }
|
2022-05-18 15:47:52 +02:00
|
|
|
|
2023-02-02 09:59:03 +01:00
|
|
|
# update champ
|
2023-03-22 11:42:58 +01:00
|
|
|
changes_by_op[:update].each { apply(_1, champs_by_stable_id[_1.stable_id]) }
|
2022-05-23 11:23:14 +02:00
|
|
|
|
2022-05-18 15:47:52 +02:00
|
|
|
# update dossier revision
|
2023-01-30 11:30:50 +01:00
|
|
|
update_column(:revision_id, target_revision.id)
|
2024-07-25 18:29:01 +02:00
|
|
|
|
|
|
|
# add champ (after changing dossier revision to avoid errors)
|
|
|
|
changes_by_op[:add]
|
|
|
|
.map { target_coordinates_by_stable_id[_1.stable_id] }
|
|
|
|
# add parent champs first so we can then add children
|
|
|
|
.sort_by { _1.child? ? 1 : 0 }
|
|
|
|
.each { add_new_champs_for_revision(_1) }
|
2022-05-23 11:23:14 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
def apply(change, champs)
|
2022-12-23 13:01:18 +01:00
|
|
|
case change.attribute
|
2022-05-23 11:23:14 +02:00
|
|
|
when :type_champ
|
2022-12-23 13:01:18 +01:00
|
|
|
champs.each { purge_piece_justificative_file(_1) }
|
2022-05-23 11:23:14 +02:00
|
|
|
GeoArea.where(champ: champs).destroy_all
|
2022-12-14 09:17:09 +01:00
|
|
|
Etablissement.where(champ: champs).destroy_all
|
2023-01-06 12:57:15 +01:00
|
|
|
champs.update_all(type: "Champs::#{change.to.classify}Champ",
|
2022-05-23 11:23:14 +02:00
|
|
|
value: nil,
|
2022-12-14 09:17:09 +01:00
|
|
|
value_json: nil,
|
2022-05-23 11:23:14 +02:00
|
|
|
external_id: nil,
|
2023-01-26 17:58:41 +01:00
|
|
|
data: nil,
|
|
|
|
rebased_at: Time.zone.now)
|
2022-05-23 11:23:14 +02:00
|
|
|
when :drop_down_options
|
2023-01-06 12:57:15 +01:00
|
|
|
# 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) }
|
2023-01-26 17:58:41 +01:00
|
|
|
champs.filter { _1.in?(removed_options) }.each do
|
|
|
|
_1.remove_option(removed_options)
|
|
|
|
_1.update_column(:rebased_at, Time.zone.now)
|
|
|
|
end
|
2023-01-06 12:57:15 +01:00
|
|
|
end
|
2022-05-23 11:23:14 +02:00
|
|
|
when :carte_layers
|
|
|
|
# if we are removing cadastres layer, we need to remove cadastre geo areas
|
2022-12-23 13:01:18 +01:00
|
|
|
if change.from.include?(:cadastres) && !change.to.include?(:cadastres)
|
2023-01-26 17:58:41 +01:00
|
|
|
champs.filter { _1.cadastres.present? }.each do
|
|
|
|
_1.cadastres.each(&:destroy)
|
|
|
|
_1.update_column(:rebased_at, Time.zone.now)
|
|
|
|
end
|
2022-05-23 11:23:14 +02:00
|
|
|
end
|
2023-01-26 17:58:41 +01:00
|
|
|
else
|
|
|
|
champs.update_all(rebased_at: Time.zone.now)
|
2022-05-23 11:23:14 +02:00
|
|
|
end
|
2021-10-13 14:41:05 +02:00
|
|
|
end
|
|
|
|
|
2022-05-23 11:23:14 +02:00
|
|
|
def add_new_champs_for_revision(target_coordinate)
|
|
|
|
if target_coordinate.child?
|
2022-05-18 15:47:52 +02:00
|
|
|
# If this type de champ is a child, we create a new champ for each row of the parent
|
2022-05-23 11:23:14 +02:00
|
|
|
parent_stable_id = target_coordinate.parent.stable_id
|
2022-05-18 15:47:52 +02:00
|
|
|
|
2023-01-31 12:32:11 +01:00
|
|
|
champs.filter { _1.stable_id == parent_stable_id }.each do |champ_repetition|
|
2023-02-02 09:59:03 +01:00
|
|
|
if champ_repetition.champs.present?
|
2023-01-31 12:32:11 +01:00
|
|
|
champ_repetition.champs.map(&:row_id).uniq.each do |row_id|
|
2023-06-23 00:29:30 +02:00
|
|
|
champs << create_champ(target_coordinate, champ_repetition, row_id:)
|
2023-01-31 12:32:11 +01:00
|
|
|
end
|
2024-07-01 15:31:32 +02:00
|
|
|
elsif target_coordinate.parent.mandatory?
|
2023-06-23 00:29:30 +02:00
|
|
|
champs << create_champ(target_coordinate, champ_repetition, row_id: ULID.generate)
|
2021-10-13 14:41:05 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
2022-05-23 11:23:14 +02:00
|
|
|
create_champ(target_coordinate, self)
|
2021-10-13 14:41:05 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-12-16 15:07:26 +01:00
|
|
|
def create_champ(target_coordinate, parent, row_id: nil)
|
2023-06-23 00:29:30 +02:00
|
|
|
target_coordinate
|
2022-05-18 15:47:52 +02:00
|
|
|
.type_de_champ
|
2023-02-02 09:59:03 +01:00
|
|
|
.build_champ(rebased_at: Time.zone.now, row_id:)
|
2023-06-23 00:29:30 +02:00
|
|
|
.tap { parent.champs << _1 }
|
2022-05-18 15:47:52 +02:00
|
|
|
end
|
2021-10-13 14:41:05 +02:00
|
|
|
|
2022-12-14 09:17:09 +01:00
|
|
|
def purge_piece_justificative_file(champ)
|
|
|
|
ActiveStorage::Attachment.where(id: champ.piece_justificative_file.ids).delete_all
|
|
|
|
end
|
2021-10-13 14:41:05 +02:00
|
|
|
end
|