УПП 1.3, УФ
Есть собственная обработка. Её цель такова - по определенному набору номенклатуры должны создаться 3 документа.
шаг1 Создается заполняется и проводится док1
шаг2 Создается заполняется и проводится док2 на основании док1
шаг3 Создается заполняется и проводится док3 на основании док2
Необходимо чтобы при любом сбое (например, не может провестись любой из трех документов)
вся эта цепочка не сохранялась, ни один из трех документов не должен остаться.

Использовать транзакцию? В каком месте?
Сейчас код такой

```1c
    &НаСервере
    Процедура СоздатьДокументыСервер()
    СоздатьДок1();
    КонецПроцедуры

    &НаСервере
    Процедура СоздатьДок1()
    Док1 = Документы. .СоздатьДокумент();
    ... заполнение док1 ...
    Док1.Записать(РежимЗаписиДокумента.Проведение);
    СоздатьДок2(Док1);
    КонецПроцедуры

    &НаСервере
    Процедура СоздатьДок2()
    Док2 = Документы. .СоздатьДокумент();
    ... заполнение док2 ...
    Док2.Записать(РежимЗаписиДокумента.Проведение);
    СоздатьДок3(Док2);
    КонецПроцедуры

    &НаСервере
    Процедура СоздатьДок3()
    Док3 = Документы. .СоздатьДокумент();
    ... заполнение док3 ...
    Док3.Записать(РежимЗаписиДокумента.Проведение);
    КонецПроцедуры
```

Как правильно реализовать?
---
ZergKRSK,

```1c
    &НаСервере
    Процедура СоздатьДокументыСервер()
    НачатьТранзакцию();
    Успех = 0;
    Попытка
    СоздатьДок1();
    Успех = 1;
    Исключение
    Успех = 0;
    КонецИсключения;
    Если Успех = 1 Тогда
    ЗафиксироватьТранзакцию();
    Иначе
    ОтменитьТранзакцию();
    КонецЕсли;
    КонецПроцедуры
```

Можно все сделать и без доп. переменной, но для автора так нагляднее
---
```1c
    Процедура СоздатьДокументыСервер()

    Начать
    СоздатьДок1();
    Зафиксировать

    КонецПроцедуры
```
---
dmt, а если ошибку вызовет док2, то док1 останется записанным и проведенным?
(3) cassper, где расставлять транзакцию?
(4) shira84, куда эту конструкцию вставлять?
---
ZergKRSK,

```1c
    &НаСервере
    Процедура СоздатьДокументыСервер()
    НачатьТранзакцию();
    Успех = 0;
    Попытка
    СоздатьДок1();
    Успех = 1;
    Исключение
    Успех = 0;
    КонецИсключения;
    Если Успех = 1 Тогда
    ЗафиксироватьТранзакцию();
    Иначе
    ОтменитьТранзакцию();
    КонецЕсли;
    КонецПроцедуры
```

Можно все сделать и без доп. переменной, но для автора так нагляднее
---
aka Любитель XML, что я получу на выходе если Док2 даст ошибку? Док1 и Док2 останутся в бд?
(7) Xershi, это понятно. непонятно где использовать эту вставку.
(8) cassper, интересная идея, надо попробовать
---
ZergKRSK, ну по идеи - если будет хотя бы одна ошибка при выполнении СоздатьДок1(); то в базе не будет ни одного документа
---
ZergKRSK, я же вам написал между вашим кодом.
---
Xershi, есть сомнения что если док2 или док3 дадут сбой то они останутся в бд. Буду проверять
(12) ASG74, не, удалять это лишние действия.
---
ZergKRSK, если док2 или док3 даст сбой, то сбой даст и СоздатьДок1() и вылетит исключение, соответственно ничего не запишется
---
ZergKRSK,
```1c
    НачатьТранзакцию();
    Вашкод;
    ЗавершитьТранзакцию();
```
---
ZergKRSK, У меня идея такая:

