Migrate IWRS from MySQL to MongoDB

- Add IWRS/common/mongo_writer.py with shared connection, indexes,
  upsert+snapshot helpers
- Add IWRS/Patients/import_to_mongo.py (subject_summary + visits)
- Add IWRS/Patients/import_notifications_to_mongo.py: parse PDF/JSON
  directly to Mongo (incl. PDF as BinData), replaces 2-step MySQL flow
- Add IWRS/Drugs/import_to_mongo.py (shipments, items, inventory,
  destruction)
- Add IWRS/backfill_mysql_to_mongo.py: one-shot history backfill
- Switch IWRS/Patients/run_all.py and IWRS/Drugs/run_all.py to Mongo
- Rewrite IWRS/Drugs/create_report.py data loaders to read from Mongo
- 8 main collections (upsert = latest state) + 5 snapshot collections
  (append-only with import_id) under studie database; notifications and
  destruction are immutable and need no snapshots

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-03 07:24:36 +02:00
parent 681095d557
commit ea9d611719
2080 changed files with 9465 additions and 172 deletions
+29
View File
@@ -0,0 +1,29 @@
---
name: project-claude-learning
description: "Stav Claude Code learning path z claude-howto repa — úroveň, mezery, doporučené projekty"
metadata:
node_type: memory
type: project
originSessionId: 2ed1a640-5825-4eb5-98bc-748c8b15e08d
---
Vladimir prošel `/self-assessment` z [claude-howto](U:/janssen/claude-howto/) repa dne 2026-06-03.
**Úroveň:** Level 2 — Intermediate (3/8 quick assessment)
**Zvládnuté:** CLI základy, CLAUDE.md/memory (viz [[setup-memory-sync]]), MCP servery (medevio, medicus-firebird, fotky-buzalkovi)
**Mezery k doučení (v pořadí priorit):**
1. Custom slash commands & Skills — [claude-howto/01-slash-commands/](U:/janssen/claude-howto/01-slash-commands/), [03-skills/](U:/janssen/claude-howto/03-skills/)
2. Subagenty (`.claude/agents/`) — [04-subagents/](U:/janssen/claude-howto/04-subagents/)
3. Hooks (PreToolUse/PostToolUse) — [06-hooks/](U:/janssen/claude-howto/06-hooks/)
4. Print mode `claude -p` pro CI/CD — [10-cli/](U:/janssen/claude-howto/10-cli/)
**Navržené praktické projekty propojené s reálnou prací:**
- EDC monitoring skill + subagent (navazuje na [[project-edc-mongo]])
- Medevio asistent skill přes existující MCP server
- IWRS xlsx validator subagent + hook (navazuje na [[project-covance]])
**Why:** User chce postupně rozšiřovat Claude Code dovednosti, ale dnes (2026-06-03) odložil pokračování — vrátí se k tomu později.
**How to apply:** Až user řekne "pokračujeme v learning path" nebo podobně, navaž od Fáze 1 (Slash Commands → Skills). Nedělej hned všechno — postupuj po fázích, vždy nejprve tutoriál + praktické cvičení napojené na jeho reálnou práci (Covance, EDC, Medevio, IWRS).
+43
View File
@@ -0,0 +1,43 @@
---
name: project-iwrs-mongo
description: IWRS data kompletně v MongoDB studie — 8 hlavních kolekcí + 5 snapshot. MySQL je nyní read-only archiv. Pipeline IWRS/Patients/run_all.py + IWRS/Drugs/run_all.py píše přímo do Mongo.
metadata:
node_type: memory
type: project
originSessionId: 7e135172-3d69-4283-801f-d2450be664a9
---
**Vše IWRS migrováno do MongoDB databáze `studie`. MySQL je nyní read-only archiv.**
## Hlavní kolekce (upsert = aktuální stav)
- `iwrs_imports` — log běhů importu (sekvenční import_id)
- `iwrs_subject_summary``_id = "{study}:{subject}"`, sjednoceno pro obě studie (společná pole + study-specifická vedle)
- `iwrs_visits``_id = "{study}:{subject}:{irt_transaction_no|scheduled_date}:{desc}"`
- `iwrs_notifications``_id = pk` (IWRS unique), obsahuje text + medications[] + fields{} + PDF jako BinData
- `iwrs_shipments``_id = shipment_id`
- `iwrs_shipment_items``_id = "{shipment_id}:{medication_id}"`
- `iwrs_inventory``_id = "{site}:{medication_id}"`
- `iwrs_destruction``_id = "{basket_id}:{medication_id}"` (immutable)
## Snapshot kolekce (append-only s `import_id`)
`iwrs_subject_summary_snapshots`, `iwrs_visits_snapshots`, `iwrs_shipments_snapshots`, `iwrs_shipment_items_snapshots`, `iwrs_inventory_snapshots`. Notifications + destruction snapshoty nepotřebují (immutable).
## Struktura kódu
- [IWRS/common/mongo_writer.py](IWRS/common/mongo_writer.py) — sdílené helpers (to_str/to_int/to_date converters, get_db, ensure_indexes, log_import, bulk_upsert_with_snapshot, bulk_upsert_only)
- [IWRS/Patients/import_to_mongo.py](IWRS/Patients/import_to_mongo.py) — subject_summary + visits parser z XLSX
- [IWRS/Patients/import_notifications_to_mongo.py](IWRS/Patients/import_notifications_to_mongo.py) — PDF+JSON z disku rovnou do Mongo (parsuje text per typ, PDF jako BinData, přesun do Zpracováno/)
- [IWRS/Drugs/import_to_mongo.py](IWRS/Drugs/import_to_mongo.py) — shipments + items + inventory + destruction
- [IWRS/backfill_mysql_to_mongo.py](IWRS/backfill_mysql_to_mongo.py) — jednorázový backfill historie z MySQL (už proběhlo)
- [IWRS/Patients/parse_notifications_to_mongo.py](IWRS/Patients/parse_notifications_to_mongo.py) — starší parser MySQL→Mongo (parsery z něj reuse-uje `import_notifications_to_mongo.py`)
## Pipeline
- `IWRS/Patients/run_all.py`: download (Playwright) → `import_to_mongo.run()` (summary + visits) → `import_notifications_to_mongo.main()` (PDF/JSON → Mongo)
- `IWRS/Drugs/run_all.py`: download (Playwright) → `drugs_mongo.run()` (shipments + items + inventory + destruction)
**Why:** UCO3001 a MDD3003 mají hodně podobnou ale ne shodnou sadu polí (společných ~16, study-specifických ~1417). Per-studie MySQL tabulky = schema sprawl při každé nové studii. Schemaless Mongo + sjednocení = přidání nové studie znamená jen nový parser, žádné DDL. Notifikace navíc obsahují lot/expirace/clinical response/audit trail, které XLSX reporty nemají.
**How to apply:** Pro nové analýzy/dotazy IWRS dat používej Mongo `studie.iwrs_*`. MySQL `studie.iwrs_*` nech být (read-only). Po nějaké době ověření lze MySQL IWRS tabulky dropnout. Související: [[project-edc-mongo]] — stejný Mongo server, stejný snapshot pattern.
**Známé limity parseru notifikací:**
- `Cohort` chybí u MDD3003 mimo `Screening` (v textu není)
- Když má klíč prázdnou hodnotu, parser vezme následující neprázdný řádek — občas v `fields` skončí název další sekce jako pseudohodnota (jen šum)