From b81f7e12a828791ee47e0ed4537d4cfa72fb3959 Mon Sep 17 00:00:00 2001 From: John Henderson Date: Tue, 21 Apr 2026 10:24:05 +0100 Subject: [PATCH] Fix missing child activity log entries when parent relationships are removed This change fixes a gap in audit visibility when parent-child relationships are removed from a child record. Previously, removing a parent relationship through either the direct child record flow or the bulk import cleanup flow deleted the relationship successfully, but did not surface a meaningful activity log entry on the child record. Jira-Issue: MAV-2789 --- app/components/app_activity_log_component.rb | 22 +++++++++++++ .../bulk_remove_parent_relationships_job.rb | 5 ++- app/models/parent_relationship.rb | 8 +++++ .../app_activity_log_component_spec.rb | 17 ++++++++++ spec/models/parent_relationship_spec.rb | 31 +++++++++++++++++++ 5 files changed, 82 insertions(+), 1 deletion(-) diff --git a/app/components/app_activity_log_component.rb b/app/components/app_activity_log_component.rb index a028a77670..1736ff351a 100644 --- a/app/components/app_activity_log_component.rb +++ b/app/components/app_activity_log_component.rb @@ -57,6 +57,7 @@ def all_events gillick_assessment_events, note_events, notify_events, + parent_relationship_events, patient_merge_events, patient_specific_direction_events, pre_screening_events, @@ -270,6 +271,17 @@ def notify_events end end + def parent_relationship_events + parent_relationship_audits.map do |audit| + { + title: "Parent relationship removed", + body: audit.comment, + at: audit.created_at, + by: audit.user + } + end + end + def patient_merge_events patient_merge_log_entries.map do |patient_merge_log_entry| { @@ -536,6 +548,16 @@ def notify_log_entries end end + def parent_relationship_audits + return [] if include_programme_specific_events? + + patient + .associated_audits + .destroys + .where(auditable_type: "ParentRelationship") + .includes(:user) + end + def patient_locations return [] unless include_programme_specific_events? diff --git a/app/jobs/bulk_remove_parent_relationships_job.rb b/app/jobs/bulk_remove_parent_relationships_job.rb index 55c4d0b7ff..31ba783f35 100644 --- a/app/jobs/bulk_remove_parent_relationships_job.rb +++ b/app/jobs/bulk_remove_parent_relationships_job.rb @@ -45,7 +45,10 @@ def perform( CohortImportsParentRelationship.where( parent_relationship_id: parent_relationship_ids ).delete_all - parent_relationships_to_remove.each(&:destroy!) + + Audited + .audit_class + .as_user(user) { parent_relationships_to_remove.each(&:destroy!) } Parent .where(id: parent_ids_to_check) diff --git a/app/models/parent_relationship.rb b/app/models/parent_relationship.rb index 7a8ddcecb2..4c87c220b3 100644 --- a/app/models/parent_relationship.rb +++ b/app/models/parent_relationship.rb @@ -52,6 +52,8 @@ class ParentRelationship < ApplicationRecord accepts_nested_attributes_for :parent validates_associated :parent + before_destroy :set_removal_audit_comment, prepend: true + def label other? ? "Other – #{other_name}" : human_enum_name(:type).capitalize end @@ -71,4 +73,10 @@ def ordinal_label "#{index.ordinalize} parent or guardian" end end + + private + + def set_removal_audit_comment + self.audit_comment = "#{label_with_parent} removed from child record" + end end diff --git a/spec/components/app_activity_log_component_spec.rb b/spec/components/app_activity_log_component_spec.rb index 038ce34113..0d32563f9f 100644 --- a/spec/components/app_activity_log_component_spec.rb +++ b/spec/components/app_activity_log_component_spec.rb @@ -810,6 +810,23 @@ by: "JOY, Nurse" end + describe "parent relationship removal events" do + let(:component) { described_class.new(patient:, team:) } + + before do + relationship = + patient.parent_relationships.includes(:parent).find_by!(parent: mum) + + Audited.audit_class.as_user(user) { relationship.destroy! } + end + + include_examples "card", + title: "Parent relationship removed", + date: "1 January 2026 at 12:00am", + notes: "Jane Doe (mum) removed from child record", + by: "JOY, Nurse" + end + describe "decision expiration events" do let(:hpv_programme) { Programme.hpv } let(:flu_programme) { Programme.flu } diff --git a/spec/models/parent_relationship_spec.rb b/spec/models/parent_relationship_spec.rb index 795d775a81..4a5b7acd6e 100644 --- a/spec/models/parent_relationship_spec.rb +++ b/spec/models/parent_relationship_spec.rb @@ -84,4 +84,35 @@ it { should eq("Unknown") } end end + + context "removal is audited" do + subject(:destroy!) do + Audited.audit_class.as_user(user) { relationship.destroy! } + end + + let(:user) { create(:user) } + let(:patient) { create(:patient) } + let(:parent) { create(:parent, full_name: "Jane Doe") } + let!(:relationship) do + create(:parent_relationship, :mother, patient:, parent:) + end + + it "creates a destroy audit with the patient association and comment" do + expect { destroy! }.to change { relationship.audits.destroys.count }.by(1) + + audit = + Audited + .audit_class + .auditable_finder(relationship.id, "ParentRelationship") + .destroys + .last + + expect(audit).to have_attributes( + action: "destroy", + associated: patient, + user:, + comment: "Jane Doe (mum) removed from child record" + ) + end + end end