# MedicusWithClaudePN – Pracovní neschopnosti

## Účel

Report aktivních pracovních neschopností pro MUDr. Buzalkovou Michaelu.
Generuje PDF a odesílá na výchozí tiskárnu.

## Spuštění

```bash
# Test – otevře PDF v prohlížeči, netiskne:
python pn_report.py --no-print

# Ostrý provoz – vytiskne rovnou na výchozí tiskárnu:
python pn_report.py
```

## Požadavky

```bash
pip install reportlab pywin32
```

## SQL dotaz – aktivní PN

Zachycen přes Firebird trace přímo z Medicusu (přesná kopie logiky aplikace),
doplněn o podotaz na poslední 14denní potvrzení z tabulky HPN.

```sql
SELECT
    nes.id,
    nes.idpac,
    TRIM(kar.prijmeni) || ', ' || TRIM(kar.jmeno) AS jmeno,
    kar.rodcis,
    nes.zacnes,
    nes.konnes,
    nes.diagno,
    COALESCE(nes.ecn, nes.cisnes) AS cisnes,
    (SELECT MAX(h.datum) FROM hpn h
     WHERE h.idnes = nes.id AND h.typ = '2' AND h.storno = 'F') AS posl_potvrzeni
FROM nes, kar
WHERE nes.zacnes <= current_date
  AND nes.konnes IS NULL
  AND nes.idpac = kar.idpac
  AND nes.pracne = 'A'
  AND nes.storno <> 'T'
  AND (
      NOT EXISTS (SELECT id FROM nesd WHERE nesd.idnes = nes.id)
      OR (SELECT FIRST 1 kam FROM nesd WHERE nesd.idnes = nes.id
          ORDER BY nesd.datum DESC, nesd.id DESC) = 'N'
  )
ORDER BY kar.prijmeni ASC, kar.jmeno ASC
```

### Klíčové podmínky

| Podmínka | Význam |
|---|---|
| `pracne = 'A'` | Pouze pracovní neschopnosti (ne jiné typy) |
| `storno <> 'T'` | Vyřazení stornovaných záznamů |
| `zacnes <= current_date` | PN již začala |
| `konnes IS NULL` | PN dosud neskončila – datum konce nemůže být v budoucnosti (pravidlo ČSSZ), aktivní PN má vždy `konnes = NULL` |
| `nesd` subquery | PN nebyla předána dál – poslední záznam `Kam = 'N'` = stále u pacienta |
| `COALESCE(ecn, cisnes)` | Použije ECN (elektronické), jinak starší CISNES |

## Sloupce reportu

| Sloupec | Zdroj | Poznámka |
|---|---|---|
| # | – | Pořadové číslo |
| Příjmení a jméno | KAR | |
| Rod. číslo | KAR | |
| Začátek PN | NES.ZACNES | |
| Dnů | výpočet | Počet dní od začátku PN do dnes |
| Diagnóza | NES.DIAGNO | |
| Posl. potvrzení | HPN (TYP='2') | Datum posledního 14denního potvrzení |
| Dní od potvr. | výpočet | Červeně pokud > 14 dní |

## Tabulka HPN – typy podání

| TYP | Význam |
|---|---|
| `H` | Hlášení neschopnosti (vznik PN) |
| `1` | První zpráva |
| `P` | **Průběžná zpráva = 14denní potvrzení trvání PN** |
| `2` | Neznámý typ (2033 záznamů v DB, ale ne pro průběžná potvrzení) |
| `C`, `Y`, `Z` | Vzácné typy (jednotky záznamů) |

Vazba: `HPN.IDNES → NES.ID`

---

## Jak Medicus zobrazuje PN daného pacienta (zachyceno z trace)

### 1. Seznam všech PN pacienta

```sql
SELECT
    ID, IDPAC, DATNES, CISNES, PODNIK, ADRESA, PROFES, ZACNES,
    KONNES, PRACNE, PRICINA, DIAGNO, KONDIA, PREDAN, IDUZI,
    VYSTAVIL, DATUKONNES, IDODD, IDPRAC, STORNO,
    DATVYCHOD, DATVYCHDO, VYCH1OD, VYCH1DO, VYCH2OD, VYCH2DO, VYCH3OD, VYCH3DO,
    DATOSETRENI, DATPRINAV, OMLUVENKA, RODCISNES,
    DatNastUstPece, DatUkonUstPece, ICPE, ECN, EPODANI,
    ADR_OBEC, ADR_CP, ADR_CO, ADR_DOD, ADR_PSC, ADR_STAT,
    ZAM_ADRESA, DATUKON_OSSZ, ZAMDRUH, STATDPNKOD,
    SOUHLAS_SSZKOD, SOUHLAS_SSZNAZ, SOUHLAS_DATUM,
    DGZMENA, CIZI, OSSZ, DUVOD_UKONCENI, UKON_OSSZ, PORUS_REZIMU,
    UKON_OSSZNAZ, ADR_ZMENA, coalesce(ECN, CISNES) as CISLO,
    ADR_ZMENA_DO, POTVRZENI_VYDANO, DATNAR, SPRAVCE_POJ,
    ZAM_OBEC, ZAM_CO, ZAM_CP, ZAM_DOD, ZAM_PSC, ZAM_STAT, ZAM_CCSZ_ID, ZAM_CSSZ_VARSYM,
    VYCHINDIVIDUAL, VERZE_DPN, LEKAR_VYSTAVIL, LEKAR_VYSTAVIL_ICPE,
    USEDATNAR, KONTAKT_TEL, KONTAKT_EMAIL,
    case when KONTAKT_TEL is not NULL then 'S'
         when KONTAKT_EMAIL is not null then 'E'
         else NULL end as NOTIFIKACE,
    coalesce(KONTAKT_TEL, KONTAKT_EMAIL) as NOTIFIKACE_KONTAKT
FROM NES
WHERE IDPAC = ?
ORDER BY DATNES ASC, ID ASC
```

