You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Filters on calculated GI columns are refused before reaching Acumatica. A $filter that references a calculated column (an =… expression in the GI design) makes Acumatica return HTTP 200 with an empty body — not an error, not an empty list. This was the single largest remaining error class: production logs attribute 279 empty-body occurrences (~14% of tool errors) almost entirely to acumatica_run_inquiry, and the cause was reproduced live three times (a filter on a stored column works; adding and <ExpressionColumn> ne 0 fails with the empty body).
The GI registry now flags expression columns (GiFieldMeta.expression), set during the positional alignment from the design row's Field starting with =. Flags are attached only where a design row was actually aligned to the property — a GI whose alignment was refused carries none, because a mis-placed flag would refuse filters on a perfectly filterable stored column.
acumatica_run_inquiry pre-flights filterExpression with filterReferencedColumns() (src/lib/odata-v4-errors.ts — string-literal-safe, case-sensitive identifier match, unit-tested) and returns a buildCalculatedColumnRefusal() envelope without contacting Acumatica: names the offending columns, lists the stored filterableFields to rewrite against, and states the query never executed so a refusal can't be reported as "no records matched".
acumatica_describe_inquiry marks such fields calculated: true and warns in its note that they cannot be filtered; both tools' descriptions carry the same guidance.
Uncurated GIs (gate inactive, or a refused alignment) still hit the raw empty body; parseAcumaticaJson()'s anomaly report (0.44.0) remains the backstop there.
Changed
align_columns.mjs brought back in sync with the server aligner. The skill script (skills/acumatica-gi-descriptions/scripts/align_columns.mjs) now carries the 0.48.2 rejection rules — declared-type constraint (expectedTypeFamily/typeConflicts), the weak shared-token tiebreak, DP optimal-solution counting, hoist-assignment ambiguity refusal, and the final pair sweep — so it no longer reports success on alignments the server rejects. A tied optimum stops the dropped-column search rather than escalating it (a higher drop count that happens to align is a free parameter rationalising a wrong mapping) and reports alignment_ambiguous with the caption-pinning remedy. Verified against the production feed: reproduces the hand-checked hoists on AP-Bills and Adjustments ({1,2,6,33}) and SO-Invoice ({1,2,6,22}, Amount ← curyOrigDocAmt), and refuses the same under-determined GIs the server does.