232 lines
6.1 KiB
Python
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() |