Dev Specs

Epic E09 — HR & Attendance [desktop]

Назначение эпика: HR-контур back-office: реестр сотрудников, фиксация и агрегация посещаемости (день/месяц/год), рабочие расписания и смены, выходные/праздники, управление отпусками с проверкой баланса. Участвует в use-cases: UC-8 (check-in/out → агрегация D/M/Y; Leave Request → проверка баланса → approve → списание). Сущности (owns/touches): owns — Employee, Attendance (daily record), Schedule (weekly per role), Shift (per-day assignment), LeaveRequest, DaysOff/PublicHoliday. touches — check-in/out события приходят из mobile (E04/E11 Profile), Department/Role из общей справочной модели. Экраны: S34 (Employees), S03 (Attendance Daily), S14 (Attendance Monthly), S19 (Attendance Yearly), S32 (Schedules), S38 (Shifts), S42 (Days Off / Public Holidays), S22 (Leave Request + Requests list). Открытые findings: F-checkin-history-tasks-per-employee (нужна ли история чек-инов и разрез «задачи на сотрудника» в HR/Schedule); F-placeholder-copy (лейблы-заглушки «John Wick», «Operations», «no»).

Общий каркас HR-модуля. Все десктоп-экраны эпика делят один layout: левое меню HR-модуля + контентная область (header-фильтр + data-table). Левое меню (дословно из сайдбаров S03/S14/S19/S32/S38/S42): Employees · Attendance Daily · Attendance Monthly · Attendance Yearly · Schedules · Shifts · Leave Management · Requests · Public Holidays. На каждом экране верх — input_text (поиск/строка) + input_dropdown (фильтр) + input_button (действия). Дальше описывается только специфика экрана.

