• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

Неявные транзакции и отказ в записи

  • Автор темы Истребитель
  • Дата начала
И

Истребитель

Добрый день!

Задача:
Есть две сущности - Событие и Бронь.
Событие (Справочник) это запись о том, когда клиент приходит в заведение
Бронь (Документ) это данные о том, что под событие забронированы места (например, пять дорожек боулинга).
На одно событие может не быть броней вообще (клиент просто заказал себе столик с едой для ДР) или быть несколько броней (боулинг, бильярд). Соответственно, связь по полю владелец (событие - владелец брони)

Проведения документа (функций "проведение" И "отмена проведения нет) не происходит, поскольку с базой работают довольно "простые" люди и учить их что такое проведение долго, проще сделать так, что документ всегда проведен, когда есть, и не проведен только если помечен на удаление. То есть, обработка проведения запускается при любой записи документа, при этом если пометка удаления истина, то регистры очищаются и ничего не пишется.

При записи брони нужно проверить, что места для бронирования доступны, и занять их в регистрах сведений (регистр сведений говорит, доступно ли место на дату Х, каждая бронь одного места создает две записи в регистр, недоступно с начала брони и доступно с конца брони). Это делается в ПередЗаписью модуля объекта документа Бронь.
При пометке на удаление события логично предложить также пометить на удаление все брони и наоборот, при снятии пометки - снять пометку с броней. Это делается в ПередЗаписью модуля объекта справочника Событие, после того, как проверено, что событие будет успешно записано, при этом сменится пометка удаления.

Но при этом может быть ситуация, что сначла пометили на удаление событие и его брони, затем места забронировали другой бронью, затем снимаем пометку удаления с события - со снятием её с броней - при этом движения по брони не могут быть записаны потому, что места этой брони уже заняты.
Такая бронь по моей идее останется без изменений, ибо ей будет установлено отказ=истина в ПередЗаписью.
То есть например, под событие две брони, боулинг и бильярд, для бильярда столы всё ещё свободны а боулинг дорожки уже заняты, пометка удаления должна сняться с бильярда а на боулинге остаться.

НО! 1С тут тупит.

Вот код:
Код:
если ЗначениеЗаполнено(Документы.Бронь.НайтиПоРеквизиту("Событие",ссылка)) тогда
Режим = РежимДиалогаВопрос.ДаНет;
Ответ = Вопрос("Снята пометка удаления. Снять пометку на удаление также с Броней, оформленных на это событие?", Режим, 0);
Если Ответ = КодВозвратаДиалога.Нет Тогда
Возврат;
КонецЕсли;

ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("Событие", Ссылка);
Выборка=Документы.Бронь.Выбрать(,,ПараметрыОтбора);

пока Выборка.Следующий() цикл

докоб=Выборка.ПолучитьОбъект();
докоб.ПометкаУдаления=Ложь;
попытка					
докоб.Записать();
исключение

КонецПопытки;
КонецЦикла;

КонецЕсли;

Идея простая - выбираем все доки по событию и ставим им пометку удаления
Но при этом докоб.Записать() вызывает ОШИБКУ если отказ=истина внутри ПередЗаписью!

Окей, я сделал попытку-исключение, но теперь Выборка.ПолучитьОбъект(); вызывает ошибку "в этой транзакции уже были ошибки!"

Да какого хрена, что они были, что с того?

Почитал интернет, говорят происходит неявная транзкция, то есть её НИКАК не остановить, не отменить и не начать заново! Офигенно.

То есть нет НИКАКОГО способа реализовать то, что я хочу (чтобы те документы, которые в своём теле получат отказ, не записались - остались помеченными - а те, которые в своём теле не получат отказ, снялись с удаления), просто потому, что кто-то в 1С решил, что нужно убивать возможность делать получение объекта при установке отказ=истина? Мне нужно дублировать код проверки легальности записи брони (места не заняты) ещё и в событии чтобы не доходило до отказа, чтоли?

Или я что-то упускаю, и есть вариант обойти эту гадость и сделать таки то, что мне нужно, без дупликации кода?
 
U

unknown181538

Хм... задачка...
А если... создать в модуле документа "Бронь" процедуру "ВозможнаЗапись()", и вынести в нее проверку из "ПередЗаписью". Здесь:
Код:
			 пока Выборка.Следующий() цикл

докоб=Выборка.ПолучитьОбъект();
Если ДокОб.ВозможнаЗапись() Тогда
докоб.ПометкаУдаления=Ложь;			 
докоб.Записать();
КонецЕсли;
А для невозможности удалить "Бронь" интерактивно без проверки, вставить вызов той же процедуры в "ПередЗаписью()" формы.

Запись документов при записи спр-ка, в целом идеологически не очень...
 
E

evgenyatam

используй явную транзакцию вокруг записи документа. транзакции могут вкладываться одна в другую до бесконечности.
 
G

Gluk8888

Запись документов при записи спр-ка, в целом идеологически не очень...
согласен на все 100, может стоит подумать в сторону изменения самой структуры базы данных и изменения алгоритма?
ИМХО: может проще не отменять запись документа? т.к. событие бронирование было произведено и помеченный на удаление документ в принципе не несет смысловой нагрузки. может лучше делать на основании документа документ отмены бронирования? в котором будут обратные движение по регистрам? как-то так.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!