Sales, finance and marketing reports
Count won Quotes per user
/a/Report_getQuotesWonPerPerson
Rank active won or paid Quotes by assigned user within a legacy relative win-date window.
When to use this endpoint
Rank active won or paid Quotes by assigned user within a legacy relative win-date window. This is the older Dashboard ranking widget; it returns tuples rather than the series-and-axis contract used by the other pages in this group.
type is "horizontal_barchart", breakdown_by is "user_id", and res contains [count,"",user_id] tuples ordered by descending count. Database count and ID are usually strings.
Authentication and permissions
Authenticate with signed API-key fields or a logged-in CRM session. The handler requires login; it does not check account reporting feature bit 8192.
The dispatcher rejects these legacy Report routes for a user with configured TeamAccess record scope, including assigned-only/parent-manager access or a department hierarchy scope. It returns an explicit legacy-report scope error; it does not return a silently partial chart.
For an allowed unscoped request, the handler reads the authenticated tenant and adds no Reports/Quotes/Invoices page-permission check, account-manager restriction or per-object ownership check. The result covers all qualifying assigned users; no user-selection parameter is implemented.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
days_from | Integer string | Yes | Relative lower day offset from database NOW(); converted with intval. Required even when daysFrom is supplied. |
days_to | Integer string | Yes | Relative upper day offset from database NOW(); converted with intval. Required even when daysTo is supplied. |
daysFrom | Integer string | No | Non-null value overrides days_from; days_from must still be supplied. Not an absolute date. |
daysTo | Integer string | No | Non-null value overrides days_to; days_to must still be supplied. Not an absolute date. |
durationType | Integer string | No | Parsed with default 0 but ignored; 1 does not enable timestamp input. |
Example request
$report = FM_api('Report_getQuotesWonPerPerson', [
'days_from'=>'-30',
'days_to'=>'1',
]);
Example response
{
"type": "horizontal_barchart",
"res": [
[
"2",
"",
"1042"
]
],
"breakdown_by": "user_id"
}
Representative populated tuple with a synthetic user ID. Count and ID remain strings; the empty middle cell is part of the wire shape.
type is "horizontal_barchart", breakdown_by is "user_id", and res contains [count,"",user_id] tuples ordered by descending count. Database count and ID are usually strings.
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. This applies before the handler’s own checks. |
{"error":"missing parameter: days_from"} | days_from omitted or null. Present blank scalars and malformed list controls return an invalid-parameter error instead. Required lists must be native arrays. |
{"error":"missing parameter: days_to"} | days_to omitted or null. Present blank scalars and malformed list controls return an invalid-parameter error instead. Required lists must be native arrays. |
{"error":"invalid parameter: daysFrom"} | A supplied numeric control is malformed, a list has the wrong shape or an unsupported token, or frequency/userType is outside 0–3. The message names the invalid control; validation occurs before chart SQL. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- days_from and days_to must both be present even if camel-case overrides are supplied. daysFrom/daysTo override their matching snake-case values when non-null; blank overrides are invalid.
- The range uses SQL NOW(): the lower bound is DATE(NOW()+daysFrom days), while the upper bound is NOW()+daysTo days and is exclusive. These are relative day offsets, not absolute timestamps.
- durationType is read but never used. Unlike the other reports in this batch, it has no account feature-bit 8192 guard and explicitly filters deleted=0.
- Requires non-null won_date and status 1 or 2, groups by user_id, and counts each active Quote. It does not join user names or exclude inactive users.
- No matching rows produces res=[]. There is no pagination, top-N limit, secondary tie-break or include-zero-users option. Other chart filters are ignored.
- This is a single aggregate response with no pagination or checkpoint.
- No direct mobile-app or m-service caller was found for this route. Browser report definitions are separate from the newer Report_getData template contract.
Side effects
- Reads report data only. No record, audit, status, notification, mail, report-cache or schema writes occur. Date helpers temporarily change PHP timezone on paths noted above.
See it in Fieldmotion
CRM1
On the older Dashboard, add Quotes Won Per Person and change its date window. pageDashboard.js registers the exact endpoint and widgetReportShow.js sends days_from/days_to. Filter Network for Report_getQuotesWonPerPerson; user names are resolved by the widget from breakdown_by=user_id.
CRM2
No direct or report-catalogue caller for this ranking route was found in CRM2. Its Reports dashboard uses the other Quote series reports; the newer template widget calls Report_getData.
Related endpoints
Report_getQuotesToWonRatio— Compare monthly Quote creation totals with the legacy won/paid subset.Report_getQuotesStatusUser— Compare selected Quote statuses and an optional overall series across report periods and selected owners or customers.