Задача
Отель хотел, чтобы гость мог заселиться без очереди на ресепшене: найти свою бронь или забронировать номер на месте, пройти проверку документов, подписать регистрационную карту, оплатить и получить ключ. Всё это — поверх уже работающей отельной системы Oracle Hospitality Suite8 (Fidelio), которую нельзя останавливать или менять.
Как устроено
Касса — приложение на Avalonia под сенсорный экран 1080×1920 с интерфейсом на русском и английском. Она не ходит в базу сама: все операции идут через сервер на ASP.NET Core, который читает и пишет в Oracle Suite8 в транзакциях. Ключ-карта кодируется через интерфейс замков Fidelio IFC8; для номеров с обычными замками касса говорит гостю, что ключ выдадут на ресепшене.
Оборудование подключено через адаптеры: сканер документов, кодер ключей, платёжный терминал и СБП. Пока заказчик выбирает терминал и банк, на их месте стоят заглушки, и кассу можно испытывать целиком. Оплата организацией и брони через турагентов уходят на ресепшен — касса только для гостей, которые платят сами.
Если гость отошёл посреди заселения, касса через 90 секунд сбрасывает сессию, чтобы следующий человек не увидел чужие паспортные данные. Тайм-ауты и режим экрана меняются из админки для всех касс или для одной.
Что умеет касса
- Два сценария. Заселение по брони — бронь находится по отсканированному документу, а если она оформлена на другой профиль, по номеру подтверждения. Бронирование на месте — свой календарь, до 10 гостей и до 30 ночей, список категорий номеров с фотографиями.
- Вся группа гостей. Касса знает из брони, сколько человек заезжает, и по очереди собирает документы каждого: паспорт, права или свидетельство о рождении ребёнка. Кто уже вписан в бронь, показан готовым.
- Цифровой ID из MAX. Вместо паспорта взрослый гость может показать QR из мессенджера MAX — данные подставятся сами и уйдут в уведомление о прибытии.
- Ранний заезд и поздний выезд. Гость выбирает час плиткой и сразу видит доплату: например, выезд с 12 до 18 часов — плюс четверть стоимости ночи. Доплата входит в общий платёж.
- Честный расчёт. К оплате — цена брони минус то, что гость уже внёс на стойке. Если оплачено всё, шаг оплаты пропускается.
- Подпись на экране. Гость ставит галочки согласий и расписывается пальцем, сервер сам собирает PDF регистрационной карты. Готового холста для подписи в Avalonia нет — написали свой.
- Ключ или подсказка. Номер с электронным замком — ключ-карта кодируется на месте. Этаж с механическими замками — касса всё равно продаёт номер и говорит, что ключ выдадут на ресепшене.
- Русский и английский. Язык переключается на лету, вместе с ним — даты, числа и склонения вроде «1 ночь / 2 ночи / 5 ночей».
- Крупный ввод. Любое поле, которое нужно поправить, открывается в увеличенном редакторе с экранной клавиатурой — легко попасть пальцем в нужную букву.
Для персонала отеля
Вместе с кассой сделали веб-админку с личными учётками и ролями: ресепшен, маркетинг, техподдержка, администратор. Каждое действие пишется в журнал.
- Кассы онлайн. Версия, экран, на связи ли и ждёт ли обновления — по каждой кассе, с обновлением раз в несколько секунд.
- Выкладка без удалённого рабочего стола. Новая сборка кассы или самого сервера перетаскивается на страницу; подпись и контрольная сумма проверяются до замены.
- Настройки из браузера. Любой параметр меняется в админке; если после перезапуска сервер не поднялся за минуту, прежние настройки возвращаются сами.
- Смены и отчёты. Открытие и закрытие смены касс, отчёт по способам оплаты и по кассам, брони за период, фактические заезды за дату и дубли профилей для ежедневного объединения — в JSON и в Excel.
- Алерты в Telegram. Касса пропала со связи, перезапустилась, ключ не записался, мало места на диске, нет звука, гость вызвал администратора. Одинаковые события не спамят — повторы сворачиваются в счётчик.
Сложности и как мы их решили
01Отельная база без документации, в которую нельзя ошибиться
Проблема
Касса пишет прямо в боевую базу Suite8 — профили гостей, документы, брони, заселение. Общая документация Fidelio к этой установке не подходит, тестовой копии с реальными данными нет, а ошибка в записи сломает регистрационные карты и выгрузку в МВД.
Решение
Восстановили, как ресепшен на самом деле заполняет данные, по статистике боевой базы — от формата номера паспорта до разбора адреса по полям. Касса пишет так же, как штатный клиент Fidelio, включая журнал изменений. Бронирование защищено от дублей ограничением самой базы, перед выездом в отель — проверочные SQL-скрипты только на чтение.
02Паспорт сканирует сам гость
Проблема
Для заселения нужны три страницы паспорта — с фотографией, с датой выдачи и с пропиской, — и все они уходят дальше в уведомление о прибытии. Гость легко кладёт не ту страницу, а у группы гостей документов несколько, включая свидетельства о рождении детей.
Решение
Касса сканирует на МФУ и распознаёт данные по машиночитаемой зоне, проверяет, что на каждом шаге лежит нужная страница, и просит перевернуть, если нет. Документы всей группы собираются по очереди, после заселения сканы передаются в конвейер уведомлений МВД.
03Обновлять кассу без удалённого доступа
Проблема
Раньше новую сборку ставили на кассу вручную через удалённый рабочий стол. Это небезопасно и мешает гостю, если обновление попадёт на середину заселения.
Решение
Касса раз в минуту отмечается на сервере, а обновлятор каждые 15 минут забирает подписанную сборку и ставит её, только пока касса на стартовом экране. Если новая версия не отметилась за 3 минуты, она откатывается. Вызов администратора, ошибки и сбои сразу приходят в Telegram.
04Касса должна вести себя как кассир Fidelio
Проблема
Ресепшен сводит деньги по сменам и кассирам Fidelio, а в полночь отель закрывает день ночным аудитом. Если касса принимает оплату мимо этого учёта, гость после аудита окажется должником и заплатит второй раз.
Решение
Сделали смены касс, которые открывают и закрывают отдельного кассира в Fidelio так же, как это делает сотрудник ресепшена. Ночью кассир закрывается перед аудитом и сам открывается после смены даты, кассы при этом продолжают работать. Закрытие смены не обрывает гостя — касса закрывается, только вернувшись на заставку.
05Паспортные данные не должны оседать где попало
Проблема
Касса стоит в общем лобби и работает с паспортами. Данные легко «утекают» не через взлом, а через мелочи — номер паспорта в адресе запроса попадает в логи, отошедший гость оставляет на экране свою сессию, текст ошибки уходит в чат поддержки.
Решение
Номера документов и ФИО передаются только в теле запроса, поиск гостя ограничен по частоте. Касса сбрасывает сессию после 90 секунд бездействия. В Telegram уходят только касса, экран, бронь и сумма — без ФИО и документов, а отчёт о падении кассы — без текста ошибки, в котором могут оказаться данные гостя.
Результат
За полтора месяца касса прошла путь от первого экрана до испытаний на боевой базе отеля: гость сам находит бронь по паспорту, расписывается в регистрационной карте, оплачивает проживание и получает ключ-карту от номера. Платёжный терминал и банк для СБП подключаются через готовые адаптеры, как только заказчик их выберет.
Технологии
- Avalonia UI
- .NET 10
- .NET 8
- ASP.NET Core
- Oracle
- Dapper
- Fidelio IFC8
- Windows
- Serilog
- xUnit