107 lines
3 KiB
Ruby
107 lines
3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module DossierRebaseConcern
|
|
extend ActiveSupport::Concern
|
|
|
|
def rebase!(force: false)
|
|
ProcedureRevisionPreloader.new([procedure.published_revision, revision].compact).all
|
|
return if procedure.published_revision.blank?
|
|
|
|
if force || can_rebase?
|
|
transaction do
|
|
rebase
|
|
end
|
|
end
|
|
end
|
|
|
|
def rebase_later
|
|
DossierRebaseJob.perform_later(self)
|
|
end
|
|
|
|
def can_rebase?
|
|
procedure.published_revision.present? && revision != procedure.published_revision &&
|
|
(brouillon? || accepted_en_construction_changes? || accepted_en_instruction_changes?)
|
|
end
|
|
|
|
def pending_changes
|
|
procedure.published_revision.present? ? revision.compare_types_de_champ(procedure.published_revision) : []
|
|
end
|
|
|
|
def can_rebase_mandatory_change?(stable_id)
|
|
!champs.filter { _1.stable_id == stable_id }.any?(&:blank?)
|
|
end
|
|
|
|
def can_rebase_drop_down_options_change?(stable_id, options)
|
|
!champs.filter { _1.stable_id == stable_id }.any? { _1.in?(options) }
|
|
end
|
|
|
|
private
|
|
|
|
def accepted_en_construction_changes?
|
|
en_construction? && pending_changes.all? { _1.can_rebase?(self) }
|
|
end
|
|
|
|
def accepted_en_instruction_changes?
|
|
en_instruction? && pending_changes.all? { _1.can_rebase?(self) }
|
|
end
|
|
|
|
def rebase
|
|
# revision we are rebasing to
|
|
target_revision = procedure.published_revision
|
|
|
|
# index published types de champ coordinates by stable_id
|
|
target_coordinates_by_stable_id = target_revision
|
|
.revision_types_de_champ
|
|
.includes(:parent)
|
|
.index_by(&:stable_id)
|
|
|
|
changes_by_op = pending_changes
|
|
.group_by(&:op)
|
|
.tap { _1.default = [] }
|
|
|
|
champs_by_stable_id = champs
|
|
.group_by(&:stable_id)
|
|
.transform_values { Champ.where(id: _1) }
|
|
.tap { _1.default = Champ.none }
|
|
|
|
# remove champ
|
|
changes_by_op[:remove].each { champs_by_stable_id[_1.stable_id].destroy_all }
|
|
|
|
# update champ
|
|
changes_by_op[:update].each { champs_by_stable_id[_1.stable_id].update_all(rebased_at: Time.zone.now) }
|
|
|
|
# update dossier revision
|
|
update_column(:revision_id, target_revision.id)
|
|
|
|
# add champ (after changing dossier revision to avoid errors)
|
|
changes_by_op[:add]
|
|
.map { target_coordinates_by_stable_id[_1.stable_id] }
|
|
.each { add_new_champs_for_revision(_1) }
|
|
end
|
|
|
|
def add_new_champs_for_revision(target_coordinate)
|
|
if target_coordinate.child?
|
|
row_ids = repetition_row_ids(target_coordinate.parent.type_de_champ)
|
|
|
|
if row_ids.present?
|
|
row_ids.each do |row_id|
|
|
create_champ(target_coordinate, row_id:)
|
|
end
|
|
elsif target_coordinate.parent.mandatory?
|
|
create_champ(target_coordinate, row_id: ULID.generate)
|
|
end
|
|
else
|
|
create_champ(target_coordinate)
|
|
end
|
|
end
|
|
|
|
def create_champ(target_coordinate, row_id: nil)
|
|
self.champs << target_coordinate
|
|
.type_de_champ
|
|
.build_champ(rebased_at: Time.zone.now, row_id:)
|
|
end
|
|
|
|
def purge_piece_justificative_file(champ)
|
|
ActiveStorage::Attachment.where(id: champ.piece_justificative_file.ids).delete_all
|
|
end
|
|
end
|