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