From 5405ce053d84122c4eb32808a3882aef43e6a1ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Mon, 2 Nov 2026 20:28:34 +0100 Subject: [PATCH] feat(fhir): code a lab value without a unit as the UCUM unity A value stored with unit "1" carries system and code on its quantity even when the analyte map knows no coding for it: the unity is UCUM by definition. Refs #1313 --- src/lib/fhir/__tests__/lab-observations.test.ts | 10 ++++++++++ src/lib/fhir/resources/labs.ts | 11 ++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/lib/fhir/__tests__/lab-observations.test.ts b/src/lib/fhir/__tests__/lab-observations.test.ts index 274f0798b..3cb005613 100644 --- a/src/lib/fhir/__tests__/lab-observations.test.ts +++ b/src/lib/fhir/__tests__/lab-observations.test.ts @@ -276,6 +276,16 @@ describe("lab-result LOINC + canonical UCUM coding (v1.18.8)", () => { expect(o?.valueQuantity?.unit).toBe("mg/dL"); }); + it("codes a value without a unit as the UCUM unity", () => { + const o = labOf("Cholesterol/HDL ratio", "1", 3.6); + expect(o?.valueQuantity).toEqual({ + value: 3.6, + unit: "1", + system: "http://unitsofmeasure.org", + code: "1", + }); + }); + it("resolves analyte aliases to the same canonical LOINC", () => { // "LDL", "LDL-C", "LDL Cholesterol" all fold to 2089-1. for (const name of ["LDL-C", "LDL Cholesterol", "ldl_c"]) { diff --git a/src/lib/fhir/resources/labs.ts b/src/lib/fhir/resources/labs.ts index 3b9bf0dab..92ffedf85 100644 --- a/src/lib/fhir/resources/labs.ts +++ b/src/lib/fhir/resources/labs.ts @@ -21,6 +21,10 @@ import type { DoctorReportData } from "@/lib/doctor-report-data"; import { LOINC_SYSTEM, UCUM_SYSTEM } from "@/lib/fhir/loinc-map"; import { resolveLabCoding } from "@/lib/fhir/lab-loinc"; import { qualitativeValueConcept } from "@/lib/fhir/lab-qualitative"; +import { + DIMENSIONLESS_UNIT, + isDimensionlessUnit, +} from "@/lib/labs/dimensionless"; import type { FhirObservation, @@ -84,10 +88,15 @@ export function labObservations( // the code system while withholding the code claims a coding the bundle // does not carry, and leaves a receiver unable to machine-compare the // value it is attached to. + // A value without a unit is the UCUM unity by definition, so it carries + // the code even for an analyte the map does not know. + const ucum = isDimensionlessUnit(lab.unit) + ? DIMENSIONLESS_UNIT + : coding?.ucum; const quantity = (value: number) => ({ value, unit: lab.unit, - ...(coding?.ucum ? { system: UCUM_SYSTEM, code: coding.ucum } : {}), + ...(ucum ? { system: UCUM_SYSTEM, code: ucum } : {}), }); // The bounds are stated in the SAME unit as the value, so they carry the // SAME coding — a bare unit beside a coded value leaves a receiver unable