Признание выручки
Эта страница объясняет, как именно система считает выручку за период и почему эта цифра может отличаться от суммы денег, которые реально легли на счёт за этот же период. Понимание этой разницы критично для любого, кто читает финансовые отчёты: владельца, бухгалтера, управляющего.
Короткий ответ
Заголовок раздела «Короткий ответ»Система использует метод начисления по ночам проживания (accrual по ночам) — международный стандарт USALI для гостиничного бизнеса. Выручка бронирования распределяется пропорционально ночам, когда гость реально проживал в номере, а не по дате создания брони и не по дате оплаты.
Это значит:
- Бронь на 10 ночей с 25 января по 4 февраля → в январе признаётся выручка за 7 ночей, в феврале — за 3.
- Момент, когда деньги легли на счёт, на эту цифру не влияет.
- В выручку попадают только заехавшие гости — брони в статусе CHECKED_IN и CHECKED_OUT. Подтверждённая, но ещё не заехавшая бронь (CONFIRMED) — это воронка продаж, а не выручка: пока гость не заселился, в номере никто не ночевал, и приписывать эту сумму к выручке месяца нельзя.
- Отменённые брони (CANCELLED, REJECTED) и неявки (NO_SHOW) в выручку не входят.
Три способа считать выручку — и почему мы выбрали именно этот
Заголовок раздела «Три способа считать выручку — и почему мы выбрали именно этот»В мировой практике есть три разных метода признания выручки, и они дают разные цифры за один и тот же период.
1. По дате брони (as-booked)
Заголовок раздела «1. По дате брони (as-booked)»Выручка признаётся в момент, когда бронь была создана. Проблема: это не выручка, это объём продаж. Забронированное в январе проживание в мае может быть отменено, и тогда «январская выручка» окажется фикцией.
2. По дате оплаты (cash-basis)
Заголовок раздела «2. По дате оплаты (cash-basis)»Выручка признаётся в момент, когда деньги пришли на счёт. Плюс: совпадает с банковской выпиской. Проблема: если гость внёс предоплату в декабре, а жил в марте, декабрь будет искусственно богатым, а март — бедным. Расходы на обслуживание гостя (уборка, коммуналка, зарплаты) всё равно пойдут в марте. В результате декабрь выглядит прибыльным без причины, март — убыточным без причины.
3. По ночам проживания (accrual — наш выбор)
Заголовок раздела «3. По ночам проживания (accrual — наш выбор)»Выручка признаётся пропорционально ночам, когда гость реально жил в номере. Плюс: выручка и расходы всегда относятся к одному и тому же периоду. GOP (прибыль до аренды и налогов) отражает реальную эффективность гостиницы за конкретный месяц. Минус: цифра выручки не совпадает один в один с движением денег по счёту.
Это и есть стандарт USALI — Uniform System of Accounts for the Lodging Industry, по которому отчитываются все международные гостиничные сети. Мы используем его, потому что это единственный метод, при котором P&L-отчёт даёт правду о том, заработала гостиница или потеряла за конкретный месяц.
Пример расхождения
Заголовок раздела «Пример расхождения»Бронь на 100 000 ₸, 10 ночей с 15 января по 25 января. Гость оплатил всё сразу при заезде 15 января. За январь расходы на эту бронь: 75 000 ₸ (зарплаты, коммуналка, продукты).
| Метод | Январь: выручка | Январь: GOP |
|---|---|---|
| По дате брони (as-booked) | зависит от даты создания | случайная цифра |
| По дате оплаты (cash) | 100 000 | +25 000 |
| По ночам (наш) | 100 000 | +25 000 |
Пока оплата и проживание в одном месяце — все методы сходятся.
А теперь тот же гость, но предоплатил в декабре:
| Метод | Декабрь выручка | Декабрь GOP | Январь выручка | Январь GOP |
|---|---|---|---|---|
| По дате брони | 100 000 (при бронировании в декабре) | +100 000 | 0 | −75 000 |
| По дате оплаты (cash) | 100 000 | +100 000 | 0 | −75 000 |
| По ночам (наш) | 0 | 0 | 100 000 | +25 000 |
Видно, что первые два метода создают ложно-прибыльный декабрь и ложно-убыточный январь. Метод по ночам даёт правду: декабрь ничего не заработал, январь принёс 25 000 ₸ прибыли.
Где какой метод используется в системе
Заголовок раздела «Где какой метод используется в системе»| Отчёт / экран | Метод | Почему именно так |
|---|---|---|
| Дашборд, карточка «Выручка» | Accrual по ночам | Показывает реальную выручку периода |
| График RevenueStats (месячная разбивка) | Accrual по ночам | Для корректной помесячной картины |
P&L отчёт (/reports/pnl) | Accrual по ночам | USALI-стандарт; доступ по праву financial_kpi.view |
| GOP, GOPPAR, NOI | Accrual по ночам | Только так имеет смысл |
| Night Audit | Cash (по оплатам смены) | Ночной аудит отвечает на вопрос «что произошло за смену», а не «какая выручка признана» |
Касса и платежи (/reports/payment-ledger) | Cash (по платежам) | Главный отчёт для сверки с банком — показывает реально поступившие деньги |
Балансы броней (/reports/aging) | Остатки по броням | Кто сколько должен (и где переплаты) |
Как считается pro-rata
Заголовок раздела «Как считается pro-rata»Для каждой брони, чьи ночи пересекаются с запрашиваемым периодом:
perNightRoom = (totalAmount − extrasSum) / totalNightsperNightExtras = extrasSum / totalNightsperNightAdjustment = adjustmentsSum / totalNightsoverlapNights = количество ночей пересечения брони с периодом
roomsRevenue += perNightRoom × overlapNightsextrasRevenue += perNightExtras × overlapNightsadjustmentsRevenue += perNightAdjustment × overlapNightsГде:
totalAmount— итоговая сумма брони (включая доп. услуги изextraCharges)extrasSum— сумма полейtotalиз массиваextraChargesadjustmentsSum— суммаBookingPriceAdjustment.calculatedAmountдля всех активных корректировок брони (SURCHARGE даёт положительный вклад, DISCOUNT — отрицательный)totalNights— количество ночей брони целиком (checkOut − checkIn)overlapNights— пересечение дат брони с запрашиваемым периодом
Если бронь полностью вне периода → выручка 0.
Если totalNights = 0 (некорректная бронь) → выручка 0.
В accrual-выручку (дашборд и P&L) попадают только заехавшие гости — брони в статусе CHECKED_IN и CHECKED_OUT. Подтверждённые, но ещё не заехавшие брони (CONFIRMED) исключаются: это будущая выручка (воронка), а не выручка периода. Отменённые (CANCELLED, REJECTED) и неявки (NO_SHOW) также не учитываются.
Скидки/доплаты (BookingPriceAdjustment)
Заголовок раздела «Скидки/доплаты (BookingPriceAdjustment)»Скидка/доплата — это пост-факт изменение цены брони (SURCHARGE — доплата, DISCOUNT — скидка), которая применяется оператором уже после создания брони (например: «доплата за дополнительного гостя», «VIP-скидка 10%», «компенсация за поломку кондиционера»).
Скидки/доплаты распределяются по тем же ночам проживания, что и сама бронь — это нужно чтобы реальная цена сделки (totalAmount + сумма скидок/доплат) корректно отражалась в accrual-выручке за период проживания.
Пример: бронь на 10 ночей с 25 января по 4 февраля, базовая цена 100 000 ₸, оператор 13 февраля добавил скидку −20 000 ₸ за лояльность. Скидка распределится по 2 000 ₸ на каждую ночь:
| Метод | Январь выручка | Февраль выручка |
|---|---|---|
По дате createdAt скидки/доплаты | 70 000 (100к × 7/10) | 30 000 − 20 000 = 10 000 |
| По ночам проживания (наш) | 70 000 − 14 000 = 56 000 | 30 000 − 6 000 = 24 000 |
Метод по ночам — единственный корректный для accrual: скидка относится к услуге (10 ночам проживания), а не к моменту, когда оператор её внёс в систему.
Доп. услуги в бронированиях и допродажи
Заголовок раздела «Доп. услуги в бронированиях и допродажи»Выручка сверх проживания разбивается на два потока:
-
Доп. услуги в бронированиях (поле
booking.extraCharges— завтрак, трансфер, доп. кровать и прочее из каталога, приложенное к брони) — распределяются пропорционально ночам проживания, так же как и основная выручка. Входят в P&L и в «Выручку» дашборда. -
Допродажи (standalone
ServiceSale— разовые продажи на ресепшене сверх брони: бар, прачечная, сувениры) — признаются по дате оплаты (paidAt). У каждой такой продажи нет понятия «ночей проживания», и дата услуги совпадает с датой оплаты в подавляющем большинстве случаев. В P&L и «Выручку» дашборда не входят — для них отдельный отчёт «Допродажи».
Это небольшое расхождение с чистым USALI (где и service sales могли бы признаваться по дате оказания услуги), но на практике оно значимо только для случая, когда гость оплачивает накопленные услуги при выезде — тогда вся сумма попадает в день выезда, а не распределяется по дням проживания. Для гостиницы это редко меняет картину.
Разбивка выручки по департаментам (USALI)
Заголовок раздела «Разбивка выручки по департаментам (USALI)»В P&L-отчёте accrual-выручка дополнительно разносится по операционным департаментам по стандарту USALI: Rooms (проживание), F&B, и прочие операционные департаменты. Привязка идёт через категорию услуги (SaleCategory.department):
- Проживание (комната + скидки/доплаты − возвраты) → всегда департамент Rooms.
- Доп. услуги в бронированиях и допродажи → в свой департамент по категории услуги; если категория не задана — попадают в UNCLASSIFIED (не распределено).
По каждому департаменту P&L показывает не только выручку, но и прибыль департамента (departmentProfits = выручка департамента − его операционные расходы). Это позволяет увидеть, какой департамент зарабатывает, а какой — съедает маржу. Сама модель расчёта по ночам при этом не меняется: департаментная разбивка — это «надстройка» над той же accrual-выручкой.
Refunds (возвраты)
Заголовок раздела «Refunds (возвраты)»Возвраты вычитаются по дате обработки (paidAt у платежа с type=REFUND). Это бухгалтерский стандарт: возврат — это поправка текущего периода, а не ретроактивное изменение прошлого закрытого месяца.
Последствие: если гость жил в январе, а возврат ему оформили в марте, то:
- Январь показывает полную выручку (100 000 ₸)
- Март вычитает возврат из своей выручки
- Сумма помесячных чисел за январь-март не равна сумме выручки за квартал, если возврат был частичным и затронул оба месяца. Для квартального периода возврат будет учтён один раз.
Если для вас это проблема (например, нужна чистая квартальная выручка без таких артефактов) — запрашивайте P&L за квартал целиком, а не складывайте три месячных отчёта вручную.
Почему цифры в P&L не сходятся с кассой
Заголовок раздела «Почему цифры в P&L не сходятся с кассой»Самый частый источник путаницы. Управляющий смотрит на дашборд за апрель и видит «Выручка: 593 270 ₸». Потом открывает банковскую выписку и кассу и понимает, что за размещение (за ночи гостей) за этот месяц фактически не пришло ни тенге — только 20 270 ₸ за услуги на ресепшене. Возникает закономерный вопрос: что это за 593 270 ₸ и где они?
Короткий ответ
Заголовок раздела «Короткий ответ»Это две разные метрики про два разных события, и обе верные — просто про разное.
- 593 270 ₸ (P&L / дашборд) — это начисленная выручка за апрель по USALI: столько гостиница заработала услугами, оказанными в апреле. Часть гостей оплачивала эти ночи в марте, часть оплатит в мае — но услуги оказаны в апреле, поэтому выручка признана в апреле.
- 20 270 ₸ (касса) — это сколько реальных денег поступило в апреле. За проживание в этом месяце большая часть уже была оплачена заранее (в марте или раньше), поэтому в кассе апреля только допродажи.
Обе цифры корректны. Они отвечают на разные вопросы:
- P&L отвечает «сколько гостиница заработала апрелем»
- Касса отвечает «сколько денег поступило в апреле»
Ещё один пример
Заголовок раздела «Ещё один пример»Владелец смотрит на P&L за март и видит «GOP: 2 000 000 ₸». Потом смотрит выписку за март — «пришло 3 500 000 ₸». Разница в другую сторону.
- GOP 2 000 000 — столько гостиница заработала за услуги, оказанные в марте (прибыль до аренды и налогов).
- 3 500 000 на счёте — это разные деньги: часть за март, часть предоплат за апрель-май, минус частичные возвраты за февральские брони.
Эти цифры никогда не обязаны совпадать. Совпадают они только в учебном примере, когда все гости заехали, прожили и расплатились в одном и том же месяце, а возвратов не было.
Как посмотреть реальные деньги — пошагово
Заголовок раздела «Как посмотреть реальные деньги — пошагово»
Если нужно ответить на вопрос «сколько денег реально пришло за этот период», зайти нужно в Касса и платежи.
- В левом меню откройте раздел «Отчёты» → «Касса и платежи» (значок кошелька).
- Вверху — три KPI-карточки:
- Поступления — сколько пришло всего за период (и количество транзакций).
- Возвраты — сколько вернули гостям (если были возвраты).
- Чистая касса — итог: поступления минус возвраты. Это число для сверки с банком.
- Ниже — блок «По источнику»: отдельно брони и отдельно сервис (бар, прачечная, допуслуги на ресепшене). Видно, откуда пришли деньги.
- График «Поступления по дням» — столбчатая диаграмма. Зелёные столбцы — поступления, красные — возвраты. Сразу видно пиковые дни.
- Таблица «По способам оплаты» — отдельно наличные, Kaspi, банк. перевод и т.д. Эта разбивка обычно нужна бухгалтеру.
- Внизу — детальная таблица транзакций: каждая запись со ссылкой на бронирование и гостя.
- Справа сверху — кнопки Excel и CSV. Обычно бухгалтеру отправляется Excel за месяц.
Фильтр периода — стандартный: сегодня / вчера / этот месяц / прошлый месяц / квартал / произвольный диапазон. Всё на странице — KPI, график, разбивки и таблица — пересчитывается в связке.
Куда смотреть в зависимости от задачи
Заголовок раздела «Куда смотреть в зависимости от задачи»| Задача | Отчёт |
|---|---|
| Сколько денег пришло за день/неделю/месяц | Касса и платежи |
| Сверка кассы с банковской выпиской | Касса и платежи → Excel |
| Сколько пришло наличными / Kaspi / переводом | Касса и платежи → «По способам оплаты» |
| Что заработала гостиница в марте (прибыльность) | P&L |
| Какая маржа (GOP, NOI, GOPPAR) | P&L |
| Сравнение этого месяца с прошлым годом по прибыли | Год к году |
| Что произошло за смену на ресепшене (заезды/выезды/оплаты одной даты) | Ночной аудит |
| Кто из гостей должен денег (и где переплаты) | Балансы броней |
Технические детали
Заголовок раздела «Технические детали»- Файл хелпера:
apps/api/src/common/helpers/revenue.helper.ts - Функция:
prorateBookingRevenue(bookings, from, to)— для суммы за период - Функция:
prorateBookingRevenueByBucket(bookings, from, to, granularity)— для помесячной/подневной разбивки - Используется в
analytics.service.revenue()иreports.service.profitAndLoss()
Что планируется дальше
Заголовок раздела «Что планируется дальше»- YoY Comparison пока использует упрощённый метод (вся выручка брони приписывается месяцу
checkIn). Это близко к accrual, но не точно. В следующей итерации переедет на тот же хелпер. - Night Audit останется на cash-basis — это его естественная семантика.
Где скидки/доплаты учитываются в отчётах
Заголовок раздела «Где скидки/доплаты учитываются в отчётах»| Отчёт | Метод учёта скидок/доплат |
|---|---|
Дашборд → «Выручка» (analytics.revenue) | Pro-rata по ночам, в составе totalRevenue |
P&L (reports.profitAndLoss) | Отдельная строка revenue.adjustments, входит в revenue.total |
| Revenue by Group | Свёрнуты в totalRevenue группы (без отдельной строки) |
| Channel Performance | Свёрнуты в totalRevenue канала (без отдельной строки) |
| Cancellation Report | Включены в lostRevenue отменённой брони целиком |
| Night Audit | Отдельная строка revenue.adjustments по createdAt скидки/доплаты |