Added everything

This commit is contained in:
Juan M. Ley
2026-03-16 21:05:52 -06:00
parent 00e997debf
commit b526e23149
44 changed files with 2147 additions and 3 deletions

View File

View File

View File

@@ -0,0 +1,46 @@
from abc import ABC, abstractmethod
from domain.reports import Report
from typing import List, Optional
class ReportRepository(ABC):
"""Puerto (interfaz) para el repositorio de Reportes"""
@abstractmethod
def save(self, report: Report) -> Report:
"""Guarda un reporte en la base de datos"""
pass
@abstractmethod
def find_by_id(self, report_id: str) -> Optional[Report]:
"""Obtiene un reporte por ID"""
pass
@abstractmethod
def find_by_user_id(self, user_id: int) -> List[Report]:
"""Obtiene todos los reportes de un usuario"""
pass
@abstractmethod
def find_all(self) -> List[Report]:
"""Obtiene todos los reportes"""
pass
@abstractmethod
def find_by_visibility_range(self, min_visibility: float, max_visibility: float) -> List[Report]:
"""Obtiene reportes dentro de un rango de visibilidad"""
pass
@abstractmethod
def update_visibility(self, report_id: str, new_visibility: float) -> None:
"""Actualiza la visibilidad de un reporte"""
pass
@abstractmethod
def delete(self, report_id: str) -> bool:
"""Elimina un reporte"""
pass
@abstractmethod
def find_shadowbanned(self, visibility_threshold: float = 20) -> List[Report]:
"""Obtiene reportes con baja visibilidad (shadowbaneados)"""
pass

View File

@@ -0,0 +1,46 @@
from abc import ABC, abstractmethod
from domain.users import User
from typing import List, Optional
class UserRepository(ABC):
"""Puerto (interfaz) para el repositorio de Usuarios"""
@abstractmethod
def save(self, user: User) -> User:
"""Guarda un usuario en la base de datos"""
pass
@abstractmethod
def find_by_id(self, user_id: int) -> Optional[User]:
"""Obtiene un usuario por ID"""
pass
@abstractmethod
def find_by_email(self, email: str) -> Optional[User]:
"""Obtiene un usuario por email"""
pass
@abstractmethod
def find_all(self) -> List[User]:
"""Obtiene todos los usuarios"""
pass
@abstractmethod
def update(self, user: User) -> User:
"""Actualiza un usuario"""
pass
@abstractmethod
def delete(self, user_id: int) -> bool:
"""Elimina un usuario"""
pass
@abstractmethod
def increment_reports(self, user_id: int) -> None:
"""Incrementa el contador de reportes de un usuario"""
pass
@abstractmethod
def update_rating(self, user_id: int, new_rating: float) -> None:
"""Actualiza la calificación de un usuario"""
pass

View File

View File

@@ -0,0 +1,115 @@
from domain.reports import Report
from application.ports.report_repository import ReportRepository
from application.ports.user_repository import UserRepository
from datetime import datetime
from typing import List, Optional
from uuid import uuid4
class CreateReport:
"""Use case para crear un nuevo reporte"""
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) -> Report:
# Verificar que el usuario existe
user = self.user_repo.find_by_id(id_usuario)
if not user:
raise ValueError(f"Usuario con ID {id_usuario} no existe")
report = Report(
id_reporte=str(uuid4()),
id_usuario=id_usuario,
tipo_reporte=tipo_reporte,
descripcion=descripcion,
ubicacion=ubicacion,
visibilidad=50.0, # Visibilidad inicial neutral
fecha_creacion=datetime.now()
)
# Incrementar contador de reportes del usuario
self.user_repo.increment_reports(id_usuario)
return self.repo.save(report)
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"""
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) -> None:
# Validar rango de visibilidad
if new_visibility < 0 or new_visibility > 100:
raise ValueError("La visibilidad debe estar entre 0 y 100")
report = self.repo.find_by_id(report_id)
if not report:
raise ValueError(f"Reporte con ID {report_id} no existe")
self.repo.update_visibility(report_id, new_visibility)
# Si la visibilidad es muy baja (shadowban), penalizar al autor
if penalize_author and new_visibility < 20:
user = self.user_repo.find_by_id(report.id_usuario)
if user:
# Reducir calificación del usuario
new_rating = max(0, user.calificacion - 5)
self.user_repo.update_rating(report.id_usuario, new_rating)
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"""
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) -> bool:
return self.repo.delete(report_id)

View File

@@ -0,0 +1,90 @@
from domain.users import User
from application.ports.user_repository import UserRepository
from datetime import datetime
from typing import List, Optional
class CreateUser:
"""Use case para crear un nuevo usuario"""
def __init__(self, repo: UserRepository):
if not isinstance(repo, UserRepository):
raise TypeError("repo must implement UserRepository")
self.repo = repo
def execute(self, nombre: str, apellido: str, email: str,
fecha_nacimiento: datetime, url_foto_perfil: Optional[str] = None,
biografia: Optional[str] = None) -> User:
user = User(
user_id=0,
nombre=nombre,
apellido=apellido,
email=email,
fecha_nacimiento=fecha_nacimiento,
fecha_creacion=datetime.now(),
calificacion=50.0, # Puntuación inicial
numero_reportes=0,
url_foto_perfil=url_foto_perfil,
biografia=biografia
)
return self.repo.save(user)
class GetUserById:
"""Use case para obtener un usuario por ID"""
def __init__(self, repo: UserRepository):
if not isinstance(repo, UserRepository):
raise TypeError("repo must implement UserRepository")
self.repo = repo
def execute(self, user_id: int) -> Optional[User]:
return self.repo.find_by_id(user_id)
class GetUserByEmail:
"""Use case para obtener un usuario por email"""
def __init__(self, repo: UserRepository):
if not isinstance(repo, UserRepository):
raise TypeError("repo must implement UserRepository")
self.repo = repo
def execute(self, email: str) -> Optional[User]:
return self.repo.find_by_email(email)
class ListAllUsers:
"""Use case para obtener todos los usuarios"""
def __init__(self, repo: UserRepository):
if not isinstance(repo, UserRepository):
raise TypeError("repo must implement UserRepository")
self.repo = repo
def execute(self) -> List[User]:
return self.repo.find_all()
class UpdateUser:
"""Use case para actualizar un usuario"""
def __init__(self, repo: UserRepository):
if not isinstance(repo, UserRepository):
raise TypeError("repo must implement UserRepository")
self.repo = repo
def execute(self, user_id: int, nombre: str = None, apellido: str = None,
url_foto_perfil: str = None, biografia: str = None) -> Optional[User]:
user = self.repo.find_by_id(user_id)
if user:
if nombre:
user.nombre = nombre
if apellido:
user.apellido = apellido
if url_foto_perfil is not None:
user.url_foto_perfil = url_foto_perfil
if biografia is not None:
user.biografia = biografia
return self.repo.update(user)
return None
class DeleteUser:
"""Use case para eliminar un usuario"""
def __init__(self, repo: UserRepository):
if not isinstance(repo, UserRepository):
raise TypeError("repo must implement UserRepository")
self.repo = repo
def execute(self, user_id: int) -> bool:
return self.repo.delete(user_id)