vettri06's picture
Deploy containerized Document Intelligence Space
c1b1f3a verified
Raw History Blame Contribute Delete
2.36 kB
from typing import Dict, Any, Tuple, List
import re
from datetime import datetime
from pydantic import BaseModel, Field
class ValidationResult(BaseModel):
is_valid: bool
errors: List[str] = Field(default_factory=list)
confidence_penalty: float = 0.0
def validate_extracted_fields(doc_class: str, fields: Dict[str, Any]) -> ValidationResult:
"""
Validates extracted field values based on business rules:
- total_amount: numeric, > 0
- date / invoice_date: valid date pattern
- invoice_number: non-empty string
Returns ValidationResult with pass/fail and penalty.
"""
errors = []
penalty = 0.0
if doc_class in ["invoice", "receipt"]:
amount_val = fields.get("total_amount")
if amount_val is not None:
# Clean currency symbols and commas
cleaned_str = re.sub(r'[^\d.-]', '', str(amount_val).replace(',', ''))
try:
amt = float(cleaned_str)
if amt <= 0:
errors.append(f"total_amount must be positive: got {amt}")
penalty += 0.25
except ValueError:
errors.append(f"total_amount cannot be parsed as float: {amount_val}")
penalty += 0.35
date_val = fields.get("date") or fields.get("invoice_date")
if date_val is not None:
# Check standard date formats
valid_date = False
date_str = str(date_val).strip()
date_formats = ["%Y-%m-%d", "%d/%m/%Y", "%m/%d/%Y", "%d-%m-%Y", "%Y/%m/%d", "%b %d, %Y", "%d %b %Y"]
for fmt in date_formats:
try:
datetime.strptime(date_str, fmt)
valid_date = True
break
except ValueError:
pass
# Also check with date regex
if not valid_date and not re.search(r'\d{1,4}[/\-.]\d{1,2}[/\-.]\d{1,4}', date_str):
errors.append(f"date format unrecognized: {date_val}")
penalty += 0.2
if doc_class == "invoice":
inv_num = fields.get("invoice_number")
if inv_num is not None and not str(inv_num).strip():
errors.append("invoice_number is empty")
penalty += 0.3
is_valid = len(errors) == 0
return ValidationResult(is_valid=is_valid, errors=errors, confidence_penalty=min(penalty, 0.5))