PRMKit.2 — May Update: My Time, Leave Management & Smarter Approvals
PRMKit.2 receives its biggest update yet — a ground-up rebuild of how people track time, request leave, and approve work. Every change listed here is live in production.
Previous releases laid the groundwork. This one rewires the plumbing: unified personal dashboards, a complete leave lifecycle with audit trails, holiday-aware approval UIs, and hardened bulk operations that no longer buckle under load.
⏱️ My Time — One Page to Rule Them All
The old split between My Timesheets and My Reports is gone. Both routes now redirect (301) to a single /app/mytime hub with two tabs:
- Insights (default landing): A year-to-date daily activity heatmap rendered as a 7×52 Mon–Sun grid. Cells are leave-aware and holiday-aware — weekend or holiday overtime renders in red so it can't hide in grey "no-capacity" tiles. Click any cell to jump straight to that day's entry card.
- Utilisation ring, billable summary, project rankings, and a pie chart all draw from a single lightweight YTD query — no extra round-trips.
- Entries: Day-grouped cards with bulk submit / recall, self-review panel, and paginated loading (page size reduced from 250 → 50 for snappier first paint;
?limit=override still works). - Heatmap refinements: 16 px cells with a 3 px gap, blue rounded outline for the active period, immediate floating tooltip (date + hours/capacity/util) replacing the laggy browser
<title>, and smart month-tick suppression to prevent label collisions at year boundaries. - Personal CSV export is now locked to the logged-in user regardless of role — previously a MANAGER or ADMIN visiting
/myreports/exportcould inadvertently export everyone.
🏖️ Leave Management — Full Lifecycle
The "Coming Soon" placeholder is gone. Leave management is now a fully operational, audited workflow:
- Employee self-service (
/app/leaves): Submit leave with a dynamic leave-type dropdown (types are now a database lookup table — HR can add new types without code changes). Resubmit rejected requests, request cancellation of approved leave, or withdraw a pending cancellation. - Admin approvals (
/app/leave-approvals): Routing is now ADMIN-only (the earlier manager / approval-chain / PM branches have been collapsed for clarity). Admins can approve their own leave (audit reason auto-tagged with:self). The queue no longer self-excludes the caller — this fixes the bug where a submitted leave would not appear in the approvals list. - Management table: Admins get a full "All Leaves" section with employee / status / date filters and paginated results. Add, edit, delete, and view audit history — all from one place.
- Audit trail: Every insert, update, and delete on
employee_leavesis captured by anAFTERtrigger intoemployee_leaves_auditwith actor identity, before/after JSON snapshots, and a business reason injected via a PostgreSQL GUC (app.audit_reason). - Cancel-approved flow: Status enum extended with
cancel_pendingandcancelled. Three new RPCs handle the round-trip: request → decide → withdraw. - Admin amend:
fn_admin_amend_leavelets an admin correct dates, hours, or notes on any leave with a mandatory reason — every correction is immutably logged. - Utilisation fix:
calculateLeaveDaysnow excludes public holidays, so a holiday falling inside an approved leave range is no longer subtracted twice.
✅ Timesheet Approvals — Smarter Review UX
Reviewing and approving timesheets is a daily ritual — so we rebuilt the UI to make it faster and less error-prone:
- Day-type shading: Each day-group header is now colour-coded — amber with a holiday-name chip for public holidays, rose with a "Weekend" chip for Sat/Sun, and neutral slate for regular weekdays. Holiday wins when a date is both a weekend and a holiday.
- Day-level select-all: A new tri-state checkbox in the date header selects every entry across all employees for that day in a single click.
- Unified sticky action bar: The desktop-only bulk-action chunk has been replaced by a single responsive sticky bar that works on all screen sizes — one source of truth, zero duplication.
- Atomicity hardening (v2.1.0): Bulk approval, bulk submit, and bulk recall are now wrapped in database-level transactions with
fn_log_submissions_bulk, eliminating partial-failure states and timeouts on large batches. - Self-review panel: Employees can self-review their full month's entries before submitting, with all drafts included in bulk-submit scope.
📊 Reports & Utilisation — Redesigned for Reality
- Management reports: Workforce utilisation table redesigned; utilisation is now capped at today's date so future working days don't dilute the percentage.
- Personal reports: Glass-themed UI with leave-aware utilisation calculations, billable summary cards, and a Month-to-Date preset.
- Holiday sync: Public holidays are now pulled from the Nager.Date API with year-scoped sync, gap detection, and a clear-year admin tool. Sync issues that previously left months without holiday data have been resolved.
👥 Management & Administration Refactor
The admin surface has been restructured for consistency:
- Active vs. Inactive separation: Staff status is split into dedicated tabs instead of filter cards.
- Role-based grouping: Staff members are grouped by role (ADMIN, MANAGER, EMPLOYEE).
- Manager visibility: Managers can see their managed projects and assigned employees at a glance.
- Daily capacity model: Capacity interpretation has shifted from weekly to per-day (default: 8 h/day), aligning with how timesheets and utilisation are actually calculated.
💾 Security, Data & CSV Stability
- Security hardening: A cross-cutting pass tightened RLS policies and query patterns.
- Database optimisation: Frequently hit queries have been restructured for lower latency.
- CSV reliability: Several high-risk bugs in large-volume CSV import/export have been identified and fixed — data moves safely and reliably at scale.
- Type-safe chart rendering: Chart components now consume typed data, eliminating a class of silent rendering bugs.
As always, reach out if you hit anything unexpected or run into a workflow blocker.
GZ.
