К статье
Практический материал

Разработка и Конфигурация · 13 мин

Как отменить проведение документа в 1С программно

Как программно отменить проведение документа в 1С: метод Записать с РежимЗаписиДокумента.ОтменаПроведения, проверка прав, обработка ошибок и примеры кода.

Отмена проведения документа программным способом — стандартная задача при разработке обработок, обменов данными и регламентных операций в 1С. В отличие от интерактивной отмены, где пользователь нажимает кнопку в форме, программный вызов требует явного получения объекта документа, записи его в специальном режиме и контроля ошибок, которые в интерактивном режиме платформа показывает пользователю автоматически.

Основной инструмент — метод Записать() объекта документа с параметром РежимЗаписиДокумента.ОтменаПроведения. Всё остальное — проверки, транзакции и обработка исключений — строится вокруг этого вызова. Ниже разобраны рабочие примеры кода, типовые проверки, отличия тонкого клиента от сервера и ошибки, которые чаще всего приводят к сбоям.

Материал ориентирован на управляемые формы и платформу 8.3, но базовый подход одинаков и для обычных форм: объектная модель документа везде одна.

Базовый способ: метод Записать с режимом ОтменаПроведения

Документ в 1С существует в двух ипостасях: ссылка (лёгкий указатель на запись в базе) и объект (полноценная структура данных с методами). Отмена проведения возможна только через объект. Поэтому первый шаг — получить объект по ссылке методом ПолучитьОбъект().

Минимальный работающий код выглядит так:

ДокументОбъект = ДокументСсылка.ПолучитьОбъект();

ДокументОбъект.Записать(РежимЗаписиДокумента.ОтменаПроведения);

bsl
ДокументОбъект = ДокументСсылка.ПолучитьОбъект();
Если ДокументОбъект.Проведен Тогда
    ДокументОбъект.Записать(РежимЗаписиДокумента.ОтменаПроведения);
КонецЕсли;

Метод Записать() с параметром РежимЗаписиДокумента.ОтменаПроведения удаляет движения документа по всем регистрам, в которых он был регистратором, и сбрасывает признак Проведен. Сам документ при этом остаётся в базе — удаляются только его движения.

Важно понимать: при отмене проведения срабатывают те же обработчики событий, что и при интерактивной отмене — ОбработкаУдаленияПроведения в модуле объекта, подписки на события, контроль закрытого периода. Если в конфигурации в обработчике стоит Отказ = Истина при определённых условиях, программная отмена тоже будет отклонена.

Проверки перед отменой проведения

Программная отмена без предварительных проверок — частый источник исключений и «падений» обработок. Минимальный набор проверок, который стоит выполнять всегда:

  • документ проведён — иначе отмена проведения бессмысленна и вызовет ошибку;
  • документ не помечен на удаление — объект помеченного документа нельзя записать в режиме отмены проведения;
  • дата документа не попадает в закрытый период (дата запрета изменения данных);
  • у текущего пользователя есть права на изменение документа и отмену его проведения.
Контрольные точки

Что проверить перед отменой

Признак Проведен
Норма

ДокументСсылка.Проведен = Истина

Тревожный признак

Ложь — отменять нечего, будет ошибка

Пометка удаления
Норма

ПометкаУдаления = Ложь

Тревожный признак

Истина — сначала снимите пометку

Закрытый период
Норма

Дата документа позже даты запрета

Тревожный признак

Дата в закрытом периоде — запись будет отклонена

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

Дату запрета изменения данных платформа проверит сама при записи, но лучше перехватить ситуацию заранее и выдать понятное сообщение, чем ловить общее исключение. Для проверки используется функциональная опция и константы даты запрета, либо типовые методы БСП (ДатыЗапретаИзменения.ИзменениеЗапрещено), если конфигурация на библиотеке стандартных подсистем.

Обработка ошибок и транзакции

Любой вызов Записать() может завершиться исключением: документ заблокирован другим пользователем, нарушены права, сработал отказ в обработчике. Поэтому программная отмена проведения всегда оборачивается в конструкцию Попытка/Исключение.

Попытка

ДокументОбъект = ДокументСсылка.ПолучитьОбъект();

ДокументОбъект.Записать(РежимЗаписиДокумента.ОтменаПроведения);

Исключение

Сообщить("Не удалось отменить проведение " + ДокументСсылка

+ ": " + ОписаниеОшибки());

КонецПопытки;

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

