Функция создания заказа была написана по стандартам разработки.
Упрощенный пример:
Функция СоздатьЗаказ(ВнешнийНомер)
НачатьТранзакцию();
Попытка
ДокументЗаказ = Документы.Заказы.СоздатьДокумент();
ДокументЗаказ.ВнешнийНомер = ВнешнийНомер;
ДокументЗаказ.Записать(РежимЗаписиДокумента.Проведение);
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Возврат "Ошибка создания заказа";
КонецПопытки;
Возврат ДокументЗаказ.Номер;
КонецФункции
С очередным обновлением внутри документа заказа появилась доработка с ошибкой и одновременно написанная с нарушением стандарта разработки.
В модуле документа заказа.
Процедура ОбработкаПроведения()
....
//Последняя доработка в конце
Попытка
...запись в базу с ошибкой
Исключение
//по стандарту должно быть исключение, т.к. есть внешняя транзакция
//но его не было
//ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
В результате, до обнаружения и исправления ошибки, довольно продолжительное время функция создания заказа успешно делал вид, что создает заказы и возвращала контрагентам какие-то номера.
В базе документы не появлялись.
На первый взгляд кажется, что функция создания заказа (она ведь по стандартам) рассчитана на ошибки внутри вложенных транзакций и на команде "ЗафиксироватьТранзакцию();" должна выдать до боли знакомое сообщение "В этой транзакции уже происходили ошибки!".
На практике функция возвращала номера как-будто создаваемых заказов!
Рассмотрим документацию на сайте "its.1c.ru".
В стандартах разработки в главе "Транзакции: правила использования (Новый раздел!)" почему то нет описания этого момента.
Ответ все-таки есть, но в разделе методической поддержки в главе "Вложенность транзакций".
Отрывок с сайта "its.1c.ru" (ссылка выше):
"При вызове отмены вложенной транзакции (явно или в результате произошедшего исключения) запоминается факт, что одна из вложенных транзакций была отменена (реального отката транзакции в этот момент не происходит), что приводит к невозможности фиксации результатов транзакции верхнего уровня. При этом, при попытке фиксации транзакции верхнего уровня никаких исключений выдано не будет. Просто вся транзакция завершится откатом. Соответственно, все изменения базы данных, произведенные в рамках транзакции верхнего уровня, будут отменены."
Вот и ответ, транзакция отменена, данные в базу не записаны, но это не вызывает исключения!!!
В свою очередь ошибка "В этой транзакции уже происходили ошибки!" возникает не на команде "ЗафискироватьТранзакцию();", а при первом обращении к базе (как при чтении, так и при записи) после отмены вложенной транзакции.
В нашем случае доработка была добавлена именно в конце модуля проведения, что в общем-то естественно, и обращений к базе больше не было.
Выводы и пожелания:
1. Хотелось бы в стандартах разработки на ИТС увидеть решение, более устойчивое к ошибкам в глубине стэка.
Например, перед командой "ЗафискироватьТранзакцию();" выполнять запрос к базе данных "Выбрать 1" для гарантированного вызова исключения "В этой транзакции уже происходили ошибки!".
Другой вариант это проверять, что ссылка "созданного" документа не пустая (ссылка объекта очищается при отмене транзакции).
2. Хотелось бы, чтобы когда-нибудь в будущем при отмене транзакции командой "ЗафискироватьТранзакцию();" вызывалось исключение.