Имя: Пароль:
1C
1С v8
Подозрение на зацикливание
0 madnus
 
07.04.18
22:52
Всем привет. Я только учусь программировать, поэтому строго не судите(( Есть документ Расходная накладная, в табличной части для каждого товара пользователь указывает партию, которую необходимо списать. В том случае, если товара по указанной партии не хватает, документ не проводится и выводится соответствующее сообщение о нехватке. Написал код, в случае, если товара хватает, всё проводится нормально. В случае, когда пытаюсь провести товара больше, чем есть партии, всё зависает. Не могу понять в чем ошибка, подозрение на зацикливание. Условия для прерывания цикла вроде сделал. Помогите разобраться ( Код ниже

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

Может все же "Прервать"?
А не перебирать все?
3 madnus
 
08.04.18
11:21
(1) Отладчиком ходил. Самое интересное, что при прохождении отладчиком иногда всё отрабатывает корректно, хотя я в коде ничего не меняю. Но в 70% случае отладчик проходит и всё снова виснет. Думал ошибка в коде, но видимо у меня что то глючит.
4 madnus
 
08.04.18
11:22
(2) Пробовал и через Прервать, пробал и после цикла в процедуре Возврат. Ничего не меняется
5 madnus
 
08.04.18
12:08
Решил вопрос. Убрал из параметров РН в запросе Партию и сделал:


        |               Номенклатура В
        |                   (ВЫБРАТЬ
        |                       ВТТовары.Номенклатура
        |                   ИЗ
        |                       ВТТовары КАК ВТТовары)) КАК ОстаткиНоменклатурыОстатки

Теперь всё отрабатывает верно, но я не могу понять почему. Если кто то может, проясните, пожалуйста, почему так, чтобы в будущем я понимал и не допускал таких ошибок.
6 youalex
 
08.04.18
12:42
1.ВыборкаДетальныеЗаписи.Номенклатура - так лучше не делать, получай представление в запросе (хоть Номенклатура.Представление), и выводи пользаку его.

2. Не вижу УПОРЯДОЧИТЬ ПО в запросе. Какой метод списания по условию задачи?  

3. Прерывать цикл не нужно, по идее тебе нужно вывести пользаку все товары с отрицательным количеством, а не по одному их выуживать)) . Тут "Продолжить" - правильно.
7 youalex
 
08.04.18
12:46
(6) + понял, по п.2 - партии прямо в документе указаны.
Используй замер производительности.
8 Borteg
 
08.04.18
13:31
(0)    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки(
        |               &МоментВремени,
        |               (Номенклатура, Партия) В
        |                   (ВЫБРАТЬ
        |                       ВТТовары.Номенклатура,
        |                       ВТТовары.Партия
        |                   ИЗ
        |                       ВТТовары КАК ВТТовары)) КАК ОстаткиНоменклатурыОстатки
        |       ПО ВТТовары.Номенклатура = ОстаткиНоменклатурыОстатки.Номенклатура
        |           И ВТТовары.Партия = ОстаткиНоменклатурыОстатки.Партия";

Убери условия
(Номенклатура, Партия) В
        |                   (ВЫБРАТЬ
        |                       ВТТовары.Номенклатура,
        |                       ВТТовары.Партия
        |                   ИЗ
        |                       ВТТовары КАК ВТТовары)

Ты это отберешь левым соединением.
Регистр то остатки номенклатуры большой?
9 youalex
 
08.04.18
13:47
(8) >>Убери условия ..>> Ты это отберешь левым соединением.

Минус два балла (вроде два) на экзамене.
10 madnus
 
08.04.18
16:43
(6) Метод списание в задаче не указан. В табличной части расходной накладной пользователь сам выбирает партию, с которой списывает товар, поэтому рассчитываю себестоимость по каждой партии отдельно
11 madnus
 
08.04.18
16:44
(9) я убрал из условия только Партию и у меня всё заработало нормально. Это будет считаться ошибкой на экзамене ? Оставил только номенклатуру там
12 youalex
 
08.04.18
18:10
(11) Ну, буквально, условие ошибки звучит как "Отсутствие значений параметров в виртуальной таблице или использование вместо них условия «ГДЕ»"  
То, что вы не отбираете по партии в параметрах вт - лично мое мнение, это не будет воспринято как ошибка. Но правильно будет  ее использовать.  Убедиться, что тупит именно запрос. Консоль запросов вам в помощь. Далее - убедиться, что тупит именно получение остатков (результат по остаткам есть смысл писать во временную таблицу). Смотреть на структуру регистра (нет ли измерений между Номенклатурой и Партией, например). Если есть возможность - прогнать эти тесты на серверной базе, на мс скуле. Тут вам поможет штатный профайлер скуля.
Чтобы обнаруживать ошибки, программист должен иметь ум, которому доставляет удовольствие находить изъяны там, где, казалось, царят красота и совершенство. Фредерик Брукс-младший