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