|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +class ReinstateRemovedParentRelationships < ActiveRecord::Migration[8.1] |
| 4 | + def up |
| 5 | + destroyed_audits = |
| 6 | + Audited::Audit.where( |
| 7 | + auditable_type: "ParentRelationship", |
| 8 | + action: "destroy" |
| 9 | + ).where("created_at > ?", Date.new(2026, 2, 19)) |
| 10 | + |
| 11 | + reinstated = 0 |
| 12 | + |
| 13 | + destroyed_audits.in_batches(of: 1000) do |batch| |
| 14 | + batch.each do |audit| |
| 15 | + changes = audit.audited_changes |
| 16 | + patient_id = changes["patient_id"] |
| 17 | + parent_id = changes["parent_id"] |
| 18 | + |
| 19 | + next unless Patient.exists?(patient_id) |
| 20 | + next unless Parent.exists?(parent_id) |
| 21 | + |
| 22 | + # Only reinstate relationships that were removed as part of discarding |
| 23 | + # an import duplicate — identified by a pending_changes clear on the |
| 24 | + # same patient within the same minute. |
| 25 | + contemporaneous_discard = |
| 26 | + Audited::Audit |
| 27 | + .where( |
| 28 | + auditable_type: "Patient", |
| 29 | + auditable_id: patient_id, |
| 30 | + action: "update", |
| 31 | + created_at: |
| 32 | + (audit.created_at - 1.minute)..(audit.created_at + 1.minute) |
| 33 | + ) |
| 34 | + .any? do |patient_audit| |
| 35 | + patient_audit.audited_changes.key?("pending_changes") && |
| 36 | + patient_audit.audited_changes["pending_changes"].second == {} |
| 37 | + end |
| 38 | + |
| 39 | + next unless contemporaneous_discard |
| 40 | + |
| 41 | + ParentRelationship.find_or_create_by!(patient_id:, parent_id:) do |pr| |
| 42 | + pr.type = changes["type"] |
| 43 | + pr.other_name = changes["other_name"] |
| 44 | + end |
| 45 | + |
| 46 | + reinstated += 1 |
| 47 | + end |
| 48 | + end |
| 49 | + |
| 50 | + say "Reinstated #{reinstated} parent relationship(s)" |
| 51 | + end |
| 52 | + |
| 53 | + def down |
| 54 | + raise ActiveRecord::IrreversibleMigration |
| 55 | + end |
| 56 | +end |
0 commit comments