Отдельный случай — блокировки. Если документ открыт у пользователя в форме, ПолучитьОбъект() и запись могут завершиться ошибкой конфликта блокировок. В серверных процедурах такие ситуации логируют и пропускают документ, а не прерывают всю обработку.

Отмена проведения из клиентского кода и на сервере

В управляемых формах код делится на клиентский и серверный. Объектная модель документа (ПолучитьОбъект(), Записать()) доступна только на сервере, в толстом клиенте и внешнем соединении. В тонком и веб-клиенте напрямую работать с объектом нельзя.

Типовой приём для управляемой формы: клиентская процедура вызывает серверную, передавая ссылку на документ.

&НаКлиенте

Процедура ОтменитьПроведение(Команда)

ОтменитьПроведениеНаСервере(ДокументСсылка);

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

&НаСервереБезКонтекста

Процедура ОтменитьПроведениеНаСервере(Ссылка)

ДокументОбъект = Ссылка.ПолучитьОбъект();

ДокументОбъект.Записать(РежимЗаписиДокумента.ОтменаПроведения);

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

Директива &НаСервереБезКонтекста предпочтительнее, если данные формы не нужны: вызов выполняется быстрее, так как не сериализуется вся форма. Ссылка передаётся на сервер без проблем — это допустимый тип для взаимодействия клиента и сервера.

Если отмена проведения выполняется в фоновом задании или регламентной операции, клиентского контекста нет вообще — код пишется сразу в серверной процедуре общего модуля с признаком «Сервер».

Пакетная отмена проведения нескольких документов

В обработках массовой отмены (например, распроведение всех документов за период перед закрытием месяца или переносом данных) выборку делают запросом, а затем в цикле отменяют проведение каждого документа. Запрос возвращает только ссылки — объекты создаются внутри цикла по одному.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| РеализацияТоваровУслуг.Ссылка

|ИЗ

| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг

|ГДЕ

| РеализацияТоваровУслуг.Проведен

| И РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода

|УПОРЯДОЧИТЬ ПО

| РеализацияТоваровУслуг.Дата УБЫВ";

Запрос.УстановитьПараметр("НачалоПериода", НачалоПериода);

Запрос.УстановитьПараметр("КонецПериода", КонецПериода);

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

Попытка

ДокументОбъект = Выборка.Ссылка.ПолучитьОбъект();

ДокументОбъект.Записать(РежимЗаписиДокумента.ОтменаПроведения);

Исключение

ЗаписьЖурналаРегистрации("ОтменаПроведения",

УровеньЖурналаРегистрации.Ошибка, , Выборка.Ссылка,

ОписаниеОшибки());

КонецПопытки;

КонецЦикла;

Обратите внимание на сортировку УБЫВ по дате: документы распроводятся от поздних к ранним, что снижает вероятность конфликтов контроля остатков и последовательностей. Ошибки по каждому документу пишутся в журнал регистрации, а цикл продолжается — это стандартная практика для массовых операций.

В больших базах массовую отмену проведения лучше запускать фоновым заданием в нерабочее время. Операция удаляет движения по регистрам и может заметно нагружать СУБД, а при интерактивном запуске пользователь получит «зависший» клиент до конца обработки.
ПЗ
Практическое замечание

Альтернативные способы и их ограничения

Помимо Записать() с режимом отмены проведения, существуют ещё два подхода, каждый со своими ограничениями.

Первый — установка признака проведения через ДокументОбъект.Проведен = Ложь с последующей обычной записью. Так делать не следует: движения по регистрам при этом не удаляются автоматически, и в базе остаются «осиротевшие» записи регистров, искажающие отчёты.

Второй — метод УстановитьПометкуУдаления() с параметром Истина. При пометке удаления проведённого документа платформа автоматически отменяет его проведение. Это подходит, если документ действительно нужно пометить на удаление, но не годится, когда документ должен остаться рабочим, просто непроведённым.

Сравнение способов

Записать(ОтменаПроведения)

Штатный способ: удаляет движения, документ остаётся активным. Подходит всегда, когда нужно именно распровести документ.

УстановитьПометкуУдаления(Истина)

Отменяет проведение попутно, но документ помечается на удаление. Только если документ больше не нужен.

Проведен = Ложь + Записать()

Опасный приём: движения по регистрам не удаляются. Не использовать.

Типичные ошибки и как их избежать

