From 9add4bdae28f769128480ad4caf441a763fa32af Mon Sep 17 00:00:00 2001 From: Marty Pradere Date: Thu, 10 Sep 2026 08:24:19 -0700 Subject: [PATCH 1/3] Normalize compliance lookups on write and consolidate the duplicated loop (#1199) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Rationale `employeeperunit` and `sopdates` were the only tables in `ehr_compliancedb` without trigger scripts, so their lookup values were never canonicalized on write, and this branch both adds those scripts and replaces the normalization loop that every other script in the schema had copied verbatim. The missing canonicalization is why the ONPRC report procedures had to wrap every unit and category comparison in `lower()`; that `lower()` removal has already merged, so those reports are exposed to case drift until this deploys. Existing rows carrying off-lookup values need a backfill before this deploys. The scripts merge the old row into the new one before validating, so a stored value that no longer matches its lookup will block edits that work today. ## Related Pull Requests - https://github.com/LabKey/LabDevKitModules/pull/310 — adds the shared helper this depends on, and must merge first. - https://github.com/LabKey/onprcEHRModules/pull/1885 — the same conversion in the ONPRC modules. - https://github.com/LabKey/onprcEHRModules/pull/1859 — removed the `lower()` calls these triggers replace. - https://github.com/LabKey/ehrModules/pull/1191 — superseded by this branch, which carries the same two new scripts written against the shared helper. ## Changes - Adds trigger scripts for `employeeperunit` and `sopdates`, normalizing the lookup columns their schema metadata already declares. - Leaves `sopdates.sopid` out deliberately: its fk to `sops` is commented out, and a lookup against a column with no fk would reject every row. - Converts the six existing `ehr_compliancedb` scripts to the shared helper, with field lists and error text unchanged so behavior is identical. --- .../ehr_compliancedb/completiondates.js | 15 ++-------- .../ehr_compliancedb/employeecategory.js | 5 ++++ .../ehr_compliancedb/employeeperunit.js | 29 ++++++++++++++++++ .../employeerequirementexemptions.js | 15 ++-------- .../queries/ehr_compliancedb/employees.js | 18 +++-------- .../queries/ehr_compliancedb/requirements.js | 15 ++-------- .../requirementspercategory.js | 15 ++-------- .../requirementsperemployee.js | 15 ++-------- .../queries/ehr_compliancedb/sopdates.js | 30 +++++++++++++++++++ .../queries/ehr_compliancedb/unit_names.js | 3 +- 10 files changed, 80 insertions(+), 80 deletions(-) create mode 100644 EHR_ComplianceDB/resources/queries/ehr_compliancedb/employeeperunit.js create mode 100644 EHR_ComplianceDB/resources/queries/ehr_compliancedb/sopdates.js diff --git a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/completiondates.js b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/completiondates.js index 5dcf17811..41d824e0a 100644 --- a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/completiondates.js +++ b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/completiondates.js @@ -6,6 +6,7 @@ var console = require("console"); var LABKEY = require("labkey"); +var ldkUtils = require("ldk/Utils").LDK.Server.Utils; var helper = org.labkey.ldk.query.LookupValidationHelper.create(LABKEY.Security.currentContainer.id, LABKEY.Security.currentUser.id, 'ehr_compliancedb', 'completiondates'); @@ -27,17 +28,5 @@ function beforeUpdate(row, oldRow, errors){ } function beforeUpsert(row, errors){ - var lookupFields = ['employeeid', 'requirementname']; - for (var i=0;i Date: Thu, 10 Sep 2026 12:32:47 -0700 Subject: [PATCH 2/3] GH Issue 1485: Fix Show Record History dataset filter (#1201) ## Rationale Fixes the "Show Record History" button on EHR dataset grids, which showed a record's history from every dataset instead of filtering to the one being viewed. The button built its audit log URL with `query.intkey1~eq`, a legacy column alias on `auditLog.DatasetAuditEvent` that was gated behind an off-by-default feature flag in 25.9 and removed outright in 26.1 along with the audit union table. The filter was therefore discarded at render time with an "Ignoring filter/sort on column 'intkey1'" warning; `datasetId` is the current column. Reported in https://github.com/LabKey/internal-issues/issues/1485. ## Related Pull Requests None. ## Changes - Filter the record history grid on the dataset's current audit column rather than the removed legacy alias. - Stop requesting a saved view that no longer exists; the grid was already falling back to the module's default view. --- ehr/resources/web/ehr/studyButtons.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ehr/resources/web/ehr/studyButtons.js b/ehr/resources/web/ehr/studyButtons.js index adfc6fb37..ecb9029de 100644 --- a/ehr/resources/web/ehr/studyButtons.js +++ b/ehr/resources/web/ehr/studyButtons.js @@ -139,8 +139,7 @@ EHR.DatasetButtons = new function () { var params = { schemaName: 'auditLog', 'query.queryName': 'DatasetAuditEvent', - 'query.viewName': 'Detailed', - 'query.intkey1~eq': row['Dataset/DataSetId'] + 'query.datasetId~eq': row['Dataset/DataSetId'] }; //NOTE: for demographics data, the objectId is not part of the LSID. therefore the best we can do is filter on Id, even though this might have changed over the life of the record. From d2d3734fa87f447f1998f32a794bad3989ade05e Mon Sep 17 00:00:00 2001 From: Marty Pradere Date: Fri, 11 Sep 2026 03:56:37 -0700 Subject: [PATCH 3/3] Bound the arrival acquisition type lookup to one row (#1200) ## Rationale Any status recalculation for an animal that has arrived more than once fails with a database error instead of saving. The recalculation reads the animal's acquisition type from the arrival dataset filtered only on the animal, which throws as soon as a second arrival row exists. Death entry is the common way to hit this, and it is worst at centers that leave the status to the recalculation rather than writing it directly, where the save and the status are both lost. This surfaced while adding rearrivals to an institution module, but it affects every center whose arrival dataset carries an acquisition type. ## Related Pull Requests - https://github.com/LabKey/nircEHRModules/pull/758 - https://github.com/LabKey/nbriEHRModules/pull/39 ## Changes - Read the acquisition type from the animal's most recent arrival rather than from all of its arrival records at once. --- ehr/src/org/labkey/ehr/utils/TriggerScriptHelper.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ehr/src/org/labkey/ehr/utils/TriggerScriptHelper.java b/ehr/src/org/labkey/ehr/utils/TriggerScriptHelper.java index 35f61d29c..b2b6013dc 100644 --- a/ehr/src/org/labkey/ehr/utils/TriggerScriptHelper.java +++ b/ehr/src/org/labkey/ehr/utils/TriggerScriptHelper.java @@ -41,6 +41,7 @@ import org.labkey.api.data.SQLFragment; import org.labkey.api.data.Selector; import org.labkey.api.data.SimpleFilter; +import org.labkey.api.data.Sort; import org.labkey.api.data.SqlExecutor; import org.labkey.api.data.SqlSelector; import org.labkey.api.data.Table; @@ -1781,7 +1782,9 @@ public void updateStatusField(List ids, Map> liveBirt ColumnInfo acquisitionColumn = columns.get(acquisitionFieldKey); if (acquisitionColumn != null) { - TableSelector ts = new TableSelector(arrivalTable, Collections.singleton(acquisitionColumn), new SimpleFilter(FieldKey.fromParts("Id"), id), null); + // In some cases, an animal can arrive more than once, so bound this to one row: unbounded, getObject() + // throws on the extra rows rather than picking one. Sort so the row picked is the latest arrival, not arbitrary. + TableSelector ts = new TableSelector(arrivalTable, Collections.singleton(acquisitionColumn), new SimpleFilter(FieldKey.fromParts("Id"), id), new Sort("-date")).setMaxRows(1); acquitype = ts.getObject(String.class); } }