71 lines
2.3 KiB
Python
71 lines
2.3 KiB
Python
|
|
"""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),
|
||
|
|
}
|