Operational reports and targets
Read Job profit and expenditure series
/a/Report_getUsersSummary
Compare Job labour, mileage and stock costs with linked Invoice charges in the Profit and Expenditure Summary report.
When to use this endpoint
Compare Job labour, mileage and stock costs with linked Invoice charges in the Profit and Expenditure Summary report. Select the matching saved Reports dashboard chart or table, choose a bounded range, and use the returned series to render that report.
res rows follow the selected status list; default order is labour, mileage, stock, profit and price charged. It returns xLabels/xLabels1 but not yLabels.
Authentication and permissions
Authenticate with signed API-key fields or a logged-in CRM session. The handler requires login and account reporting feature bit 8192. No separate Reports, Jobs, Tasks or finance page-permission check is added by the handler.
The dispatcher rejects this legacy Report route for configured TeamAccess record scope, including assigned-only/parent-manager access and applicable department hierarchy scope. It returns an explicit scope error rather than a silently filtered chart.
Allowed requests read the authenticated tenant. Entity selections are report filters or label controls, not authorization; the handler does not add customer account-manager ownership filtering.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
daysFrom | Integer string | Yes | Inclusive first date: relative day offset from current PHP time by default, or Unix seconds with durationType=1. Must be an integer; malformed/blank values are rejected. ISO strings are not parsed as dates. |
daysTo | Integer string | Yes | Inclusive last date, in the same mode as daysFrom. Expanded to 23:59:59 in the account timezone; no reversed-range validation. |
durationType | Integer string | No | Default 0. Exactly 1 uses Unix seconds; other values convert integer day offsets through strtotime. Use 0/1; numeric values are validated before report SQL. |
frequency | Integer string | No | Default 0 monthly, 1 weekly, 2 quarterly, 3 yearly. Controls helper axis and grouping, using ISO week-year for weekly periods. Unsupported values are rejected. |
userType | Integer string | Yes | 0 summary, 1 users, 2 customers, 3 asset-axis labels. User grouping is created_by for Invoices and assigned user_id for Jobs. Type 3 uses the same customer-key grouping as type 2 rather than an actual asset relationship. |
user | Native array of ID strings or ["All"] | No | Defaults to ["All"]; a supplied empty list is rejected. Summary ignores the selection; individual axes include selected IDs by name. Pass a native array, not an encoded JSON string. |
status | Native array of metric IDs or ["All"] | No | Defaults to all five metrics. 0 labour, 1 mileage, 2 stock, 3 profit, 4 price charged. Output follows request order. Empty gives no series; unknown values give zero series. Not a Job status filter. |
Example request
$report = FM_api('Report_getUsersSummary', [
'daysFrom'=>'1768003200',
'daysTo'=>'1768003200',
'durationType'=>'1',
'userType'=>'0',
'frequency'=>'0',
'user'=>['All'],
]);
Example response
{
"res": [
[
10
],
[
2
],
[
3
],
[
15
],
[
30
]
],
"xLabels": [
"Jan 2026"
],
"xLabels1": []
}
Populated fixture: labour 10.9, mileage 2.9, stock 3.9 and price 30.9 are truncated to 10, 2, 3 and 30; profit is 15.
res rows follow the selected status list; default order is labour, mileage, stock, profit and price charged. It returns xLabels/xLabels1 but not yLabels.
Errors and unusual responses
| Response | Condition |
|---|---|
{"error":"not logged in"} | No authenticated tenant context is available. Invalid signed credentials can be rejected by the dispatcher before the handler runs. |
{"error":"This legacy report does not support your configured record scope. Use the scoped Contracts reports or table exports."} | The dispatcher detects configured TeamAccess record scope before the handler. |
{"error":"no permission to access api"} | Account reporting feature bit 8192 is absent. |
{"error":"missing parameter: daysFrom"} | The named parameter is omitted or null. Present blank/malformed controls return an invalid-parameter error instead; list controls must be native arrays. |
{"error":"missing parameter: daysTo"} | The named parameter is omitted or null. Present blank/malformed controls return an invalid-parameter error instead; list controls must be native arrays. |
{"error":"missing parameter: userType"} | The named parameter is omitted or null. Present blank/malformed controls return an invalid-parameter error instead; list controls must be native arrays. |
{"error":"invalid parameter: daysFrom"} | A supplied numeric/list control is malformed, a list contains unsupported tokens, or frequency/userType/date selectors are outside 0–3. The message names the invalid control; validation precedes chart queries. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Filters active Jobs by scheduled meeting_time_e with Unix day bounds. It groups assigned user_id, or customer_id for customer/asset-axis modes; completion state does not restrict the cohort.
- Labour, mileage and stock are SUM(hours_cost), SUM(mileage_cost), SUM(stock_cost). Price Charged is SUM(invoices.total), not total_net or the Job’s current price_net. No Quote or meta.job_value fallback is applied.
- Invoice links are type-3 Job-to-Invoice rows only. Distinct linked Invoice IDs are summed per Job before outer aggregation, so duplicate links do not repeat charges and multiple Invoices do not multiply Job costs. Type-4/direct links remain outside this contract.
- Each SQL group’s cost/price sums are integer-converted before accumulation. Profit is integer price minus integer labour+mileage+stock. Schedule of Rates cost is not part of this total cost.
- status is a metric selector here, not Job completion state: 0 labour, 1 mileage, 2 stock, 3 profit, 4 price. Request order determines res order, duplicate IDs duplicate contributions and unknown IDs initialize zero rows.
- legend and displayType do not change the server calculation; the saved Reports dashboard uses its own legend selection to show/hide returned metrics.
- There is no pagination, checkpoint or result-size limit. Keep the date range and entity selection bounded. Aggregated values are numeric chart cells, not database scalar strings or object rows.
- The helper orders periods first, then entities by name; one entity collapses xLabels to period text with empty xLabels1. Temporary users with non-null meta.is_tmp are excluded from user-axis lookups, but inactive/deleted label entities are not generally excluded. Unmatched entity/date keys are silently dropped.
- PHP date conversion uses the account timezone (missing/null defaults to Europe/Dublin, blank means UTC). SQL date/Unix conversion uses its database session timezone; these handlers do not force cross-layer alignment.
- Weekly axes enumerate real Mondays and use ISO week-year keys consistently with SQL. Week 53 and ranges crossing a calendar-year boundary are included; display labels are Week NN YYYY using the ISO year.
- For scheduled Unix boundaries, Core_timeLocalToEpoch uses UTC when the timezone setting is blank/missing, while the chart timezone helper uses Europe/Dublin when missing. Configure a valid account timezone to avoid that fallback mismatch.
- Numeric controls and native selector lists are validated through Report_validateChartRequest before SQL. JSON-encoded list strings, nested/object-keyed arrays, unsafe ID values and undocumented tokens are rejected. The existing login, reporting-feature and TeamAccess entry policies remain unchanged.
- No direct caller for this endpoint was found in the mobile app or its m-service intermediary.
Side effects
- Reads tenant data only; no business-record, audit, notification or schema writes occur. The chart restores its temporary PHP timezone on normal return paths.
See it in Fieldmotion
CRM1
Open Reports dashboard, add or preview Profit and Expenditure Summary, choose filters and inspect Network for Report_getUsersSummary. pageReportDashboard.js constructs the endpoint dynamically from the saved api value. Generic legends can control presentation without changing the backend cohort; compare the actual request with this page’s parameter contract.
CRM2
Open Reports dashboard, add or preview Profit and Expenditure Summary, choose filters and inspect Network for Report_getUsersSummary. lib/displayReport.js / pageReportDashboardDetails.js constructs the endpoint dynamically from the saved api value. Generic legends can control presentation without changing the backend cohort; compare the actual request with this page’s parameter contract.
Related endpoints
ReportDashboard_getRequestedDetailsreads a saved widget definition and filters; its widget ID is not a legacy report-template ID.