from __future__ import annotations import datetime as dt from typing import Dict, Any from flask import Blueprint, current_app, render_template, request, redirect, url_for, jsonify, flash from .clients.zammad import ZammadClient, ZammadError from .services import aggregations as agg web_bp = Blueprint("web", __name__) def _client() -> ZammadClient: return ZammadClient(current_app.config["ZAMMAD_URL"], current_app.config["ZAMMAD_TOKEN"]) @web_bp.route("/") def index(): return render_template( "index.html", default_date_from=current_app.config["DEFAULT_DATE_FROM"], default_date_to=current_app.config["DEFAULT_DATE_TO"], ) AVAILABLE_GROUPS: Dict[str, Dict[str, Any]] = { "overview": {"title": "Общее количество тикетов"}, "by_agent": {"title": "Тикеты по агентам"}, "by_group": {"title": "Тикеты по группам"}, "by_state": {"title": "Тикеты по статусам"}, "open_closed": {"title": "Открытые vs Закрытые"}, "by_priority": {"title": "Тикеты по приоритетам"}, "by_day": {"title": "Динамика: тикеты по дням"}, } @web_bp.get("/report") def report(): date_from = request.args.get("date_from") date_to = request.args.get("date_to") group_by = request.args.get("group_by", "overview") if not date_from or not date_to: flash("Укажите период дат.", "warning") return redirect(url_for("web:index")) if group_by not in AVAILABLE_GROUPS: group_by = "overview" z = _client() try: tickets = z.search_tickets(date_from, date_to) except ZammadError as e: flash(f"Ошибка Zammad API: {e}", "danger") return redirect(url_for("web:index")) overview = agg.summarize_overview(tickets, z) # Determine main chart if group_by == "by_agent": data = agg.by_agent(tickets, z) elif group_by == "by_group": data = agg.by_group(tickets, z) elif group_by == "by_state": data = agg.by_state(tickets, z) elif group_by == "open_closed": data = agg.by_open_closed(tickets, z) elif group_by == "by_priority": data = agg.by_priority(tickets, z) elif group_by == "by_day": data = agg.by_day_created(tickets) else: data = {"Всего": overview["total"]} labels, values = agg.dict_to_series(data) title = AVAILABLE_GROUPS[group_by]["title"] # Supplemental tables by_agent = sorted(agg.by_agent(tickets, z).items(), key=lambda x: x[1], reverse=True) by_group = sorted(agg.by_group(tickets, z).items(), key=lambda x: x[1], reverse=True) return render_template( "report.html", date_from=date_from, date_to=date_to, group_by=group_by, title=title, chart_labels=labels, chart_values=values, overview=overview, by_agent=by_agent, by_group=by_group, ) @web_bp.get("/api/report.json") def report_json(): date_from = request.args.get("date_from") date_to = request.args.get("date_to") group_by = request.args.get("group_by", "overview") if not date_from or not date_to: return jsonify({"error": "date_from and date_to are required"}), 400 z = _client() tickets = z.search_tickets(date_from, date_to) overview = agg.summarize_overview(tickets, z) payload: Dict[str, Any] = {"overview": overview} payload.update( { "by_agent": agg.by_agent(tickets, z), "by_group": agg.by_group(tickets, z), "by_state": agg.by_state(tickets, z), "open_closed": agg.by_open_closed(tickets, z), "by_priority": agg.by_priority(tickets, z), "by_day": agg.by_day_created(tickets), } ) # Optional: main_group result if group_by in payload: labels, values = agg.dict_to_series(payload[group_by]) payload["chart"] = {"labels": labels, "values": values} return jsonify(payload)