notebook
This commit is contained in:
@@ -4,8 +4,9 @@
|
||||
import pymysql
|
||||
import requests
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
import time
|
||||
from dateutil import parser
|
||||
|
||||
# ================================
|
||||
# 🔧 CONFIGURATION
|
||||
@@ -24,21 +25,22 @@ DB_CONFIG = {
|
||||
"cursorclass": pymysql.cursors.DictCursor,
|
||||
}
|
||||
|
||||
# ⭐ NOVÝ TESTOVANÝ DOTAZ – obsahuje lastMessage.createdAt
|
||||
GRAPHQL_QUERY = r"""
|
||||
query ClinicRequestGrid_ListPatientRequestsForClinic2(
|
||||
query ClinicRequestList2(
|
||||
$clinicSlug: String!,
|
||||
$queueId: String,
|
||||
$queueAssignment: QueueAssignmentFilter!,
|
||||
$state: PatientRequestState,
|
||||
$pageInfo: PageInfo!,
|
||||
$locale: Locale!,
|
||||
$state: PatientRequestState
|
||||
$locale: Locale!
|
||||
) {
|
||||
requestsResponse: listPatientRequestsForClinic2(
|
||||
clinicSlug: $clinicSlug,
|
||||
queueId: $queueId,
|
||||
queueAssignment: $queueAssignment,
|
||||
pageInfo: $pageInfo,
|
||||
state: $state
|
||||
state: $state,
|
||||
pageInfo: $pageInfo
|
||||
) {
|
||||
count
|
||||
patientRequests {
|
||||
@@ -53,40 +55,71 @@ query ClinicRequestGrid_ListPatientRequestsForClinic2(
|
||||
surname
|
||||
identificationNumber
|
||||
}
|
||||
lastMessage {
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
# ================================
|
||||
# 🧿 SAFE DATETIME PARSER (ALWAYS UTC → LOCAL)
|
||||
# ================================
|
||||
def to_mysql_dt_utc(iso_str):
|
||||
"""
|
||||
Parse Medevio timestamps safely.
|
||||
Treat timestamps WITHOUT timezone as UTC.
|
||||
Convert to local time before saving to MySQL.
|
||||
"""
|
||||
if not iso_str:
|
||||
return None
|
||||
try:
|
||||
dt = parser.isoparse(iso_str)
|
||||
|
||||
# If tz is missing → assume UTC
|
||||
if dt.tzinfo is None:
|
||||
dt = dt.replace(tzinfo=timezone.utc)
|
||||
|
||||
# Convert to local timezone
|
||||
dt_local = dt.astimezone()
|
||||
|
||||
return dt_local.strftime("%Y-%m-%d %H:%M:%S")
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
# ================================
|
||||
# 🔑 TOKEN
|
||||
# ================================
|
||||
def read_token(path: Path) -> str:
|
||||
tok = path.read_text(encoding="utf-8").strip()
|
||||
if tok.startswith("Bearer "):
|
||||
tok = tok.split(" ", 1)[1]
|
||||
return tok.split(" ", 1)[1]
|
||||
return tok
|
||||
|
||||
|
||||
# ================================
|
||||
# 🕒 DATETIME FORMAT
|
||||
# ================================
|
||||
def to_mysql_dt(iso_str):
|
||||
if not iso_str:
|
||||
return None
|
||||
try:
|
||||
dt = datetime.fromisoformat(iso_str.replace("Z", "+00:00"))
|
||||
return dt.strftime("%Y-%m-%d %H:%M:%S")
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
# ================================
|
||||
# 💾 UPSERT
|
||||
# 💾 UPSERT (včetně správného updatedAt)
|
||||
# ================================
|
||||
def upsert(conn, r):
|
||||
p = r.get("extendedPatient") or {}
|
||||
|
||||
# raw timestamps z API – nyní přes nový parser
|
||||
api_updated = to_mysql_dt_utc(r.get("updatedAt"))
|
||||
|
||||
last_msg = r.get("lastMessage") or {}
|
||||
msg_updated = to_mysql_dt_utc(last_msg.get("createdAt"))
|
||||
|
||||
# nejnovější změna
|
||||
def max_dt(a, b):
|
||||
if a and b:
|
||||
return max(a, b)
|
||||
return a or b
|
||||
|
||||
final_updated = max_dt(api_updated, msg_updated)
|
||||
|
||||
sql = """
|
||||
INSERT INTO pozadavky (
|
||||
id, displayTitle, createdAt, updatedAt, doneAt, removedAt,
|
||||
@@ -105,10 +138,10 @@ def upsert(conn, r):
|
||||
vals = (
|
||||
r.get("id"),
|
||||
r.get("displayTitle"),
|
||||
to_mysql_dt(r.get("createdAt")),
|
||||
to_mysql_dt(r.get("updatedAt")),
|
||||
to_mysql_dt(r.get("doneAt")),
|
||||
to_mysql_dt(r.get("removedAt")),
|
||||
to_mysql_dt_utc(r.get("createdAt")),
|
||||
final_updated,
|
||||
to_mysql_dt_utc(r.get("doneAt")),
|
||||
to_mysql_dt_utc(r.get("removedAt")),
|
||||
p.get("name"),
|
||||
p.get("surname"),
|
||||
p.get("identificationNumber"),
|
||||
@@ -133,15 +166,15 @@ def fetch_active(headers, offset):
|
||||
}
|
||||
|
||||
payload = {
|
||||
"operationName": "ClinicRequestGrid_ListPatientRequestsForClinic2",
|
||||
"operationName": "ClinicRequestList2",
|
||||
"query": GRAPHQL_QUERY,
|
||||
"variables": variables,
|
||||
}
|
||||
|
||||
r = requests.post("https://api.medevio.cz/graphql", json=payload, headers=headers)
|
||||
r.raise_for_status()
|
||||
data = r.json().get("data", {}).get("requestsResponse", {})
|
||||
|
||||
data = r.json().get("data", {}).get("requestsResponse", {})
|
||||
return data.get("patientRequests", []), data.get("count", 0)
|
||||
|
||||
|
||||
@@ -160,9 +193,6 @@ def main():
|
||||
|
||||
print(f"\n=== Sync ACTIVE požadavků @ {datetime.now():%Y-%m-%d %H:%M:%S} ===")
|
||||
|
||||
# -------------------------------
|
||||
# 🚀 FETCH ALL ACTIVE REQUESTS
|
||||
# -------------------------------
|
||||
offset = 0
|
||||
total_processed = 0
|
||||
total_count = None
|
||||
@@ -193,5 +223,6 @@ def main():
|
||||
print("\n✅ ACTIVE sync hotovo!\n")
|
||||
|
||||
|
||||
# ================================
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user