notebook vb
This commit is contained in:
81
MedicusWithClaudeSelects/SELECTS.md
Normal file
81
MedicusWithClaudeSelects/SELECTS.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# MedicusWithClaudeSelects – SQL dotazy
|
||||
|
||||
## Registrovaní pacienti
|
||||
|
||||
Přesný select který Medicus používá pro záložku **Registrovaní** (zachycen přes FBScanner, dotaz č. 143).
|
||||
|
||||
### Počet registrovaných pacientů
|
||||
|
||||
```sql
|
||||
SELECT COUNT(*) FROM KAR
|
||||
WHERE (vyrazen = 'N')
|
||||
AND EXISTS (
|
||||
SELECT id FROM registr r
|
||||
JOIN icp i ON r.idicp = i.idicp
|
||||
WHERE r.idpac = kar.idpac
|
||||
AND (r.datum <= '2026-03-20')
|
||||
AND (r.datum_zruseni IS NULL OR r.datum_zruseni >= '2026-03-20')
|
||||
AND (r.priznak IN ('V','D','A'))
|
||||
AND (i.icp = '09305001')
|
||||
AND (i.odb = '001')
|
||||
)
|
||||
```
|
||||
|
||||
Vrátí: **1618 pacientů** (ověřit na Windows).
|
||||
|
||||
### Podmínky registrace – vysvětlení
|
||||
|
||||
- `vyrazen = 'N'` – pacient není vyřazen z kartotéky
|
||||
- `r.datum <= dnes` – registrace již začala
|
||||
- `r.datum_zruseni IS NULL OR r.datum_zruseni >= dnes` – registrace dosud platí
|
||||
- `r.priznak IN ('V','D','A')` – aktivní příznak (ne 'Z' = zrušen, ne 'N')
|
||||
- `i.icp = '09305001'` – IČP naší ordinace
|
||||
- `i.odb = '001'` – odbornost praktický lékař
|
||||
|
||||
### Skript pro Python
|
||||
|
||||
Viz `count_registrovani.py` v této složce – spustit na Windows.
|
||||
|
||||
### Plný select Medicusu (seznam pacientů s metadaty)
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
KAR.DATNAR,
|
||||
KAR.IDPAC,
|
||||
KAR.INFORMACE,
|
||||
KAR.INFORMACE_COL,
|
||||
KAR.JMENO,
|
||||
KAR.POHLAVI,
|
||||
GPP.POJ,
|
||||
KAR.POZNAMKA,
|
||||
KAR.PRIJMENI,
|
||||
KAR.PRIJMENI_UP,
|
||||
(SELECT DATUM_REGISTRACE FROM SP_GETREGDAT(kar.IDPAC)) AS REGDATUM,
|
||||
KAR.REGISTROVAL,
|
||||
(SELECT PRIZNAK FROM SP_GETREGDAT(kar.IDPAC)) AS REGPRIZNAK,
|
||||
KAR.RODCIS,
|
||||
KAR.ROZENA,
|
||||
KAR.TITUL,
|
||||
KAR.TITULZA,
|
||||
KAR.TRVOBEC,
|
||||
KAR.TRVPSC,
|
||||
KAR.TRVULICE,
|
||||
KAR.VYRAZEN
|
||||
FROM KAR
|
||||
LEFT JOIN GETPACPOJ(KAR.IDPAC, '2026-03-20') GPP ON GPP.IDPAC = KAR.IDPAC
|
||||
WHERE (vyrazen = 'N')
|
||||
AND EXISTS (
|
||||
SELECT id FROM registr r
|
||||
JOIN icp i ON r.idicp = i.idicp
|
||||
WHERE r.idpac = kar.idpac
|
||||
AND (r.datum <= '2026-03-20')
|
||||
AND (r.datum_zruseni IS NULL OR r.datum_zruseni >= '2026-03-20')
|
||||
AND (r.priznak IN ('V','D','A'))
|
||||
AND (i.icp = '09305001')
|
||||
AND (i.odb = '001')
|
||||
)
|
||||
ORDER BY KAR.PRIJMENI_UP ASC, KAR.RODCIS ASC
|
||||
```
|
||||
|
||||
Poznámka: `GETPACPOJ` a `SP_GETREGDAT` jsou uložené procedury Medicusu –
|
||||
fungují v kontextu Firebird připojení přes SYSDBA/masterkey.
|
||||
27
MedicusWithClaudeSelects/count_registrovani.py
Normal file
27
MedicusWithClaudeSelects/count_registrovani.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import fdb, datetime
|
||||
|
||||
conn = fdb.connect(
|
||||
dsn=r'localhost:c:\medicus 3\data\medicus.fdb',
|
||||
user='SYSDBA', password='masterkey', charset='win1250')
|
||||
|
||||
cur = conn.cursor()
|
||||
dnes = datetime.date.today().isoformat()
|
||||
|
||||
cur.execute("""
|
||||
SELECT COUNT(*) FROM KAR
|
||||
WHERE (vyrazen = 'N')
|
||||
AND EXISTS (
|
||||
SELECT id FROM registr r
|
||||
JOIN icp i ON r.idicp = i.idicp
|
||||
WHERE r.idpac = kar.idpac
|
||||
AND (r.datum <= ?)
|
||||
AND (r.datum_zruseni IS NULL OR r.datum_zruseni >= ?)
|
||||
AND (r.priznak IN ('V','D','A'))
|
||||
AND (i.icp = '09305001')
|
||||
AND (i.odb = '001')
|
||||
)
|
||||
""", (dnes, dnes))
|
||||
|
||||
pocet = cur.fetchone()[0]
|
||||
print(f'Registrovaných pacientů: {pocet}')
|
||||
conn.close()
|
||||
78
MedicusWithClaudeSelects/db_bridge_vm.py
Normal file
78
MedicusWithClaudeSelects/db_bridge_vm.py
Normal file
@@ -0,0 +1,78 @@
|
||||
"""db_bridge_vm.py – VM strana souborového mostu k Medicusu.
|
||||
|
||||
Použití z Linuxu:
|
||||
from db_bridge_vm import query
|
||||
rows, columns = query("SELECT COUNT(*) FROM KAR")
|
||||
print(columns, rows)
|
||||
"""
|
||||
import json, time, os, uuid
|
||||
|
||||
BRIDGE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
REQUEST = os.path.join(BRIDGE_DIR, 'query_request.json')
|
||||
RESPONSE = os.path.join(BRIDGE_DIR, 'query_response.json')
|
||||
|
||||
TIMEOUT_SEC = 30
|
||||
POLL_SEC = 0.3
|
||||
|
||||
|
||||
def query(sql, params=None, timeout=TIMEOUT_SEC):
|
||||
"""Pošle SQL dotaz přes souborový most a vrátí (rows, columns).
|
||||
|
||||
Raises:
|
||||
TimeoutError – watchdog neodpověděl do timeout sekund
|
||||
RuntimeError – Firebird vrátil chybu
|
||||
"""
|
||||
# Smaž případnou starou response
|
||||
if os.path.exists(RESPONSE):
|
||||
os.remove(RESPONSE)
|
||||
|
||||
req_id = uuid.uuid4().hex
|
||||
req = {'id': req_id, 'sql': sql, 'params': params or []}
|
||||
|
||||
with open(REQUEST, 'w', encoding='utf-8') as f:
|
||||
json.dump(req, f, ensure_ascii=False)
|
||||
|
||||
# Čekej na odpověď
|
||||
waited = 0.0
|
||||
while waited < timeout:
|
||||
time.sleep(POLL_SEC)
|
||||
waited += POLL_SEC
|
||||
if os.path.exists(RESPONSE):
|
||||
with open(RESPONSE, 'r', encoding='utf-8') as f:
|
||||
resp = json.load(f)
|
||||
os.remove(RESPONSE)
|
||||
if resp.get('status') == 'error':
|
||||
raise RuntimeError(f"DB chyba: {resp.get('error')}")
|
||||
return resp.get('rows', []), resp.get('columns', [])
|
||||
|
||||
# Timeout – smaž request aby watchdog nezpracoval zastaralý dotaz
|
||||
if os.path.exists(REQUEST):
|
||||
os.remove(REQUEST)
|
||||
raise TimeoutError(f'Watchdog neodpověděl do {timeout}s – běží db_bridge_windows.py?')
|
||||
|
||||
|
||||
def query_print(sql, params=None):
|
||||
"""Spustí dotaz a vypíše výsledek přehledně."""
|
||||
rows, cols = query(sql, params)
|
||||
if not cols:
|
||||
print('(žádné sloupce)')
|
||||
return rows, cols
|
||||
col_w = [max(len(str(c)), max((len(str(r[i])) for r in rows), default=0))
|
||||
for i, c in enumerate(cols)]
|
||||
sep = '+' + '+'.join('-' * (w + 2) for w in col_w) + '+'
|
||||
fmt = '|' + '|'.join(f' {{:<{w}}} ' for w in col_w) + '|'
|
||||
print(sep)
|
||||
print(fmt.format(*cols))
|
||||
print(sep)
|
||||
for row in rows:
|
||||
print(fmt.format(*[str(v) if v is not None else 'NULL' for v in row]))
|
||||
print(sep)
|
||||
print(f'{len(rows)} řádků')
|
||||
return rows, cols
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Rychlý test
|
||||
print('Testuji spojení...')
|
||||
rows, cols = query('SELECT COUNT(*) AS POCET FROM KAR')
|
||||
print(f'OK – pacientů v KAR: {rows[0][0]}')
|
||||
90
MedicusWithClaudeSelects/db_bridge_windows.py
Normal file
90
MedicusWithClaudeSelects/db_bridge_windows.py
Normal file
@@ -0,0 +1,90 @@
|
||||
"""db_bridge_windows.py – Windows watchdog pro dotazy z Linux VM.
|
||||
|
||||
Spusť jednou na Windows:
|
||||
python db_bridge_windows.py
|
||||
|
||||
Skript sleduje soubor query_request.json ve stejné složce.
|
||||
Jakmile ho najde, spustí SQL dotaz proti Medicusu a zapíše výsledek
|
||||
do query_response.json. Pak čeká na další dotaz.
|
||||
|
||||
Ukonči: Ctrl+C
|
||||
"""
|
||||
import fdb, json, time, os, traceback, datetime
|
||||
|
||||
# ── Konfigurace ───────────────────────────────────────────────────────────────
|
||||
DSN = r'localhost:c:\medicus 3\data\medicus.fdb'
|
||||
USER = 'SYSDBA'
|
||||
PASSWORD = 'masterkey'
|
||||
CHARSET = 'win1250'
|
||||
|
||||
BRIDGE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
REQUEST = os.path.join(BRIDGE_DIR, 'query_request.json')
|
||||
RESPONSE = os.path.join(BRIDGE_DIR, 'query_response.json')
|
||||
POLL_SEC = 0.5
|
||||
|
||||
# ── Pomocné funkce ────────────────────────────────────────────────────────────
|
||||
|
||||
def serialize(val):
|
||||
"""Převede Python hodnoty na JSON-serializovatelné typy."""
|
||||
if isinstance(val, (datetime.date, datetime.datetime)):
|
||||
return val.isoformat()
|
||||
if isinstance(val, datetime.time):
|
||||
return val.isoformat()
|
||||
if isinstance(val, bytes):
|
||||
return f'<bytes len={len(val)}>'
|
||||
return val
|
||||
|
||||
|
||||
def run_query(sql, params=None):
|
||||
conn = fdb.connect(dsn=DSN, user=USER, password=PASSWORD, charset=CHARSET)
|
||||
try:
|
||||
cur = conn.cursor()
|
||||
cur.execute(sql, params or [])
|
||||
columns = [d[0] for d in cur.description] if cur.description else []
|
||||
rows = [[serialize(v) for v in row] for row in cur.fetchall()]
|
||||
return {'status': 'ok', 'columns': columns, 'rows': rows, 'error': None}
|
||||
except Exception as e:
|
||||
return {'status': 'error', 'columns': [], 'rows': [], 'error': str(e)}
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
# ── Hlavní smyčka ─────────────────────────────────────────────────────────────
|
||||
print(f'DB Bridge spuštěn. Sleduju: {REQUEST}')
|
||||
print('Ukončení: Ctrl+C\n')
|
||||
|
||||
while True:
|
||||
try:
|
||||
if os.path.exists(REQUEST):
|
||||
print(f'[{datetime.datetime.now().strftime("%H:%M:%S")}] Přijat dotaz...')
|
||||
|
||||
with open(REQUEST, 'r', encoding='utf-8') as f:
|
||||
req = json.load(f)
|
||||
|
||||
os.remove(REQUEST)
|
||||
|
||||
sql = req.get('sql', '')
|
||||
params = req.get('params', [])
|
||||
req_id = req.get('id', '')
|
||||
|
||||
result = run_query(sql, params)
|
||||
result['id'] = req_id
|
||||
result['sql'] = sql
|
||||
|
||||
with open(RESPONSE, 'w', encoding='utf-8') as f:
|
||||
json.dump(result, f, ensure_ascii=False, indent=2)
|
||||
|
||||
if result['status'] == 'ok':
|
||||
print(f' → OK, {len(result["rows"])} řádků')
|
||||
else:
|
||||
print(f' → CHYBA: {result["error"]}')
|
||||
|
||||
time.sleep(POLL_SEC)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print('\nDB Bridge ukončen.')
|
||||
break
|
||||
except Exception as e:
|
||||
print(f'Neočekávaná chyba: {e}')
|
||||
traceback.print_exc()
|
||||
time.sleep(2)
|
||||
30
MedicusWithClaudeSelects/get_kar_sortby_idlist.py
Normal file
30
MedicusWithClaudeSelects/get_kar_sortby_idlist.py
Normal file
@@ -0,0 +1,30 @@
|
||||
"""get_kar_sortby_idlist.py – přečte definici stored procedure KAR_SORTBY_IDLIST z Firebirdu.
|
||||
Spustit na Windows.
|
||||
"""
|
||||
import fdb
|
||||
|
||||
conn = fdb.connect(
|
||||
dsn=r'localhost:c:\medicus 3\data\medicus.fdb',
|
||||
user='SYSDBA', password='masterkey', charset='win1250')
|
||||
|
||||
cur = conn.cursor()
|
||||
cur.execute("""
|
||||
SELECT RDB$PROCEDURE_SOURCE FROM RDB$PROCEDURES
|
||||
WHERE RDB$PROCEDURE_NAME = 'KAR_SORTBY_IDLIST'
|
||||
""")
|
||||
row = cur.fetchone()
|
||||
if row and row[0]:
|
||||
print(row[0])
|
||||
else:
|
||||
# Možná je to funkce (FUNCTION), ne procedure
|
||||
cur.execute("""
|
||||
SELECT RDB$FUNCTION_SOURCE FROM RDB$FUNCTIONS
|
||||
WHERE RDB$FUNCTION_NAME = 'KAR_SORTBY_IDLIST'
|
||||
""")
|
||||
row = cur.fetchone()
|
||||
if row and row[0]:
|
||||
print(row[0])
|
||||
else:
|
||||
print("Nenalezeno ani jako PROCEDURE ani jako FUNCTION.")
|
||||
|
||||
conn.close()
|
||||
2668
MedicusWithClaudeSelects/precti_log.txt
Normal file
2668
MedicusWithClaudeSelects/precti_log.txt
Normal file
File diff suppressed because one or more lines are too long
74
MedicusWithClaudeSelects/query_response.json
Normal file
74
MedicusWithClaudeSelects/query_response.json
Normal file
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"status": "ok",
|
||||
"columns": [
|
||||
"ID",
|
||||
"DATUM",
|
||||
"CAS",
|
||||
"UZIVATEL",
|
||||
"IDPAC",
|
||||
"TABULKA",
|
||||
"IDREC",
|
||||
"AKCE",
|
||||
"DETAIL"
|
||||
],
|
||||
"rows": [
|
||||
[
|
||||
2882053,
|
||||
"2026-03-20",
|
||||
"17:43:50.523000",
|
||||
"VBU ",
|
||||
3234,
|
||||
10000,
|
||||
3234,
|
||||
"V",
|
||||
null
|
||||
],
|
||||
[
|
||||
2882052,
|
||||
"2026-03-20",
|
||||
"17:43:46.435000",
|
||||
"VBU ",
|
||||
3234,
|
||||
10000,
|
||||
3234,
|
||||
"V",
|
||||
null
|
||||
],
|
||||
[
|
||||
2882051,
|
||||
"2026-03-20",
|
||||
"17:24:19.777000",
|
||||
"VBU ",
|
||||
4757,
|
||||
10000,
|
||||
4757,
|
||||
"V",
|
||||
null
|
||||
],
|
||||
[
|
||||
2882050,
|
||||
"2026-03-20",
|
||||
"17:24:15.866000",
|
||||
"VBU ",
|
||||
3234,
|
||||
10000,
|
||||
3234,
|
||||
"V",
|
||||
null
|
||||
],
|
||||
[
|
||||
2882049,
|
||||
"2026-03-20",
|
||||
"07:11:41.434000",
|
||||
"VBU ",
|
||||
4757,
|
||||
10000,
|
||||
4757,
|
||||
"V",
|
||||
null
|
||||
]
|
||||
],
|
||||
"error": null,
|
||||
"id": "11859d529a784bedb653030ba60131de",
|
||||
"sql": "SELECT FIRST 5 * FROM LOG ORDER BY ID DESC"
|
||||
}
|
||||
Reference in New Issue
Block a user