Контроль остатков и резервы в 1С
Контроль остатков отказывает в проведении, если расход уводит остаток в минус. Платформа сама этого не делает, поэтому собес проверяет, умеешь ли ты его написать, учесть резервы и показать пользователю внятную ошибку.
// Так спрашивают: «Как посчитать свободный остаток?» «Почему нельзя проверять остатки в форме?» «Что делать, если пользователи долго ждут блокировок?» «Как показать ошибку на конкретной строке?»
Свободный остаток
Резерв закрепляет часть остатка за заказом. Свободный остаток равен остатку минус резервы, и продать можно только его. Остатки и резервы лежат в разных регистрах, поэтому их соединяют левым соединением: у товара без резервов резерв придёт NULL, и его закрывают ЕСТЬNULL.
Без ЕСТЬNULL хлеб получил бы NULL вместо 10: вычитание NULL даёт NULL, и товар без резервов выглядел бы недоступным. Отгрузка по заказу уменьшает и остаток, и резерв. Если резерв не снять, свободный остаток навсегда занизится на отгруженное.
ВЫБРАТЬ
Остатки.Номенклатура,
Остатки.КоличествоОстаток - ЕСТЬNULL(Резервы.КоличествоОстаток, 0) КАК Свободно
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыВРезерве.Остатки КАК Резервы
ПО Остатки.Номенклатура = Резервы.Номенклатура
И Остатки.Склад = Резервы.СкладПочему не в форме
Проверка в форме при выборе товара удобна пользователю, но ничего не гарантирует: форма видит остаток на момент открытия, а параллельно продают кассы и другие менеджеры. Гарантию даёт только проверка при проведении под блокировкой, внутри транзакции.
Минус бывает нормой: для виртуальных складов, товаров под заказ, комиссии. Такие склады исключают условием в запросе проверки, а не отключают контроль целиком.
Сообщение на строке
Пользователь должен увидеть, какая строка не прошла и сколько не хватает. Сообщение привязывают к полю табличной части путём вида Товары[3].Количество, и форма подсветит ячейку. В типовых на библиотеке стандартных подсистем (БСП) для этого есть ОбщегоНазначения.СообщитьПользователю:
Текст = СтрШаблон(НСтр("ru = 'Не хватает %1: нужно %2, свободно %3'"),
Выборка.Номенклатура, Выборка.Нужно, Выборка.Свободно);
Поле = ОбщегоНазначенияКлиентСервер.ПутьКТабличнойЧасти("Товары", Выборка.НомерСтроки, "Количество");
ОбщегоНазначения.СообщитьПользователю(Текст, ЭтотОбъект, Поле, , Отказ);Когда ждут блокировок
Ожидание блокировки равно времени транзакции того, кто её держит. Поэтому долгое ожидание лечат не отключением блокировок, а короткой транзакцией: без внешних вызовов, без записи справочников, без запросов в цикле. Отключение блокировок возвращает гонки, и два документа снова спишут один остаток.
Как отвечать: «Как посчитать свободный остаток и где его проверять?»
Свободный остаток равен остатку на складе минус резервы. Беру виртуальную таблицу остатков склада и левым соединением резервы по товару и складу, резерв закрываю ЕСТЬNULL, иначе товар без резервов получит NULL. Проверяю при проведении под управляемой блокировкой, потому что форма не видит параллельных документов. А при отгрузке по заказу списываю и резерв, иначе свободный остаток занизится.
В ответе есть формула, техника соединения с ЕСТЬNULL, место проверки и побочный эффект отгрузки. Всё, на чём реально ломается контроль резервов.
На чём валят
- −Проверяют остатки только в форме при выборе товара. Форма не видит параллельных документов. Проверка при проведении под блокировкой.
- −Соединяют остатки с резервами без ЕСТЬNULL. Товар без резервов получит NULL. Резерв закрывают ЕСТЬNULL(…, 0).
- −Отгружают по заказу и не снимают резерв. Свободный остаток занижается навсегда. Отгрузка списывает и остаток, и резерв.
- −Отключают блокировки, чтобы не ждать. Возвращаются гонки и минусы. Сокращают транзакцию.
Проверь себя
Пять вопросов из банка по этой подтеме. Всего их 12, остальные разбираются в тренажёре.
- Свободный остаток = остаток на складе минус резервы. Как получить его запросом?A)Сумма остатков и резервовB)Внутреннее соединение остатков и резервов по товаруC)Остатки ЛЕВОЕ резервы, разностьD)Остатки склада с условием по резервам в ГДЕ
показать ответ и разбор
+C)Остатки ЛЕВОЕ резервы, разность// разбор: Резервы есть не у каждого товара, поэтому остатки склада соединяют с резервами левым соединением и вычитают ЕСТЬNULL(Резерв, 0). Внутреннее соединение выкинет товары без резервов, сумма даст бессмыслицу. Аккуратнее — объединение двух таблиц с разными знаками и группировка.
- Заказ клиента резервирует товар. Что должно произойти с резервом при отгрузке по этому заказу?A)Резерв сохраняется до закрытия заказаB)Резерв снимается, остаток уменьшаетсяC)Резерв переходит на следующий заказ клиентаD)Резерв остаётся, а остаток уменьшается вдвое
показать ответ и разбор
+B)Резерв снимается, остаток уменьшается// разбор: Отгрузка уменьшает фактический остаток и одновременно снимает резерв по заказу: товар ушёл к клиенту, держать его больше не нужно. Документ реализации пишет расход в регистр остатков и расход в регистр резервов по заказу. Если резерв не снять, свободный остаток занизится навсегда.
- Документ задним числом списывает товар, на момент документа остаток есть, но на сегодня товара уже нет. Как поведёт себя контроль по текущему остатку?A)Откажет: итог уходит в минусB)Пропустит: на момент документа остаток естьC)Пропустит без проверки: документ прошлой датойD)Перепроведёт хвост
показать ответ и разбор
+A)Откажет: итог уходит в минус// разбор: Если проверять остаток на конец учёта, списание задним числом уведёт его в минус, и документ не проведётся. Если проверять на момент документа, он пройдёт, а минус появится у последующих операций. Выбор зависит от политики компании, но второй вариант требует перепроведения последующих документов.
- Как сообщить пользователю о нехватке так, чтобы клик по сообщению вёл к строке табличной части?A)
ПоказатьПредупреждениес номером строки на сервереB)Сообщить()с номером строкиC)ВызватьИсключениес номером строки в текстеD)Сообщение с путём к полю строкипоказать ответ и разбор
+D)Сообщение с путём к полю строки// разбор: Сообщение пользователю можно привязать к полю: объекту и пути вида Товары[3].Количество. Тогда клик переводит курсор на ячейку. В БСП это функция СообщитьПользователю с параметрами КлючДанных и Поле, внутри — объект СообщениеПользователю. Обычный Сообщить привязки не даёт.
- Два кассира одновременно проводят чеки на последнюю единицу товара. Контроль по новой методике с
БлокироватьДляИзменения. Что произойдёт?A)Второй проведётся раньше первого и заберёт товарB)Оба чека проведутся, остаток станет -1C)Оба получат отказ из-за конфликтаD)Второй дождётся первого и получит отказпоказать ответ и разбор
+D)Второй дождётся первого и получит отказ// разбор: Первый чек пишет движения и блокирует сочетание товара и склада. Второй при записи своих движений ждёт снятия блокировки. Первый фиксируется с остатком 0, второй после ожидания записывает расход, проверка видит -1, и проведение отменяется.
дальше
Теорию прочитал. Навык ставится повторением
В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, бесплатная часть практики — одна сессия дня в сутки.