Как в отчете СКД распределить отгрузки по строкам заказа с разными датами поставки

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

При разработке отчетов по исполнительности заказов программисты часто сталкиваются со сложной задачей: в одном заказе может быть несколько строк с одной и той же номенклатурой, но разными датами поставки. При этом документы реализации не имеют прямой связи с конкретной строкой заказа (по номеру строки), а просто списывают общее количество по документу-основанию. В этой статье мы разберем, как реализовать отчет на Системе компоновки данных (СКД), который покажет количество товара, поставленного в срок и с нарушением, используя алгоритм распределения FIFO.

Анализ проблемы и постановка задачи

Рассмотрим типовую ситуацию в конфигурации Управление производственным предприятием (УПП) 1.3. В документе ЗаказПокупателя в табличной части Товары есть реквизит ДатаПоставки. Если в заказе присутствуют две строки с одинаковым товаром, но разными сроками, система должна понять, какую из них мы закрываем конкретной реализацией.

Пример ситуации:

  1. В заказе 10 единиц товара со сроком до 15.03 и 5 единиц со сроком до 20.03.
  2. Реализация №1 от 28.02 отгружает 7 единиц.
  3. Реализация №2 от 14.03 отгружает 2 единицы.
  4. Реализация №3 от 02.04 отгружает 3 единицы.

Проблема заключается в том, что для корректного отчета за период (например, за март) нам нужно не просто сложить отгрузки, а понять, какие из них «погасили» обязательства по срокам. Более того, реализации, прошедшие до начала периода отчета, должны учитываться в распределении, но не должны выводиться в финальные цифры отгрузки за текущий период.

Решение через программную подготовку данных (Набор данных Объект)

Поскольку стандартным запросом СКД реализовать логику FIFO (First In, First Out) достаточно трудоемко, наиболее надежным способом будет программная подготовка таблицы значений и передача ее в СКД как НаборДанныхОбъект. Проанализируем шаги реализации этого метода.

Во-первых, нам необходимо подготовить запрос, который соберет все данные по заказам и всем связанным реализациям без ограничения по периоду (чтобы учесть прошлые отгрузки). Затем мы программно распределим отгруженное количество по строкам заказов.


// Пример упрощенной подготовки таблицы значений
ТЗ_Результат = Новый ТаблицаЗначений;
ТЗ_Результат.Колонки.Добавить("Контрагент", Новый ОписаниеТипов("СправочникСсылка.Контрагенты"));
ТЗ_Результат.Колонки.Добавить("КоличествоВСРок", Новый ОписаниеТипов("Число"));
ТЗ_Результат.Колонки.Добавить("КоличествоПросрочено", Новый ОписаниеТипов("Число"));

// Логика распределения в цикле по заказам и товарам
Для Каждого СтрокаЗаказа Из ТаблицаЗаказов Цикл
    ОстатокПоСтроке = СтрокаЗаказа.Количество;
    Пока ОстатокПоСтроке > 0 И ТаблицаРеализаций.Количество() > 0 Цикл
        // Здесь реализуется алгоритм сопоставления FIFO
        // Сравниваем ДатуРеализации и ДатуПоставки
        // Если ДатаРеализации <= ДатаПоставки, то КоличествоВСРок
        // Если ДатаРеализации > ДатаПоставки, то КоличествоПросрочено
    КонецЦикла;
КонецЦикла;

Проблема характеристик и соединение наборов данных

При использовании НабораДанныхОбъект программисты часто сталкиваются с тем, что механизм дополнительных реквизитов и сведений (характеристик ПВХ) перестает работать автоматически, так как СКД «не видит» метаданные полей во внешней таблице значений так же хорошо, как в запросе. Чтобы решить эту проблему, проанализируем подход с использованием двух наборов данных.

Разберем по шагам, как настроить связь:

  1. Набор данных 1 (Объект): Называем его ДанныеОтгрузки. Здесь содержатся наши вычисленные поля: Контрагент, КоличествоВСРок, КоличествоПросрочено.
  2. Набор данных 2 (Запрос): Создаем запрос к справочнику Контрагенты. В этом запросе на закладке «Характеристики» настраиваем получение дополнительных реквизитов.
  3. Связи наборов данных: На соответствующей вкладке СКД устанавливаем связь по полю Контрагент. Источником связи выступает набор ДанныеОтгрузки, приемником — набор с запросом к справочнику.

Это позволит пользователю в настройках отчета (в режиме «1С:Предприятие») выбирать любые дополнительные реквизиты контрагента (например, «Регион» или «Категория»), несмотря на то, что основные данные считаются программно.

Алгоритм распределения FIFO в коде

Рассмотрим подробнее, как именно должна происходить «посадка» реализации на строки заказа. Нам важно отсортировать строки заказа по дате поставки, а реализации — по дате документа. Выясним причину, почему это критично: если мы не отсортируем заказы, товар может «зачесться» на более поздний срок, создав фиктивную просрочку по раннему сроку.

В процессе обхода мы должны вести учет «потребленного» количества из реализаций. Если реализация произошла до периода отчета, мы просто уменьшаем потребность строк заказа, но не прибавляем это количество к ресурсам КоличествоВСРок или КоличествоПросрочено в итоговой таблице.


// Фрагмент распределения с учетом периода
Если ДатаРеализации >= НачалоПериода И ДатаРеализации <= КонецПериода Тогда
    Если ДатаРеализации <= ДатаПоставкиЗаказа Тогда
        НоваяСтрока.КоличествоВСРок = РаспределяемоеКоличество;
    Иначе
        НоваяСтрока.КоличествоПросрочено = РаспределяемоеКоличество;
    КонецЕсли;
КонецЕсли;

Альтернативный метод: Распределение через нарастающий итог в запросе

Если конфигурацию изменять нельзя, но очень хочется решить задачу одним запросом, можно использовать механизм нарастающих итогов. Посмотрим, как это работает:

  1. Создаем временную таблицу ВТ_Заказы, где для каждой строки считаем сумму количеств всех предыдущих строк того же товара в этом заказе (нарастающий итог ДО текущей строки и ПО текущую строку). Таким образом, каждая строка заказа получает свой диапазон «очереди» (например, от 0 до 10, от 10 до 15).
  2. Создаем аналогичную таблицу ВТ_Реализации с нарастающим итогом отгрузок.
  3. Соединяем эти таблицы по условию перекрытия диапазонов: ИтогЗаказа_ОТ < ИтогРеализации_ДО и ИтогЗаказа_ДО > ИтогРеализации_ОТ.

Этот метод позволяет вычислить распределение без использования НабораДанныхОбъект, однако он крайне сложен в отладке и может работать медленно при больших объемах данных в УПП. Поэтому программное распределение в ТаблицуЗначений с последующей передачей в СКД остается наиболее гибким и понятным решением для данной задачи.

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

← На главную