feat: auto-detect invoice type (BT-3) from title (Teilrechnung->326)

'Teilrechnung' im Rechnungstitel setzt den Rechnungstyp automatisch auf 326, 'Korrekturrechnung'
auf 384; sonst 380. Das Dropdown ist mit dem erkannten Typ vorbelegt und bleibt aenderbar.
Verifiziert gegen 7 echte Rechnungen (ZenIT -> 326, alle anderen -> 380).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
dfuhrmann3 2026-07-13 15:08:56 +02:00
parent ac233baa2f
commit 71bb9885c6
2 changed files with 26 additions and 3 deletions

View File

@ -395,6 +395,22 @@ def detect_contract_type(text):
return ""
# Rechnungstyp (BT-3) an Schluesselwoertern im Titel/Text erkennen -> UN/UNTDID-1001-Code.
_INVOICE_TYPE_KEYWORDS = [
(re.compile(r"\bTeilrechnung\b", re.IGNORECASE), "326"), # Teilrechnung
(re.compile(r"\bKorrekturrechnung\b", re.IGNORECASE), "384"), # Korrekturrechnung
]
def detect_invoice_type_code(text):
"""Erkennt den Rechnungstyp (BT-3) an Schluesselwoertern im Rechnungstext (z.B. 'Teilrechnung'
-> 326, 'Korrekturrechnung' -> 384). Gibt sonst '380' (Handelsrechnung) zurueck."""
for pattern, code in _INVOICE_TYPE_KEYWORDS:
if pattern.search(text):
return code
return "380"
SERIAL_NUMBER_PATTERN = re.compile(
r"(?:S/?N|Seriennummer|Serial(?:\s*No\.?)?)\s*:?\s*([A-Z0-9][A-Z0-9\-]{4,})",
re.IGNORECASE,

13
main.py
View File

@ -29,6 +29,7 @@ from invoice_logic import (
compute_invoice_totals,
extract_service_period,
detect_contract_type,
detect_invoice_type_code,
extract_hardware_serial_numbers,
extract_angebot_reference,
extract_pre_position_freetext,
@ -245,6 +246,8 @@ with col2:
final_data["contract_type"] = detect_contract_type(pdf_text)
final_data["hardware_serials"] = extract_hardware_serial_numbers(pdf_text)
# Rechnungstyp (BT-3) aus dem Titel vorerkennen (z.B. 'Teilrechnung' -> 326).
final_data["invoice_type_code"] = detect_invoice_type_code(pdf_text)
# Vorlauftext (BT-22) deterministisch aus dem PDF-Text lesen statt vom (oft
# unvollstaendigen) LLM: alles zwischen Tabellenkopf und erster Position, ohne die
@ -315,11 +318,15 @@ with col2:
with tab_basis:
# --- BT-3 RECHNUNGSTYP DROPDOWN-MENÜ ---
_type_options = ["380 (Handelsrechnung)", "381 (Gutschrift)", "384 (Korrekturrechnung)", "326 (Teilrechnung)"]
_detected_type = str(data.get("invoice_type_code", "380"))
_type_index = next((i for i, o in enumerate(_type_options) if o.startswith(_detected_type)), 0)
inv_type_ui = st.selectbox(
"Rechnungstyp (BT-3)",
options=["380 (Handelsrechnung)", "381 (Gutschrift)", "384 (Korrekturrechnung)", "326 (Teilrechnung)"],
index=0,
help="Bestimmt den steuerrechtlichen Belegtyp im XML-Header."
options=_type_options,
index=_type_index,
help="Bestimmt den steuerrechtlichen Belegtyp im XML-Header. Wird aus dem Rechnungstitel "
"vorerkannt (z.B. 'Teilrechnung' -> 326) und ist hier änderbar."
)
selected_type_code = inv_type_ui.split(" ")[0]