from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from app import models, schemas from app.database import get_db from app.services.standard_qa_service import add_audit_log, mark_standard_call_status router = APIRouter(prefix="/standard-qa", tags=["standard_qa"]) def _get_standard(db: Session, standard_id: int) -> models.StandardQAItem: standard = db.get(models.StandardQAItem, standard_id) if not standard: raise HTTPException(status_code=404, detail="标准问答不存在") return standard @router.get("/callable", response_model=list[schemas.CallableQARead]) def callable_qa(db: Session = Depends(get_db)) -> list[models.StandardQAItem]: return ( db.query(models.StandardQAItem) .join(models.RawQAItem) .filter( models.StandardQAItem.audit_status == models.AuditStatus.approved, models.StandardQAItem.call_status == models.CallStatus.callable, models.StandardQAItem.risk_level.in_([models.RiskLevel.low, models.RiskLevel.medium]), models.RawQAItem.desensitization_status.in_( [models.DesensitizationStatus.not_needed, models.DesensitizationStatus.done] ), ) .order_by(models.StandardQAItem.updated_at.desc()) .all() ) @router.get("", response_model=list[schemas.StandardQARead]) def list_standard_qa( audit_status: str | None = None, call_status: str | None = None, risk_level: str | None = None, primary_topic: str | None = None, course_stage: str | None = None, db: Session = Depends(get_db), ) -> list[models.StandardQAItem]: query = db.query(models.StandardQAItem) if audit_status: query = query.filter(models.StandardQAItem.audit_status == audit_status) if call_status: query = query.filter(models.StandardQAItem.call_status == call_status) if risk_level: query = query.filter(models.StandardQAItem.risk_level == risk_level) if primary_topic: query = query.filter(models.StandardQAItem.primary_topic == primary_topic) if course_stage: query = query.filter(models.StandardQAItem.course_stage == course_stage) return query.order_by(models.StandardQAItem.updated_at.desc()).all() @router.get("/{standard_id}", response_model=schemas.StandardQARead) def get_standard_qa(standard_id: int, db: Session = Depends(get_db)) -> models.StandardQAItem: return _get_standard(db, standard_id) @router.patch("/{standard_id}", response_model=schemas.StandardQARead) def update_standard_qa( standard_id: int, payload: schemas.StandardQAUpdate, db: Session = Depends(get_db) ) -> models.StandardQAItem: standard = _get_standard(db, standard_id) for key, value in payload.model_dump(exclude_unset=True).items(): setattr(standard, key, value) db.commit() db.refresh(standard) return standard @router.post("/{standard_id}/mark-callable", response_model=schemas.StandardQARead) def mark_callable( standard_id: int, payload: schemas.ReviewActionRequest | None = None, db: Session = Depends(get_db) ) -> models.StandardQAItem: payload = payload or schemas.ReviewActionRequest() try: return mark_standard_call_status( db, _get_standard(db, standard_id), models.CallStatus.callable, payload.reviewer_id, payload.comment ) except ValueError as exc: raise HTTPException(status_code=400, detail=str(exc)) from exc @router.post("/{standard_id}/mark-not-callable", response_model=schemas.StandardQARead) def mark_not_callable( standard_id: int, payload: schemas.ReviewActionRequest | None = None, db: Session = Depends(get_db) ) -> models.StandardQAItem: payload = payload or schemas.ReviewActionRequest() return mark_standard_call_status( db, _get_standard(db, standard_id), models.CallStatus.not_callable, payload.reviewer_id, payload.comment ) @router.post("/{standard_id}/disable", response_model=schemas.StandardQARead) def disable_standard( standard_id: int, payload: schemas.ReviewActionRequest | None = None, db: Session = Depends(get_db) ) -> models.StandardQAItem: payload = payload or schemas.ReviewActionRequest() standard = _get_standard(db, standard_id) before = standard.audit_status.value standard.audit_status = models.AuditStatus.disabled standard.call_status = models.CallStatus.forbidden standard.disabled_reason = payload.comment add_audit_log( db, user_id=payload.reviewer_id, target_type=models.TargetType.standard_qa, target_id=standard.id, action=models.AuditAction.disable, before_status=before, after_status=standard.audit_status.value, comment=payload.comment, ) db.commit() db.refresh(standard) return standard @router.post("/{standard_id}/need-review", response_model=schemas.StandardQARead) def need_review( standard_id: int, payload: schemas.ReviewActionRequest | None = None, db: Session = Depends(get_db) ) -> models.StandardQAItem: payload = payload or schemas.ReviewActionRequest() standard = _get_standard(db, standard_id) before = standard.audit_status.value standard.audit_status = models.AuditStatus.needs_revision standard.call_status = models.CallStatus.need_review add_audit_log( db, user_id=payload.reviewer_id, target_type=models.TargetType.standard_qa, target_id=standard.id, action=models.AuditAction.revise, before_status=before, after_status=standard.audit_status.value, comment=payload.comment, ) db.commit() db.refresh(standard) return standard