HandyCafe Docs
owner

Тарификация сессий

HandyCafe использует сегментную систему тарификации для расчета стоимости сессий в вашем интернет-кафе или игровом центре. Вместо единой фиксированной ставки на всю сессию движок разбивает каждую сессию на сегменты, каждый из которых имеет собственный тарифный контекст. Такой подход обеспечивает точное выставление счетов даже когда сессии пересекают границы тарифных слотов, изменений ценообразования, пауз или отключений.

Основные понятия

Прежде чем переходить к деталям, ознакомьтесь с ключевыми терминами:

Термин Определение
Базовая почасовая ставка Цена за час до применения множителей. Задается в Настройки > Тарификация.
Тарифный слот Именованный временной период с определенным множителем. Всего 8 слотов, каждый с цветовой маркировкой.
Множитель Коэффициент, применяемый к базовой ставке. 1.0 = стандартная цена, 0.5 = половина цены, 2.0 = двойная цена.
Сегмент Непрерывный период внутри сессии, в течение которого тарифный контекст (слот, множитель, базовая цена) остается неизменным.
Расчет (settlement) Итоговый расчет суммы к оплате при завершении сессии.

Базовая почасовая ставка

Базовая почасовая ставка является основой всех тарифных расчетов. Она задается в Настройки > Тарификация и представляет стандартную цену за час использования ПК.

Все внутренние расчеты ведутся в минорных единицах валюты (например, копейки для рублей, центы для долларов). Если базовая ставка составляет $3.00 в час, внутреннее значение равно 300. Это исключает ошибки округления с плавающей запятой.

Поддержка двух валют

HandyCafe поддерживает базовую валюту и локальную валюту с обменным курсом (FX). Если вы работаете в стране, где международное ценообразование отличается от местного:

  • Базовая валюта. Валюта, используемая для внутренних расчетов.
  • Локальная валюта. Валюта, отображаемая клиентам и принимаемая к оплате.
  • Обменный курс (FX). Коэффициент конвертации между базовой и локальной валютами.

Если обе валюты совпадают, курс считается равным 1.0 и не оказывает влияния.

Тарифные слоты

Доступно 8 тарифных слотов с цветовой маркировкой, каждый представляет отдельный уровень ценообразования:

Слот Цвет Типичное использование
Blue Синий Стандартная ставка
Orange Оранжевый Вечерняя или выходная наценка
Red Красный Пиковые часы (премиум)
Green Зеленый Скидка в непиковые часы
Teal Бирюзовый Студенческая или членская ставка
Gray Серый Праздничное или специальное ценообразование
Cyan Голубой Ночная ставка
Emerald Изумрудный Акционная ставка

Каждый слот имеет три свойства:

  1. Название. Описательная метка (например, «Пиковые часы» или «Ночная скидка»).
  2. Множитель. Десятичное значение, модифицирующее базовую ставку. Типичные значения: 1.0 (стандарт), 0.5 (половина цены), 1.5 (наценка 50%), 2.0 (двойная цена). Множитель должен быть нулевым или положительным.
  3. Данные расписания. Внутреннее представление, определяющее в какие часы каких дней действует слот. Управляется автоматически через сетку расписания.

Слоты можно включать и отключать по отдельности. Отключенные слоты игнорируются движком тарификации.

Сетка расписания

Расписание тарификации представляет собой матрицу 7 дней на 24 часа (168 часовых блоков). Каждый блок привязан к одному тарифному слоту. Расписание определяет, какой множитель действует в каждый момент времени.

Сетка настраивается в Настройки > Расписание тарификации. Дни идут с понедельника по воскресенье, часы с 00:00 до 23:00. Для назначения слота временному блоку выберите блок в сетке и укажите нужный цвет слота.

Как движок читает расписание

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

Если ни один слот не назначен на данный час, движок использует базовую ставку с множителем 1.0.

Когда функция расписания тарификации полностью отключена (в Настройки > Тарификация), все сессии тарифицируются по базовой ставке с множителем 1.0 вне зависимости от времени.

Тарифные сегменты

Сегмент представляет собой непрерывный период внутри сессии, в течение которого тарифный контекст не меняется. Движок создает новый сегмент при наступлении любого из следующих граничных событий:

