Files
janssen/Covance/Trash/download_test_results_v1.2.md
2026-06-09 08:22:49 +02:00

234 lines
8.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# download_test_results_v1.2.py — dokumentace
**Verze:** 1.2 · **Datum:** 2026-05-29
**Umístění:** `U:\PythonProject\Janssen\Covance_UCO3001\download_test_results_v1.2.py`
> **Změny v1.2 oproti 1.1:** přidán **paralelní běh přes sharding**
> (`--shard N --of M`). Skript lze spustit ve více procesech současně, každý
> zpracuje svůj podíl reportů a používá vlastní profil. Spouští se přes launcher
> `run_test_results_parallel_v1.0.py`.
> **Změny v1.1 oproti 1.0:** druhá studie 35472 (MDD) + report Microbiology.
---
## 1. Účel
Automatické stažení reportů **Test Results** z portálu Labcorp Sponsor Portal
(`xsp.labcorp.com`). Skript projde **2 studie × jejich centra × 2 typy reportu**,
u každého vyexportuje grid do CSV a uloží ho timestampovaný do `Source/`.
| Studie | Interní ID | Význam | Počet center |
|---|---|---|---|
| UC | `36940` | 77242113UCO3001 | 12 |
| MDD | `35472` | druhá studie | 5 |
Typy reportu: **Standard** (`/standard-test-results`) a **Microbiology** (`/microbiology`).
**Celkem: (12 + 5) × 2 = 34 reportů** (prázdná centra se přeskakují, viz 6.5).
---
## 2. Spuštění
### 2a) Paralelně (doporučeno — rychlejší)
Přes launcher, který rozjede 4 procesy (každý ve vlastním okně):
```bat
U:\PythonProject\Janssen\.venv\Scripts\python.exe ^
U:\PythonProject\Janssen\Covance_UCO3001\run_test_results_parallel_v1.0.py
```
### 2b) Serialně (jeden proces, jako dřív)
```bat
U:\PythonProject\Janssen\.venv\Scripts\python.exe ^
U:\PythonProject\Janssen\Covance_UCO3001\download_test_results_v1.2.py
```
### 2c) Jeden konkrétní shard ručně
```bat
…\python.exe download_test_results_v1.2.py --shard 2 --of 4
```
- Prohlížeč běží **viditelně** (`headless=False`), maximalizovaný.
- **Persistent profile** — session přežívá (viz sekce 4).
---
## 3. Paralelní běh (sharding) — jak funguje
### 3.1 Rozdělení práce
Argumenty `--shard N --of M` rozkrojí seznam všech 34 reportů:
```python
REPORTS = ALL_REPORTS[SHARD - 1::OF]
```
Tj. shard 1 z 4 vezme reporty na indexech 0, 4, 8, … ; shard 2 indexy 1, 5, 9, …
Rovnoměrné rozdělení, **žádný report neudělají dva shardy**. Bez argumentů
(`--of 1`) běží serialně přes všech 34.
### 3.2 Proč nestačily 4 taby v jednom procesu
Playwright **sync API je blokující**`wait_for_*` drží jediné vlákno celou
dobu čekání, takže 4 taby v jednom sync skriptu by se stejně střídaly sériově
(čekání by se sčítala, ne překrývala). Skutečná paralelnost vyžaduje buď async
API (přepis logiky), nebo — jak je zvoleno zde — **4 nezávislé procesy**, kde
souběh zajišťuje OS.
### 3.3 Profil per shard (povinné)
Chrome zamyká adresář profilu → **dvě běžící instance nemohou sdílet jeden
profil**. Proto:
| Běh | Profil |
|---|---|
| serialní (`--of 1`) | `browser_profile/` (původní) |
| shard N (`--of M>1`) | `browser_profile_{N}/` |
### 3.4 Login (varianta B)
Session se mezi profily **nesdílí**. Každý shard se proto při prvním spuštění
**přihlásí sám** (login je jen heslem, žádné MFA). Po prvním běhu už session
zůstane uložená v `browser_profile_{N}/`, takže další běhy login přeskočí
(`is_visible()` check). Launcher startuje procesy s **rozestupem** (`STAGGER_S`),
aby se OKTA login nezahltil 4 současnými požadavky.
### 3.5 Launcher `run_test_results_parallel_v1.0.py`
- `N_SHARDS = 4` — počet souběžných procesů (oken).
- `STAGGER_S = 4` — rozestup mezi starty (s).
- Každý proces se spustí v **novém konzolovém okně** (`CREATE_NEW_CONSOLE`) →
logy se neprolínají; navíc každý log má prefix `[S{shard}/{of}]`.
- Launcher počká, až všechny dobíhnou, a vypíše souhrn (které shardy selhaly
dle `returncode`).
### 3.6 Reálné zrychlení
Ne přesně 4× — export běží na serveru a velká centra generují hodně řádků,
takže reálně spíš 23×. Server může souběžné exporty throttlovat.
---
## 4. Výstupní soubory
Formát názvu (timestamp + popisný název):
```
{YYYY-MM-DD_HHMMSS} sponsor-study-{STUDY}-test-results-{SITE_ID}-{TYP}.csv
```
`{TYP}` = `standard` nebo `microbiology`. Všechny shardy ukládají do **stejného**
adresáře `Source/`; timestamp + unikátní názvy (site/typ) zaručují, že nedojde ke
kolizi. Staré soubory se **nikdy nemažou** (verzování přes timestamp).
---
## 5. Průběh jednoho reportu (kroky + logging)
| Fáze | Co dělá |
|---|---|
| START | vypíše shard/of, profil, počet reportů; spustí prohlížeč |
| LOGIN | otevře login; **pokud je session aktivní, přihlášení přeskočí** |
| KROK 1/5 | navigace na report URL |
| KROK 2/5 | čeká na `.ag-row` **nebo** prázdný grid („No Data"); pak stabilizace počtu |
| KROK 3/5 | klik na viditelné tři tečky (`more_horiz`) → menu |
| KROK 4/5 | klik na viditelné „Export to CSV" → zachytí download |
| KROK 5/5 | uloží soubor do `OUT_DIR` |
| KONEC | souhrn `hotovo X/Y (shard N/M)` + seznam selhaných |
Log u každého reportu: `=== Centrum 930557 / microbiology (studie 36940) ===`,
prefixovaný `[S{shard}/{of}]` při paralelním běhu.
---
## 6. Klíčové technické poznatky (PROČ to tak je) — ověřeno přes Chrome MCP
Stránka test-results je **Angular SPA** s **MDL** a tabulkou **AG Grid**.
Microbiology záložka má **stejnou** strukturu jako Standard.
### 6.1 Čekání na data = řádky AG Gridu
- Data načtena, jakmile se objeví `div.ag-row` (count 0 → N).
- Řádky jsou `position-absolute` → Playwright je **nepovažuje za „visible"**:
-`wait_for_selector("div.ag-row")` (default visible) **timeoutuje**.
-`wait_for_function("() => document.querySelectorAll('div.ag-row').length > 0")`.
- Stabilizace: počet se čte co 2 s, dokud se 2× neshodne.
- **Počet `.ag-row` je zastropený** (~153) virtuálním renderem — NENÍ to skutečný
počet záznamů. **Export do CSV ale vyexportuje VŠECHNY řádky** (ověřeno: různé
velikosti CSV).
### 6.2 „Fetching Data" / spinner — NEPLATÍ pro tuto stránku
Na test-results NENÍ text „Fetching Data" (je jen na *samples* reportu).
`<loading-bar>` jen problikne → nespoléhat. Signál = `.ag-row`.
### 6.3 Tři tečky (export) — DVA `<ag-export>`
2× `<ag-export>` (1 skrytý) → filtr na viditelnost:
`page.locator("ag-export button:visible", has_text="more_horiz").first.click()`
### 6.4 „Export to CSV" — DVĚ položky v DOM
2× `mdl-menu-item` (1 skrytá) →
`page.locator("mdl-menu-item:visible", has_text="Export to CSV").first.click()`
(❌ `get_by_text` → strict mode violation.)
### 6.5 Prázdné centrum (ověřeno přes Chrome MCP na centru 930551)
- No-rows overlay s textem **„No Data"** ve `.ag-overlay-no-rows-wrapper`.
- ⚠️ Třída **NENÍ** `.ag-overlay-no-rows-center`.
- ⚠️ Text **NENÍ** v `.ag-body-viewport` (ten je prázdný, `height: 1px`).
- ⚠️ Na stránce **2 overlaye** (1 skrytý) → kontrola `offsetParent !== null`.
- Detekce (KROK 2):
```js
() => {
if (document.querySelectorAll('div.ag-row').length > 0) return false;
return [...document.querySelectorAll('.ag-overlay-no-rows-wrapper')]
.some(e => e.offsetParent !== null);
}
```
- KROK 2 čeká na `.ag-row` **NEBO** tuto detekci → prázdné centrum nečeká 120 s.
---
## 7. Login logika (sdílená napříč Covance skripty)
```python
page.goto(LOGIN_URL); page.wait_for_load_state("networkidle")
if not page.get_by_label("Email").is_visible():
return # session aktivní → login přeskočit
# jinak: Email → Next → Password → Verify → wait redirect (code= zmizí z URL)
```
`is_visible()` (ne kontrola URL — po redirectu zůstává `xsp.covance.com`).
---
## 8. Chrome flagy proti „Restore pages" / broken session
```
--disable-restore-session-state
--disable-session-crashed-bubble
```
---
## 9. Robustnost
- Každý report v `try/except` → chyba u jednoho nezastaví zbytek shardu.
- Souhrn na konci: `hotovo X/Y (shard N/M)` + `SELHALA centra: site/typ, …`.
- Launcher hlídá `returncode` každého shardu.
---
## 10. Možná budoucí rozšíření
- **Více/méně procesů:** změnit `N_SHARDS` v launcheru (profily `_1.._N`).
- **Další studie / centra / typ reportu:** přidat do `STUDIES` / `REPORT_TYPES`.
- **Vyčistit profily:** smazat `browser_profile_*/` (vynutí nový login).
---
## 11. Příbuzné skripty (stejná složka / portál)
| Skript | Co stahuje |
|---|---|
| `download_samples_report_v1.1.py` | All Samples (sampletracking) |
| `download_kit_inventory_v2.1.py` | Kit inventory |
| `download_equeries_report_v1.1.py` | eQuery reporty (zdroj SITE_IDS pro 36940) |
| `download_test_results_v1.2.py` | **tento** — Test Results (Standard + Microbiology, 2 studie, sharding) |
| `run_test_results_parallel_v1.0.py` | launcher 4 paralelních shardů test-results |