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