When to use this endpoint

Remove a receipt with no active Goods Returned note and recalculate the linked PO status.

Authentication and permissions

Authenticate with signed API-key fields or a logged-in CRM session. Session CSRF, account-active and IP restrictions still apply. These handlers add no receipt-specific page, finance, department or record-owner permission check.

Records are scoped to the authenticated tenant. CRM1 displays Goods Received with employer feature bit 262144; CRM2 checks features2.goodsReceivedNotes. Those screen gates are not enforced by these handlers. Mobile receipt routes run separately through the mobile intermediary and have different permission and ownership checks.

Parameters

ParameterTypeRequiredDescription
idIntegerYesReceipt ID, intval must be positive; the header must exist.

Example request

FM_api('GoodsReceivedNote_delete', ['id'=>'531']);

Example response

{"ok":1}

Errors and unusual responses

ResponseCondition
{"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"}Omitted or below 1 after intval.
{"error":"GRN does not exist"}Header lookup failed/missing.
{"error":"Goods Received Note not of a valid status for deletion"}An active goods_returned row links to this receipt; this is not a check of the receipt/PO status enum.

Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.

Behaviour and edge cases

  • The deletion guard ignores soft-deleted return headers (goods_returned.deleted=0). It does not separately inspect return lines or a receipt-created invoice/job.
  • After deleting header and lines, it sums remaining delivered quantities per PO entry. Any over-received line wins (3), else any partial line (1), else any complete line (2), else Open (0). A mix of complete and wholly unreceived rows can therefore be marked Received.
  • The sum branch tests strict !==0/!==null against DB values; zero represented as "0" can enter the numeric comparison branch. The resulting status is written directly without PO edit timestamp or status history.
  • It calls Core_logDeletion("purchase_orders", receipt ID), although the removed header belongs to purchases_in. The helper records a purchase_orders deletion and may snapshot an unrelated PO with the same numeric ID; it does not delete that PO itself.

Side effects

  • Physical header/line deletion, incorrectly named deletion-audit helper call, and direct linked PO status change. No stock restoration, inventory deletion, line deletion snapshots or receipt history. The header fmdbQuery passes purchase_orders as an unnamed array element, not a cache key.

See it in Fieldmotion

CRM1

In Goods Received use the row [x] delete action and confirm; inspect GoodsReceivedNote_delete. The UI describes the no-return-note guard.

CRM2

CRM2 bulk Delete uses GoodReceived_delete, which neither applies this return guard nor deletes lines/recalculates PO status.

Related endpoints