242 lines
8.7 KiB
Python
242 lines
8.7 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
medevio_recept.py — vytvoření požadavku "Recept na léky" v Medeviu pro pacienta.
|
||
|
||
Určeno k volání z e-mailového agenta (recepty_agent.py): jakmile agent správně
|
||
identifikuje pacienta a co chce, založí mu v Medeviu požadavek, aby ho lékař viděl
|
||
(e-mail kontrolujeme zřídka, Medevio pořád).
|
||
|
||
Hlavní funkce:
|
||
vytvor_recept(rodne_cislo, nazev_leku, poznamka) -> request_id
|
||
|
||
Co dělá (vše ověřeno/odchyceno 2026-06-13 na testovacím pacientovi Vladko):
|
||
1. RČ -> patient UUID (MySQL medevio.medevio_pacient)
|
||
2. fillECRFForm -> ecrfFill.id (prázdný formulář)
|
||
3. createPatientRequestWithoutReservation -> založí "Recept na léky"
|
||
4. createClinicPatientRequestNote -> obě pole do INTERNÍ POZNÁMKY
|
||
5. assignTagToPatientRequest -> štítek CLAUDE
|
||
|
||
POZOR: lékařský (klinický) přístup neumí vyplnit pacientský dotazník smysluplně,
|
||
proto obsah ("Název léků" + "Poznámka") jde do interní poznámky, ne do dotazníku.
|
||
|
||
Auth: Bearer token z Medevio/token.txt (dlouhodobý API token).
|
||
"""
|
||
import sys
|
||
import re
|
||
from pathlib import Path
|
||
|
||
import requests
|
||
import pymysql
|
||
from pymysql.cursors import DictCursor
|
||
|
||
try:
|
||
sys.stdout.reconfigure(encoding="utf-8")
|
||
except Exception:
|
||
pass
|
||
|
||
# ============================================================
|
||
# Konstanty odchycené z Medevia (klinika mudr-buzalkova)
|
||
# ============================================================
|
||
CLINIC_SLUG = "mudr-buzalkova"
|
||
GRAPHQL_URL = "https://api.medevio.cz/graphql"
|
||
|
||
RECEPT_USER_ECRF_ID = "79488e86-e9e5-47e3-8b19-7e5229427f23" # typ "Recept na léky"
|
||
RECEPT_SID = "ERECEPT_SIMPLEST_BEZ_DAVKOVANI"
|
||
RECEPT_STEP_ID = "erecept-gp-request"
|
||
CLAUDE_TAG_ID = "c136aeca-0625-4c43-b81f-fc3949ec6ba6" # štítek CLAUDE
|
||
|
||
TOKEN_PATH = Path(__file__).resolve().parent.parent / "Medevio" / "token.txt"
|
||
|
||
# MySQL je na různých strojích na různém portu — zkusíme kandidáty po řadě.
|
||
_MYSQL_BASE = dict(user="root", password="Vlado9674+", database="medevio")
|
||
_MYSQL_CANDIDATES = [
|
||
dict(host="192.168.1.76", port=3306),
|
||
dict(host="192.168.1.76", port=3307),
|
||
dict(host="127.0.0.1", port=3307),
|
||
dict(host="127.0.0.1", port=3306),
|
||
]
|
||
|
||
# ============================================================
|
||
# GraphQL operace (přesně jak je posílá web Medevia)
|
||
# ============================================================
|
||
M_FILL_ECRF = r"""
|
||
mutation ClinicRequestCreateModal_FillECRFForm($input: FillECRFFormInput!) {
|
||
ecrfFill: fillECRFForm(input: $input) { id }
|
||
}
|
||
"""
|
||
|
||
M_CREATE_REQUEST = r"""
|
||
mutation ClinicRequestCreateModal_CreateRequest($clinicSlug: String!, $input: CreatePatientRequestWithoutReservationInput!) {
|
||
patientRequest: createPatientRequestWithoutReservation(clinicSlug: $clinicSlug, input: $input) { id }
|
||
}
|
||
"""
|
||
|
||
M_CREATE_NOTE = r"""
|
||
mutation ClinicRequestNotes_Create($noteInput: CreateClinicPatientRequestNoteInput!) {
|
||
createClinicPatientRequestNote(noteInput: $noteInput) { id }
|
||
}
|
||
"""
|
||
|
||
M_ASSIGN_TAG = r"""
|
||
mutation TagRequestEditModal_AssignTagToRequest($clinicSlug: String!, $requestId: UUID!, $tagId: UUID!) {
|
||
tagRequest: assignTagToPatientRequest(clinicSlug: $clinicSlug, patientRequestId: $requestId, tagId: $tagId) { id }
|
||
}
|
||
"""
|
||
|
||
|
||
# ============================================================
|
||
# Pomocné funkce
|
||
# ============================================================
|
||
def _read_token() -> str:
|
||
t = TOKEN_PATH.read_text(encoding="utf-8").strip()
|
||
return t[7:].strip() if t.lower().startswith("bearer ") else t
|
||
|
||
|
||
def _gql(query: str, variables: dict, token: str) -> dict:
|
||
headers = {
|
||
"Authorization": f"Bearer {token}",
|
||
"Content-Type": "application/json",
|
||
"Accept": "application/json",
|
||
}
|
||
r = requests.post(GRAPHQL_URL, json={"query": query, "variables": variables},
|
||
headers=headers, timeout=30)
|
||
r.raise_for_status()
|
||
data = r.json()
|
||
if data.get("errors"):
|
||
raise RuntimeError(f"GraphQL chyba: {data['errors']}")
|
||
return data["data"]
|
||
|
||
|
||
def _mysql():
|
||
last = None
|
||
for cand in _MYSQL_CANDIDATES:
|
||
try:
|
||
return pymysql.connect(**cand, **_MYSQL_BASE,
|
||
cursorclass=DictCursor, connect_timeout=4)
|
||
except Exception as e:
|
||
last = e
|
||
raise RuntimeError(f"MySQL (medevio) nedostupné na žádném kandidátovi: {last}")
|
||
|
||
|
||
def najdi_uuid_dle_rc(rodne_cislo: str) -> dict:
|
||
"""RČ (s lomítkem i bez) -> řádek pacienta z medevio_pacient.
|
||
Vyhazuje LookupError když pacient není nalezen nebo je nejednoznačný."""
|
||
rc = re.sub(r"\D", "", rodne_cislo or "")
|
||
if not rc:
|
||
raise ValueError("Prázdné / neplatné rodné číslo.")
|
||
conn = _mysql()
|
||
try:
|
||
with conn.cursor() as cur:
|
||
cur.execute(
|
||
"SELECT patient_id, name, surname, status, user_id "
|
||
"FROM medevio_pacient "
|
||
"WHERE REPLACE(identification_number, '/', '') = %s",
|
||
(rc,),
|
||
)
|
||
rows = cur.fetchall()
|
||
finally:
|
||
conn.close()
|
||
if not rows:
|
||
raise LookupError(f"Pacient s RČ {rc} není v Medevio databázi (medevio_pacient).")
|
||
if len(rows) > 1:
|
||
raise LookupError(f"RČ {rc} odpovídá více pacientům — nejednoznačné, řeš ručně.")
|
||
return rows[0]
|
||
|
||
|
||
def _format_note(nazev_leku: str, poznamka: str) -> str:
|
||
return (
|
||
"Žádost o recept (zpracováno e-mailovým agentem).\n\n"
|
||
f"Název léků:\n{(nazev_leku or '').strip() or '—'}\n\n"
|
||
f"Poznámka:\n{(poznamka or '').strip() or '—'}"
|
||
)
|
||
|
||
|
||
# ============================================================
|
||
# Hlavní funkce
|
||
# ============================================================
|
||
def vytvor_recept(rodne_cislo: str = None, nazev_leku: str = "", poznamka: str = "",
|
||
*, patient_uuid: str = None, pridat_stitek: bool = True,
|
||
token: str = None, verbose: bool = True) -> str:
|
||
"""
|
||
Založí pacientovi požadavek "Recept na léky" + interní poznámku + štítek CLAUDE.
|
||
|
||
Parametry:
|
||
rodne_cislo – RČ pacienta (s lomítkem i bez); přeloží se na UUID přes MySQL.
|
||
nazev_leku – text 1. pole ("Název léků").
|
||
poznamka – text 2. pole ("Poznámka").
|
||
patient_uuid – volitelně rovnou UUID pacienta (obejde lookup dle RČ; pro testy).
|
||
pridat_stitek – True = přiřadí štítek CLAUDE.
|
||
token – volitelně Bearer token; jinak se načte z token.txt.
|
||
|
||
Vrací: request_id založeného požadavku (str).
|
||
"""
|
||
token = token or _read_token()
|
||
|
||
if patient_uuid:
|
||
uuid = patient_uuid
|
||
kdo = f"UUID {uuid}"
|
||
else:
|
||
pac = najdi_uuid_dle_rc(rodne_cislo)
|
||
uuid = pac["patient_id"]
|
||
kdo = f"{pac['surname']} {pac['name']} (RČ {rodne_cislo}, status {pac['status']})"
|
||
|
||
if verbose:
|
||
print(f"→ Pacient: {kdo}")
|
||
|
||
# 1) prázdný ECRF fill
|
||
fill = _gql(M_FILL_ECRF, {"input": {
|
||
"byDoctor": True,
|
||
"fields": [],
|
||
"patientId": uuid,
|
||
"sid": RECEPT_SID,
|
||
"stepId": RECEPT_STEP_ID,
|
||
}}, token)
|
||
ecrf_fill_id = fill["ecrfFill"]["id"]
|
||
|
||
# 2) vytvoř požadavek "Recept na léky"
|
||
created = _gql(M_CREATE_REQUEST, {"clinicSlug": CLINIC_SLUG, "input": {
|
||
"patientId": uuid,
|
||
"userECRFId": RECEPT_USER_ECRF_ID,
|
||
"ecrfFillIds": [ecrf_fill_id],
|
||
"createdByDoctor": True,
|
||
"shouldInvitePatient": False,
|
||
}}, token)
|
||
request_id = created["patientRequest"]["id"]
|
||
if verbose:
|
||
print(f"✓ Požadavek vytvořen: {request_id}")
|
||
|
||
# 3) interní poznámka s oběma poli
|
||
_gql(M_CREATE_NOTE, {"noteInput": {
|
||
"requestId": request_id,
|
||
"content": _format_note(nazev_leku, poznamka),
|
||
}}, token)
|
||
if verbose:
|
||
print("✓ Interní poznámka zapsána")
|
||
|
||
# 4) štítek CLAUDE
|
||
if pridat_stitek:
|
||
_gql(M_ASSIGN_TAG, {
|
||
"clinicSlug": CLINIC_SLUG,
|
||
"requestId": request_id,
|
||
"tagId": CLAUDE_TAG_ID,
|
||
}, token)
|
||
if verbose:
|
||
print("✓ Štítek CLAUDE přiřazen")
|
||
|
||
return request_id
|
||
|
||
|
||
# ============================================================
|
||
# Test (na testovacím pacientovi Vladko)
|
||
# ============================================================
|
||
if __name__ == "__main__":
|
||
VLADKO_UUID = "0210db7b-8fb0-4b47-b1d8-ec7a10849a63" # Vladko - testovací aplikace
|
||
rid = vytvor_recept(
|
||
patient_uuid=VLADKO_UUID,
|
||
nazev_leku="Euthyrox 100 µg (TEST z medevio_recept.py)",
|
||
poznamka="Testovací požadavek z funkce vytvor_recept — možno zavřít.",
|
||
)
|
||
print(f"\nHOTOVO. request_id = {rid}")
|
||
print(f"https://my.medevio.cz/mudr-buzalkova/klinika/pacienti?pozadavek={rid}")
|