При доработке типовых конфигураций на платформе 1С:Предприятие 8 (таких как «Управление торговлей 11», «ERP Управление предприятием» или «Комплексная автоматизация») разработчики часто сталкиваются с неожиданным поведением системы. Одной из таких неочевидных проблем является аварийное завершение работы формы при изменении данных в добавленных реквизитах. Пользователь видит пугающее сообщение: «Внутренняя ошибка подсистемы контроля несогласованных изменений» с указанием на общий модуль ОбщегоНазначенияУТКлиент.
В этой статье мы подробно разберем, почему возникает эта ошибка, как устроен механизм защиты платформы от несогласованных изменений и какими способами можно корректно внедрить новый реквизит в документ, не нарушая логику типового решения.
Данная ошибка — это результат работы встроенного механизма защиты, предназначенного для контроля интерактивного ввода данных. В типовых конфигурациях 1С важную роль играет согласованность данных в зависимости от статуса документа (например, когда документ «Заказ поставщику» находится в статусе «Закрыт» или «К поступлению», редактирование определенных полей должно быть жестко ограничено).
Давайте проанализируем, как работает эта подсистема изнутри при открытии и изменении формы:
ПриСозданииНаСервере или ПриЧтенииНаСервере) система инициализирует настройки доступности элементов.УстановитьДоступностьЭлементовПоСтатусуСервер), который обращается к общему модулю: ОбщегоНазначенияУТ.УстановитьПодпискуНаСобытияИзмененияЭлементовФормы().Товары, ЭтапыГрафикаОплаты и т.д.).ПриИзменении, система временно «подменяет» или переопределяет его, привязывая к собственному служебному обработчику контроля изменений.Товары), но не зарегистрировали его в служебных структурах формы, подсистема безопасности расценивает это изменение как потенциальную угрозу согласованности данных («несогласованное изменение») и аварийно прерывает работу вызовом исключения.Для того чтобы обойти это ограничение, нам нужно либо зарегистрировать наш реквизит в структуре исключений контроля, либо временно исключить его из проверки при создании формы. Рассмотрим подробно, как это сделать.
Прежде чем вносить изменения в код, нам необходимо точно определить, какой именно общий модуль или процедура формы отвечает за контроль изменений в конкретном документе. Разберем по шагам, как это сделать с помощью конфигуратора:
ОбщегоНазначенияУТКлиент и перейдите к процедуре КонтрольНеСогласованныхИзмененийВызватьИсключение (в районе строки 850–860).
ВызватьИсключение НСтр("ru = 'Внутренняя ошибка подсистемы контроля несогласованных изменений.'");
Теперь, когда мы понимаем логику работы системы в конкретной точке вызова, выберем один из способов решения проблемы.
Если ваша база данных находится на поддержке и вы ведете разработку с использованием механизма расширений, этот способ является наиболее приоритетным. Он позволяет избежать изменения типового кода конфигурации, что значительно облегчит последующие обновления. При наличии нескольких информационных баз этот процесс можно автоматизировать, настроив автоматическое обновление конфигураций 1С в тихом режиме.
Суть метода заключается в том, чтобы перехватить создание формы на сервере, удалить наш добавленный реквизит из структуры контроля подсистемы безопасности и вручную назначить ему стандартный клиентский обработчик.
Рассмотрим пример реализации этого метода:
ФормаДокументаЗаказПоставщику) в ваше расширение.ПриСозданииНаСервере с аннотацией &После.
&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
// Проверяем, инициализирована ли структура контроля изменений на форме
Если ПеременнаяИмяСуществует("СтруктураДействийКонтрольНеСогласованныхИзменений") Тогда
// Замените "ТоварыМойНовыйРеквизит" на фактическое имя вашего элемента формы (колонки)
ИмяМоегоЭлемента = "ТоварыМойНовыйРеквизит";
Если СтруктураДействийКонтрольНеСогласованныхИзменений <> Неопределено Тогда
// Удаляем наш элемент из структуры контроля изменений при изменении
Если СтруктураДействийКонтрольНеСогласованныхИзменений.ПриИзменении.Свойство(ИмяМоегоЭлемента) Тогда
СтруктураДействийКонтрольНеСогласованныхИзменений.ПриИзменении.Удалить(ИмяМоегоЭлемента);
КонецЕсли;
КонецЕсли;
КонецЕсли;
// Вручную привязываем стандартный обработчик события "ПриИзменении" для нашего элемента
Элементы.ТоварыМойНовыйРеквизит.УстановитьДействие("ПриИзменении", "Расш1_ТоварыМойНовыйРеквизитПриИзменении");
КонецПроцедуры
Обратите внимание, что на клиенте в модуле формы расширения у вас должна быть определена процедура Расш1_ТоварыМойНовыйРеквизитПриИзменении, которая будет выполнять полезную работу при изменении значения в этой колонке:
&НаКлиенте
Процедура Расш1_ТоварыМойНовыйРеквизитПриИзменении(Элемент)
// Здесь располагается ваша логика обработки изменения реквизита
// Например, пересчет сумм, заполнение зависимых полей и т.д.
КонецПроцедуры
Этот способ элегантен тем, что мы обходим защиту только для одного конкретного элемента, оставляя всю остальную типовую логику контроля изменений нетронутой и полностью работоспособной.
Если вы вносите изменения непосредственно в основную конфигурацию (правила поддержки изменены на «Редактируется с сохранением поддержки»), то вам необходимо зарегистрировать ваш новый реквизит в модуле формы документа.
Проанализируем структуру модуля формы документа (например, Документ.ЗаказПоставщику.Форма.ФормаДокумента):
ЗаполнитьСтруктуруКонтроляНесогласованныхИзменений или инициализируется непосредственно в ПриСозданииНаСервере.
// Найдите место инициализации структуры контроля в модуле формы:
СтруктураДействийКонтрольНеСогласованныхИзменений.ПриИзменении.Вставить("ТоварыМойНовыйРеквизит", "ВашеДействиеПриИзменении");
Если в конфигурации используется более старая версия подсистемы, контроль может осуществляться через общие клиентские модули проверки. В таком случае, используя стек вызовов из Шага 1, найдите общий модуль, проверяющий имя измененного элемента (например, ОбщегоНазначенияУТКлиентПереопределяемый), и внесите имя вашего реквизита в список исключений:
// Пример модификации типового кода проверки в общем модуле
Если ИмяЭлемента = "ТоварыНовыйРеквизит" Тогда
// Разрешаем изменение элемента без вызова стандартного исключения подсистемы
Возврат;
КонецЕсли;
Для того чтобы в будущем минимизировать возникновение подобных ошибок при обновлении программных продуктов 1С, рекомендуем придерживаться следующих правил:
Использование описанных методов позволит вам успешно справиться с ошибкой подсистемы контроля изменений и обеспечит стабильную работу доработанного функционала в вашей конфигурации «1С:Управление торговлей». Для вывода дополнительных данных в табличные части без конфликтов с системой контроля можно использовать готовое расширение для добавления колонок с остатками товаров в заказы.