feat: AI Worker 平台 MVP v1.0.0 - 多租户/项目管理/AI Worker/任务编排/HITL审核/成本治理
This commit is contained in:
@@ -0,0 +1,92 @@
|
|||||||
|
"""Review service: HITL approval/rejection flow."""
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
from typing import List, Optional
|
||||||
|
from datetime import datetime
|
||||||
|
from app.models.review import Review
|
||||||
|
from app.models.task import Task
|
||||||
|
from app.schemas.review import ReviewCreate, ReviewDecision
|
||||||
|
|
||||||
|
|
||||||
|
class ReviewService:
|
||||||
|
@staticmethod
|
||||||
|
def list_reviews(
|
||||||
|
db: Session,
|
||||||
|
tenant_id: int,
|
||||||
|
status: Optional[str] = None,
|
||||||
|
project_id: Optional[int] = None,
|
||||||
|
skip: int = 0,
|
||||||
|
limit: int = 100,
|
||||||
|
) -> List[Review]:
|
||||||
|
q = db.query(Review).filter(Review.tenant_id == tenant_id)
|
||||||
|
if status:
|
||||||
|
q = q.filter(Review.status == status)
|
||||||
|
if project_id:
|
||||||
|
q = q.filter(Review.project_id == project_id)
|
||||||
|
return q.order_by(Review.created_at.desc()).offset(skip).limit(limit).all()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_review(db: Session, tenant_id: int, review_id: int) -> Optional[Review]:
|
||||||
|
return (
|
||||||
|
db.query(Review)
|
||||||
|
.filter(Review.id == review_id, Review.tenant_id == tenant_id)
|
||||||
|
.first()
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_review(
|
||||||
|
db: Session, tenant_id: int, req: ReviewCreate
|
||||||
|
) -> Review:
|
||||||
|
review = Review(
|
||||||
|
tenant_id=tenant_id,
|
||||||
|
task_id=req.task_id,
|
||||||
|
project_id=req.project_id,
|
||||||
|
review_type=req.review_type,
|
||||||
|
status="pending",
|
||||||
|
review_content=req.review_content,
|
||||||
|
auto_check_result=req.auto_check_result,
|
||||||
|
submitted_at=datetime.utcnow(),
|
||||||
|
)
|
||||||
|
db.add(review)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(review)
|
||||||
|
return review
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def make_decision(
|
||||||
|
db: Session,
|
||||||
|
tenant_id: int,
|
||||||
|
review_id: int,
|
||||||
|
reviewer_id: int,
|
||||||
|
reviewer_role: str,
|
||||||
|
req: ReviewDecision,
|
||||||
|
) -> Review:
|
||||||
|
review = ReviewService.get_review(db, tenant_id, review_id)
|
||||||
|
if not review:
|
||||||
|
raise ValueError(f"Review #{review_id} not found")
|
||||||
|
if review.status != "pending":
|
||||||
|
raise ValueError(f"Review already {review.status}")
|
||||||
|
|
||||||
|
review.status = req.status
|
||||||
|
review.reviewer_id = reviewer_id
|
||||||
|
review.reviewer_role = reviewer_role
|
||||||
|
review.reviewer_comment = req.comment
|
||||||
|
review.reviewed_at = datetime.utcnow()
|
||||||
|
|
||||||
|
# Update task status
|
||||||
|
task = (
|
||||||
|
db.query(Task)
|
||||||
|
.filter(Task.id == review.task_id, Task.tenant_id == tenant_id)
|
||||||
|
.first()
|
||||||
|
)
|
||||||
|
if task:
|
||||||
|
if req.status == "approved":
|
||||||
|
task.status = "done"
|
||||||
|
task.completed_at = datetime.utcnow()
|
||||||
|
task.review_status = "approved"
|
||||||
|
else:
|
||||||
|
task.status = "rejected"
|
||||||
|
task.review_status = "rejected"
|
||||||
|
|
||||||
|
db.commit()
|
||||||
|
db.refresh(review)
|
||||||
|
return review
|
||||||
Reference in New Issue
Block a user