feat(ui): modern theme, dark/light toggle, polished templates
This commit is contained in:
BIN
app/services/__pycache__/aggregations.cpython-310.pyc
Normal file
BIN
app/services/__pycache__/aggregations.cpython-310.pyc
Normal file
Binary file not shown.
77
app/services/aggregations.py
Normal file
77
app/services/aggregations.py
Normal file
@@ -0,0 +1,77 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime as dt
|
||||
from collections import Counter, defaultdict
|
||||
from typing import Any, Dict, Iterable, List, Tuple
|
||||
|
||||
from ..clients.zammad import ZammadClient
|
||||
|
||||
|
||||
def summarize_overview(tickets: List[Dict[str, Any]], z: ZammadClient) -> Dict[str, Any]:
|
||||
total = len(tickets)
|
||||
open_count = 0
|
||||
closed_count = 0
|
||||
for t in tickets:
|
||||
st = z.state(t.get("state_id"))
|
||||
stype = (st.get("state_type") or "").lower()
|
||||
if "close" in stype or stype == "closed":
|
||||
closed_count += 1
|
||||
else:
|
||||
open_count += 1
|
||||
return {"total": total, "open": open_count, "closed": closed_count}
|
||||
|
||||
|
||||
def by_agent(tickets: List[Dict[str, Any]], z: ZammadClient) -> Dict[str, int]:
|
||||
counts = Counter([t.get("owner_id") or 0 for t in tickets])
|
||||
return {z.user_name(uid if uid != 0 else None): c for uid, c in counts.items()}
|
||||
|
||||
|
||||
def by_group(tickets: List[Dict[str, Any]], z: ZammadClient) -> Dict[str, int]:
|
||||
counts = Counter([t.get("group_id") or 0 for t in tickets])
|
||||
return {z.group_name(gid if gid != 0 else None): c for gid, c in counts.items()}
|
||||
|
||||
|
||||
def by_state(tickets: List[Dict[str, Any]], z: ZammadClient) -> Dict[str, int]:
|
||||
counts: Dict[str, int] = {}
|
||||
for t in tickets:
|
||||
st = z.state(t.get("state_id"))
|
||||
name = st.get("name", "unknown")
|
||||
counts[name] = counts.get(name, 0) + 1
|
||||
return counts
|
||||
|
||||
|
||||
def by_open_closed(tickets: List[Dict[str, Any]], z: ZammadClient) -> Dict[str, int]:
|
||||
opened = 0
|
||||
closed = 0
|
||||
for t in tickets:
|
||||
st = z.state(t.get("state_id"))
|
||||
stype = (st.get("state_type") or "").lower()
|
||||
if "close" in stype or stype == "closed":
|
||||
closed += 1
|
||||
else:
|
||||
opened += 1
|
||||
return {"Открытые": opened, "Закрытые": closed}
|
||||
|
||||
|
||||
def by_priority(tickets: List[Dict[str, Any]], z: ZammadClient) -> Dict[str, int]:
|
||||
counts = Counter([t.get("priority_id") or 0 for t in tickets])
|
||||
return {z.priority_name(pid if pid != 0 else None): c for pid, c in counts.items()}
|
||||
|
||||
|
||||
def by_day_created(tickets: List[Dict[str, Any]]) -> Dict[str, int]:
|
||||
counts: Dict[str, int] = defaultdict(int)
|
||||
for t in tickets:
|
||||
created = t.get("created_at") or t.get("created")
|
||||
if not created:
|
||||
continue
|
||||
day = str(created)[:10]
|
||||
counts[day] += 1
|
||||
# sort by date
|
||||
return dict(sorted(counts.items(), key=lambda kv: kv[0]))
|
||||
|
||||
|
||||
def dict_to_series(d: Dict[str, int]) -> Tuple[List[str], List[int]]:
|
||||
labels = list(d.keys())
|
||||
values = list(d.values())
|
||||
return labels, values
|
||||
|
||||
Reference in New Issue
Block a user