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