Files
medevio/07VytvorPozadavekChripka01.py
2025-09-22 15:16:39 +02:00

190 lines
6.5 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pathlib import Path
from datetime import datetime
import re
import time
import pymysql
from pymysql.cursors import DictCursor
from playwright.sync_api import sync_playwright, TimeoutError as PWTimeout
# =====================================================
STATE_FILE = Path("medevio_storage.json") # saved login state from your login script
MYSQL_CFG = dict(
host="192.168.1.76",
port=3307,
user="root",
password="Vlado9674+",
database="medevio",
cursorclass=DictCursor,
autocommit=False,
)
UUID_COLUMN = "rid" # column with Medevio UUID
FLAG_COLUMN = "pozchripkavytvoren" # bool flag we update after success
FLAG_TS_COL = "pozchripka_vytv_at" # optional timestamp when request created
MESSAGE_TEXT = (
"Dobrý den, vakcína proti chřipce je k dispozici, "
"zítra (úterý 23.9) budeme očkovat od 13-17 hodin, "
"prosím potvrďte jestli můžete přijít a jaký čas se Vám hodí."
)
PATIENT_URL_TMPL = "https://my.medevio.cz/mudr-buzalkova/klinika/pacienti?pacient={uuid}"
RC_DIGITS = re.compile(r"\D+")
# =====================================================
def normalize_rc(rc: str) -> str:
"""Return digits-only RC (removes slash/spaces)."""
return RC_DIGITS.sub("", rc or "")
def ensure_flag_columns(conn):
"""Create required columns if missing (works for all MySQL/MariaDB)."""
needed = {
FLAG_COLUMN: "TINYINT(1) NULL",
FLAG_TS_COL: "DATETIME NULL",
}
with conn.cursor() as cur:
for col, coldef in needed.items():
cur.execute("""
SELECT COUNT(*) AS cnt
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'patients_extracted'
AND COLUMN_NAME = %s
""", (col,))
if cur.fetchone()["cnt"] == 0:
ddl = f"ALTER TABLE `patients_extracted` ADD COLUMN `{col}` {coldef}"
print("Adding column:", ddl)
cur.execute(ddl)
conn.commit()
def fetch_uuid_by_rc(conn, rc_digits: str) -> dict | None:
"""
Return row with rid (primary key), medevio UUID, jmeno, prijmeni for the given RC.
Prints the query and parameter for debugging.
"""
sql = (
f"SELECT rid, `{UUID_COLUMN}` AS uuid, jmeno, prijmeni, rc "
"FROM patients_extracted "
"WHERE REPLACE(REPLACE(rc,'/',''),' ','') = %s "
"LIMIT 1"
)
print("DEBUG SQL:", sql, "| param:", rc_digits)
with conn.cursor() as cur:
cur.execute(sql, (rc_digits,))
row = cur.fetchone()
print("DEBUG result:", row)
return row
def mark_flag_success(conn, rid: str):
"""Update the flag once the Medevio request is created."""
with conn.cursor() as cur:
cur.execute(
f"UPDATE patients_extracted "
f"SET {FLAG_COLUMN}=1, {FLAG_TS_COL}=NOW() "
f"WHERE rid=%s",
(rid,)
)
conn.commit()
def create_flu_request_for_uuid(uuid: str) -> bool:
"""Automates Medevio UI to create 'Očkování - Chřipka' request and send MESSAGE_TEXT."""
with sync_playwright() as p:
browser = p.chromium.launch(headless=False, slow_mo=200)
context = browser.new_context(storage_state=str(STATE_FILE))
ptcard = context.new_page()
url = PATIENT_URL_TMPL.format(uuid=uuid)
ptcard.goto(url, wait_until="networkidle")
# ensure patient card loaded
ptcard.get_by_text("Historie požadavků").wait_for(timeout=15_000)
# create new request
ptcard.get_by_role("button", name="Nový požadavek").click()
ptcard.wait_for_timeout(300)
ptcard.keyboard.type("očkování - chřipka")
ptcard.locator("[role='option']", has_text="Očkování - Chřipka").first.click()
ptcard.get_by_role("button", name="Vytvořit požadavek").click()
time.sleep(5)
# wait until back on card
try:
ptcard.get_by_text("Historie požadavků").wait_for(timeout=7_000)
except PWTimeout:
ptcard.goto(url, wait_until="networkidle")
ptcard.get_by_text("Historie požadavků").wait_for(timeout=10_000)
ptcard.reload(wait_until="networkidle")
ptcard.get_by_text("Historie požadavků").wait_for(timeout=10_000)
time.sleep(2)
# open the new request
try:
ptcard.locator("div[data-testid='patient-request-item']").first.wait_for(timeout=10_000)
chripka_card = ptcard.locator("div[data-testid='patient-request-item']").filter(
has=ptcard.locator("h4:has-text('Očkování - Chřipka')")
).first
chripka_card.click(timeout=5_000)
except Exception:
ptcard.locator("div[data-testid='patient-request-item']").first.click(timeout=5_000)
# send the message
try:
ptcard.wait_for_url("**/pozadavky?pozadavek=*", timeout=10_000)
except PWTimeout:
pass
ptcard.get_by_placeholder("Napište odpověď").wait_for(timeout=10_000)
ptcard.get_by_placeholder("Napište odpověď").fill(MESSAGE_TEXT)
for sel in [
"button:has-text('Odeslat')",
"button:has-text('Odeslat zprávu')",
"button:has-text('Odeslat SMS')",
"button:has-text('Odeslat do aplikace')",
]:
try:
ptcard.click(sel, timeout=4000)
browser.close()
return True
except Exception:
continue
browser.close()
return False
def main():
rc_input = input("Zadejte RC (s/bez lomítka, Enter pro konec): ").strip()
# rc_input="320312460"
if not rc_input:
print("Konec.")
return
rc = normalize_rc(rc_input)
conn = pymysql.connect(**MYSQL_CFG)
try:
ensure_flag_columns(conn)
row = fetch_uuid_by_rc(conn, rc)
if not row or not row.get("uuid"):
print(f"✗ Pacient s RC {rc} nenalezen nebo nemá sloupec {UUID_COLUMN}.")
return
print(f"→ Nalezen: {row.get('prijmeni','')} {row.get('jmeno','')} "
f"| RC {row.get('rc','')} | UUID {row['uuid']} | rid {row['rid']}")
if create_flu_request_for_uuid(row["uuid"]):
mark_flag_success(conn, row["rid"])
print("✅ Požadavek chřipka vytvořen a DB aktualizována.")
else:
print("✗ Nepodařilo se odeslat zprávu v požadavku.")
finally:
conn.close()
if __name__ == "__main__":
main()