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

Проверка наличия товара

Автор Юлия56, 04 ноя 2014, 13:54

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

Юлия56

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

Сейчас при проверки кода выводит сообщение о том что переменная Результат и ПоставляемыеТовары не определена

tepliym

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

Примерно так, должно работать.

Юлия56

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


У меня еще один вопрос) Не смотря на то что выходит системное сообщение, я могу осуществить проведение и запись документа, а можно ее как-то запретить если система сообщила что остаток превышен??

tepliym


Цитата: Юлия56 от 04 ноя 2014, 16:23У меня еще один вопрос) Не смотря на то что выходит системное сообщение, я могу осуществить проведение и запись документа, а можно ее как-то запретить если система сообщила что остаток превышен??

А процедуре обработки проведения документа поставе оператор Возврат по нужному условию.

Юлия56

Спасибо за подсказку! Я не особо владею познаниями в области 1С ((( я напишу в процедуре Возврат "" , а как сформулировать это условие?? оно будет называться "Отменить проведение" ??

tepliym

Процедура ОбработкаПроведения(Отказ, РежимПроведения)

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

    Если Отказ Тогда
        Возврат;
    КонецЕсли;
ЭтотОбъект.Записать(РежимЗАписиДокумента.Проведение);

КонецПроцедуры

Юлия56

Спасибо большое!!!!
Только теперь когда осуществляется запись, а потом проведение нужных (верных)документов конфигурация зависает и программа не отвечает((

LexaK

Юлия56, 1С очень чувствительна к коду, одну и ту-же обработку можно написать оптимально и неоптимально, при оптимальном варианте все выполнится за пару секунд, при неоптимальном 1С будет висеть, а на самом деле все процессоры в поте лица будут выполнять ваш тупой код!
тот код что вы написали далек от оптимальности, поэтому 1С и висит.

в вашем случае, при проведении документа надо создать 1 ОДИН запрос и ОДИН раз его выполнить,
а не ТЫСЯЧУ раз как вы это делаете в цикле, перебирая товарную часть, у вас 1000 (а может и 10 000 , сколько товаров в товарной части?) раз вызывается расчет получение остатков, 1000 раз формируется новый запрос отправляется на сервер, там выполняется и возращается результат, и все это в тысячекратном размере!!! (да, не повезло фирме)

в вашей задаче надо оперировать сразу со всей табличной частью в запросе
примерный код процедуры проверки наличия остатков

пример ниже написан в другой базе, для другого документа и регистра,
просто замените на свои документ и регистр. (в примере есть еще пара мест которые можно оптимизировать, но это уже для любителей писать очень оптимальный код)


Процедура ОбработкаПроведения(Отказ, РежимПроведения)

Отказ = ПроверкаОстатков();
Если Отказ Тогда
//проверка не прошла, все сообщения сделаны в функции,
//просто выходим
Возврат;
КонецЕсли;

//здесь дальнейший код по проведению документа!

КонецПроцедуры

Функция ПроверкаОстатков()

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

лкЗапрос.УстановитьПараметр("Дата",Дата);
лкЗапрос.УстановитьПараметр("Ссылка",Ссылка);
лкРезультат = лкЗапрос.Выполнить();

Если лкРезультат.Пустой() Тогда
//результат пустой,
//значит в документе нет Товара по которому нехватает остатка
Возврат Ложь;
КонецЕсли;

лкРезультат = лкРезультат.Выгрузить();
//выводим одну строку - заголовок, информция о проводимом документе
//всегда помним о пакетных обработках!!!
Сообщить("Нехватает остатков по документу: " + Ссылка);
//вместо сообщить можно использовать другие методы, лог в файл
Для каждого лкСтр Из лкРезультат Цикл
//здесь выводим только сообщения по нехватке количества
//указываем товар, сколько надо отгрузить, и какой остаток
Сообщить("Товар: " + лкСтр.Номенклатура
   + " требуется: " + лкСтр.Количество
   + " вналичии: " + лкСтр.Остаток );
КонецЦикла;

//Отказ будет Истина, документ не запишется и не проведется!
Возврат Истина;

КонецФункции //




если помогло нажмите: Спасибо!

cska-fanat-kz

tepliym, зачем вы учите других писать неоптимальный код? ((((((((
1. Условие на номенклатуру делается в виртуальных параметрах, иначе сперва получаются остатки по ВСЕЙ номенклатуре, а потом из всей массы отсекается нужная номенклатура.
2. В конце обработки проведения не надо делать "ЭтотОбъект.Записать(РежимЗАписиДокумента.Проведение);"! Запись произойдет своим чередом после окончания выполнения процедуры ОбработкаПроведения().
3. "Если Отказ Тогда
        Возврат;
    КонецЕсли;"
Возврат из процедуры проведения следует делать если дальше идет какой нибудь значимый код (формирование движений и т.д.). А у вас это в конце процедуры написано. Смысл тогда?
4. Тем более запрос в цикле!!
Получил помощь - скажи СПАСИБО.
Разобрался сам - расскажи другим.

tepliym

Цитата: cska-fanat-kz от 05 ноя 2014, 06:12
tepliym, зачем вы учите других писать неоптимальный код? ((((((((
1. Условие на номенклатуру делается в виртуальных параметрах, иначе сперва получаются остатки по ВСЕЙ номенклатуре, а потом из всей массы отсекается нужная номенклатура.
2. В конце обработки проведения не надо делать "ЭтотОбъект.Записать(РежимЗАписиДокумента.Проведение);"! Запись произойдет своим чередом после окончания выполнения процедуры ОбработкаПроведения().
3. "Если Отказ Тогда
        Возврат;
    КонецЕсли;"
Возврат из процедуры проведения следует делать если дальше идет какой нибудь значимый код (формирование движений и т.д.). А у вас это в конце процедуры написано. Смысл тогда?
4. Тем более запрос в цикле!!
Никого я не учу, девушка обратилась с своим кодом, я сделал так что б он работал и все .

Теги:

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

Рейтинг@Mail.ru

Поиск