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