"""PM Approval workflow endpoints.""" from datetime import datetime from typing import List from fastapi import APIRouter, Depends, HTTPException from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from database import get_db from models import ( ApprovalCreate, ApprovalFlow, ApprovalOut, ApprovalResult, SRRequest, SRStatus, AuditLog, compute_log_hash ) router = APIRouter(prefix="/api/approvals", tags=["approvals"]) async def _write_audit(db: AsyncSession, sr_id: str, actor: str, action: str, detail: str) -> None: result = await db.execute( select(AuditLog).where(AuditLog.sr_id == sr_id) .order_by(AuditLog.id.desc()).limit(1) ) last = result.scalars().first() prev_hash = last.log_hash if last else None ts = datetime.now().isoformat() log_hash = compute_log_hash(prev_hash, actor, action, detail, ts) db.add(AuditLog( sr_id=sr_id, actor=actor, action=action, detail=detail, prev_hash=prev_hash, log_hash=log_hash )) @router.get("/{sr_id}", response_model=List[ApprovalOut]) async def list_approvals(sr_id: str, db: AsyncSession = Depends(get_db)): result = await db.execute( select(ApprovalFlow).where(ApprovalFlow.sr_id == sr_id) .order_by(ApprovalFlow.created_at) ) return result.scalars().all() @router.post("/{sr_id}", response_model=ApprovalOut, status_code=201) async def decide_approval(sr_id: str, payload: ApprovalCreate, db: AsyncSession = Depends(get_db)): r = await db.execute(select(SRRequest).where(SRRequest.sr_id == sr_id)) sr = r.scalars().first() if not sr: raise HTTPException(404, detail="SR을 찾을 수 없습니다.") if sr.status != SRStatus.PENDING_APPROVAL: raise HTTPException(400, detail="승인 대기 상태의 SR만 처리할 수 있습니다.") apv = ApprovalFlow( sr_id=sr_id, approver=payload.approver, result=payload.result, comment=payload.comment, decided_at=datetime.now(), ) db.add(apv) if payload.result == ApprovalResult.APPROVED: sr.status = SRStatus.APPROVED action, detail = "SR_APPROVED", f"{payload.approver} 승인" else: sr.status = SRStatus.REJECTED action, detail = "SR_REJECTED", f"{payload.approver} 반려: {payload.comment or ''}" sr.updated_at = datetime.now() await _write_audit(db, sr_id, payload.approver, action, detail) await db.commit() await db.refresh(apv) return apv