Restoring the predecessor's information, or the work package's information, depending on where the journal version is at.pull/11179/head
parent
4d827dfb04
commit
751468e15e
@ -0,0 +1,107 @@ |
|||||||
|
class FixDeletedDataJournals < ActiveRecord::Migration[7.0] |
||||||
|
def up |
||||||
|
get_missing_journals.each do |journable_type, relation| |
||||||
|
puts "Cleaning up journals on #{journable_type}" |
||||||
|
|
||||||
|
relation.find_each { |journal| fix_journal_data(journal) } |
||||||
|
|
||||||
|
count = relation.count |
||||||
|
raise "There shouldn't be any missing data left for #{journable_type}, but found #{count}" if count > 0 |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def down |
||||||
|
# nothing to do |
||||||
|
end |
||||||
|
|
||||||
|
def fix_journal_data(journal) |
||||||
|
# Best case, no successor |
||||||
|
# restore data from work package itself |
||||||
|
if journal.successor.nil? |
||||||
|
raise "Previous also has data nil" if (journal.previous && journal.previous.data.nil?) |
||||||
|
insert_journal_data(journal, journal.previous, write_message: false) |
||||||
|
elsif predecessor = journal.previous |
||||||
|
# Case 2, we do have a predecessor |
||||||
|
take_over_from_predecessor(journal, predecessor) |
||||||
|
elsif journal.successor |
||||||
|
# Case 3, We are the first, but have a successor |
||||||
|
# Look for data in the successor |
||||||
|
take_over_from_successor(journal, journal.successor) |
||||||
|
else |
||||||
|
raise "This should not happen for #{journal.inspect}" |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def insert_journal_data(journal, predecessor, write_message: false) |
||||||
|
service = Journals::CreateService.new(journal.journable, User.system) |
||||||
|
insert_sql = service.instance_eval { insert_data_sql('placeholder', predecessor) } |
||||||
|
|
||||||
|
result = Journal.connection.uncached do |
||||||
|
::Journal |
||||||
|
.connection |
||||||
|
.select_one(insert_sql) |
||||||
|
|
||||||
|
end |
||||||
|
|
||||||
|
raise "ID is missing #{result.inspect}" unless result['id'] |
||||||
|
|
||||||
|
if write_message |
||||||
|
update_with_new_data!(journal, result['id']) |
||||||
|
else |
||||||
|
journal.update_column(:data_id, result['id']) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def get_missing_journals |
||||||
|
Journal |
||||||
|
.pluck('DISTINCT(journable_type)') |
||||||
|
.to_h do |journable_type| |
||||||
|
journable_type = 'WorkPackage' |
||||||
|
journal_class = journable_type.constantize.journal_class |
||||||
|
table_name = journal_class.table_name |
||||||
|
|
||||||
|
relation = Journal |
||||||
|
.joins("LEFT OUTER JOIN #{table_name} ON journals.data_type = '#{journal_class.to_s}' AND #{table_name}.id = journals.data_id") |
||||||
|
.where("#{table_name}.id IS NULL") |
||||||
|
.where(journable_type: journable_type) |
||||||
|
.where.not(data_type: nil) # Ignore special tenants with data_type nil errors |
||||||
|
.order('journals.version ASC') |
||||||
|
.includes(:journable) |
||||||
|
|
||||||
|
[journable_type, relation] |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def take_over_from_predecessor(journal, predecessor) |
||||||
|
raise "Related journal does not have data, this shouldn't be!" if predecessor.data.nil? |
||||||
|
new_data = predecessor.data.dup |
||||||
|
new_data.save! |
||||||
|
|
||||||
|
update_with_new_data!(journal, new_data.id) |
||||||
|
end |
||||||
|
|
||||||
|
def take_over_from_successor(journal, successor) |
||||||
|
# The successor itself may also have its data deleted. |
||||||
|
# in this case, look for the first journal with data, or insert |
||||||
|
new_data = |
||||||
|
if successor.data.nil? |
||||||
|
first_journal_with_data = journal.journable.journals.detect { |j| j.data.present? } |
||||||
|
return insert_journal_data(journal, journal.previous, write_message: true) if first_journal_with_data.nil? |
||||||
|
|
||||||
|
first_journal_with_data.data.dup |
||||||
|
else |
||||||
|
successor.data.dup |
||||||
|
end |
||||||
|
|
||||||
|
new_data.save! |
||||||
|
update_with_new_data!(journal, new_data.id) |
||||||
|
end |
||||||
|
|
||||||
|
def update_with_new_data!(journal, data_id) |
||||||
|
notes = journal.notes |
||||||
|
notes << "\n" unless notes.empty? |
||||||
|
notes << "_(This activity had to be modified by the system and may be missing some changes or contain changes from previous or following activities.)_" |
||||||
|
|
||||||
|
journal.update_columns(notes:, data_id: data_id) |
||||||
|
end |
||||||
|
end |
Loading…
Reference in new issue