Как запретить бронирование занятого номера в 1С?

Программист 1С v8.3 (Управляемые формы) Управленческий учет Сфера услуг, туризм и социальный сектор
← На главную

Для того чтобы реализовать механизм запрета записи, если номер уже занят на конкретную дату, нам необходимо выполнить последовательность действий, которая обеспечит целостность данных в регистре сведений. В процессе разработки мы столкнемся с двумя важными аспектами: проверкой наличия записи и защитой от «состояния гонки» (когда два пользователя одновременно пытаются забронировать один и тот же номер).

Шаг 1: Подготовка запроса к регистру сведений

Первым делом нам нужно определить, свободен ли номер. Для этого мы напишем Запрос, который обратится к нашему РегистрСведений. Важное условие: мы должны исключить из выборки текущий документ, чтобы при перепроведении документа система не видела «саму себя» как занятую запись.

Разберем пример кода для проверки:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |    БронированиеСрез.Номер КАК Номер
    |ИЗ
    |    РегистрСведений.Бронирование КАК БронированиеСрез
    |ГДЕ
    |    БронированиеСрез.Номер = &Номер
    |    И БронированиеСрез.Период = &Период
    |    И БронированиеСрез.Регистратор <> &СсылкаНаДокумент";

Запрос.УстановитьПараметр("Номер", Номер);
Запрос.УстановитьПараметр("Период", ДатаБрони);
Запрос.УстановитьПараметр("СсылкаНаДокумент", Ссылка);

Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
    // Номер занят, выводим сообщение пользователю
    Отказ = Истина;
    Сообщить("Выбранный номер уже забронирован на эту дату!");
КонецЕсли;

Шаг 2: Установка блокировок для предотвращения коллизий

Простого запроса недостаточно в многопользовательской системе. Чтобы избежать ситуации, когда два пользователя одновременно проверяют статус номера, видят, что он свободен, и оба записывают данные, нам необходимо использовать объект БлокировкаДанных. Блокировка гарантирует, что пока транзакция одного пользователя не завершится, другой не сможет считать данные из этого диапазона.

Рассмотрим, как правильно установить блокировку:


Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.Бронирование");
ЭлементБлокировки.УстановитьЗначение("Номер", Объект.Номер);
ЭлементБлокировки.УстановитьЗначение("Период", Объект.ДатаБрони);
Блокировка.Заблокировать();

Размещать этот код рекомендуется в модуле объекта в процедуре ОбработкаПроведения. Именно здесь транзакция записи находится под полным контролем системы, и использование Отказ = Истина; гарантированно отменит любые изменения, если проверка не пройдена.

Шаг 3: Выбор места для проверки

Мы можем реализовать проверку в двух местах:

  1. ОбработкаПроверкиЗаполнения: подходит для интерактивных проверок до начала записи. Это позволяет пользователю увидеть ошибку сразу, не дожидаясь начала процесса проведения.
  2. ОбработкаПроведения: является более надежным местом для финализации логики, так как именно здесь мы гарантируем отсутствие ошибок записи в рамках одной транзакции.

Шаг 4: Учет интервалов дат

Если ваша система предполагает бронирование не на одну конкретную дату, а на интервал (период), задача усложняется. Простая проверка на равенство работать не будет. Нам потребуется проверить условие пересечения интервалов. Математически это выглядит следующим образом:

Новый интервал пересекается со старым, если ДатаНачалаНовой < ДатаКонцаСтарой И ДатаКонцаНовой > ДатаНачалаСтарой.

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

← На главную