Quotes: settings, costing and lookups
Recalculate quote line totals
/a/Quote_calculateCost
Recompute saved cost rows and persist quote totals plus per-section summaries.
When to use this endpoint
Use after mapped quote cost widgets save their row payloads. This mutates totals and metadata; it is not a read-only quote preview.
Authentication and permissions
Authenticates a signed API key or CRM session as its tenant user. Requires Quotes View (pageQuotes_view). Non-admin users blocked by legacy crm_access bit 32 are denied. Roleless non-admin users fail closed. Also requires Quotes Edit (pageQuotes_edit); client administrators inherit page permissions.
Uses local tenant IDs. The active quote must also satisfy the account’s customer department/account-manager visibility filters for non-admin users, including signed-key requests.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | Positive integer-compatible quote ID | Yes | Positive local quote ID, integer-converted; an active quote is required. |
Example request
$result = FM_api('Quote_calculateCost', ['id'=>'1042']);
Example response
{"ok":1}
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":"quote does not exist"} | The active quote is missing (lookup failures are reported separately). |
{"error":"Unable to save quote. Check the saved state before retrying."} | Database, audit, transaction or commit acknowledgement failed. Refresh saved state before retrying an uncertain commit. |
{"error":"permission denied"} | Required Quotes permission is absent or the non-admin actor is blocked by legacy access settings. |
{"error":"missing or invalid parameter: id"} | Missing/nonpositive quote ID. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Reads stored costs and recalculates stock, sor, labour, other and verbose sections from rows. No costs returns warning=no available data without a write. Invalid metadata/sections/numbers return errors.
- Unit cost uses cost, with SoR stock_cost + labour_cost preferred when either is supplied. Unit price uses price, labour priceph or verbose net_price. Quantity uses amt then qty, or verbose amount. Missing numeric inputs contribute zero.
- A positive selected taxType ID/object resolves account_categories.tax_rate and takes precedence over tax; unknown categories fail. Without taxType, tax is interpreted as a percentage. No category defaults to zero tax.
- Row discountValue takes precedence over discountPercentage of base row net. features2.discountMarkup=1 adds adjustments; otherwise subtracts them. Header discount_rate is then applied once to the adjusted row price.
- Stores section summaries rounded to four decimals. Header total_net is base selling price before row/header adjustments; tax/gross/profit use adjusted prices. Profit is adjusted net minus cost. total_discount is the sum of row discount values, excluding header adjustments.
- Header monetary values must be finite and fit DECIMAL(10,2): absolute rounded values at most 99999999.99. An overflow rejects the save; database monetary columns round to their own scale.
- Locks the active quote in a tenant transaction. Bound writes, last_edited (server-local date/time), quote history and quotes cache invalidation are checked together. Audit or primary write failure rolls back. Existing caller transactions retain a savepoint; an uncertain commit returns an error and is never replayed automatically.
- No direct mobile app/m-service caller for this RPC was found.
- Calculation semantics match Quote_calculateCost: total_net is pre-adjustment; tax/gross/profit use row and header adjustments. A positive chosen taxType overrides tax. Tax-only legacy rows retain percentage interpretation.
Side effects
- Updates the named data and last_edited, records quote history and requests quotes cache invalidation in the tenant transaction. No ordinary mention notice, notification or email is sent by this dedicated handler.
See it in Fieldmotion
CRM1
No direct production Quote_calculateCost caller found. Legacy Costs calls Quote_costsSet, which uses this same row calculation.
CRM2
moduleQuotes invokes Quote_calculateCost after cost-widget changes, discount edits and creation saves; quick-create also calls it. Filter Network for this follow-up after a mapped save.
Related endpoints
Quote_costsGetreads the updated stored summaries.Quote_costsSetreplaces costs before running the same row calculation.Quote_setNetoverrides header amounts from default VAT.