В рамках решения задачки по возврату комисионного товара был создан новый документ (чем-то напоминает возврат от покупателя), при проведении которого требовалось находить партии комиссионного товара и списывать их по ФИФО, так вот был реализован метод ФИФО непосредственно в запросе, т.е. все данные и расчеты формируются в одном пакетном запросе, на входе документ ссылка с заполненной табличной частью, на выходе то, что должно быть уже в проводках. Это пример того, как можно быстро и просто обрабатывать информацию, не прибегая к таблицам значений, их переборам и циклам по количеству.
В данном примере была использована конфигурация Бухгалтерия, но можно адаптировать запрос под любую конфигурацию. Основной момент это получение нарастающим итогом накопительных сумм по партиям, а затем выбор необходимого заданного количества из этих партий по ФИФО для формирования проводок.
Данный материал необходимо рассматривать как учебный, призван расширить опыт в области применения пакетных запросов.
Файл, приложенный в формате консоли запросов, на типовой бухгалтерии необходимо адаптировать под какой-либо свой новый документ, поскольку в разработке был использован документ собственной разработки, поэтому при разборе запроса нужно подставить свой вид документа в первой вт, в запросе встречается документ основание, можно взять типовой документ Отчет комиссионера о продажах.
Ниже код запроса, и он же в формате консоли.
//получаем тч с необходимым количеством номенклатуры для выполнения возврата
ВЫБРАТЬ
ВозвратПоКомиссии.Ссылка,
ВозвратПоКомиссии.ЕдиницаИзмерения,
ВозвратПоКомиссии.Количество,
ВозвратПоКомиссии.КоличествоМест,
ВозвратПоКомиссии.Коэффициент,
ВозвратПоКомиссии.Номенклатура,
ВозвратПоКомиссии.Цена,
ВозвратПоКомиссии.Сумма,
ВозвратПоКомиссии.СтавкаНДС,
ВозвратПоКомиссии.СуммаНДС,
ВозвратПоКомиссии.НомерГТД,
ВозвратПоКомиссии.СтранаПроисхождения,
ВозвратПоКомиссии.СчетУчета,
ВозвратПоКомиссии.ПереданныеСчетУчета,
ВозвратПоКомиссии.СчетУчетаНДСПоРеализации,
ВозвратПоКомиссии.СчетДоходов,
ВозвратПоКомиссии.СчетРасходов,
ВозвратПоКомиссии.Субконто,
ВозвратПоКомиссии.ДокументОприходования,
ВозвратПоКомиссии.Себестоимость,
ВозвратПоКомиссии.УчетнаяЦенаКомиссионера,
ВозвратПоКомиссии.Ссылка.ДокументОснование,
ВозвратПоКомиссии.НомерСтроки
ПОМЕСТИТЬ ТчТовары
ИЗ
Документ.ВозвратПоКомиссии.Товары КАК ВозвратПоКомиссии
ГДЕ
ПретензияТовары.Ссылка = &ДокСсылка
;
/////////получаем остатки в разрезе номенклатуры и комитентов по счетам - партии прихода///////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВЫБОР
КОГДА ХозрасчетныйОбороты.Счет.Код ПОДОБНО "004%"
ТОГДА ХозрасчетныйОбороты.Субконто1.Контрагент
ИНАЧЕ ХозрасчетныйОбороты.Субконто1
КОНЕЦ КАК Комитент,
ВЫБОР
КОГДА ХозрасчетныйОбороты.Счет.Код ПОДОБНО "004%"
ТОГДА ХозрасчетныйОбороты.Субконто1.ДоговорКонтрагента
ИНАЧЕ ТчТовары.ДокументОснование.ДоговорКонтрагента
КОНЕЦ КАК ДоговорКомитента,
ВЫБОР
КОГДА ХозрасчетныйОбороты.Счет.Код ПОДОБНО "004%"
ТОГДА ХозрасчетныйОбороты.Субконто1
ИНАЧЕ ХозрасчетныйОбороты.Субконто3
КОНЕЦ КАК Партия,
ЕСТЬNULL(ХозрасчетныйОбороты.Субконто2, ТчТовары.Номенклатура) КАК Номенклатура,
ЕСТЬNULL(ТчТовары.НомерСтроки, 0) КАК НомерСтроки,
ВЫБОР
КОГДА ХозрасчетныйОбороты.Субконто2 ЕСТЬ NULL
ТОГДА ИСТИНА
ИНАЧЕ ЛОЖЬ
КОНЕЦ КАК НетПозиции,
СУММА(ЕСТЬNULL(ХозрасчетныйОбороты.СуммаОборотКт, 0)) КАК СуммаКомитента,
СУММА(ЕСТЬNULL(ХозрасчетныйОбороты.КоличествоОборотКт, 0)) КАК КолКомитента,
СУММА(ЕСТЬNULL(ХозрасчетныйОбороты.СуммаОборотКт, 0)) / СУММА(ЕСТЬNULL(ХозрасчетныйОбороты.КоличествоОборотКт, 1)) КАК Стоимость,
ХозрасчетныйОбороты.Счет,
ТчТовары.Количество
ПОМЕСТИТЬ ПроводкиПретензия
ИЗ
ТчТовары КАК ТчТовары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.Обороты(НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаДок, ДЕНЬ, -3500), ДЕНЬ), КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаДок, ДЕНЬ, 220), ДЕНЬ), Регистратор, , , , , ) КАК ХозрасчетныйОбороты
ПО (ХозрасчетныйОбороты.Субконто2 = ТчТовары.Номенклатура)
И (ХозрасчетныйОбороты.Регистратор = ТчТовары.ДокументОснование)
И (ХозрасчетныйОбороты.Счет = ТчТовары.СчетУчета)
СГРУППИРОВАТЬ ПО
ВЫБОР
КОГДА ХозрасчетныйОбороты.Счет.Код ПОДОБНО "004%"
ТОГДА ХозрасчетныйОбороты.Субконто1.Контрагент
ИНАЧЕ ХозрасчетныйОбороты.Субконто1
КОНЕЦ,
ВЫБОР
КОГДА ХозрасчетныйОбороты.Счет.Код ПОДОБНО "004%"
ТОГДА ХозрасчетныйОбороты.Субконто1
ИНАЧЕ ХозрасчетныйОбороты.Субконто3
КОНЕЦ,
ЕСТЬNULL(ХозрасчетныйОбороты.Субконто2, ТчТовары.Номенклатура),
ХозрасчетныйОбороты.Счет,
ВЫБОР
КОГДА ХозрасчетныйОбороты.Субконто2 ЕСТЬ NULL
ТОГДА ИСТИНА
ИНАЧЕ ЛОЖЬ
КОНЕЦ,
ВЫБОР
КОГДА ХозрасчетныйОбороты.Счет.Код ПОДОБНО "004%"
ТОГДА ХозрасчетныйОбороты.Субконто1.ДоговорКонтрагента
ИНАЧЕ ТчТовары.ДокументОснование.ДоговорКонтрагента
КОНЕЦ,
ТчТовары.Количество,
ЕСТЬNULL(ТчТовары.НомерСтроки, 0)
;
/////////если дата и время различных партий совпадает их нужно как то различать, вводим номер партии///////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
КОЛИЧЕСТВО(ПроводкиПретензия_1.Партия) КАК Номер,
ПроводкиПретензия.Партия КАК Партия
ПОМЕСТИТЬ НомераПартий
ИЗ
ПроводкиПретензия КАК ПроводкиПретензия
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПроводкиПретензия КАК ПроводкиПретензия_1
ПО ПроводкиПретензия.Партия >= ПроводкиПретензия_1.Партия
СГРУППИРОВАТЬ ПО
ПроводкиПретензия.Партия
ИНДЕКСИРОВАТЬ ПО
Номер
;
///////////используем номер партии полученный выше, что бы отличить друг от друга партии с одинаковой датой и временем/////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ПроводкиПретензия.Комитент,
ПроводкиПретензия.ДоговорКомитента,
ПроводкиПретензия.Партия,
ПроводкиПретензия.Номенклатура,
ПроводкиПретензия.НомерСтроки,
ПроводкиПретензия.НетПозиции,
ПроводкиПретензия.СуммаКомитента,
ПроводкиПретензия.КолКомитента,
ПроводкиПретензия.Стоимость,
ПроводкиПретензия.Счет,
ПроводкиПретензия.Количество,
НомераПартий.Номер,
ДОБАВИТЬКДАТЕ(ПроводкиПретензия.Партия.Дата, СЕКУНДА, НомераПартий.Номер) КАК ПартияДата
ПОМЕСТИТЬ ПроводкиПретензияПартия
ИЗ
ПроводкиПретензия КАК ПроводкиПретензия
ЛЕВОЕ СОЕДИНЕНИЕ НомераПартий КАК НомераПартий
ПО ПроводкиПретензия.Партия = НомераПартий.Партия
;
///////////делаем нарастающий итог по количеству в партии/////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ЕСТЬNULL(ПроводкиПретензия.ПартияДата, ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0)) КАК ПартияДата,
ПроводкиПретензия.Номенклатура,
СУММА(ЕСТЬNULL(ПроводкиПретензия.КолКомитента, 0)) КАК КолКомитента
ПОМЕСТИТЬ ВТ_ПроводкиПретензия_сгрупп
ИЗ
ПроводкиПретензияПартия КАК ПроводкиПретензия
СГРУППИРОВАТЬ ПО
ЕСТЬNULL(ПроводкиПретензия.ПартияДата, ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0)),
ПроводкиПретензия.Номенклатура
;
//////////выводим по каждой партии нарастающий итог//////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ЕСТЬNULL(ВТ_ПроводкиПретензия_сгрупп.ПартияДата, ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0)) КАК ПартияДата,
ВТ_ПроводкиПретензия_сгрупп.Номенклатура,
СУММА(ЕСТЬNULL(ВТ_ПроводкиПретензия_сгрупп1.КолКомитента, 0)) КАК КолКомитента
ПОМЕСТИТЬ ВТ_ПроводкиПретензия_накоп
ИЗ
ВТ_ПроводкиПретензия_сгрупп КАК ВТ_ПроводкиПретензия_сгрупп
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ПроводкиПретензия_сгрупп КАК ВТ_ПроводкиПретензия_сгрупп1
ПО (ЕСТЬNULL(ВТ_ПроводкиПретензия_сгрупп.ПартияДата, ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0)) >= ЕСТЬNULL(ВТ_ПроводкиПретензия_сгрупп1.ПартияДата, ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0)))
И ВТ_ПроводкиПретензия_сгрупп.Номенклатура = ВТ_ПроводкиПретензия_сгрупп1.Номенклатура
СГРУППИРОВАТЬ ПО
ВТ_ПроводкиПретензия_сгрупп.Номенклатура,
ЕСТЬNULL(ВТ_ПроводкиПретензия_сгрупп.ПартияДата, ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0))
;
/////////привязываем необходимое количество из тч к тому что есть в партиях///////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ПроводкиПретензия.Комитент,
ПроводкиПретензия.ДоговорКомитента,
ПроводкиПретензия.Партия,
ПроводкиПретензия.Номенклатура,
ПроводкиПретензия.НетПозиции,
ПроводкиПретензия.СуммаКомитента,
ПроводкиПретензия.КолКомитента,
ПроводкиПретензия.Стоимость,
ПроводкиПретензия.Счет,
ПроводкиПретензия.Количество,
ПроводкиПретензия.НомерСтроки,
ВТ_ПроводкиПретензия_накоп.КолКомитента КАК КолКомитентаНакоп
ПОМЕСТИТЬ ВТ_ПроводкиПретензия
ИЗ
ПроводкиПретензияПартия КАК ПроводкиПретензия
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ПроводкиПретензия_накоп КАК ВТ_ПроводкиПретензия_накоп
ПО ПроводкиПретензия.Номенклатура = ВТ_ПроводкиПретензия_накоп.Номенклатура
И (ЕСТЬNULL(ПроводкиПретензия.ПартияДата, ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0)) = ЕСТЬNULL(ВТ_ПроводкиПретензия_накоп.ПартияДата, ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0)))
;
///////////получаем расчет необходимого количества для возврата в разрезе партий/////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_ПроводкиПретензия.Комитент,
ВТ_ПроводкиПретензия.ДоговорКомитента,
ВТ_ПроводкиПретензия.Партия,
ВТ_ПроводкиПретензия.Номенклатура,
ВТ_ПроводкиПретензия.НетПозиции,
ВТ_ПроводкиПретензия.СуммаКомитента,
ВТ_ПроводкиПретензия.КолКомитента,
ВТ_ПроводкиПретензия.Стоимость,
ВТ_ПроводкиПретензия.Счет,
ВТ_ПроводкиПретензия.Количество,
ВТ_ПроводкиПретензия.КолКомитентаНакоп,
ВТ_ПроводкиПретензия.НомерСтроки,
ВЫБОР
КОГДА ВТ_ПроводкиПретензия.КолКомитентаНакоп - ВТ_ПроводкиПретензия.Количество < 0
ТОГДА ВТ_ПроводкиПретензия.КолКомитента
ИНАЧЕ ВТ_ПроводкиПретензия.Количество - (ВТ_ПроводкиПретензия.КолКомитентаНакоп - ВТ_ПроводкиПретензия.КолКомитента)
КОНЕЦ КАК КолвоВернуть
ПОМЕСТИТЬ ВТ_ПроводкиПретензия1
ИЗ
ВТ_ПроводкиПретензия КАК ВТ_ПроводкиПретензия
;
//////////определяем имеено то количество, что было необходимо вернуть по тч//////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_ПроводкиПретензия1.Комитент,
ВТ_ПроводкиПретензия1.ДоговорКомитента,
ВТ_ПроводкиПретензия1.Партия,
ВТ_ПроводкиПретензия1.Номенклатура,
ВТ_ПроводкиПретензия1.НетПозиции,
ВТ_ПроводкиПретензия1.СуммаКомитента,
ВТ_ПроводкиПретензия1.КолКомитента,
ВТ_ПроводкиПретензия1.Стоимость,
ВТ_ПроводкиПретензия1.Счет,
ВТ_ПроводкиПретензия1.КолКомитентаНакоп,
ВТ_ПроводкиПретензия1.Количество,
ВЫБОР
КОГДА ВТ_ПроводкиПретензия1.КолвоВернуть > ВТ_ПроводкиПретензия1.КолКомитента
ТОГДА ВТ_ПроводкиПретензия1.КолКомитента
ИНАЧЕ ВТ_ПроводкиПретензия1.КолвоВернуть
КОНЕЦ КАК КолвоВернуть
ПОМЕСТИТЬ ВТ_ПроводкиПретензия2
ИЗ
ВТ_ПроводкиПретензия1 КАК ВТ_ПроводкиПретензия1
;
//////////убираем лишнии партии из конечной таблицы//////это уже результат////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_ПроводкиПретензия2.Комитент,
ВТ_ПроводкиПретензия2.ДоговорКомитента,
ВТ_ПроводкиПретензия2.Партия,
ВТ_ПроводкиПретензия2.Номенклатура,
ВТ_ПроводкиПретензия2.НетПозиции,
ВТ_ПроводкиПретензия2.СуммаКомитента,
ВТ_ПроводкиПретензия2.КолКомитента,
ВТ_ПроводкиПретензия2.Стоимость,
ВТ_ПроводкиПретензия2.Счет,
ВТ_ПроводкиПретензия2.КолКомитентаНакоп,
ВТ_ПроводкиПретензия2.Количество,
ВТ_ПроводкиПретензия2.КолвоВернуть
ПОМЕСТИТЬ ВТ_ПроводкиПретензия3
ИЗ
ВТ_ПроводкиПретензия2 КАК ВТ_ПроводкиПретензия2
ГДЕ
(ВТ_ПроводкиПретензия2.КолвоВернуть > 0)
;
//////Это проверка на случай если не хватит необходимого количества с остатками по партиям, ругаемся если такие есть//////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВложенныйЗапрос.Комитент,
ВложенныйЗапрос.ДоговорКомитента,
ВложенныйЗапрос.Номенклатура,
ВложенныйЗапрос.Количество,
ВложенныйЗапрос.КолвоВернуть
ИЗ
(ВЫБРАТЬ
ВТ_ПроводкиПретензия3.Комитент КАК Комитент,
ВТ_ПроводкиПретензия3.ДоговорКомитента КАК ДоговорКомитента,
ВТ_ПроводкиПретензия3.Номенклатура КАК Номенклатура,
ВТ_ПроводкиПретензия3.Количество КАК Количество,
СУММА(ВТ_ПроводкиПретензия3.КолвоВернуть) КАК КолвоВернуть
ИЗ
ВТ_ПроводкиПретензия3 КАК ВТ_ПроводкиПретензия3
ГДЕ
НЕ ВТ_ПроводкиПретензия3.Перевозчик
СГРУППИРОВАТЬ ПО
ВТ_ПроводкиПретензия3.Комитент,
ВТ_ПроводкиПретензия3.ДоговорКомитента,
ВТ_ПроводкиПретензия3.Номенклатура,
ВТ_ПроводкиПретензия3.Количество) КАК ВложенныйЗапрос
ГДЕ
ВложенныйЗапрос.Количество > ВложенныйЗапрос.КолвоВернуть
;
/////////////если вообще на остатках не нашлось наших позиций, ругаемся///////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ПроводкиПретензия.Комитент,
ПроводкиПретензия.Партия,
ПроводкиПретензия.Номенклатура,
ПроводкиПретензия.НетПозиции,
ПроводкиПретензия.СуммаКомитента,
ПроводкиПретензия.КолКомитента,
ПроводкиПретензия.Стоимость,
ПроводкиПретензия.Счет
ИЗ
ВТ_ПроводкиПретензия3 КАК ПроводкиПретензия
ГДЕ
ПроводкиПретензия.НетПозиции
;
//////////финальная таблица с нее делааем проводки//////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ПроводкиПретензия.Комитент,
ПроводкиПретензия.Партия,
ПроводкиПретензия.НетПозиции,
ПроводкиПретензия.Стоимость,
ТчТовары.Ссылка,
ТчТовары.ЕдиницаИзмерения,
СУММА(ПроводкиПретензия.КолвоВернуть) КАК Количество,
ТчТовары.Коэффициент,
ТчТовары.Номенклатура КАК Номенклатура,
ТчТовары.Цена,
СУММА(ТчТовары.Сумма) КАК Сумма,
ТчТовары.СтавкаНДС,
СУММА(ТчТовары.СуммаНДС) КАК СуммаНДС,
ТчТовары.НомерГТД,
ТчТовары.СтранаПроисхождения,
ТчТовары.СчетУчета,
ТчТовары.ПереданныеСчетУчета,
ТчТовары.СчетУчетаНДСПоРеализации,
ТчТовары.СчетДоходов,
ТчТовары.СчетРасходов,
ТчТовары.Субконто,
ТчТовары.ДокументОприходования,
СУММА(ТчТовары.Себестоимость) КАК Себестоимость,
СУММА(ТчТовары.УчетнаяЦенаКомиссионера) КАК УчетнаяЦенаКомиссионера,
ТчТовары.ДокументОснование,
СУММА(ВЫРАЗИТЬ(ТчТовары.Количество * ЕСТЬNULL(ПроводкиПретензия.Стоимость, 0) КАК ЧИСЛО(15, 2))) КАК СуммаСтоимость
ИЗ
ТчТовары КАК ТчТовары
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ПроводкиПретензия3 КАК ПроводкиПретензия
ПО ТчТовары.Номенклатура = ПроводкиПретензия.Номенклатура
ГДЕ
(НЕ ПроводкиПретензия.НетПозиции)
СГРУППИРОВАТЬ ПО
ТчТовары.ПереданныеСчетУчета,
ПроводкиПретензия.Комитент,
ТчТовары.СчетРасходов,
ТчТовары.СчетУчета,
ПроводкиПретензия.НетПозиции,
ТчТовары.СтранаПроисхождения,
ТчТовары.ЕдиницаИзмерения,
ТчТовары.НомерГТД,
ТчТовары.СтавкаНДС,
ТчТовары.Субконто,
ТчТовары.ДокументОснование,
ТчТовары.СчетДоходов,
ТчТовары.Ссылка,
ТчТовары.ДокументОприходования,
ТчТовары.Номенклатура,
ПроводкиПретензия.Партия,
ТчТовары.СчетУчетаНДСПоРеализации,
ТчТовары.Коэффициент,
ТчТовары.Цена,
ПроводкиПретензия.Стоимость