При разработке внешних обработок и алгоритмов автоматизации в платформе 1С:Предприятие 8.3 часто возникает задача отмены проведения определенных документов (распроведения). Начинающие разработчики нередко сталкиваются с ошибками контекста вызова методов или неоптимальной логикой выборки данных. Разберем по шагам, как правильно найти проведенный документ, получить объектную ссылку и выполнить корректную отмену проведения, а также рассмотрим сопутствующие ошибки при работе с датами и реквизитами формы.
Рассмотрим ситуацию: разработчик находит документ через запрос, получает объект через метод ПолучитьОбъект() и пытается вызвать глобальный метод записи без указания контекста объекта.
Посмотрим на пример кода с ошибкой:
Объект = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
Если Объект.Проведен Тогда
Сообщить("Документ проведен!");
Записать(РежимЗаписиДокумента.ОтменаПроведения); // Ошибка!
КонецЕсли;
В результате выполнения такого кода платформа выдает синтаксическую ошибку: «Процедура или функция с указанным именем не определена (Записать)».
Выясним причину этой проблемы. Метод Записать() без указания объектной переменной существует только в контексте модуля формы или модуля самого объекта. Если мы работаем во внешней процедуре, обработке или общем модуле, платформа не может определить, какой именно объект требуется модифицировать. Для корректной записи необходимо явно вызывать метод через полученную переменную объекта:
Объект.Записать(РежимЗаписиДокумента.ОтменаПроведения);
Разберем правильный и оптимизированный алгоритм поиска и распроведения документов по их номеру.
Проведен = ИСТИНА следует добавлять непосредственно в секцию ГДЕ текста запроса.ДокументОбъект и вызываем его метод записи.Рассмотрим полный рабочий пример серверной процедуры:
&НаСервере
Процедура РаспровестиДокументыПоНомеру(НомерДокумента)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЧекНаОплату.Ссылка КАК Ссылка,
| ЧекНаОплату.Номер КАК Номер
|ИЗ
| Документ.ЧекНаОплату КАК ЧекНаОплату
|ГДЕ
| ЧекНаОплату.Номер = &Номер
| И ЧекНаОплату.Проведен = ИСТИНА";
Запрос.УстановитьПараметр("Номер", НомерДокумента);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Попытка
ДокументОбъект = Выборка.Ссылка.ПолучитьОбъект();
// Выполняем отмену проведения
ДокументОбъект.Записать(РежимЗаписиДокумента.ОтменаПроведения);
Сообщить("Успешно распроведен документ № " + Выборка.Номер);
Исключение
Сообщить("Ошибка при отмене проведения документа № " + Выборка.Номер + ": " + ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
КонецПроцедуры
Проанализируем важные технические нюансы, которые необходимо соблюдать в среде 1С:Предприятие 8.3:
ПолучитьОбъект() и Записать() доступны исключительно на стороне сервера. В управляемом приложении вызов процедуры должен предваряться директивой &НаСервере или &НаСервереБезКонтекста.ОбработкаУдаленияПроведения), могут сработать проверки дат запрета изменения данных или блокировки торгового оборудования (онлайн-касс). Оборачивание вызова в блок Попытка ... Исключение защищает пакетную обработку от аварийного прерывания.Документы.ЧекНаОплату.НайтиПоНомеру(НомерДокумента, ДатаДокумента).Нередко в обработках требуется задать начальные параметры дат при открытии. Разберем типичные ошибки, возникающие при неверном обращении к элементам формы и типам данных 1С.
Неверный подход:
// Ошибка: обращение к элементам как к данным и неверный строковый литерал даты
Форма = ЭлементыФормы.ПолеВвода;
Форма.НачДата = '04.04.2018';
Разберем правила работы с формой и литералами:
Элементы отвечает только за визуальное отображение. Значения присваиваются напрямую переменной реквизита: НачПериода = ...;.'04.04.2018' не распознается синтаксисом платформы как дата. Канонический литерал задается в одинарных кавычках в формате ГГГГММДД (или ГГГГММДДЧЧММСС), например: '20180404'.Дата(Год, Месяц, День).Посмотрим на корректный пример инициализации реквизитов формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Инициализация реквизитов формы при создании
НачДата = '20180404'; // Канонический литерал ГГГГММДД
КонДата = Дата(2018, 4, 5); // Через конструктор даты
КонецПроцедуры
Инициализацию значений по умолчанию рекомендуется выполнять в событии ПриСозданииНаСервере, чтобы исключить дополнительные клиент-серверные вызовы при открытии интерфейса.