PMFlow/backend/app/api/ai_pmo_api/shared.py

54 lines
1.9 KiB
Python

from __future__ import annotations
import asyncio
from datetime import datetime
from typing import Any, Literal, Optional
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel, Field
from sqlalchemy import and_, or_, select
from sqlalchemy.ext.asyncio import AsyncSession
from ...core.logging import get_logger
from ...core.response import success_response
from ...core.database import AsyncSessionLocal, get_db
from ...dependencies.auth import get_current_user
from ...dependencies.tenant import get_tenant_id
from ...models import DecisionRecord, IngestEvent, PlanBundle, PortfolioSnapshot, Project, ReplyReceipt, User, UserProject, WorkItem
from ...services.auth import has_any_role
from ...services.ai_pmo.ai_pmo_cadence import AIPMOCadenceService
from ...services.ai_pmo.ai_pmo_kernel import AIPMOKernelService
router = APIRouter(prefix="/ai-pmo", tags=["AI PMO"])
logger = get_logger(__name__)
FRONT_NOISE_INTENTS = {"query.read_only", "query.answer"}
def _can_view_all_work_items(user: User) -> bool:
return has_any_role(str(getattr(user, "role", "") or ""), ["OWNER", "REVIEWER"])
def _visible_work_item_filter(*, current_user: User, tenant_id: int):
if _can_view_all_work_items(current_user):
return True
return or_(
WorkItem.owner_user_id == int(current_user.id),
WorkItem.project_id.in_(
select(Project.id)
.outerjoin(
UserProject,
and_(
UserProject.tenant_id == Project.tenant_id,
UserProject.project_id == Project.id,
UserProject.user_id == int(current_user.id),
),
)
.where(
and_(
Project.tenant_id == int(tenant_id),
or_(Project.owner_id == int(current_user.id), UserProject.user_id.is_not(None)),
)
)
),
)