Приветствуем вас! В процессе разработки на платформе 1С:Предприятие мы часто сталкиваемся с необходимостью контролировать или модифицировать данные документа непосредственно перед его записью в информационную базу. Одним из ключевых событий для решения такой задачи является обработчик формы ПередЗаписьюНаСервере. Давайте вместе разберемся, как правильно использовать этот механизм, какие существуют альтернативы и как избежать распространенных ошибок, особенно при работе со связанными документами, такими как ЗаказПокупателя и РеализацияТоваровУслуг.
Мы начнем с детального анализа самого события ПередЗаписьюНаСервере, чтобы четко понимать его назначение и возможности.
Процедура ПередЗаписьюНаСервере – это обработчик события формы, который вызывается на сервере. Он срабатывает после того, как завершена проверка заполнения на стороне клиента (если такая проверка есть) и непосредственно перед тем, как объект документа будет записан в базу данных.
В этом обработчике нам доступны два важных параметра, которые необходимо различать:
ТекущийОбъект: Этот параметр представляет собой объект, который будет записан в информационную базу. Все изменения, которые мы хотим сохранить, необходимо вносить именно в ТекущийОбъект. Например, если мы хотим изменить значение реквизита или добавить новую строку в табличную часть, мы должны делать это через ТекущийОбъект.Объект: Этот параметр является основным реквизитом формы и на момент вызова ПередЗаписьюНаСервере он, по сути, "мертв" для целей изменения записываемых данных. Любые изменения, внесенные в Объект, не будут записаны и пропадут после завершения операции записи. Его можно использовать только для анализа текущих данных формы, но не для их модификации перед сохранением.Важно: Если наша задача – принять решение о возможности записи данных (например, разрешить или запретить запись) или модифицировать данные, которые будут сохранены (добавить служебную информацию, изменить реквизиты), мы всегда должны работать с параметром ТекущийОбъект.
Если в процессе проверки в ПередЗаписьюНаСервере мы обнаруживаем ошибку или несоответствие, которое не позволяет записать документ, мы можем прервать операцию записи. Для этого необходимо установить параметр Отказ в значение Истина:
Процедура ПередЗаписьюНаСервере(Отказ, СтандартнаяОбработка)
// Например, проверяем какое-то условие
Если Не ПроверитьДополнительныеУсловия() Тогда
Отказ = Истина;
Сообщить("Запись документа невозможна: не выполнены дополнительные условия.");
КонецЕсли;
КонецПроцедуры
Это прервет запись документа и позволит нам вывести сообщение пользователю о причинах отказа.
Следует помнить, что событие ПередЗаписьюНаСервере срабатывает только при записи документа из формы. Если объект записывается программно (например, из другого документа, фонового задания, обработчика или обмена данными), этот обработчик формы не вызывается. В таких случаях, для выполнения обязательных алгоритмов, которые должны срабатывать при любом способе записи объекта, следует использовать обработчик события объекта ПередЗаписью.
Теперь давайте перейдем к основной задаче, часто возникающей на практике: как правильно управлять связанными документами, такими как ЗаказПокупателя и РеализацияТоваровУслуг, и синхронизировать их состояние. Например, если Реализация закрывает часть или весь Заказ, или если в Реализацию попадают товары, которых изначально не было в Заказе.
Первое, что мы должны проанализировать, это возможность использования стандартных механизмов платформы и конфигурации. Часто попытка "втиснуть" сложную логику управления связанными документами в ПередЗаписьюНаСервере основного документа приводит к излишнему усложнению и блокировкам.
Для сложных или массовых операций, которые не требуют немедленного интерактивного ответа пользователя, мы можем использовать РегламентныеЗадания. Например, если нам нужно:
Мы можем написать отдельный код, который будет выполняться, например, ночью. Этот код будет анализировать состояние документов и выполнять необходимые корректировки.
Пример ситуации:
Товар1 = 20 штТовар1 = 15 штРегламентное задание может автоматически закрыть Заказ по Товару1 на 15 шт, оставив 5 шт для дальнейшей отгрузки, или пометить его как частично выполненный.
Пример ситуации 2:
Товар1 = 20 штТовар1 = 20 шт (по заказу) + Товар1 = 3 шт (вне заказа)Регламентное задание может попытаться "втащить" эти 3 шт в существующий заказ (если это допустимо бизнес-логикой) или создать новый заказ на эти позиции.
Преимущества:
Для интерактивных действий, которые требуют подтверждения пользователя или выполнения сложного алгоритма, затрагивающего несколько документов, мы можем создать отдельную кнопку на форме документа Реализация (например, "Обновить Заказ" или "Скорректировать Заказ").
Механизм работы:
Заказе).Заказ или обновляет его статусы.В этом случае, ПередЗаписьюНаСервере документа Реализация может только проверять, было ли выполнено это действие, и если нет – предупреждать пользователя.
В некоторых сценариях мы можем рассмотреть вариант корректировки связанных документов после того, как основной документ (например, Реализация) уже записан. Для этого подойдут события ПослеЗаписиНаСервере (для формы) или ПослеЗаписи (для объекта).
Пример:
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
// После успешной записи реализации, обновляем связанный заказ
Если ТекущийОбъект.ЗаказПокупателя.Пустая() Тогда
Возврат;
КонецЕсли;
// Получаем объект заказа для модификации
ЗаказОбъект = ТекущийОбъект.ЗаказПокупателя.ПолучитьОбъект();
Если ЗаказОбъект <> Неопределено Тогда
// Вызываем процедуру обновления заказа, например, в общем модуле
МодульРаботыСЗаказами.ОбновитьСтатусЗаказаПоРеализации(ЗаказОбъект, ТекущийОбъект);
ЗаказОбъект.Записать();
КонецЕсли;
КонецПроцедуры
Осторожно: При таком подходе, если обновление связанного документа завершится с ошибкой, основной документ уже будет записан. Это может привести к рассинхронизации данных. Мы должны быть готовы к обработке таких ситуаций, возможно, с помощью механизма отложенной обработки ошибок или восстановления.
Если нам необходимо жестко контролировать состояние связанных документов до того, как основной документ будет записан, и при этом предоставить пользователю возможность исправить ситуацию, ПередЗаписьюНаСервере становится очень мощным инструментом.
Давайте разберем по шагам, как можно реализовать такой механизм:
ПередЗаписьюНаСервере:
В обработчике ПередЗаписьюНаСервере документа Реализация мы проверяем, все ли хорошо с соответствующим ЗаказомПокупателя. Например, соответствует ли количество отгружаемых товаров в Реализации остаткам по Заказу, или не осталось ли "висячих" позиций, которые должны быть закрыты.
Процедура ПередЗаписьюНаСервере(Отказ, СтандартнаяОбработка)
Если Не ТекущийОбъект.ЗаказПокупателя.Пустая() Тогда
// Вызываем серверную функцию для проверки состояния заказа
Если Не ПроверитьСостояниеЗаказа(ТекущийОбъект.ЗаказПокупателя, ТекущийОбъект) Тогда
Отказ = Истина;
// Сообщаем пользователю о необходимости действий
Сообщить("Заказ покупателя не соответствует реализации. Нажмите кнопку 'Обновить Заказ' для приведения его в соответствие.", СтатусСообщения.Внимание);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Отказ = Истина и сообщение пользователю:
Если проверка выявила проблемы, мы устанавливаем Отказ = Истина, чтобы предотвратить запись Реализации. Одновременно мы выводим пользователю сообщение, объясняющее проблему и предлагающее конкретное действие. Например: "Заказ кривой, нажмите кнопку 'Обновить Заказ'!"
Запись Реализации будет разрешена только после того, как пользователь выполнит требуемые действия (например, нажмет кнопку "Обновить Заказ", которая скорректирует Заказ) и повторит попытку записи. При повторной попытке записи ПередЗаписьюНаСервере снова сработает, и если Заказ уже в правильном состоянии, Отказ не будет установлен, и документ успешно запишется.
Для более продвинутых сценариев, где мы хотим автоматизировать процесс исправления, мы можем использовать клиентский механизм ПодключитьОбработчикОжидания. Этот подход позволяет отложить выполнение клиентской процедуры на определенный интервал времени.
Механизм работы:
ПередЗаписью на клиенте:
Мы выполняем предварительную проверку. Если условия не выполняются (например, Заказ "кривой"), мы устанавливаем Отказ = Истина и запускаем ПодключитьОбработчикОжидания.
// Пример клиентской процедуры ПередЗаписью
Процедура ПередЗаписью(Отказ, СтандартнаяОбработка)
Если Не ЭтоНовый Тогда // Проверка только для существующих документов
Если Не ПроверитьЗаказНаКлиенте() Тогда // Проверка, которая может быть выполнена на клиенте
Отказ = Истина;
Сообщить("Заказ покупателя требует обновления. Выполняем автоматическое исправление...", СтатусСообщения.Информация);
// Запускаем отложенное выполнение для исправления заказа и последующей записи
ПодключитьОбработчикОжидания("ИсправитьЗаказИЗаписатьРеализацию", 0.1, Истина); // 0.1 секунды, однократно
КонецЕсли;
КонецЕсли;
КонецеПроцедуры
// Клиентская процедура, которая будет вызвана обработчиком ожидания
Процедура ИсправитьЗаказИЗаписатьРеализацию() Экспорт
// Здесь вызываем серверную процедуру для исправления заказа
// Например:
МодифицироватьЗаказНаСервере(Объект.ЗаказПокупателя, Объект);
// После исправления, пытаемся записать реализацию снова
Записать();
КонецПроцедуры
Процедура, вызванная ПодключитьОбработчикОжидания, сначала выполняет исправление Заказа (возможно, с вызовом серверных процедур), а затем программно вызывает запись Реализации. При повторной записи, если все условия теперь выполнены, документ успешно запишется.
Важно: Процедура, вызываемая ПодключитьОбработчикОжидания, должна находиться в клиентском контексте или в глобальном общем модуле с установленным флагом "Клиент". Если требуется изменить записываемый объект или связанный документ до завершения транзакции текущего документа, более подходящими будут события ПередЗаписьюНаСервере формы или ПередЗаписью объекта.
Мы рассмотрели различные подходы к работе с событием ПередЗаписьюНаСервере и управлению связанными документами в 1С. Помните, что выбор конкретного решения всегда зависит от специфики вашей бизнес-логики и требований к пользовательскому интерфейсу. Главное – стремиться к максимально типовым и поддерживаемым решениям, избегая излишнего усложнения и дублирования логики.
Всегда анализируйте ситуацию:
ПередЗаписьюНаСервере с Отказ = Истина и сообщениями.РегламентныеЗадания или отдельные процедуры.ПодключитьОбработчикОжидания.Надеемся, что этот подробный разбор поможет вам в вашей работе с платформой 1С:Предприятие!
← К списку