"""Workspace summary read-model — tenant-scoped KPIs for current actor.""" from __future__ import annotations from typing import Any from psycopg2.extras import RealDictCursor from db import get_connection from tenant_context import TenantContext def get_workspace_summary(ctx: TenantContext) -> dict[str, Any]: """ Summary for workspace dashboard. Personal counts (current actor): open, blocked, recently done. Tenant-wide: active initiatives count. """ if not ctx.actor_id: return { "open_actions_count": 0, "blocked_actions_count": 0, "active_initiatives_count": 0, "done_actions_recent_count": 0, } conn = get_connection() try: with conn.cursor(cursor_factory=RealDictCursor) as cur: cur.execute( """ SELECT COUNT(*) FILTER ( WHERE a.status IN ('open', 'in_progress') ) AS open_actions_count, COUNT(*) FILTER ( WHERE a.status = 'blocked' ) AS blocked_actions_count, COUNT(*) FILTER ( WHERE a.status = 'done' AND a.updated_at >= NOW() - INTERVAL '7 days' ) AS done_actions_recent_count FROM actions a JOIN action_assignments aa ON aa.action_id = a.id AND aa.tenant_id = a.tenant_id WHERE a.tenant_id = %s AND aa.actor_id = %s """, (ctx.tenant_id, ctx.actor_id), ) row = dict(cur.fetchone()) cur.execute( """ SELECT COUNT(*) AS active_initiatives_count FROM initiatives WHERE tenant_id = %s AND status IN ('active', 'paused') """, (ctx.tenant_id,), ) initiatives_row = dict(cur.fetchone()) finally: conn.close() return { "open_actions_count": int(row["open_actions_count"] or 0), "blocked_actions_count": int(row["blocked_actions_count"] or 0), "active_initiatives_count": int(initiatives_row["active_initiatives_count"] or 0), "done_actions_recent_count": int(row["done_actions_recent_count"] or 0), }