247 lines
9.0 KiB
Python
247 lines
9.0 KiB
Python
from domain.reports import Report
|
|
from application.ports.report_repository import ReportRepository
|
|
from application.ports.user_repository import UserRepository
|
|
from infrastructure.adapters.rabbitmq.sender import send_to_queue
|
|
from infrastructure.adapters.rabbitmq.messages import ReportMessage, ReportEventType
|
|
from datetime import datetime
|
|
from typing import List, Optional, Dict, Any
|
|
from uuid import uuid4
|
|
|
|
class CreateReport:
|
|
"""Use case para crear un nuevo reporte - envía mensaje a RabbitMQ"""
|
|
def __init__(self, repo: ReportRepository, user_repo: UserRepository):
|
|
if not isinstance(repo, ReportRepository):
|
|
raise TypeError("repo must implement ReportRepository")
|
|
if not isinstance(user_repo, UserRepository):
|
|
raise TypeError("user_repo must implement UserRepository")
|
|
self.repo = repo
|
|
self.user_repo = user_repo
|
|
|
|
def execute(self, id_usuario: int, tipo_reporte: int, descripcion: str,
|
|
ubicacion: Optional[str] = None, lat: Optional[float] = None,
|
|
lng: Optional[float] = None, image_filename: Optional[str] = None) -> Dict[str, Any]:
|
|
"""
|
|
Sends a create report message to RabbitMQ.
|
|
Valida previamente:
|
|
- Usuario existe
|
|
- Descripción no está vacía
|
|
- Tipo de reporte válido
|
|
|
|
Returns:
|
|
Dictionary with status and message
|
|
"""
|
|
# Validación: descripción requerida
|
|
if not descripcion or not descripcion.strip():
|
|
return {
|
|
"status": "error",
|
|
"message": "La descripción del reporte es requerida"
|
|
}
|
|
|
|
# Validación: tipo de reporte válido (1-5)
|
|
if tipo_reporte < 1 or tipo_reporte > 5:
|
|
return {
|
|
"status": "error",
|
|
"message": "El tipo de reporte debe estar entre 1 y 5"
|
|
}
|
|
|
|
# Validación: usuario existe (CRÍTICO)
|
|
try:
|
|
user = self.user_repo.find_by_id(id_usuario)
|
|
if not user:
|
|
return {
|
|
"status": "error",
|
|
"message": f"Usuario con ID {id_usuario} no existe"
|
|
}
|
|
except Exception as e:
|
|
return {
|
|
"status": "error",
|
|
"message": f"Error al validar usuario: {str(e)}"
|
|
}
|
|
|
|
id_reporte = str(uuid4())
|
|
fecha_creacion = datetime.now()
|
|
|
|
# Create message object
|
|
message = ReportMessage(
|
|
event_type=ReportEventType.CREATE,
|
|
id_reporte=id_reporte,
|
|
id_usuario=id_usuario,
|
|
tipo_reporte=tipo_reporte,
|
|
descripcion=descripcion.strip(),
|
|
ubicacion=ubicacion,
|
|
lat=lat,
|
|
lng=lng,
|
|
image_filename=image_filename,
|
|
visibilidad=50.0, # Visibilidad inicial neutral
|
|
fecha_creacion=fecha_creacion.isoformat()
|
|
)
|
|
|
|
# Send to RabbitMQ
|
|
success = send_to_queue("reports_queue", message.to_dict())
|
|
|
|
if success:
|
|
return {
|
|
"status": "queued",
|
|
"message": "Reporte enviado a cola para procesamiento",
|
|
"id_reporte": id_reporte
|
|
}
|
|
else:
|
|
return {
|
|
"status": "error",
|
|
"message": "Error al enviar reporte a la cola de procesamiento"
|
|
}
|
|
|
|
class GetReportById:
|
|
"""Use case para obtener un reporte por ID"""
|
|
def __init__(self, repo: ReportRepository):
|
|
if not isinstance(repo, ReportRepository):
|
|
raise TypeError("repo must implement ReportRepository")
|
|
self.repo = repo
|
|
|
|
def execute(self, report_id: str) -> Optional[Report]:
|
|
return self.repo.find_by_id(report_id)
|
|
|
|
class GetReportsByUser:
|
|
"""Use case para obtener todos los reportes de un usuario"""
|
|
def __init__(self, repo: ReportRepository):
|
|
if not isinstance(repo, ReportRepository):
|
|
raise TypeError("repo must implement ReportRepository")
|
|
self.repo = repo
|
|
|
|
def execute(self, user_id: int) -> List[Report]:
|
|
return self.repo.find_by_user_id(user_id)
|
|
|
|
class ListAllReports:
|
|
"""Use case para obtener todos los reportes"""
|
|
def __init__(self, repo: ReportRepository):
|
|
if not isinstance(repo, ReportRepository):
|
|
raise TypeError("repo must implement ReportRepository")
|
|
self.repo = repo
|
|
|
|
def execute(self) -> List[Report]:
|
|
return self.repo.find_all()
|
|
|
|
class UpdateReportVisibility:
|
|
"""Use case para actualizar la visibilidad de un reporte basado en votación comunitaria - envía mensaje a RabbitMQ"""
|
|
def __init__(self, repo: ReportRepository, user_repo: UserRepository):
|
|
if not isinstance(repo, ReportRepository):
|
|
raise TypeError("repo must implement ReportRepository")
|
|
self.repo = repo
|
|
self.user_repo = user_repo
|
|
|
|
def execute(self, report_id: str, new_visibility: float, penalize_author: bool = False) -> Dict[str, Any]:
|
|
"""
|
|
Sends an update report visibility message to RabbitMQ.
|
|
Valida previamente:
|
|
- Reporte existe
|
|
- Visibilidad en rango válido (0-100)
|
|
|
|
Returns:
|
|
Dictionary with status and message
|
|
"""
|
|
# Validación: reporte existe
|
|
try:
|
|
report = self.repo.find_by_id(report_id)
|
|
if not report:
|
|
return {
|
|
"status": "error",
|
|
"message": f"Reporte con ID {report_id} no existe"
|
|
}
|
|
except Exception as e:
|
|
return {
|
|
"status": "error",
|
|
"message": f"Error al buscar reporte: {str(e)}"
|
|
}
|
|
|
|
# Validar rango de visibilidad
|
|
if new_visibility < 0 or new_visibility > 100:
|
|
return {
|
|
"status": "error",
|
|
"message": "La visibilidad debe estar entre 0 y 100"
|
|
}
|
|
|
|
# Create message object
|
|
message = ReportMessage(
|
|
event_type=ReportEventType.UPDATE_VISIBILITY,
|
|
id_reporte=report_id,
|
|
visibilidad=new_visibility,
|
|
penalize_author=penalize_author
|
|
)
|
|
|
|
# Send to RabbitMQ
|
|
success = send_to_queue("reports_queue", message.to_dict())
|
|
|
|
if success:
|
|
return {
|
|
"status": "queued",
|
|
"message": "Actualización de visibilidad enviada a cola para procesamiento",
|
|
"report_id": report_id,
|
|
"new_visibility": new_visibility
|
|
}
|
|
else:
|
|
return {
|
|
"status": "error",
|
|
"message": "Error al enviar actualización de visibilidad a la cola de procesamiento"
|
|
}
|
|
|
|
class GetShadowbannedReports:
|
|
"""Use case para obtener reportes shadowbaneados (baja visibilidad)"""
|
|
def __init__(self, repo: ReportRepository):
|
|
if not isinstance(repo, ReportRepository):
|
|
raise TypeError("repo must implement ReportRepository")
|
|
self.repo = repo
|
|
|
|
def execute(self, visibility_threshold: float = 20) -> List[Report]:
|
|
return self.repo.find_shadowbanned(visibility_threshold)
|
|
|
|
class DeleteReport:
|
|
"""Use case para eliminar un reporte - envía mensaje a RabbitMQ"""
|
|
def __init__(self, repo: ReportRepository):
|
|
if not isinstance(repo, ReportRepository):
|
|
raise TypeError("repo must implement ReportRepository")
|
|
self.repo = repo
|
|
|
|
def execute(self, report_id: str) -> Dict[str, Any]:
|
|
"""
|
|
Sends a delete report message to RabbitMQ.
|
|
Valida previamente:
|
|
- Reporte existe
|
|
|
|
Returns:
|
|
Dictionary with status and message
|
|
"""
|
|
# Validación: reporte existe
|
|
try:
|
|
report = self.repo.find_by_id(report_id)
|
|
if not report:
|
|
return {
|
|
"status": "error",
|
|
"message": f"Reporte con ID {report_id} no existe"
|
|
}
|
|
except Exception as e:
|
|
return {
|
|
"status": "error",
|
|
"message": f"Error al buscar reporte: {str(e)}"
|
|
}
|
|
|
|
# Create message object
|
|
message = ReportMessage(
|
|
event_type=ReportEventType.DELETE,
|
|
id_reporte=report_id
|
|
)
|
|
|
|
# Send to RabbitMQ
|
|
success = send_to_queue("reports_queue", message.to_dict())
|
|
|
|
if success:
|
|
return {
|
|
"status": "queued",
|
|
"message": f"Reporte {report_id} enviado a cola para eliminación",
|
|
"id_reporte": report_id
|
|
}
|
|
else:
|
|
return {
|
|
"status": "error",
|
|
"message": "Error al enviar eliminación del reporte a la cola de procesamiento"
|
|
}
|