Граница Триггер
session_start Начало новой сессии
session_stop Остановка сессии
pause Кассир ставит сессию на паузу
resume Кассир возобновляет приостановленную сессию
tick Часы пересекают границу часа с переходом в другой тарифный слот
disconnect Клиентский ПК теряет сетевое соединение
offline Клиентский ПК уходит в офлайн
load_recovery Сервер перезапускается и восстанавливает запущенную сессию

Каждый сегмент записывает:

Поле Описание
session_id Сессия, к которой принадлежит сегмент
segment_start Unix-метка времени начала сегмента
segment_end Unix-метка времени окончания сегмента (null если еще открыт)
pricing_slot_id ID активного тарифного слота (например, «blue», «red» или «base»)
multiplier Значение множителя из тарифного слота
base_price_snapshot Базовая почасовая ставка, зафиксированная в момент открытия сегмента
amount Рассчитанная стоимость сегмента (устанавливается при закрытии)
boundary_reason Причина создания сегмента

Зачем фиксировать базовую цену?

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

Формула расчета стоимости

Стоимость одного сегмента рассчитывается по формуле:

amount = ceil( (base_price_snapshot * multiplier * duration_seconds) / 3600 )

Движок использует масштабированную целочисленную арифметику для исключения ошибок с плавающей запятой:

  1. Множитель масштабируется до целого числа с фиксированной точкой (умножается на 1 000 000).
  2. Расчет полностью выполняется в 128-битных целых числах.
  3. Применяется деление с округлением вверх. Результат всегда округляется до следующей минорной единицы.

Расчет по минутам

Если в Настройки > Тарификация включена опция «Расчет по минутам», формула немного меняется:

amount = ceil( (base_price_snapshot * multiplier * used_minutes) / 60 )

Здесь used_minutes = ceil(duration_seconds / 60). Любая неполная минута считается как полная.

Расчет итога сессии

Итоговая стоимость сессии вычисляется в три шага:

Шаг 1: Суммирование всех сегментов

raw_total = сумма всех закрытых сегментов + частичная сумма открытого сегмента

Частичная сумма открытого сегмента рассчитывается в реальном времени по формуле выше с текущей меткой времени в качестве конца сегмента.

Шаг 2: Применение округления

rounded_total = round_up(raw_total, rounding_step)

Округление всегда выполняется вверх (потолок) для защиты выручки. Шаг округления настраивается в Настройки > Тарификация. Например, если шаг округления равен 50 (что соответствует $0.50 в валюте с 2 знаками после запятой), необработанный итог $3.27 округляется до $3.50.

Шаг 3: Применение минимальной стоимости запуска

final_total = max(rounded_total, startup_fee)

Стоимость запуска представляет собой минимальный сбор за любую сессию вне зависимости от продолжительности. Если округленный итог меньше стоимости запуска, взимается стоимость запуска.

Расчет (settlement)

Расчет представляет собой процесс финализации биллинга сессии. Существует два этапа расчета:

Начальный расчет (только для предоплатных сессий)

При начале предоплатной сессии создается запись расчета «start». Она фиксирует:

  • Расчетная стоимость. Рассчитанная системой стоимость за оплаченное время.
  • Списанная сумма. Сумма, фактически оплаченная клиентом (обычно совпадает с расчетной стоимостью).

Для режима предоплаты «Фиксация при покупке» эта зафиксированная сумма определяет стоимость сессии вне зависимости от изменений ценообразования в ходе сессии.

Финальный расчет

При остановке любой сессии (предоплатной или постоплатной) создается запись расчета «stop»:

Поле Описание
Расчетная стоимость Рассчитанная системой сумма по всем тарифным сегментам
Списанная сумма Фактически списанная сумма (по умолчанию равна расчетной стоимости)
Скорректированная сумма Если кассир вручную изменил цену, здесь сохраняется исходная расчетная стоимость
Ставка комиссии Комиссия способа оплаты (в процентах)
commission_fee Рассчитанная сумма комиссии
fixed_fee Фиксированная комиссия способа оплаты
computed_timeline_snapshot JSON-запись каждого тарифного сегмента сессии

