Jobs: forms and resources
Merge named job form answers
/a/Job_setFields
Merge a map of named main-form answers while recording changed known fields and refreshing dependent costs.
When to use this endpoint
Use for the main-form autosave workflow after obtaining the attached form’s field names. Send only changed answers; unspecified answers remain.
This is not a general job-column setter and does not edit table cells. It accepts unknown names rather than validating them against the form.
Authentication and permissions
Authenticate with signed API-key fields or a logged-in CRM session. The handler performs no additional page or role-permission check.
Job and form IDs refer to the authenticated account. Cross-account writes occur only through the stored outsourcing relationship on the routes that explicitly mirror changes.
The dispatcher also applies account/user and IP restrictions. A CRM session carrying a CSRF token must supply it through X-FMCSRF or _csrf; missing/incorrect tokens can be rejected before this handler runs.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | Integer string | Yes | Positive physical job ID. |
fields | JSON object string or array | Yes | Truthy name-to-value map. JSON-encode nested values before signing. Blank input is rejected, but encoded []/{} passes the initial check; decoded type/field values are not validated. Empty-string values clear individual answers. |
Example request
$result = FM_api('Job_setFields', [
'id'=>'1042', 'fields'=>json_encode(['Inspection result'=>'Passed']),
]);
Example response
{"ok":1,"0":[]}
The numeric property "0" contains the attached form’s decoded field definitions; this example uses a form with an empty definition array. It may instead contain definitions or null. It is not an answer count.
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":"missing or invalid parameter: id"} | Job ID is nonpositive. |
{"error":"fields paramater cannot be empty"} | fields is missing/PHP-falsy; the misspelling is the wire response. |
{"error":"job does not exist"} | No active job is read. |
{"error":"Unable to save job"} | The primary database save failed. Successful-save history and subsequent follow-ups are not run. |
{"ok":1,"0":[],"warning":"Job saved; follow-up incomplete. Inspect saved state before retrying.","warnings":["Job_updateCosts: Unable to save job"],"saved":1} | The primary save succeeded, but a recalculation, asset rebuild, notification or outsourced mirror failed. warnings identifies the failed follow-up; any normal response fields remain present. A benign no-change result from a follow-up is not a failure. Read saved state before retrying. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Merges every supplied name into decoded form_values, without required-field, form-name or field-type validation. Existing unspecified answers remain.
- Known changed fields use loose old/new comparison and the form field’s meta.id for field history. Unknown names are still saved but do not get that per-field entry.
- Changed known assets fields trigger Job_updateAssetJobs. That helper rebuilds derived asset links/movements from the job, main-form tracked assets and table assets; asset_not_tracked suppresses main-form tracking.
- Malformed decoded fields or legacy answer data can cause warnings/runtime failures. No request row limit, pagination or optimistic concurrency check is provided.
Side effects
- The checked primary UPDATE saves form_values, last_edited and edited_uuid and invalidates the meetings cache. Known-field history is recorded only after that save succeeds.
- Conditionally rebuilds asset associations and always calls Job_updateCosts; follow-up failures produce saved-state warnings. No general outsourced-answer mirror or notification-mail call is made here.
See it in Fieldmotion
CRM1
Edit an ordinary answer in the job Form with editing enabled. pageJobForm.js collects changed names and sends Job_setFields after a 500 ms debounce, then recalculates the UI.
CRM2
Edit answers in the job Form and save/confirm. pageJobForm.js sends a JSON name-to-value map to Job_setFields, including its confirmation and calculation-save paths.
Related endpoints
Job_setFieldsaves one main-form answer, including clearing an image reference.Job_setTableCellspatches selected row/field positions while retaining unspecified cells.Job_updateCostsrefreshes cost/resource snapshots and invokes the price follow-up.