В типовых решениях «1С:Управление торговлей 11», «1С:ERP» и «1С:Комплексная автоматизация» многие разработчики и администраторы сталкиваются с особенностью: система позволяет проводить реализацию даже при отсутствии товара у конкретной организации, если в настройках включен контроль остатков. Выясняется, что проверка по регистру ТоварыОрганизаций выполняется не на момент отгрузки, а на конец месяца. Рассмотрим, почему это сделано именно так, и разберем способы, как реализовать проверку «на текущую секунду».
Проанализируем архитектуру системы. В программе разделены два понятия: физический остаток (регистр ТоварыНаСкладах) и право собственности (регистр ТоварыОрганизаций). Физический контроль всегда оперативный — вы не сможете отгрузить товар, которого нет на полке. Однако контроль организаций работает иначе из-за механизма Интеркампани.
Схема Интеркампани предполагает, что одна организация может продавать товар другой. При этом документы «Передача товаров между организациями» часто оформляются не в момент продажи, а сводно в конце отчетного периода (месяца). Если бы система жестко блокировала продажу в середине месяца из-за отсутствия остатка на конкретном юридическом лице, работа схемы Интеркампани была бы парализована. Именно поэтому разработчики «1С» заложили логику: внутри месяца могут возникать отрицательные остатки по организациям, которые должны быть закрыты передачами к моменту закрытия месяца.
Прежде чем приступать к доработке, важно осознать последствия. Если мы переключим контроль на дату документа:
Разберем, как «красиво» вписаться в типовой код, о чем и спрашивал автор темы. Основная логика контроля сосредоточена в общем модуле ЗапасыСервер. Функция, отвечающая за подготовку данных контроля, — ДобавитьКонтрольПоТоварамОрганизаций.
В типовом коде период контроля определяется как ГраницаПериода(ДатаДокумента, Месяц). Чтобы изменить это поведение, нам необходимо воспользоваться механизмом расширений. Мы можем применить аннотацию &Вместо или &ИзменениеИВоВремя для перехвата момента формирования структуры контроля.
Рассмотрим пример кода, который можно разместить в расширении для изменения даты контроля:
&Вместо("ДобавитьКонтрольПоТоварамОрганизаций")
Процедура Мой_ДобавитьКонтрольПоТоварамОрганизаций(СтруктураКонтроля, ПараметрыПроведения)
// Вызываем стандартный обработчик, чтобы структура заполнилась типовыми полями
ПродолжитьВызов(СтруктураКонтроля, ПараметрыПроведения);
// Находим нужный нам элемент контроля в массиве структур
Для Каждого ЭлементКонтроля Из СтруктураКонтроля.ЭлементыКонтроля Цикл
Если ЭлементКонтроля.ИмяРегистра = "ТоварыОрганизаций" Тогда
// Подменяем период контроля с конца месяца на дату документа
ЭлементКонтроля.Период = ПараметрыПроведения.ТочкаВремени;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Этот метод считается наиболее корректным, так как мы не переписываем весь запрос формирования остатков, а лишь корректируем параметр Период, который система позже передаст в менеджер временных таблиц для расчета остатков.
Если вы новичок и боитесь вмешиваться в сложные механизмы ЗапасыСервер, проанализируем более безопасный вариант — создание собственной проверки «поверх» типовой. Для этого создадим Подписку на событие ОбработкаПроведения для документов РеализацияТоваровУслуг.
Выясним алгоритм действий для этого способа:
ОбработкаПроведения.ТоварыОрганизаций.Остатки.Пример реализации запроса для проверки остатков:
Процедура ПроверитьОстаткиОрганизацииПередПроведением(Источник, Отказ, РежимПроведения) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТоварыОрганизацийОстатки.Номенклатура,
| ТоварыОрганизацийОстатки.КоличествоОстаток КАК Остаток
|ИЗ
| РегистрНакопления.ТоварыОрганизаций.Остатки(&МоментВремени,
| Организация = &Организация И Номенклатура В (&СписокНоменклатуры)) КАК ТоварыОрганизацийОстатки
|ГДЕ
| ТоварыОрганизацийОстатки.КоличествоОстаток < 0";
Запрос.УстановитьПараметр("МоментВремени", Источник.МоментВремени());
Запрос.УстановитьПараметр("Организация", Источник.Организация);
Запрос.УстановитьПараметр("СписокНоменклатуры", Источник.Товары.ВыгрузитьКолонку("Номенклатура"));
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Недостаточно остатка по организации " + Источник.Организация +
" для товара " + Выборка.Номенклатура + ". Остаток: " + Выборка.Остаток;
Сообщение.Сообщить();
Отказ = Истина;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Важный нюанс: Этот метод сработает только в том случае, если в системе уже зафиксированы движения. Поскольку подписка срабатывает в процессе проведения, нужно убедиться, что запрос учитывает текущий документ. Однако проще и надежнее использовать Способ №1, так как он интегрирован в штатный механизм проведения, который умеет правильно работать с временными таблицами еще не записанных движений.
Перед тем как приступать к написанию кода, убедимся, что включена базовая опция контроля. Перейдем в раздел НСИ и администрирование — Настройка НСИ и разделов — Финансовый результат и контроллинг. В группе «Учет товаров» должен быть установлен флаг Контролировать остатки товаров организаций.
Помните, что эта галочка включает контроль именно в том виде, в котором его задумала «1С» (на конец месяца). Наши доработки лишь уточняют момент времени, на который этот контроль выполняется.
Подведем итоги. Для реализации жесткого контроля остатков организаций на дату реализации в УТ 11.4 оптимально использовать расширение для модуля ЗапасыСервер. Это позволит:
Совет для начинающих: Прежде чем внедрять такие изменения в рабочую базу, обязательно протестируйте их на копии в сценарии Интеркампани, чтобы убедиться, что менеджеры по продажам не потеряют возможность оформлять сделки между своими юрлицами.