From 21d926b9f4eeb47795cf5186d9e3885cfced5a7d Mon Sep 17 00:00:00 2001 From: Marty Pradere Date: Wed, 2 Sep 2026 03:14:20 -0700 Subject: [PATCH] Fix death notification firing, a duplicate Assign To field, and dropped birth/arrival times (#751) ## Rationale Three NIRC updates: the death notification now fires for a death recorded alongside its necropsy, the Submit For Review dialog no longer shows a duplicate Assign To field when reopened, and birth and arrival entry now keeps the time of day. The notification and the accompanying procedure-order update were keyed off the 'Request: Pending' state. A death entered on the same form as its necropsy is submitted straight to 'Review Required' or 'Completed' and never passes through that state, so neither ran for it. The Submit For Review dialog claimed a page-wide element name for its Assign To field and only hid itself when cancelled, so a second open rendered the previous dialog's field next to the new one. Cancelling to correct a value and reopening is routine in the combined death-and-necropsy flow, which is where it showed up. Times were lost twice over: neither date column carried a format with a time component, so both forms presented a date-only editor, and the birth trigger separately discarded the time server-side, which carried through to the records derived from the birth date. ## Changes - The deaths trigger keys the notification off the move out of draft instead of off one specific target state, so it fires once per record no matter which submit button created it. - The procedure-order update moves with the notification, so it also runs for a death recorded alongside its necropsy. - The Submit For Review dialog no longer claims a page-wide element name and now discards itself when cancelled, so reopening it renders a single Assign To field. - The birth and arrival date columns declare a date-and-time display format, so entry offers a time-of-day editor and the stored time is visible. - The birth trigger no longer discards the time from the birth date, so it survives onto the birth record and everything derived from it. --- .../resources/queries/study/arrival.query.xml | 1 + nirc_ehr/resources/queries/study/birth.js | 1 - .../resources/queries/study/birth.query.xml | 1 + nirc_ehr/resources/queries/study/deaths.js | 18 ++++++++++-------- .../nirc_ehr/buttons/deathNecropsyButtons.js | 6 ++++-- 5 files changed, 16 insertions(+), 11 deletions(-) diff --git a/nirc_ehr/resources/queries/study/arrival.query.xml b/nirc_ehr/resources/queries/study/arrival.query.xml index ffe21086..3b8933b1 100644 --- a/nirc_ehr/resources/queries/study/arrival.query.xml +++ b/nirc_ehr/resources/queries/study/arrival.query.xml @@ -11,6 +11,7 @@ Arrival Date + DateTime Arrival Type diff --git a/nirc_ehr/resources/queries/study/birth.js b/nirc_ehr/resources/queries/study/birth.js index 26b5e66a..66b4e9a2 100644 --- a/nirc_ehr/resources/queries/study/birth.js +++ b/nirc_ehr/resources/queries/study/birth.js @@ -17,7 +17,6 @@ function onInit(event, helper){ skipHousingCheck: true, announceAllModifiedParticipants: true, allowDatesInDistantPast: true, - removeTimeFromDate: true, skipAssignmentCheck: true, }); diff --git a/nirc_ehr/resources/queries/study/birth.query.xml b/nirc_ehr/resources/queries/study/birth.query.xml index 40849889..ea501cee 100644 --- a/nirc_ehr/resources/queries/study/birth.query.xml +++ b/nirc_ehr/resources/queries/study/birth.query.xml @@ -12,6 +12,7 @@ Birth Date + DateTime Birth Location diff --git a/nirc_ehr/resources/queries/study/deaths.js b/nirc_ehr/resources/queries/study/deaths.js index 9e1133f1..8695ed58 100644 --- a/nirc_ehr/resources/queries/study/deaths.js +++ b/nirc_ehr/resources/queries/study/deaths.js @@ -167,19 +167,21 @@ EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Even }); EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.COMPLETE, 'study', 'Deaths', function(event, errors, helper){ + // A delete arrives here as the deleted row with a null oldRow, which otherwise reads as a draft leaving draft. + if (event === 'delete') + return; + var rows = helper.getRows() || []; for (var i = 0; i < rows.length; i++) { var row = rows[i].row; var oldRow = rows[i].oldRow; - // Notification will get sent when: - // 1) a brand-new row saved directly as 'Request: Pending' (i.e., when a user clicks 'Submit Death'), or - // 2) a draft death record moving from 'In Progress' to 'Request: Pending'. - if (!helper.isETL() && - row && row.Id && - row.QCStateLabel && - row.QCStateLabel.toUpperCase() === 'REQUEST: PENDING' && - (!oldRow || !oldRow.QCStateLabel || oldRow.QCStateLabel.toUpperCase() === 'IN PROGRESS')) { + if (helper.isETL() || !row || !row.Id || !row.QCStateLabel) + continue; + + // Notify once, on the first non-draft save: 'Submit Death' lands on 'Request: Pending', but a death entered alongside its necropsy goes straight to 'Review Required' or 'Completed'. + var wasDraft = !oldRow || !oldRow.QCStateLabel || oldRow.QCStateLabel.toUpperCase() === 'IN PROGRESS'; + if (wasDraft && row.QCStateLabel.toUpperCase() !== 'IN PROGRESS') { console.log("Sending NIRC Death Notification") triggerHelper.sendDeathNotification(row.Id); diff --git a/nirc_ehr/resources/web/nirc_ehr/buttons/deathNecropsyButtons.js b/nirc_ehr/resources/web/nirc_ehr/buttons/deathNecropsyButtons.js index 344873ff..cd8f4f2d 100644 --- a/nirc_ehr/resources/web/nirc_ehr/buttons/deathNecropsyButtons.js +++ b/nirc_ehr/resources/web/nirc_ehr/buttons/deathNecropsyButtons.js @@ -101,7 +101,7 @@ Ext4.define('NIRC_EHR.window.DeathNecropsySubmitForReviewWindow', { text: 'Cancel', scope: this, handler: function(btn){ - btn.up('window').hide(); + btn.up('window').close(); } }], items: [{ @@ -127,8 +127,10 @@ Ext4.define('NIRC_EHR.window.DeathNecropsySubmitForReviewWindow', { value: this.getDefaultRecipient(), displayField: 'DisplayName', valueField: 'UserId', + // No global 'id' here: a reopened window would adopt the previous window's element and render a second combo. itemId: 'assignedTo', - id: 'assignedTo', + // Ext derives the input's name from the component id when 'name' is absent, so set it explicitly rather than leaning on the id. + name: 'assignedTo', anyMatch: true, caseSensitive: false, }]