### 2. Formuláře eNeschopenky pro vybranou PN (záložka "Formuláře eNeschopenky")

Zobrazuje pouze TYP `H`, `1`, `2` (ne `P` = propuštění).
Pouze záznamy s vazbou na HISTDOC (`IDHISTDOC IS NOT NULL`).

```sql
SELECT
    HD.ID       AS HISTDOCID,
    H.TYP       AS HISTDOCTYP,   -- H=hlášení, 1=první zpráva, 2=průběžná/potvrzení
    HD.DATUM    AS DATZAD,        -- Datum vystavení (z HISTDOC)
    H.DATUM     AS DATPOD,        -- Datum podání (z HPN)
    H.STAV,
    H.ODBAVENO,
    HD.TYP
FROM HPN H
JOIN HISTDOC HD ON H.IDHISTDOC = HD.ID
WHERE H.IDNES = ?
ORDER BY HD.DATUM ASC
```

### 3. Rychlý přehled formulářů (bez HISTDOC)

Používá se pro zjištění stavu – vrací všechny záznamy TYP `H`, `1`, `2`:

```sql
SELECT * FROM HPN
WHERE IDNES = ?
  AND STORNO = 'F'
  AND TYP IN ('1', '2', 'H')
ORDER BY DATUM DESC, CAS DESC, ID DESC
```

### 4. TFHpnHistorie – formulář "Historie HPN" (acHpnHistorie)

Kompletní přehled všech HPN záznamů pro vybranou PN. Spouští se akcí `acHpnHistorie`.

```sql
select h.ID, h.IDNES, h.IDPODANI, h.TYP, h.DATA, h.DATUM, h.CAS, h.ODPOVED,
  h.IDPRAC, h.IDUZI, h.UPRAVENO, h.OPRAVA_ID, h.STAV, h.STORNO,
  h.POR_CISLO, h.ID_CHYBY, h.OSSZ,
  n.CisNes, n.Ecn, coalesce(n.CisNes, n.Ecn) as Cislo, n.IdPac,
  k.Prijmeni, k.Jmeno, k.Titul, coalesce(n.RODCISNES, k.RODCIS) as RODCIS,
  u.Zkratka, hp.Odeslano, hp.CorelationId,
  (select first 1 h2.ID from HPN h2 where h2.OPRAVA_ID = h.ID) as IdOpravy,
  h.verze_dpn,
  n.SPRAVCE_POJ,
  n.ADRESA as ULICE, n.ADR_CP, n.ADR_CO, n.ADR_DOD, n.ADR_OBEC, n.ADR_PSC, n.ADR_STAT,
  n.PODNIK, n.PROFES, n.ZAM_ADRESA, n.ZAM_CP, n.ZAM_CO, n.ZAM_OBEC, n.ZAM_PSC, n.ZAM_STAT,
  n.ZACNES, n.DIAGNO, n.DATNES, n.PRICINA,
  n.KONNES, n.KONDIA, n.DATUKONNES,
  n.DATVYCHOD, n.VYCH1OD, n.VYCH1DO, n.VYCH2OD, n.VYCH2DO,
  n.PRICINA, n.ICPE, n.VYCH3OD, n.VYCH3DO, n.KONTAKT_TEL,
  h.IDHISTDOC, h.ODBAVENO,
  IIF((H.IDHISTDOC is not null),
      (select HD.TYP from HISTDOC HD where HD.ID = H.IDHISTDOC), null) as HISTDOCTYP
from HPN h
  left join NES n on (n.id = h.idnes)
  left join KAR k on (k.IdPac = n.IdPac)
  left join UZIVATEL u on (u.IdUzi = h.IdUzi)
  left join HPN_PODANI hp on (hp.ID = h.IdPodani)
where h.IdNes = ?
ORDER BY h.Datum ASC, h.Cas ASC, h.Id ASC
```

### 5. Kontrola čekajících podání (PN s neodeslanými HPN záznamy)

```sql
select nes.id from nes
where nes.idpac = ?
  and nes.storno = 'F'
  and nes.epodani = 'T'
  and nes.icpe = ?
  and coalesce(nes.verze_dpn, '') not in ('', 'p', 'o')
  and exists (
      select 1 from hpn
      where hpn.idnes = nes.id
        and hpn.storno = 'F'
        and hpn.typ in ('1', '2', 'H')
        and hpn.idpodani is null   -- dosud neodesláno
        and hpn.stav <> 99
        and hpn.stav <> 10
  )
```

