diff --git a/VTMFDownloadFiles/download_state.csv.imported b/VTMFDownloadFiles/TRASH/download_state.csv.imported similarity index 100% rename from VTMFDownloadFiles/download_state.csv.imported rename to VTMFDownloadFiles/TRASH/download_state.csv.imported diff --git a/VTMFDownloadFiles/TRASH/export_from_seaweed_v1.0.py b/VTMFDownloadFiles/TRASH/export_from_seaweed_v1.0.py new file mode 100644 index 0000000..273c52a --- /dev/null +++ b/VTMFDownloadFiles/TRASH/export_from_seaweed_v1.0.py @@ -0,0 +1,111 @@ +# ============================================================ +# export_from_seaweed_v1.0.py +# Verze: 1.0 +# Datum: 2026-06-15 +# Popis: Sestaví na disk strom dokumentů jedné úrovně studie +# ze SeaweedFS (zdroj pravdy je Mongo VTMF.documents + +# objekty v SeaweedFS Fileru). Pojmenování podle původních +# Dropbox pravidel (pipeline v1.5): +# +# \\\ +# "YYYY-MM-DD Description [VTMF-xxx] [v1.0]." +# +# Datum/verze se vynechají, když chybí. Stahuje jen +# deleted=False, downloaded=True, placeholder!=True, +# se seaweed_path. Idempotentní — existující soubory +# přeskakuje (resume), takže lze pouštět opakovaně pro +# „aktuální verzi" čehokoli. +# +# Konfigurace (konstanty níže): STUDY, LEVEL, OUTPUT_ROOT. +# Pro jinou úroveň/studii stačí změnit tyto tři. +# +# Spuštění: +# & "...\.venv\Scripts\python.exe" "...\export_from_seaweed_v1.0.py" +# ============================================================ + +import re +import sys +import urllib.request +from pathlib import Path + +from pymongo import MongoClient, ASCENDING + +# --- Konfigurace ------------------------------------------------------- + +STUDY = "77242113UCO3001" +LEVEL = "study" # study | country | site +OUTPUT_ROOT = Path(r"U:\77242113UCO3001_STUDYLEVEL") + +MONGO_URI = "mongodb://192.168.1.76:27017" +MONGO_DB = "VTMF" +MONGO_COLL = "documents" + +OVERWRITE = False # True = přepsat i existující soubory + +BAD_CHARS_RE = re.compile(r"[<>:\"/\\|?*\x00-\x1f�]") + + +def log(msg): + print(msg, flush=True) + + +def clean(s): + s = BAD_CHARS_RE.sub("_", str(s or "")) + s = re.sub(r"\s+", " ", s) + s = re.sub(r"_{2,}", "_", s) + return s.strip(" ._") + + +def target_path(doc): + """\\\\\\ + 'YYYY-MM-DD Description [VTMF-xxx] [v1.0].'.""" + ext = Path(doc.get("seaweed_path", "")).suffix + date = doc.get("date") or "" + date_prefix = (date + " ") if date else "" + version = f" [{doc['version']}]" if doc.get("version") else "" + desc = clean(doc.get("desc")) or clean(doc.get("vtmf")) + filename = f"{date_prefix}{desc} [{doc['vtmf']}]{version}{ext}" + typ = clean(doc.get("type")) or "_" + sub = clean(doc.get("subtype")) or "_" + return OUTPUT_ROOT / typ / sub / filename + + +def main(): + coll = MongoClient(MONGO_URI, serverSelectionTimeoutMS=5000)[MONGO_DB][MONGO_COLL] + q = {"level": LEVEL, "deleted": False, "downloaded": True, + "placeholder": {"$ne": True}, "seaweed_path": {"$ne": None}} + docs = list(coll.find(q).sort([("vtmf", ASCENDING), ("version", ASCENDING)])) + log(f"[i] {LEVEL}-level dokumentů studie {STUDY}: {len(docs)}") + log(f"[i] Cíl: {OUTPUT_ROOT}\n") + + OUTPUT_ROOT.mkdir(parents=True, exist_ok=True) + written = skipped = failed = 0 + total_bytes = 0 + + for n, doc in enumerate(docs, 1): + dest = target_path(doc) + if dest.exists() and not OVERWRITE: + skipped += 1 + continue + try: + with urllib.request.urlopen(doc["seaweed_url"], timeout=120) as r: + data = r.read() + dest.parent.mkdir(parents=True, exist_ok=True) + dest.write_bytes(data) + written += 1 + total_bytes += len(data) + kb = len(data) / 1024 + size = f"{kb:.0f} KB" if kb < 1024 else f"{kb / 1024:.1f} MB" + log(f"[{n}/{len(docs)}] {dest.relative_to(OUTPUT_ROOT)} ({size})") + except Exception as e: + failed += 1 + log(f"[!] {doc['_id']}: {e}") + + mb = total_bytes / 1024 / 1024 + log(f"\n[ok] Hotovo: {written} zapsáno ({mb:.1f} MB), " + f"{skipped} přeskočeno (už existuje), {failed} chyb.") + sys.exit(1 if failed else 0) + + +if __name__ == "__main__": + main() diff --git a/VTMFDownloadFiles/TRASH/export_from_seaweed_v1.1.py b/VTMFDownloadFiles/TRASH/export_from_seaweed_v1.1.py new file mode 100644 index 0000000..5859e68 --- /dev/null +++ b/VTMFDownloadFiles/TRASH/export_from_seaweed_v1.1.py @@ -0,0 +1,167 @@ +# ============================================================ +# export_from_seaweed_v1.1.py +# Verze: 1.1 +# Datum: 2026-06-15 +# Popis: Sestaví na disk strom dokumentů studie ze SeaweedFS +# (zdroj pravdy = Mongo VTMF.documents + objekty ve Fileru). +# Pojmenování podle původních Dropbox pravidel (pipeline v1.5): +# +# \\\ +# "YYYY-MM-DD Description [VTMF-xxx] [v1.0]." +# +# Základní podadresář pod OUTPUT_ROOT podle úrovně: +# study -> STUDY +# country -> COUNTRY +# site -> <číslo centra> (dokument se zapíše do složky +# KAŽDÉHO centra, do kterého je referencovaný) +# +# RYCHLÉ NASTAVENÍ (nahoře): STUDY + OUTPUT_ROOT + přepínače EXPORT +# (True/False u study/country/site). +# +# Stahuje jen deleted=False, downloaded=True, placeholder!=True, +# se seaweed_path. Idempotentní — existující soubory přeskakuje +# (resume), takže lze pouštět opakovaně pro „aktuální verzi". +# +# v1.1: přepínače úrovní (True/False) + základní podadresář dle úrovně +# (STUDY / COUNTRY / číslo centra); site-level se kopíruje do +# složky každého centra. (v1.0 v TRASH/ — jen study, pevně.) +# +# Spuštění: +# & "...\.venv\Scripts\python.exe" "...\export_from_seaweed_v1.1.py" +# ============================================================ + +import re +import sys +import urllib.request +from pathlib import Path + +from pymongo import MongoClient, ASCENDING + +# ==================================================================== +# RYCHLÉ NASTAVENÍ +# ==================================================================== +STUDY = "77242113UCO3001" # která studie +OUTPUT_ROOT = Path(r"U:\77242113UCO3001") # kam (pod ní vzniknou + # podadresáře dle úrovně) + +# Co stáhnout — přepni True/False: +EXPORT = { + "study": True, # -> OUTPUT_ROOT\STUDY\\\... + "country": False, # -> OUTPUT_ROOT\COUNTRY\\\... + "site": False, # -> OUTPUT_ROOT\<číslo centra>\\\... +} + +OVERWRITE = False # True = přepsat i existující soubory +# ==================================================================== + +MONGO_URI = "mongodb://192.168.1.76:27017" +MONGO_DB = "VTMF" +MONGO_COLL = "documents" + +BAD_CHARS_RE = re.compile(r"[<>:\"/\\|?*\x00-\x1f�]") + + +def log(msg): + print(msg, flush=True) + + +def clean(s): + s = BAD_CHARS_RE.sub("_", str(s or "")) + s = re.sub(r"\s+", " ", s) + s = re.sub(r"_{2,}", "_", s) + return s.strip(" ._") + + +def filename_for(doc): + """'YYYY-MM-DD Description [VTMF-xxx] [v1.0].'.""" + ext = Path(doc.get("seaweed_path", "")).suffix + date = doc.get("date") or "" + date_prefix = (date + " ") if date else "" + version = f" [{doc['version']}]" if doc.get("version") else "" + desc = clean(doc.get("desc")) or clean(doc.get("vtmf")) + return f"{date_prefix}{desc} [{doc['vtmf']}]{version}{ext}" + + +def base_dirs_for(doc, level): + """Seznam základních podadresářů (pod OUTPUT_ROOT) pro daný dokument. + study -> [STUDY], country -> [COUNTRY], site -> [].""" + if level == "study": + return [OUTPUT_ROOT / "STUDY"] + if level == "country": + return [OUTPUT_ROOT / "COUNTRY"] + # site: jedna kopie do složky každého centra + sites = [clean(s) for s in doc.get("sites", []) if clean(s)] + if not sites: + return [OUTPUT_ROOT / "SITE_nezname"] + return [OUTPUT_ROOT / s for s in sites] + + +def target_paths(doc, level): + fname = filename_for(doc) + typ = clean(doc.get("type")) or "_" + sub = clean(doc.get("subtype")) or "_" + return [base / typ / sub / fname for base in base_dirs_for(doc, level)] + + +def export_level(coll, level): + q = {"level": level, "studies": STUDY, "deleted": False, + "downloaded": True, "placeholder": {"$ne": True}, + "seaweed_path": {"$ne": None}} + docs = list(coll.find(q).sort([("vtmf", ASCENDING), ("version", ASCENDING)])) + log(f"\n=== {level.upper()} === dokumentů: {len(docs)}") + if not docs: + if level != "study": + log(f"[i] (žádné {level}-level dokumenty v Mongo — pipeline pro " + f"tuto úroveň zatím možná neproběhla)") + return 0, 0, 0, 0 + + written = skipped = failed = 0 + total_bytes = 0 + for n, doc in enumerate(docs, 1): + dests = target_paths(doc, level) + need = dests if OVERWRITE else [d for d in dests if not d.exists()] + if not need: + skipped += len(dests) + continue + try: + with urllib.request.urlopen(doc["seaweed_url"], timeout=120) as r: + data = r.read() + for dest in need: + dest.parent.mkdir(parents=True, exist_ok=True) + dest.write_bytes(data) + written += 1 + total_bytes += len(data) + skipped += len(dests) - len(need) + kb = len(data) / 1024 + size = f"{kb:.0f} KB" if kb < 1024 else f"{kb / 1024:.1f} MB" + extra = f" (+{len(need)} kopií)" if len(need) > 1 else "" + log(f"[{n}/{len(docs)}] {need[0].relative_to(OUTPUT_ROOT)} ({size}){extra}") + except Exception as e: + failed += 1 + log(f"[!] {doc['_id']}: {e}") + return written, skipped, failed, total_bytes + + +def main(): + coll = MongoClient(MONGO_URI, serverSelectionTimeoutMS=5000)[MONGO_DB][MONGO_COLL] + levels = [lvl for lvl in ("study", "country", "site") if EXPORT.get(lvl)] + log(f"[i] Studie: {STUDY}") + log(f"[i] Cíl: {OUTPUT_ROOT}") + log(f"[i] Úrovně: {', '.join(levels) if levels else '(žádná — zapni něco v EXPORT)'}") + if not levels: + sys.exit(0) + + OUTPUT_ROOT.mkdir(parents=True, exist_ok=True) + tw = ts = tf = tb = 0 + for level in levels: + w, s, f, b = export_level(coll, level) + tw += w; ts += s; tf += f; tb += b + + mb = tb / 1024 / 1024 + log(f"\n[ok] Hotovo: {tw} souborů zapsáno ({mb:.1f} MB), " + f"{ts} přeskočeno (už existuje), {tf} chyb.") + sys.exit(1 if tf else 0) + + +if __name__ == "__main__": + main() diff --git a/VTMFDownloadFiles/seaweed_backfill_v1.1.py b/VTMFDownloadFiles/TRASH/seaweed_backfill_v1.1.py similarity index 100% rename from VTMFDownloadFiles/seaweed_backfill_v1.1.py rename to VTMFDownloadFiles/TRASH/seaweed_backfill_v1.1.py diff --git a/VTMFDownloadFiles/test_seaweed.py b/VTMFDownloadFiles/TRASH/test_seaweed.py similarity index 100% rename from VTMFDownloadFiles/test_seaweed.py rename to VTMFDownloadFiles/TRASH/test_seaweed.py diff --git a/VTMFDownloadFiles/WhatToDownload/Zpracovano/2026-06-15_16-12-04 study Document Inventory Report - Study Level.xlsx b/VTMFDownloadFiles/WhatToDownload/Zpracovano/2026-06-15_16-12-04 study Document Inventory Report - Study Level.xlsx new file mode 100644 index 0000000..0040648 Binary files /dev/null and b/VTMFDownloadFiles/WhatToDownload/Zpracovano/2026-06-15_16-12-04 study Document Inventory Report - Study Level.xlsx differ diff --git a/VTMFDownloadFiles/WhatToDownload/Zpracovano/2026-06-15_16-12-15 country Document Inventory Report - Country Level - Selected Country.xlsx b/VTMFDownloadFiles/WhatToDownload/Zpracovano/2026-06-15_16-12-15 country Document Inventory Report - Country Level - Selected Country.xlsx new file mode 100644 index 0000000..2abf177 Binary files /dev/null and b/VTMFDownloadFiles/WhatToDownload/Zpracovano/2026-06-15_16-12-15 country Document Inventory Report - Country Level - Selected Country.xlsx differ diff --git a/VTMFDownloadFiles/export_from_seaweed_v1.2.md b/VTMFDownloadFiles/export_from_seaweed_v1.2.md new file mode 100644 index 0000000..e7fd1dd --- /dev/null +++ b/VTMFDownloadFiles/export_from_seaweed_v1.2.md @@ -0,0 +1,69 @@ +# export_from_seaweed_v1.2 — sestavení stromu dokumentů ze SeaweedFS + +**Verze:** 1.2 · **Datum:** 2026-06-15 + +Sestaví na disk strom dokumentů studie z **Mongo `VTMF.documents` + objektů +v SeaweedFS Fileru**. Náhrada za dřívější ukládání do Dropboxu — pipeline +ukládá jen do SeaweedFS, tenhle skript kdykoli „vytáhne aktuální verzi" +čehokoli na disk pod čitelnými jmény. + +## ⚠️ Pravidlo příslušnosti ke studii = `scopes[]`, NE `studies[]` + +Tohle je klíčové a platí pro každý dotaz „co je ve VTMF na study/country/site +úrovni studie X": + +- **`scopes[]`** = `"||"` — odkud jsme dokument reálně + natáhli (který report/úroveň). **Tohle určuje příslušnost** k TMF studie. +- **`studies[]`** = jen M:N reference — kam všude je dokument ve Vaultu + přilinkovaný (klidně 8–12 studií). Pro výběr „TMF studie X" se NEpoužívá. + +Příklad: dokument sdílený s CRD3001/MDD3003 je má v `studies[]`, ale když má +`scopes=['study|77242113UCO3001|']`, patří do TMF **UCO3001**, ne CRD3001. +Skript proto vybírá přes scopes (regex `^\|\|`); studie, která +přes scopes nemá nic (neproběhla pro ni pipeline), se přeskočí. + +## Pojmenování a struktura + +Podle původních Dropbox pravidel (pipeline v1.5): + +``` +\\\\ + "YYYY-MM-DD Description [VTMF-xxx] [v1.0]." +``` + +Základní podadresář podle úrovně: + +| Úroveň | Podadresář | Poznámka | +|---|---|---| +| study | `STUDY` | | +| country | `COUNTRY` | | +| site | `<číslo centra>` | dokument se zapíše do složky **každého** centra ve `sites[]` (sdílený dokument = víc kopií → browsable strom po centrech) | + +Datum / verze se z názvu vynechají, když chybí. `Type`/`Subtype` prázdné → `_`. + +## Rychlé nastavení (nahoře ve skriptu) + +```python +STUDIES = ["77242113UCO3001", "77242113UCO3002", + "77242113CRD3001", "42847922MDD3003"] # víc najednou +OUTPUT_ROOT_TMPL = r"U:\{study}" # {study} = kód studie +EXPORT = {"study": True, "country": True, "site": True} # True/False +OVERWRITE = False # True = přepsat existující +``` + +## Chování + +- Stahuje jen `deleted=False, downloaded=True, placeholder!=True, seaweed_path!=None`. +- **Idempotentní** — existující soubory přeskakuje (resume). Lze pouštět + opakovaně pro „aktuální stav". +- Stáhne obsah jednoho dokumentu jednou, u site-level ho zapíše do všech + cílových složek center. +- Studie bez scopes se přeskočí s hláškou (pipeline pro ni ještě neběžela). + +## Spuštění + +```powershell +& "U:\PythonProject\Janssen\.venv\Scripts\python.exe" "U:\PythonProject\Janssen\VTMFDownloadFiles\export_from_seaweed_v1.2.py" +``` + +Předchůdci: v1.0 (jen study, pevně), v1.1 (přepínače, filtr přes studies[]) — v TRASH/. diff --git a/VTMFDownloadFiles/export_from_seaweed_v1.2.py b/VTMFDownloadFiles/export_from_seaweed_v1.2.py new file mode 100644 index 0000000..af356c9 --- /dev/null +++ b/VTMFDownloadFiles/export_from_seaweed_v1.2.py @@ -0,0 +1,186 @@ +# ============================================================ +# export_from_seaweed_v1.2.py +# Verze: 1.2 +# Datum: 2026-06-15 +# Popis: Sestaví na disk strom dokumentů studie ze SeaweedFS +# (zdroj pravdy = Mongo VTMF.documents + objekty ve Fileru). +# Pojmenování podle původních Dropbox pravidel (pipeline v1.5): +# +# \\\ +# "YYYY-MM-DD Description [VTMF-xxx] [v1.0]." +# +# Základní podadresář pod OUTPUT_ROOT podle úrovně: +# study -> STUDY +# country -> COUNTRY +# site -> <číslo centra> (dokument se zapíše do složky +# KAŽDÉHO centra, do kterého je referencovaný) +# +# PŘÍSLUŠNOST KE STUDII = pole scopes[] (ne studies[]!). +# Dokument patří studii X na úrovni L, pokud má scope +# "L|X|..." — tj. byl reálně natažen reportem té studie/úrovně. +# studies[] je jen M:N reference (kam všude je přilinkovaný) +# a pro výběr „TMF studie X" se NEpoužívá. +# +# RYCHLÉ NASTAVENÍ (nahoře): STUDIES + OUTPUT_ROOT_TMPL + přepínače +# EXPORT (True/False u study/country/site). +# +# Stahuje jen deleted=False, downloaded=True, placeholder!=True, +# se seaweed_path. Idempotentní — existující soubory přeskakuje +# (resume), takže lze pouštět opakovaně pro „aktuální verzi". +# +# v1.2: výběr podle scopes[] (ne studies[]); více studií najednou +# (seznam STUDIES). (v1.0/v1.1 v TRASH/.) +# +# Spuštění: +# & "...\.venv\Scripts\python.exe" "...\export_from_seaweed_v1.2.py" +# ============================================================ + +import re +import sys +import urllib.request +from pathlib import Path + +from pymongo import MongoClient, ASCENDING + +# ==================================================================== +# RYCHLÉ NASTAVENÍ +# ==================================================================== +# Které studie sestavit (podle scopes[]). Klidně víc najednou. +STUDIES = [ + "77242113UCO3001", + "77242113UCO3002", + "77242113CRD3001", + "42847922MDD3003", +] + +# Kam: {study} se nahradí kódem studie. Pod tím vzniknou podadresáře +# dle úrovně (STUDY / COUNTRY / číslo centra). +OUTPUT_ROOT_TMPL = r"U:\{study}" + +# Co stáhnout — přepni True/False: +EXPORT = { + "study": True, # -> \STUDY\\\... + "country": True, # -> \COUNTRY\\\... + "site": True, # -> \<číslo centra>\\\... +} + +OVERWRITE = False # True = přepsat i existující soubory +# ==================================================================== + +MONGO_URI = "mongodb://192.168.1.76:27017" +MONGO_DB = "VTMF" +MONGO_COLL = "documents" + +BAD_CHARS_RE = re.compile(r"[<>:\"/\\|?*\x00-\x1f�]") + + +def log(msg): + print(msg, flush=True) + + +def clean(s): + s = BAD_CHARS_RE.sub("_", str(s or "")) + s = re.sub(r"\s+", " ", s) + s = re.sub(r"_{2,}", "_", s) + return s.strip(" ._") + + +def filename_for(doc): + """'YYYY-MM-DD Description [VTMF-xxx] [v1.0].'.""" + ext = Path(doc.get("seaweed_path", "")).suffix + date = doc.get("date") or "" + date_prefix = (date + " ") if date else "" + version = f" [{doc['version']}]" if doc.get("version") else "" + desc = clean(doc.get("desc")) or clean(doc.get("vtmf")) + return f"{date_prefix}{desc} [{doc['vtmf']}]{version}{ext}" + + +def base_dirs_for(doc, level, root): + """Seznam základních podadresářů (pod root) pro daný dokument. + study -> [STUDY], country -> [COUNTRY], site -> [].""" + if level == "study": + return [root / "STUDY"] + if level == "country": + return [root / "COUNTRY"] + sites = [clean(s) for s in doc.get("sites", []) if clean(s)] + return [root / s for s in sites] if sites else [root / "SITE_nezname"] + + +def target_paths(doc, level, root): + fname = filename_for(doc) + typ = clean(doc.get("type")) or "_" + sub = clean(doc.get("subtype")) or "_" + return [base / typ / sub / fname for base in base_dirs_for(doc, level, root)] + + +def export_study_level(coll, study, level, root): + # příslušnost ke studii/úrovni přes scope "level|study|..." + scope_prefix = re.escape(f"{level}|{study}|") + q = {"scopes": {"$regex": f"^{scope_prefix}"}, + "deleted": False, "downloaded": True, + "placeholder": {"$ne": True}, "seaweed_path": {"$ne": None}} + docs = list(coll.find(q).sort([("vtmf", ASCENDING), ("version", ASCENDING)])) + log(f" [{level}] dokumentů: {len(docs)}") + if not docs: + return 0, 0, 0, 0 + + written = skipped = failed = 0 + total_bytes = 0 + for n, doc in enumerate(docs, 1): + dests = target_paths(doc, level, root) + need = dests if OVERWRITE else [d for d in dests if not d.exists()] + if not need: + skipped += len(dests) + continue + try: + with urllib.request.urlopen(doc["seaweed_url"], timeout=120) as r: + data = r.read() + for dest in need: + dest.parent.mkdir(parents=True, exist_ok=True) + dest.write_bytes(data) + written += 1 + total_bytes += len(data) + skipped += len(dests) - len(need) + kb = len(data) / 1024 + size = f"{kb:.0f} KB" if kb < 1024 else f"{kb / 1024:.1f} MB" + extra = f" (+{len(need)} kopií)" if len(need) > 1 else "" + log(f" [{n}/{len(docs)}] {need[0].relative_to(root)} ({size}){extra}") + except Exception as e: + failed += 1 + log(f" [!] {doc['_id']}: {e}") + return written, skipped, failed, total_bytes + + +def main(): + coll = MongoClient(MONGO_URI, serverSelectionTimeoutMS=5000)[MONGO_DB][MONGO_COLL] + levels = [lvl for lvl in ("study", "country", "site") if EXPORT.get(lvl)] + log(f"[i] Studie: {', '.join(STUDIES)}") + log(f"[i] Úrovně: {', '.join(levels) if levels else '(žádná)'}") + log(f"[i] Cíl: {OUTPUT_ROOT_TMPL}\n") + if not levels: + sys.exit(0) + + gw = gs = gf = gb = 0 + for study in STUDIES: + root = Path(OUTPUT_ROOT_TMPL.format(study=study)) + # má studie přes scopes vůbec něco? + has = coll.count_documents({"scopes": {"$regex": f"^[a-z]+\\|{re.escape(study)}\\|"}}) + log(f"=== {study} -> {root} (scoped dokumentů: {has}) ===") + if not has: + log(f"[i] {study}: přes scopes nic — pipeline pro tuto studii " + f"zatím neproběhla, přeskakuji.\n") + continue + root.mkdir(parents=True, exist_ok=True) + for level in levels: + w, s, f, b = export_study_level(coll, study, level, root) + gw += w; gs += s; gf += f; gb += b + log("") + + mb = gb / 1024 / 1024 + log(f"[ok] Hotovo: {gw} souborů zapsáno ({mb:.1f} MB), " + f"{gs} přeskočeno (už existuje), {gf} chyb.") + sys.exit(1 if gf else 0) + + +if __name__ == "__main__": + main() diff --git a/VTMFDownloadFiles/vtmf_pipeline_v1.3.md b/VTMFDownloadFiles/vtmf_pipeline_v1.3.md deleted file mode 100644 index 6da18b0..0000000 --- a/VTMFDownloadFiles/vtmf_pipeline_v1.3.md +++ /dev/null @@ -1,102 +0,0 @@ -# vtmf_pipeline_v1.3 — Kompletní V-TMF workflow (report → Mongo → download) - -**Verze:** 1.3 · **Datum:** 2026-06-12 - -**Změny v1.1:** oprava tichého selhání — výjimka kteréhokoli kroku se -vypíše jako „PIPELINE SELHALA" + exit kód 2 (v1.0 končila zavádějícím -souhrnem „0 staženo, 0 chyb"). Export reportu robustnější: menu ⋯, -položka Export to Excel i tlačítko Export se hledají přes víc selektorů -a ve všech frames; při nenalezení se automaticky uloží diagnostika -stránky do debug/<čas>_report_* (screenshot, HTML všech frames, výpis -title/aria-label atributů) — z ní se dá určit přesný selektor. - -**Změny v1.2:** selektory exportu ověřené na živém DOM (Claude in -Chrome; žádný iframe na celé stránce): menu ⋯ = -`.actionMenuContainer .dropDown.vv_dropdown_toggle button.vv-icon-button` -(button má prázdný title!); menu se načítá asynchronně (AJAX) → -po kliknutí se čeká na položku `a.ReportAction[data-action-name='ExcelExport']`; -„Data Only" = radio `name=requiredRadioField value=STANDARD`, defaultně -checked (pojistka přes .check()); tlačítko Export = React `