chore: каркас проекта — контракты, справочник услуг, синтетические фикстуры
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
"""Общие модели данных — контракт между агентами (Pydantic v2).
|
||||
|
||||
`RawRow` и `ParsedDocument` — выход любого парсера (граница агентов B → C).
|
||||
`MatchResult` — выход сопоставления (агент C). `*Out`-модели — выдача API (агент D),
|
||||
её же потребляет фронт (агент E). Любая правка этих типов проходит через оркестратора.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
# Карта тарифов: ключ — тип цены, значение — сумма в KZT.
|
||||
# Возможные ключи: resident, nonresident, cis, far, insurance, partner.
|
||||
PriceTiers = dict[str, float]
|
||||
|
||||
|
||||
class RawRow(BaseModel):
|
||||
"""Одна сырая строка прайса — единый выход любого парсера."""
|
||||
|
||||
service_name_raw: str
|
||||
service_code_source: str | None = None
|
||||
prices: PriceTiers = Field(default_factory=dict)
|
||||
unit: str | None = None
|
||||
section: str | None = None # заголовок секции — контекст специальности
|
||||
|
||||
|
||||
class ParsedDocument(BaseModel):
|
||||
"""Результат разбора одного файла прайса."""
|
||||
|
||||
file_name: str
|
||||
file_format: str # pdf / scan_pdf / docx / xlsx / xls
|
||||
partner_name: str | None = None
|
||||
city: str | None = None
|
||||
effective_date: date | None = None
|
||||
rows: list[RawRow] = Field(default_factory=list)
|
||||
raw_content: str = ""
|
||||
parse_log: list[str] = Field(default_factory=list)
|
||||
|
||||
|
||||
class MatchResult(BaseModel):
|
||||
"""Результат сопоставления строки со справочником."""
|
||||
|
||||
service_id: str | None = None
|
||||
method: str | None = None # code / exact / embedding / fuzzy / manual
|
||||
confidence: float = 0.0
|
||||
# Лучший кандидат для очереди верификации, даже если ниже порога автосопоставления.
|
||||
suggested_service_id: str | None = None
|
||||
suggested_score: float = 0.0
|
||||
|
||||
|
||||
# --- выдача API ---
|
||||
class ServiceOut(BaseModel):
|
||||
service_id: str
|
||||
specialty: str
|
||||
name_ru: str
|
||||
tarificator_code: str | None = None
|
||||
|
||||
|
||||
class PartnerOut(BaseModel):
|
||||
partner_id: str
|
||||
name: str
|
||||
city: str | None = None
|
||||
is_active: bool = True
|
||||
|
||||
|
||||
class PriceOut(BaseModel):
|
||||
partner_id: str
|
||||
partner_name: str
|
||||
price_resident_kzt: float | None = None
|
||||
price_nonresident_kzt: float | None = None
|
||||
prices: PriceTiers = Field(default_factory=dict)
|
||||
effective_date: date | None = None
|
||||
|
||||
|
||||
class Stats(BaseModel):
|
||||
"""Сводка для дашборда и отчёта о качестве."""
|
||||
|
||||
documents_total: int = 0
|
||||
documents_done: int = 0
|
||||
items_total: int = 0
|
||||
auto_matched_pct: float = 0.0
|
||||
unmatched_total: int = 0
|
||||
Reference in New Issue
Block a user