Снимок временной шкалы обеспечивает полный аудиторский след, показывающий как именно была рассчитана стоимость, сегмент за сегментом.

Комиссии способов оплаты

Каждый способ оплаты может иметь два вида комиссий:

Процентная комиссия

Ставка комиссии выражается в процентах. Сумма комиссии рассчитывается применением этой ставки к списанной сумме.

Пример: если списанная сумма составляет $10.00 (1000 минорных единиц), а комиссия способа оплаты равна 2.5%, сумма комиссии составит $0.25 (25 минорных единиц).

Фиксированная комиссия

Фиксированная сумма, удерживаемая за каждую транзакцию вне зависимости от суммы. Например, комиссия за обработку банковской карты $0.30.

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

НДС

НДС настраивается как процент (0-100%) в Настройки > Тарификация. Он начисляется сверх рассчитанной суммы сессии:

НДС = списанная сумма x (ставка НДС / 100)

Сумма НДС отображается отдельной строкой в диалоге оплаты, чтобы кассир видел разбивку по налогам.

Режимы предоплатной тарификации

Как описано в разделе Управление сессиями, предоплатные сессии поддерживают два режима тарификации:

Фиксация при покупке

При начале предоплатной сессии начальный расчет фиксирует списанную сумму. На протяжении всей сессии:

  • Время окончания сессии фиксировано на основе оплаченных минут.
  • Даже при изменении расписания тарификации сессия продолжается до истечения зафиксированного времени.
  • Финальный расчет использует зафиксированную сумму из начального расчета.

Живое расписание

Оставшееся время сессии непрерывно пересчитывается при смене тарифных слотов:

  • Если сессия входит в более дешевый слот, оставшееся время увеличивается (клиент получает больше минут за свои деньги).
  • Если сессия входит в более дорогой слот, оставшееся время сокращается.
  • Финальный расчет отражает фактическое ценообразование, примененное на протяжении всей сессии.

Знаки после запятой

Количество знаков после запятой для отображения валюты настраивается (2-4 знака). Это влияет на отображение сумм в интерфейсе, но не меняет внутренние расчеты в минорных единицах.

Пример: при 2 знаках после запятой $3.50 отображается как «3.50». При 3 знаках отобразится как «3.500».

Практические примеры

Пример 1: Простая постоплатная сессия

  • Базовая ставка: $3.00/час (300 минорных единиц)
  • Расписание: стандартный слот (множитель 1.0) весь день
  • Сессия: с 10:00 до 11:30 (90 минут)
  • Стоимость запуска: $0.50

Расчет:

Сегмент 1: (300 * 1.0 * 5400) / 3600 = 450 минорных единиц ($4.50)
Итого: max($4.50, $0.50) = $4.50

Пример 2: Сессия, пересекающая два слота

  • Базовая ставка: $4.00/час (400 минорных единиц)
  • Расписание: Стандартный (1.0) с 10:00 до 12:00, Счастливый час (0.5) с 12:00 до 14:00
  • Сессия: с 11:00 до 13:00 (120 минут)
  • Стоимость запуска: $1.00

Расчет:

Сегмент 1 (11:00-12:00, стандартный): (400 * 1.0 * 3600) / 3600 = 400 ($4.00)
Сегмент 2 (12:00-13:00, счастливый час): (400 * 0.5 * 3600) / 3600 = 200 ($2.00)
Итого: $4.00 + $2.00 = $6.00
Финальная сумма: max($6.00, $1.00) = $6.00

Пример 3: Сессия с паузой

  • Базовая ставка: $2.00/час (200 минорных единиц)
  • Расписание: стандартный слот (множитель 1.0) весь день
  • Сессия: старт 10:00, пауза 10:30, возобновление 11:00, стоп 11:45
  • Стоимость запуска: $0.50

Расчет:

Сегмент 1 (10:00-10:30, активный): (200 * 1.0 * 1800) / 3600 = 100 ($1.00)
Период паузы (10:30-11:00): без начислений
Сегмент 2 (11:00-11:45, активный): (200 * 1.0 * 2700) / 3600 = 150 ($1.50)
Итого: $1.00 + $1.50 = $2.50
Финальная сумма: max($2.50, $0.50) = $2.50

Дальнейшие шаги