Каждый разработчик 1С хотя бы раз сталкивался с системным сообщением: "Запись не верна! Не заполнен счет дебета (Регистр бухгалтерии: Журнал проводок; Номер строки: X)". Эта ошибка часто ставит в тупик пользователей, так как она не указывает напрямую, какой именно реквизит в документе нужно заполнить, чтобы счет «подтянулся» в проводки. Попытки отловить эту ошибку в привычных событиях документа, таких как ОбработкаПроверкиЗаполнения или ПриЗаписи, обычно не приносят результата. В этой статье мы разберем, почему так происходит, и реализуем надежный механизм диагностики.
Для начала проанализируем ситуацию и выясним причину «невидимости» этой ошибки для стандартных обработчиков. Когда мы нажимаем кнопку «Провести», платформа запускает целую цепочку событий. Ошибка незаполненного счета генерируется не кодом конфигурации, а ядром платформы в момент физической записи набора записей в базу данных.
Рассмотрим жизненный цикл проведения документа:
ПередЗаписью в модуле документа.ОбработкаПроверкиЗаполнения (проверяются только реквизиты документа, помеченные галочкой «Проверка заполнения»).ОбработкаПроведения. Здесь формируются движения (записи в регистрах), но они пока находятся в оперативной памяти.Именно на четвертом этапе, когда метод Записать() вызывается для регистра бухгалтерии, платформа видит, что в метаданных у ресурса СчетДт или СчетКт стоит запрет на пустые значения, а в данных передано «ПустаяСсылка». Происходит исключение, транзакция откатывается, и управление в ПриЗаписи документа просто не передается. Поэтому искать решение в модуле документа бесполезно — нам нужно спуститься на уровень Набора Записей регистра.
Самый эффективный способ перехватить проблему — это внедриться в процесс записи самого регистра. Мы воспользуемся расширением и создадим обработчик события ПередЗаписью для регистра бухгалтерии (например, «ЖурналПроводок» в УНФ или «Хозрасчетный» в БП).
Разберем алгоритм действий по шагам. В модуле набора записей регистра нам нужно перебрать все строки, которые документ пытается сохранить, и проверить их на наличие пустых счетов. Если мы находим такие строки, мы не только прерываем запись, но и выводим пользователю детальный отчет.
Рассмотрим пример кода, который можно разместить в расширении для регистра бухгалтерии:
&Вместо("ПередЗаписью")
Процедура Расширение_ПередЗаписью(Отказ, Замещение)
// Если запись инициирована обменом данными, проверку можно пропустить
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
СписокОшибок = Новый СписокЗначений;
НомерСтроки = 0;
// ЭтотОбъект — это НаборЗаписей, который является коллекцией строк
Для Каждого ТекущаяЗапись Из ЭтотОбъект Цикл
НомерСтроки = НомерСтроки + 1;
Если ТекущаяЗапись.СчетДт.Пустая() Или ТекущаяЗапись.СчетКт.Пустая() Тогда
СообщениеТекст = СтрШаблон("В строке №%1 проводок не заполнен счет! (Период: %2)",
НомерСтроки, ТекущаяЗапись.Период);
СписокОшибок.Добавить(СообщениеТекст);
КонецЕсли;
КонецЦикла;
Если СписокОшибок.Количество() > 0 Тогда
// Сообщаем пользователю подробности
Для Каждого Ошибка Из СписокОшибок Цикл
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(Ошибка.Значение);
КонецЦикла;
// Устанавливаем Отказ, чтобы платформа не выдавала свое системное окно
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Этот подход хорош тем, что мы работаем с данными «в памяти» непосредственно перед их фиксацией в БД. Проверка коллекции в ОЗУ выполняется мгновенно и не создает ощутимой нагрузки на сервер.
Если в вашей конфигурации несколько регистров бухгалтерии или вы хотите создать универсальный инструмент диагностики для всех типов документов, лучше использовать Подписку на событие. Мы создаем новую подписку в расширении, выбираем объект РегистрБухгалтерииНаборЗаписей.ИмяВашегоРегистра и событие ПередЗаписью.
Проанализируем ситуацию: в крупных системах (например, 1С:ERP или 1С:КА) проводки могут формироваться сложными офлайн-механизмами. Подписка позволит «отловить» пустые счета независимо от того, какой документ и в каком модуле формирует эти проводки.
Важный момент: часто счета в УНФ или ERP не заполняются из-за ошибок в настройках «Счетов учета номенклатуры» или «Счетов учета расчетов». Мы можем дополнить наш код выше, чтобы он не просто ругался на пустой счет, но и пытался подсказать, для какой аналитики (субконто) этот счет не найден. Для этого в цикле перебора записей мы можем анализировать содержимое ТекущаяЗапись.СубконтоДт.
В конфигурации «Управление нашей фирмой» (УНФ) проводки часто генерируются через общий модуль ПроведениеДокументовУНФ. Система сначала формирует таблицу значений со всеми данными будущих проводок, а затем одним махом записывает её в регистр. Если мы хотим перехватить ошибку максимально «красиво», можно внедриться в этот общий модуль с помощью &После или &Вместо.
Однако, как показывает практика, использование ПередЗаписью в модуле набора записей является самым надежным «последним рубежом». Даже если логика формирования проводок в конфигурации изменится, наш код в наборе записей все равно сработает.
Выясним причину опасений некоторых разработчиков по поводу «лишней нагрузки». Они считают, что ручная проверка в ПередЗаписью дублирует проверку платформы. На самом деле, когда вы устанавливаете Отказ = Истина в своем коде, платформа не приступает к своей внутренней проверке метаданных, так как выполнение транзакции прерывается раньше. Таким образом, вы просто заменяете неинформативное системное сообщение на свое собственное, более понятное пользователю.
Для оптимизации рекомендуем придерживаться следующих правил:
ОбменДанными.Загрузка, чтобы не блокировать загрузку данных из других систем.РежимЗаписи у регистратора, если это необходимо).СообщитьПользователю с привязкой к конкретному полю или объекту, если это возможно, чтобы упростить навигацию.Таким образом, мы выяснили, что ключ к решению проблемы лежит вне модуля документа. Используя расширение для набора записей регистра, мы получаем полный контроль над процессом формирования проводок и можем предоставить пользователю качественный сервис диагностики ошибок.