fix: extract tax number, price basis quantity, spaced VAT IDs and contact email
- 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
This commit is contained in:
+18
-5
@@ -19,13 +19,13 @@ def validate_pflichtfelder(xml_data: XmlData) -> list[ErrorDetail]:
|
||||
"""Check required fields are present."""
|
||||
errors = []
|
||||
|
||||
def add_error(field: str, severity: str) -> None:
|
||||
def add_error(field: str, severity: str, message: str | None = None) -> None:
|
||||
errors.append(
|
||||
ErrorDetail(
|
||||
check="pflichtfelder",
|
||||
field=field,
|
||||
error_code="missing_required",
|
||||
message=f"Required field '{field}' is missing or empty",
|
||||
message=message or f"Required field '{field}' is missing or empty",
|
||||
severity=severity,
|
||||
)
|
||||
)
|
||||
@@ -40,8 +40,20 @@ def validate_pflichtfelder(xml_data: XmlData) -> list[ErrorDetail]:
|
||||
if not xml_data.supplier.name or not xml_data.supplier.name.strip():
|
||||
add_error("supplier.name", "critical")
|
||||
|
||||
if not xml_data.supplier.vat_id or not xml_data.supplier.vat_id.strip():
|
||||
add_error("supplier.vat_id", "critical")
|
||||
# EN 16931 BR-CO-26: seller identified by VAT ID (BT-31) OR tax number (BT-32)
|
||||
has_vat_id = bool(xml_data.supplier.vat_id and xml_data.supplier.vat_id.strip())
|
||||
has_tax_number = bool(
|
||||
xml_data.supplier.tax_number and xml_data.supplier.tax_number.strip()
|
||||
)
|
||||
if not has_vat_id and not has_tax_number:
|
||||
add_error(
|
||||
"supplier.vat_id",
|
||||
"critical",
|
||||
message=(
|
||||
"Supplier must have a VAT ID (supplier.vat_id) "
|
||||
"or a tax number (supplier.tax_number)"
|
||||
),
|
||||
)
|
||||
|
||||
if not xml_data.buyer.name or not xml_data.buyer.name.strip():
|
||||
add_error("buyer.name", "critical")
|
||||
@@ -163,7 +175,8 @@ def validate_ustid(vat_id: str) -> ErrorDetail | None:
|
||||
severity="critical",
|
||||
)
|
||||
|
||||
vat_id = vat_id.strip()
|
||||
# Whitespace inside VAT IDs is formatting only (e.g. "DE 140 978 617")
|
||||
vat_id = re.sub(r"\s+", "", vat_id)
|
||||
|
||||
# German VAT ID: DE followed by 9 digits
|
||||
if vat_id.startswith("DE"):
|
||||
|
||||
Reference in New Issue
Block a user