Budget manager: Табель, KPI и Зарплата

Полное руководство: Табель, KPI и Зарплата

Как мы создали интегрированную HR-экосистему в Budget Manager


1. Введение: Почему три модуля стали одним решением

Когда мы начинали проект Budget Manager, перед нами
стояла задача автоматизировать управление бюджетом компании. Но очень
быстро стало понятно, что самая большая статья расходов — это
Фонд Оплаты Труда (ФОТ), и именно здесь больше всего
хаоса.

Типичная проблема: В компании 50 сотрудников. Табель
ведётся в Excel, KPI обсуждаются устно, а зарплату считает бухгалтер
вручную. Каждый месяц — это 2 дня нервотрепки, ошибки, пересчёты и
недовольные сотрудники, которые не понимают, откуда взялась итоговая
сумма.

Мы задали себе вопрос:
А что, если зарплата будет рассчитываться автоматически как
математическая функция?</strong >

Формула расчёта: Зарплата = f(Оклад, Отработанные_Часы,
KPI%, Налоги)

Для этого нам нужны были три компонента:

Модуль Задача Результат
Табель (Timesheet) Точный учёт времени работы Данные для расчёта пропорциональной ЗП
KPI Объективная оценка результативности Размер премий и бонусов
Payroll Автоматический расчёт Точная ЗП без ручных расчётов

И самое главное — эти три модуля должны интегрироваться.
Каждое изменение в табеле должно мгновенно влиять на прогноз зарплаты.
Каждое обновление KPI должно автоматически пересчитывать премии.

Что мы получили в итоге

Результат Описание
Расчёт зарплаты 15 минут вместо 2 дней
Ошибки в начислениях Снизились до нуля
Прозрачность Сотрудники видят свою будущую зарплату
в реальном времени
Прогнозирование Точный прогноз ФОТ на 6-12 месяцев вперёд

Давайте разберём каждый модуль подробно, с примерами из реальных
бизнес-кейсов.


2. Модуль 1: Умный Табель (Timesheet)

Табель — это не просто список «пришёл/ушёл». Это юридически значимый
документ, который напрямую влияет на расчёт зарплаты, отпускных и
больничных.

2.1. Архитектура и типы дней

В нашей системе табель состоит из двух сущностей:

  • WorkTimesheet: Табель на месяц для одного сотрудника
    (заголовок)
  • DailyWorkRecord: Запись по каждому дню месяца
    (детализация)

Ключевая особенность: Мы различаем 6 типов дней:

Тип дня Код Описание Влияние на зарплату
Рабочий день WORK Обычный рабочий день Оплачивается по часовой ставке
Выходной WEEKEND Суббота, воскресенье Не оплачивается (если нет переработок)
Отпуск VACATION Оплачиваемый отпуск Исключается из оклада, оплата по среднему
Больничный SICK_LEAVE Лист нетрудоспособности Оплата по законодательству (ФСС)
Отгул UNPAID_LEAVE Отпуск за свой счёт Уменьшает оклад пропорционально
Праздник HOLIDAY Государственный праздник Сокращает норму рабочих часов

2.2. Производственный календарь России

Одна из самых сложных задач — корректный учёт праздников и переносов
выходных. Российское правительство ежегодно публикует переносы, и мы
должны их учитывать.

Компоненты производственного календаря

Компонент Описание Примеры
Фиксированные праздники Нерабочие дни, установленные законом 1 января, 9 мая, 12 июня, 4 ноября
Переносы выходных Рабочие субботы и дополнительные выходные В 2025: 3 января (сб) — рабочий, 8 мая (чт) — выходной
Автоматический расчёт Система считает рабочие дни в месяце Май 2025: 18 рабочих дней вместо обычных 21-22

Почему это важно?

Реальный кейс: Май 2025 года имеет всего 18 рабочих дней
(вместо обычных 21-22 из-за майских праздников). Это значит, что стоимость
одного рабочего дня в мае выше. Если сотрудник возьмёт отгул в
мае, он потеряет Оклад / 18, а не Оклад / 22.

2.3. Жизненный цикл табеля

Табель проходит строгий workflow, чтобы исключить ошибки:

