Time reports
A manager-facing view over every ticket time entry in a date range. Complements the weekly timesheet (operational, per-technician) with strategic roll-ups: "how many billable hours did we log this month, which customers consumed the most time, which work types dominate the mix".
URL: /helpdesk/reports/time
Required permission: helpdesk.view
How to get there
Go to Helpdesk → Timesheets.
Click the Time reports → link in the header actions row.
Or navigate directly to /helpdesk/reports/time.
Filter bar
The filter bar at the top drives every panel on the page. Changes push a fresh URL so you can share or bookmark a particular view.
Quick-select presets:
This week: Monday to Sunday of the current week
This month: 1st to end of current month
Last month: full previous calendar month
This quarter: current quarter (Q1 = Jan-Mar, etc.)
Custom filters (combine freely):
| Filter | Effect |
|---|---|
| From / To dates | Any window you want outside the presets |
| Technician | Limit to one staff member's entries |
| Customer | Limit to entries on tickets for one company |
| Work type | Limit to one work-type classification |
| Billable | "Billable only" or "Non-billable only" |
Click Apply to run with the current filter state. The URL updates so you can copy it.
Default view when no filter is applied: the last 30 days ending today.
Summary tiles
Five headline numbers across the top:
Total hours: every entry in the filter, including non-billable.
Billable: only entries flagged
is_billable=true, plus the percentage of total.Non-billable: the rest.
Labour value: sum of
billable hours × applied rateacross every billable entry, formatted as currency. Useslabour_rate_appliedwhen the entry has one (work-type / contract override) or falls back to the loggedhourly_rate.Avg entry: total hours ÷ entry count.
Hours are shown as Nh Mm with minutes rounded from the effective minute count (uses rounded_minutes when set, which is what actually gets billed, and falls back to duration_minutes).
Daily hours sparkline
A horizontal bar per day across the window. The longest-day bar is full width; everything else scales to it. Days with zero entries are included so gaps don't distort the rhythm.
Useful for spotting:
Weekend working (days that shouldn't have entries but do)
Under-logging at month start or end
Bank holidays or leave where hours suddenly drop
Breakdown tables
Three tables split on different dimensions, each ordered by total hours descending so the top consumers sit at the top.
By technician
| Column | What it shows |
|---|---|
| Name | Staff member who logged the entries |
| Total | All hours in the window |
| Billable | Billable hours + percentage of that tech's own total |
| Value | Labour value from billable hours × applied rate |
By customer
Groups entries via the ticket's company link. Tickets with no company are collapsed under "No company" rather than dropped.
| Column | What it shows |
|---|---|
| Company | Customer name (or "No company") |
| Total | All hours in the window |
| Billable | Billable hours |
| Value | Labour value from billable entries |
By work type
Entries without a work_type_id bucket into "Unclassified" so they still appear (and are a signal to tighten up classification at the entry point).
| Column | What it shows |
|---|---|
| Work type | Named work type (or "Unclassified") |
| Entries | Count of time-entry rows |
| Total | All hours |
| Billable | Billable hours |
What "hours" actually means
The report uses the effective minute count per entry, which is:
rounded_minutesif the entry has a rounding rule applied (most common on long-running timers where the tenant has a 15-minute-increment rounding policy)otherwise
duration_minutesotherwise 0
This matches what the weekly timesheet + charge-generation use, so the numbers on the report reconcile with billing.
Labour value is effective_minutes / 60 × (labour_rate_applied ?? hourly_rate). Non-billable entries contribute 0. No FX conversion: everything's in the tenant's base currency.
What's NOT shown
Entries on a different tenant: scoping is strict by
tenant_id.Entries from soft-deleted tickets/users: they drop out of the join.
Entries beyond the filter window: only
tte.datebetween from/to counts.
Differences from the weekly timesheet
| Weekly timesheet | Time reports | |
|---|---|---|
| Audience | Individual techs | Managers, admins |
| Scope | One tech, one week | Filtered range, aggregated |
| Granularity | Entry-level (ticket + day cell) | Roll-ups (by tech / customer / work type) |
| Interactivity | Edit entries inline | Read-only |
| Purpose | Track my own hours | Understand where time goes |
Use the weekly timesheet when you're logging or correcting your own hours. Use time reports when you're answering "how much time did we put into Acme this quarter" or "what's our billable utilisation".