import re from typing import Optional from datetime import datetime from dateutil import parser def sanitize_amount(text: str) -> Optional[float]: """ Sanitizes a string representing an amount/number (e.g., "$1,234.56", "€ 50,000", "50 USD") by removing currency symbols, commas, and other non-numeric characters (except for the decimal separator), and casts it to a float. Args: text (str): The raw extracted text from the document. Returns: Optional[float]: The sanitized numeric value, or None if no number could be extracted. """ if not text: return None # Remove obvious alphabetic currency codes, spaces, and commas # We keep digits, period, and minus sign cleaned_text = re.sub(r'[^\d\.-]', '', text) if not cleaned_text: return None try: # Handle cases where multiple periods or dashes might exist incorrectly # We just try to cast to float. If the OCR produced something like "1.23.45", this will fail. # A more robust regex can handle exact capture if needed. # But this basic cast covers 95% of standard sanitized strings. return float(cleaned_text) except ValueError: return None def sanitize_date(text: str, field_type: str = 'DATE') -> Optional[str]: """ Sanitizes a string representing a date or datetime and converts it to ISO 8601 format. Args: text (str): The raw extracted text from the document. field_type (str): 'DATE' or 'DATETIME'. Determines the output format. Returns: Optional[str]: The sanitized date string in ISO format, or None if it could not be parsed. """ if not text: return None try: # dateutil.parser is very robust at handling formats like "Dec 11, 2020", "11/12/2020", etc. # fuzzy=True allows it to ignore extra words/characters around the date parsed_date = parser.parse(text, fuzzy=True) if field_type == 'DATETIME': return parsed_date.strftime('%Y-%m-%dT%H:%M:%S') else: return parsed_date.strftime('%Y-%m-%d') except (ValueError, TypeError, OverflowError): return None