from __future__ import annotations from datetime import date from decimal import Decimal from enum import StrEnum from pydantic import BaseModel, Field class ExtractionMethod(StrEnum): NATIVE_PDF = "native_pdf" OCR = "ocr" class Severity(StrEnum): INFO = "info" WARNING = "warning" ERROR = "error" class WordBox(BaseModel): text: str page: int x0: float y0: float x1: float y1: float method: ExtractionMethod confidence: float = Field(ge=0, le=1) class SourceRef(BaseModel): page: int bbox: tuple[float, float, float, float] method: ExtractionMethod confidence: float = Field(ge=0, le=1) class ExtractedPage(BaseModel): number: int width: float height: float words: list[WordBox] method: ExtractionMethod orientation_degrees: int = 0 class ExtractedDocument(BaseModel): source_path: str source_filename: str sha256: str pages: list[ExtractedPage] class ReportMetadata(BaseModel): report_family: str = "turkish_investment_fund_portfolio" fund_code: str | None = None fund_name: str period: str source_filename: str source_sha256: str class EquityPosition(BaseModel): code: str issuer: str currency: str isin: str nominal: Decimal purchase_price: Decimal purchase_date: date contract_no: str | None = None current_price: Decimal total_value: Decimal group_pct: Decimal fpd_pct: Decimal ftd_pct: Decimal source: SourceRef class RepoPosition(BaseModel): code: str currency: str issuer: str maturity_date: date days_to_maturity: int isin: str discount_rate: Decimal interest_payment_count: int nominal: Decimal purchase_price: Decimal purchase_date: date collateral_amount: Decimal contract_no: str net_return: Decimal daily_value: Decimal total_value: Decimal group_pct: Decimal fpd_pct: Decimal ftd_pct: Decimal source: SourceRef class DerivativePosition(BaseModel): position_type: str code: str currency: str maturity_date: date | None = None nominal: Decimal purchase_price: Decimal purchase_date: date contract_no: str | None = None current_price: Decimal total_value: Decimal group_pct: Decimal fpd_pct: Decimal ftd_pct: Decimal source: SourceRef class CashCollateral(BaseModel): name: str currency: str = "TL" nominal: Decimal total_value: Decimal group_pct: Decimal fpd_pct: Decimal source: SourceRef class DeclaredTotals(BaseModel): equity_nominal: Decimal equity_value: Decimal equity_fpd_pct: Decimal equity_ftd_pct: Decimal repo_value: Decimal repo_fpd_pct: Decimal repo_ftd_pct: Decimal derivative_exposure: Decimal cash_collateral_value: Decimal cash_collateral_fpd_pct: Decimal fund_portfolio_value: Decimal class FundPortfolioReport(BaseModel): metadata: ReportMetadata equities: list[EquityPosition] repos: list[RepoPosition] derivatives: list[DerivativePosition] cash_collaterals: list[CashCollateral] declared_totals: DeclaredTotals class ValidationFinding(BaseModel): severity: Severity code: str message: str sheet: str | None = None record_key: str | None = None page: int | None = None expected: str | None = None actual: str | None = None class ValidationResult(BaseModel): status: str findings: list[ValidationFinding] error_count: int warning_count: int info_count: int class GenericRow(BaseModel): label: str note_reference: str | None = None values: list[Decimal | date | str | None] hierarchy_level: int = Field(default=0, ge=0, le=8) source: SourceRef class GenericTable(BaseModel): table_id: str title: str sheet_name: str semantic_type: str = "financial_table" description: str = "" unit: str | None = None headers: list[str] rows: list[GenericRow] source_pages: list[int] confidence: float = Field(default=0.8, ge=0, le=1) class GenericDocumentReport(BaseModel): report_family: str = "general_financial_document" document_title: str document_type: str summary: str source_filename: str source_sha256: str planner_mode: str tables: list[GenericTable] class PipelineResult(BaseModel): output_path: str report: FundPortfolioReport | GenericDocumentReport validation: ValidationResult