feat(time-tracking): finish PMS-42 story (entries, timesheets, timers, rounding, work types) #26
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/time-tracking-story-pms-42"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements YouTrack story PMS-42 (time tracking). Targets
maindirectly.Sub-tasks
src/modules/time_tracking/{mod.rs, models.rs, service.rs, routes.rs}wired viamerge, replaces the/time-entriesand/timesheetsstubs./api/v1/time-entries(F8): filter by user / ticket / project / date range, paginated./api/v1/time-entries/:idwith auto-recomputed duration + total./api/v1/timesheets: aggregates by(user_id, week)using PostgresDATE_TRUNC('week', ...)./api/v1/timesheets/{user_id}/{week_start}/submit: state transition over the week's entries./timers/active,/timers/start,/timers/{id}/stop). UNIQUE(user_id) enforced; stop creates the correspondingtime_entriesrow in one transaction.The bottom seven sub-tasks ship in one commit because they share
service.rs/routes.rsand splitting per-task would have been arbitrary diff churn; commit body lists every PMS- id withState Doneso YouTrack closes them all when this PR merges.Test plan
cargo check --bin mokosh-serverclean (verified locally).POST /api/v1/time-entries {"user_id": "...", "date": "2026-05-17", "start_time": "09:00", "end_time": "10:30", "work_type_id": "...", "company_id": "..."}returns 90 minutes.GET /api/v1/timesheets?week=2026-05-12rolls up the entry.POST /api/v1/timers/start {...}andPOST /api/v1/timers/{id}/stopproduce a time_entries row covering the elapsed window.Closes #PMS-42
`src/modules/time_tracking/{mod.rs, models.rs, service.rs, routes.rs}` with full DTO coverage (work types, time entries, timesheet summaries, active timers, rounding rules). `time_tracking_routes` is wired via `merge` and replaces the `/time-entries` and `/timesheets` stubs. Router is empty in this commit; subsequent commits add endpoints. #PMS-43 State DoneAll six remaining sub-tasks in the PMS-42 story shipped in one batch because they share the same `service.rs` and `routes.rs` files; splitting per-task would have been arbitrary diff churn. - PMS-44 GET / POST `/api/v1/time-entries` with filter (user / ticket / project / date range) + pagination. Compute `duration_minutes` from start/end or accept it directly. Non-admins can only log time for themselves. - PMS-45 GET / PUT / DELETE `/api/v1/time-entries/:id`. Recompute `duration_minutes` and `total_amount` (rate * minutes / 60) on start/end/rate changes. - PMS-46 GET `/api/v1/timesheets` aggregates `time_entries` by `(user_id, DATE_TRUNC('week', date))`. Filter by user / week. - PMS-47 POST `/api/v1/timesheets/{user_id}/{week_start}/submit` flips every non-approved entry in the (user_id, week) window to `approval_status = pending` (the conventional "submitted, awaiting approval" state). Non-admins can only submit their own. - PMS-48 active timers: GET `/timers/active`, POST `/timers/start`, POST `/timers/{id}/stop`. UNIQUE(user_id) on `active_timers` is honoured; start rejects if a timer is already running. Stop atomically removes the timer row and creates a `time_entries` row with the elapsed window; falls back to the tenant's first active work type / inferred company when the timer didn't carry one. - PMS-49 time rounding rules CRUD (`/time-rounding-rules`). Setting `is_default = true` demotes the prior default in the same transaction. `rounding_method` validated against `up | down | nearest`. - PMS-50 work types CRUD (`/work-types`). Admin-only writes; reads available to any authenticated user. #PMS-44 State Done #PMS-45 State Done #PMS-46 State Done #PMS-47 State Done #PMS-48 State Done #PMS-49 State Done #PMS-50 State DonePull request closed