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