При разработке и доработке документов в платформе 1С:Предприятие 7.7 часто возникает типовая задача: пользователь выбирает позицию номенклатуры (материал или услугу), затем выбирает подчиненный элемент (партию материала), и программа должна автоматически заполнить сопутствующие колонки строки документа (цену, код партии, пересчитать сумму). Рассмотрим подробно, как правильно настроить связь между реквизитами, организовать выборку данных и обработать периодические значения.
Разберем распространенное заблуждение начинающих разработчиков: при выборе значения из справочника в поле документа помещается не строковое наименование или код, а ссылка на элемент справочника целиком. Даже если у подчиненного справочника отключен стандартный реквизит Наименование, выборка и хранение данных работают штатно, так как система оперирует ссылочным типом данных.
Когда в табличной части пользователь выбирает партию, реквизит строки Партия получает тип Справочник.ПартииМатериалов. Через эту ссылку разработчику доступны все реквизиты выбранного элемента: как стандартные (Код), так и пользовательские (Цена, СтавкаНДС и другие).
Для того чтобы при интерактивном выборе партии автоматически заполнялись остальные колонки строки, проанализируем настройку свойств колонки табличной части:
Партия.ПриВыбореПартии()).Теперь напишем код обработчика в модуле формы документа. Посмотрим на типовую реализацию процедуры:
Процедура ПриВыбореПартии()
// Проверяем, выбрана ли партия в текущей строке
Если ПустоеЗначение(Партия) = 0 Тогда
// Получаем периодический реквизит "Цена" на дату документа
Цена = Партия.Цена.Получить(ДатаДок);
// Автоматически пересчитываем сумму строки
Сумма = Количество * Цена;
Иначе
Цена = 0;
Сумма = 0;
КонецЕсли;
КонецПроцедуры
Выясним важную причину, почему нельзя просто написать Цена = Партия.Цена;. В платформе 1С 7.7 реквизиты справочников могут быть периодическими. Если обратиться к реквизиту напрямую через точку, система вернет значение на рабочую дату или дату ТА (точки актуальности), что приведет к ошибкам при вводе документов «задним числом» или будущей датой.
Для получения корректного значения периодического реквизита на дату оформления документа обязательно используем метод Получить():
// Получение значения цены партии строго на дату документа
АктуальнаяЦена = Партия.Цена.Получить(ДатаДок);
Если в конфигурации требуется детальный анализ истории изменения значения реквизита с учетом времени проведения, применяется системный объект Периодический.
Проанализируем задачу отображения реквизита Код партии в таблице документа. Создавать для этого отдельный реквизит табличной части документа в метаданных не требуется по следующим причинам:
Вместо создания реквизита документа добавим на форму табличной части текстовую колонку:
Партия.Код.В результате при выборе партии её код сразу отобразится на форме без необходимости дополнительного сохранения в базу данных.
Разберем по шагам логику защиты от некорректных действий пользователя. Если пользователь сначала выбрал материал и партию, а затем решил изменить материал, в строке останется неактуальная партия, принадлежащая старому материалу-владельцу. Чтобы исключить эту ситуацию, настроим обработчик для колонки Материал (или РаботаУслуга):
Процедура ПриВыбореМатериала()
// При смене материала принудительно очищаем подчиненные данные
Партия = ПолучитьПустоеЗначение("Справочник.ПартииМатериалов");
Цена = 0;
Сумма = 0;
КонецПроцедуры
Также рекомендуется проверять заполнение материала-владельца перед открытием формы выбора партии. Для этого задействуем предопределенную процедуру ПриНачалеВыбораЗначения в модуле формы документа:
Процедура ПриНачалеВыбораЗначения(ИдентРекв, ФлагСтандОбр)
Если ИдентРекв = "Партия" Тогда
Если ПустоеЗначение(Материал) = 1 Тогда
Предупреждение("Сначала необходимо выбрать материал/услугу!");
ФлагСтандОбр = 0; // Блокируем открытие формы выбора
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Таким образом, мы обеспечиваем корректность данных, исключаем выбор партий чужого материала и организуем автоматический пересчет цен и сумм при заполнении табличной части документа.