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