notebookvb
This commit is contained in:
@@ -2,18 +2,28 @@
|
|||||||
|
|
||||||
## Co skript dělá
|
## Co skript dělá
|
||||||
|
|
||||||
`PodejZadostSeznamZPS.py` podává žádost o výpis registrovaných pojištěnců ZPŠ
|
`PodejZadostSeznamZPS.py` provede v jednom spuštění tři kroky:
|
||||||
za jeden měsíc (poslední den daného měsíce). Bez prohlížeče, bez NMSigneru — čistý Python.
|
|
||||||
|
|
||||||
## Flow
|
1. **Přihlásí se** certifikátem na portál ZPŠ (čistý Python, bez NMSigneru)
|
||||||
|
— uloží cookies do sdíleného `StahováníZpráv/209 ZPŠ/zps_cookies.json`
|
||||||
|
|
||||||
1. **Přihlášení** — stejný certifikátový login jako ostatní ZPŠ skripty (`01_prihlaseni.py`):
|
2. **Stáhne nové výpisy pojištěnců** ze schránky `schranka-vypis-pojistencu-v-kapitaci`
|
||||||
- GET `/app/prihlaseni` → session cookie
|
— stahuje jen `.001` soubory, jejichž obsah začíná `H09305001`
|
||||||
- POST `/json-api/prihlaseni/prihlasovaci-zprava` → challenge (`zprava`)
|
— ukládá do `U:\Dropbox\Ordinace\Dokumentace_ke_zpracování\Zúčtovací zprávy\SeznamyPojištěnců\`
|
||||||
- Podpis challenge certifikátem (PKCS7/SHA-256, **s** certifikátem)
|
— zastaví se při první již stažené zprávě
|
||||||
- POST `/json-api/prihlaseni/prihlaseni-certifikatem` → autentizovaná session
|
— po stahování se **znovu přihlásí** (Playwright invaliduje předchozí requests session)
|
||||||
|
|
||||||
|
3. **Podá žádost** o výpis pro 1 následující měsíc (poslední den daného měsíce)
|
||||||
|
|
||||||
|
## Flow přihlášení
|
||||||
|
|
||||||
|
1. GET `/app/prihlaseni` → session cookie
|
||||||
|
2. POST `/json-api/prihlaseni/prihlasovaci-zprava` → challenge (`zprava`)
|
||||||
|
3. Podpis challenge certifikátem (PKCS7/SHA-256, **s** certifikátem)
|
||||||
|
4. POST `/json-api/prihlaseni/prihlaseni-certifikatem` → autentizovaná session
|
||||||
|
|
||||||
|
## Sestavení XML žádosti
|
||||||
|
|
||||||
2. **Sestavení XML žádosti**:
|
|
||||||
```xml
|
```xml
|
||||||
<SchrankaZadost NazevSchranky="VypisPojKap" NazevFiltru="ZZ_VYP_REG">
|
<SchrankaZadost NazevSchranky="VypisPojKap" NazevFiltru="ZZ_VYP_REG">
|
||||||
<PolozkaFiltru Nazev="icz">25520</PolozkaFiltru>
|
<PolozkaFiltru Nazev="icz">25520</PolozkaFiltru>
|
||||||
@@ -24,15 +34,17 @@ za jeden měsíc (poslední den daného měsíce). Bez prohlížeče, bez NMSign
|
|||||||
```
|
```
|
||||||
Konce řádků: `\r\n` (NMSigner normalizace)
|
Konce řádků: `\r\n` (NMSigner normalizace)
|
||||||
|
|
||||||
3. **Podpis XML** — PKCS7/SHA-256, **bez** certifikátu v podpisu (`NoCerts`):
|
## Podpis XML
|
||||||
|
|
||||||
|
PKCS7/SHA-256, **bez** certifikátu v podpisu (`NoCerts`):
|
||||||
- Server při odesílání formuláře zná certifikát z registrace
|
- Server při odesílání formuláře zná certifikát z registrace
|
||||||
- Certifikát v podpisu server odmítá ("Podepsaná data obsahují certifikát")
|
- Certifikát v podpisu server odmítá ("Podepsaná data obsahují certifikát")
|
||||||
- Rozdíl oproti přihlášení: login certifikát potřebuje, formulář ne
|
- Rozdíl oproti přihlášení: login certifikát potřebuje, formulář ne
|
||||||
|
|
||||||
4. **Odeslání**:
|
## Odeslání
|
||||||
- POST `https://portal.zpskoda.cz/json-api/formular-schranky/29-vypis-registrov-pojistencu/ulozit-formular`
|
|
||||||
- Body: `{"schrXml": "...", "schrSign": "-----BEGIN PKCS7-----...", "schrFiles": []}`
|
POST `https://portal.zpskoda.cz/json-api/formular-schranky/29-vypis-registrov-pojistencu/ulozit-formular`
|
||||||
- Odpověď obsahuje referenční číslo podání
|
Body: `{"schrXml": "...", "schrSign": "-----BEGIN PKCS7-----...", "schrFiles": []}`
|
||||||
|
|
||||||
## Klíčový objev
|
## Klíčový objev
|
||||||
|
|
||||||
@@ -45,13 +57,13 @@ Výsledek: žádný prohlížeč ani NMSigner není potřeba.
|
|||||||
|
|
||||||
| Soubor | Popis |
|
| Soubor | Popis |
|
||||||
|--------|-------|
|
|--------|-------|
|
||||||
| `PodejZadostSeznamZPS.py` | Hlavní skript — přihlášení + podání žádosti |
|
| `PodejZadostSeznamZPS.py` | Hlavní skript — stažení výpisů + podání žádosti |
|
||||||
| `stav.json` | Poslední úspěšně podaný měsíc `{"mesic": 4, "rok": 2026}` |
|
| `stav.json` | Poslední úspěšně podaný měsíc `{"mesic": 4, "rok": 2026}` |
|
||||||
| `log_podani.json` | Historie podání s referenčními čísly |
|
| `log_podani.json` | Historie podání s referenčními čísly |
|
||||||
|
|
||||||
## Parametry
|
## Parametry
|
||||||
|
|
||||||
- **IČZ**: 25520 (IČZ: 09305000, MUDr. Michaela Buzalková)
|
- **IČZ**: 25520 (IČP: 09305001, MUDr. Michaela Buzalková)
|
||||||
- **Certifikát**: `Insurance/Certificates/MBQualifiedCert.pfx`
|
- **Certifikát**: `Insurance/Certificates/MBQualifiedCert.pfx`
|
||||||
- **Typ výstupu**: `soubor` (Soubor dle datového rozhraní)
|
- **Typ výstupu**: `soubor` (Soubor dle datového rozhraní)
|
||||||
- **Řazení**: `jmeno` (příjmení a jména)
|
- **Řazení**: `jmeno` (příjmení a jména)
|
||||||
|
|||||||
@@ -2,12 +2,9 @@
|
|||||||
Podávání žádostí o výpis registrovaných pojištěnců ZPŠ — čistý Python, bez prohlížeče.
|
Podávání žádostí o výpis registrovaných pojištěnců ZPŠ — čistý Python, bez prohlížeče.
|
||||||
|
|
||||||
Co dělá:
|
Co dělá:
|
||||||
- Přihlásí se certifikátem na portál ZPŠ (requests + cryptography)
|
1. Přihlásí se certifikátem na portál ZPŠ (uloží cookies pro Playwright)
|
||||||
- Sestaví XML žádosti, podepíše certifikátem (PKCS7/SHA-256)
|
2. Stáhne nové soubory z výpisové schránky (schranka-vypis-pojistencu-v-kapitaci)
|
||||||
- Odešle POST na JSON API portálu
|
3. Podá žádost pro 1 následující měsíc
|
||||||
- Zjistí poslední podaný měsíc ze stavového souboru stav.json
|
|
||||||
- Podá žádost pro 1 následující měsíc (poslední den daného měsíce)
|
|
||||||
- Při úspěchu uloží nový stav a referenční číslo do logu
|
|
||||||
|
|
||||||
Stavový soubor: stav.json vedle tohoto skriptu.
|
Stavový soubor: stav.json vedle tohoto skriptu.
|
||||||
{"mesic": 2, "rok": 2025} — poslední úspěšně podaný měsíc
|
{"mesic": 2, "rok": 2025} — poslední úspěšně podaný měsíc
|
||||||
@@ -20,12 +17,17 @@ import json
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from cryptography.hazmat.primitives import hashes, serialization
|
from cryptography.hazmat.primitives import hashes, serialization
|
||||||
from cryptography.hazmat.primitives.serialization import pkcs7, pkcs12
|
from cryptography.hazmat.primitives.serialization import pkcs7, pkcs12
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..")))
|
||||||
|
from Knihovny.najdi_dropbox import get_dropbox_root
|
||||||
|
|
||||||
PFX_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "Certificates", "MBQualifiedCert.pfx"))
|
PFX_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "Certificates", "MBQualifiedCert.pfx"))
|
||||||
PFX_PASSWORD = b"Vlado7309208104++"
|
PFX_PASSWORD = b"Vlado7309208104++"
|
||||||
|
|
||||||
@@ -36,13 +38,23 @@ ICZ = "25520"
|
|||||||
STATE_FILE = os.path.join(os.path.dirname(__file__), "stav.json")
|
STATE_FILE = os.path.join(os.path.dirname(__file__), "stav.json")
|
||||||
LOG_FILE = os.path.join(os.path.dirname(__file__), "log_podani.json")
|
LOG_FILE = os.path.join(os.path.dirname(__file__), "log_podani.json")
|
||||||
|
|
||||||
|
# Sdílené soubory s ostatními ZPŠ skripty
|
||||||
|
STAHUJ_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "StahováníZpráv", "209 ZPŠ"))
|
||||||
|
COOKIES_FILE = os.path.join(STAHUJ_DIR, "zps_cookies.json")
|
||||||
|
CHROME_PROFILE = os.path.join(STAHUJ_DIR, "chrome_profile")
|
||||||
|
DOWNLOAD_DIR = os.path.join(get_dropbox_root(), "Ordinace", "Dokumentace_ke_zpracování", "Zúčtovací zprávy", "SeznamyPojištěnců")
|
||||||
|
|
||||||
|
VYPIS_URL = f"{BASE_URL}/app/schranka-vypis-pojistencu-v-kapitaci"
|
||||||
|
DOWNLOAD_URL = f"{BASE_URL}/html/prehled-zprav-ve-schrankach/zobrazit-prilohu"
|
||||||
|
PROTOKOL_URL = f"{BASE_URL}/html/prehled-zprav-ve-schrankach/zobrazit-protokol"
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Přihlášení
|
# Přihlášení
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
def prihlaseni() -> requests.Session:
|
def prihlaseni() -> requests.Session:
|
||||||
"""Přihlásí se certifikátem, vrátí autentizovanou session."""
|
"""Přihlásí se certifikátem, vrátí autentizovanou session. Uloží cookies pro Playwright."""
|
||||||
challenge_url = f"{BASE_URL}/json-api/prihlaseni/prihlasovaci-zprava"
|
challenge_url = f"{BASE_URL}/json-api/prihlaseni/prihlasovaci-zprava"
|
||||||
certlogin_url = f"{BASE_URL}/json-api/prihlaseni/prihlaseni-certifikatem"
|
certlogin_url = f"{BASE_URL}/json-api/prihlaseni/prihlaseni-certifikatem"
|
||||||
|
|
||||||
@@ -84,9 +96,198 @@ def prihlaseni() -> requests.Session:
|
|||||||
raise RuntimeError(f"Přihlášení selhalo: {r.json().get('errMsg', '')}")
|
raise RuntimeError(f"Přihlášení selhalo: {r.json().get('errMsg', '')}")
|
||||||
|
|
||||||
print("Přihlášení úspěšné!")
|
print("Přihlášení úspěšné!")
|
||||||
|
|
||||||
|
cookies = [
|
||||||
|
{
|
||||||
|
"name": c.name,
|
||||||
|
"value": c.value,
|
||||||
|
"domain": c.domain if c.domain.startswith(".") else "." + c.domain,
|
||||||
|
"path": c.path or "/",
|
||||||
|
"expires": int(c.expires) if c.expires else -1,
|
||||||
|
"secure": bool(c.secure),
|
||||||
|
"httpOnly": False,
|
||||||
|
"sameSite": "Lax",
|
||||||
|
}
|
||||||
|
for c in session.cookies
|
||||||
|
]
|
||||||
|
with open(COOKIES_FILE, "w", encoding="utf-8") as f:
|
||||||
|
json.dump(cookies, f, indent=2, ensure_ascii=False)
|
||||||
|
print(f"Cookies uloženy: {len(cookies)} → {COOKIES_FILE}")
|
||||||
|
|
||||||
return session
|
return session
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Stahování z výpisové schránky
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def safe_filename(name: str) -> str:
|
||||||
|
return re.sub(r'[\\/:*?"<>|]', "_", name).strip()
|
||||||
|
|
||||||
|
|
||||||
|
def parse_date(date_str: str) -> str:
|
||||||
|
try:
|
||||||
|
return datetime.strptime(date_str.strip()[:19], "%d.%m.%Y %H:%M:%S").strftime("%Y-%m-%d")
|
||||||
|
except Exception:
|
||||||
|
try:
|
||||||
|
return datetime.strptime(date_str.strip()[:10], "%d.%m.%Y").strftime("%Y-%m-%d")
|
||||||
|
except Exception:
|
||||||
|
return "0000-00-00"
|
||||||
|
|
||||||
|
|
||||||
|
def parse_row(cells: list) -> dict:
|
||||||
|
date_raw = cells[1].strip() if len(cells) > 1 else ""
|
||||||
|
desc_raw = cells[2].strip() if len(cells) > 2 else ""
|
||||||
|
fname_raw = cells[3].strip() if len(cells) > 3 else ""
|
||||||
|
|
||||||
|
desc_lines = [l.strip() for l in desc_raw.split("\n") if l.strip()]
|
||||||
|
if len(desc_lines) >= 3:
|
||||||
|
description = desc_lines[2]
|
||||||
|
elif len(desc_lines) >= 2:
|
||||||
|
description = desc_lines[1]
|
||||||
|
else:
|
||||||
|
description = desc_lines[0] if desc_lines else ""
|
||||||
|
description = description[:80]
|
||||||
|
|
||||||
|
fname_match = re.match(r'^(.+?)\s*\(\d{2}\.\d{2}\.\d{4}\)\s*$', fname_raw)
|
||||||
|
original = fname_match.group(1).strip() if fname_match else fname_raw.split("(")[0].strip()
|
||||||
|
orig_path = Path(original)
|
||||||
|
stem = orig_path.stem or "zprava"
|
||||||
|
ext = orig_path.suffix or ""
|
||||||
|
|
||||||
|
date_iso = parse_date(date_raw)
|
||||||
|
name = f"{date_iso} {safe_filename(description)} ({safe_filename(stem)}){ext}"
|
||||||
|
if len(name) > 240:
|
||||||
|
name = f"{date_iso} ({safe_filename(stem)}){ext}"
|
||||||
|
|
||||||
|
return {"date": date_iso, "desc": description, "original": original, "filename": name}
|
||||||
|
|
||||||
|
|
||||||
|
def stahni_nove_vypisy() -> int:
|
||||||
|
"""Stáhne nové soubory z výpisové schránky. Vrátí počet stažených souborů."""
|
||||||
|
try:
|
||||||
|
from playwright.sync_api import sync_playwright
|
||||||
|
except ImportError:
|
||||||
|
print("Chybí playwright: pip install playwright && playwright install chrome")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
os.makedirs(DOWNLOAD_DIR, exist_ok=True)
|
||||||
|
|
||||||
|
with open(COOKIES_FILE, encoding="utf-8") as f:
|
||||||
|
cookies = json.load(f)
|
||||||
|
|
||||||
|
downloaded = 0
|
||||||
|
|
||||||
|
with sync_playwright() as p:
|
||||||
|
context = p.chromium.launch_persistent_context(
|
||||||
|
user_data_dir=CHROME_PROFILE,
|
||||||
|
channel="chrome",
|
||||||
|
headless=False,
|
||||||
|
slow_mo=100,
|
||||||
|
ignore_https_errors=True,
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
context.add_cookies(cookies)
|
||||||
|
page = context.new_page()
|
||||||
|
|
||||||
|
page.goto(f"{VYPIS_URL}/", wait_until="domcontentloaded", timeout=30_000)
|
||||||
|
if "prihlaseni" in page.url or "login" in page.url.lower():
|
||||||
|
print("Session v prohlížeči expirovala — stahování přeskočeno")
|
||||||
|
return 0
|
||||||
|
print("Prohlížeč přihlášen OK\n")
|
||||||
|
|
||||||
|
already = set(os.listdir(DOWNLOAD_DIR))
|
||||||
|
print(f"V archivu: {len(already)} souborů.\n")
|
||||||
|
|
||||||
|
page_num = 1
|
||||||
|
seen_ids: set = set()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
url = f"{VYPIS_URL}/stranka-{page_num}"
|
||||||
|
print(f" Stránka {page_num}: {url}")
|
||||||
|
try:
|
||||||
|
page.goto(url, wait_until="domcontentloaded", timeout=30_000)
|
||||||
|
except Exception as e:
|
||||||
|
print(f" Navigace selhala: {e}")
|
||||||
|
break
|
||||||
|
page.wait_for_load_state("networkidle", timeout=15_000)
|
||||||
|
|
||||||
|
data = page.evaluate("""() => {
|
||||||
|
const rows = [];
|
||||||
|
for (const tr of document.querySelectorAll('table tr')) {
|
||||||
|
const cells = Array.from(tr.querySelectorAll('td')).map(td => td.innerText.trim());
|
||||||
|
if (cells.length < 4) continue;
|
||||||
|
const dlLink = tr.querySelector('a[onclick*="SchrPolOpenFile"]');
|
||||||
|
if (!dlLink) continue;
|
||||||
|
const mFile = dlLink.getAttribute('onclick').match(/\\d+/);
|
||||||
|
const protLink = tr.querySelector('a[onclick*="SchrPolDBProtokol"]');
|
||||||
|
const mProt = protLink ? protLink.getAttribute('onclick').match(/\\d+/) : null;
|
||||||
|
rows.push({
|
||||||
|
cells,
|
||||||
|
fileId: mFile ? mFile[0] : null,
|
||||||
|
protokolId: mProt ? mProt[0] : null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return rows;
|
||||||
|
}""")
|
||||||
|
rows = [r for r in data if r["fileId"]]
|
||||||
|
|
||||||
|
if not rows:
|
||||||
|
print(f" Stránka {page_num} — žádné řádky, konec schránky.")
|
||||||
|
break
|
||||||
|
|
||||||
|
current_ids = {r["fileId"] for r in rows}
|
||||||
|
if current_ids & seen_ids:
|
||||||
|
print(f" Stránka {page_num} — opakující se obsah, konec schránky.")
|
||||||
|
break
|
||||||
|
seen_ids.update(current_ids)
|
||||||
|
print(f" Nalezeno {len(rows)} zpráv.")
|
||||||
|
|
||||||
|
stop = False
|
||||||
|
for row in rows:
|
||||||
|
info = parse_row(row["cells"])
|
||||||
|
|
||||||
|
# Zajímají nás pouze .001 soubory
|
||||||
|
if Path(info["original"]).suffix.lower() != ".001":
|
||||||
|
continue
|
||||||
|
|
||||||
|
target = os.path.join(DOWNLOAD_DIR, info["filename"])
|
||||||
|
|
||||||
|
if info["filename"] in already or os.path.exists(target):
|
||||||
|
print(f" [stop] Nalezena již stažená zpráva: {info['filename']}")
|
||||||
|
stop = True
|
||||||
|
break
|
||||||
|
|
||||||
|
dl_url = f"{DOWNLOAD_URL}?zprava_id={row['fileId']}"
|
||||||
|
try:
|
||||||
|
r = context.request.get(dl_url, headers={"Referer": VYPIS_URL}, timeout=30_000)
|
||||||
|
if not r.ok:
|
||||||
|
print(f" HTTP {r.status} příloha (id={row['fileId']})")
|
||||||
|
else:
|
||||||
|
body = r.body()
|
||||||
|
if not body[:9].decode("ascii", errors="ignore").startswith("H09305001"):
|
||||||
|
print(f" přeskočeno (není výpis pojištěnců): {info['filename']}")
|
||||||
|
else:
|
||||||
|
with open(target, "wb") as fh:
|
||||||
|
fh.write(body)
|
||||||
|
print(f" OK: {info['filename']}")
|
||||||
|
already.add(info["filename"])
|
||||||
|
downloaded += 1
|
||||||
|
except Exception as e:
|
||||||
|
print(f" Chyba příloha (id={row['fileId']}): {e}")
|
||||||
|
time.sleep(1.0)
|
||||||
|
|
||||||
|
if stop:
|
||||||
|
break
|
||||||
|
|
||||||
|
page_num += 1
|
||||||
|
|
||||||
|
finally:
|
||||||
|
context.close()
|
||||||
|
|
||||||
|
return downloaded
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Sestavení XML a podpis
|
# Sestavení XML a podpis
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@@ -115,7 +316,6 @@ def sign_xml(xml: str) -> str:
|
|||||||
.sign(serialization.Encoding.PEM, [pkcs7.PKCS7Options.DetachedSignature, pkcs7.PKCS7Options.NoCerts])
|
.sign(serialization.Encoding.PEM, [pkcs7.PKCS7Options.DetachedSignature, pkcs7.PKCS7Options.NoCerts])
|
||||||
.decode("ascii")
|
.decode("ascii")
|
||||||
)
|
)
|
||||||
# NMSigner normalizuje konce řádků na \r\n
|
|
||||||
return pem.replace("\r\n", "\n").replace("\n", "\r\n")
|
return pem.replace("\r\n", "\n").replace("\n", "\r\n")
|
||||||
|
|
||||||
|
|
||||||
@@ -143,7 +343,6 @@ def odeslat_zadost(session: requests.Session, datum: date) -> str | None:
|
|||||||
print(f" Odpověď není JSON: {r.text[:300]}")
|
print(f" Odpověď není JSON: {r.text[:300]}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Hledáme referenční číslo v odpovědi
|
|
||||||
resp_str = json.dumps(resp, ensure_ascii=False)
|
resp_str = json.dumps(resp, ensure_ascii=False)
|
||||||
m = re.search(r'\b(17\d{7}|18\d{7})\b', resp_str)
|
m = re.search(r'\b(17\d{7}|18\d{7})\b', resp_str)
|
||||||
ref = m.group(1) if m else None
|
ref = m.group(1) if m else None
|
||||||
@@ -218,11 +417,23 @@ def hlavni() -> None:
|
|||||||
' {"mesic": 2, "rok": 2025}'
|
' {"mesic": 2, "rok": 2025}'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 1. Přihlášení — uloží cookies pro Playwright
|
||||||
|
prihlaseni()
|
||||||
|
|
||||||
|
# 2. Stažení nových výpisů z výpisové schránky
|
||||||
|
print("\n=== Stahování nových výpisů ===")
|
||||||
|
stazeno = stahni_nove_vypisy()
|
||||||
|
print(f"Staženo: {stazeno} souborů.\n")
|
||||||
|
|
||||||
|
# 3. Znovu přihlásit — Playwright mohl invalidovat předchozí session
|
||||||
|
print("=== Znovu přihlašuji před podáním ===")
|
||||||
|
session = prihlaseni()
|
||||||
|
|
||||||
|
# 4. Podání žádosti pro následující měsíc
|
||||||
mesic, rok = dalsi_mesic(*posledni)
|
mesic, rok = dalsi_mesic(*posledni)
|
||||||
datum = posledni_den(mesic, rok)
|
datum = posledni_den(mesic, rok)
|
||||||
print(f"Podávám žádost pro: {datum.strftime('%d.%m.%Y')}")
|
print(f"=== Podávám žádost pro: {datum.strftime('%d.%m.%Y')} ===")
|
||||||
|
|
||||||
session = prihlaseni()
|
|
||||||
ref = odeslat_zadost(session, datum)
|
ref = odeslat_zadost(session, datum)
|
||||||
|
|
||||||
if ref:
|
if ref:
|
||||||
|
|||||||
@@ -68,5 +68,10 @@
|
|||||||
"datum": "30.04.2026",
|
"datum": "30.04.2026",
|
||||||
"ref_cislo": "178201321",
|
"ref_cislo": "178201321",
|
||||||
"podano_kdy": "2026-05-12 21:59:31"
|
"podano_kdy": "2026-05-12 21:59:31"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datum": "31.05.2026",
|
||||||
|
"ref_cislo": "178213777",
|
||||||
|
"podano_kdy": "2026-05-13 07:09:12"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -1 +1 @@
|
|||||||
{"mesic": 4, "rok": 2026}
|
{"mesic": 5, "rok": 2026}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"name": "SID",
|
"name": "SID",
|
||||||
"value": "8be68e23c6afb14ff6937b6a8832001c",
|
"value": "cfdefd7ad7d093aeeadee6402dff0fa8",
|
||||||
"domain": ".portal.zpskoda.cz",
|
"domain": ".portal.zpskoda.cz",
|
||||||
"path": "/",
|
"path": "/",
|
||||||
"expires": -1,
|
"expires": -1,
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
"value": "CERT",
|
"value": "CERT",
|
||||||
"domain": ".portal.zpskoda.cz",
|
"domain": ".portal.zpskoda.cz",
|
||||||
"path": "/",
|
"path": "/",
|
||||||
"expires": 1808541904,
|
"expires": 1810184951,
|
||||||
"secure": true,
|
"secure": true,
|
||||||
"httpOnly": false,
|
"httpOnly": false,
|
||||||
"sameSite": "Lax"
|
"sameSite": "Lax"
|
||||||
|
|||||||
Reference in New Issue
Block a user