187 lines
6.0 KiB
Python
187 lines
6.0 KiB
Python
"""
|
|
Data Consistency API endpoints for validating and monitoring task aggregation consistency.
|
|
"""
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
from sqlalchemy.orm import Session
|
|
from typing import List, Optional, Dict, Any
|
|
|
|
from database import get_db
|
|
from models.user import User, UserRole
|
|
from services.data_consistency import create_data_consistency_service
|
|
from utils.auth import get_current_user_from_token, _get_user_from_db
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
def get_current_user_with_db(
|
|
token_data: dict = Depends(get_current_user_from_token),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""Get current user with proper database dependency."""
|
|
return _get_user_from_db(db, token_data["user_id"])
|
|
|
|
|
|
def require_admin_or_coordinator(
|
|
token_data: dict = Depends(get_current_user_from_token),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""Require admin or coordinator role for consistency operations."""
|
|
current_user = _get_user_from_db(db, token_data["user_id"])
|
|
if current_user.role not in [UserRole.COORDINATOR] and not current_user.is_admin:
|
|
raise HTTPException(
|
|
status_code=403,
|
|
detail="Admin or Coordinator role required for consistency operations"
|
|
)
|
|
return current_user
|
|
|
|
|
|
@router.get("/validate/{entity_type}/{entity_id}")
|
|
async def validate_entity_consistency(
|
|
entity_type: str,
|
|
entity_id: int,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user_with_db)
|
|
):
|
|
"""
|
|
Validate task aggregation consistency for a specific shot or asset.
|
|
|
|
Args:
|
|
entity_type: 'shot' or 'asset'
|
|
entity_id: ID of the shot or asset
|
|
"""
|
|
if entity_type not in ['shot', 'asset']:
|
|
raise HTTPException(
|
|
status_code=400,
|
|
detail="entity_type must be 'shot' or 'asset'"
|
|
)
|
|
|
|
consistency_service = create_data_consistency_service(db)
|
|
|
|
try:
|
|
result = consistency_service.validate_task_aggregation_consistency(entity_id, entity_type)
|
|
return result
|
|
except ValueError as e:
|
|
raise HTTPException(status_code=400, detail=str(e))
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=f"Validation failed: {str(e)}")
|
|
|
|
|
|
@router.post("/validate/bulk")
|
|
async def validate_bulk_consistency(
|
|
entity_ids: List[int],
|
|
entity_type: str,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(require_admin_or_coordinator)
|
|
):
|
|
"""
|
|
Validate task aggregation consistency for multiple shots or assets.
|
|
|
|
Args:
|
|
entity_ids: List of shot or asset IDs
|
|
entity_type: 'shot' or 'asset'
|
|
"""
|
|
if entity_type not in ['shot', 'asset']:
|
|
raise HTTPException(
|
|
status_code=400,
|
|
detail="entity_type must be 'shot' or 'asset'"
|
|
)
|
|
|
|
if len(entity_ids) > 100:
|
|
raise HTTPException(
|
|
status_code=400,
|
|
detail="Maximum 100 entities can be validated at once"
|
|
)
|
|
|
|
consistency_service = create_data_consistency_service(db)
|
|
|
|
try:
|
|
result = consistency_service.validate_bulk_consistency(entity_ids, entity_type)
|
|
return result
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=f"Bulk validation failed: {str(e)}")
|
|
|
|
|
|
@router.get("/report")
|
|
async def get_consistency_report(
|
|
project_id: Optional[int] = Query(None, description="Filter by project ID"),
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(require_admin_or_coordinator)
|
|
):
|
|
"""
|
|
Generate a comprehensive consistency report for shots and assets.
|
|
|
|
Args:
|
|
project_id: Optional project ID to filter by
|
|
"""
|
|
consistency_service = create_data_consistency_service(db)
|
|
|
|
try:
|
|
result = consistency_service.get_consistency_report(project_id)
|
|
return result
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=f"Report generation failed: {str(e)}")
|
|
|
|
|
|
@router.post("/propagate/{task_id}")
|
|
async def propagate_task_update(
|
|
task_id: int,
|
|
old_status: Optional[str] = None,
|
|
new_status: Optional[str] = None,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(require_admin_or_coordinator)
|
|
):
|
|
"""
|
|
Manually propagate a task update and validate consistency.
|
|
|
|
Args:
|
|
task_id: ID of the task to propagate
|
|
old_status: Previous task status (optional)
|
|
new_status: New task status (optional)
|
|
"""
|
|
consistency_service = create_data_consistency_service(db)
|
|
|
|
try:
|
|
result = consistency_service.propagate_task_update(task_id, old_status, new_status)
|
|
return result
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=f"Task propagation failed: {str(e)}")
|
|
|
|
|
|
@router.get("/health")
|
|
async def consistency_health_check(
|
|
project_id: Optional[int] = Query(None, description="Filter by project ID"),
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user_with_db)
|
|
):
|
|
"""
|
|
Quick health check for data consistency across the system.
|
|
|
|
Args:
|
|
project_id: Optional project ID to filter by
|
|
"""
|
|
consistency_service = create_data_consistency_service(db)
|
|
|
|
try:
|
|
report = consistency_service.get_consistency_report(project_id)
|
|
|
|
# Extract key health metrics
|
|
summary = report['summary']
|
|
health_status = "healthy" if summary['consistency_percentage'] >= 95 else "degraded" if summary['consistency_percentage'] >= 80 else "unhealthy"
|
|
|
|
return {
|
|
'status': health_status,
|
|
'consistency_percentage': summary['consistency_percentage'],
|
|
'total_entities': summary['total_entities'],
|
|
'valid_entities': summary['valid_entities'],
|
|
'invalid_entities': summary['invalid_entities'],
|
|
'total_inconsistencies': summary['total_inconsistencies'],
|
|
'project_id': project_id,
|
|
'timestamp': report['report_timestamp']
|
|
}
|
|
except Exception as e:
|
|
return {
|
|
'status': 'error',
|
|
'error': str(e),
|
|
'timestamp': None
|
|
} |