Как исправить ошибку «Внутренняя ошибка подсистемы контроля несогласованных изменений» в 1С:Управление торговлей?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей IT и автоматизация бизнеса
← На главную

При доработке типовых конфигураций на платформе 1С:Предприятие 8 (таких как «Управление торговлей 11», «ERP Управление предприятием» или «Комплексная автоматизация») разработчики часто сталкиваются с неожиданным поведением системы. Одной из таких неочевидных проблем является аварийное завершение работы формы при изменении данных в добавленных реквизитах. Пользователь видит пугающее сообщение: «Внутренняя ошибка подсистемы контроля несогласованных изменений» с указанием на общий модуль ОбщегоНазначенияУТКлиент.

В этой статье мы подробно разберем, почему возникает эта ошибка, как устроен механизм защиты платформы от несогласованных изменений и какими способами можно корректно внедрить новый реквизит в документ, не нарушая логику типового решения.

Почему возникает эта ошибка? Выясняем причину

Данная ошибка — это результат работы встроенного механизма защиты, предназначенного для контроля интерактивного ввода данных. В типовых конфигурациях 1С важную роль играет согласованность данных в зависимости от статуса документа (например, когда документ «Заказ поставщику» находится в статусе «Закрыт» или «К поступлению», редактирование определенных полей должно быть жестко ограничено).

Давайте проанализируем, как работает эта подсистема изнутри при открытии и изменении формы:

  1. При создании или чтении формы на сервере (в процедурах ПриСозданииНаСервере или ПриЧтенииНаСервере) система инициализирует настройки доступности элементов.
  2. Вызывается специализированный метод (например, УстановитьДоступностьЭлементовПоСтатусуСервер), который обращается к общему модулю: ОбщегоНазначенияУТ.УстановитьПодпискуНаСобытияИзмененияЭлементовФормы().
  3. Этот метод динамически обходит все элементы формы, включая колонки табличных частей (таких как Товары, ЭтапыГрафикаОплаты и т.д.).
  4. Если у элемента назначен стандартный обработчик события ПриИзменении, система временно «подменяет» или переопределяет его, привязывая к собственному служебному обработчику контроля изменений.
  5. Когда пользователь редактирует значение в этой колонке на клиенте, управление сначала передается в этот служебный обработчик. Он сверяет имя изменившегося элемента по жестко зафиксированному списку разрешенных реквизитов формы.
  6. Поскольку вы добавили новый реквизит (например, новую колонку в табличную часть Товары), но не зарегистрировали его в служебных структурах формы, подсистема безопасности расценивает это изменение как потенциальную угрозу согласованности данных («несогласованное изменение») и аварийно прерывает работу вызовом исключения.

Для того чтобы обойти это ограничение, нам нужно либо зарегистрировать наш реквизит в структуре исключений контроля, либо временно исключить его из проверки при создании формы. Рассмотрим подробно, как это сделать.

Шаг 1. Локализуем проблему с помощью отладчика

Прежде чем вносить изменения в код, нам необходимо точно определить, какой именно общий модуль или процедура формы отвечает за контроль изменений в конкретном документе. Разберем по шагам, как это сделать с помощью конфигуратора:

  1. Откройте конфигуратор вашей базы данных и запустите сеанс отладки.
  2. Найдите общий модуль ОбщегоНазначенияУТКлиент и перейдите к процедуре КонтрольНеСогласованныхИзмененийВызватьИсключение (в районе строки 850–860).
  3. Установите точку останова (клавиша F9) на строке с вызовом исключения:
    
    ВызватьИсключение НСтр("ru = 'Внутренняя ошибка подсистемы контроля несогласованных изменений.'");
    
  4. Перейдите в режим «1С:Предприятие», откройте ваш документ (например, «Заказ поставщику») и измените значение в вашем новом реквизите.
  5. Система остановится на точке останова. Теперь откройте панель «Стек вызовов» (Call Stack).
  6. Дважды кликните по предыдущей строке в стеке вызовов (на один уровень выше). Вы попадете в процедуру-распределитель, которая вызвала это исключение. Обычно это процедура контроля изменений конкретной формы или общий модуль, обрабатывающий интерактивные действия. Здесь вы сможете увидеть структуру или массив элементов, которые система ожидала проверить.

Теперь, когда мы понимаем логику работы системы в конкретной точке вызова, выберем один из способов решения проблемы.

Решение 1. Безопасное добавление через расширение конфигурации (Рекомендуемое)

Если ваша база данных находится на поддержке и вы ведете разработку с использованием механизма расширений, этот способ является наиболее приоритетным. Он позволяет избежать изменения типового кода конфигурации, что значительно облегчит последующие обновления. При наличии нескольких информационных баз этот процесс можно автоматизировать, настроив автоматическое обновление конфигураций 1С в тихом режиме.

