В процессе разработки часто возникает задача получить себестоимость проданных товаров по конкретному документу, например, по «Реализации товаров и услуг». Стандартные отчеты показывают итоговые цифры, но как извлечь эти данные программно для дальнейшей обработки? Разберем несколько подходов, которые помогут решить эту задачу в конфигурации 1С:Управление торговлей 11.
Проанализируем ситуацию: у нас есть проведенный документ реализации, и нам нужно для каждой строки его табличной части "Товары" получить рассчитанную себестоимость. Эта информация может быть нужна для анализа позиций товаров в документе реализации, кастомных отчетов, выгрузок или других специфических механизмов.
Самый "правильный" и надежный способ — обратиться к тем же механизмам, которые использует сама конфигурация. В УТ 11 за расчет себестоимости отвечает сложная система, но для наших целей можно воспользоваться экспортными процедурами из общих модулей.
Основной модуль, который нас интересует, — это УчетСебестоимости. Он содержит процедуры для подготовки и расчета данных. Рассмотрим по шагам, как его использовать.
Сначала необходимо собрать информацию о документах, для которых мы хотим рассчитать себестоимость. Даже если это один документ, его нужно поместить в таблицу значений или массив. В нашем случае, мы берем ссылку на конкретный документ реализации.
Воспользуемся процедурой РассчитатьСебестоимость из общего модуля УчетСебестоимости. Эта процедура принимает на вход параметры расчета и возвращает таблицу с результатами.
Посмотрим на практический пример кода, который решает нашу задачу:
// Предполагается, что СсылкаНаДокумент - это переменная,
// содержащая ссылку на нужный документ "РеализацияТоваровУслуг".
// 1. Создаем структуру параметров для расчета
ПараметрыРасчета = Новый Структура;
ПараметрыРасчета.Вставить("РассчитатьПартии", Истина);
ПараметрыРасчета.Вставить("Источник", СсылкаНаДокумент);
// 2. Вызываем основную процедуру расчета из общего модуля
ТаблицаСебестоимости = УчетСебестоимости.РассчитатьСебестоимость(ПараметрыРасчета);
// 3. Обрабатываем результат
Для Каждого Строка Из ТаблицаСебестоимости Цикл
Сообщить(
Строка("Номенклатура: %1, Себестоимость: %2",
Строка.Номенклатура,
Строка.Сумма)
);
КонецЦикла;
Разберем код подробнее:
ПараметрыРасчета = Новый Структура;: Мы создаем структуру, в которой будем передавать настройки для процедуры расчета.ПараметрыРасчета.Вставить("РассчитатьПартии", Истина);: Этот параметр указывает, что необходимо выполнить полный расчет по партиям.ПараметрыРасчета.Вставить("Источник", СсылкаНаДокумент);: Это ключевой момент. Мы явно указываем, что расчет нужно произвести только в контексте нашего документа. Система не будет пересчитывать весь месяц, а ограничится только данными, связанными с этой реализацией.УчетСебестоимости.РассчитатьСебестоимость(ПараметрыРасчета): Вызываем процедуру, которая выполняет всю "магию". На выходе мы получаем таблицу значений, где каждая строка содержит номенклатуру, характеристику и рассчитанные суммы. Также на результат влияет возможность распределения расходов на документы реализации.Этот метод является предпочтительным, так как он использует типовой механизм, устойчив к обновлениям конфигурации и гарантирует получение тех же цифр, что и в стандартных отчетах (если отсутствуют ошибки в учете товаров на складах и организаций).
Иногда требуется более простое решение, которое не требует глубокого погружения в общие модули. В таком случае можно программно сформировать стандартный отчет, установив в нем нужные отборы. Отчет "Валовая прибыль предприятия" идеально подходит для этой цели, так как он оперирует данными о продажах и себестоимости.
Основная идея: мы создаем экземпляр отчета, устанавливаем отбор по документу-регистратору и выводим результат в таблицу значений, которую затем можем обработать, например, выполнив ABC/XYZ Анализ номенклатуры.
Рассмотрим пример реализации этого подхода:
// Предполагается, что ДокументСсылка - это переменная,
// содержащая ссылку на нужный документ "РеализацияТоваровУслуг".
// 1. Получаем объект отчета
Отчет = Отчеты.ВаловаяПрибыльПредприятия.Создать();
// 2. Устанавливаем настройки компоновки данных
СхемаКомпоновкиДанных = Отчет.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = СхемаКомпоновкиДанных.НастройкиПоУмолчанию;
// 3. Устанавливаем отбор по регистратору (нашему документу)
ЭлементОтбора = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Регистратор");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = ДокументСсылка;
ЭлементОтбора.Использование = Истина;
// 4. Устанавливаем период (можно взять из документа)
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("НачалоПериода", НачалоМесяца(ДокументСсылка.Дата));
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("КонецПериода", КонецМесяца(ДокументСсылка.Дата));
// 5. Формируем отчет
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
// 6. Выводим результат в таблицу значений
Результат = Новый ТаблицаЗначений;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(Результат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
// 7. Результат находится в таблице "Результат"
// Теперь можно перебрать строки и получить нужные данные
Для Каждого Строка Из Результат Цикл
Сообщить(
Строка("Номенклатура: %1, Себестоимость: %2",
Строка.Номенклатура,
Строка.Себестоимость)
);
КонецЦикла;
Преимущества этого метода:
Недостатки:
Выбор метода зависит от конкретной задачи:
УчетСебестоимости.В любом случае, оба способа позволяют надежно получить данные о себестоимости в разрезе конкретного документа, решая поставленную задачу.