> ## Documentation Index
> Fetch the complete documentation index at: https://agents.nanonets.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# SAP Update Sales Order

> Adds, changes and (when enabled) deletes line items on an existing SAP sales order. Adding accepts the full create field set, including a contract or quotation reference.

Modifies an existing sales order in SAP: appends line items, changes existing ones, and deletes them when an operator has enabled deletion. Display name **"SAP Update Sales Order"**. Off by default.

Each item is handled in its own SAP transaction, so **partial success is normal** — some lines can commit while others are refused. Read `created_items` and `failed_items` and re-send only what failed; repeating the whole call duplicates the lines that already committed.

## Authentication and enablement

Requires a workspace SAP integration. `base_url` and `authorization` are injected. Enable the tool and bind the integration.

## Calling off a contract into multiple order lines

`items_to_add` accepts `reference_sd_document` and `reference_sd_document_item`, and **the same contract item may be referenced by several lines in one call**.

This is the tool's main reason to exist for contract work. A single `POST /A_SalesOrder` deep create rejects a payload that references one contract item twice, with:

```
SDSLS_INTEGRATION/011 — ReferenceSDDocument <doc> and Item <item> are referenced multiple times.
```

That check lives only on the deep-create path. Adding items one at a time goes through a different SAP entry point that has no such restriction, which is what this tool does.

With a reference, **omit `material` and `production_plant`** — SAP copies both from the referenced document, and sending `material` explicitly makes SAP reject the line with `SLS_LORD/025 "field is not an input field"`.

## Inputs

`sales_order` (required), plus at least one of `items_to_update`, `items_to_add`, `items_to_delete`.

### `items_to_add` — full parity with create

Accepts exactly the fields `sap_create_sales_order` accepts for a line item: `material`,
`material_by_customer`, `requested_quantity`, `requested_quantity_unit`, `production_plant`,
`reference_sd_document`, `reference_sd_document_item`, `incoterms_location1`, `pricing_date`,
`shipping_point`, `shipping_type`, `sales_order_item_category`, `item_billing_block_reason`,
`delivery_date_quantity_is_fixed`, `schedule_line`, `pricing_elements`, `texts`.

`requested_quantity` is always required. `material` is required **unless** a reference is supplied. Do not set an item number — SAP assigns it.

Limit: **200 items per call**. At roughly 2.5–5 s per item a larger batch would hold a worker step for many minutes and monopolise the document's lock. Split the work across calls.

### `items_to_update` — a narrower set

A PATCH cannot set every field. `A_SalesOrderItem`'s CDS view marks the quantity, weight, amount and status fields read-only, and SAP additionally decides editability **per item, per document state** — a line created by copy-with-reference accepts less than a manually entered one. Exposed fields:

`sales_order_item` (required), `requested_quantity`, `requested_quantity_unit`, `production_plant`, `material_by_customer`, `incoterms_location1`, `delivery_date_quantity_is_fixed`, `pricing_elements`.

`material` and the reference pair are **not** updatable here. Changing either is a delete-and-re-add, not an update. Anything SAP refuses appears in `failed_items` rather than being silently dropped.

`pricing_elements` is an **upsert**, keyed on `condition_type`: a condition the item already carries
is changed in place, one it does not carry is added. Supply `condition_currency` when adding — a
rate alone does not define a condition. SAP decides which condition types may be entered manually,
so a type its pricing procedure determines automatically is refused with SAP's own reason.

### `items_to_delete` — disabled by default

Deleting a line from a live order is destructive and cannot be undone through this API, so it is opt-in per configured tool. With `allow_item_delete` unset, a call containing `items_to_delete` is **rejected in full** before anything is sent to SAP — including a mixed payload, so adds cannot half-apply ahead of a refused delete.

### Operator settings

Not agent-visible; set per configured tool.

| Setting                | Default | Purpose                                                         |
| ---------------------- | ------- | --------------------------------------------------------------- |
| `item_create_delay_ms` | `500`   | Pause between item creates. Tune to the customer system's load. |
| `max_lock_retries`     | `3`     | Retries for an item that failed on a SAP document lock.         |
| `allow_item_delete`    | `false` | Must be enabled before the tool may delete items.               |

**On pacing:** adding items to one order serialises on SAP's lock for the order and — for copy-with-reference items — for the source contract too. Measured on a fresh order, 500 ms between calls produced zero lock errors across 100 items, while 100 ms lost 9 of 100 even with three retries each. Lower it only with evidence from the target system.

## Output

```
{
  sales_order_number, items_updated, items_added, items_deleted,
  sap_messages:  [{ code, message, severity, target }],
  created_items: [{ input_index, sales_order_item, material,
                    reference_sd_document, reference_sd_document_item, lock_retries }],
  failed_items:  [{ operation, input_index, identifier, reason, retryable }],
  errors[], total_net_amount, transaction_currency, line_item_count,
  full_details, completed_at, sap_url
}
```

`sap_messages` carries SAP's own business messages from every request the call made — credit
blocks, incompleteness, `SLS_LORD/025` field refusals — plus one `error` entry per operation the
tool could not apply and one leading `success` entry summarising what was applied. Repeats are
de-duplicated (SAP sends the document-level warnings on every item response) and the list is capped
at 50 with a trailing note when anything was dropped. This is what the feed card renders, exactly as
`sap_create_sales_order` does.

`retryable: true` marks a transient document lock that used up its retry budget — those items can be re-sent as-is. `retryable: false` is a real rejection and will fail again unchanged.

The call ends by reading the order back, which is where `full_details`, `total_net_amount` and
`line_item_count` come from. If that read fails, the call is reported as an error but **still
returns `created_items`, `failed_items` and `sap_messages`** — those items are already committed in
SAP, and the order-derived fields are left empty rather than guessed. Re-send only what is listed in
`failed_items`; re-sending the whole payload duplicates every line that succeeded.

## Limits and side effects

* **Writes to SAP.** Adds, changes and deletes are immediate and not transactional across items.
* Re-running the same call after a partial failure **duplicates** the items that already succeeded.
* Concurrent call-offs from the same contract cannot be parallelised: SAP locks the source document during each copy, so two agents working the same contract will collide regardless of pacing.
* Lock retries use exponential backoff (1 s, 2 s, 4 s). Retrying at the pacing interval does not work — it lands inside the same lock window.

## Expected errors

| Error                       | Meaning                                                                                                                             |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `allow_item_delete` message | Deletion requested but not enabled for this configured tool.                                                                        |
| `SDSLS_INTEGRATION/010`     | Only one half of the reference pair was supplied. Validated locally before the call.                                                |
| `SLS_LORD/025`              | A field is not editable on that item in its current state — commonly `material` sent alongside a reference.                         |
| `V1/042`                    | The sales order or the source contract was locked. Retried automatically; surfaces as `retryable: true` if the budget is exhausted. |
| `SLS_LORD/006`              | The order type requires a reference document and none was supplied.                                                                 |

## Notes

Customer-specific extension fields (`ZZ1_*` / `YY1_*`) are **not** supported. An earlier version
exposed one such field; it was removed because it exists on only one tenant and made the request
fail everywhere else.