```1c
    Процедура СоздатьЦепочкуДокументов()
    Перем Док1, Док2, Док3;

    НачатьТранзакцию();

    Если НЕ УспешноСозданДок1(Док1) Тогда
    ОтменитьТранзакцию();
    Возврат;
    КонецЕсли;

    Если НЕ УспешноСозданДок2(Док1, Док2) Тогда
    ОтменитьТранзакцию();
    Возврат;
    КонецЕсли;

    Если НЕ УспешноСозданДок3(Док2, Док3) Тогда
    ОтменитьТранзакцию();
    Возврат;
    КонецЕсли;

    ЗафиксироватьТранзакцию();

    Док1 = Неопределено;
    Док2 = Неопределено;
    Док3 = Неопределено;

    КонецПроцедуры

    Функция УспешноСозданДок1(Док1)

    ДокОбъект = Документы[ВидДокумента].СоздатьДокумент();

    Успех = Истина;

    ...
    ...
    ...
    Попытка
    ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
    Исключение
    Успех = Ложь;
    Сообщить(ОписаниеОшибки());
    КонецПопытки;

    Док1 = ДокОбъект.Ссылка;

    Возврат Успех;

    КонецФункции

    Функция УспешноСозданДок2(Док1, Док2)

    ДокОбъект = Документы[ВидДокумента].СоздатьДокумент();
    ДокОбъект.Заполнить(Док1);

    Успех = Истина;

    ...
    ...
    ...
    Попытка
    ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
    Исключение
    Успех = Ложь;
    Сообщить(ОписаниеОшибки());
    КонецПопытки;

    Док2 = ДокОбъект.Ссылка;

    Возврат Успех;

    КонецФункции

    Функция УспешноСозданДок3(Док2, Док3)

    ДокОбъект = Документы[ВидДокумента].СоздатьДокумент();
    ДокОбъект.Заполнить(Док2);

    Успех = Истина;

    ...
    ...
    ...
    Попытка
    ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
    Исключение
    Успех = Ложь;
    Сообщить(ОписаниеОшибки());
    КонецПопытки;

    Док3 = ДокОбъект.Ссылка;

    Возврат Успех;

    КонецФункции
```
---
Делайте функции с возвратом результата записи/проведения каждого документа, если гдбе-то ошибка, то возвращать ложь и проверять результат возврата. При ошибке делать отмену транзакции, при успехе создавать след.документ. Если при втором ошибка -снова вернуть ложь и отменить транзакцию и так до конца. В самом конце проверять были ли ошибки, если нет - фиксировать транзакцию
---
Попытка
Исключение
КонецПопытки
---
Док1 и Док2 останутся в бд? можно попробовать в случае ошибки при записи второго или третьего программно удалять предыдущие созданные?
---
ASG74, а зачем их вообще записывать? имхо целых два лишних действия
---
aka Любитель XML, как вариант...
---
а у этих трех документов разные виды?
---
ASG74, разные
---
ASG74, не имеет значения.
(18) ZergKRSK, попробовал? что получилось?
---
aka Любитель XML, занят был, сейчас сделаю
---
Простой способ конечно в лоб
Н
```1c
    ачатьТранзакцию()
    Попытка
    Шаг1
    Шаг2
    Шаг3
    ЗафиксироватьТранзакцию();
    Исключение
    ОтменитьТранзакцию()
    КонецПопытки.
```

Но стоит подумать о блокировках.
Записывать и проводить документы нужно одновременно, исключив обработку создания.
А именно создать, но не запысывать и проводить три документа. (естественно если это возможно, т.е. при создании документ 2 не использует проводки документа 1, а документ 3 не использует проводки документа 2 и документа 1)
Для связи документов используем методы УстановитьСсылкуНового и ПолучитьСсылкуНового
И тольлко в конце

```1c
    НачатьТранзакцию()
    Попытка
    Док1.Записать(РежимЗаписиДокумента.Проведение);
    Док2.Записать(РежимЗаписиДокумента.Проведение);
    Док3.Записать(РежимЗаписиДокумента.Проведение);
    ЗафиксироватьТранзакцию();
    Исключение
    ОтменитьТранзакцию()
    КонецПопытки.
```
---
```1c
    НачатьТранзакцию();
    Попытка
    СоздатьДок1();
    ЗафиксироватьТранзакцию();
    Исключение
    ОтменитьТранзакцию();
    КонецПопытки
```

Третий док не смог провестись, первый и второй не сохранились. Работает.