При доработке типовых конфигураций, таких как 1С:Управление производственным предприятием (УПП), программисты часто сталкиваются с неприятной ситуацией: в стандартный документ добавляется новая табличная часть, программно заполняется, но после вызова метода Записать() данные из этой таблицы бесследно исчезают. При этом стандартные табличные части (например, Товары) сохраняются корректно.
В этой статье мы подробно разберем, почему так происходит, изучим внутренние механизмы УПП и научимся находить «виновника» очистки данных с помощью отладчика.
Рассмотрим типичный сценарий. Вы добавили в документ (например, «Реализация товаров и услуг») табличную часть Отклонения. В коде обработки заполнения вы обращаетесь к объекту и добавляете строки:
НоваяСтрока = Объект.Отклонения.Добавить();
НоваяСтрока.Номенклатура = ВыбраннаяНоменклатура;
НоваяСтрока.Количество = 10;
// В отладчике на этом этапе Объект.Отклонения содержит данные
Объект.Записать(РежимЗаписиДокумента.Запись);
// После этой строки Объект.Отклонения становится пустым
Проблема заключается в том, что УПП — это конфигурация с очень жесткой архитектурой. В модулях объектов типовых документов прописано огромное количество проверок и процедур автоматического заполнения, которые срабатывают в событии ПередЗаписью. Если ваша новая табличная часть не «зарегистрирована» в этих внутренних механизмах, система может посчитать её лишней или временной и просто очистить перед тем, как данные попадут в базу данных.
Проанализируем программный код модуля документа. В большинстве документов УПП процедура ПередЗаписью содержит вызовы общих процедур из модулей ОбщегоНазначения, ЗаполнениеДокументов или РаботаСДиалогами.
Выясним причину: в типовых решениях часто реализован механизм «санитарной» обработки. Система проходит циклом по всем табличным частям, которые она «знает» (которые прописаны в программном коде как обязательные), а остальные либо игнорирует, либо принудительно обнуляет, чтобы избежать хранения неконсистентных данных. Особенно часто это встречается в процедурах типа ЗаполнитьТабличныеЧасти() или СброситьДанныеТабличныхЧастей().
В УПП при записи документа активно используется структура ДополнительныеСвойства. Если документ записывается из формы, в эту структуру могут передаваться флаги, управляющие перезаполнением таблиц. При программной записи из обработки (как в нашем примере) эти флаги могут отсутствовать, что заставляет систему выполнять «полную очистку и перезаполнение» по умолчанию. Если ваша ТЧ не включена в алгоритм перезаполнения, она останется пустой.
Чтобы не гадать, в какой из сотен процедур пропадают данные, воспользуемся механизмом отладки. Проделаем следующие шаги:
ПередЗаписью.ЭтотОбъект.МояТабличнаяЧасть.Количество().Совет: Если процедур слишком много, можно поставить точку останова с условием. Нажмите правой кнопкой мыши на точку останова, выберите «Условие» и напишите: ЭтотОбъект.МояТабличнаяЧасть.Количество() = 0. Это позволит «поймать» момент сразу после очистки.
После того как мы выяснили, где именно очищаются данные, рассмотрим способы исправления ситуации:
Если вы нашли процедуру, которая очищает таблицы (например, цикл по метаданным или жесткий список ТЧ), вам нужно добавить имя своей табличной части в список исключений. Посмотрим на пример логики, которую можно встретить в УПП:
// Пример того, как может выглядеть очистка в типовом коде
Для Каждого ТЧ Из Метаданные().ТабличныеЧасти Цикл
Если ТЧ.Имя <> "Товары" И ТЧ.Имя <> "ВозвратнаяТара" Тогда
ЭтотОбъект[ТЧ.Имя].Очистить(); // Вот здесь пропадают ваши данные!
КонецЕсли;
КонецЦикла;
В этом случае необходимо добавить проверку вашей ТЧ: И ТЧ.Имя <> "Отклонения".
Иногда проще не менять логику ПередЗаписью, а использовать подписку на событие ПриЗаписи. Однако помните, что на этапе ПриЗаписи данные уже улетают в БД. Если ТЧ очистилась перед записью, то в ПриЗаписи восстанавливать её будет поздно. Поэтому основной упор всегда делаем на анализ ПередЗаписью.
Если ваша база работает в распределенном режиме, убедитесь, что новая табличная часть включена в состав Плана обмена. В УПП механизмы регистрации изменений могут блокировать запись данных, если объект метаданных не участвует в обмене, что иногда приводит к странному поведению при попытке зафиксировать транзакцию.
Проблема «исчезающих» табличных частей в УПП почти всегда кроется в типовых механизмах очистки, заложенных в модуль объекта. Тщательная трассировка события ПередЗаписью с контролем количества строк в ТЧ позволяет быстро локализовать проблему и внести необходимые правки в исключения типовых процедур заполнения.