Metadata-Version: 2.3
Name: gaeb
Version: 0.5.4
Summary: Python library for reading, writing, converting and diffing GAEB files (AVA data exchange format, DA XML 2.0–3.3, GAEB 90, GAEB 2000)
Keywords: gaeb,ava,construction,leistungsverzeichnis,bau,gaeb90,gaeb2000,xml,excel,diff
Author: Attackwave
Author-email: Attackwave <attackwave@gmail.com>
License: MIT
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business
Requires-Dist: pydantic>=2.0
Requires-Dist: lxml>=4.9.4
Requires-Dist: pytest>=7.0 ; extra == 'dev'
Requires-Dist: pytest-cov>=4.0 ; extra == 'dev'
Requires-Dist: openpyxl>=3.1 ; extra == 'excel'
Requires-Python: >=3.10
Project-URL: Homepage, https://github.com/Attackwave/gaeb-python
Project-URL: Repository, https://github.com/Attackwave/gaeb-python
Project-URL: Issues, https://github.com/Attackwave/gaeb-python/issues
Project-URL: Changelog, https://github.com/Attackwave/gaeb-python/blob/main/CHANGELOG.md
Project-URL: CLI, https://pypi.org/project/gaeb-cli/
Provides-Extra: dev
Provides-Extra: excel
Description-Content-Type: text/markdown

# gaeb

Python-Bibliothek zum Lesen, Schreiben, Konvertieren und Vergleichen von **GAEB-Dateien** (AVA – Ausschreibung, Vergabe, Abrechnung im deutschen Bauwesen).

