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
|
||||
@@ -0,0 +1,415 @@
|
||||
[
|
||||
{
|
||||
"canon_id": "cbc",
|
||||
"canonical_ru": "Общий анализ крови",
|
||||
"canonical_kz": "Қанның жалпы анализі",
|
||||
"canonical_en": "Complete blood count (CBC)",
|
||||
"category": "Лаборатория",
|
||||
"code": "B03.016.003",
|
||||
"unit": "1 иссл.",
|
||||
"synonyms": [
|
||||
{
|
||||
"text": "ОАК",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Общий анализ крови (развернутый)",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Клинический анализ крови",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "КАК",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "CBC",
|
||||
"lang": "en"
|
||||
},
|
||||
{
|
||||
"text": "Қанның жалпы талдауы",
|
||||
"lang": "kz"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"canon_id": "uzi_abd",
|
||||
"canonical_ru": "УЗИ органов брюшной полости",
|
||||
"canonical_kz": "Құрсақ қуысы ағзаларының УДЗ",
|
||||
"canonical_en": "Abdominal ultrasound",
|
||||
"category": "Диагностика/УЗИ",
|
||||
"code": "A04.16.001",
|
||||
"unit": "1 иссл.",
|
||||
"synonyms": [
|
||||
{
|
||||
"text": "УЗИ ОБП",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "УЗИ брюшной полости",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Ультразвуковое исследование брюшной полости",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Құрсақ қуысы УДЗ",
|
||||
"lang": "kz"
|
||||
},
|
||||
{
|
||||
"text": "Abdominal US",
|
||||
"lang": "en"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"canon_id": "therapist",
|
||||
"canonical_ru": "Приём врача-терапевта",
|
||||
"canonical_kz": "Терапевт дәрігердің қабылдауы",
|
||||
"canonical_en": "General practitioner consultation",
|
||||
"category": "Приём специалистов",
|
||||
"code": "B01.047.001",
|
||||
"unit": "1 приём",
|
||||
"synonyms": [
|
||||
{
|
||||
"text": "Прием терапевта",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Консультация терапевта первичная",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Терапевт қабылдауы",
|
||||
"lang": "kz"
|
||||
},
|
||||
{
|
||||
"text": "GP visit",
|
||||
"lang": "en"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"canon_id": "ecg",
|
||||
"canonical_ru": "Электрокардиография (ЭКГ)",
|
||||
"canonical_kz": "Электрокардиография (ЭКГ)",
|
||||
"canonical_en": "Electrocardiography (ECG)",
|
||||
"category": "Диагностика",
|
||||
"code": "A05.10.006",
|
||||
"unit": "1 иссл.",
|
||||
"synonyms": [
|
||||
{
|
||||
"text": "ЭКГ",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "ЭКГ с расшифровкой",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Электрокардиография",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "ECG",
|
||||
"lang": "en"
|
||||
},
|
||||
{
|
||||
"text": "ЭКГ + описание",
|
||||
"lang": "ru"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"canon_id": "glucose",
|
||||
"canonical_ru": "Глюкоза крови",
|
||||
"canonical_kz": "Қандағы глюкоза",
|
||||
"canonical_en": "Blood glucose",
|
||||
"category": "Лаборатория",
|
||||
"code": "B03.016.006",
|
||||
"unit": "1 иссл.",
|
||||
"synonyms": [
|
||||
{
|
||||
"text": "Глюкоза",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Сахар крови",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Қандағы глюкоза",
|
||||
"lang": "kz"
|
||||
},
|
||||
{
|
||||
"text": "Glucose",
|
||||
"lang": "en"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"canon_id": "cardiologist",
|
||||
"canonical_ru": "Консультация кардиолога",
|
||||
"canonical_kz": "Кардиолог кеңесі",
|
||||
"canonical_en": "Cardiologist consultation",
|
||||
"category": "Приём специалистов",
|
||||
"code": "B01.015.001",
|
||||
"unit": "1 приём",
|
||||
"synonyms": [
|
||||
{
|
||||
"text": "Прием кардиолога",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Кардиолог консультация первичная",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Кардиолог қабылдауы",
|
||||
"lang": "kz"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"canon_id": "mri_brain",
|
||||
"canonical_ru": "МРТ головного мозга",
|
||||
"canonical_kz": "Бас миының МРТ",
|
||||
"canonical_en": "Brain MRI",
|
||||
"category": "Диагностика/МРТ",
|
||||
"code": "A05.23.009",
|
||||
"unit": "1 иссл.",
|
||||
"synonyms": [
|
||||
{
|
||||
"text": "МРТ г/м",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Магнитно-резонансная томография головного мозга",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Бас миы МРТ",
|
||||
"lang": "kz"
|
||||
},
|
||||
{
|
||||
"text": "Brain MRI",
|
||||
"lang": "en"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"canon_id": "biochem",
|
||||
"canonical_ru": "Биохимический анализ крови",
|
||||
"canonical_kz": "Қанның биохимиялық анализі",
|
||||
"canonical_en": "Blood chemistry panel",
|
||||
"category": "Лаборатория",
|
||||
"code": "B03.016.004",
|
||||
"unit": "1 иссл.",
|
||||
"synonyms": [
|
||||
{
|
||||
"text": "Биохимия крови",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Б/х крови",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Биохимический анализ крови (базовый)",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Қан биохимиясы",
|
||||
"lang": "kz"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"canon_id": "tooth_ext",
|
||||
"canonical_ru": "Удаление зуба",
|
||||
"canonical_kz": "Тісті жұлу",
|
||||
"canonical_en": "Tooth extraction",
|
||||
"category": "Стоматология",
|
||||
"code": "A16.07.001",
|
||||
"unit": "1 зуб",
|
||||
"synonyms": [
|
||||
{
|
||||
"text": "Удаление зуба простое",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Экстракция зуба",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Тіс жұлу",
|
||||
"lang": "kz"
|
||||
},
|
||||
{
|
||||
"text": "Tooth removal",
|
||||
"lang": "en"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"canon_id": "xray_chest",
|
||||
"canonical_ru": "Рентген грудной клетки",
|
||||
"canonical_kz": "Кеуде клеткасының рентгені",
|
||||
"canonical_en": "Chest X-ray",
|
||||
"category": "Диагностика",
|
||||
"code": "A06.09.007",
|
||||
"unit": "1 иссл.",
|
||||
"synonyms": [
|
||||
{
|
||||
"text": "Рентгенография ОГК",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Флюорография",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Кеуде рентгені",
|
||||
"lang": "kz"
|
||||
},
|
||||
{
|
||||
"text": "Chest X-ray",
|
||||
"lang": "en"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"canon_id": "tsh",
|
||||
"canonical_ru": "Тиреотропный гормон (ТТГ)",
|
||||
"canonical_kz": "Тиреотропты гормон (ТТГ)",
|
||||
"canonical_en": "Thyroid-stimulating hormone (TSH)",
|
||||
"category": "Лаборатория",
|
||||
"code": "B03.016.021",
|
||||
"unit": "1 иссл.",
|
||||
"synonyms": [
|
||||
{
|
||||
"text": "ТТГ",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Тиреотропный гормон",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "TSH",
|
||||
"lang": "en"
|
||||
},
|
||||
{
|
||||
"text": "ТТГ гормоны",
|
||||
"lang": "kz"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"canon_id": "urinalysis",
|
||||
"canonical_ru": "Общий анализ мочи",
|
||||
"canonical_kz": "Зәрдің жалпы анализі",
|
||||
"canonical_en": "Urinalysis",
|
||||
"category": "Лаборатория",
|
||||
"code": "B03.016.010",
|
||||
"unit": "1 иссл.",
|
||||
"synonyms": [
|
||||
{
|
||||
"text": "ОАМ",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Общий анализ мочи",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Зәр анализі",
|
||||
"lang": "kz"
|
||||
},
|
||||
{
|
||||
"text": "Urine test",
|
||||
"lang": "en"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"canon_id": "gyn",
|
||||
"canonical_ru": "Приём гинеколога",
|
||||
"canonical_kz": "Гинеколог қабылдауы",
|
||||
"canonical_en": "Gynecologist consultation",
|
||||
"category": "Приём специалистов",
|
||||
"code": "B01.001.001",
|
||||
"unit": "1 приём",
|
||||
"synonyms": [
|
||||
{
|
||||
"text": "Прием гинеколога",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Консультация гинеколога первичная",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Гинеколог кеңесі",
|
||||
"lang": "kz"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"canon_id": "covid_pcr",
|
||||
"canonical_ru": "ПЦР на COVID-19",
|
||||
"canonical_kz": "COVID-19 ПТР",
|
||||
"canonical_en": "COVID-19 PCR test",
|
||||
"category": "Лаборатория",
|
||||
"code": "A26.08.027",
|
||||
"unit": "1 иссл.",
|
||||
"synonyms": [
|
||||
{
|
||||
"text": "ПЦР COVID-19",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "ПЦР-тест на коронавирус",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "COVID PCR",
|
||||
"lang": "en"
|
||||
},
|
||||
{
|
||||
"text": "COVID ПТР",
|
||||
"lang": "kz"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"canon_id": "vit_d",
|
||||
"canonical_ru": "Витамин D (25-OH)",
|
||||
"canonical_kz": "D дәрумені (25-OH)",
|
||||
"canonical_en": "Vitamin D (25-OH)",
|
||||
"category": "Лаборатория",
|
||||
"code": "B03.016.115",
|
||||
"unit": "1 иссл.",
|
||||
"synonyms": [
|
||||
{
|
||||
"text": "25-OH витамин D",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Витамин Д",
|
||||
"lang": "ru"
|
||||
},
|
||||
{
|
||||
"text": "Vitamin D",
|
||||
"lang": "en"
|
||||
},
|
||||
{
|
||||
"text": "D витамині",
|
||||
"lang": "kz"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user