|
Как бы половчее избежать запроса в цикле? | ☑ | ||
---|---|---|---|---|
0
pessok
17.12.14
✎
10:58
|
Коллеги, приветствую
УТ 10.3, несколько допиленная под нужды. В данном случае говорим о розничной продаже в разрезе заказов. Дополнительно сделан РН ТоварыНаБорту, соответственно кладовщик при отгрузке "отправляет" в машину товары, и уже именно из этих товаров формируются документы продажи. Есть обработочка, которая по списку заказов формирует ЧекиККМ, а потом закрытие заказов, чтобы подчистить хвосты. Ранее списание происходило с того склада, который был указан кладовщиком при отправке на борт. Теперь нужно реализовать нечто типа метода списания ФИФО в разрезе организаций, чтобы ЧекККМ создавался на ту организацию, где сейчас есть остатки (т.е. на один заказ может быть N чеков от разных организаций, не спрашивайте зачем, это "узбекский учет" (: ) Притом надо учесть, что созданные ранее чеки тоже виртуально списывают партии (хотя на самом деле спишет уже только ОРП). Чеки создаются группой в одной транзакции, соответственно для каждого конкретного заказа нужно проверить остатки с учетом уже созданных ранее в этой транзакции чеков. Я представляю себе только запрос в цикле (при обходе заказов формируем запрос остатков), а как сделать красивее? |
|||
1
gerthog
17.12.14
✎
11:06
|
(0) Блин, два раза прочитал и ничего не понял(
|
|||
2
spiller26
17.12.14
✎
11:07
|
(1) та же ботва.
Кусок кода дайте. |
|||
3
pessok
17.12.14
✎
11:10
|
щас, момент
|
|||
4
H A D G E H O G s
17.12.14
✎
11:14
|
(0) Бред какой-то. Почему не РТУ + ПКО?
|
|||
5
H A D G E H O G s
17.12.14
✎
11:15
|
(0) Заказ - это заказ покупателя?
Как один заказ покупателя может быть на несколько организаций? |
|||
6
pessok
17.12.14
✎
11:17
|
(4) потому что хотят чеки. см. "узбекский учет". Продажа обезличена, но все равно ведется в разрезе заказов
(5) заказ один, а чеков по нему может быть несколько, на несколько разных организаций. Код, пока не дописан, т.к. я не уверен, что ход мыслей правильный. Пока писал все эти TODO уже, кажись, придумал относительно нормальное решение Процедура СформироватьЧеки(МассивЗаказов) Экспорт Запрос = Новый Запрос( "ВЫБРАТЬ | Заказы.Заказ КАК Заказ, | Заказы.ДатаОтгрузки, | Заказы.КассаПродажи, | Заказы.Номенклатура, | СУММА(Заказы.Количество) КАК Количество, | Заказы.ЕдиницаИзмерения, | Заказы.Цена КАК Цена, | СУММА(Заказы.Сумма) КАК Сумма, | СУММА(Заказы.СуммаНДС) КАК СуммаНДС, | Заказы.Водитель |ПОМЕСТИТЬ Заказы |ИЗ | (ВЫБРАТЬ | ЗаказыПокупателей.ЗаказПокупателя.АдресТочки.КассаПродажи КАК КассаПродажи, | ЗаказыПокупателей.ЗаказПокупателя КАК Заказ, | ЗаказыПокупателей.ЗаказПокупателя.ДатаОтгрузки КАК ДатаОтгрузки, | ТоварыНаБортуОстатки.Водитель КАК Водитель, | ЗаказыПокупателей.Номенклатура КАК Номенклатура, | ЗаказыПокупателей.ЕдиницаИзмерения КАК ЕдиницаИзмерения, | ЗаказыПокупателей.Цена КАК Цена, | ТоварыНаБортуОстатки.КоличествоОстаток КАК Количество, | ТоварыНаБортуОстатки.КоличествоОстаток * ЗаказыПокупателей.Цена КАК Сумма, | (ТоварыНаБортуОстатки.КоличествоОстаток * ЗаказыПокупателей.Цена / 1.18 - ТоварыНаБортуОстатки.КоличествоОстаток * ЗаказыПокупателей.Цена) * -1 КАК СуммаНДС | ИЗ | РегистрНакопления.ЗаказыПокупателей.Обороты( | , | , | , | ЗаказПокупателя В (&Заказы) | И ДоговорКонтрагента.Владелец = ЗНАЧЕНИЕ(Справочник.Контрагенты.ФизЛицо)) КАК ЗаказыПокупателей | ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаБорту.Остатки(, ЗаказПокупателя В (&Заказы)) КАК ТоварыНаБортуОстатки | ПО ЗаказыПокупателей.ЗаказПокупателя = ТоварыНаБортуОстатки.ЗаказПокупателя | И ЗаказыПокупателей.Номенклатура = ТоварыНаБортуОстатки.Номенклатура | ГДЕ | ТоварыНаБортуОстатки.КоличествоОстаток > 0) КАК Заказы | |СГРУППИРОВАТЬ ПО | Заказы.Номенклатура, | Заказы.ЕдиницаИзмерения, | Заказы.Заказ, | Заказы.Цена, | Заказы.Водитель, | Заказы.КассаПродажи, | Заказы.ДатаОтгрузки |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ | ЧекККМ.Ссылка КАК ЧекККМ, | ЧекККМ.ЗаказПокупателя, | ЧекККМ.Организация |ПОМЕСТИТЬ ЧекиККМ |ИЗ | Документ.ЧекККМ КАК ЧекККМ |ГДЕ | НЕ ЧекККМ.ПометкаУдаления | |СГРУППИРОВАТЬ ПО | ЧекККМ.Ссылка, | ЧекККМ.ЗаказПокупателя, | ЧекККМ.Организация | |ОБЪЕДИНИТЬ ВСЕ | |ВЫБРАТЬ | ОтчетОРозничныхПродажахТовары.Ссылка, | ОтчетОРозничныхПродажахТовары.ЗаказПокупателя, | ОтчетОРозничныхПродажахТовары.Ссылка.Организация |ИЗ | Документ.ОтчетОРозничныхПродажах.Товары КАК ОтчетОРозничныхПродажахТовары |ГДЕ | НЕ ОтчетОРозничныхПродажахТовары.Ссылка.ПометкаУдаления | |СГРУППИРОВАТЬ ПО | ОтчетОРозничныхПродажахТовары.Ссылка, | ОтчетОРозничныхПродажахТовары.ЗаказПокупателя, | ОтчетОРозничныхПродажахТовары.Ссылка.Организация |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ | Заказы.Заказ КАК ЗаказПокупателя, | Заказы.ДатаОтгрузки КАК Дата, | Заказы.Водитель КАК Водитель, | ЧекиККМ.ЧекККМ КАК ЧекККМ, | Заказы.КассаПродажи, | Заказы.Номенклатура, | Заказы.Количество КАК Количество, | Заказы.ЕдиницаИзмерения, | Заказы.Цена, | Заказы.Сумма КАК Сумма, | Заказы.СуммаНДС КАК СуммаНДС |ИЗ | Заказы КАК Заказы | ЛЕВОЕ СОЕДИНЕНИЕ ЧекиККМ КАК ЧекиККМ | ПО Заказы.Заказ = ЧекиККМ.ЗаказПокупателя |ИТОГИ | СУММА(Количество), | СУММА(Сумма), | СУММА(СуммаНДС) |ПО | ЗаказПокупателя"); Запрос.УстановитьПараметр("Заказы", МассивЗаказов); ВыборкаЗаказ = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); Пока ВыборкаЗаказ.Следующий() Цикл МассивЗаказов = Новый Массив(); МассивЗаказов.Добавить(ВыборкаЗаказ.Заказ); ТаблицаОстатков = СформироватьТаблицуОстатковПартийПоЗаказам(МассивЗаказов); // получение остатков для заказа с учетом чеков //TODO сделать обход остатков по товарам, сформировать таблицу организаций, складов, товаров под спиание //пройтись циклом по полученной таблице и создать документы Документ = Документы.ЧекККМ.СоздатьДокумент(); ЗаполнениеДокументов.ЗаполнитьШапкуДокумента(Документ, ПараметрыСеанса.ТекущийПользователь); ЗаполнитьЗначенияСвойств(Документ, ВыборкаЗаказ); Документ.Организация = Справочники.Организации.НайтиПоКоду("Р00000002"); //TODO заполнение должно идти по таблице, сформированной для остатков Документ.Комментарий = "Создан на основании "+ВыборкаЗаказ.ЗаказПокупателя+" по складу "; //TODO заполнение должно идти по таблице, сформированной для остатков ВыборкаДетали = ВыборкаЧекККМ.Выбрать(); Пока ВыборкаДетали.Следующий() Цикл //TODO список товаров и количество уже должно заполняться по таблице остатков Товар = Документ.Товары.Добавить(); ЗаполнитьЗначенияСвойств(Товар, ВыборкаДетали); Товар.Коэффициент = Товар.ЕдиницаИзмерения.Коэффициент; КонецЦикла; Документ.СуммаДокумента = Документ.Товары.Итог("Сумма"); НСтр = Документ.Оплата.Добавить(); НСтр.ВидОплаты = Справочники.ВидыОплатЧекаККМ.Наличные; НСтр.Сумма = Документ.СуммаДокумента; Попытка Документ.Записать(РежимЗаписиДокумента.Проведение); Сообщить("Записан "+Документ.Ссылка); Исключение Сообщить("Ошибка "+ОписаниеОшибки()); КонецПопытки; КонецЦикла; КонецПроцедуры Функция СформироватьТаблицуОстатковПартийПоЗаказам(МассивЗаказов) Экспорт //формируем массив номенклатуры и дат ТаблицаНоменклатураЗаказ = Новый ТаблицаЗначений; ТаблицаНоменклатураЗаказ.Колонки.Добавить("ЗаказПокупателя", Новый ОписаниеТипов("ДокументСсылка.ЗаказПокупателя")); ТаблицаНоменклатураЗаказ.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура")); ТаблицаНоменклатураЗаказ.Колонки.Добавить("ДатаОтгрузки", Новый ОписаниеТипов("Дата")); ТаблицаНоменклатураЗаказ.Колонки.Добавить("АдресТочки", Новый ОписаниеТипов("СправочникСсылка.ТорговыеТочки")); СписокДат = Новый ТаблицаЗначений; СписокДат.Колонки.Добавить("ДатаОтгрузки", Новый ОписаниеТипов("Дата")); Для Каждого ЗаказПокупателя Из МассивЗаказов Цикл ЗаполнитьЗначенияСвойств(СписокДат.Добавить(), ЗаказПокупателя); Для Каждого ТекСтр Из ЗаказПокупателя.Товары Цикл НовСтр = ТаблицаНоменклатураЗаказ.Добавить(); НовСтр.ЗаказПокупателя = ЗаказПокупателя; НовСтр.Номенклатура = ТекСтр.Номенклатура; ЗаполнитьЗначенияСвойств(НовСтр, ЗаказПокупателя); КонецЦикла; КонецЦикла; СписокНоменклатуры = ОбщегоНазначения.УдалитьПовторяющиесяЭлементыМассива(ТаблицаНоменклатураЗаказ.ВыгрузитьКолонку("Номенклатура")); СписокДат.Свернуть("ДатаОтгрузки"); СписокДат.Сортировать("ДатаОтгрузки Возр"); //получаем остатки Запрос = Новый Запрос(); Запрос.Текст = "ВЫБРАТЬ | ДатыОтгрузки.ДатаОтгрузки КАК Период |ПОМЕСТИТЬ ВТДатыОтгрузки |ИЗ | &ДатыОтгрузки КАК ДатыОтгрузки |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ | ЗаказыНоменклатура.ЗаказПокупателя, | ЗаказыНоменклатура.ДатаОтгрузки, | ЗаказыНоменклатура.Номенклатура, | ЗаказыНоменклатура.АдресТочки |ПОМЕСТИТЬ ВТЗаказыНоменклатура |ИЗ | &ЗаказыНоменклатура КАК ЗаказыНоменклатура |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ РАЗЛИЧНЫЕ | ТорговыеТочкиДоступныеСклады.Склад |ПОМЕСТИТЬ ВТДоступныеСклады |ИЗ | Справочник.ТорговыеТочки.ДоступныеСклады КАК ТорговыеТочкиДоступныеСклады |ГДЕ | ТорговыеТочкиДоступныеСклады.Ссылка В | (ВЫБРАТЬ | ВТЗаказыНоменклатура.АдресТочки | ИЗ | ВТЗаказыНоменклатура) |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ | ВложенныйЗапросОстатков.Период, | ВложенныйЗапросОстатков.Организация, | ВложенныйЗапросОстатков.Склад, | ВложенныйЗапросОстатков.Номенклатура, | ВложенныйЗапросОстатков.КоличествоКонечныйОстаток |ИЗ | (ВЫБРАТЬ | ВТДатыОтгрузки.Период КАК Период, | ОстаткиПартий.Организация КАК Организация, | ОстаткиПартий.Склад КАК Склад, | ОстаткиПартий.Номенклатура КАК Номенклатура, | ОстаткиПартий.КоличествоКонечныйОстаток КАК КоличествоКонечныйОстаток | ИЗ | ВТДатыОтгрузки КАК ВТДатыОтгрузки | ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ | Оборот1.Дата КАК ДатаС, | МИНИМУМ(ВЫБОР | КОГДА Оборот2.Дата ЕСТЬ NULL | ТОГДА КОНЕЦПЕРИОДА(&КонецПериода, ДЕНЬ) | ИНАЧЕ КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(Оборот2.Дата, ДЕНЬ, -1), ДЕНЬ) | КОНЕЦ) КАК ДатаПо, | Оборот1.Организация КАК Организация, | Оборот1.Склад КАК Склад, | Оборот1.Номенклатура КАК Номенклатура, | Оборот1.КоличествоКонечныйОстаток КАК КоличествоКонечныйОстаток | ИЗ | (ВЫБРАТЬ | ПартииТоваровНаСкладахОстаткиИОбороты.Период КАК Дата, | ПартииТоваровНаСкладахОстаткиИОбороты.Регистратор.Организация КАК Организация, | ПартииТоваровНаСкладахОстаткиИОбороты.Склад КАК Склад, | ПартииТоваровНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура, | ПартииТоваровНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток КАК КоличествоКонечныйОстаток | ИЗ | РегистрНакопления.ПартииТоваровНаСкладах.ОстаткиИОбороты( | &НачалоПериода, | &КонецПериода, | Запись, | , | Номенклатура В (&СписокНоменклатуры) | И Склад В | (ВЫБРАТЬ | ВТДоступныеСклады.Склад | ИЗ | ВТДоступныеСклады)) КАК ПартииТоваровНаСкладахОстаткиИОбороты) КАК Оборот1 | ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ | ПартииТоваровНаСкладахОстаткиИОбороты.Период КАК Дата, | ПартииТоваровНаСкладахОстаткиИОбороты.Регистратор.Организация КАК Организация, | ПартииТоваровНаСкладахОстаткиИОбороты.Склад КАК Склад, | ПартииТоваровНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура | ИЗ | РегистрНакопления.ПартииТоваровНаСкладах.ОстаткиИОбороты( | &НачалоПериода, | &КонецПериода, | Запись, | , | Номенклатура В (&СписокНоменклатуры) | И Склад В | (ВЫБРАТЬ | ВТДоступныеСклады.Склад | ИЗ | ВТДоступныеСклады)) КАК ПартииТоваровНаСкладахОстаткиИОбороты) КАК Оборот2 | ПО Оборот1.Дата < Оборот2.Дата | И Оборот1.Номенклатура = Оборот2.Номенклатура | И Оборот1.Склад = Оборот2.Склад | И Оборот1.Организация = Оборот2.Организация | | СГРУППИРОВАТЬ ПО | Оборот1.Дата, | Оборот1.Номенклатура, | Оборот1.КоличествоКонечныйОстаток, | Оборот1.Склад, | Оборот1.Организация) КАК ОстаткиПартий | ПО (ВТДатыОтгрузки.Период МЕЖДУ НАЧАЛОПЕРИОДА(ОстаткиПартий.ДатаС, ДЕНЬ) И КОНЕЦПЕРИОДА(ОстаткиПартий.ДатаПо, ДЕНЬ))) КАК ВложенныйЗапросОстатков | ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ | ТоварыНаСкладахОбороты.Регистратор.Организация КАК Организация, | ТоварыНаСкладахОбороты.Номенклатура КАК Номенклатура, | СУММА(ТоварыНаСкладахОбороты.КоличествоРасход) КАК КоличествоСписанийПоЧекам | ИЗ | РегистрНакопления.ТоварыНаСкладах.Обороты(&НачалоПериода, &КонецПериода, Запись, ) КАК ТоварыНаСкладахОбороты | ГДЕ | ТоварыНаСкладахОбороты.Регистратор ССЫЛКА Документ.ЧекККМ | | СГРУППИРОВАТЬ ПО | ТоварыНаСкладахОбороты.Номенклатура, | ТоварыНаСкладахОбороты.Регистратор.Организация) КАК СписанныеЧекамиТовары | ПО ВложенныйЗапросОстатков.Организация = СписанныеЧекамиТовары.Организация | И ВложенныйЗапросОстатков.Номенклатура = СписанныеЧекамиТовары.Номенклатура |АВТОУПОРЯДОЧИВАНИЕ"; Запрос.УстановитьПараметр("ДатыОтгрузки", СписокДат); Запрос.УстановитьПараметр("СписокНоменклатуры", СписокНоменклатуры); Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(СписокДат[0].ДатаОтгрузки)); Запрос.УстановитьПараметр("КонецПериода", КонецДня(СписокДат[СписокДат.Количество()-1].ДатаОтгрузки)); Запрос.УстановитьПараметр("ЗаказыНоменклатура", ТаблицаНоменклатураЗаказ); Возврат Запрос.Выполнить().Выгрузить(); КонецФункции |
|||
7
batman69
17.12.14
✎
11:21
|
(6) мля..
|
|||
8
pessok
17.12.14
✎
11:21
|
+(6) более верное, на мой взгляд, решение появилось:
сначала сформировать полную таблицу остатков, а потом уже непосредственно в ней при создании чеков уменьшать количество остатка по организации. И для этой таблице при обходе искать соответствия |
|||
9
H A D G E H O G s
17.12.14
✎
11:21
|
(6) Удачи вам, мистер Горски.
|
|||
10
pessok
17.12.14
✎
11:21
|
(7) конкретнее, пожалуйста ;)
|
|||
11
pessok
17.12.14
✎
11:22
|
(9) да кто спорит, что это жутота, но делать надо
|
|||
12
spiller26
17.12.14
✎
11:24
|
(6) ВыборкаЗаказ = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам)
Зачем группировка??? Зачем в запросе Итоги? |
|||
13
Garykom
гуру
17.12.14
✎
11:24
|
Ух ты "рюкзачки"
|
|||
14
pessok
17.12.14
✎
11:26
|
(12) это еще старый вариант просто, когда для одного заказа четко создавался один чек по организации заказа. Заполнять чеки удобнее по группировкам. Итоги не нужны, согласен
|
|||
15
Garykom
гуру
17.12.14
✎
11:26
|
Кстати запросы считают что то (когда + и -) медленно, они тока выборку быстро делают данных (по индексам)
Так что самое быстрое и без запросов в цикле, это запросом строим таблицу(ы) и дальше по ней(ним) работаем |
|||
16
pessok
17.12.14
✎
11:28
|
(15) ну вот я так и подумал. в (8) описал
|
|||
17
spiller26
17.12.14
✎
11:32
|
Можно сделать все в одном запросе, но долго
"МассивЗаказов" загнать в ВТ_МассивЗаказов Функцию СформироватьТаблицуОстатковПартийПоЗаказам(МассивЗаказов) переработать в запрос |
|||
18
pessok
17.12.14
✎
11:35
|
(17) не можно, к сожалению. мне нужно проверять чеки, которые уже созданы в этой транзакции. Т.е:
В массиве заказов два заказа. в каждом "Номенклатура А" - 1 шт У нас есть по одной партии этого товара на каждой из двух организаций. Соответственно после того, как создался первый чек остатки уже изменились, второй чек должен создаваться с учетом этого |
|||
19
pessok
17.12.14
✎
11:36
|
(18) посему оптимальное, на мой взгляд, сразу создать таблицу остатков и уже при создании чеков убирать из нее "списанную" чеком номенклатуру
|
|||
20
Михаил Козлов
17.12.14
✎
11:48
|
(19)+. Как модуле партионного учета.
|
|||
21
mdocs
17.12.14
✎
11:56
|
(0) набор умных слов. Сначала надо написать работающий код, потом думать об оптимизации. Если можете сразу все продумать оптимально, то это отлично. Если нет - то пишите хоть как нибудь но чтоб на выходе были верные данные.
|
|||
22
pessok
17.12.14
✎
12:02
|
(21) вот это как раз таки плохой подход. надо сразу писать нормально. потому что в противной случае этот копрокод так и останется навсегда
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |