Как в 1С создать сводные документы на каждую дату из выбранного периода

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

При автоматизации розничной торговли и налогового учета часто возникает задача сформировать итоговые сводные документы за определенный интервал времени — например, создать по одной сводной налоговой накладной или отчету о розничных продажах на каждый день периода на основании первичных приходных кассовых ордеров (ПКО).

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

Разберем по шагам, как решить эту задачу с помощью итоговых группировок запроса и двухуровневой выборки данных.

Шаг 1. Анализируем типичные ошибки при построении запроса

Рассмотрим частые ошибки, которые мешают корректному объединению данных по дням:

  1. Группировка по точному времени: если включить реквизит Ссылка.Дата в секцию СГРУППИРОВАТЬ ПО без приведения к началу дня, каждая запись с уникальным временем (секундами) создаст отдельную строку, и группировка за день не сработает.
  2. Отсутствие поля группировки в списке полей: если поле НАЧАЛОПЕРИОДА(...) объявлено только в секции итогов, но не выведено в ВЫБРАТЬ, обращение к нему через ВыборкаНачалоПериода.НачалоПериода вызовет ошибку "Поле не обнаружено".
  3. Неправильная граница периода: условие Ссылка.Дата МЕЖДУ &ДатаНачала И &ДатаКонец без приведения параметра &ДатаКонец к концу суток исключит из обработки все документы за последний день, проведенные позже 00:00:00.

Шаг 2. Составляем правильный текст запроса с итогами по датам

Сформируем запрос, в котором приведем дату к началу дня с помощью функции НАЧАЛОПЕРИОДА(..., ДЕНЬ), рассчитаем суммы по номенклатурным группам и добавим секцию ИТОГИ для иерархического обхода.

Посмотрим на пример текста запроса:


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

Запрос.УстановитьПараметр("ДатаНачала", НачалоДня(ПериодС));
Запрос.УстановитьПараметр("ДатаКонец", КонецДня(ПериодПо));
Запрос.УстановитьПараметр("СвойствоКодУКТВЭД", ПланыВидовХарактеристик.СвойстваОбъектов.НайтиПоНаименованию("Код УКТВЭД"));

Шаг 3. Организуем двухуровневый обход выборки и создание документов

Для того чтобы создать по одному документу на каждый день, применим метод Выбрать с параметром ОбходРезультатаЗапроса.ПоГруппировкам. Внешний цикл будет перебирать даты, а внутренний — детальные строки, относящиеся к текущей дате.

Разберем реализацию алгоритма в коде:


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

Если РезультатЗапроса.Пустой() Тогда
    Возврат;
КонецЕсли;

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

Пока ВыборкаПоДням.Следующий() Цикл

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

КонецЦикла;

Шаг 4. Важные нюансы при пакетном создании документов

При внедрении данного механизма в рабочую конфигурацию обратим внимание на следующие практические рекомендации:

  1. Установка времени документа: вызов НАЧАЛОПЕРИОДА(..., ДЕНЬ) устанавливает время на 00:00:00. Если сводные документы должны проводиться позже первичных документов розницы, для реквизита Дата целесообразно использовать КонецДня(ВыборкаПоДням.НачалоПериода).
  2. Фильтрация по свойствам: передавайте ссылку на свойство через параметр запроса, а не по строковому наименованию в секции ПО, чтобы исключить замедление запроса и ошибки при смене наименования свойства.
  3. Обработка исключений: оборачивайте операцию записи каждого документа в блок Попытка ... Исключение, чтобы сбой при проведении одного документа не прерывал формирование остальных документов за период.
← На главную