Статус реализации (2026-06-22): E09 крупный → режется на ~4 WP.

  • WP-1 DONE (ветка feat/e09-hr-wp1, PR #26): HR-шелл (вложенный layout hr/layout.tsx + HrNav подменю 9 пунктов: 2 активны, 7 disabled «coming soon») + S34 Employees (/hr/employees, 7 колонок, search+Department, StatusChip Active/Inactive, inert Add 🟡) + S03 Attendance Daily (/hr/attendance/daily, 17 колонок горизонт-скролл, производный Attendance Status Present/Late/ Absent/Day Off/On Leave/Holiday — приоритет Holiday>Day Off>On Leave>Absent>Late>Present, цветные chip
    • новый Badge warning/amber). Owns Employee/AttendanceRecord/AttendanceDailyRow. pure-utils computeAttendanceStatus/filterEmployees/toAttendanceDailyRow/filterAttendanceRows. Read-only. PDD blind: pre-review 3 CRIT+5 IMP resolved-in-plan → validation 791/791 первый прогон → post-review clean (0/0, 2 NIT fix-now) → verify-feature SHIP 8/8 (EN/ID). План: docs/superpowers/plans/2026-06-22-e09-hr-wp1.md.
  • WP-2 DONE (ветка feat/e09-hr-wp2): S14 Attendance Monthly (/hr/attendance/monthly, 11 колонок, Balance = quota − taken, overdrawn → red Badge, Period-фильтр) + S19 Attendance Yearly (/hr/attendance/yearly, 10 колонок, Working Days/Public Holiday/Annual Leave/Leave, Year-фильтр) + S42 Public Holidays (/hr/public-holidays, 5 колонок, Year-фильтр + "all", inert Add/edit/delete 🟡). HrNav: AttendanceMonthly/AttendanceYearly/PublicHolidays → enabled (теперь 5 активных, 4 disabled). Owns MonthlyAttendanceRecord/YearlyAttendanceRecord/PublicHoliday + LeaveQuota. pure-utils toMonthlyAttendanceRow(Balance)/filterMonthlyRows/toYearlyAttendanceRow/filterYearlyRows/filterPublicHolidays. Mocked pre-aggregated summary (Q-18). Read-only. PDD blind: pre-review 3 CRIT+3 IMP resolved-in-plan → validation 1036/1036 первый прогон (+168) → post-review clean (0/0, 1 NIT) → verify-feature (DEV). Open 🟡: Q-17 (квоты/Balance), Q-18 (источник агрегата/таксономия Leave), Q-19 (Days Off count-vs-dates). План: docs/superpowers/plans/2026-06-22-e09-hr-wp2.md.
  • WP-3 DONE (ветка feat/e09-hr-wp3, PR #29, SHA 8b2de738): S32 Schedules (/hr/schedules, 11 колонок ID/Name/Role/Monday…Sunday/Actions, день-ячейка интервал/«Day off» via formatScheduleDay, Role-фильтр, structural ScheduleDay) + S38 Shifts (/hr/shifts, 7 колонок, Day+Assignment фильтры) + pure-util resolveExpectedTimes (приоритет Holiday/DayOff>Shift>Schedule, 5 веток, tested, НЕ wired в S03 — backend-эталон, Q-22). Общий inert RowActions (Edit/Delete). HrNav: Schedules/Shifts → enabled (7 активных, 2 disabled). Owns Schedule/Shift + Row/Filters. Read-only (всё inert 🟡). PDD blind: pre-review 2 CRIT+2 IMP resolved-in-plan → validation 1221/1221 первый прогон (+185) → post-review clean (0/0, 1 NIT fix + 1 wontfix) → verify-feature SHIP 16/16 DEV + 23/23 PROD (EN/ID). Open 🟡: Q-20/Q-21/Q-22. План: docs/superpowers/plans/2026-06-22-e09-hr-wp3.md.
  • WP-4 DONE (ветка feat/e09-hr-wp4, PR #30, SHA fb2a2ff9) — ЗАВЕРШАЕТ E09 desktop (8/8): S22 Leave Request (/hr/leave, 6 колонок Request/Date/Type/Employee/Role/Status[Badge], type fast-filter чипы All/Annual/Sick/Holiday/Other, row-click → drawer [From/To/Days/Current Balance/Comment/ Attachments + inert Approve/Reject], reuse core/ui/drawer+useUiStore паттерн E08). pure-utils computeLeaveDays(inclusive, DST-safe)/computeLeaveBalance(Annual/Holiday=quota−taken, Sick/Other→null «—»)/toLeaveRequestRow/filterLeaveRequests/leaveStatusVariant. HrNav: Leave Management → enabled (8 активных, 1 disabled). Owns LeaveRequest/LeaveRequestRow/LeaveType/LeaveStatus. Read-only (всё inert 🟡). PDD blind: pre-review 0 CRIT+3 IMP+2 NIT resolved-in-plan → validation 1328/1328 (+107, 1 механический дедуп импортов) → post-review clean (0/0, 2 NIT) → verify-feature SHIP 22/22 DEV + 23/23 PROD (EN/ID). Open 🟡: Q-23 (attendance-chip dropped), Q-24 (Sick/Other balance null). План: docs/superpowers/plans/2026-06-22-e09-hr-wp4.md. 🎉 ЭПИК E09 desktop ЗАВЕРШЁН.

S34 — Employees [desktop]

  • Назначение: реестр сотрудников — единый справочник людей HR-модуля.
  • Источник (Miro): «Copy of … Templates» id 3458764671657205745 (2× = точные дубли).
  • Layout: HR-меню слева · header (search-input + dropdown-фильтр + 3 кнопки) · data-table со строками-сотрудниками.
  • Данные на экране: колонки — ID, Name, Department, Role, Lark ID, Employee Status, User Type. Данные-заглушки: John Wick, Operations/Operations (department/role), статусы повторяются.
  • Контролы и действия:
    • search input_text → фильтр по Name/ID (filter).
    • input_dropdown → фильтр по Department (dropdown).
    • input_button → предположительно + Add Employee (create), export/bulk-действие 🟡, и переход в строку → карточка сотрудника 🟡.
    • строка таблицы → открыть карточку сотрудника (read/edit) 🟡 [не было додумано] — карточки-экрана в прототипе нет, но Employees — корень для остальных HR-экранов; минимально нужен переход для редактирования полей.
  • Состояния/вкладки: table (default), filtered, empty (нет сотрудников), loading.
  • Связи (data-flow): источник идентичности для всех HR-экранов (Attendance/Schedule/Shift/Leave ссылаются на Employee по ID). Lark ID — связка с внешней Lark (мессенджер/SSO). Пишет: создание/правку профиля сотрудника.
  • Мутации: create Employee; update полей (Department, Role, Lark ID, Employee Status, User Type).
  • Права: Operations/Coordinator — read/edit. Accounting — read. Field staff — нет доступа (desktop HR).
  • 🟡 [не было додумано]: переход строка→карточка и кнопка + Add — в каталоге видны только лейблы 3 кнопок без подписей; реестр без create/edit бессмыслен, поэтому минимально достроено.
  • Edge cases: пустой Lark ID (сотрудник без интеграции); длинное Name; неактивный Employee Status (показывать приглушённо); нет прав → меню HR скрыто.

S03 — Attendance Daily [desktop]

  • Назначение: посуточный журнал посещаемости — факт прихода/ухода против ожидаемого, плюс контекст (leave/holiday/day-off).
  • Источник (Miro): «Copy of … Templates» id 3458764671658286045 (2× = дубли).
  • Layout: HR-меню · header (search + date/department dropdown + кнопки) · широкая data-table (одна строка = сотрудник × день).
  • Данные на экране: ID, Name, Department, Role, Lark ID, Employee Status, Attendance Status, Day Off, Check In, Check Out, Exp Check In, Exp Check Out, Leave, CI Location, CO Location, Holiday, Annual Leave. Значения: время 09:00/19:00, --:-- (нет отметки), флаги no.
  • Контролы и действия:
    • search input_text → по Name/ID (filter).
    • input_dropdown → выбор даты/департамента (dropdown) 🟡 точное назначение dropdown не подписано.
    • input_button → навигация по дню (prev/next 🟡), export, ручная корректировка отметки 🟡.
  • Состояния/вкладки: table, filtered (по дню/department), empty (нет смен в этот день), строки-статусы: present / late (Check In > Exp Check In) / absent (--:--) / day-off / on-leave / holiday.
  • Связи (data-flow): Check In/Out + CI/CO Location приходят из mobile check-in/out (E04/E11 Profile, UC-8). Exp Check In/Out берутся из Schedule (S32) или Shift (S38). Day Off/Holiday — из S32/S42. Leave/Annual Leave — из одобренного LeaveRequest (S22). Является источником для агрегатов S14 (Monthly) и S19 (Yearly).
  • Мутации: обычно read-only витрина (агрегатор событий); опционально ручная правка отметки координатором (update Attendance) 🟡.
  • Права: Operations/Coordinator — read (+ ручная правка). Accounting — read. Сотрудник свои отметки видит в mobile Profile (E11).
  • 🟡 [не было додумано]: late/absent статусы как производные от сравнения Check In с Exp Check In — в прототипе только колонки, правило вычисления не подписано; нужно для смысла «Attendance Status».
  • Edge cases: --:-- (нет check-out — смена не закрыта / забыл отметиться); check-in без геолокации (CI Location пустой); день, попавший и на holiday, и на day-off (приоритет отображения); сотрудник на leave (отметки не ожидаются).

S14 — Attendance Monthly [desktop]

  • Назначение: месячная сводка отпусков по сотрудникам — взято и остаток баланса.
  • Источник (Miro): id 3458764673083859834 (2× = дубли). В сайдбаре пункт — Leave Management (под этим разделом живёт месячная сводка).
  • Layout: HR-меню · header (search + dropdown месяц/год + 3 кнопки) · data-table.
  • Данные на экране: ID, Name, Department, Role, Lark ID, Employee Status, Annual Leave Taken, Annual Leave Balance, Public Holiday Taken, Public Holiday Balance, Leave. Значения — счётчики (1).
  • Контролы и действия:
    • search input_text → по сотруднику (filter).
    • input_dropdown → выбор месяца/года (dropdown).
    • input_button → export, period-навигация 🟡.
  • Состояния/вкладки: table, filtered (по периоду), empty.
  • Связи (data-flow): агрегирует S03 (Daily) записи Leave/Annual Leave/Holiday за месяц → *_Taken; *_Balance = квота − taken (с учётом списаний по одобренным LeaveRequest, S22). Read-down от Daily.
  • Мутации: read-only (агрегат).
  • Права: Operations/Coordinator/Accounting — read.
  • 🟡 [не было додумано]: формула Balance = annual_quota − Taken — квота сотрудника в прототипе не показана; нужна для смысла «Balance». Связать с S22 «Current Balance».
  • Edge cases: отрицательный баланс (взято сверх квоты — overdrawn, подсветить); сотрудник нанят в середине месяца (пропорция квоты) 🟡; смешение Annual vs Public Holiday в одной строке.

S19 — Attendance Yearly [desktop]

  • Назначение: годовая сводка по сотруднику — отработанные дни и использованные отпуска/праздники за год.
  • Источник (Miro): id 3458764671768989422 (4× = дубли — самый частый дубль HR-набора).
  • Layout: HR-меню · header (search + dropdown год + 3 кнопки) · data-table.
  • Данные на экране: ID, Name, Department, Role, Lark ID, Employee Status, Working Days, Public Holiday, Annual Leave, Leave. Значения — счётчики (1).
  • Контролы и действия:
    • search input_text (filter).
    • input_dropdown → выбор года (dropdown).
    • input_button → export, year-навигация 🟡.
  • Состояния/вкладки: table, filtered (год), empty.
  • Связи (data-flow): агрегирует S03 (Daily) за год: Working Days = дни с present-отметкой; Public Holiday/Annual Leave/Leave — суммы соответствующих дней. Roll-up над S14 (Monthly).
  • Мутации: read-only (агрегат).
  • Права: Operations/Coordinator/Accounting — read.
  • 🟡 [не было додумано]: разделение Annual Leave vs общий Leave (последний — все типы из S22: Sick/Holiday/Other) — в прототипе обе колонки рядом без определения; вытекает из типов LeaveRequest.
  • Edge cases: неполный год работы; год без данных (новый сотрудник); расхождение Working Days с числом рабочих дней расписания (пропуски).

S32 — Schedules [desktop]

  • Назначение: недельная сетка рабочего времени per role (шаблон рабочей недели).
  • Источник (Miro): id 3458764674667384346 (2× = дубли).
  • Layout: HR-меню · header (search + dropdown + кнопка) · data-table: строка = расписание (привязано к Role/группе), колонки = дни недели.
  • Данные на экране: ID, Name, колонки MondaySunday со значениями 09:00 - 18:00 или day off; per-строка edit / delete. Привязки: Office, Handyman (роли/группы).
  • Контролы и действия:
    • search input_text (filter).
    • input_dropdown → фильтр по роли (dropdown).
    • input_button+ Add Schedule (create).
    • edit (button-в-строке) → редактировать недельную сетку (update).
    • delete (button-в-строке) → удалить расписание (delete).
  • Состояния/вкладки: table, filtered, empty (нет расписаний).
  • Связи (data-flow): задаёт Exp Check In/Exp Check Out и Day Off для S03 (Daily). Конкретные смены S38 (Shifts) наследуют/переопределяют расписание.
  • Мутации: create / update / delete Schedule; задание per-day интервала или day off.
  • Права: Operations/Coordinator — full. Accounting — read.
  • 🟡 [не было додумано]: уровень привязки расписания (per role vs per employee) — в данных видны роли (Office/Handyman), считаем привязку к роли/группе; индивидуальные отклонения — через S38. Обоснование: иначе неясно, кому применяется сетка.
  • Edge cases: неделя целиком day-off; пересечение с праздником (S42 имеет приоритет над рабочим днём) 🟡; удаление расписания, на которое ссылаются активные сотрудники (запретить/предупредить).

S38 — Shifts [desktop]

  • Назначение: конкретные смены на дату — назначение времени check-in/out отдельным сотрудникам/группам (переопределяет шаблон расписания).
  • Источник (Miro): id 3458764674668376446 (2× = дубли).
  • Layout: HR-меню · header (search + dropdown + кнопка) · data-table: строка = смена.
  • Данные на экране: ID, Name, Day, Check In, Check Out, Assignment; значения 09:00/19:00, дата 25/06/2026, привязки Office/Handyman; per-строка edit / delete.
  • Контролы и действия:
    • search input_text (filter).
    • input_dropdown → фильтр по дню/assignment (dropdown).
    • input_button+ Add Shift (create).
    • edit → update смены; delete → удалить смену.
  • Состояния/вкладки: table, filtered (по дню/assignment), empty.
  • Связи (data-flow): уточняет ожидаемое время для S03 (Daily) на конкретную дату поверх S32 (Schedule). Assignment связывает смену с сотрудником/группой/локацией.
  • Мутации: create / update / delete Shift.
  • Права: Operations/Coordinator — full. Accounting — read.
  • 🟡 [не было додумано]: приоритет Shift над Schedule при вычислении Exp Check In/Out в Daily — прототип не определяет разрешение конфликта; разумный дефолт: конкретная смена побеждает шаблон.
  • Edge cases: две смены на один день/сотрудника (split-shift или конфликт); смена на день, помеченный day-off расписанием; смена в прошлом (read-only).

S42 — Days Off / Public Holidays [desktop]

  • Назначение: календарь нерабочих дней — годовые выходные/госпраздники, влияющие на ожидаемую посещаемость.
  • Источник (Miro): id 3458764674668785386 (2× = дубли). Пункт меню — Public Holidays.
  • Layout: HR-меню · header (search + dropdown год + кнопка) · data-table.
  • Данные на экране: ID, Name, Year, Days Off, Assignment; значения Office/Handyman, 2026; per-строка edit / delete.
  • Контролы и действия:
    • search input_text (filter).
    • input_dropdown → фильтр по году (dropdown).
    • input_button+ Add (create запись нерабочих дней).
    • edit → update; delete → удалить.
  • Состояния/вкладки: table, filtered (год), empty.
  • Связи (data-flow): питает колонки Holiday/Public Holiday в S03 (Daily) и S14/S19 агрегатах; Public Holiday Balance в S14 опирается на эти дни. Assignment определяет, к какой группе/локации применяется набор выходных.
  • Мутации: create / update / delete набора Days Off (год + перечень дней).
  • Права: Operations/Coordinator — full. Accounting — read.
  • 🟡 [не было додумано]: Days Off как счётчик vs перечень конкретных дат — в прототипе колонка одна; для расчёта Daily нужны конкретные даты, поэтому редактирование подразумевает список дат внутри записи года.
  • Edge cases: регион-специфичные праздники Bali (разные Assignment); праздник, совпавший с day-off расписания (без двойного списания); прошлый год (архив, read-only).

S22 — Leave Request [desktop]

  • Назначение: подача и обработка заявки на отпуск/отгул с проверкой текущего баланса; плюс список заявок (Requests).
  • Источник (Miro): id 3458764673084340037 (2× = дубли). Содержит ОБА состояния: форму заявки (detail) и список заявок (Requests-таб/таблица).
  • Layout: HR-меню · две зоны: (1) Requests list — таблица заявок с быстрым фильтром по типу; (2) Request form — форма/drawer заявки.
  • Данные на экране:
    • Фильтр-чипы типов: All, Annual Leave, Sick Leave, Holiday Leave, Other, Attendance.
    • Список: строка заявки — Request, дата (22/05/2026), тип (Annual Leave), сотрудник (Agus Putri), роль (Housekeeping Coordinator).
    • Форма: From: (22/05/2026), To: (24/05/2026), Days: (2), Current Balance: (10), Comment (textarea), Attachements (вложения).
  • Контролы и действия:
    • фильтр-чипы типов (filter) → сузить список заявок.
    • From/To (date input) → пересчёт Days (вычисляемое поле).
    • тип (dropdown: Annual/Sick/Holiday/Other) → подставляет соответствующий Current Balance.
    • Comment (textarea input); Attachements (file input).
    • Submit/Approve/Reject (button) 🟡 явных кнопок в каталоге нет — нужны для жизненного цикла заявки.
  • Состояния/вкладки: list (с фильтром по типу) · form (new/edit) · статусы заявки: Pending / Approved / Rejected 🟡; empty (нет заявок); error (баланс недостаточен).
  • Связи (data-flow): Current Balance читается из S14 (Monthly) / квоты сотрудника. Одобренная заявка списывает баланс и проставляет Leave/Annual Leave дни в S03 (Daily) на диапазон From..To → отражается в S14/S19. Days = рабочие дни между From и To (учёт расписания/праздников) 🟡.
  • Мутации: create LeaveRequest; transition Pending→Approved/Rejected; при Approve — decrement balance + write Attendance leave-дни.
  • Права: сотрудник — create свою заявку (обычно из mobile Profile, E11). Coordinator/Operations — approve/reject подчинённых. Accounting — read.
  • 🟡 [не было додумано]: статусы (Pending/Approved/Rejected) и кнопки Submit/Approve/Reject — прототип показывает поля формы и список, но не lifecycle; без перехода статусов сценарий UC-8 (approve → списание) нереализуем.
  • Edge cases: Days > Current Balance → блокировать submit или пометить overdraw; To < From (валидация диапазона); пересечение с уже одобренным leave; заявка на прошедшие даты; вложение превышает лимит.

Cross-screen relations (внутри эпика)

S34 Employees ──(identity: ID/Lark ID)──► все HR-экраны

S32 Schedules ─┐
S38 Shifts ────┤(Exp Check In/Out, Day Off; Shift override Schedule)
S42 Days Off ──┘──► S03 Attendance Daily ◄── mobile check-in/out (E04/E11, CI/CO Location)
                          │ агрегация
                          ├──► S14 Attendance Monthly (Taken/Balance)
                          └──► S19 Attendance Yearly (Working Days, roll-up)

S22 Leave Request ──[Approve]──► баланс− + leave-дни в S03 Daily ──► отражение в S14/S19
                  └─ Current Balance ◄── S14 / квота сотрудника

Решения заказчика (2026-06-22)

Закрывают открытые 🟡 эпика (Q-17..Q-24) + сквозное K-1 (реестр 00-client-questions.md). Перенос в вёрстку — Tier B/C отдельными PDD.

  • K-1 · Assignment везде = конфигурируемая композиция людей (resolves S32 §149, S38 §166, S42 §189 «assignment»): во ВСЕХ HR-модулях Assignment оперирует конкретными людьми, НЕ ролью/локацией как абстракцией. Где назначается набор (Schedules, Public Holidays, Annual Leave) — это настраиваемая композиция: группа/роль/кластер, ИЛИ отдельные люди, ИЛИ комбинация («Office + Иван Петров», «две группы», «группа + 2 чел.») — как в Lark. В UI сохраняется идентичность группы (показывается её название, не плоский разворот); на бэке композиция резолвится в список людей (membership-expansion). Единичная замена (Shift, Q-21) — частный случай: один человек.
  • Q-20 · schedule binding (S32) — РЕШЕНО (resolves §149): канон — per employee (делаем 100%). Привязка к роли/группе — UI-удобство (второй сценарий): новые сотрудники роли авто-попадают под её график; но т.к. внутри роли бывают разные графики, база обязана быть per-employee. Нужен multi-select (office standard work ≈ 95% офиса) + значок «добавить сотрудника» в смену. Schedule.role: string → привязка людей.
  • Q-21 · shift Name/Assignment (S38) — РЕШЕНО (resolves §166): Name = свободный лейбл записи (ни к чему не привязан, можно с пресетами). Assignment = ОДИН конкретный сотрудник (выбор из базы), НЕ роль и НЕ локация — shift = разовое изменение графика конкретного человека на день. Shift.assignment свободная строка Office/Handymanemployee-picker (1 чел.). → Tier B U2.
  • Q-22 · expected-time priority (S03/S32/S38) — ПОДТВЕРЖДЕНО (resolves §169, §238): движок: Schedule (база) → Shift (перезаписывает на день) → Leave/Holiday (перезаписывает). Итог (побеждает верхний): Leave/Holiday > Shift > Schedule. Подтверждает прототипный resolveExpectedTimes (5 веток). expected популяризируется в daily-БД заранее.
  • Q-18 · aggregate source + taxonomy (S03/S14/S19) — РЕШЕНО (resolves §128, §241): источник истины — Attendance Daily. Ежедневный движок забирает всех сотрудников, резолвит графики (schedules+shifts), проверяет реквесты/ливы → постит на день expected check-in/out, holiday/выходной да-нет, leave-тип. Сотрудник чекинится в мобильном → факт check-in/out + фото в ту же запись. Месячные/годовые агрегаты роллапятся из daily на бэке. Прототип-снимок (pre-aggregated) — ОК. Таксономия: Annual / Sick / Holiday / Day-off / Attendance(коррекция); общий Leave = прочий (non-annual).
  • Q-17 · annual leave quota + accrual (S14 + новый экран) — ЧАСТИЧНО (resolves §110, §241): единая константа на всех active (~17 дней/год; точная 17 vs 12 — у HR, action Akira). Не зависит от стажа, но только active (не trial). Accrual: нельзя взять больше дней отпуска, чем отработано месяцев в этом году (leaveTaken ≤ monthsWorkedThisYear). Управление — через Annual Leave settings/schedules (по образцу attendance schedules): лист графиков (обычно один, «Annual Leave Bali Office»), у каждого дней/год + правило начисления, к графику подписываются сотрудники (K-1). Настройка — не отдельная админ-страница отпусков, а секция в единой «Странице настроек отделов» (Departments Settings) (общее место для ВСЕХ конфигурируемых переменных). LEAVE_QUOTA-константу не зашивать числом до ответа HR. Открыто: точная квота; пропорция при найме среди года (накрывается accrual-правилом).
  • Q-24 · Sick/Other balance (S22) — ПОДТВЕРЖДЕНО: квот нет ни у Sick, ни у Other, ни у day-off — всё по согласованию супервайзера/директора. Current Balance для них = «—» (подтверждает WP-4 computeLeaveBalance). Квота только у Annual / Public Holiday.
  • Q-19 · Public Holidays / Days Off (S42) — ЧАСТИЧНО (resolves §189): Assignment = люди (K-1). Public Holidays имеют свои графики (как attendance/leave), к которым подписываются сотрудники (графики праздников разные). Day-off (неоплачиваемый отгул) — через Request: без баланса (не лимитирован), HR аппрувит → пишется в attendance как day-off. Открыто: «Days Off = счётчик vs перечень дат» внутри записи года явно НЕ закрыто (для дневных holiday-колонок логично нужны даты) — уточнить.
  • Q-23 · Requests / Attendance-chip (S22) — РЕШЕНО: верхние вкладки Requests = пред-фильтры по типу реквеста (All/Annual/Holiday/Sick/Attendance/other). Attendance — легитимный тип реквеста-коррекции (забыл зачекиниться → просит HR проставить за прошлый день). НО весь Requests-модуль HR пока НЕ задизайнен (отложен — было неясно про attendance) → следующий этап. В прототипе чип временно убран до постройки Requests. Точка ввода day-off/leave-реквестов — этот модуль (см. Q-19).

Дозумано на уровне эпика 🟡

  • Lifecycle LeaveRequest (Pending/Approved/Rejected) + кнопки Submit/Approve/Reject — прототип даёт только поля формы и список; UC-8 требует переходов статуса и точки списания баланса. Минимальное достраивание, без доп. ролей сверх скелета.
  • Производные Attendance-статусы (present/late/absent) — выводятся сравнением Check In с Exp Check In и наличием отметок; в каталоге только колонки.
  • Разрешение конфликта Schedule vs Shift vs Days Off при вычислении ожидаемого времени Daily — дефолт: Days Off/Holiday > Shift (конкретная дата) > Schedule (шаблон). Прототип приоритет не задаёт.
  • Переход Employees-строка → карточка сотрудника для edit полей — карточки-экрана в прототипе нет, но реестр без редактирования нефункционален; достроен минимальный переход.
  • F-checkin-history-tasks-per-employee (defer): история чек-инов и разрез «задачи на сотрудника» НЕ включены в эти экраны — это открытый продуктовый вопрос (sticky-note). Если подтвердится заказчиком — добавить вкладку History в карточку сотрудника (S34) и/или раздел в Schedule (S44, вне этого эпика). Пока намеренно не достраиваем, чтобы не плодить фичи сверх скелета.
  • Формула Balance (annual_quota − Taken) и пропорция квоты при найме в середине периода — отмечены, но не реализованы как UI; квота сотрудника в прототипе не показана.