Статус Описание Кто может редактировать Следующий шаг
DRAFT Черновик, заполняется HR HR, Руководитель Утверждение → APPROVED
APPROVED Утверждён руководителем Только Руководитель (откат на DRAFT) Используется для расчёта ЗП

Важное правило: Зарплата не может быть рассчитана, пока
табель не утверждён.

2.4. Кейсы и примеры

Кейс №1: «Майские праздники»

Параметр Значение
Ситуация Сотрудник хочет взять отгул 2-3 мая 2025
Оклад 120 000 руб.
Рабочих дней в мае 18 дней (вместо обычных 22)
Стоимость 1 дня 120 000 / 18 = 6 667 руб.
Потери за 2 дня 13 334 руб.
Преимущество Сотрудник видит это в личном кабинете до заявления

Кейс №2: «Больничный в середине месяца»

Шаг Действие Результат
1 Разработчик заболел 10-15 ноября (5 дней) Сотрудник уведомляет HR
2 HR меняет статус дней на SICK_LEAVE Система пересчитывает часы: 176 → 136
3 Табель возвращается в DRAFT Требуется переутверждение
4 Руководитель утверждает изменения Данные готовы для Payroll
5 Payroll пересчитывает зарплату Оклад уменьшен на 40 часов + строка «Больничные»

Кейс №3: «Сотрудник вышел 15-го числа»

Параметр Значение Комментарий
Дата выхода 15 ноября Новый дизайнер
Оклад (полный) 100 000 руб. При полном месяце
Плановых часов 176 часов Норма для ноября
Отработано 88 часов Ровно половина месяца
Формула (100 000 / 176) × 88 Пропорциональный расчёт
Зарплата 50 000 руб. Без «на глаз»

Кейс №4: «Переработки в выходные»

Параметр Значение
Ситуация Программист работал в субботу 8 часов (критический релиз)
Действие HR Ставит в табеле: day_type = WORK, hours_worked = 8
Реакция системы Добавляет 8 часов к total_hours_worked
Оплата По обычной ставке (или с повышающим коэффициентом)

Кейс №5: «Корпоративный праздник (сокращённый день)»

Параметр Значение
Ситуация 31 декабря компания отпустила всех в 14:00
Норма 8 часов (до 18:00)
Фактически 4 часа (до 14:00)
Действие HR hours_worked = 4, day_type = WORK
Опция Если руководство оплачивает полный день — добавить комментарий

3. Модуль 2: KPI и Система Мотивации

Самый сложный и одновременно самый интересный модуль. Здесь мы превратили
абстрактные «цели» в математически рассчитываемые премии.

3.1. Иерархия целей: Monthly, Quarterly, Annual

Мы отказались от плоской системы «оклад + премия». Вместо этого создали
три горизонта планирования:

Тип цели Период Когда выплачивается Примеры
MONTHLY 1 месяц В конце каждого месяца Выполнение плана продаж, количество закрытых тикетов
QUARTERLY 3 месяца Март, Июнь, Сентябрь, Декабрь Запуск нового продукта, внедрение CRM
ANNUAL 12 месяцев Декабрь (13-я зарплата) Прибыль компании, достижение стратегических целей

Архитектура данных

Сущность Назначение Примеры данных
KPIGoal Библиотека целей (общие для компании) «План продаж», «Качество кода», «Удовлетворённость клиентов»
EmployeeKPI KPI сотрудника за конкретный период Ноябрь 2025, статус DRAFT/APPROVED, итоговый KPI%
EmployeeKPIGoal Связь сотрудника с целями + трекинг Цель, вес, target, actual, achievement%

3.2. Математика расчёта KPI%

Итоговый KPI% сотрудника — это взвешенное среднее всех
его целей. Причём для каждого типа премии (месячная, квартальная, годовая)
рассчитывается свой KPI%.

Формула: KPI% = (Цель1_Выполнение × Цель1_Вес +
Цель2_Выполнение × Цель2_Вес + …) / Сумма_Весов

Пример расчёта: Менеджер по продажам

