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