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