Как реализовать автоматический перенос данных из «Записи на прием» в «Прием» в 1С 8.3

Программист 1С v8.3 (Управляемые формы) Сфера услуг, туризм и социальный сектор
← На главную

В медицинской практике и других сферах услуг часто возникает задача связать два документа: предварительную регистрацию (запись) и фактическое оказание услуги (прием). Основная сложность для начинающего разработчика 1С заключается в том, чтобы данные, введенные пользователем ранее (например, жалобы пациента), автоматически «подтягивались» в новый документ при выборе пациента. Рассмотрим подробно, как реализовать этот функционал несколькими способами, используя стандартные механизмы платформы 1С:Предприятие 8.3.

Метод 1: Механизм «Ввод на основании»

Разберем самый правильный с точки зрения архитектуры 1С способ — использование стандартного механизма ввода на основании. Это позволяет врачу не создавать документ Прием вручную, а нажать кнопку «Создать на основании» прямо в документе ЗаписьНаПрием.

Проанализируем шаги настройки в Конфигураторе:

  1. Откроем свойства документа Прием.
  2. Перейдем на закладку «Ввод на основании».
  3. В списке «Является основанием для» выберем документ ЗаписьНаПрием (или наоборот, в документе Прием укажем ЗаписьНаПрием в списке «Вводится на основании»).
  4. Нажмем кнопку «Конструктор ввода на основании».

В открывшемся окне мы сопоставим поля. Однако для переноса табличной части Жалобы потребуется ручная корректировка кода в модуле объекта. Разберем пример кода, который автоматически сформирует система в процедуре ОбработкаЗаполнения:


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
    Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ЗаписьНаПрием") Тогда
        // Заполняем основные реквизиты
        ЭтотОбъект.Пациент = ДанныеЗаполнения.Пациент;
        ЭтотОбъект.ДатаПриема = ДанныеЗаполнения.ДатаЗаписи;
        
        // Очищаем текущую табличную часть перед заполнением
        ЭтотОбъект.Жалобы.Очистить();
        
        // Циклом переносим строки из документа-основания
        Для Каждого СтрокаИзОснования Из ДанныеЗаполнения.Жалобы Цикл
            НоваяСтрока = ЭтотОбъект.Жалобы.Добавить();
            ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаИзОснования);
        КонецЦикла;
    КонецЕсли;
КонецПроцедуры

Использование метода ЗаполнитьЗначенияСвойств позволяет автоматически скопировать данные из колонок с одинаковыми именами, что значительно упрощает код. Этот метод идеален, если структуры табличных частей в обоих документах идентичны.

Метод 2: Автозаполнение при выборе пациента (Событие «ПриИзменении»)

Рассмотрим ситуацию, которую описывал автор темы: Гл. врач открывает пустой документ Прием, выбирает пациента, и в этот момент должны появиться его жалобы из последней записи. Здесь нам потребуется работа с формой документа и серверный вызов.

Выясним логику работы: при изменении реквизита Пациент программа должна найти в базе данных актуальный документ ЗаписьНаПрием для этого человека и скопировать оттуда данные. Посмотрим, как это реализуется программно.

Шаг 1. Обработчик на клиенте

В модуле формы документа Прием создадим событие для поля выбора пациента:


&НаКлиенте
Процедура ПациентПриИзменении(Элемент)
    // Вызываем серверную функцию для поиска данных
    Если ЗначениеЗаполнено(Объект.Пациент) Тогда
        ЗаполнитьЖалобыНаСервере();
    КонецЕсли;
КонецПроцедуры

Шаг 2. Поиск данных на сервере

Проанализируем, как эффективно найти нужный документ. Лучше всего использовать Запрос, чтобы ограничить выборку только актуальными записями (например, за сегодняшнее число).


&НаСервере
Процедура ЗаполнитьЖалобыНаСервере()
    
    // Очищаем таблицу перед новым поиском
    Объект.Жалобы.Очистить();
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 1
        |    ЗаписьНаПриемЖалобы.Жалоба,
        |    ЗаписьНаПриемЖалобы.Подробности
        |ИЗ
        |    Документ.ЗаписьНаПрием.Жалобы КАК ЗаписьНаПриемЖалобы
        |ГДЕ
        |    ЗаписьНаПриемЖалобы.Ссылка.Пациент = &Пациент
        |    И ЗаписьНаПриемЖалобы.Ссылка.Проведен = ИСТИНА
        |УПОРЯДОЧИТЬ ПО
        |    ЗаписьНаПриемЖалобы.Ссылка.Дата УБЫВ";
    
    Запрос.УстановитьПараметр("Пациент", Объект.Пациент);
    
    РезультатЗапроса = Запрос.Выполнить();
    
    Если Не РезультатЗапроса.Пустой() Тогда
        Выборка = РезультатЗапроса.Выбрать();
        Пока Выборка.Следующий() Цикл
            НоваяСтрока = Объект.Жалобы.Добавить();
            НоваяСтрока.Жалоба = Выборка.Жалоба;
            НоваяСтрока.Подробности = Выборка.Подробности;
        КонецЦикла;
    КонецЕсли;
    
КонецПроцедуры

Обратите внимание на использование конструкции ПЕРВЫЕ 1 и УПОРЯДОЧИТЬ ПО Ссылка.Дата УБЫВ. Это позволяет нам всегда получать самую свежую запись пациента, игнорируя старые обращения.

Важные технические нюансы

Разберем несколько критически важных моментов, о которых часто забывают новички:

  1. Очистка табличной части: Всегда вызывайте метод Объект.Жалобы.Очистить() перед началом заполнения. Если врач сначала выберет одного пациента, а потом передумает и выберет другого, без очистки жалобы обоих пациентов смешаются в одном документе.
  2. Права доступа: Убедитесь, что у роли Гл. врача есть право на «Чтение» и «Просмотр» документа ЗаписьНаПрием. Если прав нет, запрос на сервере вернет пустой результат, и данные не перенесутся, при этом система не выдаст ошибки.
  3. Типизация: Если в табличной части используются ссылки на справочники (например, справочник ВидыЖалоб), убедитесь, что в обоих документах колонки имеют одинаковый тип данных.

Контекст «Билета №9»

В обсуждении упоминался «Билет №9». Это одна из стандартных задач экзамена «1С:Специалист по платформе». Она учит разработчика не только переносить данные, но и контролировать состояние объектов. В расширенной версии этой задачи часто требуется проверять, не был ли на основании данной записи уже создан прием ранее. Для этого в документе ЗаписьНаПрием можно завести признак (реквизит) ПриемОсуществлен или проверять наличие ссылок в критериях отбора.

Рассмотрим, как можно дополнить наш запрос проверкой на уникальность:


// Добавляем условие, чтобы не подтягивать записи, по которым уже был прием
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1...
    |ГДЕ Ссылка.Пациент = &Пациент 
    |И Ссылка НЕ В (ВЫБРАТЬ ДокументОснование ИЗ Документ.Прием ГДЕ ДокументОснование ССЫЛКА Документ.ЗаписьНаПрием)";

Таким образом, мы исключим дублирование документов и поможем пользователю избежать ошибок в учете.

Проанализировав данные методы, мы видим, что наиболее надежным является Ввод на основании, так как он сохраняет явную связь между документами в системе. Однако метод с обработкой события ПриИзменении более гибок для оперативной работы пользователя в интерфейсе.

← На главную