Перейти к содержанию

Соответствие таблиц требованиям

Проверка полноты: каждая обязательная группа данных и каждое функциональное требование должны иметь место хранения. Таблица без требования — лишняя; требование без таблицы — пробел.

Семь обязательных групп данных

[ОП] Формулировки групп — дословно из требований заказчика.

# Группа данных Основные таблицы Вспомогательные
1 Входящие запросы на наличие свободных мест в стационаре bed_requests inbound_messages, providers
2 Входящая информация по направлению пациента в приёмное отделение: номер кареты скорой, персональная информация по пациенту, его состояние на момент начала транспортировки transport_notifications, patients, ambulances practitioners, inbound_messages, vital_observations (исходный набор), transport_events
3 Параметры изменения состояния пациента в процессе транспортировки. Регистрируются основные жизненные показатели vital_observations inbound_messages
4 Лог запросов на уточнение положения кареты скорой помощи location_requests ambulance_locations, integration_log
5 Информация о доставке пациента deliveries transport_notifications, transport_events
6 Постановка пациента в очередь на сортировку ТРИАЖ triage_queue, appeals appeal_events
7 Результаты сортировки пациента и передача информации в медицинскую информационную систему triage_assessments, mis_handoffs triage_assessment_inputs, triage_rule_versions, triage_rules
flowchart LR
  G1["1 · Запросы мест"] --> T1["bed_requests"]
  G2["2 · Направление"] --> T2["transport_notifications<br/>patients · ambulances"]
  G3["3 · Состояние в пути"] --> T3["vital_observations"]
  G4["4 · Лог координат"] --> T4["location_requests<br/>ambulance_locations"]
  G5["5 · Доставка"] --> T5["deliveries"]
  G6["6 · Очередь ТРИАЖ"] --> T6["triage_queue · appeals"]
  G7["7 · Результаты + МИС"] --> T7["triage_assessments<br/>mis_handoffs"]

Группа 2 хранится в трёх таблицах, а не в одной

Формулировка объединяет разнородные сущности: направление (событие), пациент (долгоживущая запись ПДн), карета (справочник) и состояние на момент старта (наблюдения). Хранить их одной таблицей означало бы дублировать ПДн пациента при каждом обращении и терять возможность связать пациента с его прошлыми визитами. Требование выполнено полностью — просто нормализованно.

Группа 4 — именно лог запросов, а не только координаты

Требование говорит о логе запросов, а не о позициях. Поэтому location_requests (каждый запрос: когда, к кому, с каким результатом, сколько длился, была ли ошибка) — основная таблица, а ambulance_locations — полученные данные. Реализация, хранящая только координаты, требование не закрывает: разобрать «почему карета пропала с карты» без лога запросов невозможно.

Покрытие функциональных требований

Подсистема «Триаж»

Требование Где реализуется
FR-T-1 приём сообщений сервер-сервер inbound_messages, provider_endpoints
FR-T-2 пять типов сообщений inbound_messages.message_type
FR-T-3 ответ на запрос мест bed_requests.decision, decision_reason, decided_by
FR-T-4 регистрация кареты transport_notifications, ambulances
FR-T-5 изменения состояния в пути vital_observations
FR-T-6 координаты кареты location_requests, ambulance_locations
FR-T-7 мультипровайдерность координат providers.axis='geo', adapter_class, settings
FR-T-8 мультипровайдерность API СМП providers.axis='smp'
FR-T-9 мультипровайдерность МИС providers.axis='mis', mis_handoffs.provider_id
FR-T-10 интерфейс направляющихся чтение transport_notifications + ambulance_locations
FR-T-11 ручная передача в МИС mis_handoffs.kind='team_request', initiated_by
FR-T-12 отмена транспортировки transport_notifications.status='cancelled', cancel_reason, mis_handoffs.kind='cancel_notice'
FR-T-13 регистрация доставки, отсечка времени deliveries.delivered_at, accepted_at
FR-T-14 терминал самообращения appeals.source='self'
FR-T-15 анонимная очередь appeals.patient_id IS NULL, triage_assessment_inputs
FR-T-16 цвет и талон triage_assessments.color, ticket_code
FR-T-17 правила сортировки triage_rules, triage_rule_versions.conditions
FR-T-18 СМП-пациенты не зелёные ограничение в правилах + проверка приложения
FR-T-19 автозаполнение из данных СМП appeals.notification_idtransport_notifications
FR-T-20 приоритетная очередь triage_queue.priority_rank
FR-T-21 нормативное время выбытия triage_queue.sla_deadline, sla_breached
FR-T-22 оформление обращения appeals.status='registered', registered_at
FR-T-23 передача обращения в МИС mis_handoffs.kind='appeal'
FR-T-24 выписка из приёмного отделения appeals.closed_at, closed_reason
FR-T-25 режим массового поступления triage_assessments.mode='mass_casualty'
FR-T-26 печать браслета/талона appeals.appeal_number → штрих-код

