В этой статье я поделюсь нашим опытом настройки в медицинской информационной системе формирования структурированного электронного документа «Санаторно-курортная карта» (форма 072/у) в формате CDA (Редакция 1). Материал будет полезен коллегам, которые внедряют электронный документооборот с РЭМД и хотят избежать типичных ошибок при конфигурации типов действий, справочников и связки с лабораторными/инструментальными исследованиями.
1. Зачем вообще понадобилась эта карта
Санаторно-курортная карта (форма 072/у, утверждённая приказом Минздрава России от 15.12.2014 № 834н) – это документ, который выдается пациенту при направлении на санаторно-курортное лечение. Без неё путевка недействительна. В бумажном виде – сплошная головная боль: заполнять несколько страниц, потом обратный талон должен вернуться из санатория. Мы решили перевести этот процесс в электронный вид и передавать CDA-документ в РЭМД.
Руководство по реализации CDA для этого документа имеет OID шаблона 1.2.643.5.1.13.13.14.48.9.1 (Редакция 1). Код документа – 48 по классификатору «Виды медицинской документации». В карте есть две основные части: собственно санаторно-курортная карта (заполняется в поликлинике) и обратный талон (заполняется в санатории). В нашей МИС мы формируем только первую часть – направляющую. Обратный талон – это отдельный CDA (мы его настраивали ранее).
2. Что мы сделали в типе действия
Создали тип действия с плоским кодом CARD_SANATOR. В настройках указали:
- Код для отчётов –
OtherDocuments. - Вид услуги –
Прочее. - Идентификация по справочнику CDA –
1.2.643.2.69.1.1.1.195.Cdaс идентификатором (уточняйте в своём классификаторе, у нас это было значение для санаторно-курортной карты). - Идентификация по справочнику МИС –
n3.medDocumentType.Cda(чтобы система понимала, что это CDA).
2.1. Свойства типа действия (секции CDA)
Мы добавили в тип действия следующие свойства и для каждого указали параметр «Секция CDA» согласно таблице из руководства:
| Название свойства | Код секции | Обязательность | Тип | Примечание |
|---|---|---|---|---|
| Номер санаторно-курортной карты | NUMBER_CARD | 1 | String | |
| Имеет право на получение набора социальных услуг | SOC_PRIV | 0 | Boolean | Если true – появляются поля климата, факторов, документов |
| Климат в месте проживания | CLIMAT | 0 | Справочник | Справочник 1.2.643.5.1.13.13.99.2.685 |
| Климатические факторы в месте проживания | CL_FACTOR | 0 | Справочник | Справочник 1.2.643.5.1.13.13.99.2.684 |
| Необходимость сопровождения пациента | ESCORT | 0 | Boolean | |
| Жалобы | COMP | 1 | Text | |
| Анамнез заболевания | ANAM | 1 | Text | |
| Название санаторно-курортной организации | SANATOR_NAME | 1 | String | |
| Рекомендовано лечение в условиях пребывания в санатории | REGIME | 0 | Boolean | Если true – стационарное лечение, иначе амбулаторное |
| Продолжительность курса лечения (дней) | DURATION | 1 | Integer | |
| Номер путевки | NUMBER_PUT | 1 | String |
Важно: Для свойств CLIMAT и CL_FACTOR мы настроили выпадающие списки в соответствии с федеральными справочниками. Без этого CDA не пройдёт контроль в РЭМД.
2.2. Идентификатор документа и счётчик
Как обычно, настроили свойство «Идентификатор документа» со счётчиком CDA_ID. В XML-шаблоне этот идентификатор используется в элементах <id root="...51" extension="..."/> и <setId root="...50" extension="..."/>.
3. Связанные исследования: лаборатория и инструментальная диагностика
Одно из ключевых требований – в санаторно-курортной карте должны быть перечислены результаты клинических, лабораторных и инструментальных исследований, которые обосновывают направление на лечение. Мы реализовали автоматический поиск таких документов в текущем случае обслуживания (event).
В HTML-шаблоне (который формирует PDF и вызывает генерацию XML) мы написали логику:
{: lab_list = [x for x in event.actions if x.status == 2 and x.serviceType == 10 and (x.flatCode == 'OtherDocuments:LI' or x.flatCode == 'OAK' or x.flatCode == 'OAM')]}
{: instr_list = [x for x in event.actions if x.status == 2 and (x.flatCode == 'OtherDocuments:II' or (x.serviceType == 5 and x.identify('urn:oid:1.2.643.2.69.1.1.1.195.Cda') == '148'))]}
Что мы здесь сделали:
- Берём только завершённые действия (
status == 2). - Для лабораторных исследований ищем плоские коды
OtherDocuments:LI,OAK(общий анализ крови),OAM(общий анализ мочи) или тип услуги 10 (лаборатория). - Для инструментальных –
OtherDocuments:IIили тип услуги 5 с идентификатором CDA 148 (у нас это протокол инструментального исследования).
В секции «Связанные документы» (LINKDOCS) мы выводим эти исследования в читаемом виде и для каждого создаём элемент <entry> с внешней ссылкой (<externalDocument>). Это позволяет РЭМД установить связь между документами.
4. Работа с льготниками (SOC_PRIV)
Если у пациента есть право на получение набора социальных услуг (флаг SOC_PRIV == True), в карте появляются дополнительные поля:
- климат и климатические факторы в месте проживания (обязательные),
- документ, удостоверяющий право на льготу (серия, номер, дата выдачи),
- код льготной категории.
Данные о льготе мы берём из социального статуса пациента (client.socStatuses). В рег. карте пациента у нас есть отдельная вкладка «Соц. статус», где для статусов с признаком «льгота» заполняются реквизиты документа. В шаблоне мы их подставляем:
{if: len(client.socStatuses) > 0}
{for: status in client.socStatuses}
{if: status.classes == u'льгота'}
{: L_SERIES = status.document.serial}
{: L_NUMBER = status.document.number}
{: L_DATE = status.document.date}
{: L_NAME = status.name}
{: L_CODE = status.code}
{end:}
{end:}
{end:}
Обратите внимание: код льготы (L_CODE) мы маппим в коды справочника 1.2.643.5.1.13.13.99.2.713 (Сопоставление кодов льгот с льготными категориями). В XML мы передаём не текст, а код (1 – инвалиды войны, 2 – участники ВОВ, 3 – ветераны боевых действий, 8 – инвалиды, 9 – дети-инвалиды).
5. Диагнозы и МКБ
В карте указываются:
- основной диагноз (тип
1или2в статистическом талоне), - сопутствующие (тип
9).
В XML-шаблоне мы формируем секцию DGN с подробным описанием каждого диагноза: текстовое описание и код МКБ-10 (справочник 1.2.643.5.1.13.13.11.1005). Для основного диагноза обязательно указываем код поля 9029, для сопутствующих – 9012.
6. Проверки заполнения – чтобы документ не ушёл в РЭМД с ошибками
Мы добавили в HTML-шаблон блок проверок. Если какое-то обязательное поле не заполнено, пользователь увидит сообщение, а формирование документа прервётся. Вот ключевые проверки:
- СНИЛС пациента –
if: not client.SNILS - Номер полиса ОМС –
if: not client.compulsoryPolicy.number - Адрес регистрации по КЛАДР –
if: not client.regAddress.KLADRCode - СНИЛС исполнителя (врача, заполнившего карту) –
if: not action.person.SNILS - Идентификация должности исполнителя –
if: not action.person.post.identify('urn:oid:1.2.643.5.1.13.13.11.1002') - Состояние документа –
Закончено(action.status != 2) - Наличие основного/заключительного диагноза –
if: not main_diag(и не более одного) - Если
SOC_PRIV == True– проверяемCLIMAT,CL_FACTOR, серию/номер/дату документа льготы. - Обязательные свойства с
penalty > 0– проверяем на пустоту (с учётом типа поля). - Наличие хотя бы одного лабораторного или инструментального исследования –
if: not lab_list and not instr_list. Это требование логики, а не формальной валидации, но мы его добавили, чтобы карта не была пустой.
7. Формирование регионального идентификатора пациента
Как и для других CDA, нам нужен глобальный идентификатор пациента (MPI). В конце HTML-шаблона мы вызываем:
{: from library.Utils import forceString}
{: clientGlobalIdNetrika = readUrl("http://"+forceString(dbServerName)+"/extendedmse/api?fromtemplate=1&clientid="+forceString(client.id), timeout=50)}
Для Санкт-Петербурга (код КЛАДР 78) мы формируем идентификатор по особому правилу: {OID_MDR308[26:]}.17.1.{client.id}. В остальных случаях – через сервис extendedmse. Не забудьте проверить, что в глобальных настройках есть ExtendedMseUrl и в конфигурации ИЭМК прописаны gDefaultMpiUrl и gMpiToken.
8. Вызов генерации XML
В том же HTML-шаблоне, после всех проверок и до закрывающих тегов, мы добавляем:
{: addSupplement('xml', '\n'.join(line for line in formatByTemplate('CDA_CARD_SANATOR', 'CDA').split('\n') if line.strip() != '')) }
Этот вызов создаёт XML-дополнение (файл, который будет отправлен в РЭМД) на основе шаблона CDA_CARD_SANATOR в контексте CDA. Обратите внимание, что мы убираем пустые строки – это экономит место и упрощает валидацию.
9. На что ещё обратить внимание
9.1. Справочники
- Организация (
MDR308) – обязательна. У нас настроена идентификация и для головной организации, и для структурного подразделения (поликлиники). - Должности – справочник
1.2.643.5.1.13.13.11.1002, версия 7.6. Убедитесь, что у врача, заполняющего карту, должность имеет код из этого справочника. - Типы документов (ДУЛ) – двойная идентификация: OID
1.2.643.5.1.13.13.99.2.48(код) и...48*(наименование), версия 7.1.
9.2. Адрес регистрации по КЛАДР
В XML мы передаём код субъекта РФ (address:stateCode) на основе первых двух символов КЛАДР. Если адрес не заполнен или не соответствует КЛАДР, документ не пройдёт валидацию. У нас это одна из самых частых ошибок – поэтому мы вывели проверку client.regAddress.KLADRCode.
9.3. Обратный талон – отдельная история
Мы не формируем обратный талон в этой карте – это отдельный тип действия и отдельный CDA. В санаторно-курортной карте только прямые поля, обратный талон будет создаваться в санатории и присылаться обратно.
9.4. Идентификатор документа для связанных исследований
В секции LINKDOCS мы ссылаемся на внешние документы по их идентификатору (lab[u'Идентификатор документа']). Убедитесь, что у лабораторных и инструментальных протоколов настроено свойство «Идентификатор документа» и оно заполняется автоматически счётчиком.
10. Заключение
Настройка CDA «Санаторно-курортная карта» оказалась не такой сложной, как лабораторный протокол, но потребовала внимания к деталям: правильная привязка секций, учёт льготных категорий, автоматический подбор связанных исследований и проверка адреса по КЛАДР. Мы потратили несколько дней на отладку справочников и проверок, но в итоге документ успешно проходит валидацию в РЭМД.
Если вы только начинаете внедрять этот CDA – советую начать с макета (HTML) и проверить все обязательные поля на тестовом пациенте. А уже потом переносить логику в продуктив. Удачи!


