Files
james.maesandClaude Opus 5.5 4f8916246a feat: phase g - EDIFACT
- EDIFACT envelope reader and writer (UNA, UNB/UNZ, UNG/UNE, UNH/UNT,
  release-character escaping, syntax 3 and 4) with envelope findings.
- Routing by UNB identities, EDIFACT control references and duplicate
  detection; mixed X12 and EDIFACT inbox processing.
- In-house baseline guides (D96A, D01B) for ORDERS, ORDRSP, DESADV,
  INVOIC and CONTRL; CONTRL generation and inbound reconciliation.
- Sample maps (ORDERS in; ORDRSP, DESADV, INVOIC out) and demo partner
  Lindqvist Retail AB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 08:26:05 -05:00

6.0 KiB
Raw Permalink Blame History

EDI maps

A map comprises an edi_map row and ordered edi_map_rule rows. EDI paths resolve through the guide's loop tree; target paths support one association level. condition, defaultValue and required apply within each loop occurrence. Missing optional values preserve child alignment.

transformArgs is a JSON object with string values. Omitted transforms copy the first value.

An inbound ediPath may join several element paths with + (outside any [...] predicate); their values are concatenated in order. This is how a date and a time held in separate elements reach DATETIME: G62[G6201=10]/G6202+G62[G6201=10]/G6204. Inside a [*] loop path only the part after the anchor is split (S5[*]/G6202+G6204). A condition such as present(G62[G6201=10]/G6202) skips the rule when the elements are absent; a transform with no input otherwise fails the rule.

Transform Arguments / result
DATE CCYYMMDD or YYMMDD; fixed 1950–2049 century window; QQQ date
TIME HHMM, HHMMSS, fractional seconds; normalized string
DATETIME Date and time values, or time argument; timezone defaults UTC
DATEPART / TIMEPART Outbound halves of a DATETIME: a QQQ timestamp (an instant, an offset timestamp, or a zone-less one read as UTC) rendered as CCYYMMDD or HHMMSS in the timezone argument (default UTC)
DECIMAL scale implied decimal places, default 0
QUALIFIER Sibling predicate in ediPath, e.g. N1[N101=ST]/N104
CODE Map-local translation object, e.g. {"EA":"each","CA":"case"}
UNIT factor, divisor, scale (defaults 1, 1, 6), HALF_UP
CONSTANT value; needs no EDI input
CONCAT separator, default empty; joins selected values
SPLIT Literal separator (comma), zero-based index (0)
SUBSTRING Zero-based start inclusive, end exclusive
TRIM / UPPER Whitespace trim / locale-independent uppercase
LOOKUP table, key, result (default id); exactly one permitted row
SEQUENCE Outbound loop occurrence, starting at start (default 1)
HL Outbound HL01 counter, HL02 nearest parent, HL03 code, HL04 child indicator

Supply the partner timezone explicitly for DATETIME. UNIT uses configured conversion factors/pack sizes; host-dependent field lookups and code-list translation can register named transforms through EdiRuntime.current().transforms().register(name, transform). Transforms execute as the service session. LOOKUP explicitly enforces permissions.

Samples reference encrypted PayloadStore objects. Preview JSON contains values and recursive associations; expectedResultJson uses the same shape. Comparisons show structured before/after JSON as Result lines. Preview never invokes target application. See the synthetic 850 resources under src/main/resources/edi/maps and GUIDE-FORMAT.md.

Outbound maps

OUTBOUND rules are evaluated in sequence order. EDI path prefixes create nested loop scopes; the directly mapped QQQ association drives each occurrence. Nested QQQ paths such as cartons.items.sku are supported and fetched recursively by the worker. Constants within a loop can carry an association field as qqqPath to identify their scope. See the 856 samples for Shipment/Order/Pack/Item loops and parent numbering.

DATE/TIME format QQQ values as X12 dates/times; DECIMAL multiplies by the implied scale. Other registered transforms operate on the source value. Conditions use the existing EDI rule language over segments already emitted. A missing required mapping input fails mapping; structurally invalid mapped output opens VALIDATION and is never sent. ST/SE or UNH/UNT are generated by the mapper; the worker allocates controls. Component-target paths use -, for example LIN03-1 and LIN03-2, and retain components separately so the EDIFACT writer can escape data.

Warehouse and logistics samples

Phase d adds baseline guides and sample maps for four documents; test sources define the synthetic sample_wms_*, sample_shipment_status and sample_load* tables. Maps with a second direction use an -in or -out file suffix.

File Direction Target Business key
940-*-sample.json INBOUND sample_wms_order + lines W0502 (secondary W0503)
945-*-sample.json / 945-in-* OUTBOUND / INBOUND sample_wms_shipment + lines W0602
214-*-sample.json INBOUND sample_shipment_status (flat, first LX event) B1002 (secondary B1001)
204-*-sample.json / 204-out-* INBOUND / OUTBOUND sample_load + stops B204

Order dates and appointments arrive as DATETIME from a qualified G62 (G62[G6201=10]/...) or from the stop's G62 and leave as DATEPART plus TIMEPART. The 204 stop address is read from the nested loop (S5[*]/S5N1/N102; the guide gives the stop-level N1 loop its own id, S5N1, so it does not collide with the header N1 loop) and the stop sequence is mapped from S501. A 214 can carry several LX events; the sample map records the first (LX[1]/...) and a host that wants all of them maps an association instead. Optional outbound qualifiers such as MAN01 and L1102 are constants, so the sample source rows must carry the value they qualify (the carton SSCC, the bill of lading).

EDIFACT retail samples

Each of D96A and D01B includes ORDERS-<version>-sample.json inbound to sample_order and lines, and outbound ORDRSP from sample_order, DESADV from sample_shipment with cartons.items, and INVOIC from sample_invoice with lines. Test sources define these synthetic tables. ORDERS carries its business key in BGM02, date in qualified DTM01 component 2, buyer in qualified NAD02 component 1, and items in SG25. BGM's document codes are 220, 231, 351 and 380 respectively. These subsets intentionally carry only the fields exercised by the samples.

Composite paths address values, not delimiter-joined strings. An identifier containing +, : or ' remains a single value; the writer supplies release escapes. The outbound agreement owns UNA settings. Separate map resources per directory keep future version-specific changes isolated.