Биомаркер, который был назначен или ожидался в панели лабораторного анализа, но фактически не выполнен (не сдан, отказ, технический сбой, нет образца). Это не «отсутствует в данных», а «известно, что должен был быть, но измерения нет».

Зачем выделять как сущность

  1. Не путать с null. Биомаркер которого нет в результатах ≠ биомаркер который не был выполнен. Первое — нет информации, второе — есть информация о невыполнении.
  2. Тренд сохраняется. Если у пациента есть исторический ряд по этому биомаркеру, оценка тренда продолжает работать поверх предыдущих точек. Один пропущенный анализ — это не сброс серии.
  3. Сигнал для напоминаний/follow-up. Не-выполненный биомаркер — кандидат на «пересдай» / повтор по patient-portal follow-up.

FHIR encoding

В FHIR Observation для not-performed используется поле dataAbsentReason (CodeableConcept). Стандартные коды из http://terminology.hl7.org/CodeSystem/data-absent-reason:

  • not-performed — измерение не выполнено
  • unknown — статус неизвестен
  • not-applicable — не применимо к данному пациенту/контексту
  • error — попытка измерения, ошибка
  • not-asked — биомаркер не был запрошен

Для не-выполненных в нашей доменной модели — обычно not-performed (известно из источника, что назначен и не сделан) или unknown (если источник не уточняет причину).

Resource shape:

Observation {
  status: "registered" | "cancelled",   // не "final"
  code: { coding: [{ system: "loinc", code: "..." }] },
  // value[x] ОТСУТСТВУЕТ
  dataAbsentReason: { coding: [{
    system: "http://terminology.hl7.org/CodeSystem/data-absent-reason",
    code: "not-performed"
  }]}
}

См. parameter-range-type-prompt — LLM-промпт уже знает про dataAbsentReason как один из 8+1 вариантов value[x] в Observation.

UI rendering (legacy patient portal)

На старом фронте patient portal not-performed биомаркеры рендерились в серых панелях:

  • Без числового значения и без unit
  • С сохранённым историческим трендом (если была серия предыдущих значений)
  • Визуально отделены от выполненных биомаркеров (приглушённый цвет, опциональный hint «не выполнено»)

Not-performed biomarker — gray panel with trend on legacy patient portal

Скриншот старого UI — оставлен как иллюстрация паттерна (новый design system может рендерить иначе). Виден бейдж «Unknown», reason-текст в body, и Trend Analysis с trend-индикатором.

Источник скриншота — Slack thread с @mk (приватная ссылка; локальный файл — attachments/not-performed-biomarker-legacy-portal.png).

Pipeline preservation

Текущий открытый риск: новый /upload pipeline может терять Observation без value[x] при ingestion (если фильтрация фокусируется на «есть значение → создать Observation»).

Что должно сохраняться:

  1. Сам Observation создаётся даже без value, со status registered / cancelled.
  2. dataAbsentReason присутствует, чтобы фронт мог дискриминировать «not-performed» от других дыр в данных.
  3. Тренды на UI собираются из совокупности Observation с одинаковым LOINC code — pipeline не должен ронять «пустые» Observation, иначе тренды разорвутся.

Tracker: BG-1449Preserve not-performed parameters in /upload pipeline (status: Todo, project B2C Dashboard Migration).

Открытые вопросы

  • Какой именно dataAbsentReason код выбирать в каких случаях — not-performed всегда, или различать unknown / not-asked?
  • Поведение в новом design system дашборда — серые панели сохраняются или меняется представление?
  • Cross-resource: если назначение фиксируется как ServiceRequest, должен ли быть pair ServiceRequest.status="completed-with-error" + Observation с dataAbsentReason, или это избыточно?

Связано