- test_fixture_sweep: extract+validate every fixture PDF on every run;
known extractor/validator gaps are catalogued explicitly and the sweep
fails on any deviation from that catalogue
- tests/fixtures/real/: anonymized XML from real production invoices that
revealed bugs (verified to contain no real-world data); first entry
locks in the FC-tax-number/basis-quantity/spaced-VAT-ID regressions
- CI workflow: uv sync --frozen from lockfile + pytest + docker build
The venv had drifted (python 3.14 interpreter with python 3.13 packages)
because uv.lock was never committed. Lockfile is now tracked and CI syncs
from it with --frozen.
- supplier/buyer: extract FC tax registration (BT-32/BT-49) into new
tax_number field; previously only VA (USt-IdNr.) was read
- pflichtfelder: critical error only when neither vat_id nor tax_number
is present (EN 16931 BR-CO-26)
- ustid: tolerate formatting whitespace inside VAT IDs (e.g. 'DE 140 978 617')
- line items: normalize unit price by basis quantity (BT-149), so a
price per 100 units no longer inflates line totals by factor 100
- supplier email: also look in DefinedTradeContact (BT-42)
- rewrite xrechnung fallback test to assert only our own behavior,
independent of factur-x version specifics
- Expose nixosModules.default in flake outputs for easy import
- Add argparse to main.py for --host and --port CLI flags
- Support priority: CLI args > env vars > defaults
Wave 2 tasks complete:
- Task 4: ZUGFeRD extractor with profile detection (factur-x)
- Task 5: PDF text parser with regex patterns
- Task 6: Utils with unit code mapping and tolerance checks
Features:
- extract_zugferd() extracts XML and text from PDFs
- parse_zugferd_xml() parses UN/CEFACT CII XML to models
- extract_from_text() extracts values using regex patterns
- translate_unit_code() maps UN/ECE codes to German
- amounts_match() checks with 0.01 EUR tolerance
- German number/date format handling
Tests: 27 utils tests, 27 pdf_parser tests, extractor tests