Сервис доступа к данным 1С для внешних систем
Жёлтый мост
Код · Аналитику

Остатки товаров по складам с резервами, себестоимостью и продажами за период

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

Управление торговлей 11.5

Задача

Руководитель склада спрашивает: что лежит без движения и сколько в этом денег. Чтобы ответить, нужны сразу четыре регистра: наличие, резервы под заказы, стоимость остатка и продажи за период. Свободный остаток нигде не хранится, это разность наличия и резерва.

Решение

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

Результат: наличие, резерв, свободно, количество и стоимость по учету себестоимости без НДС, себестоимость единицы, списано без расчета себестоимости, продано и выручка без НДС за период.

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

ОБЪЕДИНИТЬ

ВЫБРАТЬ
	Резервы.Номенклатура,
	Резервы.Склад
ИЗ
	втРезервы КАК Резервы
;
ВЫБРАТЬ
	СправочникНоменклатура.Наименование КАК Номенклатура,
	СправочникСклады.Наименование КАК Склад,
	ЕСТЬNULL(Остатки.ВНаличии, 0) КАК ВНаличии,
	ЕСТЬNULL(Резервы.ВРезерве, 0) КАК ВРезерве,
	ЕСТЬNULL(Остатки.ВНаличии, 0) - ЕСТЬNULL(Резервы.ВРезерве, 0) КАК Свободно,
	ЕСТЬNULL(Себестоимость.Количество, 0) КАК КоличествоПоУчетуСебестоимости,
	ЕСТЬNULL(Себестоимость.Стоимость, 0) КАК СтоимостьБезНДСПоУчету,
	ВЫБОР
		КОГДА ЕСТЬNULL(Себестоимость.Количество, 0) > 0
			ТОГДА Себестоимость.Стоимость / Себестоимость.Количество
		ИНАЧЕ 0
	КОНЕЦ КАК СебестоимостьЕдиницыБезНДС,
	ЕСТЬNULL(Себестоимость.СписаноБезРасчета, 0) КАК СписаноБезРасчетаСебестоимости,
	ЕСТЬNULL(Продажи.Продано, 0) КАК ПроданоЗаПериод,
	ЕСТЬNULL(Продажи.Выручка, 0) КАК ВыручкаБезНДСЗаПериод
ИЗ
	втКлючи КАК Ключи
		ЛЕВОЕ СОЕДИНЕНИЕ втОстатки КАК Остатки
		ПО Ключи.Номенклатура = Остатки.Номенклатура
			И Ключи.Склад = Остатки.Склад
		ЛЕВОЕ СОЕДИНЕНИЕ втРезервы КАК Резервы
		ПО Ключи.Номенклатура = Резервы.Номенклатура
			И Ключи.Склад = Резервы.Склад
		ЛЕВОЕ СОЕДИНЕНИЕ втСебестоимость КАК Себестоимость
		ПО Ключи.Номенклатура = Себестоимость.Номенклатура
			И Ключи.Склад = Себестоимость.Склад
		ЛЕВОЕ СОЕДИНЕНИЕ втПродажи КАК Продажи
		ПО Ключи.Номенклатура = Продажи.Номенклатура
			И Ключи.Склад = Продажи.Склад
		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК СправочникНоменклатура
		ПО Ключи.Номенклатура = СправочникНоменклатура.Ссылка
		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Склады КАК СправочникСклады
		ПО Ключи.Склад = СправочникСклады.Ссылка
УПОРЯДОЧИТЬ ПО
	СтоимостьБезНДСПоУчету УБЫВ,
	Номенклатура,
	Склад
;
УНИЧТОЖИТЬ втОстатки
;
УНИЧТОЖИТЬ втРезервы
;
УНИЧТОЖИТЬ втСебестоимостьПоАналитике
;
УНИЧТОЖИТЬ втСебестоимость
;
УНИЧТОЖИТЬ втПродажиПоАналитике
;
УНИЧТОЖИТЬ втПродажи
;
УНИЧТОЖИТЬ втКлючи
Обработка для Управление торговлей 11.5Открыть через "Файл, Открыть", выбрать даты, нажать "Сформировать результат". Ничего не пишет в базу, работает от прав пользователя.
Скачать .epf

Функция для обработки

// Остатки товаров по складам на дату с резервами, свободным остатком,
// себестоимостью остатка и продажами за период.
//
// Четыре регистра сведены одним пакетом запросов:
//  - ТоварыНаСкладах: что физически лежит на складе (ВНаличии);
//  - ТоварыКОтгрузке: что уже обещано клиентам (ВРезерве);
//  - СебестоимостьТоваров: стоимость остатка по разделу учета "Товары на складах";
//  - ВыручкаИСебестоимостьПродаж: сколько продано и на какую сумму за период.
// Ключ соединения везде пара Номенклатура + Склад. Характеристики и серии
// свернуты: если они нужны, добавьте их в группировки всех временных таблиц.
// Складской учет (ТоварыНаСкладах) и финансовый учет себестоимости
// (СебестоимостьТоваров) это разные контуры: количество в них расходится,
// пока не выполнен расчет себестоимости или движения проведены не по всем
// регистрам. Поэтому количество по учету себестоимости выводится отдельной
// колонкой, а себестоимость единицы считается от него, а не от наличия.
// Стоимость и выручка берутся без НДС, чтобы их можно было сравнивать между собой.
// Колонка СписаноБезРасчетаСебестоимости показывает количество, списанное без
// партии (отрицательные остатки по партиям): пока оно не ноль, расчет
// себестоимости за период не выполнен и себестоимость единицы завышена.
// Аналитика учета в регистрах себестоимости и продаж хранится ключом
// (справочник КлючиАналитикиУчетаНоменклатуры). Виртуальные таблицы этих
// регистров сначала кладутся во временные таблицы и только потом соединяются
// со справочником ключей: соединение напрямую с виртуальной таблицей платформа
// выполняет плохо. Строки итога собираются от объединения ключей остатков и
// резервов, полное соединение не используется.
//
// Параметры:
//  Дата   - Дата - момент остатков, берется конец этого дня;
//  Начало - Дата - начало периода продаж;
//  Конец  - Дата - конец периода продаж, берется конец дня.
//
// Возвращаемое значение:
//  ТаблицаЗначений - Номенклатура, Склад, ВНаличии, ВРезерве, Свободно,
//                    КоличествоПоУчетуСебестоимости, СтоимостьБезНДСПоУчету,
//                    СебестоимостьЕдиницыБезНДС, СписаноБезРасчетаСебестоимости,
//                    ПроданоЗаПериод, ВыручкаБезНДСЗаПериод.
&НаСервереБезКонтекста
Функция ОстаткиСРезервамиИПродажами(Знач Дата, Знач Начало, Знач Конец)

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

	// Нужен результат восьмого запроса пакета (индекс 7): временные таблицы
	// и УНИЧТОЖИТЬ строк не возвращают.
	Результаты = Запрос.ВыполнитьПакет();
	Возврат Результаты[7].Выгрузить();

КонецФункции

Что учесть

Как воспользоваться

  1. Выберите вкладку своей конфигурации над кодом: под каждой лежит запрос, выполненный именно в этой конфигурации.
  2. Скачайте обработку под ней и откройте в 1С через "Файл, Открыть". Форма покажет поля отбора, результат появится в той же форме таблицей.
  3. Нужно иначе: скопируйте запрос кнопкой над кодом и подставьте в консоль запросов или в свою обработку. Все параметры перечислены в тексте, значения по умолчанию видны в обработке.
  4. Хотите то же самое, но под свою базу и свои поля: подключите базу к мосту и попросите ИИ доработать этот запрос. Он увидит структуру вашей конфигурации и проверит результат на ваших данных.
Свои задачи таким же способом. Подключение занимает около пятнадцати минут: обработка из кабинета, ключ, готовый текст для ИИ. При регистрации даются три дня работы одной базы, карта не нужна.
Подключить свою базу Другие решения

Комментарии

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