Skip to content

Commit a922104

Browse files
waleedlatif1claude
andcommitted
fix(sap_s4hana): preserve $ in OData query params; reject empty items array
- buildOdataUrl now constructs query strings manually with encodeURIComponent and restores literal "$" so OData system options ($filter, $top, $select, $expand, $orderby, $skip, $format) reach SAP and any intermediary proxies/WAFs as-is, not as "%24filter". URLSearchParams was percent-encoding "$" to "%24" which most ICMs decode but some intermediaries silently drop, returning unfiltered results. - create_sales_order now rejects an empty items array (matches create_purchase_requisition) so callers get a clear client-side error instead of an opaque SAP validation failure on the deep-insert. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent cd2fdf7 commit a922104

2 files changed

Lines changed: 6 additions & 5 deletions

File tree

apps/sim/app/api/tools/sap_s4hana/proxy/route.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -420,12 +420,13 @@ function buildOdataUrl(req: ProxyRequest, pathOverride?: string): string {
420420
if (!req.query || Object.keys(req.query).length === 0) {
421421
return base
422422
}
423-
const search = new URLSearchParams()
423+
const encode = (s: string) => encodeURIComponent(s).replace(/%24/g, '$')
424+
const parts: string[] = []
424425
for (const [key, value] of Object.entries(req.query)) {
425426
if (value === undefined || value === null) continue
426-
search.append(key, String(value))
427+
parts.push(`${encode(key)}=${encode(String(value))}`)
427428
}
428-
const queryString = search.toString()
429+
const queryString = parts.join('&')
429430
if (!queryString) return base
430431
return base.includes('?') ? `${base}&${queryString}` : `${base}?${queryString}`
431432
}

apps/sim/tools/sap_s4hana/create_sales_order.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ export const createSalesOrderTool: ToolConfig<CreateSalesOrderParams, SapProxyRe
125125
headers: () => ({ 'Content-Type': 'application/json' }),
126126
body: (params) => {
127127
const items = parseJsonInput<Array<Record<string, unknown>>>(params.items, 'items')
128-
if (!Array.isArray(items)) {
129-
throw new Error('items must be a JSON array of sales order item objects')
128+
if (!Array.isArray(items) || items.length === 0) {
129+
throw new Error('items must be a non-empty JSON array of sales order item objects')
130130
}
131131
const extra = parseJsonInput<Record<string, unknown>>(params.body, 'body') ?? {}
132132
const payload: Record<string, unknown> = {

0 commit comments

Comments
 (0)