fix(bt-10): fall back to customer number when no Leitweg-ID (BR-DE-15)

Validatoren bemaengelten leeres BT-10 (Kaeuferreferenz, in XRechnung Pflicht). BT-10 nutzt jetzt
die Leitweg-ID (Behoerden) und faellt sonst auf die Kundennummer zurueck - so ist das Feld nie
leer, BT-46 (Kundennummer) bleibt zusaetzlich erhalten. UI-Blocker/Hilfetext angepasst.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
dfuhrmann3 2026-07-13 15:29:57 +02:00
parent 1851ed7074
commit 308cddedef
2 changed files with 17 additions and 14 deletions

View File

@ -559,10 +559,11 @@ def generate_compliant_xrechnung(data):
ET.SubElement(root, f"{{{CBC}}}DocumentCurrencyCode").text = "EUR" ET.SubElement(root, f"{{{CBC}}}DocumentCurrencyCode").text = "EUR"
# BT-10 Käuferreferenz = Leitweg-ID: NUR bei Behörden-Rechnungen (B2G) vorhanden. Fehlt sie, # BT-10 Käuferreferenz = Leitweg-ID: NUR bei Behörden-Rechnungen (B2G) vorhanden. Fehlt sie,
# wird das Element weggelassen; bei XRechnung blockiert die UI den Export (BR-DE-15 Pflicht), # wird das Element weggelassen. BT-10 ist in XRechnung Pflicht (BR-DE-15), darf aber nie leer
# bei ZUGFeRD (B2B) bleibt es zulässigerweise leer. # sein: bei Behoerden (B2G) die Leitweg-ID, sonst als Fallback die Kundennummer.
if data.get("leitweg_id") and str(data["leitweg_id"]).strip() != "": _buyer_ref_bt10 = str(data.get("leitweg_id") or data.get("customer_number") or "").strip()
ET.SubElement(root, f"{{{CBC}}}BuyerReference").text = str(data["leitweg_id"]).strip() if _buyer_ref_bt10:
ET.SubElement(root, f"{{{CBC}}}BuyerReference").text = _buyer_ref_bt10
if data.get("service_start_date") and data.get("service_end_date"): if data.get("service_start_date") and data.get("service_end_date"):
period_elem = ET.SubElement(root, f"{{{CAC}}}InvoicePeriod") period_elem = ET.SubElement(root, f"{{{CAC}}}InvoicePeriod")
@ -837,10 +838,11 @@ def generate_compliant_zugferd_cii(data):
ET.SubElement(mon_sum, f"{{{RAM}}}LineTotalAmount").text = f"{item['total_amount']:.2f}" ET.SubElement(mon_sum, f"{{{RAM}}}LineTotalAmount").text = f"{item['total_amount']:.2f}"
header_agree = ET.SubElement(trade_trans, f"{{{RAM}}}ApplicableHeaderTradeAgreement") header_agree = ET.SubElement(trade_trans, f"{{{RAM}}}ApplicableHeaderTradeAgreement")
# BT-10 Käuferreferenz = Leitweg-ID: nur bei Behörden-Rechnungen (B2G). Fehlt sie, wird das # BT-10 Käuferreferenz: bei Behörden (B2G) die Leitweg-ID, sonst als Fallback die Kundennummer,
# Element weggelassen (bei ZUGFeRD/B2B zulässig; bei XRechnung blockiert die UI). # damit das in XRechnung verpflichtende Feld (BR-DE-15) nie leer bleibt.
if data.get("leitweg_id") and str(data["leitweg_id"]).strip() != "": _buyer_ref_bt10 = str(data.get("leitweg_id") or data.get("customer_number") or "").strip()
ET.SubElement(header_agree, f"{{{RAM}}}BuyerReference").text = str(data["leitweg_id"]).strip() if _buyer_ref_bt10:
ET.SubElement(header_agree, f"{{{RAM}}}BuyerReference").text = _buyer_ref_bt10
supplier_party = ET.SubElement(header_agree, f"{{{RAM}}}SellerTradeParty") supplier_party = ET.SubElement(header_agree, f"{{{RAM}}}SellerTradeParty")
ET.SubElement(supplier_party, f"{{{RAM}}}Name").text = VERKAEUFER["name"] ET.SubElement(supplier_party, f"{{{RAM}}}Name").text = VERKAEUFER["name"]

13
main.py
View File

@ -341,8 +341,9 @@ with col2:
leitweg_id = st.text_input( leitweg_id = st.text_input(
"Leitweg-ID (BT-10)", "Leitweg-ID (BT-10)",
value=data.get("leitweg_id", ""), value=data.get("leitweg_id", ""),
help="Nur für Behörden-Rechnungen (B2G). Bei XRechnung Pflicht (BR-DE-15) - dann die " help="Nur für Behörden-Rechnungen (B2G) die Leitweg-ID eintragen. Bleibt das Feld leer "
"Leitweg-ID der Behörde eintragen. Bei ZUGFeRD / B2B leer lassen.", "(normaler B2B-Fall), wird automatisch die Kundennummer als Käuferreferenz (BT-10) "
"verwendet - so bleibt das für XRechnung verpflichtende Feld nie leer.",
) )
buyer_ref = st.text_input( buyer_ref = st.text_input(
"Ihr Auftrag / Bestellnummer (BT-13)", "Ihr Auftrag / Bestellnummer (BT-13)",
@ -586,10 +587,10 @@ with col2:
if parse_to_strict_xml_date(inv_date) == "": if parse_to_strict_xml_date(inv_date) == "":
blocker.append("Rechnungsdatum (BT-2) fehlt oder ist unlesbar (erwartet: YYYY-MM-DD). " blocker.append("Rechnungsdatum (BT-2) fehlt oder ist unlesbar (erwartet: YYYY-MM-DD). "
"Bitte korrigieren - es wird KEIN Datum automatisch eingesetzt.") "Bitte korrigieren - es wird KEIN Datum automatisch eingesetzt.")
if is_xrechnung and not str(leitweg_id).strip(): if is_xrechnung and not str(leitweg_id).strip() and not str(cust_num).strip():
blocker.append("Leitweg-ID / Käuferreferenz (BT-10) fehlt. Bei XRechnung ist sie Pflicht " blocker.append("Käuferreferenz (BT-10) fehlt. Bei XRechnung ist sie Pflicht (BR-DE-15) - "
"(BR-DE-15) - für Behörden-Rechnungen bitte die Leitweg-ID eintragen. " "bitte die Leitweg-ID (Behörden) ODER mindestens die Kundennummer (BT-46) "
"(Bei ZUGFeRD/B2B ist das Feld optional.)") "eintragen; letztere wird sonst automatisch als Käuferreferenz verwendet.")
if is_xrechnung and not str(r_email).strip(): if is_xrechnung and not str(r_email).strip():
blocker.append("Elektronische Adresse des Kunden (BT-49) fehlt. Bei XRechnung ist sie " blocker.append("Elektronische Adresse des Kunden (BT-49) fehlt. Bei XRechnung ist sie "
"Pflicht (PEPPOL-EN16931-R010) - entweder E-Mail-Adresse oder Netzwerkcode " "Pflicht (PEPPOL-EN16931-R010) - entweder E-Mail-Adresse oder Netzwerkcode "