Skip to content

Add case handoff feature for transferring patients between case managers#3551

Open
Rolling2405 wants to merge 10 commits intoDARIAEngineering:mainfrom
Rolling2405:feature/case-handoff-notes
Open

Add case handoff feature for transferring patients between case managers#3551
Rolling2405 wants to merge 10 commits intoDARIAEngineering:mainfrom
Rolling2405:feature/case-handoff-notes

Conversation

@Rolling2405
Copy link
Copy Markdown
Contributor

@Rolling2405 Rolling2405 commented Apr 8, 2026

I rule and have completed some work on Case Manager that's ready for review!

This lets case managers transfer a patient to another case manager with a handoff note and automatic notification, making it easy to reassign cases when workloads shift or someone is unavailable.

This pull request makes the following changes:

  • Add handoff action on PatientsController to transfer a patient to a target case manager
  • Atomic transaction: updates patient, creates handoff note, and sends notification in one operation
  • Add Stimulus handoff_controller.js for form submission (includes standalone fallback — works with or without Replace React with Stimulus — remove React dependency entirely #3544)
  • Scope user lookup to current tenant for security
  • Use Bootstrap 5 classes throughout

Notes:

(If there are changes to the views, please include a screenshot so we know what to look for!)

For reviewer:

  • Adjust the title to explain what it does for the notification email to the listserv.
  • Tag this PR:
    • feature if it contains a feature, fix, or similar. This is anything that contains a user-facing fix in some way, such as frontend changes, alterations to backend behavior, or bug fixes.
    • dependencies if it contains library upgrades or similar. This is anything that upgrades any dependency, such as a Gemfile update or npm package upgrade.
  • If it contains neither, no need to tag this PR.

Handoff workflow:
- 'Hand Off To' dropdown on patient dashboard (below delete button row)
- Select target case manager + optional handoff note
- Patient automatically moved from current user's call list to target's
- Handoff recorded on patient: handed_off_at, from/to user IDs, note
- Automatic note created documenting the handoff
- Notification sent to receiving CM via notification center
- Flash confirmation shown to handing-off user

Database changes:
- Migration adds handed_off_at, handed_off_from_id, handed_off_to_id,
  handoff_note columns to patients table

Routing:
- POST /patients/:id/handoff added as member route

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rolling2405 added a commit to Rolling2405/dcaf_case_management that referenced this pull request Apr 9, 2026
Bug fixes:
- Remove autosave_controller.js (belongs in DARIAEngineering#3545 auto-save PR,
  not in this foundation PR — avoids merge conflict)
- Export Stimulus Application as window.Stimulus so downstream PRs
  (DARIAEngineering#3545, DARIAEngineering#3551) can register controllers without re-importing
- Keep jquery-ujs and popper.js restored (from prior commit)

Tests (4):
- Patient edit page renders successfully (replaces deleted React unit
  tests with server-side rendering integration tests)
- Patient name displayed on dashboard
- Stimulus application.js loads without errors
- Dashboard form with data attributes renders

Note: React component tests (Input, Select, Tooltip, PatientDashboardForm)
and hook tests (useDebounce, useFetch, useFlash, usei18n) are removed
because this PR replaces React with server-rendered ERB + Stimulus.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… tests

Critical bug fixes:
- Move handoff form OUTSIDE the patient edit form to eliminate
  illegal nested <form> tags (HTML spec violation)
- Remove Note created_by: current_user (field doesn't exist on Note;
  PaperTrail whodunnit tracks the acting user automatically)
- Wrap entire handoff in ActiveRecord::Base.transaction for atomicity
- User.find -> User.find_by! for safer lookup

Infrastructure fixes:
- Migration FK columns: :integer -> :bigint (handed_off_from_id,
  handed_off_to_id)
- Migration version: [8.0] -> [8.1]

Tests (5):
- Handoff sets all metadata fields correctly
- Handoff creates documentation note with both user names
- Handoff works without optional note
- Invalid target_user_id raises RecordNotFound
- Flash notice includes patient and target user names

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rolling2405 and others added 8 commits April 9, 2026 16:13
Update handoff form in patient dashboard:
- ml-auto → ms-auto
- form-group → mb-3 (BS5 dropped form-group)
- select_tag form-control → form-select (BS5 convention for selects)
- text_field_tag form-control stays (correct for inputs in BS5)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Change ms-auto to ml-auto (BS4 margin utility)
- Change form-select to form-control (BS4 select styling)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Unauthorized users (data volunteers, CMs without the patient on their
call list) are blocked from handing off patients. Admins can always
hand off regardless of call list.

Added before_action and comprehensive authorization tests covering
admin override, unassigned CM rejection, and data volunteer rejection.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The confirm_handoff_authorization method previously allowed any user
with the patient on their call list, including data_volunteers. This
changes the check to require current_user.cm? (case manager role) in
addition to being assigned. Admins are still always permitted.

This matches the existing test expectation at line 94-102 which expects
data_volunteer to be rejected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The handoff action in PatientsController calls Notification.notify!
from the unmerged feature/notification-center branch. Wrap the call in
a defined?(Notification) guard so handoffs still work when the
Notification model is not yet available.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Issue 1 - Popover: Replace jQuery .popover() with bootstrap.Popover and
update data-toggle to data-bs-toggle on budget bar template.

Issue 2 - Multi-step modal: Rewrite vendor jquery-bootstrap-modal-steps
plugin to use bootstrap.Modal.getInstance() instead of jQuery .modal()
method. Update data-dismiss to data-bs-dismiss in multi_modal template.

Additional BS4 patterns found during verification (Step 6):
- Convert all .modal('toggle'/'hide') calls in js.erb files to
  bootstrap.Modal.getOrCreateInstance()/getInstance() API
- Convert .tooltip() calls in tooltips.js to bootstrap.Tooltip API
- Convert .tooltip('update') in update.js.erb to dispose/recreate pattern

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add call list transfer verification (patient removed from source, added to target)
- Add handed_off_at timestamp precision test with freeze_time
- Add handoff note content in note text assertion
- Add unauthenticated access rejection test

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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