# some race condition (regarding double submit of dossier.passer_en_construction!) might remove champs # until now we haven't decided to push a stronger fix than an UI change # so we might have to recreate some deleted champs and notify administration class DataFixer::DossierChampsMissing def fix fixed_on_origin = apply_fix(@original_dossier) fixed_on_other = Dossier.where(editing_fork_origin_id: @original_dossier.id) .map(&method(:apply_fix)) [fixed_on_origin, fixed_on_other.sum].sum end private attr_reader :original_dossier def initialize(dossier:) @original_dossier = dossier end def apply_fix(dossier) added_champs_root = fix_champs_root(dossier) added_champs_in_repetition = fix_champs_in_repetition(dossier) added_champs = added_champs_root + added_champs_in_repetition if !added_champs.empty? dossier.save! log_champs_added(dossier, added_champs) added_champs.size else 0 end end def fix_champs_root(dossier) champs_root, _ = dossier.champs.partition { _1.parent_id.blank? } expected_tdcs = dossier.revision.revision_types_de_champ.filter { _1.parent.blank? }.map(&:type_de_champ) expected_tdcs.filter { !champs_root.map(&:stable_id).include?(_1.stable_id) } .map do |missing_tdc| champ_root_missing = missing_tdc.build_champ dossier.champs_public << champ_root_missing champ_root_missing end end def fix_champs_in_repetition(dossier) champs_repetition, _ = dossier.champs.partition(&:repetition?) champs_repetition.flat_map do |champ_repetition| champ_repetition_missing = champ_repetition.rows.flat_map do |row| row_id = row.first.row_id expected_tdcs = dossier.revision.children_of(champ_repetition.type_de_champ) row_tdcs = row.map(&:type_de_champ) (expected_tdcs - row_tdcs).map do |missing_tdc| champ_repetition_missing = missing_tdc.build_champ(row_id: row_id) champ_repetition.champs << champ_repetition_missing champ_repetition_missing end end end end def log_champs_added(dossier, added_champs) app_traces = caller.reject { _1.match?(%r{/ruby/.+/gems/}) }.map { _1.sub(Rails.root.to_s, "") } payload = { message: "DataFixer::DossierChampsMissing", dossier_id: dossier.id, champs_ids: added_champs.map(&:id).join(","), caller: app_traces } logger = Lograge.logger || Rails.logger logger.info payload.to_json end end