324 lines
13 KiB
Python
324 lines
13 KiB
Python
import os, shutil, fdb, time
|
||
import re, datetime, funkce, funkce_ext
|
||
|
||
# Connect to the Firebird database
|
||
conn = fdb.connect(
|
||
dsn=r'localhost:c:\medicus 3\data\medicus.fdb',
|
||
user='SYSDBA',
|
||
password="masterkey",
|
||
charset="win1250")
|
||
|
||
cesta = r"u:\NextcloudOrdinace\Dokumentace_ke_zpracování"
|
||
cestazpracovana = r"u:\NextcloudOrdinace\Dokumentace_zpracovaná"
|
||
|
||
# Konstanty pro detekci sekce Vložené přílohy (RTF kódování win1250)
|
||
PRILOHY_HEADER = r"Vlo\'9een\'e9 p\'f8\'edlohy:"
|
||
PRILOHY_CLOSING = r'\pard\s10\plain\cs15\f0\fs20 \par'
|
||
|
||
# ─── Helper funkce ────────────────────────────────────────────────────────────
|
||
|
||
def restore_files_for_import(retezec):
|
||
drop = r"u:\Dropbox\!!!Days\Downloads Z230\Dokumentace"
|
||
next = r"u:\NextcloudOrdinace\Dokumentace_ke_zpracování"
|
||
if not os.path.exists(drop):
|
||
print(f"The directory '{drop}' does not exist.")
|
||
return
|
||
for item in os.listdir(drop):
|
||
item_path = os.path.join(drop, item)
|
||
if os.path.isfile(item_path) or os.path.islink(item_path):
|
||
os.unlink(item_path)
|
||
print(f"Deleted file: {item_path}")
|
||
elif os.path.isdir(item_path):
|
||
shutil.rmtree(item_path)
|
||
print(f"Deleted directory: {item_path}")
|
||
for item in os.listdir(next):
|
||
item_path = os.path.join(next, item)
|
||
if os.path.isfile(item_path) and item_path.endswith(".pdf") and retezec in item_path:
|
||
shutil.copy(item_path, os.path.join(drop, item))
|
||
print(f"Copied file: {item_path}")
|
||
|
||
|
||
def kontrola_rc(rc, connection):
|
||
cur = connection.cursor()
|
||
cur.execute("select count(*),idpac from kar where rodcis=? group by idpac", (rc,))
|
||
row = cur.fetchone()
|
||
if row:
|
||
return row[1]
|
||
else:
|
||
return False
|
||
|
||
|
||
def kontrola_struktury(souborname, connection):
|
||
if souborname.endswith('.pdf'):
|
||
pattern = re.compile(r'(^\d{9,10}) (\d{4}-\d{2}-\d{2}) (\w+, \w.+?) \[(.+?)\] \[(.*?)\]')
|
||
match = pattern.search(souborname)
|
||
vpohode = True
|
||
if match and len(match.groups()) == 5:
|
||
datum = match.group(2)
|
||
try:
|
||
datetime.datetime.strptime(datum, "%Y-%m-%d").date()
|
||
except:
|
||
vpohode = False
|
||
return vpohode
|
||
cur = connection.cursor()
|
||
cur.execute("select count(*) from kar where rodcis=?", (match.group(1),))
|
||
row = cur.fetchone()[0]
|
||
if row != 1:
|
||
vpohode = False
|
||
return vpohode
|
||
else:
|
||
vpohode = False
|
||
return vpohode
|
||
else:
|
||
vpohode = False
|
||
return vpohode
|
||
return vpohode
|
||
|
||
|
||
def vrat_info_o_souboru(souborname, connection):
|
||
pattern = re.compile(r'(^\d{9,10}) (\d{4}-\d{2}-\d{2}) (\w+, \w.+?) \[(.+?)\] \[(.*?)\]')
|
||
match = pattern.search(souborname)
|
||
rc = match.group(1)
|
||
datum = datetime.datetime.strptime(match.group(2), "%Y-%m-%d").date()
|
||
jmeno = match.group(3)
|
||
prvnizavorka = match.group(4)
|
||
druhazavorka = match.group(5)
|
||
cur = connection.cursor()
|
||
cur.execute("select idpac from kar where rodcis=?", (rc,))
|
||
idpac = cur.fetchone()[0]
|
||
datumsouboru = datetime.datetime.fromtimestamp(os.path.getctime(os.path.join(cesta, souborname)))
|
||
return (rc, idpac, datum, jmeno, prvnizavorka, druhazavorka, souborname, datumsouboru)
|
||
|
||
|
||
def prejmenuj_chybny_soubor(souborname, cesta):
|
||
if souborname[0] != "♥":
|
||
soubornovy = "♥" + souborname
|
||
os.rename(os.path.join(cesta, souborname), os.path.join(cesta, soubornovy))
|
||
|
||
|
||
def najdi_posledni_dekurs_dnes(conn, idpac, datum_vlozeni):
|
||
"""Vrátí (id, rtf) posledního dekurzu pacienta pokud je z dnešního dne, jinak None."""
|
||
cur = conn.cursor()
|
||
cur.execute("""
|
||
SELECT FIRST 1 ID, DATUM, DEKURS FROM DEKURS
|
||
WHERE IDPAC = ?
|
||
ORDER BY ID DESC
|
||
""", (idpac,))
|
||
row = cur.fetchone()
|
||
if row is None:
|
||
return None
|
||
dekurs_id, dekurs_datum, dekurs_rtf = row
|
||
print(f" Poslední dekurs: ID={dekurs_id}, datum={dekurs_datum}")
|
||
if dekurs_datum == datum_vlozeni:
|
||
print(f" → dnešní den ({datum_vlozeni}) ✓")
|
||
return (dekurs_id, dekurs_rtf)
|
||
else:
|
||
print(f" → jiný den ({dekurs_datum} ≠ {datum_vlozeni}), vytvoříme nový")
|
||
return None
|
||
|
||
|
||
def ma_sekci_prilohy(rtf):
|
||
return PRILOHY_HEADER in rtf
|
||
|
||
|
||
def pridat_do_sekce_prilohy(rtf, bookmark_list, filenameforbookmark_list):
|
||
"""Přidá více souborů do EXISTUJÍCÍ sekce 'Vložené přílohy'.
|
||
|
||
Postup:
|
||
1. Spočítá počet Files: odkazů = N → nové indexy začínají od N
|
||
2. Vloží nové \\pard řádky před uzavírací prázdný řádek sekce
|
||
3. Přidá nové bookmarky na konec {\\info{\\bookmarks ...}}
|
||
"""
|
||
# 1. Počet existujících Files: odkazů
|
||
bkm_match = re.search(r'\{\\info\{\\bookmarks ([^}]*)\}\}', rtf)
|
||
if bkm_match:
|
||
bkm_entries = [e for e in bkm_match.group(1).split(';') if e.strip()]
|
||
n_files = sum(1 for e in bkm_entries if '"Files:' in e)
|
||
else:
|
||
n_files = 0
|
||
print(f" Počet existujících Files odkazů: {n_files}, přidávám {len(bookmark_list)} nových")
|
||
|
||
# 2. Vložit nové \pard řádky před PRILOHY_CLOSING
|
||
prilohy_pos = rtf.find(PRILOHY_HEADER)
|
||
closing_pos = rtf.find(PRILOHY_CLOSING, prilohy_pos)
|
||
if closing_pos == -1:
|
||
raise RuntimeError("Nenalezen uzavírací řádek sekce Vložené přílohy!")
|
||
|
||
new_pards = ''
|
||
for i, fname in enumerate(filenameforbookmark_list):
|
||
idx = n_files + i
|
||
new_pards += (r'\pard\s10{\*\bkmkstart ' + str(idx) + r'}'
|
||
r'\plain\cs32\f0\ul\fs20\cf1 ' + fname
|
||
+ r'{\*\bkmkend ' + str(idx) + r'}\par' + '\n')
|
||
|
||
rtf = rtf[:closing_pos] + new_pards + rtf[closing_pos:]
|
||
|
||
# 3. Přidat nové bookmarky na konec {\info{\bookmarks ...}}
|
||
def append_bookmarks(m):
|
||
entries = [e for e in m.group(1).split(';') if e.strip()]
|
||
entries.extend(bookmark_list)
|
||
return '{\\info{\\bookmarks ' + ';'.join(entries) + '}}'
|
||
|
||
rtf = re.sub(r'\{\\info\{\\bookmarks ([^}]*)\}\}', append_bookmarks, rtf)
|
||
return rtf
|
||
|
||
|
||
def merge_rtf_prepend(existing_rtf, new_bkm_list, new_body_pards, n_new):
|
||
"""Vloží novou sekci příloh na ZAČÁTEK stávajícího dekurzu (sekce tam ještě není)."""
|
||
rtf = existing_rtf
|
||
rtf = re.sub(r'\\bkmkstart (\d+)',
|
||
lambda m: '\\bkmkstart ' + str(int(m.group(1)) + n_new), rtf)
|
||
rtf = re.sub(r'\\bkmkend (\d+)',
|
||
lambda m: '\\bkmkend ' + str(int(m.group(1)) + n_new), rtf)
|
||
|
||
new_bkm_str = ';'.join(new_bkm_list)
|
||
|
||
def merge_bkm(m):
|
||
existing = m.group(1).strip()
|
||
combined = new_bkm_str + (';' + existing if existing else '')
|
||
return '{\\info{\\bookmarks ' + combined + '}}'
|
||
|
||
if re.search(r'\{\\info\{\\bookmarks', rtf):
|
||
rtf = re.sub(r'\{\\info\{\\bookmarks ([^}]*)\}\}', merge_bkm, rtf)
|
||
else:
|
||
rtf = re.sub(r'(\\deflang\d+)',
|
||
r'\1{\\info{\\bookmarks ' + new_bkm_str + '}}', rtf, count=1)
|
||
|
||
match = re.search(r'\\uc1\\pard', rtf)
|
||
if match:
|
||
pos = match.start()
|
||
rtf = rtf[:pos] + new_body_pards + '\n' + rtf[pos:]
|
||
return rtf
|
||
|
||
|
||
# Šablona RTF pro nový dekurs
|
||
RTF_TEMPLATE = r"""{\rtf1\ansi\ansicpg1250\uc1\deff0\deflang1029{\info{\bookmarks BOOKMARKNAMES}}{\fonttbl{\f0\fnil\fcharset238 Arial;}{\f5\fnil\fcharset238 Symbol;}}
|
||
{\colortbl ;\red0\green0\blue255;\red0\green128\blue0;\red0\green0\blue0;}
|
||
{\stylesheet{\s10\fi0\li0\ql\ri0\sb0\sa0 Vlevo;}{\*\cs15\f0\fs20 Norm\'e1ln\'ed;}{\*\cs20\f0\i\fs20 Z\'e1hlav\'ed;}{\*\cs32\f0\ul\fs20\cf1 Odkaz;}}
|
||
BOOKMARKSTEXT
|
||
\pard\s10\plain\cs15\f0\fs20 \par
|
||
}"""
|
||
|
||
# ─── Hlavní tělo skriptu ──────────────────────────────────────────────────────
|
||
|
||
info = []
|
||
for soubor in os.listdir(cesta):
|
||
if os.path.isfile(os.path.join(cesta, soubor)):
|
||
print(soubor)
|
||
if kontrola_struktury(soubor, conn):
|
||
info.append(vrat_info_o_souboru(soubor, conn))
|
||
else:
|
||
prejmenuj_chybny_soubor(soubor, cesta)
|
||
|
||
info = sorted(info, key=lambda x: (x[0], x[1]))
|
||
print(info)
|
||
|
||
skupiny = {}
|
||
for row in info:
|
||
skupiny[row[0]] = []
|
||
for row in info:
|
||
skupiny[row[0]].append(row)
|
||
|
||
for key in skupiny.keys():
|
||
print(f"\n{'='*60}")
|
||
print(f"RC: {key}, souborů: {len(skupiny[key])}")
|
||
|
||
cislo = 9
|
||
poradi = 0
|
||
bookmark_list = []
|
||
filenameforbookmark_list = []
|
||
bookmarks_body = ''
|
||
idpac = skupiny[key][0][1]
|
||
|
||
# ── Krok 1: vložit každý soubor do ext DB + přesunout do zpracovaných ────
|
||
for row in skupiny[key]:
|
||
fileid = funkce_ext.zapis_file_ext(
|
||
vstupconnection=conn, idpac=row[1],
|
||
cesta=cesta, souborname=row[6], prvnizavorka=row[4],
|
||
soubordate=row[2], souborfiledate=row[7], poznamka=row[5])
|
||
print(f" → FILES.ID = {fileid} ({row[6]})")
|
||
|
||
# Přesun souboru do zpracovaných
|
||
for attempt in range(3):
|
||
try:
|
||
dest = os.path.join(cestazpracovana, row[6])
|
||
if not os.path.exists(dest):
|
||
shutil.move(os.path.join(cesta, row[6]), dest)
|
||
else:
|
||
ts = datetime.datetime.now().strftime("%Y-%m-%d %H-%M-%S")
|
||
shutil.move(os.path.join(cesta, row[6]),
|
||
os.path.join(cestazpracovana, row[6][:-4] + " " + ts + ".pdf"))
|
||
print(" Přesun OK!")
|
||
break
|
||
except Exception as e:
|
||
print(f" Attempt {attempt + 1} failed: {e}")
|
||
if attempt < 2:
|
||
print(" Retrying in 5 seconds...")
|
||
time.sleep(5)
|
||
else:
|
||
print(" Max retries reached. Command failed.")
|
||
|
||
filenameforbookmark = row[2].strftime('%Y-%m-%d') + ' ' + row[4] + ': ' + row[5]
|
||
bookmark_list.append('"' + filenameforbookmark + '","Files:' + str(fileid) + '",' + str(cislo))
|
||
filenameforbookmark_list.append(filenameforbookmark)
|
||
cislo += 7
|
||
|
||
bookmarks_body += (r'\pard\s10{\*\bkmkstart ' + str(poradi) + r'}'
|
||
r'\plain\cs32\f0\ul\fs20\cf1 ' + filenameforbookmark
|
||
+ r'{\*\bkmkend ' + str(poradi) + r'}\par')
|
||
poradi += 1
|
||
|
||
# ── Krok 2: sestavit tělo nové sekce příloh ───────────────────────────────
|
||
new_body = (r'\uc1\pard\s10\plain\cs20\f0\i\fs20 Vlo\'9een\'e9 p\'f8\'edlohy:\par' + '\n'
|
||
+ bookmarks_body + '\n'
|
||
+ r'\pard\s10\plain\cs15\f0\fs20 \par')
|
||
|
||
# ── Krok 3: rozhodovací logika (3 případy) ────────────────────────────────
|
||
datumzapisu = datetime.datetime.now().date()
|
||
caszapisu = datetime.datetime.now().time()
|
||
cur = conn.cursor()
|
||
|
||
print(f"\n>>> Hledám poslední dekurs pro IDPAC={idpac}...")
|
||
existujici = najdi_posledni_dekurs_dnes(conn, idpac, datumzapisu)
|
||
|
||
if existujici:
|
||
dekurs_id, existing_rtf = existujici
|
||
|
||
if ma_sekci_prilohy(existing_rtf):
|
||
# Případ 1: dnešní dekurs má sekci příloh → přidáme soubory dovnitř
|
||
print(f"\n>>> Sekce 'Vložené přílohy' nalezena v DEKURS ID={dekurs_id}")
|
||
print(">>> Přidávám soubory DO existující sekce...")
|
||
merged_rtf = pridat_do_sekce_prilohy(existing_rtf, bookmark_list, filenameforbookmark_list)
|
||
else:
|
||
# Případ 2: dnešní dekurs existuje, ale sekci příloh nemá → prepend
|
||
print(f"\n>>> DEKURS ID={dekurs_id} nemá sekci příloh → vkládám sekci na začátek...")
|
||
merged_rtf = merge_rtf_prepend(existing_rtf, bookmark_list, new_body, len(skupiny[key]))
|
||
|
||
print("\n=== Výsledný RTF ===")
|
||
print(merged_rtf)
|
||
cur.execute("UPDATE DEKURS SET DEKURS = ? WHERE ID = ?", (merged_rtf, dekurs_id))
|
||
conn.commit()
|
||
print(f"\n>>> UPDATE DEKURS ID={dekurs_id} – hotovo!")
|
||
|
||
else:
|
||
# Případ 3: žádný dnešní dekurs → vytvoříme nový
|
||
print(f"\n>>> Žádný dekurs pro dnešek → vytvářím nový...")
|
||
bookmark_str = ';'.join(bookmark_list)
|
||
rtf = RTF_TEMPLATE.replace('BOOKMARKNAMES', bookmark_str)
|
||
rtf = rtf.replace('BOOKMARKSTEXT', new_body)
|
||
|
||
print("\n=== Výsledný RTF ===")
|
||
print(rtf)
|
||
|
||
dekursid = funkce.get_dekurs_id(conn)
|
||
cur.execute(
|
||
"INSERT INTO DEKURS (id, iduzi, idprac, idodd, idpac, datum, cas, dekurs)"
|
||
" VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
||
(dekursid, 6, 2, 2, idpac, datumzapisu, caszapisu, rtf)
|
||
)
|
||
conn.commit()
|
||
print(f"\n>>> Nový DEKURS ID={dekursid}")
|
||
|
||
print("\n=== HOTOVO ===")
|
||
conn.close()
|