При сопровождении и аудите базы 1С:ERP часто возникает задача выявления документов, которые имеют статус проведения, но не сформировали движений в регистре бухгалтерии Хозрасчетный. Разберем архитектурные особенности отражения операций в ERP, причины отсутствия проводок, а также технические и штатные способы решения этой задачи.
В отличие от классической 1С:Бухгалтерии, где проводки формируются непосредственно в момент нажатия кнопки проведения, в 1С:ERP реализована концепция отложенного проведения по регламентированному учету. При проведении документа формируются только оперативные регистры накопления, а проводки по регистру бухгалтерии создаются асинхронно — вручную пользователем или регламентным заданием.
Основные причины, почему документ может быть проведен, но не иметь проводок:
Прежде чем писать программный код или сложные запросы, обратим внимание на типовой функционал. В 1С:ERP предусмотрено специализированное рабочее место «Отражение документов в регламентированном учете».
В этом рабочем месте конфигурация сама классифицирует документы по статусам:
Информация о текущем состоянии отражения хранится в специализированных регистрах сведений статусов документов, что избавляет от необходимости сканировать всю базу тяжелыми запросами.
Если требуется получить точный список ссылок через запрос (например, для внешней обработки или отчета), нельзя написать единый статический запрос без перечисления таблиц, так как в языке запросов 1С нет конструкции обращения сразу ко «всем документам».
Однако мы можем программно обойти коллекцию метаданных, отобрать только те документы, которые являются регистраторами для регистра бухгалтерии, и сформировать динамический пакетный запрос с конструкцией ОБЪЕДИНИТЬ ВСЕ.
Разберем по шагам, как правильно реализовать такой алгоритм:
Хозрасчетный.ОБЪЕДИНИТЬ ВСЕ.NULL.Посмотрим на пример кода генерации такого запроса:
ТекстЗапроса = "";
МассивРегистраторов = Метаданные.РегистрыБухгалтерии.Хозрасчетный.Регистраторы;
Для Каждого ДокументМетаданные Из МассивРегистраторов Цикл
Если Не ПустаяСтрока(ТекстЗапроса) Тогда
ТекстЗапроса = ТекстЗапроса + "
|ОБЪЕДИНИТЬ ВСЕ
|";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + "
|ВЫБРАТЬ
| Док.Ссылка КАК Документ,
| Док.Дата КАК Дата,
| ТИПЗНАЧЕНИЯ(Док.Ссылка) КАК ТипДокумента
|ИЗ
| Документ." + ДокументМетаданные.Имя + " КАК Док
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
| ПО Док.Ссылка = Хозрасчетный.Регистратор
|ГДЕ
| Док.Проведен = ИСТИНА
| И Хозрасчетный.Регистратор ЕСТЬ NULL";
КонецЦикла;
Запрос = Новый Запрос(ТекстЗапроса);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
// Обработка найденного документа
КонецЦикла;
В ERP насчитывается более сотни видов документов-регистраторов. Единый запрос со 100+ секциями ОБЪЕДИНИТЬ ВСЕ и множественными соединениями может привести к долгой компиляции плана на сервере СУБД и значительному потреблению оперативной памяти.
Для оптимизации рекомендуется:
Посмотрим на структуру оптимизированного запроса с временной таблицей существующих регистраторов:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| Хозрасчетный.Регистратор КАК Регистратор
|ПОМЕСТИТЬ ВТ_РегистраторыСПроводками
|ИЗ
| РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
|ГДЕ
| Хозрасчетный.Период МЕЖДУ &ДатаНачала И &ДатаОкончания
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Док.Ссылка КАК Документ
|ИЗ
| Документ.ПриобретениеТоваровУслуг КАК Док
| ЛЕВОЕ СОЕДИНЕНИЕ ВТ_РегистраторыСПроводками КАК ВТ
| ПО Док.Ссылка = ВТ.Регистратор
|ГДЕ
| Док.Проведен = ИСТИНА
| И Док.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
| И ВТ.Регистратор ЕСТЬ NULL";
Запрос.УстановитьПараметр("ДатаНачала", НачалоДня(ДатаНачала));
Запрос.УстановитьПараметр("ДатаОкончания", КонецДня(ДатаОкончания));
Результат = Запрос.Выполнить();
Такой подход обеспечивает высокую скорость выполнения и исключает перегрузку СУБД при работе с большими массивами учетных данных.