115 lines
3.9 KiB
Python
115 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
import sys as _sys
|
||
_sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
||
_sys.stderr.reconfigure(encoding="utf-8", errors="replace")
|
||
"""
|
||
01_parse_seznam.py
|
||
==================
|
||
Najde a rozparsuje dávky VZP – Seznam registrovaných pojištěnců (III-1.1.2).
|
||
Formát souboru: Fxxxmmur.nnn, pevná šířka, kódování CP852.
|
||
|
||
Záhlaví (typ H, délka 20):
|
||
HTYP C 1 0 typ věty 'H'
|
||
HICP N 8 1 IČP lékaře
|
||
HPUP N 5 9 počet uznávaných pojištěnců
|
||
HROK N 2 14 poslední dvojčíslí roku
|
||
HMES N 2 16 měsíc
|
||
HDEN N 2 18 den
|
||
|
||
Registrace (typ I, délka 82):
|
||
ITYP C 1 0 typ věty 'I'
|
||
IPOR N 4 1 pořadové číslo
|
||
IVS N 2 5 věková skupina
|
||
IPRI C 30 7 příjmení
|
||
IJME C 24 37 jméno
|
||
ICIP C 10 61 číslo pojištěnce
|
||
IDUOD D 8 71 datum uznání registrace (DDMMRRRR)
|
||
ICPO C 3 79 kód pojišťovny
|
||
"""
|
||
|
||
import re
|
||
from pathlib import Path
|
||
from datetime import date, timedelta
|
||
|
||
DAVKY_DIR = Path(r"U:\Dropbox\Ordinace\Dokumentace_ke_zpracování\Zúčtovací zprávy\111 VZP Podání")
|
||
ENCODING = "cp852"
|
||
|
||
|
||
def parse_davku(path: Path) -> dict:
|
||
"""Vrátí dict s klíči 'hlavicka' a 'pojistenci'."""
|
||
lines = path.read_bytes().splitlines()
|
||
hlavicka = None
|
||
pojistenci = []
|
||
|
||
for raw in lines:
|
||
line = raw.decode(ENCODING, errors="replace")
|
||
if not line:
|
||
continue
|
||
|
||
if line[0] == "H":
|
||
hlavicka = {
|
||
"icp": line[1:9].strip(),
|
||
"pocet": int(line[9:14].strip() or 0),
|
||
"rok": 2000 + int(line[14:16]),
|
||
"mesic": int(line[16:18]),
|
||
"den": int(line[18:20]),
|
||
}
|
||
|
||
elif line[0] == "I":
|
||
if len(line) < 82:
|
||
continue
|
||
dat_raw = line[71:79] # DDMMRRRR
|
||
try:
|
||
datum = date(int(dat_raw[4:8]), int(dat_raw[2:4]), int(dat_raw[0:2]))
|
||
except ValueError:
|
||
datum = None
|
||
|
||
pojistenci.append({
|
||
"por": int(line[1:5].strip() or 0),
|
||
"vs": line[5:7].strip(),
|
||
"prijmeni": line[7:37].strip(),
|
||
"jmeno": line[37:61].strip(),
|
||
"cip": line[61:71].strip(),
|
||
"datum_od": datum,
|
||
"pojistovna": line[79:82].strip(),
|
||
})
|
||
|
||
return {"hlavicka": hlavicka, "pojistenci": pojistenci, "soubor": path.name}
|
||
|
||
|
||
def najdi_davky(adresar: Path) -> list[Path]:
|
||
"""Vrátí seřazený seznam souborů odpovídajících vzoru Fxxx*.nnn."""
|
||
return sorted(
|
||
[p for p in adresar.iterdir()
|
||
if re.search(r"F\d{3}.*\.\d{3}$", p.name, re.IGNORECASE)],
|
||
key=lambda p: p.name
|
||
)
|
||
|
||
|
||
def tiskni_davku(d: dict) -> None:
|
||
h = d["hlavicka"]
|
||
if h:
|
||
print(f"\n=== {d['soubor']} ===")
|
||
print(f" IČP: {h['icp']} | datum: {h['den']:02d}.{h['mesic']:02d}.{h['rok']} | pojištěnců: {h['pocet']}")
|
||
print(f" {'#':>4} {'Příjmení':<30} {'Jméno':<24} {'ČIP':<10} {'Datum od':>10} Pojiš.")
|
||
print(f" {'-'*4} {'-'*30} {'-'*24} {'-'*10} {'-'*10} {'-'*6}")
|
||
else:
|
||
print(f"\n=== {d['soubor']} === (záhlaví chybí)")
|
||
|
||
for p in d["pojistenci"]:
|
||
datum_str = p["datum_od"].strftime("%d.%m.%Y") if p["datum_od"] else "?"
|
||
print(f" {p['por']:>4} {p['prijmeni']:<30} {p['jmeno']:<24} {p['cip']:<10} {datum_str:>10} {p['pojistovna']}")
|
||
|
||
|
||
# ── MAIN ──────────────────────────────────────────────────────────────────────
|
||
|
||
davky = najdi_davky(DAVKY_DIR)
|
||
print(f"Nalezeno dávek: {len(davky)}")
|
||
|
||
for cesta in davky:
|
||
data = parse_davku(cesta)
|
||
tiskni_davku(data)
|
||
|
||
print(f"\nCelkem dávek: {len(davky)}")
|