Общие требования

Требование Где реализуется
FR-C-1 своя БД и логи вся схема + integration_log
FR-C-2 журнал событий ИБ ≥ 1 года security_events + политика ретеншна
FR-C-3 ЭЦП triage_assessments.signature_ref, users.cert_thumbprint
FR-C-4 разграничение доступа users, roles, user_roles
FR-C-5 отчётность по КПЭ вычисляется из deliveries, triage_queue, appeals
FR-C-6 администрирование providers, facilities.settings, triage_rule_versions
FR-C-7 обезличивание шифрование patients + выгрузки без patient_id
FR-C-8 синхронизация времени timestamptz везде + NTP на уровне ОС

Расчёт показателей эффективности

[ТЗ] Два КПЭ паспорта должны считаться из схемы, иначе достижение целей нечем подтвердить (FR-C-5).

Среднее время ожидания оказания медицинской помощи

Цель: 30–120 мин → 15–60 мин.

-- По категориям (цветам) за период
SELECT
    ta.color,
    count(*)                                              AS patients,
    avg(tq.called_at - a.opened_at)                       AS avg_wait,
    percentile_cont(0.5) WITHIN GROUP (ORDER BY tq.called_at - a.opened_at) AS median_wait,
    percentile_cont(0.9) WITHIN GROUP (ORDER BY tq.called_at - a.opened_at) AS p90_wait
FROM appeals a
JOIN triage_queue tq        ON tq.appeal_id = a.id
JOIN triage_assessments ta  ON ta.appeal_id = a.id
WHERE a.facility_id = $1
  AND a.opened_at >= $2 AND a.opened_at < $3
  AND tq.called_at IS NOT NULL
GROUP BY ta.color;

Количество пациентов, обслуженных за единицу времени

Цель: 0,5–2 в час → 1–4 в час.

-- Пропускная способность приёмного отделения по часам
SELECT
    date_trunc('hour', a.closed_at) AS hour,
    count(*)                        AS patients_completed
FROM appeals a
WHERE a.facility_id = $1
  AND a.closed_at >= $2 AND a.closed_at < $3
  AND a.status = 'closed'
GROUP BY 1
ORDER BY 1;

«Время ожидания» нужно определить однозначно до внедрения

[?] Запрос выше считает от opened_at (момент обращения) до called_at (вызов на оформление). Возможны и другие трактовки: до начала оказания помощи, до сортировки, для СМП-пациентов — от delivered_at или от accepted_at.

Разные определения дают разные числа при одной и той же работе, а показатель приёмочный. Определение должно быть согласовано с заказчиком и зафиксировано в частном ТЗ до начала измерений — иначе на приёмке возникнет спор о методике, а не о результате. См. R-7.

Пробелы и осознанные исключения

Что Статус
Учёт коечного фонда и занятости для решения по bed_requests [?] Источник данных о свободных местах не определён: собственный учёт в 3H или запрос в МИС. См. R-6
Хранение сканов документов (DocumentReference) [ПР] Файлы — во внешнем объектном хранилище, в БД только ссылка и хеш
ЭКГ как изображение (п. 21.18) [?] Зависит от ответа вендора — файл или текст. См. вопрос 6 в наборе данных
Расписания и слоты (Appointment, Schedule, Slot) Осознанно не хранятся: ведутся в МИС, ПАК их не использует
Назначения и направления Осознанно не хранятся: «система направлений и назначений работает в МИС»
Электронные рецепты (List) Осознанно не хранятся: вне контура ПАК