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