Форум 1С
Программистам, бухгалтерам, администраторам, пользователям
Задай вопрос - получи решение проблемы
14 дек 2024, 09:33

Ошибка в запросе

Автор Кобзик, 22 сен 2023, 09:45

0 Пользователей и 1 гость просматривают эту тему.

Кобзик

Доброго времени суток. Изучаю 1с и параллельно пытаюсь практиковаться. Суть такая запроса в том, что требуется рассчитать себестоимость по фифо. Как я это вижу и делал: Создаем запрос из регистра накопления "ТоварыНаСкладах", в нем же мы выбираем с помощью вложенного запроса(виртуальной таблицы) выбираем только ту номенклатуру, которая указывается в нашем документе "РеализацияТоваров". Подскажите, пожалуйста. Почему мой прием не работает и куда копать? Конфигурацию БД прилагаю

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТоварыНаСкладахОстатки.Партия,
| ЕСТЬNULL(ТоварыНаСкладахОстатки.КоличествоОстаток, 0) КАК КоличествоОстаток,
| ЕСТЬNULL(ТоварыНаСкладахОстатки.СтоимостьОстаток, 0) КАК СтоимостьОстаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(
| &МоментВремени,
| Склад = &Склад
| И Номенклатура В
| (ВЫБРАТЬ
| РеализацияТоваров.Товар.( РеализацияТоваров.Товар.Товар КАК Товар,
| РеализацияТоваров.Товар.Количество КАК Количество)
| ИЗ
| Документ.РеализацияТоваров КАК РеализацияТоваров
| ГДЕ
| РеализацияТоваров.Ссылка = &Ссылка)) КАК ТоварыНаСкладахОстатки
|
|УПОРЯДОЧИТЬ ПО
| ТоварыНаСкладахОстатки.Партия.Дата";





Запрос.УстановитьПараметр("МоментВремени", МоментВремени());
Запрос.УстановитьПараметр("Склад", Склад);
Запрос.УстановитьПараметр("Ссылка", Ссылка);

РезультатЗапроса = Запрос.Выполнить();

ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();

ОсталосьСписать = ВыборкаДетальныеЗаписи.Количество;


Пока ВыборкаДетальныеЗаписи.Следующий() И ОсталосьСписать > 0 Цикл

Движение = Движения.ТоварыНаСкладах.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Период = Дата;
Движение.Склад = Склад;
Движение.Номенклатура = ВыборкаДетальныеЗаписи.Товар;
Движение.Количество = МИН(ОсталосьСписать,ВыборкаДетальныеЗаписи.КоличествоОстаток);
Движение.Партия =  ВыборкаДетальныеЗаписи.Партия;


Если Движение.Количество  =  ВыборкаДетальныеЗаписи.КоличествоОстаток Тогда
Движение.Стоимость =  ВыборкаДетальныеЗаписи.СтоимостьОстаток;
Иначе
Движение.Стоимость =  Движение.Количество / ВыборкаДетальныеЗаписи.КоличествоОстаток * ВыборкаДетальныеЗаписи.СтоимостьОстаток;
КонецЕсли;

ОсталосьСписать = ОсталосьСписать - Движение.Количество ;

КонецЦикла;

 

Kvark5d

Кобзик, что именно не работает?

Максим75

Кобзик, зачем в условие отбора по виртуальной таблице в товарах еще кол-во?
отбираете только по нужной номенклатуре, а уже потом при обходе результата запроса по партиям учитываете какое кол-во надо списать, какое уже списали, какое осталось списать.

Кобзик

Kvark5d, При создании документа "Реализация товаров" выпадет ошибка "Ошибка SDBL: Вложенный результат в запросе, вложенный в IN"

Кобзик

Максим75, Спасибо. Это поправил, но тем не менее, основная проблема не решена)

Максим75

вынесите отбор товаров по временный запрос.
а потом уже в основном запросе товары отбирайте из этого временного запроса.
может в условиях отбора не обработать из-за параметра.
да и кол-во уберите в условиях отбора по Товару в виртуальной таблице.
посмотрите как в везде в типовых это реализовано.

Kvark5d

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

Максим75

Kvark5d, работает?
можно склад и товары сразу запихнуть в отбор виртуальной таблицы. так будет лучше для скорости работы, хотя на накладной Вы вряд ли замените, записей не так много.

и не совсем понятно, как Вы обрабатываете нехватку товара для списания.
Вы просто в цикле продолжаете, а необходимо отказать в проведении документа, если остатков не хватает. иначе документ проведется, отрицательные остатки не полезут и что? ну просемафорило пользователю, он болт забил, документ провел, а склад потом вешается, ищет товар.

посмотрите, как сейчас сама 1С рекомендует проверять на отрицательные остатки, есть у Чистова ролики. Смысл такой, что вначале делаются записи в регистр, а потом проверяют на отрицательные остатки, и при обнаружении выводят сообщения и Отказывают в проведении.

Kvark5d

Максим75, я же написал, что это очень примерно  :D Дальше пусть автор поста сам разбирается

Максим75

Kvark5d, извините, не глянул, от кого пост был.

Теги:

Похожие темы (5)

Рейтинг@Mail.ru

Поиск