视觉画布设计
canvas-design
基于设计原则创作静态视觉作品,用于海报与品牌图形。
s4hana-update-record【文档与办公】Update existing records in SAP S/4HANA Cloud Public or on-prem private edition via OData V2 PATCH. Use whenever the user wants to update, change, edit, modify, patch, set, rename, adjust, or correct any existing record on S/4HANA — purchase orders (dates, payment terms, item text/qty/price), business partners (name, address, payment terms, recon acco…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Generic update skill for SAP S/4HANA records. Verified pattern against <your-tenant>.s4hana.cloud.sap 2026-05-12 — 6 different entity types successfully PATCH'd; 2 confirmed entity-disabled; 1 "silent success" trap documented.
Verbs: update / change / edit / modify / patch / set / rename / adjust / correct / backdate / amend Objects: any existing S/4HANA record — PO, supplier, customer, BP, PIR, SES, product description, etc.
s4hana-create-* skillsBusinessPartnerIsBlocked=true etc.) instead.mcp-server/src/sap/.tmp/<user>-<YYYYMMDD-HHMM>/update-<entity>/. Never commit, never modify .env.Before any API call, before any tool use, do this check. Even if you already know credentials from earlier in the conversation — IGNORE that knowledge and re-check from scratch each invocation.
<current cwd>...".env file at ./.env (in the current working directory — NOT parent dirs, NOT ~/.env, NOT any memory file)SAP_HOST AND SAP_AUTH_MODE both present./.env from the bundled template (curl from https://raw.githubusercontent.com/ilia-inovaflow/s4hana-create-record-skills/main/.env.example), append .env to .gitignore if not already there, tell the user clearly what to fill in (auth mode + host + creds), and wait for them to say "ready" before making any API call. Never overwrite an existing .env.<host> in <auth-mode> mode. Proceeding with [task]."Never use credentials from conversation memory, from another project's .env, or from any tenant the user previously worked with in a different session. Each project gets its own .env. See shared/setup-check.md for the full rationale and edge cases.
Parse the user's intent:
PurchaseOrder='4500000020') or composite (e.g. PIR org-plant has 4 keys).PaymentTerms).If ambiguous, ask once before proceeding. Show the user your planned interpretation: "I'm going to update PO 4500000020's PurchaseOrderDate to 2025-08-15. Correct?"
For known entities, use the table below to find the right endpoint. For unknown entities, switch to research mode (Phase 1b).
If the entity isn't in the verified table:
$metadata lookup or search SAP API Hub.$metadata and inspect:sap:updatable="false" on properties (write-once fields)sap:creatable annotations (which fields appear in PATCH vs POST)references/mutable-fields-catalog.md for next time.GET /sap/opu/odata/sap/<SERVICE>/<EntityKey>?$select=<key fields + target fields>&$format=json
Authorization: Basic <auth>
Accept: application/json
Show user: "Current value of PurchaseOrderDate is 2026-04-30. Want me to change it to 2025-08-15?"
For batch operations, GET each record (or a sample) and show the user a table of planned changes before any PATCH.
PATCH /sap/opu/odata/sap/<SERVICE>/<EntityKey>?sap-client=<n>
Authorization: Basic <auth>
X-CSRF-Token: <captured>
Cookie: <captured>
Content-Type: application/json
Accept: application/json
{"<field>": "<new value>"}
PATCH semantics: partial update. Only send the field(s) you want to change — don't echo the full record. Body should be minimal.
Expected response: HTTP 204 No Content (success) or HTTP 400 with error.innererror.errordetails for failures.
GET /sap/opu/odata/sap/<SERVICE>/<EntityKey>?$select=<target fields>&$format=json
Compare BEFORE → AFTER for each field. Report to user:
PurchaseOrderDate: 2026-04-30 → 2025-08-15NetPriceAmount: 50.00 → 50.00 (silent failure — field may be read-only despite 204 response)After single or batch: summarize changes, surface any silent failures or rejections, write log to disk.
mcp-server/src/sap/.tmp/<user>-<YYYYMMDD-HHMM>/update-<entity>/
├── targets.json # records to update + proposed changes
├── before.json # GET-before snapshots
├── update-log.jsonl # one line per PATCH attempt
├── after.json # GET-after snapshots
├── diff.md # human-readable before/after table
└── results.json
See references/mutable-fields-catalog.md for the full per-entity catalog. Quick summary:
| Entity | Service | What works | Notes |
|---|---|---|---|
A_BusinessPartner | API_BUSINESS_PARTNER | OrganizationBPName1 and most header fields | Single key: BusinessPartner |
A_BusinessPartnerAddress | API_BUSINESS_PARTNER | CityName, StreetName, PostalCode, Country | Composite key: BusinessPartner + AddressID |
A_ProductDescription | API_PRODUCT_SRV | ProductDescription | Composite key: Product + Language. Useful for Toblerone-style overrides |
A_PurchaseOrder | API_PURCHASEORDER_PROCESS_SRV | PurchaseOrderDate, PaymentTerms, header text, most header fields | NOT Supplier, CompanyCode, PurchasingOrganization — write-once |
A_PurchaseOrderItem | API_PURCHASEORDER_PROCESS_SRV | PurchaseOrderItemText, NetPriceAmount, OrderQuantity, Plant, StorageLocation | NOT Material, PurchaseOrderItemCategory — write-once |
A_ServiceEntrySheet | API_SERVICE_ENTRY_SHEET_SRV | ServiceEntrySheetName, PostingDate (pre-approval) | After approval (workflow status changes), most fields lock |
A_PurgInfoRecdOrgPlantData | API_INFORECORD_PROCESS_SRV | Status fields, validity dates | TRAP: NetPriceAmount returns 204 but DOES NOT change — see known-traps.md. Price is in to_PurInfoRecdPrcgCndnValidity |
A_SupplierPurchasingOrg | API_BUSINESS_PARTNER | PaymentTerms, PurchaseOrderCurrency | Composite key: Supplier + PurchasingOrganization |
A_SupplierCompany | API_BUSINESS_PARTNER | PaymentTerms, ReconciliationAccount | Composite key: Supplier + CompanyCode |
Don't even try — these entities reject all PATCH with 405 CX_SADL_ENTITY_CUD_DISABLED. They need cancel-and-recreate flows:
| Entity | Why | Alternative |
|---|---|---|
A_SupplierInvoice | Posted invoices are immutable for audit | Cancel via Cancel_SupplierInvoice action + create new |
A_MaterialDocumentHeader (GR) | Material movements are immutable for inventory integrity | Reverse via movement type 102 (creates negative MatDoc) |
A_Product | Cloud Public locks Product master to MDG | Update via A_ProductDescription for description; A_ProductPlant for plant data |
references/mutable-fields-catalog.md — full per-entity table of what worksreferences/known-traps.md — the "204 looks like success but didn't change" casesreferences/key-resolution.md — how to construct keys for composite-key entities (PIR org-plant, BP address, etc.)references/cancel-vs-update.md — when to cancel-recreate vs PATCHscripts/safe-update.mjs — reference implementation with GET-PATCH-GET verify flow + dry-run mode