mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 14:16:12 +00:00
docs(api): describe the dimensionless lab unit on every lab unit field
The unit on lab results, biomarkers, the scanned-report commit and the document fact edit now states that "1" means the value has no unit, that it matches only itself, and that an empty unit stays refused. The lab CSV import description names the 1 in the unit column. Refs #1313
This commit is contained in:
1 parent
f9431da64f
commit
e605fe0ae8
8 files changed
+79
-14
No files matched your search
@@ -14,6 +14,8 @@
|
||||
import type { ZodOpenApiObject } from "zod-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
import { LAB_UNIT_DESCRIPTION } from "@/lib/labs/dimensionless";
|
||||
|
||||
import {
|
||||
createBiomarkerSchema,
|
||||
updateBiomarkerSchema,
|
||||
@@ -54,7 +56,7 @@ const biomarkerRow = z
|
||||
.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
unit: z.string(),
|
||||
unit: z.string().describe(LAB_UNIT_DESCRIPTION),
|
||||
lowerBound: z.number().nullable(),
|
||||
upperBound: z.number().nullable(),
|
||||
panel: z.string().nullable(),
|
||||
|
||||
@@ -553,7 +553,7 @@ export const importPaths: NonNullable<ZodOpenApiObject["paths"]> = {
|
||||
post: {
|
||||
tags: ["Import"],
|
||||
summary: "Import lab results from CSV",
|
||||
description: `${RECORD_IMPORT_COMMON} Each row's name resolves to the account's marker the way a scanned report's rows do (name, alias, catalog name); a new analyte mints one marker from its first row. A numeric result needs a unit; one in another unit is converted when the conversion is known and keeps the printed value beside it, otherwise the row is refused with \`unit_mismatch\`. Any other text in the value column is a qualitative result. A date without a time is stored as that calendar date. At most 20 000 data rows.`,
|
||||
description: `${RECORD_IMPORT_COMMON} Each row's name resolves to the account's marker the way a scanned report's rows do (name, alias, catalog name); a new analyte mints one marker from its first row. A numeric result needs a unit: an empty unit cell is refused with \`missing_unit\`, and \`1\` (the UCUM unity) states a value without a unit, such as a ratio or INR. A result in another unit is converted when the conversion is known and keeps the printed value beside it, otherwise the row is refused with \`unit_mismatch\`. Any other text in the value column is a qualitative result. A date without a time is stored as that calendar date. At most 20 000 data rows.`,
|
||||
requestParams: { query: labsCsvQuerySchema },
|
||||
requestBody: {
|
||||
required: true,
|
||||
|
||||
@@ -11,6 +11,8 @@ import { withRelated } from "./relation-links";
|
||||
import type { ZodOpenApiObject } from "zod-openapi";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
import { LAB_UNIT_DESCRIPTION } from "@/lib/labs/dimensionless";
|
||||
|
||||
import {
|
||||
createLabResultSchema,
|
||||
labOverviewQuerySchema,
|
||||
@@ -71,7 +73,7 @@ const labResultRow = z
|
||||
// exactly one of the two is non-null per row.
|
||||
value: z.number().nullable(),
|
||||
valueText: z.string().nullable(),
|
||||
unit: z.string(),
|
||||
unit: z.string().describe(LAB_UNIT_DESCRIPTION),
|
||||
converted: z.boolean(),
|
||||
sourceValue: z.number().nullable(),
|
||||
sourceUnit: z.string().nullable(),
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
import { z } from "zod/v4";
|
||||
|
||||
import { LAB_UNIT_DESCRIPTION } from "@/lib/labs/dimensionless";
|
||||
|
||||
const requiredText = (max: number) => z.string().trim().min(1).max(max);
|
||||
|
||||
const lowerBound = z.number().finite().optional();
|
||||
@@ -40,7 +42,7 @@ const optionalPanel = z
|
||||
export const createBiomarkerSchema = z
|
||||
.object({
|
||||
name: requiredText(120),
|
||||
unit: requiredText(40),
|
||||
unit: requiredText(40).describe(LAB_UNIT_DESCRIPTION),
|
||||
lowerBound,
|
||||
upperBound,
|
||||
context: optionalContext,
|
||||
@@ -67,7 +69,7 @@ export type CreateBiomarkerInput = z.infer<typeof createBiomarkerSchema>;
|
||||
export const updateBiomarkerSchema = z
|
||||
.object({
|
||||
name: requiredText(120).optional(),
|
||||
unit: requiredText(40).optional(),
|
||||
unit: requiredText(40).optional().describe(LAB_UNIT_DESCRIPTION),
|
||||
lowerBound: lowerBound.or(z.null()),
|
||||
upperBound: upperBound.or(z.null()),
|
||||
context: optionalContext.or(z.null()),
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
import { z } from "zod/v4";
|
||||
import { locales } from "@/lib/i18n/config";
|
||||
import { LAB_UNIT_DESCRIPTION } from "@/lib/labs/dimensionless";
|
||||
import {
|
||||
DOCUMENT_BULK_MAX_IDS,
|
||||
DOCUMENT_CONTENT_INDEX_SOURCES,
|
||||
@@ -34,7 +35,6 @@ import {
|
||||
type DocumentContentIndexSourceValue,
|
||||
type InboundDocumentKindValue,
|
||||
} from "@/lib/documents/inbound-constants";
|
||||
|
||||
import type { AiCapabilityState } from "@/lib/ai/capabilities/types";
|
||||
import { OCR_MAX_ROWS } from "@/lib/validations/labs-ocr";
|
||||
|
||||
@@ -443,7 +443,7 @@ const observationEditSchema = z
|
||||
codeSystem: optCode,
|
||||
value: z.number().finite().nullable().optional(),
|
||||
valueText: optText(300),
|
||||
unit: optText(80),
|
||||
unit: optText(80).describe(LAB_UNIT_DESCRIPTION),
|
||||
referenceLow: z.number().finite().nullable().optional(),
|
||||
referenceHigh: z.number().finite().nullable().optional(),
|
||||
referenceText: optText(120),
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
import type { AiCapabilityState } from "@/lib/ai/capabilities/types";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
import { LAB_UNIT_DESCRIPTION } from "@/lib/labs/dimensionless";
|
||||
import type { WrittenOutcome } from "@/lib/outcome/written-outcome";
|
||||
|
||||
import { validateEntryInstant } from "@/lib/validations/entry-instant";
|
||||
@@ -257,7 +258,13 @@ export const ocrCommitRowSchema = z
|
||||
.or(z.literal("").transform(() => undefined)),
|
||||
value: z.number().finite().optional(),
|
||||
valueText: z.string().trim().min(1).max(OCR_VALUE_TEXT_MAX).optional(),
|
||||
unit: z.string().trim().min(1).max(OCR_UNIT_MAX).optional(),
|
||||
unit: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1)
|
||||
.max(OCR_UNIT_MAX)
|
||||
.optional()
|
||||
.describe(LAB_UNIT_DESCRIPTION),
|
||||
referenceLow,
|
||||
referenceHigh,
|
||||
/**
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
import { z } from "zod/v4";
|
||||
|
||||
import { LAB_UNIT_DESCRIPTION } from "@/lib/labs/dimensionless";
|
||||
import { SOURCE_REFERENCE_TEXT_MAX } from "@/lib/labs/parse-reference-range";
|
||||
import { validateEntryInstant } from "@/lib/validations/entry-instant";
|
||||
import { isoDateTime } from "@/lib/validations/datetime";
|
||||
@@ -123,7 +124,7 @@ export const createLabResultSchema = z
|
||||
// (`value`) OR qualitative (`valueText`), never both, never neither.
|
||||
value: z.number().finite().optional(),
|
||||
valueText,
|
||||
unit: requiredText(40).optional(),
|
||||
unit: requiredText(40).optional().describe(LAB_UNIT_DESCRIPTION),
|
||||
referenceLow,
|
||||
referenceHigh,
|
||||
sourceReferenceLow,
|
||||
@@ -208,7 +209,7 @@ export const updateLabResultSchema = z
|
||||
// row's type (numeric ↔ qualitative) is intentionally not supported here —
|
||||
// delete and re-add — so an omitted key leaves the row's existing type.
|
||||
valueText: requiredText(120).optional(),
|
||||
unit: requiredText(40).optional(),
|
||||
unit: requiredText(40).optional().describe(LAB_UNIT_DESCRIPTION),
|
||||
referenceLow: referenceLow.or(z.null()),
|
||||
referenceHigh: referenceHigh.or(z.null()),
|
||||
sourceReferenceLow: sourceReferenceLow.or(z.null()),
|
||||
|
||||
Reference in new issue
Block a user