feat(c7): dashboard widgets as plugin contributions + contact counts via contacts contract
Check Cross-Plugin Imports / check (push) Has been cancelled

This commit is contained in:
Agent Zero
2026-08-23 23:36:36 +02:00
parent dff97f5589
commit cad7d084e8
5 changed files with 116 additions and 49 deletions
+11 -48
View File
@@ -5,13 +5,11 @@ from __future__ import annotations
import uuid
from fastapi import APIRouter, Depends
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.db import get_db
from app.core.visibility import apply_visibility_filter
from app.deps import require_permission
from app.models.contact import Contact
from app.plugins.builtins.contracts import get_contract
from app.plugins.registry import get_registry
router = APIRouter(prefix="/api/v1/dashboard", tags=["dashboard"])
@@ -50,51 +48,16 @@ async def get_dashboard_counts(
):
"""Get dashboard count statistics filtered by user visibility.
Returns counts for contacts and companies that the current user
is allowed to see based on ownership and sharing permissions.
Counts come from the contacts plugin contract (Block C7) — the core
dashboard route has no direct dependency on the Contact model.
"""
tenant_id = uuid.UUID(current_user["tenant_id"])
user_id = uuid.UUID(current_user["user_id"])
is_system_admin = current_user.get("is_system_admin", False)
contacts_contract = get_contract("contacts")
if contacts_contract is None or not hasattr(contacts_contract, "get_counts"):
return {"contacts": 0, "companies": 0, "persons": 0, "total": 0}
# Contact count with visibility filter
contact_query = select(func.count(Contact.id)).where(
Contact.tenant_id == tenant_id,
Contact.deleted_at.is_(None),
return await contacts_contract.get_counts(
db=db,
tenant_id=uuid.UUID(current_user["tenant_id"]),
user_id=uuid.UUID(current_user["user_id"]),
is_system_admin=current_user.get("is_system_admin", False),
)
contact_query = await apply_visibility_filter(
db, contact_query, "contact", Contact, user_id, tenant_id, is_system_admin
)
contact_result = await db.execute(contact_query)
contact_count = contact_result.scalar() or 0
# Company count (Contact.type == 'company') with visibility filter
company_query = select(func.count(Contact.id)).where(
Contact.tenant_id == tenant_id,
Contact.deleted_at.is_(None),
Contact.type == "company",
)
company_query = await apply_visibility_filter(
db, company_query, "contact", Contact, user_id, tenant_id, is_system_admin
)
company_result = await db.execute(company_query)
company_count = company_result.scalar() or 0
# Person count (Contact.type == 'person') with visibility filter
person_query = select(func.count(Contact.id)).where(
Contact.tenant_id == tenant_id,
Contact.deleted_at.is_(None),
Contact.type == "person",
)
person_query = await apply_visibility_filter(
db, person_query, "contact", Contact, user_id, tenant_id, is_system_admin
)
person_result = await db.execute(person_query)
person_count = person_result.scalar() or 0
return {
"contacts": contact_count,
"companies": company_count,
"persons": person_count,
"total": contact_count,
}