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