Имя: Пароль:
1C
 
Как убрать запрос в цикле
0 pro3ri
 
06.11.15
09:03
Добрый день!
Есть документ с табличной частью Товары, там несколько строчек номенклатуры с соответствующими складами. Нам необходимо выяснить достаточно ли товара до проведения документа.

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


Но он не оптимален, как убрать запрос в цикле?
1 ДенисЧ
 
06.11.15
09:04
Надо себя как-то заставить...
2 piter3
 
06.11.15
09:05
в параметры передать список не подходит?склады в ТЧ?
3 Тактик
 
06.11.15
09:05
Сделать запрос к обоим таблицам сразу.
С этим есть проблемы?
4 Metman
 
06.11.15
09:06
Соедини ТЗ по товарам с ТЗ по остаткам
5 Тактик
 
06.11.15
09:06
(0) Задача с экзамена "1С:Специалист" по платформе... в упрощенном варианте.
6 Тактик
 
06.11.15
09:07
(0) Ты хотя бы учебник Радченко почитай.
7 Metman
 
06.11.15
09:07
Посмотри как в типовой сделано
8 pro3ri
 
06.11.15
09:10
(2) да, склад в ТЧ
9 Бубка Гоп
 
06.11.15
09:11
(0) Молодец, хотя бы интуитивно понимает что это надо переписать. Некоторые годами не видят в таком коде ничего плохого.

Варианта 2:
1) определяешь сразу список всех складов где надо проверить и передаешь их всех параметром (массивом).
2) соединяешь свою тч с таблицей остатков по складу и товару
10 gigi789
 
06.11.15
09:14
(0) 2 варианта
1) если проверяй после записи соответсвенно по ссылки береш тч
2) перез запись в зпрос кладеш таблицу значений
11 cw014
 
06.11.15
09:15
Запрос.Текст = "ВЫБРАТЬ
                                   |    ПартииТоваровНаСкладахОстатки.Номенклатура,
                                   |    ПартииТоваровНаСкладахОстатки.Склад,
                                   |    СУММА(ПартииТоваровНаСкладахОстатки.КоличествоОстаток) КАК КоличествоОстаток
                                   |ИЗ
                                   |    РегистрНакопления.ПартииТоваровНаСкладах.Остатки(
                                   |            &Момент,
                                   |            (Номенклатура,Склад) В (ВЫБРАТЬ Номенклатура,Склад Из Документ.ТвойДокумент.ТвояТабличнаяЧасть ГДЕ Ссылка = &СсылкаНаТвойДокумент)) КАК ПартииТоваровНаСкладахОстатки
                                   |
                                   |СГРУППИРОВАТЬ ПО
                                   |    ПартииТоваровНаСкладахОстатки.Номенклатура,
                                   |    ПартииТоваровНаСкладахОстатки.Склад";
12 vde69
 
06.11.15
09:16
на самом деле задача не совсем простая, тут дело в том, что получить номер строки при двух строках с одинаковой номенклатурой в запросе не так легко....

я для себя так и не решил ее одним запросом, у меня все равно 2 запроса и потом цикл (уже без запроса)
13 piter3
 
06.11.15
09:16
(8) для чего не расскажешь?
14 gigi789
 
06.11.15
09:18
(12) а не просветите зачем номер строки??
15 Ненавижу 1С
 
гуру
06.11.15
09:18
(12) сгруппировать одинаковую номенклатуру во временной таблице не вариант?
16 Ненавижу 1С
 
гуру
06.11.15
09:19
(0) кстати, не решает, надо проверять количество, даже когда строка есть
17 vde69
 
06.11.15
09:21
(14)(15) номер строки нужен для вывода сообщения в какой именно строке табличной части не хватает товара.

в принципе задача решаема, но на мой взгляд получается сильно сложнее чем с небольшим циклом
18 patria0muerte
 
06.11.15
09:21
19 gigi789
 
06.11.15
09:23
(17) найти строки??
20 gigi789
 
06.11.15
09:23
(18)  "Нам необходимо выяснить достаточно ли товара до проведения документа."
21 vde69
 
06.11.15
09:24
(18) главный  минус - нет номера строки для пользователя...

представь документ на 800 строк.... это тебе нужно скопировать наименование номенклатуры, поиском его найти.... а если такой номенклатуры несколько строк, то вообще....
22 Ненавижу 1С
 
