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