### 6. Kontrola potvrzení vydaného tento měsíc (POTVRZENI_VYDANO)

Medicus kontroluje zda pro daného pacienta existuje PN aktivní alespoň 10 dní,
u které ještě nebylo vydáno potvrzení v aktuálním měsíci:

```sql
select first 1 ZACNES, CISNES, ID, POTVRZENI_VYDANO
from NES
where (IDPAC = ?)
  and (? >= ZACNES + 10)         -- PN trvá alespoň 10 dní
  and ((KONNES is NULL) or (KONNES > ?))
  and (STORNO = 'F')
  and (
      extract(month from POTVRZENI_VYDANO) || extract(year from POTVRZENI_VYDANO)
      =
      extract(month from cast(? as date)) || extract(year from cast(? as date))
  )
```

### 7. Vyhledání HPN záznamu podle ICPE v XML datech

Číslo `11031812` (ICPE lékaře) se hledá přímo v obsahu XML blobu `HPN.DATA`.
Medicus takto identifikuje konkrétní HPN záznam při opravě nebo ověření stavu:

```sql
-- Neodeslané nebo čekající záznamy:
select h.id from HPN h
left join HPN h2 on (h2.OPRAVA_ID = h.ID)
where (h.storno = 'F')
  and ((h.stav in (0,1)) or (h.stav is NULL))
  and (h2.OPRAVA_ID is null)
  and (H.DATA containing '11031812')   -- hledá ICPE v XML obsahu
  and (h.IDNES = ?)

-- Úspěšně odeslané záznamy (stav=1):
select h.id from HPN h
left join HPN h2 on (h2.OPRAVA_ID = h.ID)
where (h.storno = 'F')
  and (h.stav = 1)
  and h2.OPRAVA_ID is null
  and (H.DATA containing '11031812')
  and h.IDNES = ?
```

### 8. Předání/Převzetí (záložka "Předání/Převzetí")

```sql
SELECT ID, IDNES, KAMODKUD, DATUM, KAM, ICZ, ICPE, ICO, JMENO_LEKARE
FROM NESD
WHERE IDNES = ?
ORDER BY DATUM ASC, ID ASC
```

### Poznámky

- **HISTDOC** – každé odeslání formuláře vytváří záznam v HISTDOC; HPN bez IDHISTDOC se v UI nezobrazí
- **HPN.STAV** – stav podání (1 = odesláno/přijato)
- **HPN.ODBAVENO** – příznak zpracování (`'F'` = ne, `'T'` = ano)
- HPN záznamy TYP='2' (průběžná potvrzení) **nemají IDHISTDOC** – JOIN s HISTDOC by je odfiltroval. Pro datum posledního potvrzení v reportu proto používáme prostý MAX bez JOINu. HISTDOC mají pouze TYP='P' (ukončení PN).

---

## Vazby tabulky NES (zjištěno z DB)

### Formální FK constrainty

| Směr | Vazba | Popis |
|---|---|---|
| NES → KAR | `NES.IDPAC → KAR.IDPAC` | Každá neschopenka patří pacientovi v kartotéce |
| HPN → NES | `HPN.IDNES → NES.ID` | Formuláře/hlášení HPN odkazují na konkrétní neschopenku |

### Logické vazby (bez FK constraintu)

| Tabulka | Pole | Poznámka |
|---|---|---|
| NESD | `NESD.IDNES → NES.ID` | Předání/převzetí PN – vazba jen kódem, ne constraintem |
| HISTDOC | `HPN.IDHISTDOC → HISTDOC.ID` | Dokumenty k formulářům – vazba přes HPN |

### Indexy na NES

| Index | Unique | Pole |
|---|---|---|
| PK_NES | Ano | ID |
| FK_NES_KAR | Ne | IDPAC |
| NES_POTVRZENI_VYDANO | Ne | POTVRZENI_VYDANO |

### Poznámka

Medicus obecně používá minimum DB constraintů – většina vazeb je řešena aplikačním kódem.
`NESD` a `HISTDOC` nemají formální FK na `NES`, přesto jsou klíčové pro zobrazení PN v UI.

---

## Červené zvýraznění

Sloupce "Posl. potvrzení" a "Dní od potvr." jsou červeně zvýrazněny pokud:
- Od posledního potvrzení uplynulo více než 14 dní, nebo
- PN nemá žádné potvrzení a trvá déle než 14 dní (zobrazí se s `(!)`)

## Tisk

Skript používá `win32api.ShellExecute` s příkazem `'print'` – odešle PDF
na výchozí tiskárnu Windows.

## Automatizace

Plánované spouštění každé pondělí a pátek ráno přes Windows Task Scheduler
– zatím nenastaveno, připravit až bude skript stabilní.

## Soubory

| Soubor | Obsah |
|---|---|
| `pn_report.py` | Hlavní skript – DB dotaz, generování PDF, tisk |
| `PN.md` | Tento soubor – dokumentace |