гуру
06.11.15
09:26
(17) а в какой не хватает, в первой или во второй если их две? мы просто артикул выводим, вполне устраивает
23 Ненавижу 1С
 
гуру
06.11.15
09:26
вот примерно так, выводит строки с дефицитом:

ВЫБРАТЬ
    РеализацияТоваровУслугТовары.Номенклатура,
    РеализацияТоваровУслугТовары.Склад,
    СУММА(РеализацияТоваровУслугТовары.Количество * РеализацияТоваровУслугТовары.Коэффициент) КАК Количество
ПОМЕСТИТЬ Т
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
ГДЕ
    РеализацияТоваровУслугТовары.Ссылка = &Ссылка

СГРУППИРОВАТЬ ПО
    РеализацияТоваровУслугТовары.Номенклатура,
    РеализацияТоваровУслугТовары.Склад
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Т.Номенклатура,
    Т.Склад,
    Т.Количество,
    ЕСТЬNULL(ТоварыНаСкладахОстатки.КоличествоОстаток, 0) КАК Поле1
ИЗ
    Т КАК Т
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(
                ,
                (Склад, Номенклатура) В
                    (ВЫБРАТЬ
                        Т.Склад,
                        Т.Номенклатура
                    ИЗ
                        Т КАК Т)) КАК ТоварыНаСкладахОстатки
        ПО Т.Номенклатура = ТоварыНаСкладахОстатки.Номенклатура
            И Т.Склад = ТоварыНаСкладахОстатки.Склад
ГДЕ
    Т.Количество < ЕСТЬNULL(ТоварыНаСкладахОстатки.КоличествоОстаток, 0)
24 Dotoshin
 
06.11.15
09:37
(21) Это чем же вы торгуете, если в документе 800 строк?
25 gigi789
 
06.11.15
10:05
(24) все норм судя по описанию все эти строки могут быть зяняты 1 ном позицией
26 Cyberhawk
 
06.11.15
10:07
(21) "а если такой номенклатуры несколько строк, то вообще" // Я правильно понял, что если товара-таки не хватает, то считается, что его не хватает всегда у последней / последних строк?
27 Cyberhawk
 
06.11.15
10:08
(строк с таким товаром)
28 Гёдза
 
06.11.15
10:09
(24) Оптовая торговля, например запчастями или таблетками, вполне может быть по столько строк
29 cw014
 
06.11.15
10:11
(28) "Таблетки на Блюхера. Всегда хороший приход." (С) Масяня
30 Dotoshin
 
06.11.15
10:43
31 pro3ri
 
06.11.15
13:09
(16) согласен, моя ошибка
(12) решил одним запросом с выводом номера строки,

ВЫБРАТЬ
    ТоварыНаСкладахОстатки.Номенклатура,
    ТоварыНаСкладахОстатки.Склад,
    СУММА(ТоварыНаСкладахОстатки.КоличествоОстаток) КАК КоличествоОстаток,
    СУММА(ЗаказПокупателяТовары.Количество) КАК КоличествоДок,
    ЗаказПокупателяТовары.НомерСтроки
ИЗ
    Документ.ЗаказПокупателя.Товары КАК ЗаказПокупателяТовары
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(
                &Дата,
                (Номенклатура, Склад) В
                    (ВЫБРАТЬ
                        ЗаказПокупателяТовары.Номенклатура,
                        ЗаказПокупателяТовары.Размещение КАК Склад
                    ИЗ
                        Документ.ЗаказПокупателя.Товары КАК ЗаказПокупателяТовары
                    ГДЕ
                        ЗаказПокупателяТовары.Ссылка = &Ссылка)) КАК ТоварыНаСкладахОстатки
        ПО ЗаказПокупателяТовары.Номенклатура = ТоварыНаСкладахОстатки.Номенклатура
            И ЗаказПокупателяТовары.Размещение = ТоварыНаСкладахОстатки.Склад
ГДЕ
    ЗаказПокупателяТовары.Ссылка = &Ссылка

СГРУППИРОВАТЬ ПО
    ТоварыНаСкладахОстатки.Номенклатура,
    ТоварыНаСкладахОстатки.Склад,
    ЗаказПокупателяТовары.НомерСтроки

Всем спасибо за участие!
32 vde69
 
06.11.15
13:11
(31) у тебя будет ошибка если в ТЧ две строки с одинаковой номенклатурой
33 vde69
 
06.11.15
13:14
а еще КоличествоОстаток будет задвоено если остатки по разным партиям лежат :)
34 Лефмихалыч
 