Типичные ошибки
01
Вызов Записать(ОтменаПроведения) для непроведённого документа — платформа выдаёт ошибку; проверяйте ДокументСсылка.Проведен заранее.
02
Попытка отменить проведение помеченного на удаление документа — сначала снимите пометку, затем отменяйте проведение.
03
Игнорирование закрытого периода — запись отклоняется датой запрета; проверяйте период до вызова или обрабатывайте исключение.
04
Отмена проведения на клиенте в тонком клиенте — объектная модель там недоступна; выносите код в серверную процедуру.
05
Пакетная обработка без Попытка/Исключение — первый же заблокированный документ прерывает весь цикл.

Ещё одна тонкость — подписки на события. В типовых конфигурациях на отмену проведения могут быть подписаны обработчики, обновляющие связанные данные (статусы, взаиморасчёты, последовательности). Если ваша обработка обходит их через ОбменДанными.Загрузка = Истина, эти механизмы не сработают, и данные окажутся рассогласованы. Режим загрузки при отмене проведения использовать не рекомендуется — он отключает и контроль, и сопутствующую логику.

Наконец, помните про восстановление последовательностей. Если документ входит в последовательность, отмена его проведения сдвигает границу последовательности. После массовой отмены проведения границу обычно требуется восстановить — иначе отчёты по регистрам, включённым в последовательность, могут показывать некорректные данные.

Как проверить результат отмены

После выполнения кода убедитесь, что операция прошла именно так, как ожидалось. Минимальный контроль — три точки:

  • признак Проведен у ссылки стал равен Ложь;
  • движения документа по регистрам удалены — это видно через «Ещё → Движения документа» в форме или запросом к регистрам с отбором по регистратору;
  • в журнале регистрации нет ошибок, связанных с обработкой (если она пакетная).

Если признак сброшен, а движения остались — значит, где-то использовался нештатный способ записи (например, режим загрузки данных), и ситуацию нужно разбирать отдельно: такие «висячие» движения удаляют через повторную запись документа в штатном режиме или специальную обработку.

Итог

Что важно запомнить

Программная отмена проведения — это получение объекта по ссылке и вызов Записать(РежимЗаписиДокумента.ОтменаПроведения). Обязательны проверки признака проведения, пометки удаления и закрытого периода, обработка исключений и серверный контекст выполнения. Для пакетной обработки — цикл с транзакцией на документ и запись ошибок в журнал регистрации.

Частые вопросы

Можно ли отменить проведение документа, не получая объект?

Нет. Отмена проведения возможна только через объект документа, потому что при этом выполняются обработчики событий и удаляются движения по регистрам. Ссылка служит лишь для проверок и передачи в серверную процедуру.

Почему Записать(ОтменаПроведения) выдаёт ошибку «Документ не проведен»?

У документа уже снят признак проведения — отменять нечего. Перед вызовом проверьте ДокументСсылка.Проведен. Такая ситуация часто возникает в пакетных обработках, когда документ попал в выборку дважды или был распроведён другим сеансом.

Как отменить проведение документа в закрытом периоде программно?

Штатно — никак: дата запрета изменения данных блокирует запись и для кода, и для пользователя. Нужно либо временно сдвинуть дату запрета (при наличии прав администратора), либо выполнять операцию под пользователем, для которого запрет не установлен. Обходить запрет режимом ОбменДанными.Загрузка не следует — это нарушает контроль учёта.

Чем отмена проведения отличается от пометки удаления?

Отмена проведения удаляет только движения по регистрам: документ остаётся рабочим, его можно изменить и провести снова. Пометка удаления дополнительно выводит документ из оборота: он перестаёт участвовать в отборах, а физически удаляется только специальной обработкой удаления помеченных объектов.

Нужно ли восстанавливать последовательности после массовой отмены проведения?

Да, если документы входят в последовательности. Отмена проведения сдвигает границу последовательности, и до её восстановления механизмы, опирающиеся на последовательность (например, контроль актуальности партионного учёта), будут считать данные неактуальными. Восстановление выполняется штатной обработкой проведения по последовательностям или программно через менеджер последовательности.

Можно ли отменить проведение через COM-соединение или внешнюю обработку?

Да, код идентичен: через COM-соединение получаете ссылку на документ внешней базы, затем ПолучитьОбъект() и Записать с режимом ОтменаПроведения. Единственное отличие — все проверки и обработку ошибок нужно выполнять в контексте подключённой базы, а исключения корректно передавать в вызывающий сеанс.