Цель Вес Выполнение Взвешенный результат
План продаж 50% 100% 50 × 100 = 5000
Количество звонков 30% 80% 30 × 80 = 2400
Обучение новичков 20% 50% 20 × 50 = 1000
Итоговый KPI% 8400 / 100 = 84%
База премии 50 000 руб.
Премия к выплате 42 000 руб.

3.3. Типы бонусов: Performance, Fixed, Mixed

Не все премии должны зависеть от KPI. Мы реализовали три типа:

Тип бонуса Описание Формула Пример
PERFORMANCE_BASED Премия напрямую зависит от KPI% Премия = База × (KPI% / 100) База 50k, KPI 84% → Премия 42k
FIXED Выплачивается полностью при KPI ≥ порога Премия = База (если KPI ≥ 80%), иначе 0 База 30k, KPI 84% → Премия 30k
KPI 70% →
Премия 0
MIXED Часть гарантирована, часть зависит от KPI Премия = База × Фикс% + База × (1 — Фикс%) × (KPI% / 100) База 100k, фикс 30%, KPI 80%
→ 30k + 70k×0.8 =
86k

3.4. Кейсы и примеры

Кейс №6: «Прозрачная мотивация менеджера»

Персонаж: Алексей, менеджер по продажам

Параметр Значение
Оклад 60 000 руб.
Месячная премия (база) 40 000 руб. (PERFORMANCE_BASED)
Цели на ноябрь:
План продаж (вес 60%) 1 000 000 руб.
Количество звонков (вес 40%) 200 звонков

Сценарий 1: Отличный месяц

Показатель План Факт Выполнение
Продажи 1 000 000 руб. 1 200 000 руб. 120%
Звонки 200 220 110%
KPI% 116%
Премия 46 400 руб.
Итого ЗП 106 400 руб.

Сценарий 2: Плохой месяц

Показатель План Факт Выполнение
Продажи 1 000 000 руб. 600 000 руб. 60%
Звонки 200 180 90%
KPI% 72%
Премия 28 800 руб.
Итого ЗП 88 800 руб.

Что видит Алексей: В личном кабинете есть виджет «Прогноз
зарплаты». Он показывает текущий KPI% и прогнозируемую премию
в реальном времени.

Кейс №7: «Квартальная премия разработчика»

Персонаж: Мария, Senior Developer

Период Прогресс цели Выплата Причина
Октябрь 30% 0 руб. Не конец квартала
Ноябрь 70% 0 руб. Не конец квартала
Декабрь 100% 100 000 руб. Конец Q4, релиз выпущен
Итого зарплата Марии в декабре: 250 000 (оклад) +
100 000 (квартальная) = 350 000 руб.

Кейс №8: «Годовой бонус для всех»

Уровень База годовой премии KPI компании Выплата
Junior 50 000 руб. 120% 60 000 руб.
Middle 100 000 руб. 120% 120 000 руб.
Senior 200 000 руб. 120% 240 000 руб.
Компания выполнила годовой план прибыли на 120%. Все получают
«13-ю зарплату» в декабре.</em >

Кейс №9: «Смешанный бонус Sales Director»

Персонаж: Иван, директор по продажам. Нужен стабильный
доход для ипотеки + мотивация на результат.

Параметр Значение
База премии 150 000 руб.
Фиксированная часть (40%) 60 000 руб. (гарантировано)
Переменная часть (60%) 90 000 руб. (зависит от KPI)
Сценарий: KPI = 80%
Расчёт 60 000 + 90 000 × 0.8 = 132 000 руб.
Сценарий: KPI = 0% (катастрофа)
Расчёт 60 000 + 90 000 × 0 = 60 000 руб.
Даже при полном провале остаётся минимальная гарантия

Кейс №10: «Депремирование за низкий KPI»

Условие Действие
KPI < 10% Премия обнуляется (депремирование)
Пример Сотрудник выполнил KPI на 5% → Премия = 0
Цель Защита от ситуаций, когда сотрудник формально «работал», но не
принёс результата

4. Модуль 3: Расчёт Зарплаты (Payroll)

Это «финишная прямая» — здесь данные из Табеля и KPI превращаются в
деньги.

