From f8ada463a266f76fecfaa5a3f1655ad4def40a41 Mon Sep 17 00:00:00 2001 From: vlado Date: Sun, 30 Nov 2025 20:21:01 +0100 Subject: [PATCH] reporter --- .../PRAVIDELNE_0_READ_ALL_ACTIVE_POZADAVKY.py | 2 +- .../PRAVIDELNE_1_ReadLast300DonePozadavku.py | 2 +- 10ReadPozadavky/PRAVIDELNE_2_ReadPoznamky.py | 2 +- .../PRAVIDELNE_3_StahniKomunikaci.py | 2 +- .../PRAVIDELNE_4_StahniPrilohyUlozDoMySQL.py | 2 +- ...AVIDELNE_5_SaveToFileSystem incremental.py | 120 ++++++++---------- 6 files changed, 57 insertions(+), 73 deletions(-) diff --git a/10ReadPozadavky/PRAVIDELNE_0_READ_ALL_ACTIVE_POZADAVKY.py b/10ReadPozadavky/PRAVIDELNE_0_READ_ALL_ACTIVE_POZADAVKY.py index 4fb8c7f..cbabdcf 100644 --- a/10ReadPozadavky/PRAVIDELNE_0_READ_ALL_ACTIVE_POZADAVKY.py +++ b/10ReadPozadavky/PRAVIDELNE_0_READ_ALL_ACTIVE_POZADAVKY.py @@ -16,7 +16,7 @@ CLINIC_SLUG = "mudr-buzalkova" BATCH_SIZE = 100 DB_CONFIG = { - "host": "127.0.0.1", + "host": "192.168.1.76", "port": 3307, "user": "root", "password": "Vlado9674+", diff --git a/10ReadPozadavky/PRAVIDELNE_1_ReadLast300DonePozadavku.py b/10ReadPozadavky/PRAVIDELNE_1_ReadLast300DonePozadavku.py index dc16a25..f7d4590 100644 --- a/10ReadPozadavky/PRAVIDELNE_1_ReadLast300DonePozadavku.py +++ b/10ReadPozadavky/PRAVIDELNE_1_ReadLast300DonePozadavku.py @@ -15,7 +15,7 @@ CLINIC_SLUG = "mudr-buzalkova" LIMIT = 300 # stáhneme posledních 300 ukončených požadavků DB_CONFIG = { - "host": "127.0.0.1", + "host": "192.168.1.76", "port": 3307, "user": "root", "password": "Vlado9674+", diff --git a/10ReadPozadavky/PRAVIDELNE_2_ReadPoznamky.py b/10ReadPozadavky/PRAVIDELNE_2_ReadPoznamky.py index d3b32bd..b742f2f 100644 --- a/10ReadPozadavky/PRAVIDELNE_2_ReadPoznamky.py +++ b/10ReadPozadavky/PRAVIDELNE_2_ReadPoznamky.py @@ -21,7 +21,7 @@ CLINIC_SLUG = "mudr-buzalkova" GRAPHQL_URL = "https://api.medevio.cz/graphql" DB_CONFIG = { - "host": "127.0.0.1", + "host": "192.168.1.76", "port": 3307, "user": "root", "password": "Vlado9674+", diff --git a/10ReadPozadavky/PRAVIDELNE_3_StahniKomunikaci.py b/10ReadPozadavky/PRAVIDELNE_3_StahniKomunikaci.py index ed5d46b..2b05def 100644 --- a/10ReadPozadavky/PRAVIDELNE_3_StahniKomunikaci.py +++ b/10ReadPozadavky/PRAVIDELNE_3_StahniKomunikaci.py @@ -22,7 +22,7 @@ import time TOKEN_PATH = Path("token.txt") DB_CONFIG = { - "host": "127.0.0.1", + "host": "192.168.1.76", "port": 3307, "user": "root", "password": "Vlado9674+", diff --git a/10ReadPozadavky/PRAVIDELNE_4_StahniPrilohyUlozDoMySQL.py b/10ReadPozadavky/PRAVIDELNE_4_StahniPrilohyUlozDoMySQL.py index afbbe6a..1a7d578 100644 --- a/10ReadPozadavky/PRAVIDELNE_4_StahniPrilohyUlozDoMySQL.py +++ b/10ReadPozadavky/PRAVIDELNE_4_StahniPrilohyUlozDoMySQL.py @@ -22,7 +22,7 @@ TOKEN_PATH = Path("token.txt") CLINIC_SLUG = "mudr-buzalkova" DB_CONFIG = { - "host": "127.0.0.1", + "host": "192.168.1.76", "port": 3307, "user": "root", "password": "Vlado9674+", diff --git a/10ReadPozadavky/PRAVIDELNE_5_SaveToFileSystem incremental.py b/10ReadPozadavky/PRAVIDELNE_5_SaveToFileSystem incremental.py index 6c4948c..6d907c4 100644 --- a/10ReadPozadavky/PRAVIDELNE_5_SaveToFileSystem incremental.py +++ b/10ReadPozadavky/PRAVIDELNE_5_SaveToFileSystem incremental.py @@ -8,12 +8,29 @@ import re from pathlib import Path from datetime import datetime import time +import sys + +# ============================== +# 🛡 SAFE PRINT FOR CP1250 / EMOJI +# ============================== +def safe_print(text: str = ""): + enc = sys.stdout.encoding or "" + if not enc.lower().startswith("utf"): + # Strip emoji and characters outside BMP for Task Scheduler + text = ''.join(ch for ch in text if ord(ch) < 65536) + try: + print(text) + except UnicodeEncodeError: + # ASCII fallback + text = ''.join(ch for ch in text if ord(ch) < 128) + print(text) + # ============================== # ⚙️ CONFIGURATION # ============================== DB_CONFIG = { - "host": "127.0.0.1", + "host": "192.168.1.76", "port": 3307, "user": "root", "password": "Vlado9674+", @@ -31,24 +48,15 @@ def sanitize_name(name: str) -> str: def make_abbrev(title: str) -> str: - """ - Create abbreviation from displayTitle: - - First letter of each word - - Keep digits together - - Uppercase - """ if not title: return "" - words = re.findall(r"[A-Za-zÁ-Žá-ž0-9]+", title) - abbr = "" for w in words: if w.isdigit(): abbr += w else: abbr += w[0] - return abbr.upper() @@ -56,28 +64,20 @@ def make_abbrev(title: str) -> str: # 🧹 DELETE UNEXPECTED FILES # ============================== def clean_folder(folder: Path, valid_files: set): - """ - Remove unexpected files. - RULE: - - Files starting with `▲` are ALWAYS kept. - """ if not folder.exists(): return for f in folder.iterdir(): if f.is_file(): - - # zpracované soubory (▲filename.pdf) nikdy nemažeme if f.name.startswith("▲"): continue - sanitized = sanitize_name(f.name) if sanitized not in valid_files: - print(f"🗑️ Removing unexpected file: {f.name}") + safe_print(f"🗑️ Removing unexpected file: {f.name}") try: f.unlink() except Exception as e: - print(f"⚠️ Could not delete {f}: {e}") + safe_print(f"⚠️ Could not delete {f}: {e}") # ============================== @@ -88,30 +88,30 @@ conn = pymysql.connect(**DB_CONFIG) cur_meta = conn.cursor(pymysql.cursors.DictCursor) cur_blob = conn.cursor() -print("🔍 Loading metadata from DB (FAST)…") +safe_print("🔍 Loading metadata from DB (FAST)…") cur_meta.execute(""" SELECT d.id AS download_id, - d.request_id, - d.filename, - d.created_at, - p.updatedAt AS req_updated_at, - p.pacient_jmeno AS jmeno, - p.pacient_prijmeni AS prijmeni, - p.displayTitle - FROM medevio_downloads d - JOIN pozadavky p ON d.request_id = p.id - ORDER BY p.updatedAt DESC + d.request_id, + d.filename, + d.created_at, + p.updatedAt AS req_updated_at, + p.pacient_jmeno AS jmeno, + p.pacient_prijmeni AS prijmeni, + p.displayTitle +FROM medevio_downloads d +JOIN pozadavky p ON d.request_id = p.id +WHERE d.downloaded_at IS NULL +ORDER BY p.updatedAt DESC """) rows = cur_meta.fetchall() -print(f"📋 Found {len(rows)} attachment records.\n") +safe_print(f"📋 Found {len(rows)} attachment records.\n") # ============================== # 🧠 MAIN LOOP WITH PROGRESS # ============================== -# list of unique request_ids in order unique_request_ids = [] seen = set() for r in rows: @@ -121,7 +121,7 @@ for r in rows: seen.add(req_id) total_requests = len(unique_request_ids) -print(f"🔄 Processing {total_requests} unique requests...\n") +safe_print(f"🔄 Processing {total_requests} unique requests...\n") processed_requests = set() current_index = 0 @@ -136,17 +136,16 @@ for r in rows: current_index += 1 percent = (current_index / total_requests) * 100 - print(f"\n[ {percent:5.1f}% ] Processing request {current_index} / {total_requests} → {req_id}") + safe_print(f"\n[ {percent:5.1f}% ] Processing request {current_index} / {total_requests} → {req_id}") - # ========== FETCH ALL VALID FILES FOR THIS REQUEST ========== + # ========== FETCH VALID FILENAMES ========== cur_meta.execute( "SELECT filename FROM medevio_downloads WHERE request_id=%s", (req_id,) ) - valid_files = {sanitize_name(row["filename"]) for row in cur_meta.fetchall()} - # ========== FOLDER NAME BASED ON UPDATEDAT ========== + # ========== BUILD FOLDER NAME ========== updated_at = r["req_updated_at"] or datetime.now() date_str = updated_at.strftime("%Y-%m-%d") @@ -159,17 +158,14 @@ for r in rows: f"{date_str} {prijmeni}, {jmeno} [{abbr}] {req_id}" ) - # ========== DETECT EXISTING FOLDER (WITH OR WITHOUT ▲) ========== + # ========== DETECT EXISTING FOLDER ========== existing_folder = None - folder_has_flag = False for f in BASE_DIR.iterdir(): if f.is_dir() and req_id in f.name: existing_folder = f - folder_has_flag = ("▲" in f.name) break - # pokud složka existuje → pracujeme v ní main_folder = existing_folder if existing_folder else BASE_DIR / clean_folder_name # ========== MERGE DUPLICATES ========== @@ -179,14 +175,13 @@ for r in rows: ] for dup in possible_dups: - print(f"♻️ Merging duplicate folder: {dup.name}") + safe_print(f"♻️ Merging duplicate folder: {dup.name}") clean_folder(dup, valid_files) main_folder.mkdir(parents=True, exist_ok=True) for f in dup.iterdir(): if f.is_file(): - # prostě přesuneme, ▲ případně zůstane v názvu target = main_folder / f.name if not target.exists(): f.rename(target) @@ -204,11 +199,9 @@ for r in rows: dest_plain = main_folder / filename dest_marked = main_folder / ("▲" + filename) - # soubor už existuje (buď filename, nebo ▲filename) if dest_plain.exists() or dest_marked.exists(): continue - # stáhneme nový soubor → znamená že se má odstranit ▲ složky added_new_file = True cur_blob.execute( @@ -227,31 +220,22 @@ for r in rows: with open(dest_plain, "wb") as f: f.write(content) - print(f"💾 Wrote: {dest_plain.relative_to(BASE_DIR)}") + safe_print(f"💾 Wrote: {dest_plain.relative_to(BASE_DIR)}") - # ============================== - # 🔵 REMOVE FOLDER-LEVEL ▲ ONLY IF NEW FILE ADDED - # ============================== - if added_new_file: - # složka se má přejmenovat bez ▲ - if "▲" in main_folder.name: - new_name = main_folder.name.replace("▲", "") - new_name = new_name.strip() # pro jistotu - new_path = main_folder.parent / new_name + # ========== REMOVE ▲ FLAG IF NEW FILES ADDED ========== + if added_new_file and "▲" in main_folder.name: + new_name = main_folder.name.replace("▲", "").strip() + new_path = main_folder.parent / new_name - if new_path != main_folder: - try: - main_folder.rename(new_path) - print(f"🔄 Folder flag ▲ removed → {new_name}") - main_folder = new_path - except Exception as e: - print(f"⚠️ Could not rename folder: {e}") - else: - # žádné nové soubory → NIKDY nesahat na název složky - pass + if new_path != main_folder: + try: + main_folder.rename(new_path) + safe_print(f"🔄 Folder flag ▲ removed → {new_name}") + main_folder = new_path + except Exception as e: + safe_print(f"⚠️ Could not rename folder: {e}") - -print("\n🎯 Export complete.\n") +safe_print("\n🎯 Export complete.\n") cur_blob.close() cur_meta.close()