Skip to content

Prevent orphaned CE referrals when deleting enrollments - #6000

Draft
gigxz wants to merge 5 commits into
stablefrom
gig/8539-ce-delete-source-enrollment-handling
Draft

Prevent orphaned CE referrals when deleting enrollments#6000
gigxz wants to merge 5 commits into
stablefrom
gig/8539-ce-delete-source-enrollment-handling

Conversation

@gigxz

@gigxz gigxz commented Nov 12, 2025

Copy link
Copy Markdown
Contributor

Merging this PR

  • use the squash-merge strategy for PRs targeting a release-X branch
  • use a merge-commit or rebase strategy for PRs targeting the stable branch

Description

Prevent orphaned CE referrals when deleting enrollments

Problem

When an Enrollment with outgoing CE referrals was destroyed, the referrals were left with a source_enrollment_id pointing to a non-existent enrollment. This caused issues:

  • Direct referrals: Lost their association to the source project, making them invisible on the source project's outgoing referrals list (they would "float" without context)
  • Waitlist referrals: Could function without a source enrollment, but leaving orphaned references was inconsistent

Solution

Implemented custom before_destroy hooks that handle referrals based on their origin and status:

  1. Active direct referrals prevent deletion: Enrollments with active (initialized/in_progress) direct referrals cannot be deleted, preserving the source project context. This forces the user to deal with the situation by closing those referrals
  2. Completed direct referrals are destroyed: When deletion is allowed, all direct referrals are destroyed since they require the source enrollment to identify the sending project
  3. Waitlist referrals are nullified: Waitlist referrals have their source_enrollment_id set to NULL since they can exist without the source enrollment context

Also added validation requiring source_enrollment_id for direct referrals to prevent creating orphaned direct referrals.

Alternatives Considered

Considered simpler approaches for the referral relation on Enrollment, I couldn't square any of these:

  1. dependent: :nullify Problem: Works for waitlist referrals, but direct referrals become orphaned. The sending project loses visibility of the referral on their outgoing referrals list (though it remains visible on the receiving project's incoming referrals list).

  2. dependent: :restrict_with_exception Problem: Prevents deletion of any enrollment that has ever been tied to a referral, even if the referral is completed. This is too restrictive and prevents necessary cleanup.

  3. dependent: :destroy Problem: Might unintentionally delete legitimate referrals in waitlist-based scenarios where referrals should persist even if the source enrollment is removed.

Type of change

Bug fix

Checklist before requesting review

  • I have performed a self-review of my code
  • I have run the code that is being changed under ideal conditions, and it doesn't fail
  • If adding a new endpoint / exposing data in a new way, I have:
    • ensured the API can't leak data from other data sources
    • ensured this does not introduce N+1s
    • ensured permissions and visibility checks are performed in the right places
  • Any major architectural changes are supported by an approved ADR (Architectural Decision Record)
  • I have updated the documentation (or not applicable)
  • I have added spec tests (or not applicable)
  • I have provided testing instructions in this PR or the related issue (or not applicable)

//: # NOTE: system tests may fail if there is no branch on the hmis-frontend that matches the Source or Target branch of this PR. This is expected

private def check_active_outgoing_direct_referrals
return unless outgoing_ce_referrals.originated_from_direct_send.active.exists?

raise ActiveRecord::DeleteRestrictionError, 'Cannot delete enrollment because it has active outgoing referrals. Please complete or reject the referrals first.'

@gigxz gigxz Nov 12, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This prevents the deletion, but the descriptive message doesn't make its way to the end-user (yet)

@gigxz
gigxz changed the base branch from release-189 to release-190 November 17, 2025 19:57
end

# Nullifies source_enrollment_id on waitlist-based referrals when enrollment is deleted.
# Waitlist-based referrals can exist without as source enrollment since they're already resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs ticket: support changing/adding source enrollment to referral


# Destroys all direct send referrals when enrollment is deleted.
# Direct send referrals require the source enrollment to identify which project sent them.
# Without the source enrollment, they would "float" and not appear on the source project's outgoing referrals list.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not as compelling, revisit this one.. its more about the target project no?

Comment on lines +115 to +117
before_destroy :check_active_outgoing_direct_referrals
before_destroy :nullify_outgoing_waitlist_referrals
before_destroy :destroy_outgoing_direct_referrals

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To do - add handling for destroying target enrollment

Base automatically changed from release-190 to stable December 18, 2025 18:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant