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
+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.