agnes-the-ai-analyst/services/telegram_bot/test_report.py
Petr f2d3d156e3 Move standalone services from server/ to services/
Extract 4 self-contained services into services/ module:
- server/telegram_bot/ -> services/telegram_bot/
- server/ws_gateway/ -> services/ws_gateway/
- server/corporate_memory/ -> services/corporate_memory/
- server/session_collector.py -> services/session_collector/

Each service now has its own systemd/ directory with .service and .timer files.
deploy.sh updated to auto-discover service units from services/*/systemd/*.

server/ now contains only deployment infrastructure (deploy.sh, setup scripts,
bin/ management tools, sudoers, nginx config).

All imports updated: webapp/app.py, server/bin/ scripts, systemd ExecStart paths.
2026-03-09 12:54:30 +01:00

204 lines
6.4 KiB
Python

"""
Generate a sample report chart for /test command.
Creates a polished demo dashboard image with fake data
to showcase what notifications can look like.
"""
import os
import random
import tempfile
from datetime import datetime, timedelta
import numpy as np
# Brand colors
COLOR_PRIMARY = "#0073D1"
COLOR_DARK = "#1A253C"
COLOR_SUCCESS = "#10B77F"
COLOR_WARNING = "#F59F0A"
COLOR_ERROR = "#EA580C"
COLOR_BG = "#F5F7FA"
COLOR_SURFACE = "#FFFFFF"
COLOR_GRAY = "#6B7280"
def generate_test_report(username: str) -> tuple[str, str]:
"""Generate a test report image and return (image_path, caption).
Creates a professional-looking dashboard with:
- Revenue trend line (7 days)
- KPI summary bar
- Top metrics breakdown
"""
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.patches import FancyBboxPatch
rng = random.Random(42)
# Generate fake data - 14 days of revenue
today = datetime.now()
dates = [today - timedelta(days=i) for i in range(13, -1, -1)]
base_revenue = 52000
revenues = [
base_revenue + rng.gauss(0, 5000) + i * 300
for i, _ in enumerate(dates)
]
# Make today slightly lower for "alert" feel
revenues[-1] = revenues[-2] * 0.82
# KPI data
today_rev = revenues[-1]
yesterday_rev = revenues[-2]
week_avg = np.mean(revenues[-7:])
total_7d = sum(revenues[-7:])
change_pct = ((today_rev - yesterday_rev) / yesterday_rev) * 100
# Create figure with subplots
fig = plt.figure(figsize=(10, 7), facecolor=COLOR_BG)
fig.subplots_adjust(top=0.88, bottom=0.08, left=0.08, right=0.95, hspace=0.45)
# Title
fig.text(
0.08, 0.95,
"Data Analyst Report",
fontsize=18, fontweight="bold", color=COLOR_DARK,
fontfamily="sans-serif",
)
fig.text(
0.08, 0.91,
f"{today.strftime('%B %d, %Y')} | Demo report for {username}",
fontsize=11, color=COLOR_GRAY, fontfamily="sans-serif",
)
# --- KPI Cards (top row) ---
kpi_data = [
("Today's Revenue", f"${today_rev:,.0f}", f"{change_pct:+.1f}%", change_pct >= 0),
("7-Day Average", f"${week_avg:,.0f}", "", True),
("7-Day Total", f"${total_7d:,.0f}", "", True),
("Active Projects", f"{rng.randint(180, 220)}", "+12", True),
]
for i, (label, value, badge, is_positive) in enumerate(kpi_data):
ax_kpi = fig.add_axes([0.08 + i * 0.225, 0.72, 0.19, 0.14])
ax_kpi.set_xlim(0, 1)
ax_kpi.set_ylim(0, 1)
ax_kpi.axis("off")
# Card background
card = FancyBboxPatch(
(0, 0), 1, 1,
boxstyle="round,pad=0.05",
facecolor=COLOR_SURFACE, edgecolor="#E5E7EB", linewidth=1,
)
ax_kpi.add_patch(card)
ax_kpi.text(0.1, 0.7, label, fontsize=8, color=COLOR_GRAY, fontfamily="sans-serif")
ax_kpi.text(0.1, 0.25, value, fontsize=16, fontweight="bold", color=COLOR_DARK, fontfamily="sans-serif")
if badge:
badge_color = COLOR_SUCCESS if is_positive else COLOR_ERROR
ax_kpi.text(0.9, 0.25, badge, fontsize=9, fontweight="bold",
color=badge_color, ha="right", fontfamily="sans-serif")
# --- Revenue Chart ---
ax_chart = fig.add_subplot(2, 1, 2)
ax_chart.set_facecolor(COLOR_SURFACE)
# Plot area fill
ax_chart.fill_between(
dates, revenues,
alpha=0.1, color=COLOR_PRIMARY,
)
# Main line
ax_chart.plot(
dates[:-1], revenues[:-1],
color=COLOR_PRIMARY, linewidth=2.5, solid_capstyle="round",
)
# Today's point (highlighted)
ax_chart.plot(
dates[-1], revenues[-1],
"o", color=COLOR_ERROR, markersize=8, zorder=5,
)
ax_chart.plot(
dates[-1], revenues[-1],
"o", color=COLOR_ERROR, markersize=14, alpha=0.2, zorder=4,
)
# Dashed line connecting to today
ax_chart.plot(
dates[-2:], revenues[-2:],
color=COLOR_ERROR, linewidth=2, linestyle="--", alpha=0.7,
)
# Average line
ax_chart.axhline(
y=week_avg, color=COLOR_WARNING, linewidth=1, linestyle=":",
alpha=0.8, label=f"7d avg: ${week_avg:,.0f}",
)
# Styling
ax_chart.set_title(
"Daily Revenue (14 days)", fontsize=13, fontweight="bold",
color=COLOR_DARK, loc="left", pad=12, fontfamily="sans-serif",
)
ax_chart.xaxis.set_major_formatter(mdates.DateFormatter("%b %d"))
ax_chart.xaxis.set_major_locator(mdates.DayLocator(interval=2))
plt.setp(ax_chart.xaxis.get_majorticklabels(), rotation=0, fontsize=9, color=COLOR_GRAY)
plt.setp(ax_chart.yaxis.get_majorticklabels(), fontsize=9, color=COLOR_GRAY)
ax_chart.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f"${x/1000:.0f}k"))
ax_chart.spines["top"].set_visible(False)
ax_chart.spines["right"].set_visible(False)
ax_chart.spines["left"].set_color("#E5E7EB")
ax_chart.spines["bottom"].set_color("#E5E7EB")
ax_chart.tick_params(colors="#E5E7EB")
ax_chart.grid(axis="y", color="#F3F4F6", linewidth=0.8)
ax_chart.legend(
loc="upper left", fontsize=9, frameon=False,
labelcolor=COLOR_GRAY,
)
# Annotate today's drop
ax_chart.annotate(
f"${today_rev:,.0f}\n({change_pct:+.1f}%)",
xy=(dates[-1], revenues[-1]),
xytext=(30, 25), textcoords="offset points",
fontsize=9, fontweight="bold", color=COLOR_ERROR,
fontfamily="sans-serif",
arrowprops=dict(arrowstyle="->", color=COLOR_ERROR, lw=1.2),
bbox=dict(boxstyle="round,pad=0.4", facecolor="white", edgecolor=COLOR_ERROR, alpha=0.9),
)
# Footer
fig.text(
0.5, 0.01,
"This is a demo report. Set up real notifications with your AI assistant.",
fontsize=8, color=COLOR_GRAY, ha="center", fontstyle="italic",
fontfamily="sans-serif",
)
# Save
chart_path = os.path.join(
tempfile.gettempdir(),
f"notify_test_{username}_{datetime.now():%Y%m%d%H%M%S}.png",
)
fig.savefig(chart_path, dpi=180, bbox_inches="tight", facecolor=COLOR_BG)
plt.close(fig)
caption = (
f"*Test Report for {username}*\n"
f"Revenue today: ${today_rev:,.0f} ({change_pct:+.1f}%)\n"
f"7d avg: ${week_avg:,.0f}\n\n"
f"This is a demo. Ask your AI assistant to create real notifications!"
)
return chart_path, caption