149 lines
6.2 KiB
Markdown
149 lines
6.2 KiB
Markdown
# vtmf_pipeline_v1.6 — V-TMF workflow přes 3 úrovně (STUDY / COUNTRY / SITE)
|
||
|
||
**Verze:** 1.6 · **Datum:** 2026-06-15
|
||
|
||
## Co je nové proti v1.5
|
||
|
||
v1.5 stahovala jen **study-level** dokumenty jedné studie do ploché
|
||
`<Type>\<Subtype>` struktury. v1.6 řeší celou hierarchii VTMF
|
||
**STUDY → COUNTRY → SITE** a sdílený (M:N) charakter dokumentů.
|
||
|
||
**Klíčové poznatky z reportů:**
|
||
- Dokument je do studií/zemí/center jen **referencovaný** (M:N) — např.
|
||
Master Confidentiality Agreement v nemocnici je jeden dokument
|
||
referencovaný do všech studií i center té nemocnice. Reference ≠ kopie.
|
||
- Sloupce `Study`, `Study Country`, `Site` jsou **comma-separated seznamy**.
|
||
- Tři reporty = tři **úrovně** dokumentu. Aby byl TMF kompletní, musí se
|
||
stáhnout všechny tři.
|
||
- Country i site report filtrují **jen na zemi** (CZ), ne na studii →
|
||
empiricky vrací 100 % dokumentů navázaných na UCO3001, ořez na studii je
|
||
pojistka (no-op).
|
||
- Study report má 15 sloupců (+ `Document Date`), country/site 17
|
||
(+ `Created By`, `Study Country`, `Site`; bez `Document Date`).
|
||
|
||
## Konfigurace REPORTS
|
||
|
||
```python
|
||
TARGET_STUDY = "77242113UCO3001"
|
||
REPORTS = [
|
||
{"level":"study", "study":TARGET_STUDY, "country":None,
|
||
"url":".../0RP000000000182?study__v...IN=0ST000000137008"},
|
||
{"level":"country", "study":TARGET_STUDY, "country":"Czech Republic",
|
||
"url":".../0RP000000000319?study_country__v...IN=0SC00000017T056"},
|
||
{"level":"site", "study":TARGET_STUDY, "country":"Czech Republic",
|
||
"url":".../0RP000000000762?study_country__v...EQ=0SC00000017T056"},
|
||
]
|
||
```
|
||
Jiná studie / země = jen úprava ID v URL + TARGET_STUDY.
|
||
|
||
## Tok jednoho běhu
|
||
|
||
1. **Login** (persistentní profil, J&J SSO, 2FA na telefonu).
|
||
2. Pro **každý report** v `REPORTS`:
|
||
- export do Excelu (Data Only) → `WhatToDownload/<ts> <level> ...xlsx`,
|
||
- parse (zobecněný parser, sloupce podle názvu),
|
||
- ořez na `TARGET_STUDY` (řádek se bere jen pokud má studii v `studies`),
|
||
- **scoped sync** do Mongo,
|
||
- archiv reportu do `Zpracovano/`.
|
||
3. **Jeden průchod stažení** všech `deleted=False, downloaded≠True`
|
||
na disk i do SeaweedFS.
|
||
|
||
## Mongo schéma (kolekce documents)
|
||
|
||
```
|
||
_id: "VTMF-9108777|v2.0" # číslo dokumentu | verze
|
||
vtmf, version, url, level # level = study|country|site (pro cestu)
|
||
levels: ["site"] # všechny úrovně, kde se objevil
|
||
scopes: ["site|77242113UCO3001|Czech Republic", ...] # pro scoped mazání
|
||
name, status, type, subtype, classification, desc
|
||
process_name, external_system_name
|
||
created_by, last_modified_by, version_created_by
|
||
date # YYYY-MM-DD (Document/Approval/Version date)
|
||
studies: ["77242113UCO3001", ...] # comma-split sloupce reportu
|
||
countries: ["Czech Republic", ...]
|
||
sites: ["BH5-CZ10001", ...]
|
||
first_seen, last_seen, deleted, deleted_at
|
||
downloaded, downloaded_at, placeholder # žádné pole file (Dropbox zrušen)
|
||
sha256 # kontrolní součet (NE cesta)
|
||
seaweed_path, seaweed_url, seaweed_synced_at # jediné umístění souboru
|
||
history: [{ts, changes:{pole:{old,new}}}]
|
||
```
|
||
|
||
## ⚠️ Příslušnost ke studii/úrovni = `scopes[]`, NE `studies[]`
|
||
|
||
Pravidlo platné pro každý dotaz i skript („co je ve VTMF na study/country/site
|
||
úrovni studie X"):
|
||
|
||
- **`scopes[]`** = `"<level>|<study>|<country>"` — odkud byl dokument reálně
|
||
natažen (který report/úroveň). **Tohle určuje příslušnost k TMF studie.**
|
||
- **`studies[]`** = jen M:N reference (kam všude je 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 s
|
||
`scopes=['study|77242113UCO3001|']` patří do TMF UCO3001, ne CRD3001.
|
||
Export i jakýkoli reporting filtruje přes scopes (`^<level>\|<study>\|`).
|
||
|
||
## Scoped sync (řeší mazací háček)
|
||
|
||
Mazání už **nekouká na celou kolekci** (to by sync country reportu označil
|
||
study/site dokumenty jako smazané). Každý report má
|
||
`scope = "<level>|<study>|<country>"`; dokument nese pole `scopes[]`.
|
||
- dokument v reportu → `$addToSet` scope,
|
||
- dokument, který z **tohoto** scope zmizel → scope se odebere; teprve když
|
||
nemá **žádný** scope → `deleted=True` + soubor ` [D]`.
|
||
|
||
## Evidence reportů — kolekce report_runs
|
||
|
||
```
|
||
level, study, country, url, scope, exported_at, file, row_count, doc_keys[]
|
||
```
|
||
Umožní ukázat „co přesně bylo v reportu" a slouží jako audit.
|
||
|
||
## Úložiště = JEN SeaweedFS (žádný Dropbox/disk)
|
||
|
||
Dokumenty se stahují z Vaultu přes **dočasný soubor Playwrightu** rovnou do
|
||
SeaweedFS Fileru — na disk/Dropbox se nic neukládá. Klíč = číslo dokumentu
|
||
+ verze:
|
||
|
||
```
|
||
/vtmf-documents/<vtmf>/<verze>.<přípona>
|
||
např. /vtmf-documents/VTMF-9108777/v2.0.pdf
|
||
```
|
||
Žádné SHA cesty, žádný content dedup, žádné hardlinky. SHA-256 se počítá a
|
||
ukládá do Mongo jen jako kontrolní součet. Která úroveň / země / centra =
|
||
pole `level` / `countries[]` / `sites[]` v Mongo.
|
||
|
||
Aktuální verzi čehokoli do Dropboxu (nebo kamkoli jinam) zařídí samostatný
|
||
export skript ze SeaweedFS — pipeline se tím nezdržuje.
|
||
|
||
## Migrace stávajících dat → migrate_to_v16.py
|
||
|
||
Stávající study-level data (v1.3–v1.5) převede na schéma v1.6. Dvě fáze,
|
||
**default DRY-RUN**, ostře s `--apply`:
|
||
|
||
- `--phase mongo` — re-parse nejnovějšího archivu study reportu v1.6
|
||
parserem → obohatí ~1692 dokumentů o nová pole (level, scopes[],
|
||
studies[], countries=[], sites=[], classification, …). Nesahá na
|
||
download stav.
|
||
- `--phase seaweed` — překlíčuje SeaweedFS ze starých SHA cest na nové
|
||
`<vtmf>/<verze>` (~1637 souborů; zdroj bajtů = stávající soubor na disku,
|
||
fallback GET ze SHA cesty), opraví `seaweed_path/url` + `sha256`, smaže
|
||
staré SHA objekty a odebere pole `file` z Mongo. Fyzické soubory
|
||
v Dropboxu pak můžeš smazat ručně.
|
||
|
||
```powershell
|
||
# náhled
|
||
& "...\.venv\Scripts\python.exe" "...\migrate_to_v16.py"
|
||
# ostře
|
||
& "...\.venv\Scripts\python.exe" "...\migrate_to_v16.py" --apply
|
||
```
|
||
|
||
## Spuštění pipeline
|
||
|
||
```powershell
|
||
& "U:\PythonProject\Janssen\.venv\Scripts\python.exe" "U:\PythonProject\Janssen\VTMFDownloadFiles\vtmf_pipeline_v1.6.py"
|
||
```
|
||
|
||
Předchůdce: vtmf_pipeline_v1.5 (TRASH/).
|
||
```
|