feat(time-tracking): enforce per-tenant max-hours-per-day cap #298

Merged
vas2000-work merged 2 commits from feat/PMS-396-max-hours-per-day-cap into main 2026-06-18 02:21:22 +02:00
Owner

Reject any time entry whose creation or update would push a user's total logged minutes for a calendar date over a configurable per-tenant cap, closing the server-side gap where the only 24h limit lived in the frontend and multiple entries (or a direct API call) could evade it.

  • Teach validate_setting_value the time_tracking/max_hours_per_day shape: an integer in 1..=24 (a day cannot exceed 24 real hours), rejecting out-of-range or non-integer values with HTTP 422.
  • Add read_max_minutes_per_day, a free function returning the cap in minutes for a tenant and defaulting to 24*60 when unset, mirroring read_default_due_business_days.
  • Enforce the cap in create_time_entry and update_time_entry: sum the user's existing minutes for the target date inside the same tenant-scoped transaction as the write (excluding the edited row on update, honoring a changed date), and return HTTP 400 naming the cap and the remaining minutes when the day would overflow.
  • Bound a single entry's duration_minutes to 1..=1440 on both create and update DTOs so one entry can never alone exceed a day regardless of the per-day cap.

#PMS-396

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

Reject any time entry whose creation or update would push a user's total logged minutes for a calendar date over a configurable per-tenant cap, closing the server-side gap where the only 24h limit lived in the frontend and multiple entries (or a direct API call) could evade it. - Teach `validate_setting_value` the `time_tracking/max_hours_per_day` shape: an integer in 1..=24 (a day cannot exceed 24 real hours), rejecting out-of-range or non-integer values with HTTP 422. - Add `read_max_minutes_per_day`, a free function returning the cap in minutes for a tenant and defaulting to 24*60 when unset, mirroring `read_default_due_business_days`. - Enforce the cap in `create_time_entry` and `update_time_entry`: sum the user's existing minutes for the target date inside the same tenant-scoped transaction as the write (excluding the edited row on update, honoring a changed date), and return HTTP 400 naming the cap and the remaining minutes when the day would overflow. - Bound a single entry's `duration_minutes` to 1..=1440 on both create and update DTOs so one entry can never alone exceed a day regardless of the per-day cap. #PMS-396 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
vas2000-work force-pushed feat/PMS-396-max-hours-per-day-cap from f883172749
Some checks failed
E2E / Playwright against staging (pull_request) Successful in 53s
Integration / integration tests (pull_request) Failing after 1m0s
Check / fmt + clippy + compile + unit/doc tests (pull_request) Successful in 1m46s
to 43cf626d88
Some checks failed
Create release / Create release from merged PR (pull_request) Has been skipped
Integration / integration tests (pull_request) Failing after 37s
Check / fmt + clippy + compile + unit/doc tests (pull_request) Failing after 55s
E2E / Playwright against staging (pull_request) Successful in 56s
2026-06-18 00:48:49 +02:00
Compare
fix(test): set work_category on day-cap test helpers after rebase
All checks were successful
E2E / Playwright against staging (pull_request) Successful in 38s
Check / fmt + clippy + compile + unit/doc tests (pull_request) Successful in 1m20s
Integration / integration tests (pull_request) Successful in 4m58s
Create release / Create release from merged PR (pull_request) Has been skipped
99935374e4
The PMS-396 day-cap helpers create_minutes / duration_only_update predate PMS-394's work_category field on CreateTimeEntryRequest / UpdateTimeEntryRequest, so they failed to compile once rebased onto main. Set work_category: None to match the other helpers.

#PMS-396
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/mokosh-server!298
No description provided.