# run_all_v1.1.py — IWRS: kompletní pipeline Pacienti + Léky **Verze:** 1.1 | **Datum:** 2026-06-10 - **v1.1:** všechny moduly pipeline přesunuty na úroveň `IWRS/` — adresáře `Patients/` a `Drugs/` už pipeline nepotřebuje. Worker přejmenován: `Patients/import_to_mongo.py` → `import_patients_mongo.py`; parsery notifikací vyčleněny do `notification_parsers.py` (bez závislosti na MySQL). - **v1.0:** první verze sjednocené pipeline (nahradila `Drugs/run_all.py` a `Patients/download_all.py`+`import_all.py`). Jeden vstupní skript na úrovni `IWRS/`, který stáhne z janssen.4gclinical.com a naimportuje do MongoDB (db `studie`) data pacientů i léků pro obě studie (77242113UCO3001, 42847922MDD3003). ## Tok souborů ``` IWRS/Incoming/ ← sem padá vše stažené (pacienti i léky, datumované názvy) IWRS/Incoming/Processed/ ← sem se přesouvá po úspěšném importu ``` - Při chybě importu soubor **zůstává v Incoming/** a zpracuje se při příštím běhu. - Import jde vždy **nejstarší soubor napřed** (mtime) — chronologická správnost snapshotů. - Kolize jména v Processed/ → přepíše se (Mongo už data má, soubor je jen archiv). - Adresář `IWRS/Incoming/` je v `.gitignore`. - Původní adresáře `Drugs/xls_*` zůstávají zmrazené na místě jako archiv — nový kód je nepoužívá. ## Názvy souborů v Incoming/ | Typ | Vzor | |---|---| | Subject Summary | `YYYY-MM-DD {study} Subject Summary Report.xlsx` | | Subject Detail | `YYYY-MM-DD {study} {subject} Subject Detail.xlsx` | | Notifikace | `{datum}_{study}_{subject}_{label}.pdf` + `.json` | | Onsite Inventory | `YYYY-MM-DD {study} Onsite Inventory {site}.xlsx` | | IP Destruction | `YYYY-MM-DD {study} IP Destruction {basket}.xlsx` | | Shipments Report | `YYYY-MM-DD {study} Shipments Report.xlsx` | | Shipment Details | `YYYY-MM-DD {study} Shipment Details {shipment_id}.xlsx` | Při kolizi (druhý běh ve stejný den) se před příponu přidá ` HHMM`. Metadata (site, basket, study) se při importu čtou primárně z **obsahu** souboru; z názvu se bere jen `shipment_id` u Shipment Details. ## Průběh ### Fáze 1 — stahování (2 přihlášení, per studie jedna browser session) 1. Login + výběr studie (`common/iwrs_portal.py`) 2. **Pacienti** (`download_patients.py`): - Subject Summary Report - per subjekt: Subject Detail XLSX + notifikace PDF+JSON (stahují se jen notifikace, jejichž `pk` ještě není v Mongo `iwrs_notifications`) 3. **Léky** (`download_drugs.py`): - Onsite Inventory — všechna centra, vždy znovu - IP Destruction — přeskočí košíky už importované v `iwrs_destruction` (destrukce je immutable) - Shipments Report — vždy znovu - Shipment Details — jen CZ zásilky; přeskočí zásilky, jejichž položky jsou v `iwrs_shipment_items` se statusem RECEIVED (finální stav). CANCELLED zásilky se stahují při každém běhu (záměrně zachováno). ### Fáze 2 — import (po stažení obou studií) 1. `ensure_indexes()` (jednou) 2. **Pacienti** (`import_patients.py`): summary → detaily → notifikace; per soubor, po úspěchu přesun do Processed/ 3. **Léky** (`import_drugs.py`): jeden `import_id` per studie a běh; parsuje všechny čekající soubory (nejstarší napřed, poslední vyhrává per `_id`), pak hromadný zápis: - `iwrs_shipments`, `iwrs_shipment_items`, `iwrs_inventory` — upsert + snapshot - `iwrs_destruction` — upsert bez snapshotu Po úspěšném zápisu se zparsované soubory přesunou do Processed/; soubor s chybou parsování zůstává v Incoming/. Prázdný inventory report (centrum bez zásob — jen meta řádky `Site:` atd., bez tabulky léků) se bere jako 0 položek a normálně se archivuje. ## Použití ``` python run_all_v1.1.py # vše (download + import, obě studie) python run_all_v1.1.py --download-only # jen stažení do Incoming/ python run_all_v1.1.py --import-only # jen import čekajících souborů python run_all_v1.1.py --only-patients # jen pacientská část python run_all_v1.1.py --only-drugs # jen léková část python run_all_v1.1.py --study 42847922MDD3003 # jen jedna studie ``` Prohlížeč běží s `headless=False` (viditelné okno) jako dosud. Moduly `import_patients.py` a `import_drugs.py` lze spustit i samostatně. ## Mapa modulů (vše na úrovni IWRS/) ``` IWRS/ run_all_v1.1.py ← vstupní skript (CLI, orchestrace) download_patients.py ← summary + delegace na download_subject_details.run() download_subject_details.py ← detaily subjektů + notifikace (worker) import_patients.py ← orchestrace importu pacientů import_patients_mongo.py ← worker: summary + visits → Mongo (ex Patients/import_to_mongo.py) import_notifications_to_mongo.py ← worker: notifikace PDF+JSON → Mongo notification_parsers.py ← parsery textů notifikací (bez MySQL) download_drugs.py ← 4 typy reportů → Incoming/, skip-logika přes Mongo import_drugs.py ← parsery + import léků z Incoming/ common/ iwrs_portal.py ← BASE_URL, credentials, login(page, study) paths.py ← INCOMING/PROCESSED, unique_path, move_done, sorted_by_mtime mongo_writer.py ← konvertory, upserty, snapshoty, import log Trash/ ← run_all_v1.0.py + .md ``` ## Úklid IWRS (provedeno 2026-06-10) Na úrovni `IWRS/` zůstává jen aktivní kód a data: `run_all_v1.1.py`, `create_report_v1.0.py` (+ oba `.md`), 8 modulů pipeline, `common/`, `Incoming/` (+ `Processed/`) a `Reports/`. Vše ostatní je v `IWRS/Trash/`: celé adresáře `Patients/` a `Drugs/` (vč. zmrazených archivů `xls_*`, starých výstupů `output/` a `CreatedReports/` a jejich vlastních `Trash/`), `Testing/`, `backfill_mysql_to_mongo.py` (jednorázový legacy nástroj; importoval `db_config` z Patients, v Trash zůstává funkční vedle sebe), `reports.json` a `run_all_v1.0.*`. Reportovací skripty byly sjednoceny do `IWRS/create_report_v1.0.py` — původní `Drugs/create_report.py` a `Patients/create_subject_report.py` jsou v Trash. ## Jednorázová migrace (provedeno 2026-06-10) - `Patients/Incoming/Zpracováno/` (1343 souborů) → `IWRS/Incoming/Processed/` - `.gitignore`: `IWRS/Patients/Incoming/` → `IWRS/Incoming/` - Staré vstupní skripty → `Patients/Trash/`, `Drugs/Trash/` - v1.1: moduly pipeline → úroveň `IWRS/` (git mv, historie zachována)