Für die Kommandozeile (info, show, convert, diff, validate) gibt es die zugehörige [`gaeb-cli`](https://pypi.org/project/gaeb-cli/): `pip install gaeb-cli`.

## Features

- **GAEB DA XML 2.0–3.3** lesen und schreiben (automatische Versionserkennung, Multi-Version Writer)
- **GAEB 90** lesen und schreiben (`.d80`–`.d89`; Encoding-Autoerkennung)
- **GAEB 2000** lesen und schreiben (`.p80`–`.p89`)
- **Alle Austauschphasen**: Mengenermittlung (31), Kostenermittlung (50–52), Vergabe (80–89, 83Z, 84Z, 86ZR, 86ZE), Handel/Handwerk (93–97)
- **BoQ Builder**: programmatischer LV-Aufbau mit Auto-OZ-Generierung und Fluent API
- **Excel-Export** (.xlsx) mit Hierarchie-Layout — optional via `pip install gaeb[excel]`
- **Document Diff**: zwei LVs vergleichen, alle Felder prüfen, finanzielle Auswirkungen berechnen
- **XSD-Validierung** gegen offizielle GAEB-Schemas (Phasen 80–87)
- **Preisspiegel- & Raumbuch-Modell** für Angebotsvergleiche und räumliche Zuordnung
- **Security-Hardened**: XXE-Prevention, Billion-Laughs-Schutz, Dateigrössen-Limit, Rekursionstiefenbegrenzung
- Einheitliches **Pydantic v2** Datenmodell für alle Formate

## Installation

```bash
pip install gaeb

# Mit Excel-Export
pip install gaeb[excel]
```

## Schnellstart

```python
import gaeb

# Lesen
lv = gaeb.read_xml("ausschreibung.x83")
lv = gaeb.read_gaeb90("ausschreibung.d83")
lv = gaeb.read_gaeb2000("ausschreibung.p83")

# Metadaten
print(lv.titel_lv)        # LV-Titel
print(lv.phase)           # Phase.ANGEBOTSAUFFORDERUNG
print(lv.xml_version)     # "3.3" (nur bei DA XML)
print(lv.encoding)        # "cp850" (nur bei GAEB 90 / 2000)
print(lv.gesamtsumme)     # Decimal oder None

# Positionen
for pos in lv.alle_positionen:
    print(pos.oz, pos.kurztext, pos.menge, pos.einheit)

# Schreiben / Konvertieren
gaeb.write_xml(lv, "ausgabe.x83")
gaeb.write_xml(lv, "ausgabe_v32.x83", version="3.2")  # explizite Version
gaeb.write_gaeb90(lv, "ausgabe.d83")
gaeb.write_gaeb2000(lv, "ausgabe.p83")

# Excel-Export
gaeb.write_excel(lv, "ausgabe.xlsx")
gaeb.write_excel(lv, "ausgabe.xlsx", langtext=True)

# Zwei LVs vergleichen
lv_neu = gaeb.read_xml("angebot.x84")
result = gaeb.compare(lv, lv_neu)

print(result.only_in_old)        # gelöschte OZ-Nummern
print(result.only_in_new)        # neue OZ-Nummern
for pc in result.changed:
    print(pc.oz, pc.changes)
print(result.gesamtsumme_diff)   # finanzielle Differenz

# XSD-Validierung
fehler = gaeb.validate("ausschreibung.x83")
if fehler:
    print(fehler)
```

## BoQ Builder

```python
import gaeb

lv = (
    gaeb.BoQBuilder(
        phase=gaeb.Phase.ANGEBOTSAUFFORDERUNG,
        titel_lv="Hochwasserschutz",
        projekt="Testprojekt",
    )
    .titel("Erdarbeiten")
        .position("Bodenaushub", einheit="m³", menge=250, ep="12.50")
        .position("Bodentransport", einheit="m³", menge=250, ep="8.00")
    .end()
    .titel("Betonarbeiten")
        .untertitel("Fundamente")
            .position("Streifenfundament", einheit="m³", menge=30, ep="185.00")
        .end()
    .end()
    .build()
)

gaeb.write_xml(lv, "ausschreibung.x83")
```

OZ-Generierung basiert auf dem `BoQBkdn`-Schema (Standard: 2+2+4 Zeichen):
- Titel: `01`, `02`, …
- Untertitel: `0101`, `0102`, …
- Position: `01000001`, `01010001`, …

## Datenmodell

```
Leistungsverzeichnis
  ├── phase: Phase
  ├── titel_lv, projekt, auftraggeber, auftragnehmer
  ├── waehrung, xml_version, encoding
  ├── vorbemerkungen: list[str]
  ├── zeitvertrag_typ: str | None
  ├── boq_bkdn: list[BoQBkdn]
  ├── gesamtsumme: Decimal | None  (property)
  └── titel: list[Titel]
        ├── nummer, kurztext, langtext
        ├── positionen: list[Position]
        │     ├── oz, kurztext, langtext
        │     ├── menge, einheit, einheitspreis
        │     ├── gesamtpreis  (property: menge × EP)
        │     ├── gesamtbetrag, mwst, nachlass_prozent
        │     ├── pauschale, entfaellt, nicht_angeboten
        │     ├── stundenlohn, schwerpunkt, provis
        │     ├── typ: PositionTyp
        │     ├── aln_gruppe, aln_nummer, ep_anteile
        │     └── periodqty, min_menge, max_menge  (Z-Phasen)
        └── untertitel: list[Titel]  (rekursiv)
```

## Unterstützte Phasen

| Bereich | Phasen |
|---------|--------|
| Mengenermittlung | 31 |
| Kostenermittlung | 50, 51, 52 |
| Vergabe (Procurement) | 80–89, 83Z, 84Z, 86ZR, 86ZE |
| Handel / Handwerk | 93–97 |

## Optionale Abhängigkeiten

| Extra | Paket | Feature |
|-------|-------|---------|
| `gaeb[excel]` | openpyxl ≥ 3.1 | Excel-Export (.xlsx) |

## Lizenz

MIT – siehe [LICENSE](https://github.com/Attackwave/gaeb-python/blob/main/LICENSE)
