В процессе разработки внешних обработок для конфигурации «Управление производственным предприятием» (УПП) программисты часто сталкиваются с ситуацией, когда необходимо программно создать и провести документ РеализацияТоваровУслуг. Одной из типичных проблем является жесткий контроль остатков, установленный в настройках пользователя или учетной политике. Особенно остро это проявляется, когда документ создается как промежуточное звено (например, для печати счета-фактуры), а точные данные о сериях товаров на момент формирования документа еще отсутствуют.
В этой статье мы подробно разберем, какими методами можно временно «усыпить бдительность» системы, чтобы провести документ даже при отсутствии товара на складе или незаполненных сериях. Мы проанализируем различные подходы — от самых простых до профессиональных методов, используемых в архитектуре 1С.
Разберем самый простой и эффективный способ, который помог автору вопроса. В платформе 1С существует два режима проведения документа: оперативный и неоперативный. Оперативный режим предназначен для отражения текущих событий «здесь и сейчас» и всегда включает в себя контроль остатков на текущий момент времени. Неоперативный режим используется для исправления прошлых периодов или ввода документов «задним числом».
Проанализируем, как это реализовать в коде внешней обработки. При вызове метода Записать() нам нужно явно указать режим проведения:
// Получаем объект документа
ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
// Устанавливаем режим проведения — Неоперативный
// Это позволит обойти проверку остатков, которая настроена для оперативной работы
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Неоперативный);
Почему это работает? В большинстве типовых механизмов УПП встроенная проверка остатков срабатывает только в том случае, если РежимПроведения равен РежимПроведенияДокумента.Оперативный. При неоперативном проведении система предполагает, что данные вводятся за прошедшее время, и контроль остатков либо отключается вовсе, либо проверяется по иным алгоритмам.
Рассмотрим ситуацию, когда даже неоперативное проведение блокируется системой из-за жестких настроек в дополнительных правах пользователя. В УПП существует настройка «Разрешить превышение остатка товаров на складе». Если мы не хотим менять ее вручную для пользователя, мы можем попытаться подменить ее значение в кэше на время выполнения нашего кода.
Выясним, как программа проверяет это право. Обычно это обращение к функции ДополнительныеПраваПользователя. Мы можем программно изменить настройки в текущем сеансе, провести документ и вернуть их обратно. Однако, более безопасный путь — это использование механизма передачи параметров напрямую в объект документа.
Посмотрим на более «продвинутый» способ, который часто используют разработчики конфигураций. У каждого объекта 1С есть коллекция ДополнительныеСвойства. Это структура, данные из которой видны в модуле документа (в процедурах ПередЗаписью и ОбработкаПроведения).
Если мы заглянем внутрь модуля документа РеализацияТоваровУслуг в УПП, мы можем увидеть, что алгоритм проведения проверяет определенные флаги. Попробуем передать такой флаг программно:
ДокументОбъект = ДокументСсылка.ПолучитьОбъект();
// Добавляем флаг отказа от контроля остатков в дополнительные свойства объекта
// Название ключа может отличаться в зависимости от версии УПП (например, "ОтказОтКонтроляОстатков")
ДокументОбъект.ДополнительныеСвойства.Вставить("ОтказОтКонтроляОстатков", Истина);
// Теперь при проведении код внутри документа может увидеть этот флаг и пропустить проверку
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
Этот метод хорош тем, что он не влияет на глобальные настройки пользователя и работает только для конкретного экземпляра объекта, который мы обрабатываем в коде.
Разберем радикальный способ — использование свойства ОбменДанными.Загрузка. Многие начинающие разработчики считают его «панацеей» для записи документов без проверок. Выглядит это так:
ДокументОбъект = ДокументСсылка.ПолучитьОбъект();
ДокументОбъект.ОбменДанными.Загрузка = Истина;
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
Важно понимать последствия: когда это свойство установлено в Истина, платформа отключает выполнение кода в процедуре ОбработкаПроведения. Документ в списке будет помечен как проведенный («зеленая галочка»), но движения по регистрам созданы не будут. Если ваша цель — просто создать документ-основание для Счета-фактуры и вам абсолютно не важны проводки и остатки по складам, этот метод подойдет. Но если вы хотите, чтобы товар все-таки списался (пусть и «в минус»), этот метод использовать нельзя.
Если основной причиной ошибки является отсутствие серий, мы можем применить хитрость: временно заполнить серии «фиктивными» данными. Проанализируем этот алгоритм:
Товары или СерииНоменклатуры этими данными.Рассмотрим пример кода для подбора серии:
Для Каждого СтрокаТовара Из ДокументОбъект.Товары Цикл
Если СтрокаТовара.Номенклатура.ВестиУчетПоСериям Тогда
// Здесь можно написать запрос к остаткам и выбрать любую доступную серию
СтрокаТовара.СерияНоменклатуры = НайтиЛюбуюСерию(СтрокаТовара.Номенклатура);
КонецЕсли;
КонецЦикла;
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
Иногда контроль остатков завязан на правах доступа (RLS) или программных проверках, которые анализируют роль текущего пользователя. В таком случае мы можем обернуть код проведения в вызов привилегированного режима. Это позволит выполнить операцию с правами администратора, для которого ограничения могут быть отключены.
УстановитьПривилегированныйРежим(Истина);
// Выполняем проведение документа
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
УстановитьПривилегированныйРежим(Ложь);
Обратите внимание, что это сработает только в том случае, если в коде ОбработкаПроведения есть явное условие вида: Если Не РольДоступна("ПолныеПрава") Тогда ВыполнитьКонтроль(); КонецЕсли;.
Мы рассмотрели несколько способов решения проблемы. Подведем итоги того, какой метод выбрать в зависимости от ситуации:
Помните, что отключение контроля остатков — это ответственная операция. Всегда анализируйте, как это повлияет на последующую работу бухгалтерии и склада, чтобы избежать путаницы в учете.