Files
ordinaceprojekt/DASTA/roztrid_dle_odberu.py
T
2026-06-15 16:10:24 +02:00

115 lines
3.6 KiB
Python
Raw 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.
# -*- coding: utf-8 -*-
"""
Roztřídí DASTA XML soubory do adresářové struktury podle DATA ODBĚRU.
Zdroj: u:\\Dropbox\\Ordinace\\pomoc\\DASTA\\*.xml
Cíl: U:\\DASTA_SUBGROUPS\\RRRR\\MM\\DD\\<soubor>.xml (kopie, originál zůstává)
Datum odběru = první element <dat_du> v souboru (první potomek prvního <vr>).
Hodnota má formát DTS (2016-06-20T08:00:00) nebo DT (2017-05-18T07:30)
v obou případech začíná YYYY-MM-DD, takže rok/měsíc/den čteme z prvních znaků.
Speciální případy:
_BEZ_DATUMU soubor neobsahuje žádný <dat_du>
_CHYBY soubor se nepodařilo naparsovat
Použití:
python roztrid_dle_odberu.py # zdroj = výchozí (Dropbox)
python roztrid_dle_odberu.py U:\\DASTA # jiný zdrojový adresář
python roztrid_dle_odberu.py U:\\DASTA --dry-run # jen vypíše, co by udělal
"""
from __future__ import annotations
import re
import shutil
import sys
from collections import Counter
from pathlib import Path
from xml.etree import ElementTree as ET
ZDROJ_VYCHOZI = Path(r"u:\dasta")
CIL = Path(r"U:\DASTA_SUBGROUPS")
# Záchytný regex pro případ, že ElementTree selže (poškozená hlavička apod.)
_RE_DAT_DU = re.compile(rb"<dat_du[^>]*>\s*(\d{4})-(\d{2})-(\d{2})")
def datum_odberu(cesta: Path) -> tuple[str, str, str] | None:
"""Vrátí (rok, měsíc, den) z prvního <dat_du>, nebo None když chybí."""
raw = cesta.read_bytes()
# Rychlá a robustní cesta: najdi první <dat_du> v bytech.
m = _RE_DAT_DU.search(raw)
if m:
return m.group(1).decode(), m.group(2).decode(), m.group(3).decode()
# Záloha přes ElementTree (kdyby byl dat_du formátovaný jinak)
try:
root = ET.fromstring(raw)
el = root.find(".//dat_du")
if el is not None and el.text:
d = el.text.strip()
return d[0:4], d[5:7], d[8:10]
except ET.ParseError:
raise
return None
def main() -> None:
dry = "--dry-run" in sys.argv
pozicni = [a for a in sys.argv[1:] if not a.startswith("--")]
zdroj = Path(pozicni[0]) if pozicni else ZDROJ_VYCHOZI
soubory = sorted(zdroj.glob("*.xml"))
print(f"Zdroj: {zdroj}")
print(f"Cíl: {CIL}")
print(f"Nalezeno souborů: {len(soubory)}"
f"{' [DRY-RUN]' if dry else ''}")
print("-" * 60)
if not dry:
CIL.mkdir(parents=True, exist_ok=True)
stat = Counter()
roky = Counter()
chyby: list[str] = []
for src in soubory:
try:
d = datum_odberu(src)
except ET.ParseError as e:
d = None
cilovy_dir = CIL / "_CHYBY"
chyby.append(f"{src.name}: parse error {e}")
stat["chyba"] += 1
else:
if d is None:
cilovy_dir = CIL / "_BEZ_DATUMU"
stat["bez_datumu"] += 1
else:
rok, mes, den = d
cilovy_dir = CIL / rok / mes / den
stat["ok"] += 1
roky[rok] += 1
dst = cilovy_dir / src.name
if dry:
continue
cilovy_dir.mkdir(parents=True, exist_ok=True)
shutil.copy2(src, dst)
print("Hotovo:")
print(f" zařazeno dle data odběru : {stat['ok']}")
print(f" bez data (_BEZ_DATUMU) : {stat['bez_datumu']}")
print(f" chyby parsování (_CHYBY) : {stat['chyba']}")
if roky:
print("\nRozložení podle roku:")
for rok in sorted(roky):
print(f" {rok}: {roky[rok]}")
if chyby:
print("\nDetail chyb:")
for c in chyby:
print(f" {c}")
if __name__ == "__main__":
main()