Purchase orders
Save carriage cost and tax amounts
/a/PurchaseOrder_setDeliveryCosts
Store delivery charges and recompute the persisted order totals from line items plus carriage.
When to use this endpoint
Use after the client calculates delivery net and delivery tax. The tax-code label does not calculate the amount server-side.
Authentication and permissions
Authenticate with signed API-key fields or a logged-in CRM session. Session requests use dispatcher CSRF protection when configured.
Requires explicit View on Purchase Order or Purchase Orders. Writes also require the matching Edit permission; clearing invoice details requires Delete. A non-administrator blocked by the legacy Purchase Orders visibility flag (crm_access bit 256) is denied. API keys use their owner’s permissions.
The primary order is checked against the current tenant and Purchase Order record scope. Configured TeamAccess follows permitted linked Contracts, Customers, Jobs, Quotes and Departments; the legacy department filter follows direct Customer/Quote/customer-Job links. An inaccessible or missing order returns purchase order does not exist.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | Integer-compatible | Yes | Positive local Purchase Order ID/digit string; not the displayed po_num. Missing, malformed or inaccessible IDs fail. |
delivery_net | Numeric-compatible | Yes | Finite nonnegative number or numeric string, maximum 999999999.9999. Blank, malformed and negative values fail. |
delivery_taxcode | String | Yes | Required scalar string, at most 32 bytes; blank is permitted. Label is retained without an implicit tax-catalogue/rate calculation. |
delivery_tax | Numeric-compatible | Yes | Finite nonnegative tax amount, not a percentage; same numeric bound as delivery_net. |
Example request
$result = FM_api('PurchaseOrder_setDeliveryCosts', [
'id'=>'1042',
'delivery_net'=>'10.00',
'delivery_taxcode'=>'VAT20',
'delivery_tax'=>'2.00',
]);
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": "no ID provided"} | id absent/null. |
{"error": "no delivery_net provided"} | delivery_net absent/null. |
{"error": "no delivery_taxcode provided"} | delivery_taxcode absent/null. |
{"error": "no delivery_tax provided"} | delivery_tax absent/null. |
{"error": "permission denied"} | The required page/action or legacy visibility setting denies access. |
{"error": "purchase order does not exist"} | The primary order is missing or outside the caller’s permitted scope. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Net and tax must be finite nonnegative numeric values, at most 999999999.9999 each. Blank/nonnumeric/nonfinite/negative/nested inputs are rejected.
- delivery_tax is a supplied amount, not a percentage. The scalar tax-code label is at most 32 bytes; the endpoint retains the manual supplied-tax contract rather than deriving a rate from the label.
- Recalculation sums stored line total_net/total_tax and adds carriage once. Raw persisted total_net/total_tax remain delivery-inclusive. Mapped orderNet/orderTax expose line-only amounts so CRM2 layout totals add carriage exactly once.
- Changing supplier, carriage amounts/code or line items clears date_approved and requires approval again. Exact no-op saves retain approval. The legacy approved-edit restriction (crm_access bit 8192) is still enforced for non-administrators. Sent history is retained.
Side effects
- Header writes lock the existing order and tenant owner, check persistence and record history in the same transaction. Errors roll back the header and audit; a true no-op returns {ok:1,warning:"no change needed"} without a new event/history entry. Cache invalidation and edit-event follow-ups run after the owning transaction commits; an event exception returns saved=1 and a no-replay warning.
See it in Fieldmotion
CRM1
In CRM1 Purchase Order details, edit Carriage Net or its tax code. The page computes tax and sends delivery_net, delivery_taxcode and delivery_tax to PurchaseOrder_setDeliveryCosts.
CRM2
No direct caller was found in CRM2 source. Its Purchase Order screen uses mapped reads and generic field saves rather than this legacy endpoint.
Related endpoints
PurchaseOrder_get— Read the current raw header.PurchaseOrder_approve— Apply the approval action.PurchaseOrder_getRequestedDetails— Read mapped fields with explicit IDs.