2025-04-12 15:56:29 +02:00
|
|
|
from datetime import date, timedelta
|
2025-04-12 11:55:18 +02:00
|
|
|
from enum import StrEnum
|
2025-04-12 13:04:26 +02:00
|
|
|
from typing import Any, Callable, Optional
|
2025-04-12 11:55:18 +02:00
|
|
|
from pydantic import BaseModel
|
|
|
|
|
2025-04-12 13:38:43 +02:00
|
|
|
from validation.from_account import FromAccount
|
|
|
|
from validation.from_description import FromDescription
|
|
|
|
from validation.from_passport import FromPassport
|
|
|
|
from validation.from_profile import FromProfile
|
|
|
|
|
2025-04-12 12:01:02 +02:00
|
|
|
|
|
|
|
|
2025-04-12 13:04:26 +02:00
|
|
|
class ExtractedData(BaseModel):
|
2025-04-12 11:55:18 +02:00
|
|
|
account: FromAccount
|
|
|
|
description: FromDescription
|
|
|
|
passport: FromPassport
|
|
|
|
profile: FromProfile
|
|
|
|
|
2025-04-12 13:04:26 +02:00
|
|
|
|
2025-04-12 11:55:18 +02:00
|
|
|
class DocType(StrEnum):
|
|
|
|
account = "account"
|
|
|
|
description = "description"
|
|
|
|
passport = "passport"
|
|
|
|
profile = "profile"
|
|
|
|
|
|
|
|
|
2025-04-12 13:04:26 +02:00
|
|
|
class XValFailure(BaseModel):
|
2025-04-12 11:55:18 +02:00
|
|
|
doc1_type: DocType
|
|
|
|
doc1_val: str
|
|
|
|
|
|
|
|
doc2_type: DocType
|
|
|
|
doc2_val: str
|
|
|
|
|
|
|
|
|
2025-04-12 13:04:26 +02:00
|
|
|
def xval_name_account_description(data: ExtractedData) -> Optional[XValFailure]:
|
2025-04-12 13:42:16 +02:00
|
|
|
if data.account.account_name != data.description.full_name:
|
2025-04-12 13:04:26 +02:00
|
|
|
return XValFailure(
|
|
|
|
doc1_type=DocType.account,
|
|
|
|
doc1_val=f"{data.account.account_holder_name=}",
|
|
|
|
doc2_type=DocType.description,
|
|
|
|
doc2_val=f"{data.description.full_name=}",
|
2025-04-12 11:55:18 +02:00
|
|
|
)
|
|
|
|
|
2025-04-12 13:04:26 +02:00
|
|
|
|
|
|
|
def xval_email_account_profile(data: ExtractedData) -> Optional[XValFailure]:
|
|
|
|
if data.account.email != data.profile.email:
|
|
|
|
return XValFailure(
|
|
|
|
doc1_type=DocType.account,
|
|
|
|
doc1_val=f"{data.account.email=}",
|
|
|
|
doc2_type=DocType.profile,
|
|
|
|
doc2_val=f"{data.profile.email=}"
|
|
|
|
)
|
|
|
|
|
2025-04-12 14:20:40 +02:00
|
|
|
def xval_passport_no_account_passport(data: ExtractedData) -> Optional[XValFailure]:
|
|
|
|
if data.account.passport_number != data.passport.passport_number:
|
|
|
|
return XValFailure(
|
|
|
|
doc1_type=DocType.account,
|
|
|
|
doc1_val=f"{data.account.passport_number=}",
|
|
|
|
doc2_type=DocType.passport,
|
|
|
|
doc2_val=f"{data.passport.passport_number=}"
|
|
|
|
)
|
2025-04-12 13:04:26 +02:00
|
|
|
|
2025-04-12 15:56:29 +02:00
|
|
|
def birth_date_to_age(birth_date: date) -> int:
|
|
|
|
today = date.today()
|
|
|
|
return today.year - birth_date.year - ((today.month, today.day) < (birth_date.month, birth_date.day))
|
|
|
|
|
|
|
|
def xval_age_description_passport(data: ExtractedData) -> Optional[XValFailure]:
|
|
|
|
age_from_birth_date = birth_date_to_age(data.passport.birth_date)
|
|
|
|
if data.description.age != age_from_birth_date:
|
|
|
|
return XValFailure(
|
|
|
|
doc1_type=DocType.description,
|
|
|
|
doc1_val=f"{data.description.age=}",
|
|
|
|
doc2_type=DocType.passport,
|
|
|
|
doc2_val=f"{data.passport.birth_date=}"
|
|
|
|
)
|
|
|
|
|
2025-04-12 14:20:40 +02:00
|
|
|
def xval_all(data: ExtractedData) -> list[XValFailure]:
|
2025-04-12 13:04:26 +02:00
|
|
|
xref_validators: list[Callable[[ExtractedData], Optional[XValFailure]]] = [
|
2025-04-12 14:20:40 +02:00
|
|
|
xval_name_account_description,
|
|
|
|
xval_email_account_profile,
|
2025-04-12 15:56:29 +02:00
|
|
|
xval_passport_no_account_passport,
|
|
|
|
xval_age_description_passport
|
2025-04-12 13:04:26 +02:00
|
|
|
]
|
2025-04-12 11:55:18 +02:00
|
|
|
|
|
|
|
validation_failures = []
|
|
|
|
for validator in xref_validators:
|
2025-04-12 13:04:26 +02:00
|
|
|
failure = validator(data)
|
|
|
|
if not failure is None:
|
|
|
|
validation_failures.append(failure)
|
|
|
|
return validation_failures
|