Skip to content

fix(gaeb): serialize position type, qty splits & long text on write - #26

Merged
kalyanakannan merged 2 commits into
mainfrom
add-cla
Jul 22, 2026
Merged

fix(gaeb): serialize position type, qty splits & long text on write#26
kalyanakannan merged 2 commits into
mainfrom
add-cla

Conversation

@kalyanakannan

Copy link
Copy Markdown
Contributor

A €50,000 bid could export as €121,000. _add_item never serialized Item.item_type, so every Bedarfs-/Alternativ-/Zuschlags-/Textposition was written as a Normalposition and its price silently joined the sum on re-read. The parser had the mirror defect: _detect_item_type recognised only pyGAEB-internal names that no real GAEB exporter emits, so a genuine tender's Bedarfspositionen were already mis-read as Normal on import.

Fixes (all in the _add_item write path + _detect_item_type read path):

  • item_type now serialized. Writer emits the real GAEB marker ( for Bedarfs-/Eventualposition, for Pauschalposition); non-standard types use a pyGAEB-internal marker WITH a warning that it is not yet interoperable. Blast radius covered X84 bid, X86 contract, X83 tender issue.
  • Parser reads the real tgItem markers (, , …) in addition to the legacy synthetic forms. Parser and writer now share one mapping table (pygaeb/models/position_types.py) so they cannot drift again.
  • qty_splits (QtySplit) now round-trip instead of being dropped on write.
  • Long text no longer compounds: the parser stores inner content only (was storing the wrapping tag, which the writer then re-wrapped, nesting a layer deeper each round trip) and the writer falls back to plain_text so plaintext long texts are no longer dropped.

Canonical element names pinned against the official GAEB tgItem schema + Fachdokumentation 3.3 (see docs/reference/position-types.md). New field-level round-trip tests assert per-item item_type, sum inclusion, qty_splits, and long-text stability — the old round-trip test asserted only item count and passed while all four defects fired.

A €50,000 bid could export as €121,000. _add_item never serialized
Item.item_type, so every Bedarfs-/Alternativ-/Zuschlags-/Textposition was
written as a Normalposition and its price silently joined the sum on re-read.
The parser had the mirror defect: _detect_item_type recognised only
pyGAEB-internal names that no real GAEB exporter emits, so a genuine tender's
<Provis> Bedarfspositionen were already mis-read as Normal on import.

Fixes (all in the _add_item write path + _detect_item_type read path):

- item_type now serialized. Writer emits the real GAEB marker (<Provis> for
  Bedarfs-/Eventualposition, <LumpSumItem> for Pauschalposition); non-standard
  types use a pyGAEB-internal marker WITH a warning that it is not yet
  interoperable. Blast radius covered X84 bid, X86 contract, X83 tender issue.
- Parser reads the real tgItem markers (<Provis>, <LumpSumItem>, …) in addition
  to the legacy synthetic forms. Parser and writer now share one mapping table
  (pygaeb/models/position_types.py) so they cannot drift again.
- qty_splits (QtySplit) now round-trip instead of being dropped on write.
- Long text no longer compounds: the parser stores inner content only (was
  storing the wrapping <LongText> tag, which the writer then re-wrapped, nesting
  a layer deeper each round trip) and the writer falls back to plain_text so
  plaintext long texts are no longer dropped.

Canonical element names pinned against the official GAEB tgItem schema +
Fachdokumentation 3.3 (see docs/reference/position-types.md). New field-level
round-trip tests assert per-item item_type, sum inclusion, qty_splits, and
long-text stability — the old round-trip test asserted only item count and
passed while all four defects fired.
@kalyanakannan
kalyanakannan merged commit 0a10190 into main Jul 22, 2026
6 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 22, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant