z230
This commit is contained in:
@@ -0,0 +1,220 @@
|
||||
"""
|
||||
download_drugs.py — stažení Drugs reportů pro jednu studii do IWRS/Incoming/.
|
||||
Verze: 1.0 | Datum: 2026-06-10
|
||||
|
||||
Volá se z IWRS/run_all_v1.0.py s již přihlášenou Playwright page (login +
|
||||
výběr studie zajišťuje common.iwrs_portal.login).
|
||||
|
||||
1. Onsite inventory detail (per site, stahuje se vždy)
|
||||
2. IP destruction (per košík; přeskočí košíky už importované
|
||||
v Mongo iwrs_destruction — destrukce se nemění)
|
||||
3. Shipments report (jeden soubor na studii, stahuje se vždy)
|
||||
4. Shipment details (per CZ zásilka; přeskočí zásilky, jejichž
|
||||
položky jsou v Mongo iwrs_shipment_items se
|
||||
statusem RECEIVED — finální stav)
|
||||
|
||||
Názvy souborů (datumované, aby zapadly do Incoming/ flow):
|
||||
YYYY-MM-DD {study} Onsite Inventory {site}.xlsx
|
||||
YYYY-MM-DD {study} IP Destruction {basket}.xlsx
|
||||
YYYY-MM-DD {study} Shipments Report.xlsx
|
||||
YYYY-MM-DD {study} Shipment Details {shipment_id}.xlsx
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import datetime
|
||||
|
||||
import pandas as pd
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
IWRS_DIR = os.path.dirname(BASE_DIR)
|
||||
for _p in (IWRS_DIR, BASE_DIR):
|
||||
if _p not in sys.path:
|
||||
sys.path.insert(0, _p)
|
||||
|
||||
from common.iwrs_portal import BASE_URL
|
||||
from common.paths import INCOMING_DIR, unique_path
|
||||
from common.mongo_writer import get_db
|
||||
|
||||
SITES = {
|
||||
"77242113UCO3001": [
|
||||
"DD5-CZ10001", "DD5-CZ10003", "DD5-CZ10006", "DD5-CZ10009",
|
||||
"DD5-CZ10010", "DD5-CZ10012", "DD5-CZ10013", "DD5-CZ10015",
|
||||
"DD5-CZ10016", "DD5-CZ10020", "DD5-CZ10021", "DD5-CZ10022",
|
||||
],
|
||||
"42847922MDD3003": [
|
||||
"S10-CZ10002", "S10-CZ10004", "S10-CZ10005",
|
||||
"S10-CZ10008", "S10-CZ10011", "S10-CZ10012",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def _today():
|
||||
return datetime.date.today().strftime("%Y-%m-%d")
|
||||
|
||||
|
||||
# ── skip-logika přes Mongo (náhrada za dřívější "soubor existuje") ───────────
|
||||
|
||||
def get_existing_baskets(study):
|
||||
"""Košíky už importované v iwrs_destruction — destrukce je immutable."""
|
||||
try:
|
||||
db = get_db()
|
||||
return set(db.iwrs_destruction.distinct("basket_id", {"study": study}))
|
||||
except Exception as e:
|
||||
print(f" UPOZORNĚNÍ: nelze načíst košíky z Mongo ({e}), stahuji vše")
|
||||
return set()
|
||||
|
||||
|
||||
def get_received_shipments(study):
|
||||
"""Zásilky, jejichž položky už jsou v Mongo se statusem RECEIVED (finální stav)."""
|
||||
try:
|
||||
db = get_db()
|
||||
return set(db.iwrs_shipment_items.distinct(
|
||||
"shipment_id",
|
||||
{"study": study, "shipment_status": {"$regex": "^received$", "$options": "i"}},
|
||||
))
|
||||
except Exception as e:
|
||||
print(f" UPOZORNĚNÍ: nelze načíst zásilky z Mongo ({e}), stahuji vše")
|
||||
return set()
|
||||
|
||||
|
||||
# ── download funkce ──────────────────────────────────────────────────────────
|
||||
|
||||
def download_inventory(page, study):
|
||||
today = _today()
|
||||
page.goto(f"{BASE_URL}/report/onsite_inventory_detail")
|
||||
page.wait_for_load_state("networkidle", timeout=120000)
|
||||
|
||||
for site_id in SITES[study]:
|
||||
print(f" [{site_id}] inventory...")
|
||||
page.locator('input[placeholder="search"], input[type="text"]').first.click()
|
||||
page.get_by_role("option", name=site_id).click()
|
||||
page.wait_for_load_state("networkidle", timeout=120000)
|
||||
|
||||
filename = unique_path(INCOMING_DIR, f"{today} {study} Onsite Inventory {site_id}")
|
||||
with page.expect_download(timeout=120000) as dl:
|
||||
page.get_by_role("button", name="Download XLS").click()
|
||||
dl.value.save_as(filename)
|
||||
|
||||
page.get_by_role("button", name="Clear").click()
|
||||
page.wait_for_load_state("networkidle", timeout=120000)
|
||||
print(f" Inventory OK ({len(SITES[study])} center)")
|
||||
|
||||
|
||||
def download_destruction(page, study):
|
||||
today = _today()
|
||||
page.goto(f"{BASE_URL}/report/ip_destruction_form")
|
||||
page.wait_for_load_state("networkidle", timeout=120000)
|
||||
|
||||
page.locator('input[placeholder="search"], input[type="text"]').first.click()
|
||||
page.wait_for_timeout(1000)
|
||||
baskets = [b.strip() for b in page.locator("mat-option").all_inner_texts()
|
||||
if b.strip() and b.strip() != "No results found"]
|
||||
page.keyboard.press("Escape")
|
||||
page.wait_for_timeout(500)
|
||||
|
||||
if not baskets:
|
||||
print(" Žádné destruction košíky")
|
||||
return
|
||||
|
||||
existing = get_existing_baskets(study)
|
||||
new_count = 0
|
||||
for basket in baskets:
|
||||
if basket in existing:
|
||||
continue # destrukce se nemění — přeskočit
|
||||
print(f" [košík {basket}] stahování...")
|
||||
input_field = page.locator('input[placeholder="search"], input[type="text"]').first
|
||||
input_field.click()
|
||||
input_field.fill(basket)
|
||||
page.wait_for_timeout(500)
|
||||
page.locator("mat-option").first.dispatch_event("click")
|
||||
page.wait_for_load_state("networkidle", timeout=120000)
|
||||
|
||||
filename = unique_path(INCOMING_DIR, f"{today} {study} IP Destruction {basket}")
|
||||
with page.expect_download(timeout=120000) as dl:
|
||||
page.get_by_role("button", name="Download XLS").click()
|
||||
dl.value.save_as(filename)
|
||||
new_count += 1
|
||||
|
||||
page.get_by_role("button", name="Clear").click()
|
||||
page.wait_for_load_state("networkidle", timeout=120000)
|
||||
|
||||
print(f" Destruction OK ({new_count} nových, {len(baskets) - new_count} přeskočeno)")
|
||||
|
||||
|
||||
def download_shipments_report(page, study):
|
||||
today = _today()
|
||||
page.goto(f"{BASE_URL}/report/shipments_report")
|
||||
page.wait_for_load_state("networkidle", timeout=120000)
|
||||
|
||||
filename = unique_path(INCOMING_DIR, f"{today} {study} Shipments Report")
|
||||
with page.expect_download(timeout=120000) as dl:
|
||||
page.get_by_role("button", name="Download XLS").click()
|
||||
dl.value.save_as(filename)
|
||||
print(f" Shipments report OK -> {os.path.basename(filename)}")
|
||||
return filename
|
||||
|
||||
|
||||
def download_shipment_details(page, study, shipments_report_path):
|
||||
today = _today()
|
||||
|
||||
# načti CZ shipment IDs z právě staženého shipments reportu
|
||||
raw = pd.read_excel(shipments_report_path, header=None)
|
||||
header_row = None
|
||||
for i, row in raw.iterrows():
|
||||
if "Shipment ID" in [str(v).strip() for v in row]:
|
||||
header_row = i
|
||||
break
|
||||
df = pd.read_excel(shipments_report_path, header=header_row)
|
||||
df = df.dropna(how="all")
|
||||
df = df[df["Location"].astype(str).str.contains("Czech", na=False, case=False)]
|
||||
cz_shipments = list(zip(
|
||||
df["Shipment ID"].astype(str).str.strip(),
|
||||
df["IRT Shipment Status"].astype(str).str.strip() if "IRT Shipment Status" in df.columns else [""] * len(df),
|
||||
))
|
||||
print(f" CZ zásilek celkem: {len(cz_shipments)}")
|
||||
|
||||
received = get_received_shipments(study)
|
||||
|
||||
page.goto(f"{BASE_URL}/report/shipment_details_report")
|
||||
page.wait_for_load_state("networkidle", timeout=120000)
|
||||
|
||||
skipped = 0
|
||||
for shipment, status in cz_shipments:
|
||||
if shipment in received:
|
||||
skipped += 1
|
||||
continue # položky v Mongo už mají finální stav RECEIVED
|
||||
input_field = page.locator('input[placeholder="search"], input[type="text"]').first
|
||||
input_field.click()
|
||||
input_field.fill(shipment)
|
||||
page.wait_for_timeout(500)
|
||||
page.locator("mat-option").first.dispatch_event("click")
|
||||
page.wait_for_load_state("networkidle", timeout=120000)
|
||||
|
||||
filename = unique_path(INCOMING_DIR, f"{today} {study} Shipment Details {shipment}")
|
||||
with page.expect_download(timeout=120000) as dl:
|
||||
page.get_by_role("button", name="Download XLS").click()
|
||||
dl.value.save_as(filename)
|
||||
print(f" [{shipment}] ({status}) OK")
|
||||
|
||||
page.get_by_role("button", name="Clear").click()
|
||||
page.wait_for_load_state("networkidle", timeout=120000)
|
||||
|
||||
print(f" Přeskočeno (RECEIVED v Mongo): {skipped}")
|
||||
|
||||
|
||||
def run(page, study):
|
||||
"""Stáhne všechny 4 typy Drugs reportů pro studii do IWRS/Incoming/."""
|
||||
os.makedirs(INCOMING_DIR, exist_ok=True)
|
||||
|
||||
print("\n [1/4] Onsite inventory...")
|
||||
download_inventory(page, study)
|
||||
|
||||
print("\n [2/4] IP destruction...")
|
||||
download_destruction(page, study)
|
||||
|
||||
print("\n [3/4] Shipments report...")
|
||||
report_path = download_shipments_report(page, study)
|
||||
|
||||
print("\n [4/4] Shipment details (CZ)...")
|
||||
download_shipment_details(page, study, report_path)
|
||||
@@ -0,0 +1,306 @@
|
||||
"""
|
||||
import_drugs.py — import Drugs reportů z IWRS/Incoming/ do MongoDB.
|
||||
Verze: 1.0 | Datum: 2026-06-10
|
||||
|
||||
Nahrazuje Drugs/import_to_mongo.py (ten parsoval pevné adresáře xls_*;
|
||||
nyní se parsují datumované soubory z IWRS/Incoming/).
|
||||
|
||||
Per studie a běh: jeden import_id. Soubory se zpracují nejstarší napřed,
|
||||
při více souborech stejného záznamu vyhrává poslední (poslední stav).
|
||||
Po úspěšném zápisu do Monga se zparsované soubory přesunou do
|
||||
IWRS/Incoming/Processed/; soubor s chybou parsování zůstává v Incoming/.
|
||||
|
||||
Cílové kolekce (db `studie`):
|
||||
iwrs_shipments / iwrs_shipment_items / iwrs_inventory (upsert + snapshot)
|
||||
iwrs_destruction (upsert only, immutable)
|
||||
|
||||
Volá se z IWRS/run_all_v1.0.py (ensure_indexes volá orchestrátor);
|
||||
lze spustit i samostatně: python import_drugs.py
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import glob
|
||||
|
||||
import pandas as pd
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
IWRS_DIR = os.path.dirname(BASE_DIR)
|
||||
for _p in (IWRS_DIR, BASE_DIR):
|
||||
if _p not in sys.path:
|
||||
sys.path.insert(0, _p)
|
||||
|
||||
from common.paths import INCOMING_DIR, STUDIES, move_done, sorted_by_mtime
|
||||
from common.mongo_writer import (
|
||||
to_str, to_int, to_date,
|
||||
ensure_indexes, log_import,
|
||||
bulk_upsert_with_snapshot, bulk_upsert_only,
|
||||
)
|
||||
|
||||
|
||||
def _pending(pattern):
|
||||
return sorted_by_mtime(glob.glob(os.path.join(INCOMING_DIR, pattern)))
|
||||
|
||||
|
||||
def _find_header_row(raw, marker):
|
||||
for i, row in raw.iterrows():
|
||||
if marker in [str(v).strip() for v in row]:
|
||||
return i
|
||||
return None
|
||||
|
||||
|
||||
# ── XLSX parsery (per soubor) ────────────────────────────────────────────────
|
||||
|
||||
def parse_shipments_file(path, study):
|
||||
raw = pd.read_excel(path, header=None)
|
||||
header_row = _find_header_row(raw, "Shipment ID")
|
||||
if header_row is None:
|
||||
raise ValueError("hlavičkový řádek 'Shipment ID' nenalezen")
|
||||
df = pd.read_excel(path, header=header_row).dropna(how="all")
|
||||
df = df[df["Location"].astype(str).str.contains("Czech", na=False, case=False)]
|
||||
col = df.columns.tolist()
|
||||
rows = []
|
||||
for _, r in df.iterrows():
|
||||
sid = to_str(r["Shipment ID"])
|
||||
if not sid:
|
||||
continue
|
||||
rows.append({
|
||||
"_id": sid,
|
||||
"shipment_id": sid,
|
||||
"study": study,
|
||||
"status": to_str(r["IRT Shipment Status"]),
|
||||
"type": to_str(r["Type"]),
|
||||
"ship_from": to_str(r["Shipment From"]),
|
||||
"ship_to_site": to_str(r["Ship To:"]),
|
||||
"location": to_str(r["Location"]),
|
||||
"request_date": to_date(r["Request Date"]),
|
||||
"shipped_date": to_date(r["Shipped Date"]),
|
||||
"received_date": to_date(r["Received Date"]) if "Received Date" in col else None,
|
||||
"received_by": to_str(r["Received by"]) if "Received by" in col else None,
|
||||
"delivered_date_utc": to_date(r["Delivered Date [UTC]"]) if "Delivered Date [UTC]" in col else None,
|
||||
"delivery_recipient": to_str(r["Delivery Recipient"]) if "Delivery Recipient" in col else None,
|
||||
"delivery_details": to_str(r["Delivery Details"]) if "Delivery Details" in col else None,
|
||||
"cancelled_date": to_date(r["Cancelled Date"]) if "Cancelled Date" in col else None,
|
||||
"total_medication_ids": to_int(r["Total Medication IDs"]) if "Total Medication IDs" in col else None,
|
||||
"tracking_no": to_str(r["Tracking #"]) if "Tracking #" in col else None,
|
||||
"shipping_category": to_str(r["Shipping Category"]) if "Shipping Category" in col else None,
|
||||
"expected_arrival": to_date(r["Expected Arrival"]) if "Expected Arrival" in col else None,
|
||||
})
|
||||
return rows
|
||||
|
||||
|
||||
def parse_shipment_details_file(path, study):
|
||||
# shipment_id z názvu: "... Shipment Details {id}[ HHMM].xlsx"
|
||||
m = re.search(r"Shipment Details (\S+?)(?: \d{4})?\.xlsx$", os.path.basename(path))
|
||||
shipment_id = m.group(1) if m else "UNKNOWN"
|
||||
raw = pd.read_excel(path, header=None)
|
||||
header_row = _find_header_row(raw, "Medication ID")
|
||||
if header_row is None:
|
||||
raise ValueError("hlavičkový řádek 'Medication ID' nenalezen")
|
||||
df = pd.read_excel(path, header=header_row).dropna(how="all")
|
||||
rows = []
|
||||
for _, r in df.iterrows():
|
||||
med_desc = (to_str(r.get("Medication Description"))
|
||||
or to_str(r.get("Medication ID Description")))
|
||||
med_type = (to_str(r.get("Medication type"))
|
||||
or to_str(r.get("Medication ID type")))
|
||||
med_id = to_str(r.get("Medication ID"))
|
||||
if not med_id:
|
||||
continue
|
||||
rows.append({
|
||||
"_id": f"{shipment_id}:{med_id}",
|
||||
"study": study,
|
||||
"shipment_id": shipment_id,
|
||||
"destination_location": to_str(r.get("Destination Location")),
|
||||
"shipment_status": to_str(r.get("IRT Shipment Status")),
|
||||
"shipment_type": to_str(r.get("Type")),
|
||||
"destination_site": to_str(r.get("Destination Site")),
|
||||
"investigator": to_str(r.get("Investigator")),
|
||||
"medication_description": med_desc,
|
||||
"medication_type": med_type,
|
||||
"medication_id": med_id,
|
||||
"packaged_lot_no": to_str(r.get("Packaged Lot number")),
|
||||
"packaged_lot_description": to_str(r.get("Packaged Lot description")),
|
||||
"container_id": to_str(r.get("Container ID")),
|
||||
"quantity": to_int(r.get("Quantity of Medication IDs")),
|
||||
"expiration_date": to_date(r.get("Expiration Date")),
|
||||
"item_status": to_str(r.get("Status")),
|
||||
})
|
||||
return rows
|
||||
|
||||
|
||||
def parse_inventory_file(path, study):
|
||||
raw = pd.read_excel(path, header=None)
|
||||
site = investigator = location = None
|
||||
header_row = None
|
||||
for i, row in raw.iterrows():
|
||||
first = str(row.iloc[0]).strip() if pd.notna(row.iloc[0]) else ""
|
||||
if first.startswith("Site:"):
|
||||
site = first.replace("Site:", "").strip()
|
||||
elif first.startswith("Investigator:"):
|
||||
investigator = first.replace("Investigator:", "").strip()
|
||||
elif first.startswith("Location:"):
|
||||
location = first.replace("Location:", "").strip()
|
||||
if first in ("Medication", "Medication ID") and header_row is None:
|
||||
header_row = i
|
||||
if header_row is None:
|
||||
raise ValueError("hlavičkový řádek 'Medication' nenalezen")
|
||||
df = pd.read_excel(path, header=header_row).dropna(how="all")
|
||||
df = df.rename(columns={df.columns[0]: "medication_id"})
|
||||
rows = []
|
||||
for _, r in df.iterrows():
|
||||
med_id = to_str(r["medication_id"])
|
||||
if not med_id or not site:
|
||||
continue
|
||||
rows.append({
|
||||
"_id": f"{site}:{med_id}",
|
||||
"study": study,
|
||||
"site": site,
|
||||
"investigator": investigator,
|
||||
"location": location,
|
||||
"medication_id": med_id,
|
||||
"packaged_lot_no": to_str(r.get("Packaged Lot number")),
|
||||
"original_expiration_date": to_date(r.get("Original Expiration Date when Packaged Lot was Added")),
|
||||
"expiration_date": to_date(r.get("Expiration date")),
|
||||
"received_date": to_date(r.get("Received Date")),
|
||||
"receipt_user": to_str(r.get("Shipment Receipt User")),
|
||||
"subject_identifier": to_str(r.get("Subject Identifier")),
|
||||
"quantity_assigned": to_int(r.get("Quantity Assigned")),
|
||||
"irt_transaction": to_str(r.get("IRT Transaction")),
|
||||
"date_assigned": to_date(r.get("Date Assigned")),
|
||||
"assignment_user": to_str(r.get("Assignment User")),
|
||||
"dispensation_status": to_str(r.get("Dispensation Status")),
|
||||
"dispensing_date": to_date(r.get("Dispensing date") or r.get("Dispensing Date")),
|
||||
"quantity_dispensed": to_int(r.get("Quantity Dispensed")),
|
||||
"dispensing_user": to_str(r.get("Dispensing User")),
|
||||
"quantity_returned": to_int(r.get("Quantity Returned")),
|
||||
"date_returned": to_date(r.get("Date Returned")),
|
||||
"return_user": to_str(r.get("Return User")),
|
||||
})
|
||||
return rows
|
||||
|
||||
|
||||
def parse_destruction_file(path, study):
|
||||
raw = pd.read_excel(path, header=None)
|
||||
meta = {}
|
||||
header_row = None
|
||||
for i, row in raw.iterrows():
|
||||
first = str(row.iloc[0]).strip() if pd.notna(row.iloc[0]) else ""
|
||||
for key, attr in [
|
||||
("Investigator Name:", "investigator"),
|
||||
("Site ID:", "site_id"),
|
||||
("Location:", "location"),
|
||||
("Basket ID:", "basket_id"),
|
||||
("Drug Destruction Created Date:", "destruction_date"),
|
||||
]:
|
||||
if first.startswith(key):
|
||||
meta[attr] = first.replace(key, "").strip()
|
||||
if first == "Medication ID Description" and header_row is None:
|
||||
header_row = i
|
||||
if header_row is None:
|
||||
raise ValueError("hlavičkový řádek 'Medication ID Description' nenalezen")
|
||||
df = pd.read_excel(path, header=header_row).dropna(how="all")
|
||||
basket_id = meta.get("basket_id")
|
||||
rows = []
|
||||
for _, r in df.iterrows():
|
||||
med_id = to_str(r.get("Medication ID"))
|
||||
if not med_id or not basket_id:
|
||||
continue
|
||||
rows.append({
|
||||
"_id": f"{basket_id}:{med_id}",
|
||||
"study": study,
|
||||
"site_id": meta.get("site_id"),
|
||||
"investigator": meta.get("investigator"),
|
||||
"location": meta.get("location"),
|
||||
"basket_id": basket_id,
|
||||
"destruction_date": to_date(meta.get("destruction_date")),
|
||||
"medication_description": to_str(r.get("Medication ID Description")),
|
||||
"medication_id": med_id,
|
||||
"packaged_lot_description": to_str(r.get("Packaged Lot description")),
|
||||
"comments": to_str(r.get("Comments")),
|
||||
})
|
||||
return rows
|
||||
|
||||
|
||||
# ── zpracování souborů ───────────────────────────────────────────────────────
|
||||
|
||||
def _parse_files(files, parser, study, label):
|
||||
"""Zparsuje soubory (nejstarší napřed, poslední vyhrává per _id).
|
||||
|
||||
Vrací (docs, ok_paths, failed_paths).
|
||||
"""
|
||||
docs, ok, failed = {}, [], []
|
||||
for path in files:
|
||||
try:
|
||||
for d in parser(path, study):
|
||||
docs[d["_id"]] = d
|
||||
ok.append(path)
|
||||
except Exception as e:
|
||||
failed.append(path)
|
||||
print(f" [{study}] CHYBA parsování {label} {os.path.basename(path)}: {e}")
|
||||
return list(docs.values()), ok, failed
|
||||
|
||||
|
||||
def import_study(study):
|
||||
ship_files = _pending(f"* {study} Shipments Report*.xlsx")
|
||||
item_files = _pending(f"* {study} Shipment Details *.xlsx")
|
||||
inv_files = _pending(f"* {study} Onsite Inventory *.xlsx")
|
||||
dest_files = _pending(f"* {study} IP Destruction *.xlsx")
|
||||
|
||||
if not (ship_files or item_files or inv_files or dest_files):
|
||||
print(f" [{study}] drugs: nic ke zpracování")
|
||||
return
|
||||
|
||||
shipments, ok_ship, _ = _parse_files(ship_files, parse_shipments_file, study, "shipments")
|
||||
items, ok_item, _ = _parse_files(item_files, parse_shipment_details_file, study, "details")
|
||||
inventory, ok_inv, _ = _parse_files(inv_files, parse_inventory_file, study, "inventory")
|
||||
destruct, ok_dest, _ = _parse_files(dest_files, parse_destruction_file, study, "destruction")
|
||||
|
||||
ok_files = ok_ship + ok_item + ok_inv + ok_dest
|
||||
if not ok_files:
|
||||
print(f" [{study}] drugs: žádný soubor se nepodařilo zparsovat")
|
||||
return
|
||||
|
||||
print(f" [{study}] Zásilky: {len(shipments)} | Položky: {len(items)} | "
|
||||
f"Sklad: {len(inventory)} | Destrukce: {len(destruct)}")
|
||||
|
||||
import_id = log_import(study, f"drugs_{study}", "drugs", {
|
||||
"shipments": len(shipments),
|
||||
"shipment_items": len(items),
|
||||
"inventory": len(inventory),
|
||||
"destruction": len(destruct),
|
||||
})
|
||||
print(f" [{study}] import_id = {import_id}")
|
||||
|
||||
bulk_upsert_with_snapshot("iwrs_shipments", "iwrs_shipments_snapshots", shipments, import_id)
|
||||
bulk_upsert_with_snapshot("iwrs_shipment_items", "iwrs_shipment_items_snapshots", items, import_id)
|
||||
bulk_upsert_with_snapshot("iwrs_inventory", "iwrs_inventory_snapshots", inventory, import_id)
|
||||
bulk_upsert_only("iwrs_destruction", destruct, import_id)
|
||||
|
||||
# zápis do Monga prošel → archivovat zdrojové soubory
|
||||
for path in ok_files:
|
||||
move_done(path)
|
||||
print(f" [{study}] drugs: {len(ok_files)} soubor(ů) přesunuto do Processed")
|
||||
|
||||
|
||||
def run(studies=None):
|
||||
studies = studies or STUDIES
|
||||
if not os.path.isdir(INCOMING_DIR):
|
||||
print(f"Adresář neexistuje: {INCOMING_DIR}")
|
||||
return
|
||||
print("=" * 60)
|
||||
print("Import Drugs (shipments / items / inventory / destruction)")
|
||||
print("=" * 60)
|
||||
for study in studies:
|
||||
try:
|
||||
import_study(study)
|
||||
except Exception as e:
|
||||
import traceback
|
||||
print(f" [{study}] CHYBA importu drugs: {e}")
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
ensure_indexes()
|
||||
run(sys.argv[1:] or None)
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,48 @@
|
||||
"""
|
||||
download_patients.py — stažení pacientských reportů pro jednu studii.
|
||||
Verze: 1.0 | Datum: 2026-06-10
|
||||
|
||||
Volá se z IWRS/run_all_v1.0.py s již přihlášenou Playwright page (login +
|
||||
výběr studie zajišťuje common.iwrs_portal.login).
|
||||
|
||||
1. Subject Summary Report
|
||||
2. Subject Detail Reports + notifikace PDF+JSON (per subjekt, jen nové dle pk v Mongo)
|
||||
|
||||
Vše se ukládá ploše do IWRS/Incoming/ s datumovanými názvy.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import datetime
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
IWRS_DIR = os.path.dirname(BASE_DIR)
|
||||
for _p in (IWRS_DIR, BASE_DIR):
|
||||
if _p not in sys.path:
|
||||
sys.path.insert(0, _p)
|
||||
|
||||
from common.iwrs_portal import BASE_URL
|
||||
from common.paths import INCOMING_DIR, unique_path
|
||||
|
||||
import download_subject_details as dsd
|
||||
|
||||
|
||||
def download_summary(page, study, today):
|
||||
print(f" [{study}] Stahuji Subject Summary Report...")
|
||||
page.goto(f"{BASE_URL}/report/patient_summary_report")
|
||||
page.wait_for_load_state("networkidle", timeout=120000)
|
||||
filename = unique_path(INCOMING_DIR, f"{today} {study} Subject Summary Report")
|
||||
with page.expect_download(timeout=120000) as dl:
|
||||
page.get_by_role("button", name="Download XLS").click()
|
||||
dl.value.save_as(filename)
|
||||
print(f" [{study}] Summary OK -> {os.path.basename(filename)}")
|
||||
return filename
|
||||
|
||||
|
||||
def run(page, study):
|
||||
"""Stáhne summary + detaily + notifikace pro studii do IWRS/Incoming/."""
|
||||
os.makedirs(INCOMING_DIR, exist_ok=True)
|
||||
today = datetime.date.today().strftime("%Y-%m-%d")
|
||||
download_summary(page, study, today)
|
||||
# detail XLSX + notifikace přímo do Incoming/ (flat názvy se study+subject)
|
||||
dsd.run(page, study, out_dir=INCOMING_DIR, subjects_source_dir=INCOMING_DIR)
|
||||
@@ -0,0 +1,90 @@
|
||||
"""
|
||||
import_patients.py — import pacientských reportů z IWRS/Incoming/ do MongoDB.
|
||||
Verze: 1.0 | Datum: 2026-06-10
|
||||
|
||||
Pořadí zpracování per typ + studie: nejstarší soubor podle mtime první
|
||||
(důležité pro chronologickou správnost snapshotů).
|
||||
|
||||
Po úspěšném importu se soubor přesune do IWRS/Incoming/Processed/.
|
||||
Při chybě zůstane soubor v Incoming/.
|
||||
|
||||
Volá se z IWRS/run_all_v1.0.py (ensure_indexes volá orchestrátor);
|
||||
lze spustit i samostatně: python import_patients.py
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
IWRS_DIR = os.path.dirname(BASE_DIR)
|
||||
for _p in (IWRS_DIR, BASE_DIR):
|
||||
if _p not in sys.path:
|
||||
sys.path.insert(0, _p)
|
||||
|
||||
from common.paths import INCOMING_DIR, PROCESSED_DIR, STUDIES, move_done, sorted_by_mtime
|
||||
from common.mongo_writer import ensure_indexes
|
||||
|
||||
import import_to_mongo
|
||||
import import_notifications_to_mongo
|
||||
|
||||
|
||||
def import_summaries(study):
|
||||
pattern = os.path.join(INCOMING_DIR, f"* {study} Subject Summary Report*.xlsx")
|
||||
files = sorted_by_mtime(glob.glob(pattern))
|
||||
if not files:
|
||||
print(f" [{study}] summary: nic ke zpracování")
|
||||
return
|
||||
print(f" [{study}] summary: {len(files)} soubor(ů) (oldest first)")
|
||||
for path in files:
|
||||
try:
|
||||
import_to_mongo.import_subject_summary(study, path)
|
||||
move_done(path)
|
||||
except Exception as e:
|
||||
print(f" [{study}] CHYBA summary {os.path.basename(path)}: {e}")
|
||||
|
||||
|
||||
def import_details(study):
|
||||
pattern = os.path.join(INCOMING_DIR, f"* {study} * Subject Detail.xlsx")
|
||||
files = sorted_by_mtime(glob.glob(pattern))
|
||||
if not files:
|
||||
print(f" [{study}] detail: nic ke zpracování")
|
||||
return
|
||||
print(f" [{study}] detail: {len(files)} soubor(ů) (oldest first)")
|
||||
for path in files:
|
||||
parsed = import_to_mongo.parse_detail_filename(path)
|
||||
if not parsed:
|
||||
print(f" [{study}] PŘESKAKUJI (nelze parsovat název): {os.path.basename(path)}")
|
||||
continue
|
||||
_, parsed_study, subject = parsed
|
||||
if parsed_study != study:
|
||||
continue # patří jiné studii
|
||||
try:
|
||||
import_to_mongo.import_visits_single_file(study, subject, path)
|
||||
move_done(path)
|
||||
except Exception as e:
|
||||
print(f" [{study}] CHYBA detail {os.path.basename(path)}: {e}")
|
||||
|
||||
|
||||
def run(studies=None):
|
||||
studies = studies or STUDIES
|
||||
if not os.path.isdir(INCOMING_DIR):
|
||||
print(f"Adresář neexistuje: {INCOMING_DIR}")
|
||||
return
|
||||
|
||||
print("=" * 60)
|
||||
print("Import Subject Summary + Visits")
|
||||
print("=" * 60)
|
||||
for study in studies:
|
||||
import_summaries(study)
|
||||
import_details(study)
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("Import notifikací")
|
||||
print("=" * 60)
|
||||
import_notifications_to_mongo.import_from_dir(INCOMING_DIR, PROCESSED_DIR, studies)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
ensure_indexes()
|
||||
run()
|
||||
@@ -0,0 +1,24 @@
|
||||
"""
|
||||
iwrs_portal.py — přihlášení k IWRS portálu janssen.4gclinical.com (Playwright).
|
||||
Verze: 1.0 | Datum: 2026-06-10
|
||||
|
||||
Studie se vybírá až po přihlášení, proto login(page, study) udělá obojí.
|
||||
"""
|
||||
|
||||
BASE_URL = "https://janssen.4gclinical.com"
|
||||
EMAIL = "vbuzalka@its.jnj.com"
|
||||
PASSWORD = "Vlado123++-+"
|
||||
|
||||
|
||||
def login(page, study):
|
||||
"""Přihlásí se a vybere studii. Page musí být čerstvá (nepřihlášená)."""
|
||||
page.goto(BASE_URL)
|
||||
page.wait_for_load_state("networkidle")
|
||||
page.get_by_label("Email *").fill(EMAIL)
|
||||
page.get_by_label("Password *").fill(PASSWORD)
|
||||
page.locator("#login__submit").click()
|
||||
page.wait_for_load_state("networkidle")
|
||||
page.get_by_label("Study *").click()
|
||||
page.get_by_role("option", name=study).click()
|
||||
page.get_by_role("button", name="SELECT").click()
|
||||
page.wait_for_load_state("networkidle")
|
||||
@@ -0,0 +1,54 @@
|
||||
"""
|
||||
paths.py — sdílené cesty a souborové utility pro IWRS pipeline.
|
||||
Verze: 1.0 | Datum: 2026-06-10
|
||||
|
||||
Tok souborů:
|
||||
IWRS/Incoming/ — sem padají všechny stažené reporty (pacienti i léky)
|
||||
IWRS/Incoming/Processed/ — sem se přesouvají po úspěšném importu do MongoDB
|
||||
Při chybě importu soubor zůstává v Incoming/ a zpracuje se při příštím běhu.
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import datetime
|
||||
|
||||
IWRS_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
INCOMING_DIR = os.path.join(IWRS_DIR, "Incoming")
|
||||
PROCESSED_DIR = os.path.join(INCOMING_DIR, "Processed")
|
||||
|
||||
STUDIES = ["77242113UCO3001", "42847922MDD3003"]
|
||||
|
||||
|
||||
def ensure_dirs():
|
||||
os.makedirs(INCOMING_DIR, exist_ok=True)
|
||||
os.makedirs(PROCESSED_DIR, exist_ok=True)
|
||||
|
||||
|
||||
def unique_path(directory, stem, ext=".xlsx"):
|
||||
"""Cesta bez kolize — při kolizi přidá ' HHMM' před příponu."""
|
||||
path = os.path.join(directory, f"{stem}{ext}")
|
||||
if not os.path.exists(path):
|
||||
return path
|
||||
time_tag = datetime.datetime.now().strftime("%H%M")
|
||||
return os.path.join(directory, f"{stem} {time_tag}{ext}")
|
||||
|
||||
|
||||
def move_done(path, done_dir=None):
|
||||
"""Přesune zpracovaný soubor do Processed/.
|
||||
|
||||
Kolize → přepíše (Mongo už má aktuální data, soubor je jen archiv).
|
||||
"""
|
||||
dst_dir = done_dir or PROCESSED_DIR
|
||||
os.makedirs(dst_dir, exist_ok=True)
|
||||
dst = os.path.join(dst_dir, os.path.basename(path))
|
||||
if os.path.exists(dst):
|
||||
os.remove(dst)
|
||||
shutil.move(path, dst)
|
||||
|
||||
|
||||
def sorted_by_mtime(paths):
|
||||
"""Nejstarší první, bez Excel lock souborů (~$...)."""
|
||||
return sorted(
|
||||
(p for p in paths if not os.path.basename(p).startswith("~$")),
|
||||
key=os.path.getmtime,
|
||||
)
|
||||
@@ -0,0 +1,110 @@
|
||||
# run_all_v1.0.py — IWRS: kompletní pipeline Pacienti + Léky
|
||||
|
||||
**Verze:** 1.0 | **Datum:** 2026-06-10
|
||||
|
||||
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). Nahrazuje dřívější `Drugs/run_all.py`
|
||||
a `Patients/download_all.py` + `Patients/import_all.py` (přesunuty do `Trash/`).
|
||||
|
||||
## 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` (stejně jako dříve `Patients/Incoming/`).
|
||||
- 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** (`Patients/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** (`Drugs/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); dříve se přeskakovalo podle existence souboru
|
||||
- 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);
|
||||
dříve „soubor existuje a status RECEIVED“. CANCELLED zásilky se stahují
|
||||
při každém běhu (záměrně zachováno z původní verze).
|
||||
|
||||
### Fáze 2 — import (po stažení obou studií)
|
||||
|
||||
1. `ensure_indexes()` (jednou)
|
||||
2. **Pacienti** (`Patients/import_patients.py`): summary → detaily → notifikace;
|
||||
per soubor, po úspěchu přesun do Processed/
|
||||
3. **Léky** (`Drugs/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/.
|
||||
|
||||
## Použití
|
||||
|
||||
```
|
||||
python run_all_v1.0.py # vše (download + import, obě studie)
|
||||
python run_all_v1.0.py --download-only # jen stažení do Incoming/
|
||||
python run_all_v1.0.py --import-only # jen import čekajících souborů
|
||||
python run_all_v1.0.py --only-patients # jen pacientská část
|
||||
python run_all_v1.0.py --only-drugs # jen léková část
|
||||
python run_all_v1.0.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ů
|
||||
|
||||
```
|
||||
IWRS/
|
||||
run_all_v1.0.py ← vstupní skript (CLI, orchestrace)
|
||||
common/
|
||||
iwrs_portal.py ← BASE_URL, credentials, login(page, study)
|
||||
paths.py ← INCOMING/PROCESSED, unique_path, move_done, sorted_by_mtime
|
||||
mongo_writer.py ← beze změny (konvertory, upserty, snapshoty, import log)
|
||||
Patients/
|
||||
download_patients.py ← summary + delegace na download_subject_details.run()
|
||||
import_patients.py ← logika z bývalého import_all.py, nové cesty
|
||||
download_subject_details.py, import_to_mongo.py,
|
||||
import_notifications_to_mongo.py, parse_notifications_to_mongo.py ← beze změny
|
||||
Trash/download_all.py, Trash/import_all.py ← nahrazeno
|
||||
Drugs/
|
||||
download_drugs.py ← 4 typy reportů → Incoming/, skip-logika přes Mongo
|
||||
import_drugs.py ← parsery z bývalého import_to_mongo.py, čte Incoming/
|
||||
Trash/run_all.py, Trash/import_to_mongo.py ← nahrazeno
|
||||
```
|
||||
|
||||
## 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 → `Trash/` (viz mapa výše)
|
||||
@@ -0,0 +1,147 @@
|
||||
"""
|
||||
================================================================================
|
||||
run_all_v1.0.py — IWRS: kompletní pipeline Pacienti + Léky (obě studie)
|
||||
Verze: 1.0
|
||||
Datum: 2026-06-10
|
||||
================================================================================
|
||||
|
||||
Stáhne z janssen.4gclinical.com a naimportuje do MongoDB (db `studie`):
|
||||
|
||||
Pacienti: Subject Summary, Subject Details, notifikace (PDF+JSON)
|
||||
Léky: Onsite Inventory, IP Destruction, Shipments Report, Shipment Details
|
||||
|
||||
Tok souborů: vše se stahuje do IWRS/Incoming/, po úspěšném importu se přesouvá
|
||||
do IWRS/Incoming/Processed/. Při chybě soubor zůstává v Incoming/ a zpracuje
|
||||
se při příštím běhu.
|
||||
|
||||
Přihlášení: 2× (jednou per studie) — studie se vybírá až po přihlášení, takže
|
||||
jedna browser session stáhne pacienty i léky pro jednu studii.
|
||||
|
||||
Použití:
|
||||
python run_all_v1.0.py # vše (download + import, obě studie)
|
||||
python run_all_v1.0.py --download-only # jen stažení do Incoming/
|
||||
python run_all_v1.0.py --import-only # jen import čekajících souborů
|
||||
python run_all_v1.0.py --only-patients # jen pacientská část
|
||||
python run_all_v1.0.py --only-drugs # jen léková část
|
||||
python run_all_v1.0.py --study 42847922MDD3003 # jen jedna studie
|
||||
|
||||
Detaily v run_all_v1.0.md.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import traceback
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
for _p in (os.path.join(BASE_DIR, "Drugs"), os.path.join(BASE_DIR, "Patients"), BASE_DIR):
|
||||
if _p not in sys.path:
|
||||
sys.path.insert(0, _p)
|
||||
|
||||
from playwright.sync_api import sync_playwright
|
||||
|
||||
from common.iwrs_portal import login
|
||||
from common.paths import STUDIES, INCOMING_DIR, PROCESSED_DIR, ensure_dirs
|
||||
from common.mongo_writer import ensure_indexes
|
||||
|
||||
import download_patients
|
||||
import import_patients
|
||||
import download_drugs
|
||||
import import_drugs
|
||||
|
||||
|
||||
def download_phase(studies, do_patients, do_drugs):
|
||||
with sync_playwright() as p:
|
||||
for study in studies:
|
||||
print(f"\n{'='*60}")
|
||||
print(f"[{study}] STAHOVÁNÍ")
|
||||
print(f"{'='*60}")
|
||||
|
||||
browser = p.chromium.launch(headless=False)
|
||||
context = browser.new_context(accept_downloads=True)
|
||||
page = context.new_page()
|
||||
|
||||
try:
|
||||
print(" Přihlášení...")
|
||||
login(page, study)
|
||||
|
||||
if do_patients:
|
||||
print(f"\n ── PACIENTI [{study}] ──")
|
||||
try:
|
||||
download_patients.run(page, study)
|
||||
except Exception as e:
|
||||
print(f" CHYBA při stahování pacientů: {e}")
|
||||
traceback.print_exc()
|
||||
|
||||
if do_drugs:
|
||||
print(f"\n ── LÉKY [{study}] ──")
|
||||
try:
|
||||
download_drugs.run(page, study)
|
||||
except Exception as e:
|
||||
print(f" CHYBA při stahování léků: {e}")
|
||||
traceback.print_exc()
|
||||
|
||||
except Exception as e:
|
||||
print(f" CHYBA (login/session): {e}")
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
browser.close()
|
||||
|
||||
|
||||
def import_phase(studies, do_patients, do_drugs):
|
||||
print(f"\n{'='*60}")
|
||||
print("IMPORT DO MongoDB")
|
||||
print(f"{'='*60}")
|
||||
ensure_indexes()
|
||||
|
||||
if do_patients:
|
||||
try:
|
||||
import_patients.run(studies)
|
||||
except Exception as e:
|
||||
print(f" CHYBA při importu pacientů: {e}")
|
||||
traceback.print_exc()
|
||||
|
||||
if do_drugs:
|
||||
try:
|
||||
import_drugs.run(studies)
|
||||
except Exception as e:
|
||||
print(f" CHYBA při importu léků: {e}")
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(
|
||||
description="IWRS pipeline: stažení + import pacientů a léků (obě studie)")
|
||||
ap.add_argument("--download-only", action="store_true", help="jen stažení do Incoming/")
|
||||
ap.add_argument("--import-only", action="store_true", help="jen import čekajících souborů")
|
||||
ap.add_argument("--only-patients", action="store_true", help="jen pacientská část")
|
||||
ap.add_argument("--only-drugs", action="store_true", help="jen léková část")
|
||||
ap.add_argument("--study", choices=STUDIES, help="jen jedna studie")
|
||||
args = ap.parse_args()
|
||||
|
||||
if args.download_only and args.import_only:
|
||||
ap.error("--download-only a --import-only nelze kombinovat")
|
||||
if args.only_patients and args.only_drugs:
|
||||
ap.error("--only-patients a --only-drugs nelze kombinovat")
|
||||
|
||||
studies = [args.study] if args.study else STUDIES
|
||||
do_patients = not args.only_drugs
|
||||
do_drugs = not args.only_patients
|
||||
|
||||
ensure_dirs()
|
||||
|
||||
if not args.import_only:
|
||||
download_phase(studies, do_patients, do_drugs)
|
||||
|
||||
if not args.download_only:
|
||||
import_phase(studies, do_patients, do_drugs)
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print("Vše hotovo.")
|
||||
print(f" Incoming: {INCOMING_DIR}")
|
||||
print(f" Processed: {PROCESSED_DIR}")
|
||||
print(f"{'='*60}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user