Files
KPK/closing_report.py
T
2026-06-23 15:20:56 +02:00

232 lines
6.1 KiB
Python

import json
from collections import defaultdict
import sqlite3
import json
from collections import defaultdict
from data import (
ClosureInterval,
ClosureSummary,
ClosureUser,
ClosureVAT,
ClosureReportOut,
)
def compute_closure_report(conn,
table_ucty: str,
table_clsrep: str | None=None,
ucislo_st: str | None=None,
ucislo_end: str | None=None,
id_kas: str="") -> ClosureReportOut | None:
if not table_clsrep:
table_clsrep = table_ucty.replace("_ucty", "_clsrep")
cur = conn.cursor()
# =====================================================
# 1️⃣ URČENÍ STARTU
# =====================================================
if not ucislo_st:
# zjisti poslední uzávěrku
cur.execute(f"""
SELECT ucislo_end
FROM "{table_clsrep}"
WHERE id_kas=?
ORDER BY clsrep_id DESC
LIMIT 1
""", (id_kas,))
row = cur.fetchone()
if row and row[0]:
# další účet po poslední uzávěrce
ucislo_st = row[0]
else:
# žádná uzávěrka → vezmi první existující účet
cur.execute(f"""
SELECT MIN(ucislo)
FROM "{table_ucty}"
WHERE id_kas=?
AND closed_at IS NOT NULL
AND TRIM(ucislo) != ''
""", (id_kas,))
row = cur.fetchone()
ucislo_st = row[0] if row else None
# =====================================================
# 2️⃣ URČENÍ KONCE
# =====================================================
if not ucislo_end:
cur.execute(f"""
SELECT MAX(ucislo)
FROM "{table_ucty}"
WHERE id_kas=?
AND closed_at IS NOT NULL
AND TRIM(ucislo) != ''
""", (id_kas,))
row = cur.fetchone()
ucislo_end = row[0] if row else None
if not ucislo_st or not ucislo_end:
return None
# =====================================================
# 3️⃣ NAČTENÍ ÚČTŮ
# =====================================================
cur.execute(f"""
SELECT ucislo, closed_at, data
FROM "{table_ucty}"
WHERE id_kas=?
AND closed_at IS NOT NULL
AND TRIM(ucislo) != ''
AND ucislo>=?
AND ucislo<=?
ORDER BY ucislo
""", (id_kas, ucislo_st, ucislo_end))
rows = cur.fetchall()
if not rows:
return None
# --- interval ---
ucislo_first, closed_first, _ = rows[0]
ucislo_last, closed_last, _ = rows[-1]
# =====================================================
# 4️⃣ AGREGACE (stejná jako předtím)
# =====================================================
by_payment = defaultdict(float)
by_user_total = defaultdict(float)
by_user_cash = defaultdict(float)
by_vat = defaultdict(lambda: {"zaklad": 0.0, "dan": 0.0})
total_base = 0.0
total_payments = 0.0
count = 0
for ucislo, closed_at, data_json in rows:
if not data_json:
continue
try:
u = json.loads(data_json)
except Exception:
continue
if not u.get("ucislo"):
continue
count += 1
autor = u.get("autor") or "UNKNOWN"
base_val = u.get("total_base_currency") or 0.0
total_base += base_val
by_user_total[autor] += base_val
for p in u.get("platby", []) or []:
code = p.get("code") or "UNKNOWN"
suma = p.get("suma_czk") or 0.0
by_payment[code] += suma
total_payments += suma
if code == "CASH":
by_user_cash[autor] += suma
for d in u.get("dane", []) or []:
rate = str(d.get("rate"))
zaklad = d.get("zaklad") or 0.0
try:
r = float(rate)
dan = zaklad * (r - 1)
except Exception:
dan = 0.0
by_vat[rate]["zaklad"] += zaklad
by_vat[rate]["dan"] += dan
# =====================================================
# 5️⃣ SLOŽENÍ MODELU
# =====================================================
interval = ClosureInterval(
ucislo_od=ucislo_first,
ucislo_do=ucislo_last,
closed_at_od=closed_first,
closed_at_do=closed_last,
)
summary = ClosureSummary(
pocet_uctu=count,
total_base_currency=round(total_base, 2),
total_payments=round(total_payments, 2),
difference=round(total_base - total_payments, 2),
)
users = {
user: ClosureUser(
total_base_currency=round(by_user_total[user], 2),
hotovost=round(by_user_cash[user], 2),
)
for user in by_user_total
}
vat = {
rate: ClosureVAT(
zaklad=round(v["zaklad"], 2),
dan=round(v["dan"], 2),
celkem=round(v["zaklad"] + v["dan"], 2),
)
for rate, v in by_vat.items()
}
return ClosureReportOut(
blocked_by="",
clsrep_no=None,
created_at=None,
interval=interval,
summary=summary,
platby={k: round(v, 2) for k, v in by_payment.items()},
uzivatele=users,
dph=vat,
)
import sqlite3
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
import kivy_printer
class TestApp(App):
def build(self):
with sqlite3.connect("testVIII.db") as conn:
rep = compute_closure_report(
conn,
table_ucty="00001_ucty",
#table_clsrep="00001_clsrep",
#ucislo_st="01000435",
#ucislo_end="01000500",
id_kas="01"
)
if rep:
print(rep.model_dump_json(indent=4, ensure_ascii=False))
kivy_printer.show_clsrep_preview(rep.model_dump())
else:
print("Uzávěrka je prázdná.")
return BoxLayout() # dummy root
if __name__ == "__main__":
TestApp().run()