Мы часто сталкиваемся с ситуациями, когда при программной работе с документами в 1С:Предприятии необходимо временно или полностью отключить стандартные проверки, которые выполняются при записи или проведении. Особенно это актуально для таких конфигураций, как 1С:Зарплата и кадры государственного учреждения (ЗКГУ) или 1С:Зарплата и управление персоналом (ЗУП), где документ "Отпуск сотрудников" имеет сложную логику проверок, связанную с кадровым учетом, расчетом остатков отпусков и пересечением периодов. Давайте вместе разберем, как можно решить эту задачу, используя различные подходы, основываясь на опыте разработчиков и возможностях платформы 1С. Мы рассмотрим несколько эффективных способов, каждый из которых имеет свои особенности и области применения.
Объект.ОбменДанными.Загрузка = Истина;
Один из наиболее распространенных и мощных механизмов для временного отключения проверок при программной записи объектов — это установка свойства Объект.ОбменДанными.Загрузка в значение Истина.
* **Назначение и принцип работы:** Платформа 1С и разработчики прикладных решений активно используют это свойство для обозначения того, что объект записывается в режиме обмена данными. Это означает, что данные пришли извне, и предполагается, что они уже прошли необходимую валидацию в источнике. Как следствие, многие стандартные проверки, будь то проверки заполнения обязательных реквизитов, логические проверки в обработчиках ПередЗаписью, ПриЗаписи или ОбработкаПроведения, могут быть проигнорированы, если в коде присутствует условие Если ОбменДанными.Загрузка Тогда Возврат; КонецЕсли;.
* **Применение:** Мы устанавливаем это свойство для объекта документа непосредственно перед вызовом метода Записать().
Давайте посмотрим на пример кода:
// Создаем новый документ "Отпуск сотрудников"
ДокументОтпуск = Документы.ОтпускСотрудников.СоздатьДокумент();
// Заполняем необходимые реквизиты документа
ДокументОтпуск.Сотрудник = Справочники.Сотрудники.НайтиПоКоду("00001");
ДокументОтпуск.ДатаНачала = '20240701';
ДокументОтпуск.ДатаОкончания = '20240714';
ДокументОтпуск.Организация = Справочники.Организации.НайтиПоКоду("001");
// ... заполняем другие обязательные или нужные реквизиты
// *** Важный шаг: отключаем проверки, устанавливая флаг загрузки ***
ДокументОтпуск.ОбменДанными.Загрузка = Истина;
Попытка
// Записываем документ.
// Мы можем выбрать режим записи:
// РежимЗаписиДокумента.Запись - только записывает, не проводит.
// РежимЗаписиДокумента.Проведение - записывает и проводит.
// Если нам нужно обойти проверки проведения, выбираем Проведение.
ДокументОтпуск.Записать(РежимЗаписиДокумента.Проведение);
Сообщить("Документ 'Отпуск сотрудников' успешно записан без стандартных проверок.");
Исключение
Сообщить("Произошла ошибка при записи документа: " + ОписаниеОшибки());
КонецПопытки;
* **Важно помнить:** Используя этот механизм, мы берем на себя полную ответственность за корректность и целостность записываемых данных. Если данные некорректны, это может привести к ошибкам в учете и расчетах.
ПриЗаписи() с помощью расширения
Когда требуется более глубокий контроль над логикой записи документа или необходимо полностью заменить стандартное поведение, мы можем использовать механизм расширений конфигурации. Это позволяет дорабатывать функционал без изменения основной конфигурации и снятия ее с поддержки.
* **Механизм расширений:** Расширения дают нам возможность изменять поведение существующих объектов (документов, справочников, отчетов) без прямого вмешательства в их код. Это особенно ценно при обновлениях типовых конфигураций.
* **Аннотация &ВместоПроцедура:** Эта аннотация позволяет нам полностью перехватить выполнение стандартной процедуры или функции модуля объекта и заменить ее своей собственной реализацией. В нашем случае, мы можем переопределить процедуру ПриЗаписи() модуля объекта документа "Отпуск сотрудников".
* **Гибкость:** Внутри переопределенной процедуры мы можем реализовать любую логику. Если нам нужно полностью отключить проверки, мы просто не включаем их в наш код. Если же нам нужно выполнить часть стандартной логики, а часть своей, мы можем использовать функцию ПродолжитьВызов().
Давайте проанализируем пример из форума и адаптируем его для практического применения:
1. **Создайте расширение:** В конфигураторе создайте новое расширение.
2. **Добавьте документ:** В расширение добавьте документ "Отпуск сотрудников".
3. **Переопределите процедуру:** В модуле объекта документа "Отпуск сотрудников" (в расширении) создайте процедуру ПриЗаписи() с аннотацией &ВместоПроцедура.
// В модуле объекта документа "Отпуск сотрудников" (в расширении)
&ВместоПроцедура ПриЗаписи()
#НачалоВставки
// Мы полностью перехватили стандартную процедуру ПриЗаписи().
// Здесь мы можем реализовать свою логику, которая НЕ включает
// стандартные проверки, которые мы хотим обойти.
// Например, если стандартная ПриЗаписи() содержит вызов ПроверитьЗаполнение()
// или другую сложную логику ЗКГУ, мы просто не включаем ее сюда.
// Если нам нужно выполнить какую-то свою проверку, мы можем ее добавить:
Перем ЕстьСвоиОшибки;
ЕстьСвоиОшибки = Ложь;
// Пример вашей собственной проверки (если нужна):
// Если Объект.ВидОтпуска.Пустая() Тогда
// Сообщить("Не указан вид отпуска!", СтатусСообщения.Внимание);
// ЕстьСвоиОшибки = Истина;
// КонецЕсли;
Если Не ЕстьСвоиОшибки Тогда
// Если своих ошибок нет, мы можем продолжить стандартное выполнение,
// но только той части, которая нам нужна, или полностью пропустить.
// Если мы хотим полностью отключить проверки, то здесь может быть
// просто завершение процедуры, или выполнение только той логики,
// которая не вызывает нежелательных проверок.
// Или, если нужно, вызываем оригинальную процедуру:
// ПродолжитьВызов(); // Вызовет оригинальную процедуру ПриЗаписи()
// Но если цель - "без проверки ЗКГУ", то мы просто не вызываем ПроверитьЗаполнение
// или иные проверки из стандартного кода.
// В контексте "без проверки ЗКГУ", мы просто не пишем здесь код,
// который эти проверки выполняет. Документ уже записан в базу,
// эта процедура вызывается после записи, но до окончания транзакции.
// Здесь мы могли бы влиять на движения или другие последствия записи.
// Если задача - просто записать без проверок, то этого достаточно.
// Если нам нужно было бы управлять проведением (что обычно делается в ОбработкаПроведения),
// то логика была бы другой. В ПриЗаписи() мы уже после записи в БД.
КонецЕсли;
// В данном примере, если мы ничего не делаем и не вызываем ПродолжитьВызов(),
// мы фактически "пусто" переопределяем процедуру, отключая всю её
// стандартную логику, которая могла бы быть в ПриЗаписи().
// Это и является способом обойти проверки, которые выполнялись бы здесь.
#КонецВставки
КонецПроцедуры
* **Важные моменты:**
* `&ВместоПроцедура ПриЗаписи()` полностью заменяет стандартную реализацию. Если в стандартной процедуре ПриЗаписи() содержатся важные действия (например, запись данных в регистры, не связанные с проведением), их придется воспроизвести в расширении, если они все еще нужны.
* Режим совместимости платформы может влиять на работу расширений. Убедитесь, что он настроен корректно.
Иногда проблема заключается не в общей логике записи, а в конкретных проверках заполнения реквизитов, которые мешают записать документ. Мы можем выборочно отключить эти проверки.
* **Процедура ОбработкаПроверкиЗаполнения:** Эта процедура в модуле объекта документа предназначена для формирования списка реквизитов, которые должны быть проверены на заполнение. Она вызывается при интерактивном вводе и иногда при программной записи.
* **Применение:** Мы можем переопределить эту процедуру в расширении и удалить из массива ПроверяемыеРеквизиты те элементы, проверку которых хотим отключить.
Давайте рассмотрим пример:
1. **Создайте расширение** и добавьте в него документ "Отпуск сотрудников".
2. **Переопределите процедуру** ОбработкаПроверкиЗаполнения:
// В модуле объекта документа "Отпуск сотрудников" (в расширении)
&ВместоПроцедура ОбработкаПроверкиЗаполнения(ПроверяемыеРеквизиты)
#НачалоВставки
// Сначала вызываем оригинальную процедуру, чтобы получить стандартный список реквизитов.
ПродолжитьВызов(ПроверяемыеРеквизиты);
// Теперь мы можем удалить из списка те реквизиты, которые не хотим проверять.
// Например, если мы не хотим проверять заполнение реквизита "ВидОтпуска"
// или "ОбоснованиеОтсутствия".
Для Индекс = ПроверяемыеРеквизиты.Количество() - 1 По 0 Цикл
Если ПроверяемыеРеквизиты[Индекс] = "ВидОтпуска" Тогда
ПроверяемыеРеквизиты.Удалить(Индекс);
ИначеЕсли ПроверяемыеРеквизиты[Индекс] = "ОбоснованиеОтсутствия" Тогда
ПроверяемыеРеквизиты.Удалить(Индекс);
КонецЕсли;
КонецЦикла;
// Теперь массив ПроверяемыеРеквизиты содержит только те реквизиты,
// которые мы хотим проверять.
#КонецВставки
КонецПроцедуры
* **Особенности:** Этот метод влияет только на проверки заполнения реквизитов. Он не отключает другие логические проверки, которые могут быть реализованы в ПередЗаписью, ПриЗаписи или ОбработкаПроведения.
Хотя внешняя обработка сама по себе не предоставляет механизмов переопределения внутренних процедур объектов, она является удобным инструментом для программной работы с документами. В контексте внешней обработки мы чаще всего будем использовать первый рассмотренный нами подход: установку свойства Объект.ОбменДанными.Загрузка = Истина; перед вызовом Записать().
* **Сценарий использования:** Если нам нужно однократно или по требованию создать или изменить документы без проверок, внешняя обработка с флагом ОбменДанными.Загрузка = Истина будет оптимальным решением.
Давайте посмотрим на пример кода для внешней обработки:
// В модуле внешней обработки
// Предполагаем, что у нас есть кнопка "Записать Отпуск Без Проверок"
&НаСервере
Процедура ЗаписатьОтпускБезПроверокНаСервере()
// Создаем новый документ "Отпуск сотрудников"
ДокументОтпуск = Документы.ОтпускСотрудников.СоздатьДокумент();
// Заполняем реквизиты документа (например, из полей формы обработки)
ДокументОтпуск.Сотрудник = МойСотрудник; // МойСотрудник - реквизит формы обработки
ДокументОтпуск.ДатаНачала = МояДатаНачала;
ДокументОтпуск.ДатаОкончания = МояДатаОкончания;
ДокументОтпуск.Организация = МояОрганизация;
// ... другие реквизиты
// Отключаем проверки
ДокументОтпуск.ОбменДанными.Загрузка = Истина;
Попытка
// Записываем и проводим документ
ДокументОтпуск.Записать(РежимЗаписиДокумента.Проведение);
Сообщить("Документ 'Отпуск сотрудников' успешно записан без стандартных проверок.");
Исключение
Сообщить("Произошла ошибка при записи документа: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Процедура ЗаписатьОтпускБезПроверок(Команда)
ЗаписатьОтпускБезПроверокНаСервере();
КонецПроцедуры
Мы выяснили, что обход стандартных проверок может быть необходим в определенных сценариях, таких как миграция данных, массовая загрузка или специфические интеграции. Однако, мы должны четко осознавать потенциальные риски: * **Нарушение целостности данных:** Отключение проверок может привести к записи некорректных данных, что, в свою очередь, повлияет на расчеты, отчетность и общую достоверность учета. * **Ошибки в учете ЗКГУ/ЗУП:** Документ "Отпуск сотрудников" в ЗКГУ/ЗУП тесно связан с кадровым учетом, расчетом зарплаты и рабочего времени. Некорректная запись может нарушить логику расчета среднего заработка, остатков отпусков, формирования табеля и т.д. * **Сложность отладки:** Если возникают проблемы, их будет сложнее диагностировать, поскольку стандартные механизмы валидации были отключены. **Всегда используйте эти методы с осторожностью и только при полном понимании последствий.** Перед применением на "боевой" базе, обязательно протестируйте изменения на копии. Надеемся, что этот подробный разбор поможет вам успешно решить задачу по программной записи документа "Отпуск сотрудников" без стандартных проверок в 1С:ЗКГУ!
← К списку