Суть метода заключается в том, чтобы перехватить создание формы на сервере, удалить наш добавленный реквизит из структуры контроля подсистемы безопасности и вручную назначить ему стандартный клиентский обработчик.

Рассмотрим пример реализации этого метода:

  1. Добавьте форму документа (например, ФормаДокументаЗаказПоставщику) в ваше расширение.
  2. Создайте для этой формы обработчик события ПриСозданииНаСервере с аннотацией &После.
  3. Пропишите в теле процедуры следующий код, который исключит ваш реквизит из контроля:

&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
    
    // Проверяем, инициализирована ли структура контроля изменений на форме
    Если ПеременнаяИмяСуществует("СтруктураДействийКонтрольНеСогласованныхИзменений") Тогда
        
        // Замените "ТоварыМойНовыйРеквизит" на фактическое имя вашего элемента формы (колонки)
        ИмяМоегоЭлемента = "ТоварыМойНовыйРеквизит";
        
        Если СтруктураДействийКонтрольНеСогласованныхИзменений <> Неопределено Тогда
            
            // Удаляем наш элемент из структуры контроля изменений при изменении
            Если СтруктураДействийКонтрольНеСогласованныхИзменений.ПриИзменении.Свойство(ИмяМоегоЭлемента) Тогда
                СтруктураДействийКонтрольНеСогласованныхИзменений.ПриИзменении.Удалить(ИмяМоегоЭлемента);
            КонецЕсли;
            
        КонецЕсли;
        
    КонецЕсли;
    
    // Вручную привязываем стандартный обработчик события "ПриИзменении" для нашего элемента
    Элементы.ТоварыМойНовыйРеквизит.УстановитьДействие("ПриИзменении", "Расш1_ТоварыМойНовыйРеквизитПриИзменении");
    
КонецПроцедуры

Обратите внимание, что на клиенте в модуле формы расширения у вас должна быть определена процедура Расш1_ТоварыМойНовыйРеквизитПриИзменении, которая будет выполнять полезную работу при изменении значения в этой колонке:


&НаКлиенте
Процедура Расш1_ТоварыМойНовыйРеквизитПриИзменении(Элемент)
    // Здесь располагается ваша логика обработки изменения реквизита
    // Например, пересчет сумм, заполнение зависимых полей и т.д.
КонецПроцедуры

Этот способ элегантен тем, что мы обходим защиту только для одного конкретного элемента, оставляя всю остальную типовую логику контроля изменений нетронутой и полностью работоспособной.

Решение 2. Изменение логики в основной конфигурации (если конфигурация снята с поддержки)

Если вы вносите изменения непосредственно в основную конфигурацию (правила поддержки изменены на «Редактируется с сохранением поддержки»), то вам необходимо зарегистрировать ваш новый реквизит в модуле формы документа.

Проанализируем структуру модуля формы документа (например, Документ.ЗаказПоставщику.Форма.ФормаДокумента):

  1. Найдите в модуле формы процедуру, которая заполняет структуру контролируемых реквизитов. Обычно она называется ЗаполнитьСтруктуруКонтроляНесогласованныхИзменений или инициализируется непосредственно в ПриСозданииНаСервере.
  2. В этой процедуре создается структура соответствий, где ключами выступают имена элементов формы, а значениями — выполняемые действия.
  3. Добавьте ваш реквизит в эту структуру. Пример добавления кода:

// Найдите место инициализации структуры контроля в модуле формы:
СтруктураДействийКонтрольНеСогласованныхИзменений.ПриИзменении.Вставить("ТоварыМойНовыйРеквизит", "ВашеДействиеПриИзменении");

Если в конфигурации используется более старая версия подсистемы, контроль может осуществляться через общие клиентские модули проверки. В таком случае, используя стек вызовов из Шага 1, найдите общий модуль, проверяющий имя измененного элемента (например, ОбщегоНазначенияУТКлиентПереопределяемый), и внесите имя вашего реквизита в список исключений:


// Пример модификации типового кода проверки в общем модуле
Если ИмяЭлемента = "ТоварыНовыйРеквизит" Тогда
    // Разрешаем изменение элемента без вызова стандартного исключения подсистемы
    Возврат; 
КонецЕсли;

Рекомендации по разработке в типовых конфигурациях

Для того чтобы в будущем минимизировать возникновение подобных ошибок при обновлении программных продуктов 1С, рекомендуем придерживаться следующих правил:

Использование описанных методов позволит вам успешно справиться с ошибкой подсистемы контроля изменений и обеспечит стабильную работу доработанного функционала в вашей конфигурации «1С:Управление торговлей». Для вывода дополнительных данных в табличные части без конфликтов с системой контроля можно использовать готовое расширение для добавления колонок с остатками товаров в заказы.

← На главную