06.11.15
13:15
отличный вопрос для собеседования още-то - (0)
35 pro3ri
 
06.11.15
13:38
(32) Если РежимПроведения = РежимПроведенияДокумента.Оперативный Тогда
                //НаборДвижений.КонтрольОстатковПоЗаказамПоставщикам(ЭтотОбъект, "Товары", СтруктураШапкиДокумента, Отказ, Заголовок);
                
                Запрос = Новый Запрос;
                Запрос.Текст = "ВЫБРАТЬ
                               |    ТоварыНаСкладахОстатки.Номенклатура,
                               |    ТоварыНаСкладахОстатки.Склад,
                               |    СУММА(ТоварыНаСкладахОстатки.КоличествоОстаток) КАК КоличествоОстаток,
                               |    СУММА(ЗаказПокупателяТовары.Количество) КАК КоличествоДок
                               |ИЗ
                               |    Документ.ЗаказПокупателя.Товары КАК ЗаказПокупателяТовары
                               |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(
                               |                &Момент,
                               |                (Номенклатура, Склад) В
                               |                    (ВЫБРАТЬ
                               |                        ЗаказПокупателяТовары.Номенклатура,
                               |                        ЗаказПокупателяТовары.Размещение КАК Склад
                               |                    ИЗ
                               |                        Документ.ЗаказПокупателя.Товары КАК ЗаказПокупателяТовары
                               |                    ГДЕ
                               |                        ЗаказПокупателяТовары.Ссылка = &Ссылка
                               |                    СГРУППИРОВАТЬ ПО
                               |                                ЗаказПокупателяТовары.Номенклатура,
                               |                        ЗаказПокупателяТовары.Размещение)) КАК ТоварыНаСкладахОстатки
                               |        ПО ЗаказПокупателяТовары.Номенклатура = ТоварыНаСкладахОстатки.Номенклатура
                               |            И ЗаказПокупателяТовары.Размещение = ТоварыНаСкладахОстатки.Склад
                               |ГДЕ
                               |    ЗаказПокупателяТовары.Ссылка = &Ссылка
                               |
                               |СГРУППИРОВАТЬ ПО
                               |    ТоварыНаСкладахОстатки.Номенклатура,
                               |    ТоварыНаСкладахОстатки.Склад";
                Если РежимПроведения = РежимПроведенияДокумента.Оперативный Тогда
                    Запрос.УстановитьПараметр("Момент", Неопределено);
                Иначе
                    Граница = Новый Граница(МоментВремени(),ВидГраницы.Включая);
                    Запрос.УстановитьПараметр("Момент", Граница);
                КонецЕсли;
                Запрос.УстановитьПараметр("Ссылка", Ссылка);
                Результат= Запрос.Выполнить();
                Выборка = Результат.Выбрать();
                Пока Выборка.Следующий() Цикл
                    
                    Нехватка =  Выборка.КоличествоОстаток - Выборка.КоличествоДок;
                    Если Нехватка<0 Тогда
                    
                        Отказ = Истина;
                        Сообщить("Товара " + Выборка.Номенклатура + " со склада " + Выборка.Склад + " недостаточно в количестве " +(-Нехватка));
                    
                    КонецЕсли;    
                
                КонецЦикла;
                
                
                
            КонецЕсли;

(33) не ведется учет по партиям
36 KA-52
 
06.11.15
14:09
Проводите по новой методике: контроль остатков после формирования движений и откат, если есть отрицательные остатки. Тут и номер строки будет, и какава с чаем
37 Domovoi
 
06.11.15
14:24
(35)а если начнет вестись? Обязательно за 5 мин перепишите все свои поделки?
38 Domovoi
 
06.11.15
14:27
+(37)и это
"Нехватка =  Выборка.КоличествоОстаток - Выборка.КоличествоДок;
                    Если Нехватка<0 Тогда"

в запрос надо пихать, чтоб меньше перебирать строк.
39 Domovoi
 
06.11.15
14:40
+(38)То что в (0) может даже быстрее отработает чем (35). В (23) покрасивше будет.
40 Domovoi
 
06.11.15
14:45
+(39)
"|ГДЕ
|ЗаказПокупателяТовары.Ссылка = &Ссылка"

Условие надо накладывать при отборе обрабатываемого документа, а не после того как все выберите и склеите.
Программист всегда исправляет последнюю ошибку.