Allow zero-euro line item amounts
This commit is contained in:
+20
-9
@@ -5,6 +5,7 @@ import time
|
||||
from typing import Any
|
||||
|
||||
from pydantic import ValidationError
|
||||
|
||||
from src.models import (
|
||||
ErrorDetail,
|
||||
ValidateRequest,
|
||||
@@ -78,10 +79,10 @@ def validate_pflichtfelder(xml_data: XmlData) -> list[ErrorDetail]:
|
||||
if item.quantity == 0:
|
||||
add_error(f"{field_prefix}.quantity", "critical")
|
||||
|
||||
if item.unit_price == 0:
|
||||
if item.unit_price is None:
|
||||
add_error(f"{field_prefix}.unit_price", "critical")
|
||||
|
||||
if item.line_total == 0:
|
||||
if item.line_total is None:
|
||||
add_error(f"{field_prefix}.line_total", "critical")
|
||||
|
||||
if item.vat_rate is None:
|
||||
@@ -94,7 +95,7 @@ def validate_betraege(xml_data: XmlData) -> list[ErrorDetail]:
|
||||
"""Check amount calculations are correct."""
|
||||
errors = []
|
||||
|
||||
def add_mismatch(field: str, expected: float, actual: float) -> None:
|
||||
def add_mismatch(field: str, expected: float, actual: float | None) -> None:
|
||||
errors.append(
|
||||
ErrorDetail(
|
||||
check="betraege",
|
||||
@@ -107,16 +108,24 @@ def validate_betraege(xml_data: XmlData) -> list[ErrorDetail]:
|
||||
|
||||
# Check line_total = quantity × unit_price
|
||||
for idx, item in enumerate(xml_data.line_items):
|
||||
expected_line_total = item.quantity * item.unit_price
|
||||
if not amounts_match(item.line_total, expected_line_total):
|
||||
unit_price = item.unit_price
|
||||
line_total = item.line_total
|
||||
if unit_price is None or line_total is None:
|
||||
continue
|
||||
|
||||
expected_line_total = item.quantity * unit_price
|
||||
if not amounts_match(line_total, expected_line_total):
|
||||
add_mismatch(
|
||||
f"line_items[{idx}].line_total",
|
||||
expected_line_total,
|
||||
item.line_total,
|
||||
line_total,
|
||||
)
|
||||
|
||||
# Check totals.net = sum(line_items.line_total)
|
||||
line_total_sum = sum(item.line_total for item in xml_data.line_items)
|
||||
line_total_sum = 0.0
|
||||
for item in xml_data.line_items:
|
||||
if item.line_total is not None:
|
||||
line_total_sum += item.line_total
|
||||
if not amounts_match(xml_data.totals.net, line_total_sum):
|
||||
add_mismatch("totals.net", line_total_sum, xml_data.totals.net)
|
||||
|
||||
@@ -280,12 +289,14 @@ def validate_invoice(request: ValidateRequest) -> ValidationResult:
|
||||
xml_data = XmlData(**request.xml_data)
|
||||
except ValidationError as e:
|
||||
# Convert Pydantic validation errors to ValidationResult
|
||||
validation_errors = []
|
||||
validation_errors: list[ErrorDetail] = []
|
||||
for error in e.errors():
|
||||
loc = error["loc"]
|
||||
field = str(loc[0]) if loc else None
|
||||
validation_errors.append(
|
||||
ErrorDetail(
|
||||
check="schema_validation",
|
||||
field=error["loc"][0] if error["loc"] else None,
|
||||
field=field,
|
||||
error_code=error["type"],
|
||||
message=error["msg"],
|
||||
severity="critical",
|
||||
|
||||
Reference in New Issue
Block a user