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