202 lines
7.7 KiB
Python
202 lines
7.7 KiB
Python
"""
|
|
Report posledních receptů — generuje HTML soubor.
|
|
|
|
Spuštění:
|
|
python report/report_predpisy.py
|
|
|
|
Výstup:
|
|
report/report_predpisy.html
|
|
"""
|
|
|
|
from pathlib import Path
|
|
from datetime import date
|
|
import pymysql
|
|
import pymysql.cursors
|
|
|
|
# ── Konfigurace ───────────────────────────────────────────────────────────────
|
|
DB = dict(
|
|
host = "192.168.1.76",
|
|
user = "root",
|
|
password = "Vlado9674+",
|
|
database = "medicus",
|
|
charset = "utf8mb4",
|
|
cursorclass = pymysql.cursors.DictCursor,
|
|
)
|
|
|
|
LIMIT = 100
|
|
VYSTUP = Path(__file__).parent / "report_predpisy.html"
|
|
|
|
# ── Odbornosti ────────────────────────────────────────────────────────────────
|
|
def nacti_odbornosti(conn):
|
|
with conn.cursor() as cur:
|
|
cur.execute("""
|
|
SELECT vp.icp, o.nazev
|
|
FROM vzp_pracoviste vp
|
|
JOIN odbornost o ON o.kod = vp.odbornost
|
|
WHERE CURDATE() BETWEEN vp.platnost_od AND vp.platnost_do
|
|
ORDER BY vp.platnost_od DESC
|
|
""")
|
|
result = {}
|
|
for row in cur.fetchall():
|
|
result.setdefault(row["icp"], row["nazev"])
|
|
return result
|
|
|
|
def odbornost_z_icp(icp, slovnik):
|
|
if not icp or len(icp) < 3:
|
|
return ""
|
|
return slovnik.get(icp, f"odb. {icp[-3:]}")
|
|
|
|
# ── Data ──────────────────────────────────────────────────────────────────────
|
|
def nacti_predpisy(conn, limit):
|
|
with conn.cursor() as cur:
|
|
cur.execute("""
|
|
SELECT
|
|
p.datum_vystaveni,
|
|
z.pacient_prijmeni,
|
|
z.pacient_jmena,
|
|
z.pacient_datum_narozeni,
|
|
COALESCE(v.nazev, p.nazev) AS vydany_lek,
|
|
v.nazev IS NULL AS nevyzvednuto,
|
|
p.atc,
|
|
p.navod,
|
|
pr.prijmeni AS lekar_prijmeni,
|
|
pr.jmena AS lekar_jmena,
|
|
pr.icp,
|
|
pr.pzs_nazev,
|
|
pr.ulice,
|
|
pr.psc,
|
|
pr.mesto,
|
|
rd.stav,
|
|
rd.druh_pojisteni
|
|
FROM predpis p
|
|
JOIN zprava z ON z.id = p.zprava_id
|
|
JOIN predepisujici pr ON pr.lekar_kod = p.kod_predepisujiciho
|
|
LEFT JOIN vydej v ON v.id_lp_predpis = p.id_lp_predpis
|
|
LEFT JOIN recept_plp rp ON rp.id_lp = p.id_lp_predpis
|
|
LEFT JOIN recept_doklad rd ON rd.id_dokladu = rp.id_dokladu
|
|
ORDER BY p.datum_vystaveni DESC, p.id DESC
|
|
LIMIT %s
|
|
""", (limit,))
|
|
return cur.fetchall()
|
|
|
|
# ── HTML ──────────────────────────────────────────────────────────────────────
|
|
def stav_badge(stav, nevyzvednuto):
|
|
if nevyzvednuto:
|
|
return '<span class="badge badge-nv">nevyzvednut</span>'
|
|
if stav == "PLNE_VYDANY":
|
|
return '<span class="badge badge-ok">vydán</span>'
|
|
if stav == "CASTECNE_VYDANY":
|
|
return '<span class="badge badge-partial">část. vydán</span>'
|
|
if stav == "ZRUSENY":
|
|
return '<span class="badge badge-cancel">zrušen</span>'
|
|
if stav == "PRIPRAVOVANY":
|
|
return '<span class="badge badge-prep">připravován</span>'
|
|
if stav == "PREDEPSANY":
|
|
return '<span class="badge badge-pred">předepsán</span>'
|
|
return ""
|
|
|
|
def e(s):
|
|
"""HTML escape."""
|
|
if s is None:
|
|
return ""
|
|
return str(s).replace("&", "&").replace("<", "<").replace(">", ">")
|
|
|
|
def render_html(rows, odbornosti, dnes):
|
|
radky = []
|
|
for i, r in enumerate(rows, 1):
|
|
lekar = f"{e(r['lekar_prijmeni'])} {e(r['lekar_jmena'])}".strip()
|
|
pacient = f"{e(r['pacient_prijmeni'])} {e(r['pacient_jmena'])}".strip()
|
|
odb = e(odbornost_z_icp(r["icp"], odbornosti))
|
|
adresa = ", ".join(filter(None, [e(r["pzs_nazev"]), e(r["ulice"]),
|
|
f"{e(r['psc'])} {e(r['mesto'])}".strip()]))
|
|
badge = stav_badge(r["stav"], r["nevyzvednuto"])
|
|
tr_class = "tr-nv" if r["nevyzvednuto"] else ("tr-even" if i % 2 == 0 else "")
|
|
|
|
radky.append(f"""
|
|
<tr class="{tr_class}">
|
|
<td class="num">{i}</td>
|
|
<td class="datum">{e(r['datum_vystaveni'])}</td>
|
|
<td>{pacient}<br><small>{e(r['pacient_datum_narozeni'])}</small></td>
|
|
<td><strong>{e(r['vydany_lek'])}</strong>{badge}<br><small class="atc">{e(r['atc'])}</small></td>
|
|
<td class="navod">{e(r['navod'])}</td>
|
|
<td>{lekar}<br><small>{odb}</small></td>
|
|
<td class="adresa">{adresa}</td>
|
|
</tr>""")
|
|
|
|
return f"""<!DOCTYPE html>
|
|
<html lang="cs">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Přehled receptů</title>
|
|
<style>
|
|
* {{ box-sizing: border-box; margin: 0; padding: 0; }}
|
|
body {{ font-family: Arial, sans-serif; font-size: 13px; background: #f4f6f9; color: #222; }}
|
|
header {{ background: #1F4E79; color: #fff; padding: 18px 28px; }}
|
|
header h1 {{ font-size: 20px; font-weight: bold; }}
|
|
header p {{ font-size: 12px; opacity: .8; margin-top: 4px; }}
|
|
.wrap {{ padding: 20px 28px; }}
|
|
table {{ width: 100%; border-collapse: collapse; background: #fff; border-radius: 6px; overflow: hidden; box-shadow: 0 1px 4px rgba(0,0,0,.1); }}
|
|
thead tr {{ background: #1F4E79; color: #fff; font-size: 12px; }}
|
|
thead th {{ padding: 10px 10px; text-align: left; font-weight: 600; }}
|
|
tbody td {{ padding: 8px 10px; border-bottom: 1px solid #dce6f1; vertical-align: top; }}
|
|
tbody tr:last-child td {{ border-bottom: none; }}
|
|
.tr-even {{ background: #EBF3FB; }}
|
|
.tr-nv {{ background: #FCE4D6; }}
|
|
.num {{ color: #888; width: 36px; text-align: right; }}
|
|
.datum {{ white-space: nowrap; width: 90px; }}
|
|
.atc {{ color: #666; }}
|
|
.navod {{ max-width: 200px; color: #444; }}
|
|
.adresa {{ font-size: 11px; color: #555; max-width: 180px; }}
|
|
small {{ font-size: 11px; color: #666; }}
|
|
.badge {{ display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 10px; font-size: 10px; font-weight: bold; vertical-align: middle; }}
|
|
.badge-ok {{ background: #d4edda; color: #155724; }}
|
|
.badge-nv {{ background: #FCE4D6; color: #c0392b; }}
|
|
.badge-partial {{ background: #fff3cd; color: #856404; }}
|
|
.badge-cancel {{ background: #e2e3e5; color: #383d41; }}
|
|
.badge-pred {{ background: #d1ecf1; color: #0c5460; }}
|
|
.badge-prep {{ background: #e8daef; color: #6c3483; }}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<h1>Přehled receptů — posledních {LIMIT}</h1>
|
|
<p>Vygenerováno: {dnes} | Počet záznamů: {len(rows)}</p>
|
|
</header>
|
|
<div class="wrap">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>#</th>
|
|
<th>Datum</th>
|
|
<th>Pacient</th>
|
|
<th>Vydaný lék</th>
|
|
<th>Návod</th>
|
|
<th>Lékař / Odbornost</th>
|
|
<th>Pracoviště</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{"".join(radky)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</body>
|
|
</html>"""
|
|
|
|
|
|
def main():
|
|
conn = pymysql.connect(**DB)
|
|
print("Načítám odbornosti...")
|
|
odbornosti = nacti_odbornosti(conn)
|
|
print(f"Načítám posledních {LIMIT} receptů...")
|
|
rows = nacti_predpisy(conn, LIMIT)
|
|
conn.close()
|
|
|
|
html = render_html(rows, odbornosti, date.today().isoformat())
|
|
VYSTUP.write_text(html, encoding="utf-8")
|
|
print(f"Hotovo: {VYSTUP}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|