notebookvb

This commit is contained in:
Vladimir Buzalka
2026-05-14 05:57:16 +02:00
parent 68416deae6
commit d33c0da218
6 changed files with 605 additions and 79 deletions
@@ -73,5 +73,10 @@
"datum": "31.05.2026",
"ref_cislo": "178213777",
"podano_kdy": "2026-05-13 07:09:12"
},
{
"datum": "30.06.2026",
"ref_cislo": "178258393",
"podano_kdy": "2026-05-13 21:03:20"
}
]
@@ -1 +1 @@
{"mesic": 5, "rok": 2026}
{"mesic": 6, "rok": 2026}
@@ -1,7 +1,7 @@
[
{
"name": "SID",
"value": "cfdefd7ad7d093aeeadee6402dff0fa8",
"value": "0589c59247aa8fa221c380eec74c9cef",
"domain": ".portal.zpskoda.cz",
"path": "/",
"expires": -1,
@@ -14,7 +14,7 @@
"value": "CERT",
"domain": ".portal.zpskoda.cz",
"path": "/",
"expires": 1810184951,
"expires": 1810234998,
"secure": true,
"httpOnly": false,
"sameSite": "Lax"
+25
View File
@@ -0,0 +1,25 @@
CREATE TABLE IF NOT EXISTS medevio.medevio_pacient (
patient_id VARCHAR(36) NOT NULL PRIMARY KEY,
name VARCHAR(100),
surname VARCHAR(100),
identification_number VARCHAR(20) COMMENT 'Rodne cislo bez lomitka',
sex VARCHAR(10) COMMENT 'Male / Female',
dob DATE COMMENT 'Datum narozeni',
email VARCHAR(200),
phone VARCHAR(50),
insurance_code INT COMMENT 'Kod pojistovny (111=VZP, 207=OZP, ...)',
insurance_name VARCHAR(100) COMMENT 'Nazev pojistovny',
status VARCHAR(20) COMMENT 'ACTIVE / INACTIVE',
is_in_clinic TINYINT(1) DEFAULT 1,
has_mobile_app TINYINT(1) DEFAULT 0,
anamnesis_shared TINYINT(1) DEFAULT 0,
note TEXT COMMENT 'Interni poznamka lekare',
city VARCHAR(200),
street VARCHAR(200),
house_number VARCHAR(50),
user_id VARCHAR(36) COMMENT 'ID uzivatelskeho uctu (PatientUser)',
user_email VARCHAR(200) COMMENT 'Email spravujici osoby',
user_phone VARCHAR(50) COMMENT 'Telefon spravujici osoby',
created_at DATETIME COMMENT 'Kdy byl pacient vytvoren v Medeviu',
synced_at DATETIME NOT NULL COMMENT 'Cas posledni synchronizace'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
@@ -0,0 +1,337 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Sync Medevio patients to MySQL table medevio.medevio_pacient.
Stahuje seznam pacientů přes GraphQL API (stránkovaně po 50),
pro každého pacienta stáhne detail a uloží/aktualizuje v MySQL.
"""
import sys
try:
sys.stdout.reconfigure(encoding="utf-8")
sys.stderr.reconfigure(encoding="utf-8")
except AttributeError:
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8")
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8")
import json
import time
import pymysql
import requests
from pathlib import Path
from datetime import datetime
from dateutil import parser as dtparser, tz
# ==================== CONFIG ====================
GRAPHQL_URL = "https://api.medevio.cz/graphql"
CLINIC_SLUG = "mudr-buzalkova"
PAGE_SIZE = 50
DELAY_BETWEEN_REQUESTS = 0.3
TOKEN_PATH = Path(__file__).resolve().parent.parent / "token.txt"
DB_CONFIG = {
"host": "192.168.1.76",
"port": 3306,
"user": "root",
"password": "Vlado9674+",
"database": "medevio",
"charset": "utf8mb4",
"cursorclass": pymysql.cursors.DictCursor,
}
PRAGUE_TZ = tz.gettz("Europe/Prague")
# ==================== TABLE ====================
CREATE_TABLE_SQL = """
CREATE TABLE IF NOT EXISTS medevio_pacient (
patient_id VARCHAR(36) NOT NULL PRIMARY KEY,
name VARCHAR(100),
surname VARCHAR(100),
identification_number VARCHAR(20) COMMENT 'Rodne cislo bez lomitka',
sex VARCHAR(10) COMMENT 'Male / Female',
dob DATE COMMENT 'Datum narozeni',
email VARCHAR(200),
phone VARCHAR(50),
insurance_code INT COMMENT 'Kod pojistovny (111=VZP, 207=OZP, ...)',
insurance_name VARCHAR(100) COMMENT 'Nazev pojistovny',
status VARCHAR(20) COMMENT 'ACTIVE / INACTIVE',
is_in_clinic TINYINT(1) DEFAULT 1,
has_mobile_app TINYINT(1) DEFAULT 0,
anamnesis_shared TINYINT(1) DEFAULT 0,
note TEXT COMMENT 'Interni poznamka lekare',
city VARCHAR(200),
street VARCHAR(200),
house_number VARCHAR(50),
user_id VARCHAR(36) COMMENT 'ID uzivatelskeho uctu (PatientUser)',
user_email VARCHAR(200) COMMENT 'Email spravujici osoby',
user_phone VARCHAR(50) COMMENT 'Telefon spravujici osoby',
created_at DATETIME COMMENT 'Kdy byl pacient vytvoren v Medeviu',
synced_at DATETIME NOT NULL COMMENT 'Cas posledni synchronizace'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
"""
# ==================== UPSERT ====================
UPSERT_SQL = """
INSERT INTO medevio_pacient (
patient_id, name, surname, identification_number,
sex, dob, email, phone,
insurance_code, insurance_name,
status, is_in_clinic, has_mobile_app, anamnesis_shared,
note, city, street, house_number,
user_id, user_email, user_phone,
created_at, synced_at
) VALUES (
%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s
)
ON DUPLICATE KEY UPDATE
name = VALUES(name),
surname = VALUES(surname),
identification_number = VALUES(identification_number),
sex = VALUES(sex),
dob = VALUES(dob),
email = VALUES(email),
phone = VALUES(phone),
insurance_code = VALUES(insurance_code),
insurance_name = VALUES(insurance_name),
status = VALUES(status),
is_in_clinic = VALUES(is_in_clinic),
has_mobile_app = VALUES(has_mobile_app),
anamnesis_shared = VALUES(anamnesis_shared),
note = VALUES(note),
city = VALUES(city),
street = VALUES(street),
house_number = VALUES(house_number),
user_id = VALUES(user_id),
user_email = VALUES(user_email),
user_phone = VALUES(user_phone),
created_at = VALUES(created_at),
synced_at = VALUES(synced_at)
"""
# ==================== GRAPHQL QUERIES ====================
LIST_PATIENTS_QUERY = """
query SyncListPatients($clinicSlug: String!, $pageInfo: PageInfo!, $filter: ListPatientFilter!) {
patientsList: listPatients(clinicSlug: $clinicSlug, filter: $filter, pageInfo: $pageInfo) {
count
patients {
id
identificationNumber
name
surname
sex
phone
status2
isInClinic
locale
insuranceCompanyObject { id shortName }
user { id phone name surname }
}
}
}
"""
DETAIL_PATIENT_QUERY = """
query GetPatientDetail($clinicSlug: String!, $patientId: String!) {
patient: getPatientForClinic(clinicSlug: $clinicSlug, patientId: $patientId) {
id
name
surname
identificationNumber
sex
dob
email
phone
status
isInClinic
hasMobileApp
anamnesisShared
note
city
street
houseNumber
createdAt
insuranceCompanyObject {
code
name
}
user {
id
email
phone
}
}
}
"""
def parse_dt(iso_str):
if not iso_str:
return None
try:
return dtparser.isoparse(iso_str).astimezone(PRAGUE_TZ).replace(tzinfo=None)
except Exception:
return None
def make_headers(token):
return {
"content-type": "application/json",
"authorization": f"Bearer {token}",
"origin": "https://my.medevio.cz",
"referer": "https://my.medevio.cz/",
}
def gql_request(headers, query, variables):
payload = {"query": query, "variables": variables}
resp = requests.post(GRAPHQL_URL, headers=headers, json=payload, timeout=30)
resp.raise_for_status()
data = resp.json()
if "errors" in data:
print(f" GQL errors: {data['errors']}")
return None
return data.get("data")
def fetch_patients_list(headers):
"""Stáhne seznam všech patient IDs stránkovaně přes listPatients."""
all_patients = []
offset = 0
total = None
while True:
data = gql_request(headers, LIST_PATIENTS_QUERY, {
"clinicSlug": CLINIC_SLUG,
"filter": {},
"pageInfo": {"first": PAGE_SIZE, "offset": offset},
})
if not data or "patientsList" not in data:
print(f" Chyba pri stahovani seznamu (offset={offset}).")
return None
result = data["patientsList"]
if total is None:
total = result.get("count", 0)
print(f" Celkem pacientu v Medevio: {total}")
patients = result.get("patients") or []
if not patients:
break
all_patients.extend(patients)
offset += PAGE_SIZE
print(f" Stazeno {len(all_patients)}/{total}...")
if offset >= total:
break
time.sleep(DELAY_BETWEEN_REQUESTS)
return all_patients
def fetch_patient_detail(headers, patient_id):
"""Stáhne detail jednoho pacienta."""
data = gql_request(headers, DETAIL_PATIENT_QUERY, {
"clinicSlug": CLINIC_SLUG,
"patientId": patient_id,
})
if data and "patient" in data:
return data["patient"]
return None
def patient_to_row(p):
"""Převede patient dict na tuple pro UPSERT."""
insurance = p.get("insuranceCompanyObject") or {}
user = p.get("user") or {}
now = datetime.now().replace(microsecond=0)
return (
p.get("id"),
p.get("name"),
p.get("surname"),
p.get("identificationNumber"),
p.get("sex"),
p.get("dob"),
p.get("email"),
p.get("phone"),
insurance.get("code"),
insurance.get("name"),
p.get("status") or p.get("status2"),
1 if p.get("isInClinic") else 0,
1 if p.get("hasMobileApp") else 0,
1 if p.get("anamnesisShared") else 0,
p.get("note"),
p.get("city"),
p.get("street"),
p.get("houseNumber"),
user.get("id"),
user.get("email"),
user.get("phone"),
parse_dt(p.get("createdAt")),
now,
)
def upsert_patients(conn, patients):
rows = [patient_to_row(p) for p in patients]
with conn.cursor() as cur:
cur.executemany(UPSERT_SQL, rows)
conn.commit()
return len(rows)
def main():
token = TOKEN_PATH.read_text(encoding="utf-8").strip()
if token.startswith("Bearer "):
token = token.split(" ", 1)[1]
headers = make_headers(token)
conn = pymysql.connect(**DB_CONFIG)
with conn.cursor() as cur:
cur.execute(CREATE_TABLE_SQL)
conn.commit()
print("Tabulka medevio_pacient pripravena.")
# --- Krok 1: stáhni seznam patient IDs ---
print("\nStahuji seznam pacientu...")
patients = fetch_patients_list(headers)
if patients is None or len(patients) == 0:
print("Nepodařilo se stáhnout seznam pacientů.")
conn.close()
return
# --- Krok 2: pro každého stáhni detail ---
print(f"\nStahuji detaily pro {len(patients)} pacientu...")
detailed = []
errors = 0
for i, p in enumerate(patients):
detail = fetch_patient_detail(headers, p["id"])
if detail:
detailed.append(detail)
else:
errors += 1
if (i + 1) % 50 == 0:
print(f" Detail {i + 1}/{len(patients)}...")
time.sleep(DELAY_BETWEEN_REQUESTS)
# --- Krok 3: upsert do MySQL ---
count = upsert_patients(conn, detailed)
print(f"\nHotovo — {count} pacientu upsertovano.")
if errors:
print(f" ({errors} pacientu se nepodařilo stáhnout)")
conn.close()
print("\nDokonceno.")
if __name__ == "__main__":
main()
+235 -76
View File
@@ -1,11 +1,11 @@
# 🧭 MEDEVIO API Working Notes
# MEDEVIO API -- Working Notes
## General Architecture
- **Frontend:** React + MaterialUI (MUI) + Apollo GraphQL
- **Backend:** GraphQL API `https://api.medevio.cz/graphql`
- **Authentication:** cookies/tokens stored in `medevio_storage.json` (Playwright session)
- **Frontend base:** `https://my.medevio.cz/mudr-buzalkova/klinika/...`
- **Session handling:** token refreshed through `AccessToken_AuthSelf` calls
- **Frontend:** React + Material-UI (MUI) + Apollo GraphQL
- **Backend:** GraphQL API -> `https://api.medevio.cz/graphql`
- **Authentication:** cookies/tokens stored in `medevio_storage.json` (Playwright session)
- **Frontend base:** `https://my.medevio.cz/mudr-buzalkova/klinika/...`
- **Session handling:** token refreshed through `AccessToken_AuthSelf` calls
---
@@ -21,51 +21,6 @@ Use these cookies in every `requests.post(GRAPHQL_URL, headers, cookies, data=..
---
## Key GraphQL Operations
| Operation name | Purpose |
|----------------|----------|
| `AccessToken_AuthSelf` | Verify or refresh session |
| `ClinicNavigation_GetClinic` | Get basic clinic info |
| `ClinicAgenda_GetCalendarsForClinic` | List calendars within clinic |
| **`ClinicAgenda_ListClinicReservations`** | **List reservations (appointments)** |
| **`UpdateReservation_GetReservation`** | **Get full detail of one reservation** |
| **`ClinicRequestDetail_GetPatientRequest2`** | **Fetch detailed “Požadavek” (request card)** |
| `ClinicRequestNotes_Get` | Load Požadavek notes |
| `UseMessages_ListMessages` | Load chat messages |
| `Communication_GetClinicFooter` | UI footer text |
---
## Workflow for Automation
### 1️⃣ Extract reservations (agenda overview)
```graphql
operationName: "ClinicAgenda_ListClinicReservations"
variables: {
"clinicId": "<clinic-uuid>",
"dateFrom": "YYYY-MM-DDT00:00:00Z",
"dateTo": "YYYY-MM-DDT23:59:59Z"
}
```
→ returns `id`, `startDateTime`, `endDateTime`, `patient {name, age}`, `reason`, `status`.
### 2️⃣ Get detail of a single reservation
```graphql
operationName: "UpdateReservation_GetReservation"
variables: {"id": "<reservation-uuid>"}
```
→ returns reason, time, doctor, patient contact, note, etc.
### 3️⃣ Get detail of Požadavek
```graphql
operationName: "ClinicRequestDetail_GetPatientRequest2"
variables: {"id": "<request-uuid>"}
```
→ returns text, attachments, communication, etc.
---
## HTTP Setup (Python)
```python
@@ -80,56 +35,260 @@ response = requests.post(GRAPHQL_URL, headers=headers, cookies=cookies, data=jso
---
## Reservation Data Example
## Key IDs
```json
{
"id": "0e3a4f5c-1c15-40e6-b1b1-325de9269ef5",
"reason": "Očkování - Chřipka",
"startDateTime": "2025-10-17T09:10:00Z",
"endDateTime": "2025-10-17T09:20:00Z",
"status": "confirmed",
"note": "přijde i s taťkou",
"patient": {"id": "...", "name": "Černík Pavel", "age": 53},
"doctor": {"id": "...", "name": "MUDr. Buzalková"},
"location": {"name": "Ordinace Prosek"}
| Entity | ID |
|--------|----|
| Clinic | `25f24970-dae3-4f80-9337-d3616e53fb10` |
| Clinic slug | `mudr-buzalkova` |
| Calendar MUDr. Buzalkova | `144c4e12-347c-49ca-9ec0-8ca965a4470d` |
| AIS entity (Medicus) | `ef1549a5-d266-4f52-9a4d-7275e79ac82e` |
---
## Complete GraphQL Operations Catalog
### Session & Auth
| Operation | Purpose |
|-----------|---------|
| `AccessToken_AuthSelf` | Verify or refresh session |
### Search
| Operation | Variables | Response |
|-----------|-----------|----------|
| `Search` | `clinicSlug`, `locale`, `query` | `clinic`, `results` (patients + requests) |
### Patient Card (modal)
| Operation | Variables | Response |
|-----------|-----------|----------|
| `ClinicPatientDetailModal_GetData` | `clinicSlug`, `patientId`, `patientUuid`, `locale`, `challengesStatus` | `clinic`, `calendars`, `patient` (full detail), `challenges`, `patientRequestsResponse`, `treatmentPlanPatients`, `premiumPlans`, `insuranceCards`, `pinnedRequests`, `canBeRemoved` |
| `ClinicPatientRequestHistory_FilterPatientRequestsForClinic` | `clinicSlug`, `locale`, `patientId`, `patientRequestFilter`, `pageInfo {first, offset}` | `filterResponse`, `clinic`, `queues`, `calendars`, `userECRFs`, `substates`, `tags` |
| `ClinicPatientDetailModal_FindMergeSuggestions` | `clinicSlug`, `patientUuid` | `mergeSuggestions` |
#### Patient object structure (from GetData)
```
patient {
id, name, surname, identificationNumber (rodne cislo bez lomitka),
sex (Male/Female), dob (YYYY-MM-DD), email, phone,
kind (Human), type (Human), status (ACTIVE),
isInClinic, isInOrganizationOnly, hasMobileApp,
anamnesisShared, anamnesisStatusForClinic { updatedAt },
insuranceCompanyObject { id, code, name, shortName },
tags [], familyMembers [], clinics [],
note, organizationNotes [],
city, street, houseNumber,
user { id, name, surname, email, phone, registrationCompletedTime },
createdAt, editableByDoctor, userRelationship, premiumPlanPatient
}
```
### Patient Edit
| Operation | Variables | Response |
|-----------|-----------|----------|
| `EditPatientModal_GetClinic` | `clinicSlug` | `clinic` |
| `ClinicEditPatient_GetPatientForClinic` | `clinicSlug`, `patientId`, `includePatient` | `patient`, `clinic` |
| `ClinicEditPatient_ListInsuranceCompanies` | `country` | `insuranceCompanies []` (id, code, name) |
| `UseSupportedCountryCodes_Codes` | (none) | `codes` (phone country codes) |
### Patient List (Kartoteka)
| Operation | Variables | Response |
|-----------|-----------|----------|
| `LegacyClinicPatientListPage_ListClinicPatients` | `clinicSlug`, `criteria {premiumPlanId, tagId}`, `pageInfo {first: 50, offset}` | `count`, `patients`, `clinic` |
### Requests (Pozadavky)
| Operation | Variables | Response |
|-----------|-----------|----------|
| `ClinicLegacyRequestList_ListPatientRequestsForClinic` | `clinicSlug`, `locale`, `pageInfo {first: 30, offset}`, `queueAssignment`, `queueId`, `state` (ACTIVE/DONE) | `requests`, `clinic` |
#### Request list item structure
```
request {
id, createdAt, dueDate, displayTitle, doneAt, removedAt,
priority, evaluationResult, clinicId,
extendedPatient { id, identificationNumber, kind, name, surname,
note, owner, key, premiumPlanPatient, status, tags [] },
queue { id, name }, substate, pinType,
ecrf { id, name, iconMaskColor { name } },
flags [], hasMobileApp
}
```
### Request Detail
| Operation | Variables | Response |
|-----------|-----------|----------|
| `ClinicRequestDetail_GetPatientRequest2` | `clinicSlug`, `isDoctor`, `requestId`, `locale` | `request` (full detail) |
| `UseMessages_ListMessages` | `requestId`, `updatedSince` | `messages` |
| `Communication_GetClinicFooter` | `clinicSlug` | `footer` |
| `ClinicRequestNotes_Get` | `patientRequestId` | `notes` |
#### Request detail structure
```
request {
id, doneAt, doneBy { id, name, surname },
removedAt, queue, isInClinic,
clinic { id, paymentEnabled, hasInvoicingEnabled, slug, features },
clinicMedicalRecord, clinicMedicalRecordVisibleToPatient,
extendedPatient { ... (same as patient) },
ecrf, ecrfFilledData, eventType (PATIENT_REQUEST),
flags [], invoice, userNote, paymentData,
recording, reservations [], evaluationResult, tags [],
createdAt, createdBy, customTitle, createdByDoctor,
displayTitle, referringClinic, pinType,
dueDate, substate, hasMobileApp,
priceWhenCreated, currencyWhenCreated
}
```
### Calendar (Kalendar)
| Operation | Variables | Response |
|-----------|-----------|----------|
| `ClinicCalendar_ListClinicReservations` | `calendarIds []`, `clinicCountry`, `clinicSlug`, `locale`, `since` (ISO), `until` (ISO), `showTimeSlots`, `schedulePatientId`, `emptyCalendarIds` | `holidays`, `reservations`, `vacations` |
| `ClinicCalendar_GetWindows` | `calendarIds []`, `clinicSlug`, `locale`, `since`, `until` | `calendarWindows` (ordinacni hodiny) |
#### Reservation structure
```
reservation {
id, calendarId,
clinic { id, slug, aisEntity { id, slug } },
color, done, canceledAt,
end (ISO), note,
request {
displayTitle, id,
ecrf { id, name, iconMaskColor { name } },
extendedPatient { dob, email, id, identificationNumber,
kind, name, surname, note, phone, sex, status, tags [],
insuranceCompanyObject { code, name } }
}
}
```
### References (Referovani)
| Operation | Variables | Response |
|-----------|-----------|----------|
| `ClinicReferences_GetClinic` | `clinicSlug` | `clinic`, `substates` |
| `ClinicReferences_ListReferencesSentByClinic` | `clinicSlug`, `locale`, `pageInfo {first: 51, offset}` | `references` |
### Treatment Plans (Lecebne plany)
| Operation | Variables | Response |
|-----------|-----------|----------|
| `PlanPatientsPage_GetClinic` | `clinicSlug` | `clinic` |
| `PlanPatientsPage_ListPlanPatients` | `clinicSlug`, `pageInfo {first: 51, offset}` | `planPatients` |
### Settings (Nastaveni)
| Operation | Purpose |
|-----------|---------|
| `ClinicSettingsSubNavigation_GetClinic` | Navigation state for settings |
| `ClinicRequestSettings_GetClinic` | Request settings |
| `UserEcrfListing_GetClinicECRFMenu` | List request types (ECRF forms) |
| `ClinicEcrfSet_ListECRFSets` | List request type groups |
| `ClinicOpeningHoursEdit_GetClinicOpeningHours2` | Opening hours settings |
| `ClinicPaymentsSettings_GetClinic` | Payment settings |
| `StripeVerificationContext_GetClinicCompanyInfo` | Stripe payment verification |
| `SettingsPage` | General settings |
| `InviteSettings` | Invite settings |
| `InviteSettings_GetInviteContent` | Invite content/templates |
| `ImportAisSettings_GetClinic` | AIS integration settings |
| `ImportAisSettings_GetAises` | Available AIS systems |
| `ClinicUserGrid_Columns` | User grid columns (queues, calendars) |
| `ClinicUserGrid_Rows` | User list for clinic |
### Clinic Info
| Operation | Purpose |
|-----------|---------|
| `ClinicNavigation_GetClinic` | Basic clinic info |
| `ClinicAgenda_GetCalendarsForClinic` | List calendars within clinic |
---
## Playwright Selectors
| Purpose | Selector |
|----------|-----------|
|---------|----------|
| Agenda rows | `div[data-testid='reservation-row']` |
| Row ID | `data-id` |
| Agenda fields | `div[data-field='Time']`, `div[data-field='Patient']`, `div[data-field='Reason']` |
---
## Recommended Automation Pipeline
## URL Patterns
1. **Agenda scrape (Playwright)** → extract `data-id`, patient, time, reason.
2. **GraphQL fetch (Python)** → use `ClinicAgenda_ListClinicReservations`.
3. **Detail enrichment** → call `UpdateReservation_GetReservation` and `ClinicRequestDetail_GetPatientRequest2`.
4. **Storage/reporting** → save to MySQL/Excel for vaccine planning.
| Page | URL |
|------|-----|
| Search | `/mudr-buzalkova/klinika/hledat/?q={query}` |
| Patient card | `/mudr-buzalkova/klinika/hledat/?q={query}&pacient={uuid}` |
| Request detail | `/mudr-buzalkova/klinika/hledat/?q={query}&pozadavek={uuid}` |
| Requests (active) | `/mudr-buzalkova/klinika/pozadavky/` |
| Requests (done) | `/mudr-buzalkova/klinika/pozadavky?vyrizene=1` |
| Calendar | `/mudr-buzalkova/klinika/kalendar/?kalendar={calendarId}&pohled=pracovni-tyden` |
| Patient list | `/mudr-buzalkova/klinika/kartoteka/` |
| References | `/mudr-buzalkova/klinika/reference` |
| Treatment plans | `/mudr-buzalkova/klinika/lecebne-plany/pacienti` |
| Settings - requests | `/mudr-buzalkova/klinika/nastaveni/pozadavky` |
| Settings - groups | `/mudr-buzalkova/klinika/nastaveni/skupiny-pozadavku` |
| Settings - invites | `/mudr-buzalkova/klinika/nastaveni/pozvanky` |
| Settings - integrations | `/mudr-buzalkova/klinika/nastaveni/propojky` |
| Settings - hours | `/mudr-buzalkova/klinika/nastaveni/ordinacni-doba` |
| Settings - payments | `/mudr-buzalkova/klinika/nastaveni/platby` |
| Users | `/mudr-buzalkova/klinika/uzivatele/` |
---
## Insurance Companies (CZ)
| Code | Name |
|------|------|
| 0 | Ministerstvo zdravotnictvi CR |
| 111 | VZP |
| 201 | VoZP |
| 205 | CPZP |
| 207 | OZP |
| 209 | ZPS |
| 211 | ZPMV |
| 213 | RBP |
| 999 | Jina |
---
## Clinic Features (enabled)
RESERVATION_REMINDERS, PUSH_NOTIFICATIONS, INVITES, ON_DEMAND_SLOT_GENERATOR,
REQUEST_TYPES_ACCESS_RULES, CAN_REFER_PATIENTS, TREATMENT_PLANS_V2,
MEDICAL_RECORDS, CAMPAIGNS, PATIENT_SEGMENTATION, ADVANCED_CALENDAR_FUNCTIONS,
PATIENT_CLINIC_STATUS, STANDARD_TARIFF_FUNCTIONS, CLINIC_CLOSED_WARNINGS,
ADVANCED_SWITCHBOARD, REQUEST_AUTOMATIONS, REQUEST_PINNING,
AI_SWITCHBOARD_PROMO, PATIENT_REQUEST_SUBSTATES
---
## Security / Maintenance Notes
- GraphQL introspection disabled.
- Refresh session cookies periodically.
- GraphQL introspection disabled.
- Refresh session cookies periodically.
- Keep data GDPR-compliant.
---
## Future Tasks
- Automate cookie renewal.
- Build helper functions:
- `get_reservations(date)` using `ClinicAgenda_ListClinicReservations`
- `get_reservation_detail(reservation_id)`
- Map vaccine keywords (`Očkování Chřipka`, `COVID`, `Hepatitida`, …).
- Automate cookie renewal.
- Build helper functions:
- `get_reservations(date)` using `ClinicCalendar_ListClinicReservations`
- `get_reservation_detail(reservation_id)`
- `get_patient(patient_id)` using `ClinicPatientDetailModal_GetData`
- `list_patients(offset)` using `LegacyClinicPatientListPage_ListClinicPatients`
- `search_patients(query)` using `Search`
- `get_requests(state, offset)` using `ClinicLegacyRequestList_ListPatientRequestsForClinic`
- `get_request_detail(request_id)` using `ClinicRequestDetail_GetPatientRequest2`
- Map vaccine keywords.
- Export to Excel/MySQL for vaccine order planning.