
Два менеджера открыли календарь и увидели свободную площадку. Каждый оформил бронь, пока другой ещё заполнял карточку. Оба действовали правильно, но бизнес получил два обязательства на один ресурс.
Проверять занятость в момент записи
В календаре площадок занятость нужно перепроверять при сохранении. Показ свободного времени — подсказка для человека, а подтверждённая бронь требует согласованного решения по актуальным данным.
Если проверка и запись разделены без защиты от одновременных действий, обе операции способны пройти. Поэтому важно не только вычислить пересечение, но и обеспечить согласованное сохранение.
С чего начинается модель занятости
Прежде чем выбирать календарный компонент, нужно решить, какое обещание бизнес даёт клиенту. «Зал доступен на экране» означает только результат последнего чтения. «Бронь подтверждена» означает обязательство предоставить конкретный ресурс в конкретное время. Между этими фразами находится операция, которая должна учитывать действия других сотрудников. Именно её проектируют первой.
Для одного зала удобно рассматривать два интервала: время услуги и время, в течение которого ресурс недоступен другим заказам. Клиент арендует зал с 16:00 до 18:00, а подготовка начинается в 15:30 и уборка заканчивается в 18:20. Внутренний запрет пересечения относится к 15:30–18:20. В подтверждении клиенту при этом остаётся согласованная аренда, а не служебный интервал.
Такое разделение помогает избежать скрытой наценки временем. Если менеджер вручную увеличивает окончание каждой брони ради уборки, клиентская длительность и техническое ограничение начинают смешиваться. При переносе сотрудник забудет прибавить буфер, а отчёт по занятости посчитает подготовку продажей услуги. Отдельные поля делают происхождение блокировки объяснимым.
Таблица граничных условий
Допустим, уже подтверждена аренда 10:00–12:00. Если используется полуоткрытая модель интервала, начало входит в него, а окончание служит границей следующего. Это математическое соглашение нужно зафиксировать для разработчика; сотруднику достаточно понятных правил соседних записей. В таблице сначала рассматривается случай без подготовки и уборки.
| Новый запрос | Состояние относительно 10:00–12:00 | Ожидаемое решение | Что дополнительно уточнить |
|---|---|---|---|
| 09:00–10:00 | Заканчивается на начале аренды | Можно принять при отсутствии буферов | Нужна ли подготовка к 10:00 |
| 09:30–10:30 | Занимает начало действующей аренды | Отказать в этом интервале | Предложить время до начала блокировки |
| 10:30–11:00 | Полностью расположен внутри | Отказать независимо от короткой длительности | Нет ли ошибки выбора ресурса |
| 09:00–13:00 | Полностью охватывает аренду | Отказать: проверка одного начала недостаточна | Возможна ли другая площадка |
| 11:30–12:30 | Занимает окончание действующей аренды | Отказать | Проверить допустимый перенос начала |
| 12:00–13:00 | Начинается на окончании | Можно принять только по принятому правилу буфера | Когда закончится уборка |
| 10:00–12:00 | Совпадает полностью | Отказать для другого заказа | Не является ли запрос повтором той же операции |
| 12:00–12:00 | Нулевая длительность | Не создавать обычную аренду | Нужно ли отдельное событие без занятия ресурса |
Полезно проверить не только таблицу, но и её симметрию: результат не должен зависеть от того, какую бронь сравнивают первой. Ошибка «начало нового интервала не попало внутрь старого» пропускает случай, когда новая бронь полностью накрывает старую. Поэтому в техническом задании лучше приложить конкретные пары времени, а не ограничиваться фразой «проверять пересечение».
Почему две правильные проверки способны дать неправильный итог
Рассмотрим последовательность двух менеджеров. Первый прочитал, что зал свободен. Второй прочитал то же состояние. Первый записал бронь. Второй тоже записал бронь, поскольку его предварительная проверка была успешной. Ни один сотрудник не нарушил инструкцию, однако после завершения появились несовместимые обязательства. Исправлять нужно не внимательность людей, а границу согласованной операции.
Требование к системе звучит так: решение о доступности и создание блокирующей записи должны сохранять правило даже при конкурирующих запросах. Способ зависит от хранилища и архитектуры: используются ограничения базы, блокировки или иной согласованный механизм. Нельзя автоматически считать любой режим транзакции достаточным. В частности, важно понять, какое множество записей или какой ресурс защищает выбранное решение.
Если применяется повтор операции после конкурентного конфликта, заново оценивается актуальная доступность. Нельзя повторить только последнюю вставку, сохранив старый положительный ответ проверки. Для пользователя допустим понятный отказ или предложение другого времени. Недопустим «успех», который команда позже вынуждена превращать в отмену по телефону.
Рабочий сценарий
Пересечение броней одного ресурса
Подтверждать клиенту только действительно доступное время
01
Запрос
Сотрудник выбирает ресурс и интервал
02
Перепроверка
Сервер получает актуальные блокирующие записи
03
Конфликт
Сопоставляются интервалы и буферы подготовки
04
Фиксация
Доступность и новая бронь подтверждаются согласованно
05
Ответ
Клиенту обещают время только после подтверждения
06
Контроль
Отказ и альтернативный интервал видны менеджеру
Два одновременных сохранения?
Условие выполнено: Подтверждена только одна несовместимая бронь
Условие не выполнено: Доступность и новая бронь подтверждаются согласованно
Ответственный
руководитель площадки
Подтверждение
Отказ и альтернативный интервал видны менеджеру
Что измеряем
число подтверждённых несовместимых броней и доля конфликтов, завершённых выбором альтернативы
| Момент | Менеджер А | Менеджер Б | Контрольный вопрос |
|---|---|---|---|
| До сохранения | Видит свободный зал | Видит свободный зал | Является ли экран обещанием или подсказкой |
| Первая попытка | Отправляет подтверждение | Ещё заполняет карточку | Где принимается окончательное решение |
| Конкурирующая попытка | Получает результат | Отправляет свой запрос | Защищено ли правило между проверкой и записью |
| После обработки | Имеет одну подтверждённую бронь | Видит конфликт либо иной согласованный исход | Не выданы ли два несовместимых подтверждения |
| Повторное чтение | Открывает сохранённую карточку | Ищет альтернативу | Совпадает ли экран с фактическими записями |
Паспорт блокирующей записи
Для диагностики полезно договориться о минимальном составе данных. У ресурса должен быть устойчивый идентификатор: «Большой зал» можно переименовать, поэтому само название не подходит для связи. У брони — собственный идентификатор и принадлежность к заказу. Отдельно сохраняются начало и окончание услуги, вычисленный или явно заданный интервал блокировки, статус и основание технического закрытия.
Часовой пояс нельзя восстанавливать по компьютеру менеджера. Если компания работает с несколькими городами, пользователь может находиться в одной зоне, а площадка — в другой. В карточке и подтверждении должно быть понятно, к какому местному времени относится обещание. Правило хранения и отображения фиксируется в проекте; приёмочный пример включает пользователя с отличающимися настройками устройства.
Время создания и время последней правки помогают восстановить последовательность, но не заменяют историю значимых переходов. Для спорной брони нужно увидеть, кто изменил ресурс, интервал или блокирующий статус. Комментарий «перенесли по просьбе клиента» полезен вместе с конкретной парой старого и нового состояния. Одной новой даты недостаточно, чтобы разобрать первоначальное обещание.
Перенос — это новое решение о доступности
При изменении существующей брони система сравнивает предлагаемый интервал с другими блокирующими записями. Собственную текущую запись исключают из сравнения по идентификатору, иначе любой перенос будет конфликтовать сам с собой. Но исключить все записи того же клиента или заказа нельзя: в одном заказе могут существовать отдельные реальные обязательства.
Если новый интервал недоступен, прежняя бронь должна остаться действующей. Сначала удалять старую запись, а затем пытаться создать новую опасно: отказ оставит клиента без обоих вариантов. На приёмке специально выбирают занятое время и после отказа повторно открывают исходную карточку. Проверяют не только сообщение, но и сохранность ресурса, времени и связанных условий.
Отдельный сценарий — два менеджера редактируют одну бронь. Даже если оба предлагаемых интервала свободны, второй пользователь способен незаметно перезаписать решение первого. Команда определяет, как обнаружить устаревшую версию карточки: например, предложить перечитать изменения и подтвердить новый выбор. Это другой вид конфликта, чем две разные брони одного ресурса, и его нельзя забыть в требованиях.
Повтор запроса после потери ответа
Менеджер нажал «Подтвердить», соединение прервалось, результат неизвестен. Отсутствие ответа браузеру не доказывает, что сервер ничего не сохранил. Если повтор всегда создаёт новый заказ, бизнес получит дубль. Если повтор всегда запрещён, сотрудник не сможет закончить работу после обычного сетевого сбоя. Нужна проверяемая связь попытки с итогом.
Практический вариант требований: у попытки подтверждения есть устойчивый идентификатор, который сохраняется при техническом повторе. Система умеет найти уже завершённый результат и вернуть его вместо нового действия. Формат и срок жизни такого идентификатора определяют при разработке. Он не должен использоваться как право доступа: найденную бронь всё равно показывают только разрешённому пользователю.
Не следует объединять по этому механизму разные намерения клиента. Один человек вправе забронировать зал дважды на разные дни. Даже совпадение контакта, времени и суммы не всегда означает технический дубль. Решение о повторе связано с конкретной командой, а подозрительные похожие заказы можно вынести в отдельный список для менеджера.
Разбор процесса при конкурентном отказе
Вход процесса — запрос на конкретный ресурс, время услуги и известные условия подготовки. Участники — менеджер, клиент, владелец календарных правил и система хранения. На первом шаге менеджер заполняет карточку; на втором сервер проверяет состав и полномочия; на третьем принимает согласованное решение о занятости. Выход — подтверждённая бронь либо объяснимый отказ без потери исходного обращения.
Ветка исключения начинается, когда выбранное время занято. Менеджер должен видеть достаточное объяснение, но не обязательно чужие контакты: для предложения альтернативы часто достаточно времени блокировки. Система сохраняет заполненные данные и позволяет изменить интервал. Если клиент просит исключение, оно направляется уполномоченной роли; обычная кнопка повтора не должна обходить правило.
Контроль процесса проводится по сохранённым обязательствам, а не по числу успешных уведомлений. Владелец площадки периодически проверяет пары конфликтующих интервалов, причины отказов и судьбу обращений после конфликта. Высокое число отказов может означать востребованность ресурса, неудобный подбор времени или техническую ошибку. Эти причины требуют разной реакции.
Матрица приёмки бронирования
| Сценарий | Подготовка | Ожидаемый итог | Артефакт проверки |
|---|---|---|---|
| Параллельное создание | Два пользователя, один зал, пересекающееся время | Только один несовместимый запрос подтверждён | Две попытки и фактический список броней |
| Подготовительный буфер | Услуга закончилась, уборка ещё идёт | Следующая аренда не заняла буфер | Поля услуги и блокировки |
| Перенос в занятое время | Есть действующая исходная бронь | Отказ не изменил прежнее обязательство | Карточка до и после отказа |
| Повтор после неизвестного ответа | Первая команда сохранена, ответ не получен | Возвращён прежний результат без второй брони | Идентификатор попытки и количество записей |
| Редактирование устаревшей карточки | Два окна одной брони | Изменения другого сотрудника не потеряны молча | История версий и решение пользователя |
| Отмена и новое создание | Отменено блокирующее обязательство | Время освобождено согласно принятому статусу | История отмены и новая проверка |
| Другой часовой пояс | Устройство и площадка используют разные зоны | Подтверждение относится к верному местному времени | Отображение в обеих ролях |
| Ограниченная роль | Пользователь видит только занятость | Отказ объясним без раскрытия лишних данных | Ответ календаря и состав полей |
Тест параллельности нужно выполнять действительно с перекрывающимися попытками. Два последовательных сохранения проверяют обычный отказ по уже видимой записи, но могут не обнаружить разрыв между проверкой и записью. В протоколе фиксируют число попыток, исходное состояние, полученные ответы и окончательное количество подтверждённых обязательств. Если проверка нерегулярно даёт два успеха, её нельзя считать пройденной на основании удачного повторного запуска.
Что передать в поддержку
Для будущего разбора достаточно короткого паспорта ресурса: идентификатор, часовой пояс, график доступности, буферы, блокирующие статусы и лицо, принимающее исключения. К нему добавляют таблицу граничных интервалов и несколько обезличенных примеров. Доступ к журналам ограничивают рабочей необходимостью; реальные контакты не нужно копировать в общие технические задачи.
Полезный диагностический запрос содержит номер брони, примерное время действия, ожидаемый ресурс и наблюдаемый ответ. Формулировка «календарь сломался» заставит поддержку заново выяснять весь маршрут. Скриншот помогает увидеть интерфейс, но основной разбор опирается на сохранённое состояние и идентификаторы. Это позволяет отличить конфликт ресурсов от устаревшего экрана, дубля команды или ошибки отображения времени.
Для технической реализации необходимо сверять гарантии конкретного хранилища. Например, официальное описание уровней изоляции PostgreSQL помогает обсуждать поведение конкурентных операций. Выбор одного режима по названию не заменяет проверку принятого правила на двух одновременных запросах. Упоминание документации здесь не утверждает, что эта база использовалась во всех календарных проектах.
Что обещать клиенту до подтверждения
Если выбранное время ещё не закреплено, назовите его предварительным вариантом. В условной аренде менеджер может обсуждать условия, пока другой сотрудник оформляет тот же зал. Скриншот свободного календаря в этот момент не должен становиться основанием безусловного обещания.
После конфликта сохраните содержание обращения и предложите разрешённые альтернативы. Если бизнес допускает ручное исключение, определите уполномоченного участника и последствия для уже подтверждённой брони. Обычный повтор сохранения не должен незаметно превращаться в такое исключение.
Документация и источники
Расскажите, что бронируете, какие перерывы нужны и кто меняет записи. Я отделю время услуги от блокировки ресурса и подготовлю проверку конфликтов, переносов и повторов. Направления автоматизации. Написать в Telegram · Написать в MAX
Короткие ответы
Вопросы по теме
Когда можно обещать клиенту время?
После подтверждения по согласованному механизму, а не по одному отображению свободного календаря.
Что должно произойти при неудачном переносе?
Согласованное исходное обязательство не должно исчезать из-за частичного неудачного изменения.
Повтор после потери ответа — новая бронь?
Не обязательно. Сначала устанавливают исходный результат по устойчивому ключу операции.