4.1. Интеграция с Табелем и KPI

Сущность Назначение Когда создаётся
PayrollPlan Плановые начисления (что мы ожидаем выплатить) В начале месяца автоматически
PayrollActual Фактические начисления (что мы выплатили) После утверждения табеля и KPI

4.1. Главная формула расчёта

Компонент формулы Описание
Часовая_Ставка = Оклад / Плановые_Часы
ЗП_За_Часы = Часовая_Ставка × Фактические_Часы
Gross = ЗП_За_Часы + Премии
НДФЛ = Gross × 13%
Net = Gross — НДФЛ
К выплате = Net — Аванс — Удержания

Пример полного расчёта

Параметр Значение Комментарий
Оклад 200 000 руб.
Плановых часов 176 часов 22 дня × 8 часов
Фактически 160 часов Брал 2 дня за свой счёт
Премия по KPI 50 000 руб.
Аванс 100 000 руб. Выплачен 25 октября
Расчёт:
Часовая ставка 1 136.36 руб/час 200 000 / 176
ЗП за часы 181 818 руб. 1 136.36 × 160
Gross 231 818 руб. 181 818 + 50 000
НДФЛ (13%) 30 136 руб.
Net 201 682 руб.
К выплате 101 682 руб. 201 682 — 100 000

4.2. Аванс и окончательный расчёт

Выплата Дата Формула Зависит от табеля?
Аванс 25-е число Оклад × 50% НЕТ (табель ещё не закрыт)
Окончательный расчёт 10-е число (Оклад / План_Часы) × Факт_Часы — Аванс + Премии ДА

4.4. Налоги и удержания

Налог/Взнос Ставка Кто платит Формула
НДФЛ 13% (прогрессивная ) Удерживается из ЗП сотрудника НДФЛ = Gross × 0.13
Страховые взносы 30.2% Платит работодатель сверх ЗП Взносы = Gross × 0.302
На руки (Net) 87% Получает сотрудник Net = Gross × 0.87
Полная стоимость 130.2% Реальные затраты компании Стоимость = Gross × 1.302

Пример: Оклад 200 000 руб.

Показатель Сумма Комментарий
Оклад (Gross) 200 000 руб. То, что указано в договоре
НДФЛ -26 000 руб. 200 000 × 0.13
На руки (Net) 174 000 руб. То, что получает сотрудник
Страховые взносы +60 400 руб. 200 000 × 0.302 (платит компания)
Полная стоимость 260 400 руб. Реальные затраты компании

Вывод: Когда HR говорит «оклад 200 000», компания тратит
260 400 руб.

Gross ↔ Net калькулятор

Направление Формула Пример
Gross → Net Net = Gross × 0.87 200 000 → 174 000 руб.
Net → Gross Gross = Net / 0.87 200 000 → 229 885 руб.
Net → Полная стоимость Стоимость = (Net / 0.87) × 1.302 200 000 → 299 350 руб.

4.5. Кейсы и примеры

Кейс №11: «Полный цикл расчёта Senior Developer»

Персонаж: Дмитрий, Senior Python Developer

Параметр Значение
Оклад 300 000 руб.
Плановых часов 176 (22 дня × 8 часов)
Отработано 168 часов (брал 1 день за свой счёт)
KPI 100%
Премия 50 000 руб.
Аванс 150 000 руб.
Расчёт системы:
Часовая ставка 1 704.55 руб/час
ЗП за время 286 364 руб. (❌ -13 636 руб. из-за отгула)
Премия +50 000 руб. (✅ KPI 100%)
Gross 336 364 руб.
НДФЛ (13%) -43 727 руб.
Net 292 637 руб.
Аванс -150 000 руб.
К выплате 10 декабря 142 637 руб.

Кейс №12: «Сотрудник вышел 15-го числа»

Параметр Значение
Ситуация Новый дизайнер вышел 15 ноября
Оклад 100 000 руб.
Отработано 88 часов (половина месяца)
Часовая ставка 568.18 руб/час
ЗП 50 000 руб.
НДФЛ -6 500 руб.
На руки 43 500 руб.
Никаких «делений на 30» или «на глаз»

