В процессе разработки печатных форм для конфигурации «Управление торговым предприятием для Украины» (УТП) 1.2 часто возникает задача отображения не только текущих отгрузок, но и накопленной задолженности контрагента. Одной из специфических задач является вывод долга по многооборотной таре (ящики, бутылки, поддоны). Рассмотрим подробно, как правильно реализовать этот функционал, разберем типичные ошибки и напишем оптимизированный код запроса.
Проанализируем программный код, который часто пытаются использовать новички. Основная проблема заключается в обращении к физической таблице регистра накопления РегистрНакопления.ТоварыПереданные. Физическая таблица хранит записи о каждом движении (приход/расход), но она не предназначена для получения актуальных остатков. Если клиент брал тару 10 раз и возвращал 5 раз, физическая таблица вернет вам 15 строк, а не итоговый долг.
Вторая критическая ошибка — использование логического оператора Если Выборка.Следующий() Тогда. Этот оператор проверяет наличие хотя бы одной записи и выводит только первую попавшуюся строку. Если у клиента есть долг по нескольким позициям (например, и по ящикам, и по бутылкам), то в печатную форму попадет только что-то одно. Для вывода всех позиций необходимо использовать цикл Пока.
Для получения актуальной задолженности в 1С всегда следует использовать виртуальные таблицы. В нашем случае это таблица ТоварыПереданные.Остатки. Она автоматически вычисляет итоги на указанный момент времени, что значительно ускоряет работу системы и упрощает код запроса.
Рассмотрим структуру регистра ТоварыПереданные в УТП. Данный регистр используется для учета товаров, которые переданы контрагенту, но право собственности на которые еще не перешло (или которые подлежат возврату). Важно понимать, что в этом регистре могут храниться и товары на комиссии. Чтобы отделить тару, мы должны использовать фильтр по измерению СтатусПередачи с типом Перечисление.СтатусыПередачиТоваров.Тара.
Разберем алгоритм создания кода для вывода задолженности. Нам потребуется выполнить запрос, передать в него параметры текущего документа (Организация, Контрагент) и вывести результат в макет.
Проанализируем текст правильного запроса. Нам нужно получить номенклатуру, количество остатка и сумму взаиморасчетов (залоговую стоимость).
ТекстЗапроса =
"ВЫБРАТЬ
| ТоварыПереданныеОстатки.Номенклатура КАК Номенклатура,
| ТоварыПереданныеОстатки.КоличествоОстаток КАК Количество,
| ТоварыПереданныеОстатки.СуммаВзаиморасчетовОстаток КАК Сумма
|ИЗ
| РегистрНакопления.ТоварыПереданные.Остатки(&Период,
| Организация = &Организация
| И Контрагент = &Контрагент
| И СтатусПередачи = ЗНАЧЕНИЕ(Перечисление.СтатусыПередачиТоваров.Тара)) КАК ТоварыПереданныеОстатки";
Обратите внимание на параметр &Период. Если мы хотим видеть долг включая текущую реализацию, в этот параметр нужно передать Неопределено или пустую дату (что означает "на текущий момент"). Если же нам нужен долг до текущей отгрузки, следует передать МоментВремени() текущего документа.
Теперь выясним, как правильно связать запрос с данными документа. Мы будем использовать объект ЭтотОбъект (если код пишется в модуле документа) или ссылку на документ.
Запрос = Новый Запрос;
Запрос.Текст = ТекстЗапроса;
// Используем МоментВремени, чтобы получить остатки точно на секунду документа
Запрос.УстановитьПараметр("Период", ЭтотОбъект.МоментВремени());
Запрос.УстановитьПараметр("Организация", ЭтотОбъект.Организация);
Запрос.УстановитьПараметр("Контрагент", ЭтотОбъект.Контрагент);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Рассмотрим процесс вывода строк в макет. Нам необходимо сначала вывести заголовочную часть области задолженности, а затем в цикле заполнить строки.
// Получаем макет документа
Макет = ПолучитьМакет("Макет"); // Замените на имя вашего макета
// Выводим шапку секции задолженности по таре
ОбластьШапка = Макет.ПолучитьОбласть("ЗаголовокДолгТара");
ТабДокумент.Вывести(ОбластьШапка);
ОбластьСтрока = Макет.ПолучитьОбласть("СтрокаДолгТара");
// Используем цикл Пока для обхода всех позиций задолженности
Пока Выборка.Следующий() Цикл
// Заполняем параметры области макета
ОбластьСтрока.Параметры.Номенклатура = Выборка.Номенклатура;
ОбластьСтрока.Параметры.Количество = Выборка.Количество;
ОбластьСтрока.Параметры.Сумма = Выборка.Сумма;
// Вычисляем цену единицы тары (залоговую стоимость)
Если Выборка.Количество <> 0 Тогда
ОбластьСтрока.Параметры.Цена = Выборка.Сумма / Выборка.Количество;
Иначе
ОбластьСтрока.Параметры.Цена = 0;
КонецЕсли;
// Выводим строку в финальный документ
ТабДокумент.Вывести(ОбластьСтрока);
КонецЦикла;
При работе с задолженностью по таре в украинских конфигурациях следует помнить о нескольких нюансах:
ДоговоруКонтрагента, так как задолженность в 1С жестко привязана к конкретному договору. Если у клиента несколько договоров, остатки по ним могут не пересекаться.ХарактеристикаНоменклатуры в запрос и в Группировку.Мы проанализировали ситуацию и выяснили, что для корректного вывода задолженности по таре необходимо отказаться от использования физических таблиц регистра и перейти к виртуальным таблицам остатков. Использование правильных фильтров по Статусу передачи и обход выборки через цикл Пока гарантирует, что в печатную форму попадут все данные о долгах контрагента. Данный подход является стандартом разработки на платформе 1С и обеспечивает высокую производительность системы.