Develop - #90
Merged
Merged
Conversation
The same date range produced four different answers. Measured org-wide over one
60-day window: reports tab 23.02h, report builder 31.52h, dashboard 31.51h, Time
page 31.68h — of which the Time page displayed only the slice on screen (3905h
against a true 2001h across the full dataset).
There was no shared definition of "worked time", and the four surfaces disagreed
on all three axes at once:
* Which rows count — analytics filtered `type='tracked'` for its headline KPI,
dropping approved MANUAL time, while its own charts and log tables filtered
nothing and counted IDLE. A table never reconciled with its own header.
* How long a row is — the dashboard summed `duration_seconds`, a desktop-written
column that is not trustworthy: idle rows store 1897h against 55h of real
wall-clock, and several tracked rows store NEGATIVE seconds, which SUM()
silently subtracts.
* Which day it lands on — summary() grouped by `DATE(started_at)`, i.e. the UTC
date, inside range bounds resolved in the org timezone. For Asia/Karachi that
pushed work done before 05:00 local onto the previous day's bar.
And the Time page summed the page it had been handed (20 rows) beside an entry
count covering every match, so the card moved as you paged.
App\Support\WorkedTime is now the single definition — clamped timestamp-derived
duration, org-timezone day bucket, approved-non-idle scope — wired through
ReportService, DashboardController, and TimeEntryController, which now returns
total_seconds/idle_seconds/unapproved_seconds for the WHOLE filtered set instead
of letting the client sum a page.
fix(reports): honour the report user filter by permission scope, not role name
Picking any user in the Advanced Report Builder — or "All Users" — returned the
logged-in user's own figures.
`reports.view` is granted to the employee role at scope 'own', so an employee
legitimately reaches these endpoints. The web client gated the user picker on
merely HOLDING the permission, so it rendered a full team dropdown, sent user_id,
and the API then clamped every request back to the caller. The UI advertised a
capability the API was never going to honour.
The server side was brittle too: it decided visibility with `$user->isEmployee()`,
which reads the `users.role` STRING — a fallback used only when a user has no
user_roles row, on a role set that is open because orgs define custom roles.
ReportController now resolves visibility from the SCOPE on the actor's grant:
organization sees anyone, project sees their team (a requested outsider narrows
to self rather than widening), own is clamped to self. ReportService accepts a
list of user ids so project scope is expressible instead of falling through to
the whole org. The reports page gates the picker on
hasPermissionWithScope('reports.view','project') — the same test the Time page
already uses — so own-scoped users get no dropdown at all.
Verified with real dispatched requests: owner sees 15.58h all / 13.71h for a
chosen member; an own-scoped employee gets their own 1.87h whatever they ask.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…t-user-filter fix(reports): one worked-time total across every surface, and a user filter that actually filters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.