Введение:
В статье рассматривается вариант решения задачи создания вложенной транзакции на примере трассировки ошибок при записи, проведении или отмены проведения документа в конструкции:
НачатьТранзакцию();
Попытка
ДокОбъект.Записать(пРежимЗаписиДокумента);
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Сообщить(мояфункция_ПолучитьИнформациюТрассировкиОтмененнойТранзакции());
КонецПопытки;
В процессе записи/проведения/отката ДокОбъект выполняется множество функций и проверок, возможно возникновение ошибок, которые в режимах работы пользователя отображаются у него на экране в виде сообщений, а сам документ не проводится (Отказ = Истина).
Когда то же самое происходит (запись/проведение/откат проведения ДокОбъект) через WebService, то все сопутствующие, проясняющие причину ошибки операции утеряны и в итоге видна только ошибка совершения операции записи/проведения/отката документа.
Для того, чтобы получить эти пояснения можно создать, например, регистр сведений, в который добавлять все эти сообщения для объекта.
К сожалению, система 1С не позволяет реализовать такой функционал в лоб, так как для этого необходимо использовать "вложенную транзакцию", которая будет записывать данные в регистр. В противном случае команда "ОтменитьТранзакцию();" отменит и записи в наш регистр сведений. Если же попытаться обратиться к регистру до отмены транзакции, то появится сообщение об ошибке "в данной транзакции уже происходили ошибки".
Решение:
Создадим РегистрыСведений: "ТекстОшибокИнтеграции" с измерениями"ВнешнийИдентификатор", "Индекс" и реквизитом "ТекстОшибки".
Для решения задачи предлагается использовать WebService.
Для этого необходимо создать WebService и функцию, которая будет производить запись информации в наш регистр сведений.
// функция ВебСервиса - запись сообщений об ошибках в транзакции, для организации трассировки
Функция SetTextError(Numb, Error)
ДобавитьТекстОшибкиПоВнешнемуИдентификатору(Numb, Error);
Возврат "1";
КонецФункции
//процедура общего модуля (или менеджера регистра) - запись сообщений об ошибках в транзакции, для организации трассировки
Процедура ДобавитьТекстОшибкиПоВнешнемуИдентификатору(ВнешнийИдентификатор, НовыйТекстОшибки) Экспорт
Если НЕ ЗначениеЗаполнено(ВнешнийИдентификатор) Тогда
Возврат;
КонецЕсли;
Если ЗначениеЗаполнено(НовыйТекстОшибки) Тогда
НаборЗаписей = РегистрыСведений.ТекстОшибокИнтеграции.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.ВнешнийИдентификатор.Установить(ВнешнийИдентификатор);
НаборЗаписей.Прочитать();
НовыйИндекс = НаборЗаписей.Количество() + 1;
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.ВнешнийИдентификатор = ВнешнийИдентификатор;
НоваяЗапись.Индекс = НовыйИндекс;
НоваяЗапись.ТекстОшибки = НовыйТекстОшибки;
НаборЗаписей.Записать();
КонецЕсли;
КонецПроцедуры
Технология работы 1С в этом случае такова
- при вызове функции:
ДокОбъект.Записать(пРежимЗаписиДокумента);
Во всех местах, где происходит Отказ = Истина и выводится сообщение об ошибке нам необходимо вставить программный код по вызову функции SetTextError() нашего веб-сервиса, примерно таким образом:
Прокси.SetTextError(пВнешнийИдентификатор, НовыйТекстОшибки);
, где Прокси - это предварительно выполненное соединение с нашим веб-сервисом текущей базы, по следующему шаблону:
мWebCервис = пВнешнееСоединение.Сервер;
мПользователь = пВнешнееСоединение.Пользователь;
мПароль = пВнешнееСоединение.Пароль;
мURIПространстваИменСервиса = пВнешнееСоединение.URIПространстваИменСервиса;
мИмяСервиса = пВнешнееСоединение.ИмяСервиса;
мИмяТочкиПодключения = пВнешнееСоединение.ИмяТочкиПодключения;
ОпределениеСервиса = Новый WSОпределения(мWebCервис, мПользователь, мПароль);
Прокси = Новый WSПрокси(ОпределениеСервиса, мURIПространстваИменСервиса, мИмяСервиса, мИмяТочкиПодключения);
Прокси.Пользователь = мПользователь;
Прокси.Пароль = мПароль;
1С зафиксирует изменения в регистре сведений в отдельной транзакции веб-сервиса, поэтому даже при откате основной транзакции информацию из регистра можно будет прочитать.
- Для того, чтобы прочитать информацию, достаточно обратиться к регистру, например, с помощью функции:
Функция мояфункция_ПолучитьИнформациюТрассировкиОтмененнойТранзакции(ВнешнийИдентификатор) Экспорт
ТекстОшибок = "";
Если НЕ ЗначениеЗаполнено(ВнешнийИдентификатор) Тогда
Возврат ТекстОшибок;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТекстОшибокИнтеграции.схпВнешнийИдентификатор,
| ТекстОшибокИнтеграции.Индекс КАК Индекс,
| ТекстОшибокИнтеграции.ТекстОшибки
|ИЗ
| РегистрСведений.ТекстОшибокИнтеграцииКАК ТекстОшибокИнтеграции
|ГДЕ
| ТекстОшибокИнтеграции.ВнешнийИдентификатор = &ВнешнийИдентификатор
|
|УПОРЯДОЧИТЬ ПО
| Индекс";
Запрос.УстановитьПараметр("ВнешнийИдентификатор ", СокрЛП(ВнешнийИдентификатор));
ВыборкаДетальныеЗаписи = Запрос.Выполнить().Выбрать();
пТаб = "";
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ТекстОшибок = ТекстОшибок + пТаб + ВыборкаДетальныеЗаписи.ТекстОшибки;
пТаб = Символы.ПС;
КонецЦикла;
Возврат ТекстОшибок;
КонецФункции
Вывод:
Можно организовать через веб-сервис "вложенную транзакцию", в которой выполнить задачу и зафиксировать в СУБД запись каких-то данных, которые сохранятся даже при отмене основной транзакции.
Конечно, предложенный метод - это не "вложенная транзакция" в чистом виде, как она есть в СУБД. Но для решения некоторых практических задач такая методика будет полезной.