Почему при отключенном превышении остатков документы проводятся в минус задним числом и как это исправить?

Программист 1С v8.3 (Обычные формы) Управленческий учет Торговля и дистрибуция
← На главную

При настройке прав и дополнительных прав пользователей в типовых конфигурациях 1С (таких как «Управление торговым предприятием», «Управление торговлей 10.3», «Управление производственным предприятием» и «Комплексная автоматизация») администраторы часто сталкиваются с неочевидной ситуацией. В дополнительных настройках пользователя флажок «Разрешить превышение остатка товаров на складе» снят, однако при проведении расходных накладных задним числом или документов, добавленных копированием, система без каких-либо предупреждений списывает товар «в минус». Разберем подробно, почему так происходит и какие существуют методы исправления этой ситуации.

Выясним причину такого поведения типового функционала. В платформе 1С:Предприятие существует два режима проведения документов: оперативный и неоперативный. Флажок дополнительных настроек пользователя «Разрешить превышение остатка товаров на складе» анализируется кодом конфигурации только тогда, когда параметр РежимПроведения равен значению РежимПроведенияДокумента.Оперативный. Если документ проводится прошлым временем (неоперативно), блок проверки остатков в типовом коде просто пропускается платформой. Эта настройка изначально проектировалась для контроля действий менеджера в текущем времени («в моменте»), чтобы не допустить отгрузку фактически отсутствующего на складе товара, но она не предназначена для регламентации ввода данных задним числом.

Проанализируем технические сложности контроля остатков задним числом. Простая проверка остатка на МоментВремени проводимого документа не гарантирует целостность складского учета: если партия товара была законно списана следующим днем, проведение документа задним числом все равно приведет к отрицательному остатку на следующий день или на текущий момент. Полный же контроль остатков на всем интервале от даты документа до текущего момента требует наложения широких управляемых блокировок и чтения больших объемов движений регистра накопления ТоварыНаСкладах, что существенно замедляет параллельную работу пользователей в базе данных. Тем не менее, если бизнес-процессы компании требуют строгого запрета минусов даже в прошлом, задачу можно решить несколькими путями.

Способ 1. Запрет неоперативного проведения в правах пользователя

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

  1. Откроем конфигурацию или панель администрирования прав доступа.
  2. Найдем неполноправную роль, назначенную менеджерам по продажам или складским операторам.
  3. В дереве метаданных найдем документы списания (например, РеализацияТоваровУслуг или ТребованиеНакладная).
  4. Снимем флажок с права «Интерактивное проведение неоперативное».

В результате пользователи смогут проводить документы только текущим временем сеанса. При попытке провести документ оперативно конфигурация отработает в штатном режиме: проверит значение настройки «Разрешить превышение остатка товаров на складе» и заблокирует операцию при нехватке свободного остатка.

Способ 2. Установка даты запрета изменения данных

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

Для исключения этой ситуации включим в конфигурации механизм «Граница запрета изменения данных». Установим границу запрета концом вчерашнего дня для всех пользователей, не имеющих полных прав. Это гарантирует, что менеджеры смогут вводить и проводить документы исключительно текущей датой, где списание всегда происходит в оперативном режиме с обязательным контролем остатков.

Способ 3. Автоматическая актуализация времени документа при копировании

Посмотрим на практическую проблему: когда пользователь создает документ методом копирования, платформа переносит из оригинала не только состав строк, но и дату старого документа. Если пользователь нажимает кнопку проведения, документ проводится неоперативно.

Чтобы избежать этой ошибки, дополним обработчик события ПередЗаписью в модуле объекта документа или в расширении. Проверим, является ли документ новым, и установим актуальное время сеанса:


Если ЭтоНовый() Тогда
    Дата = ТекущаяДатаСеанса();
КонецЕсли;

Благодаря этому при интерактивном копировании документа его дата сразу становится актуальной, и проведение документа выполняется в штатном оперативном режиме с проверкой всех ограничений пользователя.

Способ 4. Программный контроль остатков через подписку на событие

Если бизнес-процесс неизбежно требует проведения расходных накладных задним числом, но появление минусов на складе категорически недопустимо, реализуем собственный механизм проверки. Для этого создадим подписку на событие ОбработкаПроведения для целевых документов.

Разберем логику обработчика: если у текущего пользователя в регистре сведений НастройкиПользователей отключено превышение остатков, а документ проводится неоперативно, мы выполним запрос к виртуальной таблице Остатки регистра накопления ТоварыНаСкладах на момент времени документа.


Процедура КонтрольОстатковПриНеоперативномПроведении(Источник, Отказ, РежимПроведения) Экспорт

    Если РежимПроведения = РежимПроведенияДокумента.Оперативный Тогда
        Возврат; // Оперативный режим уже проверяется типовым кодом
    КонецЕсли;

    // Проверяем настройку пользователя в регистре или параметрах сеанса
    ЗапретитьПревышение = Истина; // Считывается из регистра НастройкиПользователей
    Если Не ЗапретитьПревышение Тогда
        Возврат;
    КонецЕсли;

    ГраницаКонтроля = Новый Граница(Источник.МоментВремени(), ВидГраницы.Включая);

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

    Запрос.УстановитьПараметр("ГраницаКонтроля", ГраницаКонтроля);
    Запрос.УстановитьПараметр("Склад", Источник.Склад);
    Запрос.УстановитьПараметр("СписокНоменклатуры", Источник.Товары.ВыгрузитьКолонку("Номенклатура"));

    Результат = Запрос.Выполнить();
    Если Не Результат.Пустой() Тогда
        Выборка = Результат.Выбрать();
        Пока Выборка.Следующий() Цикл
            ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
                СтрШаблон("По товару %1 зафиксирован отрицательный остаток: %2", Выборка.Номенклатура, Выборка.КоличествоОстаток)
            );
        КонецЦикла;
        Отказ = Истина;
    КонецЕсли;

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

Для максимальной строгости учета в этот же запрос можно включить получение остатков на текущую дату, передав срез без параметров времени. Это позволит заблокировать проведение задним числом, если в прошлом товара хватало, но его списание задним числом приведет к дефициту на текущий момент времени.

← На главную