Skip to content

Normalize employeeid, unit, and category on write in compliance tables - #1191

Closed
labkey-martyp wants to merge 1 commit into
release26.3-SNAPSHOTfrom
26.3_fb_final_onprc_scripts
Closed

Normalize employeeid, unit, and category on write in compliance tables#1191
labkey-martyp wants to merge 1 commit into
release26.3-SNAPSHOTfrom
26.3_fb_final_onprc_scripts

Conversation

@labkey-martyp

Copy link
Copy Markdown
Contributor

Rationale

The ported PostgreSQL report procedures in ONPRC's compliance module wrapped every unit and category comparison in lower() to emulate the case-insensitive default collation the MS SQL originals relied on implicitly. All of those comparisons join employeeperunit against requirementspercategory, and the latter already canonicalizes unit and category on write through its trigger script — so employeeperunit, the only table in ehr_compliancedb without one, was the sole source of case drift. Normalizing on write instead removes the need for lower() downstream and keeps the joins indexable.

Related Pull Requests

Changes

  • Adds employeeperunit.js, normalizing employeeid, unit, and category against the lookups its schema metadata already declares.
  • Adds sopdates.js, normalizing employeeid. sopid is excluded deliberately — its fk to sops is commented out in ehr_compliancedb.xml, and getLookupValue returns null for a column with no fk, which would reject every row.

Tasks 📍

  • Claude Code Review
  • Code Review

employeeperunit was the only table in ehr_compliancedb with no trigger script, so its employeeid, unit, and category values were never canonicalized against their lookups - the reason the ONPRC report procedures had to wrap every unit and category comparison in lower(). Its schema metadata already declares all three columns as lookups, so the script is a drop-in copy of the ten siblings.

sopdates had no trigger script either. sopid is deliberately left out of its lookupFields: the fk to sops is commented out in ehr_compliancedb.xml, and getLookupValue returns null for a column with no fk, which would reject every row.

Pairs with the lower() removal in onprcEHRModules (PR 1859). Merge this first, or those reports will silently drop rows whose unit or category differs only by case. Existing rows carrying off-lookup values need a backfill before this deploys, since beforeUpdate revalidates the merged old row and will otherwise block edits that work today.
@bbimber

bbimber commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

@labkey-martyp and @labkey-jeckels: the pattern outlined here probably need to occur in more places. Are there ways to do this that are more efficiency and wont require repeating a lot of boilerplate code? Some thoughts:

  • If we need to do this in query-specific trigger scripts, can the code be generalized into a central method that accepts the row object, key, lookup target, etc.?
  • Could this jump into java, iterate ColumnInfos and infer what to do? For example, and string with a lookup to a table in EHR_Lookups probably should have enforcement.
  • Perhaps something in the EHR trigger init() layer could let modules register names of target tables or target tables/field pairs, and any column with a FK to that table undergoes case-normalization?
  • If we need JS files, could we use a JS schema customizer instead of per query?

@labkey-martyp labkey-martyp left a comment

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.

@bbimber Good point on the duplication. I have another PR that does something more like your first point. I will open that and close this one. It's combining the JS code into a reusable function in LDK.

Converting to a java trigger is probably the next step on this. Need to do more investigation into the scope of that trigger though.

To your third point, the EHR does have this feature, using the same LDK LookupValidationHelper only for registered fields - lookupValidationFields. It does not look very widely used though, and it probably should be.

A JS schema customizer sounds interesting but I'm not aware of any current implementation that matches that.

@labkey-martyp

Copy link
Copy Markdown
Contributor Author

Closing in favor of #1199, which carries these same two trigger scripts — employeeperunit.js and sopdates.js — written against the new shared helper in LabKey/LabDevKitModules#310 instead of each copying the normalization loop. That branch also converts the six existing ehr_compliancedb scripts, so all eight now go through one implementation.

labkey-martyp added a commit that referenced this pull request Sep 10, 2026
…loop (#1199)

## 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

- LabKey/LabDevKitModules#310 — adds the shared
helper this depends on, and must merge first.
- LabKey/onprcEHRModules#1885 — the same
conversion in the ONPRC modules.
- LabKey/onprcEHRModules#1859 — removed the
`lower()` calls these triggers replace.
- #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.
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.

2 participants