Кейс №13: «Больничный + Отгул в одном месяце»

Тип дня Часы Как оплачивается
Рабочие 136 часов По часовой ставке: 115 909 руб.
Больничный 24 часа (3 дня) Отдельно, ~15 000 руб. (по среднему)
Отгул 16 часов (2 дня) Не оплачивается (вычтено из рабочих)
Итого Gross 130 909 руб.
НДФЛ (13%) -17 018 руб.
На руки (Net) 113 891 руб.

Кейс №14: «Квартальная + Годовая премия в декабре»

Компонент Сумма
Оклад 200 000 руб.
Месячная премия 30 000 руб.
Квартальная премия (Q4) 50 000 руб.
Годовая премия 100 000 руб.
Gross 380 000 руб.
НДФЛ (13%) -49 400 руб.
Net 330 600 руб.
Если годовой доход > 2.4 млн, применяется 15% на сумму свыше</em >

Кейс №15: «Переработки в выходные (x2)»

Параметр Значение
Оклад 180 000 руб.
Плановых часов 176
Отработано (норма) 176 часов
Работа в выходные 16 часов
Коэффициент ×2 (двойная оплата)
Часовая ставка 1 022.73 руб/час
ЗП за норму 180 000 руб.
Переработки 1 022.73 × 16 × 2 = 32 727 руб.
Gross 212 727 руб.

5. Технологический стек и особенности реализации

Стек технологий

Компонент Технология Назначение
Backend
Фреймворк Python 3.11 + FastAPI Современный асинхронный API
База данных PostgreSQL Надёжное хранение данных
ORM SQLAlchemy Строгая типизация, миграции
Валидация Pydantic Валидация на уровне API
Миграции Alembic Версионирование БД
Frontend
UI React 18 + TypeScript Типизированный интерфейс
Сборка Vite Быстрая разработка
Данные TanStack Query Кэширование и синхронизация
Стили Tailwind CSS Утилитарный CSS

Ключевые паттерны

Паттерн Зачем Где применяется
Decimal вместо Float Избежать ошибок округления Все финансовые операции
Atomic Transactions Гарантировать целостность данных Утверждение табеля, расчёт ЗП
Service Layer Изолировать бизнес-логику KPICalculationService, PayrollKPISyncService
Строгая типизация (Enums) Избежать ошибок в статусах DayTypeEnum, TimesheetStatusEnum, BonusTypeEnum
API Versioning Безопасное изменение API /api/v1/timesheets

Оптимизация производительности

Техника Описание Эффект
Индексы БД На все FK, даты, статусы Быстрые запросы
Eager Loading Предзагрузка через joinedload Избежать N+1 запросов
Pagination Все списки с пагинацией Быстрая загрузка больших списков

6. Заключение и результаты

Что мы получили

Метрика До внедрения После внедрения Улучшение
Время расчёта ЗП (50 чел.) 2 дня 15 минут 192× быстрее
Ошибки в начислениях 5-7 в месяц 0 100% точность
Прозрачность для сотрудников Нет 100% (личный кабинет) Полная прозрачность
Точность прогноза ФОТ ±15% ±2% 7.5× точнее
Время на вопросы «Почему так мало?» 5-10 часов в месяц 0 часов 100% экономия

Ключевые преимущества

Преимущество Описание Ценность
Детерминированность Зарплата = функция от входных данных Нет «человеческого фактора»
Прозрачность Каждый сотрудник понимает свою ЗП Доверие и мотивация
Интеграция Три модуля работают как единое целое Автоматическая синхронизация
Масштабируемость 1 000 зарплат = 10 зарплат по времени Рост без затрат
Аудит Полная история изменений Контроль и безопасность

Дальнейшее развитие

Функция Описание Статус
Прогрессивная шкала НДФЛ Автоматический расчёт 13%/15%/18% Уже готово
Интеграция с 1С Автоматическая выгрузка начислений В планах
Мобильное приложение Отметки в табеле через телефон В планах
AI-ассистент Рекомендации по KPI на основе истории Исследование
Сценарное моделирование «Что если повысим всем на 10%?» Уже готово