В медицинской практике и других сферах услуг часто возникает задача связать два документа: предварительную регистрацию (запись) и фактическое оказание услуги (прием). Основная сложность для начинающего разработчика 1С заключается в том, чтобы данные, введенные пользователем ранее (например, жалобы пациента), автоматически «подтягивались» в новый документ при выборе пациента. Рассмотрим подробно, как реализовать этот функционал несколькими способами, используя стандартные механизмы платформы 1С:Предприятие 8.3.
Разберем самый правильный с точки зрения архитектуры 1С способ — использование стандартного механизма ввода на основании. Это позволяет врачу не создавать документ Прием вручную, а нажать кнопку «Создать на основании» прямо в документе ЗаписьНаПрием.
Проанализируем шаги настройки в Конфигураторе:
Прием.ЗаписьНаПрием (или наоборот, в документе Прием укажем ЗаписьНаПрием в списке «Вводится на основании»).В открывшемся окне мы сопоставим поля. Однако для переноса табличной части Жалобы потребуется ручная корректировка кода в модуле объекта. Разберем пример кода, который автоматически сформирует система в процедуре ОбработкаЗаполнения:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ЗаписьНаПрием") Тогда
// Заполняем основные реквизиты
ЭтотОбъект.Пациент = ДанныеЗаполнения.Пациент;
ЭтотОбъект.ДатаПриема = ДанныеЗаполнения.ДатаЗаписи;
// Очищаем текущую табличную часть перед заполнением
ЭтотОбъект.Жалобы.Очистить();
// Циклом переносим строки из документа-основания
Для Каждого СтрокаИзОснования Из ДанныеЗаполнения.Жалобы Цикл
НоваяСтрока = ЭтотОбъект.Жалобы.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаИзОснования);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Использование метода ЗаполнитьЗначенияСвойств позволяет автоматически скопировать данные из колонок с одинаковыми именами, что значительно упрощает код. Этот метод идеален, если структуры табличных частей в обоих документах идентичны.
Рассмотрим ситуацию, которую описывал автор темы: Гл. врач открывает пустой документ Прием, выбирает пациента, и в этот момент должны появиться его жалобы из последней записи. Здесь нам потребуется работа с формой документа и серверный вызов.
Выясним логику работы: при изменении реквизита Пациент программа должна найти в базе данных актуальный документ ЗаписьНаПрием для этого человека и скопировать оттуда данные. Посмотрим, как это реализуется программно.
Шаг 1. Обработчик на клиенте
В модуле формы документа Прием создадим событие для поля выбора пациента:
&НаКлиенте
Процедура ПациентПриИзменении(Элемент)
// Вызываем серверную функцию для поиска данных
Если ЗначениеЗаполнено(Объект.Пациент) Тогда
ЗаполнитьЖалобыНаСервере();
КонецЕсли;
КонецПроцедуры
Шаг 2. Поиск данных на сервере
Проанализируем, как эффективно найти нужный документ. Лучше всего использовать Запрос, чтобы ограничить выборку только актуальными записями (например, за сегодняшнее число).
&НаСервере
Процедура ЗаполнитьЖалобыНаСервере()
// Очищаем таблицу перед новым поиском
Объект.Жалобы.Очистить();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 1
| ЗаписьНаПриемЖалобы.Жалоба,
| ЗаписьНаПриемЖалобы.Подробности
|ИЗ
| Документ.ЗаписьНаПрием.Жалобы КАК ЗаписьНаПриемЖалобы
|ГДЕ
| ЗаписьНаПриемЖалобы.Ссылка.Пациент = &Пациент
| И ЗаписьНаПриемЖалобы.Ссылка.Проведен = ИСТИНА
|УПОРЯДОЧИТЬ ПО
| ЗаписьНаПриемЖалобы.Ссылка.Дата УБЫВ";
Запрос.УстановитьПараметр("Пациент", Объект.Пациент);
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
НоваяСтрока = Объект.Жалобы.Добавить();
НоваяСтрока.Жалоба = Выборка.Жалоба;
НоваяСтрока.Подробности = Выборка.Подробности;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Обратите внимание на использование конструкции ПЕРВЫЕ 1 и УПОРЯДОЧИТЬ ПО Ссылка.Дата УБЫВ. Это позволяет нам всегда получать самую свежую запись пациента, игнорируя старые обращения.
Разберем несколько критически важных моментов, о которых часто забывают новички:
Объект.Жалобы.Очистить() перед началом заполнения. Если врач сначала выберет одного пациента, а потом передумает и выберет другого, без очистки жалобы обоих пациентов смешаются в одном документе.ЗаписьНаПрием. Если прав нет, запрос на сервере вернет пустой результат, и данные не перенесутся, при этом система не выдаст ошибки.ВидыЖалоб), убедитесь, что в обоих документах колонки имеют одинаковый тип данных.В обсуждении упоминался «Билет №9». Это одна из стандартных задач экзамена «1С:Специалист по платформе». Она учит разработчика не только переносить данные, но и контролировать состояние объектов. В расширенной версии этой задачи часто требуется проверять, не был ли на основании данной записи уже создан прием ранее. Для этого в документе ЗаписьНаПрием можно завести признак (реквизит) ПриемОсуществлен или проверять наличие ссылок в критериях отбора.
Рассмотрим, как можно дополнить наш запрос проверкой на уникальность:
// Добавляем условие, чтобы не подтягивать записи, по которым уже был прием
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1...
|ГДЕ Ссылка.Пациент = &Пациент
|И Ссылка НЕ В (ВЫБРАТЬ ДокументОснование ИЗ Документ.Прием ГДЕ ДокументОснование ССЫЛКА Документ.ЗаписьНаПрием)";
Таким образом, мы исключим дублирование документов и поможем пользователю избежать ошибок в учете.
Проанализировав данные методы, мы видим, что наиболее надежным является Ввод на основании, так как он сохраняет явную связь между документами в системе. Однако метод с обработкой события ПриИзменении более гибок для оперативной работы пользователя в интерфейсе.