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:
parent
ac233baa2f
commit
71bb9885c6
|
|
@ -395,6 +395,22 @@ def detect_contract_type(text):
|
||||||
return ""
|
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(
|
SERIAL_NUMBER_PATTERN = re.compile(
|
||||||
r"(?:S/?N|Seriennummer|Serial(?:\s*No\.?)?)\s*:?\s*([A-Z0-9][A-Z0-9\-]{4,})",
|
r"(?:S/?N|Seriennummer|Serial(?:\s*No\.?)?)\s*:?\s*([A-Z0-9][A-Z0-9\-]{4,})",
|
||||||
re.IGNORECASE,
|
re.IGNORECASE,
|
||||||
|
|
|
||||||
13
main.py
13
main.py
|
|
@ -29,6 +29,7 @@ from invoice_logic import (
|
||||||
compute_invoice_totals,
|
compute_invoice_totals,
|
||||||
extract_service_period,
|
extract_service_period,
|
||||||
detect_contract_type,
|
detect_contract_type,
|
||||||
|
detect_invoice_type_code,
|
||||||
extract_hardware_serial_numbers,
|
extract_hardware_serial_numbers,
|
||||||
extract_angebot_reference,
|
extract_angebot_reference,
|
||||||
extract_pre_position_freetext,
|
extract_pre_position_freetext,
|
||||||
|
|
@ -245,6 +246,8 @@ with col2:
|
||||||
|
|
||||||
final_data["contract_type"] = detect_contract_type(pdf_text)
|
final_data["contract_type"] = detect_contract_type(pdf_text)
|
||||||
final_data["hardware_serials"] = extract_hardware_serial_numbers(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
|
# Vorlauftext (BT-22) deterministisch aus dem PDF-Text lesen statt vom (oft
|
||||||
# unvollstaendigen) LLM: alles zwischen Tabellenkopf und erster Position, ohne die
|
# unvollstaendigen) LLM: alles zwischen Tabellenkopf und erster Position, ohne die
|
||||||
|
|
@ -315,11 +318,15 @@ with col2:
|
||||||
|
|
||||||
with tab_basis:
|
with tab_basis:
|
||||||
# --- BT-3 RECHNUNGSTYP DROPDOWN-MENÜ ---
|
# --- 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(
|
inv_type_ui = st.selectbox(
|
||||||
"Rechnungstyp (BT-3)",
|
"Rechnungstyp (BT-3)",
|
||||||
options=["380 (Handelsrechnung)", "381 (Gutschrift)", "384 (Korrekturrechnung)", "326 (Teilrechnung)"],
|
options=_type_options,
|
||||||
index=0,
|
index=_type_index,
|
||||||
help="Bestimmt den steuerrechtlichen Belegtyp im XML-Header."
|
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]
|
selected_type_code = inv_type_ui.split(" ")[0]
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue