ТЗ: табель, зарплата и передача выплат в финансы
Редакция от 01.10.2026. Рабочая версия с комментариями — документ Claude Docs; этот файл — её копия в репозитории.
1. Цель и принципы
Табель перестаёт быть месячной отчётностью и становится непрерывной лентой часов. Сотрудник отмечает часы, начальник подтверждает, руководитель в любой день формирует расчёт от нужной даты, и расчёт уходит в финансы задачей на выплату.
Принципы, по которым принимаются все решения ниже:
- Никто не думает о периодах. Сотрудник не «сдаёт месяц». Он отмечает часы, остальное система собирает сама.
- Одно действие на роль. Сотрудник вносит часы, начальник подтверждает, финансы платят. Каждый шаг сам создаёт следующий.
- Учёт времени не блокирует работу. Задачи двигаются всегда. Если часы начислить нельзя, система поясняет это и не выдаёт ошибку.
- Деньги считает система. Ставка и оклад берутся из настроек сотрудника. Руками суммы никто не вводит.
- Любое решение обратимо. Часы можно поправить, табель можно вернуть, в том числе по закрытому проекту.
- Игровые механики поощряют и не наказывают. Серии, прогресс и быстрые подтверждения видны, штрафов и публичных антирейтингов нет.
2. Как устроено сейчас
Сейчас между часами сотрудника и деньгами стоят четыре ручных шага и жёсткая привязка к календарному месяцу. Половина нужного уже есть в бэкенде, но у неё нет интерфейса.
| Что | Как сейчас | Что мешает |
|---|---|---|
| Часы | Сотрудник пишет их через таймер задачи и кнопку «Добавить часы». Изменить или удалить запись нельзя ни ему, ни начальнику | Ошибку правят только корректировкой с согласованием |
| Табель | Календарный месяц одного сотрудника. Сотрудник сам сдаёт его после 1-го числа, начальник утверждает или возвращает | Нельзя рассчитать человека 20-го числа или за неделю. Сотрудник обязан помнить про сдачу |
| Сводный табель | Список всех сотрудников за месяц, у большинства «Черновик, 0 ч» | Начальник не видит, кого пора рассчитать и сколько часов накопилось |
| Ставка и оклад | В базе есть условия оплаты с историей: либо оклад, либо ставка за час. Экрана для них нет | Ставку задать негде, оклад и ставку одновременно указать нельзя |
| Ставка на проекте | У участника команды проекта есть своя ставка за час | Фиксированной суммы за проект нет |
| Ведомость | В бэкенде есть месячная ведомость: начисление, НДФЛ 13 %, выплата платежами. Экрана нет | Ведомость одна на месяц на всех, собирает её бухгалтер вручную через API |
| Финансы | Экран «Платежи» показывает запланированные выплаты и плитку «К оплате», платёж проводится одной кнопкой | Зарплата туда сама не попадает |
| Закрытый проект | Часы принимаются только в датах проекта. После закрытия трудозатраты проекта не пересчитываются | Часы после даты окончания внести нельзя, а внесённые по закрытому проекту не попадают в его затраты |
| Игровые механики | Нет. Есть только подсветка кнопки «Сдать табель» и KPI заполняемости для руководства | Учёт времени воспринимается как отчётность |
От текущей реализации сохраняются три решения. Работа с задачами никогда не блокируется учётом времени. Утверждает начальник по оргструктуре, администратор или проверяющий по матрице прав. Деньги за уже выплаченный период не пересчитываются, разница уходит в следующую выплату.
3. Основной сценарий
У каждой роли одно действие, и каждое действие само ставит работу следующему.
Сотрудник: отмечает часы (таймер или вручную) получает выплату и уведомление
│ ▲
▼ │ выплачено
Начальник: формирует табель с любой даты ──▶ подтверждает часы и передаёт в финансы
▲ │
│ вернуть с причиной ▼
Финансы: └──────────────────────── выплата в очереди («К оплате») ──▶ проводит выплату, табель закрытВозврат из финансов попадает начальнику, а не сотруднику: сотрудник ничего не пересдаёт.
| Роль | Что делает человек | Что система делает сама |
|---|---|---|
| Сотрудник | Отмечает часы таймером задачи или вручную | Собирает часы в ленту, показывает заработок с последней выплаты, напоминает в конце дня |
| Начальник | Формирует табель с нужной даты, при необходимости правит часы, подтверждает | Подставляет даты, ставку и оклад, считает сумму, создаёт выплату в финансах |
| Финансы | Проводят выплату или возвращают табель с причиной | Закрывает табель и часы, уведомляет сотрудника и начальника |
4. Условия оплаты сотрудника
Условия оплаты состоят из независимых частей, которые складываются: оклад, ставка за час, ставка за смену и проектные суммы. Заполняется только нужное. Условия хранятся с историей: новое значение действует с указанной даты, прошлые расчёты не меняются.
| Часть | Что задаётся | Как попадает в табель |
|---|---|---|
| Оклад | Сумма, период (месяц или неделя) и день начисления: число месяца или день недели | Целиком, один раз за период, в табель, в который попал день начисления. Не зависит от числа отработанных дней. Пропущенный период догоняется следующим табелем |
| Ставка за час | ₽/час | Все подтверждённые часы × ставка, поверх оклада |
| Ставка за смену | ₽/смена | Смена — день с подтверждёнными часами. Число смен × ставка, поверх оклада и часов |
| Ставка на проекте | ₽/час в карточке участника команды (уже есть) | Часы этого проекта считаются по проектной ставке вместо личной |
| Сумма за проект | Фиксированная сумма в карточке участника команды (новое поле) | Строка «Гонорар за проект» предлагается в табеле, когда проект сдан или закрыт. Начальник может включить её раньше целиком или частью |
Правила:
- Ставка для часа: сначала ставка участника на проекте, затем личная ставка на дату записи. Нет ни той, ни другой — час в начисление не входит.
- Оклад есть оклад. Он начисляется целиком в день начисления, сколько бы дней ни было отработано. У кого оклада нет, тот получает только часы, смены и проектные суммы.
- Вычет из оклада за отпуск, больничный или отгул появится вместе с учётом отсутствий. До этого начальник добавляет в табель строку «Вычет» с суммой и причиной.
- Удержаний нет. К выплате ровно столько, сколько начислено.
- Ставка фиксируется в строке табеля в момент формирования. Изменение условий после этого влияет только на новые табели.
- Без условий оплаты табель формируется с часами и суммой 0 ₽. Система показывает подсказку «Не заданы условия оплаты» со ссылкой в карточку сотрудника и не блокирует работу.
5. Учёт и правка часов
Час живёт в одном из трёх состояний, и состояние определяет, кто может его менять. Месячной блокировки больше нет: часы за любую дату принимаются всегда и попадают в ближайший табель.
| Состояние часа | Как видит сотрудник | Сотрудник | Начальник и администратор |
|---|---|---|---|
| Не в табеле | «Ждёт табеля» | Меняет и удаляет свои записи | Меняют, удаляют, добавляют за сотрудника |
| В табеле до выплаты | «В табеле от 12.10» | Только читает | Меняют в черновике и возвращённом табеле, сумма пересчитывается сразу |
| Выплачен | «Выплачено 15.10» | Только читает | Запись не меняется. Исправление делается корректирующей записью с плюсом или минусом, она уходит в следующий табель |
Сотрудник
- Часы появляются тремя путями, как сейчас: таймер задачи, «Добавить часы», «Заполнить по задачам».
- Кнопки «Сдать табель» больше нет. Сдавать ничего не нужно.
- Свою запись «Ждёт табеля» можно изменить или удалить прямо в списке.
- Для выплаченных часов остаётся «Корректировка» за день или за период, например за неделю: сотрудник пишет причину, начальник согласует, часы уходят в следующий табель.
- Сам сотрудник не вносит часы за дату вне сроков проекта и по закрытому проекту. Таймер при этом работает, часы не начисляются, приходит пояснение
hours_note.
Начальник и администратор
- Меняют часы, дату, проект, задачу и комментарий любой невыплаченной записи подчинённого, добавляют и удаляют записи.
- Закрытый проект и даты проекта их не ограничивают. Часы по закрытому проекту можно добавить и исправить.
- Правка часов закрытого проекта пересчитывает только его статьи «Трудозатраты». Остальные финансы закрытого проекта остаются замороженными. Иначе выплаченная зарплата разойдётся с затратами проекта.
- Каждая чужая правка пишется в историю записи: кто, когда, было, стало. Сотрудник получает уведомление «Начальник изменил ваши часы за 12.10: 8 ч → 6 ч». Для закрытого проекта в истории стоит пометка «после закрытия».
- Запись можно исключить из табеля с причиной. Она возвращается сотруднику в «Ждёт табеля» с пометкой «Нужно поправить» и текстом причины.
- Свои часы начальник правит как обычный сотрудник. Свой табель формирует только администратор, остальным его формирует вышестоящий.
6. Табель от произвольной даты
Табель теперь документ на выплату: один сотрудник, любой отрезок дат, часы и начисление. Его формирует начальник, а не сдаёт сотрудник.
Формирование
- Начальник нажимает «Сформировать табель» у сотрудника или «Сформировать табели» для нескольких.
- Поле «С даты» заполнено само: день после конца прошлого табеля сотрудника. Если табелей не было, берётся дата первой записи часов. Поле «По дату» по умолчанию сегодня. Обе даты можно изменить.
- Система показывает предпросмотр: часы по проектам, строки начисления, итог к выплате. Ничего ещё не сохранено.
- Начальник при необходимости правит часы или исключает записи и нажимает «Подтвердить и передать в финансы». Это одно действие: часы подтверждены, табель создан, выплата встала в финансы.
- Вторая кнопка «Сохранить черновик» оставляет табель у начальника без передачи.
Состав
- Часы периода: все записи сотрудника с датой в отрезке, которые ещё не входят ни в один табель.
- Часы за прошлые даты: записи раньше «С даты», не попавшие в прошлые табели (внесены задним числом, согласованные корректировки). Они показаны отдельной группой и включены по умолчанию.
- Оклад и смены: оклад целиком, если в период попал день его начисления, и смены по ставке за смену.
- Гонорары за проекты с фиксированной суммой, которые ещё не выплачены.
Периоды табелей одного сотрудника не пересекаются, поэтому оклад и смену нельзя начислить дважды. Каждый час входит ровно в один табель.
Расчёт суммы
начислено = оклады, чей день начисления попал в период
+ Σ (часы × ставка строки)
+ смены × ставка за смену
+ гонорары ± корректирующие записи − вычеты
к выплате = начисленоУдержаний нет. Суммы считаются точным денежным типом money.Money, округление до копеек. Начисление не уходит ниже нуля. В табеле хранится расшифровка каждой строки: проект, часы, ставка, источник ставки, сумма.
Статусы
| Статус | Что значит | Кто переводит дальше |
|---|---|---|
| Черновик | Сформирован, у начальника. Часы можно править | Начальник: передать в финансы или расформировать |
| В финансах | Подтверждён, ждёт выплаты. Часы закрыты | Финансы: выплатить или вернуть. Начальник: отозвать |
| Возвращён | Вернули финансы или отозвал начальник, с причиной. Часы снова можно править | Начальник: передать снова или расформировать |
| Выплачен | Платёж проведён. Табель и часы закрыты навсегда | Никто. Правки идут в следующий табель |
| Расформирован | Отменён. Часы вернулись в «Ждёт табеля» | Никто |
Возврат
- Финансы возвращают табель со статуса «В финансах». Причина обязательна. Запланированная выплата отменяется, начальник получает уведомление с причиной.
- Начальник отзывает табель, пока он не выплачен. Результат тот же: статус «Возвращён», выплата отменена.
- В возвращённом табеле начальник правит часы и даты, сумма пересчитывается, затем он передаёт табель снова.
- Выплаченный табель не возвращается, потому что проведённый платёж не отменяется. Ошибка исправляется корректирующей записью в следующем табеле.
- Каждая смена статуса пишется в историю табеля с автором, временем и причиной.
7. Передача в финансы
Переданный табель сам создаёт запланированную выплату в реестре платежей. Это и есть задача для финансов: она стоит в очереди «К оплате», у неё есть срок, и она закрывается одной кнопкой.
Что происходит при передаче
- Создаётся платёж в статусе «Запланирован»: выплата, получатель сотрудник, сумма «к выплате», назначение «Зарплата: Иванов И. О., 16.09–30.09.2026».
- Дата платежа берётся из поля «Выплатить до» в форме табеля. По умолчанию это три рабочих дня от сегодня. Число дней задаётся в настройках компании.
- Счёт берётся из настройки «Счёт для зарплаты». Финансы могут сменить счёт при проведении.
- Платёж связан с табелем. Из строки платежа открывается табель с часами и расшифровкой суммы.
- Финансовая служба получает уведомление «Новая выплата: Иванов И. О., 18 400 ₽, до 05.10».
Что делают финансы
- Провести. Платёж становится проведённым, табель сам переходит в «Выплачен», сотрудник получает уведомление «Выплата проведена».
- Провести несколько. Финансист отмечает строки и проводит их одним подтверждением с одного счёта.
- Вернуть. Финансист пишет причину, платёж отменяется, табель уходит начальнику в статусе «Возвращён». Отменить зарплатный платёж молча нельзя: отмена всегда идёт через возврат с причиной.
- Задача на выплату. С этапа 5 передача табеля ещё и создаёт финансовой службе задачу без проекта «Выплатить зарплату» со ссылкой на платёж. Проведение платежа закрывает задачу.
- Сформировать самим. Финансовый директор может сформировать табели на любых сотрудников. Это сценарий для окладников: оклад подтягивается из настроек, часы для расчёта не нужны.
Связь с затратами проектов
Трудозатраты проекта считаются по-прежнему по каждой записи часов, сразу при её изменении. Табель на них не влияет и второй раз затраты не создаёт. Новое только одно: фиксированный гонорар за проект попадает в статью «Трудозатраты» проекта в момент включения в табель.
Старая месячная ведомость
Месячная ведомость (payroll_runs) больше не создаётся. Её расчётная логика (условия оплаты, удержание, создание платежа сотруднику) переезжает в расчёт табеля. Существующие ведомости остаются в базе только для чтения.
8. Геймификация
Игровые механики встраиваются в те места, где человек уже работает, и показывают ему три вещи: сколько сделано сегодня, сколько заработано и что ждёт его решения. Отдельного «игрового» раздела нет.
Правила для всех механик
- Только поощрение. Штрафов, красных счётчиков пропусков и публичных списков отстающих нет.
- Ничего не блокирует работу. Механика подсказывает и радует, но не требует.
- Каждый видит только свой прогресс. Начальник видит сводку по команде без рейтинга людей.
- В профиле, в разделе «Оформление», есть переключатель «Игровые элементы». Выключенный переключатель убирает серии, достижения и анимации, счётчики часов и денег остаются.
- Анимации короткие и уважают системную настройку «меньше движения».
Механики первой очереди: часы и выплаты
| Механика | Кому | Где | Правило |
|---|---|---|---|
| Кольцо дня | Сотрудник | Шапка, рядом с таймером | Заполняется часами за сегодня до дневной нормы 8 ч. При заполнении короткая анимация и подпись «День закрыт» |
| Счётчик «С последней выплаты» | Сотрудник | Главная «Мой день», экран «Мои часы» | Часы и сумма, накопленные с прошлого табеля: «32 ч · 16 000 ₽». Растёт после каждой записи |
| Серия дней | Сотрудник | «Мой день», «Мои часы» | Рабочие дни подряд с отмеченными часами. Выходные серию не рвут. Пропущенный день можно заполнить в течение двух рабочих дней без потери серии |
| Быстрая отметка | Сотрудник | Уведомление в 18:00, если за день 0 ч | Список сегодняшних задач с кнопками «+1 ч», «+2 ч», «+4 ч», «как вчера». Одно нажатие создаёт запись |
| Выплата проведена | Сотрудник | Уведомление и экран «Мои часы» | «Выплачено 18 400 ₽ за 16–30.09» с короткой анимацией. Счётчик обнуляется |
| Очередь «Ждут табеля» | Начальник | Главная, экран «Команда» | «5 сотрудников · 124 ч» и кнопка «Сформировать табели». Пустая очередь показывает «Все рассчитаны» |
| Напоминание начальнику | Начальник | Уведомление в пятницу | Приходит, если у подчинённых есть часы без табеля старше порога из настроек компании, по умолчанию 14 дней. Ведёт сразу в форму формирования |
| Очередь «Зарплата к выплате» | Финансы | Главная, «Платежи» | Счётчик и сумма. Пустая очередь показывает «Всё выплачено» |
| Скорость цепочки | Начальник, финансы | Экран «Команда», «Платежи» | Среднее число дней от часа до выплаты за месяц. Показатель собственный, без сравнения с коллегами |
Вторая очередь: вся система
Те же приёмы распространяются на остальные разделы через общий модуль «Прогресс». Модуль слушает события системы и ведёт серии и достижения, разделы сами ничего не считают.
| Событие | Что даёт |
|---|---|
| Часы отмечены в день работы | Серия дней |
| Задача завершена в срок | Серия задач в срок, достижение «10 задач без просрочки» |
| Табель сформирован в течение 7 дней от последнего часа | Достижение начальника «Расчёт без задержек» |
| Выплата проведена до срока | Достижение финансов «Месяц без просроченных выплат» |
| Месяц без корректировок выплаченных часов | Достижение сотрудника «Точный учёт» |
Достижения показываются в профиле в блоке «Прогресс» и приходят уведомлением в момент получения. В стартовом наборе не больше восьми достижений. Очков, уровней и магазина наград в этом ТЗ нет.
9. Экраны фронтенда
Новых разделов в меню нет: меняется экран «Табель», добавляется вкладка в карточке сотрудника и фильтр в «Платежах». Всё собирается из существующих компонентов дизайн-системы (AppPage, AppStatTiles, AppDataTable, AppSidePanel, AppDialog, AppStatusChip).
| Экран | Сейчас | Станет |
|---|---|---|
| «Табель», вид сотрудника | «Мой табель» за выбранный месяц, кнопка «Сдать табель», плитки «Часов / Записей / Дней с часами» | «Мои часы»: лента без выбора месяца, плитки «Сегодня / Неделя / С последней выплаты / Серия», блок «Мои табели» |
| «Табель», вид начальника | «Сводный табель»: все сотрудники за месяц, в основном «Черновик, 0 ч» | «Команда»: только те, у кого есть часы без табеля или табель в работе, кнопка «Сформировать табели» |
| Диалог «Добавить часы» | Задача обязательна, дата в пределах выбранного месяца | Проект обязателен, задача по желанию, любая дата, быстрые кнопки часов. Тот же диалог открывается для правки записи |
| Карточка табеля | Боковая панель: записи и история, кнопки «Утвердить / Вернуть» | Боковая панель: часы с правкой в строке, начисление, история, кнопки по статусу |
| Карточка сотрудника («Сотрудники») | Вкладки «Профиль», «Роли и права», «Проекты», «NDA» | Новая вкладка «Оплата» |
| Участник команды проекта | Поле «Ставка за час» | Плюс поле «Сумма за проект» |
| «Платежи» | Фильтры по направлению, счёту, статусу, контрагенту | Плюс быстрый фильтр «Зарплата», ссылка на табель в строке, выбор строк и «Провести выбранные», действие «Вернуть табель» |
| Главная | У сотрудника плитка «Учтено за месяц, табель: статус» | Сотрудник: «С последней выплаты» и серия. Начальник: виджет «Ждут табеля». Финансы: виджет «Зарплата к выплате» |
| Шапка | Таймер текущей задачи | Плюс кольцо дня вокруг значка таймера |
«Мои часы»
- Главное действие страницы: «Добавить часы». Рядом остаётся «Заполнить по задачам».
- Полоса недели: семь ячеек с часами за день. Нажатие на ячейку открывает диалог с этой датой. Стрелки листают недели, переключатель «Неделя / Месяц» показывает нынешнюю сетку месяца.
- Список записей сгруппирован по дням. У каждой записи статус: «Ждёт табеля», «В табеле», «Выплачено», «Нужно поправить». Записи «Ждёт табеля» правятся и удаляются из меню строки.
- Блок «Мои табели»: период, часы, сумма к выплате, статус, дата выплаты. Строка открывает карточку табеля только для чтения.
- Корректировки остаются карточкой на этой странице, кнопка «Подать корректировку» переезжает в меню выплаченной записи.
«Команда»
- Плитки: «Ждут табеля» (сотрудники и часы), «В финансах», «Возвращено», «Выплачено за месяц». Плитка «Возвращено» подсвечена, если не пустая.
- Таблица: сотрудник, часы без табеля, с какой даты, последний табель и его статус, кнопка «Сформировать». Сотрудники без часов и без табелей в работе скрыты, переключатель «Показать всех» их возвращает.
- Кнопка «Сформировать табели» подсвечена кольцом-сигналом (
attention), когда есть часы без табеля старше порога напоминания. - Фильтр по статусу табеля и поиск по сотруднику, состояние фильтров в адресной строке.
Диалог «Сформировать табели»
- Поля: «С даты» (по умолчанию «с прошлого табеля», своя для каждого сотрудника), «По дату», «Выплатить до».
- Список сотрудников с галочками: часы, сумма к выплате (если есть право видеть суммы), предупреждения «Не заданы условия оплаты», «Есть часы за прошлые даты».
- Итог внизу: число табелей, часы, сумма.
- Кнопки: «Подтвердить и передать в финансы» (основная), «Сохранить черновики».
Карточка табеля
- Шапка: сотрудник, период, статус. У возвращённого табеля сверху причина возврата и автор.
- Блок «Часы»: записи по проектам, итог по каждому проекту. Начальник меняет часы прямо в строке, добавляет запись, исключает запись с причиной.
- Блок «Начисление»: оклад, часы по ставкам, смены, гонорары, вычеты, к выплате. Блок виден самому сотруднику и тем, у кого есть доступ к заработку.
- Блок «История»: смены статуса и правки часов.
- Кнопки внизу зависят от статуса и роли: «Подтвердить и передать в финансы», «Отозвать», «Расформировать», «Провести выплату», «Вернуть».
Вкладка «Оплата» в карточке сотрудника
- Текущие условия: оклад, его период и день начисления, ставка за час, ставка за смену.
- Кнопка «Изменить условия» открывает форму с полем «Действует с». Старая запись закрывается днём раньше.
- История условий таблицей, новые сверху.
- Вкладка видна только при доступе к заработку (владелец, операционный и финансовый директор). Свои условия сотрудник видит в профиле только для чтения.
Статусы табеля и часов добавляются в реестр src/data/statuses.ts, правила бэкенда зеркалятся в src/data/businessRules.ts. Ошибки действий показываются тостами, в формах подсвечиваются поля. Каждый экран проверяется на ширине 1280 и 375.
10. Данные, API и права
Реализация развивает существующие модули timesheets, timeentries, payroll и payments, новый модуль нужен только для «Прогресса». Миграции начинаются с номера 0161.
Схема
| Таблица | Изменение |
|---|---|
compensation_profiles | Новые поля: salary_amount, salary_period (month / week), salary_day (число месяца 1–31 или день недели 1–7), hourly_rate, shift_rate, created_by. Старые kind и base_amount переносятся в новые поля и дальше заполняются только для старой ведомости |
project_team_members | Новое поле fixed_fee: сумма за проект |
timesheet_periods | Становится табелем произвольного периода: period_end, formed_by, pay_due, accrued, sent_at, paid_at (связь с выплатой — payments.timesheet_id). Статусы: draft, sent, returned, paid, cancelled. Уникальность «сотрудник + месяц» заменяется запретом пересечения периодов неотменённых табелей одного сотрудника |
timesheet_lines (новая) | Строки начисления табеля: вид (salary, hours, shift, fee, adjustment, deduction), проект, часы или смены, ставка, источник ставки, сумма, причина вычета. Это снимок на момент расчёта |
time_entries | Новые поля: timesheet_id (в каком табеле час), review_note (причина исключения), updated_by. Индексы по timesheet_id и по (user_id, entry_date) для часов без табеля |
time_entry_events (новая) | История правок часов: кто, действие, было, стало, признак «проект закрыт». История переживает удаление записи |
payments | Новое поле timesheet_id с индексом |
payment_accounts | Новое поле is_payroll_default: счёт для зарплаты, не больше одного |
payroll_settings (новая, одна строка) | Срок выплаты по умолчанию (3 рабочих дня) и порог напоминания начальнику (14 дней). Правит администратор |
progress_streaks, progress_achievements (новые) | Серии и достижения сотрудника |
Перенос существующих месячных табелей: утверждённый месяц с выплаченной ведомостью становится табелем «Выплачен», утверждённый без выплаты становится «Черновиком» у начальника. Черновики, сданные и возвращённые месяцы удаляются, их часы остаются и получают состояние «Ждёт табеля». Каждая миграция имеет обратную половину.
API
| Метод и путь | Назначение |
|---|---|
PATCH /time-entries/:id, DELETE /time-entries/:id | Правка и удаление записи часов. Свои без табеля, чужие невыплаченные по правам начальника |
GET /time-entries/:id/history | История правок записи |
GET /timesheets/my/overview | Свои часы лентой, сводка «сегодня / неделя / с последней выплаты», свои табели |
GET /timesheets/team | Сотрудники в охвате: часы без табеля, дата первого такого часа, последний табель. Сводка для плиток |
POST /timesheets/preview | Расчёт без сохранения: сотрудники, «с даты», «по дату» |
POST /timesheets | Сформировать табели: сотрудники, даты, «выплатить до», исключённые записи, признак «сразу передать» |
GET /timesheets, GET /timesheets/:id | Список и карточка табеля со строками, часами и историей |
PATCH /timesheets/:id | Изменить даты, добавить или убрать вычет, пересчёт. Только черновик и возвращённый |
POST /timesheets/:id/send, /recall, /return, /cancel | Переходы статуса. recall и return требуют причину |
POST /timesheets/:id/entries/:entry_id/exclude | Исключить запись из табеля с причиной |
GET /compensation-profiles, POST /compensation-profiles | Уже есть. Расширяются новыми полями, новая запись закрывает предыдущую |
GET /compensation-profiles/my | Свои условия оплаты для профиля |
PATCH /payments/:id/status | Уже есть. Принимает счёт при проведении. Проведение зарплатного платежа закрывает табель, отмена такого платежа напрямую запрещена |
POST /payments/complete | Провести несколько платежей одним запросом |
GET /progress/me | Кольцо дня, серия, достижения |
GET /payroll/settings, PUT /payroll/settings | Срок выплаты по умолчанию и порог напоминания начальнику |
Удаляются POST /timesheets/my/submit и POST /timesheets/:id/review. Маршруты /payroll/runs* остаются только на чтение. Списки отдаются каноническим конвертом transport.RespondList, суммы типом money.Money, ошибки через реестр текстов. Между модулями связь идёт через интерфейсы сервисов, как сейчас в internal/app/payroll_adapters.go.
Права
| Действие | Кто может |
|---|---|
| Вносить и править свои часы без табеля | Каждый |
| Править чужие часы, в том числе по закрытому проекту | Администратор. Начальник по оргструктуре для подчинённых. Запись others_timesheets в своём охвате |
| Формировать, передавать, отзывать, расформировывать табель | Те же, плюс запись earnings_margin для всех сотрудников |
| Формировать свой табель | Только администратор |
| Видеть суммы в табеле | Сам сотрудник в своём табеле. Чтение earnings_margin. Остальные видят только часы |
| Менять условия оплаты | Запись earnings_margin |
| Проводить выплату, возвращать табель из финансов | Финансовая служба: те, кто сейчас проводит платежи |
Интерфейс получает признаки из /org/me, как сейчас: timesheets_team, timesheets_form (вместо timesheets_approve), timesheets_self_form, timesheets_amounts, timesheets_pay.
Уведомления
| Событие | Кому |
|---|---|
| Начальник изменил или исключил запись часов | Сотрудник |
| Табель передан в финансы | Сотрудник, финансовая служба |
| Табель возвращён финансами | Тот, кто его сформировал |
| Выплата проведена | Сотрудник, тот, кто сформировал табель |
| Выплата просрочена | Финансовая служба |
| Есть часы без табеля старше порога (пятница) | Начальник |
| За день 0 часов (18:00, рабочий день) | Сотрудник, если не отключил |
11. Этапы и приёмка
Работа делится на пять этапов, каждый выкатывается отдельно и полезен сам по себе. Основной сценарий «часы, табель, выплата» замыкается после третьего этапа.
| Этап | Что входит | Результат для пользователя |
|---|---|---|
| 1. Условия оплаты и правка часов | Новые поля условий оплаты (оклад с днём начисления, ставки за час и за смену), вкладка «Оплата», сумма за проект у участника команды. Правка и удаление часов, правка начальником по закрытому проекту, история правок | Ставка и оклад задаются в интерфейсе. Ошибка в часах исправляется без корректировки |
| 2. Табель от даты | Новая модель табеля, перенос месячных табелей, расчёт, статусы, возврат. Экраны «Мои часы» и «Команда», диалог формирования, карточка табеля. Корректировки за день или период. Сдача месяца сотрудником убирается | Начальник формирует табель за любой период и видит сумму |
| 3. Финансы | Запланированная выплата из табеля, счёт для зарплаты, настройки срока выплаты и порога напоминания, проведение закрывает табель, возврат из финансов, массовое проведение. Фильтр «Зарплата» в «Платежах», виджеты на главной, уведомления | Цепочка замкнута: подтверждённый табель сам встаёт в очередь финансов |
| 4. Геймификация | Первая очередь: кольцо дня, счётчик «С последней выплаты», серия, быстрая отметка, напоминания, пустые очереди. Затем модуль «Прогресс» и достижения по задачам и выплатам | Учёт времени перестаёт быть отчётностью |
| 5. Задачи без проекта | Задачи и часы вне проектов (внутренняя работа отделов). Финансовой службе при передаче табеля создаётся задача «Выплатить зарплату», проведение платежа её закрывает | Внутренняя работа учитывается и оплачивается так же, как проектная |
Приёмочный сценарий
Сценарий проходится через интерфейс целиком, после каждого шага сверяется база и перезагружается страница. Он же становится e2e-тестом фронтенда.
- [ ] Финансовый директор задаёт инженеру ставку 500 ₽/час, ставку 2 000 ₽ за смену и оклад 60 000 ₽/месяц с начислением 15-го числа во вкладке «Оплата».
- [ ] Инженер вносит часы таймером и вручную, правит свою запись, счётчик «С последней выплаты» меняется.
- [ ] Начальник видит инженера в «Ждут табеля», формирует табель с 10-го по 20-е число, меняет одну запись, исключает другую с причиной.
- [ ] В период попало 15-е число, поэтому сумма табеля равна окладу целиком плюс часы × ставка плюс смены × ставка за смену, до копейки. Следующий табель того же месяца оклада уже не содержит.
- [ ] После «Подтвердить и передать в финансы» в «Платежах» появляется запланированная выплата на ту же сумму, финансист получает уведомление.
- [ ] Финансист возвращает табель с причиной: платёж отменён, начальник видит причину, правит часы, передаёт снова.
- [ ] Финансист проводит выплату: табель «Выплачен», часы закрыты, инженер получает уведомление, счётчик обнулён.
- [ ] Исключённая запись и часы, внесённые задним числом, предлагаются в следующем табеле группой «Часы за прошлые даты».
- [ ] Начальник добавляет часы по закрытому проекту: запись создана, трудозатраты проекта пересчитаны, в истории пометка «после закрытия». Инженеру то же действие недоступно.
- [ ] Два табеля одного сотрудника с пересекающимися датами создать нельзя. Один час не попадает в два табеля.
- [ ] Начальник без доступа к заработку видит в табеле подчинённого часы и не видит сумм.
- [ ] Старт, пауза, завершение и перетаскивание задачи не дают ошибок ни при каком состоянии табелей.
Определение готовности каждого этапа
- Тесты сервисов и репозиториев,
go test ./...и проверка контрактовgo test ./internal/contractcheck/...проходят. - Контракты перегенерированы, обновлены
docs/concepts/timesheets.md,docs/concepts/payroll.md,docs/concepts/permissions-matrix.md. - Миграции проверены на локальной базе в обе стороны.
- Фронтенд проходит
pnpm guard, проверку типов и e2e.
12. Решения по открытым вопросам
Все вопросы первой редакции закрыты 01.10.2026. Решения уже внесены в разделы выше.
| Вопрос | Решение |
|---|---|
| Какие часы оплачиваются поверх оклада | Все подтверждённые часы. Оклад начисляется целиком в свой день начисления и есть не у всех |
| Как считать оклад за неполный период | Не пропорционально: оклад есть оклад. Вычет за отпуск, больничный и отгул появится с учётом отсутствий, до него строка «Вычет» вручную |
| Удержание 13 % | Не удерживать. К выплате равно начисленному |
| Видит ли начальник суммы подчинённых | Нет, только часы. Суммы видят владелец, операционный и финансовый директор |
| Видит ли сотрудник свой заработок | Да. Счётчик «С последней выплаты» показывает и часы, и рубли |
| Задачи для финансов | Задачи без проекта нужны в любом случае: работа идёт не только по проектам. Это этап 5, после него передача табеля создаёт задачу «Выплатить зарплату» |
| Ставка за смену | Нужна. Смена — день с подтверждёнными часами, ставка плюсуется к окладу и часам |
| Корректировки от 29.09 | Удалить: данные тестовые. Сам механизм остаётся для выплаченных часов и умеет добавить часы за день или за период |
| Срок выплаты и порог напоминания | Настраиваются в настройках компании, по умолчанию 3 рабочих дня и 14 дней |
Вне этого ТЗ: учёт отпусков и больничных, авансы и займы сотрудникам, выгрузка в банк и бухгалтерскую программу, очки и магазин наград.