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