Речь пойдет о "расширениях конфигурации" и механизме "контроля несогласованных изменений".
Начиная с 8.3.6. появился новый механизм разработчиков "Расширения конфигурации".
Позволяет дорабатывать некоторые вещи, оставляя при этом конфигурацию типовой.
В данном примере мы будет дорабатывать форму документа.
Условная задача: клиент хочет на форме документа одновлеменно видеть 2 ед.изм. и пересчет между ними.
Тестировалось на "Управлении торговлей" ред 11.2 и ERP 2.1
Итак, берем типовую демо базу УТ 11.2 ( в моем случае 11.2.2.116), открываем конфигурацию.
Добавляем новое расширение (Конфигуратор - "Расширения конфигурации" - Добавить).
У нас открывается дополнительное окно конфигурации - если раскрыть дерево объектов, в нем ничего нет.
Возвращаемся в окно основной конфигурации добавляем объекты в наше расширение:
- документы - заказы клиентов - форма документа - пкм - добавить в расширение (см. скрин №1)
при этом в расширение так же добавляется все объекты на которые есть ссылки в форме,
Если нам нужен реквизит, а его нет в расширении, значит, реквизит не выведен на форму, и его нужно принудительно добавить в расширение (возвращаемся в основную конфигурацию - на реквизит - пкм - добавить в расширение.
Теперь у нас в дереве конфигурации расширения появилась форма документа Заказ клиента
Открываем форму, добавляем в реквизиты формы в табличную часть Товары 2 реквизита формы - "доп.ед.изм." и "кол-во доп.ед.изм." и привязываем к ним обработчики "При изменении".
(см. скрин №2)
Сохраняем, обновляем (F7) , запускаем 1С в режиме предприятия (я запускаю из конфигуратора по отладчику F5, так быстрее). Замечу, что при этом надо закрыть окно конфигурации расширения, иначе будет ругаться.
Заходим в Заказ клиента и пробуем изменить наши доп. реквизиты - получаем ошибку "Внутренняя ошибка подсистемы контроля несогласованных изменений."
(см. скрин №3)
Начинаем копать:
Происходит следующее
- "ПриСозданииНаСервере" и "ПриЧтенииНаСервере" вызывается
- процедура "ПриЧтенииСозданииНаСервере" из нее вызывается
- процедура "УстановитьДоступностьЭлементовПоСтатусуСервер" в ней вызывается
- процедура ОбщегоНазначенияУТ.УстановитьПодпискуНаСобытияИзмененияЭлементовФормы
И вот эта чудесная процедура делает следующее: она пробегается по объектам табличной части товары и если находит обработчик при изменении она его переопределяет на свой - в форме документа процедура "Подключаемый_ПриИзменении_УстановитьДоступностьЭлементовПоСтатусуСервер"
Теперь на все обрабочики "при изменении" будет вызываться именно эта процедура !
А что делает эта процедура - она вызывает следующую
"КонтрольНеСогласованныхИзмененийОбработатьСобытиеПриИзменении"
и вот эта процедура пробегается по списку объектов и обратно переназначает изначальные обработчики "при изменении", но только на тот список объектов который прописан в процедуре, все новые дают ошибку.
А происходит это, видимо, потому, что в процедуре "УстановитьДоступностьЭлементовПоСтатусуСервер" (см. 3 шаг выше) содержится строка
МассивЭлементов.Добавить("Товары;ПередНачаломДобавления,ПередУдалением")
и он обрабатывает все подчиненные объекты таблицы товары.
Как это обойти.
Если коротко, то после выполнения стандартных обработчиков мы переопределяем наши обработчики обратно
и удаляем из списка реквизитов контроля.
1) создаем процедуру переопределения
&НаСервере
Процедура Расш1_ПереопределитьОбработчикиПриИзменении()
Если СтруктураДействийКонтрольНеСогласованныхИзменений <> Неопределено Тогда
Если СтруктураДействийКонтрольНеСогласованныхИзменений.ПриИзменении.Свойство("ТоварыДопЕдИзм") Тогда
СтруктураДействийКонтрольНеСогласованныхИзменений.ПриИзменении.Удалить("ТоварыДопЕдИзм");
КонецЕсли;
Если СтруктураДействийКонтрольНеСогласованныхИзменений.ПриИзменении.Свойство("ТоварыКоличествоДопЕдИзм") Тогда
СтруктураДействийКонтрольНеСогласованныхИзменений.ПриИзменении.Удалить("ТоварыКоличествоДопЕдИзм");
КонецЕсли;
КонецЕсли;
Элементы.ТоварыДопЕдИзм .УстановитьДействие("ПриИзменении", "Расш1_ТоварыДопЕдИзмПриИзменении");
Элементы.ТоварыКоличествоДопЕдИзм.УстановитьДействие("ПриИзменении", "Расш1_ТоварыКоличествоДопЕдИзмПриИзменении");
КонецПроцедуры
2) подключаем вызов
- ПриСозданииНаСервере - после обработчика
&НаСервере
Процедура Расш1_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
УстановитьВыполнениеПослеОбработчиковСобытия("Расш1_ОбработчикСобытия_ПриСозданииНаСервере", Неопределено);
//после работы типового будет вызвана процедура а из нее переопределение обработчиков
КонецПроцедуры
&НаСервере
Процедура Расш1_ОбработчикСобытия_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка, ДополнительныйПараметр)
Расш1_ПереопределитьОбработчикиПриИзменении();
КонецПроцедуры
- ПриЧтенииНаСервере - перед обработчиком
&НаСервере
Процедура Расш1_ПриЧтенииНаСервере(ТекущийОбъект)
Расш1_ПереопределитьОбработчикиПриИзменении();
//ПриЧтенииНаСервере будем вызывать переопределение перед типовой обработкой
КонецПроцедуры
- ОбработкаОповещения - после обработчика
&НаКлиенте
Процедура Расш1_ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
УстановитьВыполнениеПослеОбработчиковСобытия("Расш1_ОбработчикСобытия_ОбработкаОповещения", Неопределено);
//после работы типового будет вызвана процедура а из нее переопределение обработчиков
КонецПроцедуры
&НаКлиенте
Процедура Расш1_ОбработчикСобытия_ОбработкаОповещения(ИмяСобытия, Параметр, Источник, ДополнительныйПараметр)
Расш1_ПереопределитьОбработчикиПриИзменении();
КонецПроцедуры
Пример расширения во вложении.