Как получить все документы для перепроведения по партиям в 1С?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

В процессе работы с конфигурациями 1С, особенно с такими как "Управление торговлей 10.3", часто возникает задача массового перепроведения документов для восстановления последовательности партионного учета. Основная сложность заключается в том, чтобы выбрать абсолютно все документы, которые могут влиять на регистр партий, а не только те, которые уже сделали по нему движения. Рассмотрим, как решить эту задачу правильно и надежно.

Проанализируем ситуацию: из-за ошибок в учете (например, не хватило остатка товара на складе) какой-то документ мог провеcтись, но не сделать движений по регистру ПартииТоваровНаСкладах. Если мы будем выбирать документы для перепроведения просто по наличию движений в этом регистре, мы пропустим такой "проблемный" документ. После исправления данных он должен сделать движения, но в нашу выборку он не попадет. Наша цель — найти способ получить список всех потенциальных регистраторов.

Решение 1: Получение списка регистраторов из метаданных (рекомендуемый способ)

Самый надежный и правильный способ получить полный список типов документов, которые могут делать движения по определённому регистру накопления — это обратиться напрямую к метаданным конфигурации. Этот метод гарантирует, что мы получим все возможные типы документов-регистраторов, даже если ни один документ такого типа еще не создавал движений или не был проведен.

Рассмотрим по шагам, как это сделать программно.

Шаг 1. Получаем имена документов-регистраторов.

Для этого мы обращаемся к свойству Регистраторы нужного нам регистра накопления в метаданных. В цикле переберем коллекцию регистраторов и соберем их имена в массив.


// Создаем массив для хранения имен документов
ИменаДокументовРегистраторов = Новый Массив;

// Обращаемся к метаданным регистра накопления "ПартииТоваровНаСкладах"
Для Каждого Регистратор Из Метаданные.РегистрыНакопления.ПартииТоваровНаСкладах.Регистраторы Цикл
    // Добавляем строковое имя документа в массив
    // Например, "РеализацияТоваровУслуг", "ПоступлениеТоваровУслуг" и т.д.
    ИменаДокументовРегистраторов.Добавить(Регистратор.Имя);
КонецЦикла;

// Теперь в массиве ИменаДокументовРегистраторов содержатся
// имена всех документов, которые могут делать движения по этому регистру.

Этот подход является наиболее предпочтительным, так как он напрямую читает структуру конфигурации и не зависит от наличия данных в информационной базе.

Шаг 2. Формируем динамический запрос для выборки документов.

Теперь, имея массив с именами документов, нам нужно выбрать сами документы из базы данных за определенный период. Поскольку документы разных типов хранятся в разных таблицах, для их одновременного получения необходимо использовать запрос с объединением (ОБЪЕДИНИТЬ ВСЕ). Текст такого запроса удобно формировать динамически в цикле.


// Предполагаем, что массив ИменаДокументовРегистраторов уже заполнен на предыдущем шаге

// Начальные параметры для выборки
ДатаНачала = '20230101';
ДатаОкончания = '20231231';

ТекстЗапроса = "";
// В цикле обходим массив с именами документов
Для Каждого ИмяДокумента Из ИменаДокументовРегистраторов Цикл
    
    // Для каждого типа документа формируем свой блок ВЫБРАТЬ
    ЧастьЗапроса = "
    |ВЫБРАТЬ
    |    Ссылка,
    |    Дата,
    |    Проведен
    |ИЗ
    |    Документ." + ИмяДокумента + "
    |ГДЕ
    |    Дата МЕЖДУ &НачалоПериода И &КонецПериода И НЕ ПометкаУдаления";
    
    // Объединяем части запроса через ОБЪЕДИНИТЬ ВСЕ
    Если НЕ ПустаяСтрока(ТекстЗапроса) Тогда
        ТекстЗапроса = ТекстЗапроса + "
        |
        |ОБЪЕДИНИТЬ ВСЕ
        |";
    КонецЕсли;
    ТекстЗапроса = ТекстЗапроса + ЧастьЗапроса;
КонецЦикла;

// Добавляем сортировку для соблюдения хронологии
ТекстЗапроса = ТекстЗапроса + "
|
|УПОРЯДОЧИТЬ ПО
|    Дата";

// Создаем и выполняем запрос
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ДатаНачала));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(ДатаОкончания));

РезультатВыборки = Запрос.Выполнить().Выбрать();

// Перебираем результат и перепроводим документы
Пока РезультатВыборки.Следующий() Цикл
    // Здесь логика перепроведения документов
    // ВАЖНО: простое перепроведение в цикле может быть опасным.
    // Лучше использовать обертку Попытка-Исключение.
    Попытка
        ОбъектДокумента = РезультатВыборки.Ссылка.ПолучитьОбъект();
        // Перепроводим только проведенные документы
        Если ОбъектДокумента.Проведен Тогда
            ОбъектДокумента.Записать(РежимЗаписиДокумента.Проведение);
        КонецЕсли;
    Исключение
        Сообщить("Не удалось перепровести документ: " + РезультатВыборки.Ссылка + ". Ошибка: " + ОписаниеОшибки());
    КонецПопытки;
КонецЦикла;

Важно: массовое перепроведение документов — ресурсоемкая операция. Она может заблокировать работу пользователей и привести к новым ошибкам. Всегда выполняйте такие операции в монопольном режиме, предварительно сделав резервную копию базы. Обязательно используйте механизм Попытка-Исключение, чтобы обработка не прервалась на первом же проблемном документе.

Решение 2: Получение типов через набор записей (альтернативный способ)

Существует и другой программный способ получить список типов-регистраторов, который также был предложен на форуме. Он заключается в создании пустого набора записей регистра и анализе типов, доступных для его отбора по полю Регистратор.


// Создаем пустой набор записей для регистра
НаборЗаписей = РегистрыНакопления.ПартииТоваровНаСкладах.СоздатьНаборЗаписей();

// Получаем доступные типы для отбора по регистратору
МассивТиповРегистраторов = НаборЗаписей.Отбор.Регистратор.ТипЗначения.Типы();

// Теперь в МассивТиповРегистраторов находятся объекты типа "Тип",
// описывающие все возможные документы-регистраторы.
// Дальнейший код для построения запроса будет немного отличаться,
// так как нужно будет получать имя из метаданных типа.

Этот метод тоже работает, но считается менее "правильным" с архитектурной точки зрения, так как для получения информации о структуре (метаданных) мы создаем объект данных (набор записей). Прямое обращение к объекту Метаданные, как в первом решении, является более логичным и эффективным.

Решение 3: Использование штатной обработки "Групповое перепроведение документов"

Если вы не хотите писать код, можно воспользоваться стандартным инструментом, который есть в большинстве типовых конфигураций, включая "Управление торговлей 10.3".

Обработка "Групповое перепроведение документов" (обычно находится в меню "Сервис" -> "Универсальные обработки") позволяет выполнить ту же задачу без программирования.

  1. Откройте обработку.
  2. Укажите период, за который нужно перепровести документы.
  3. В списке "Документы" вручную отметьте галочками все типы документов, которые относятся к партионному учету (например, "Реализация товаров и услуг", "Поступление товаров и услуг", "Перемещение товаров", "Списание товаров", "Оприходование товаров" и т.д.).
  4. Нажмите кнопку "Выполнить".

Преимущества этого способа:

Недостаток:

Выбирайте способ, который лучше всего подходит под вашу задачу и уровень квалификации. Для разовых операций или для пользователей без прав на изменение конфигурации идеально подойдет штатная обработка. Для регулярных автоматизированных процедур лучше использовать программный метод с обращением к метаданным.

← На главную