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

@@ -0,0 +1,22 @@
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base, sessionmaker
from core.config import ConfSettings
# Base de datos MySQL para Usuarios
engine = create_engine(
ConfSettings.mysql_url,
echo=False,
pool_pre_ping=True,
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
def get_db():
"""Obtiene una sesión de base de datos"""
db = SessionLocal()
try:
yield db
finally:
db.close()

View File

@@ -0,0 +1,18 @@
from sqlalchemy import Column, Integer, String, Float, DateTime
from infrastructure.adapters.persistence.db import Base
from datetime import datetime
class UserModel(Base):
"""Modelo SQLAlchemy para Usuario (MySQL)"""
__tablename__ = "usuarios"
user_id = Column(Integer, primary_key=True, index=True, autoincrement=True)
nombre = Column(String(100), nullable=False, index=True)
apellido = Column(String(100), nullable=False, index=True)
email = Column(String(255), unique=True, nullable=False, index=True)
fecha_nacimiento = Column(DateTime, nullable=False)
fecha_creacion = Column(DateTime, default=datetime.utcnow, nullable=False)
calificacion = Column(Float, default=50.0, nullable=False) # 0-100
numero_reportes = Column(Integer, default=0, nullable=False)
url_foto_perfil = Column(String(500), nullable=True)
biografia = Column(String(1000), nullable=True)

View File

@@ -0,0 +1,11 @@
from pymongo import MongoClient
from pymongo.collection import Collection
from core.config import ConfSettings
# Conexión a MongoDB para Reportes
mongo_client = MongoClient(ConfSettings.mongodb_url)
mongodb = mongo_client[ConfSettings.mongodb_db]
def get_reports_collection() -> Collection:
"""Obtiene la colección de reportes desde MongoDB"""
return mongodb["reportes"]

View File

@@ -0,0 +1,81 @@
from application.ports.report_repository import ReportRepository
from domain.reports import Report
from infrastructure.adapters.persistence.mongodb import get_reports_collection
from typing import List, Optional
from bson import ObjectId
from datetime import datetime
class ReportRepositoryMongo(ReportRepository):
"""Implementación del repositorio de Reportes usando MongoDB"""
def __init__(self):
self.collection = get_reports_collection()
def save(self, report: Report) -> Report:
"""Guarda un nuevo reporte"""
report_dict = {
"id_reporte": report.id_reporte,
"id_usuario": report.id_usuario,
"tipo_reporte": report.tipo_reporte,
"descripcion": report.descripcion,
"ubicacion": report.ubicacion,
"visibilidad": report.visibilidad,
"fecha_creacion": report.fecha_creacion or datetime.utcnow()
}
result = self.collection.insert_one(report_dict)
return report
def find_by_id(self, report_id: str) -> Optional[Report]:
"""Obtiene un reporte por ID"""
doc = self.collection.find_one({"id_reporte": report_id})
if doc:
return self._to_domain(doc)
return None
def find_by_user_id(self, user_id: int) -> List[Report]:
"""Obtiene todos los reportes de un usuario"""
docs = self.collection.find({"id_usuario": user_id})
return [self._to_domain(doc) for doc in docs]
def find_all(self) -> List[Report]:
"""Obtiene todos los reportes"""
docs = self.collection.find()
return [self._to_domain(doc) for doc in docs]
def find_by_visibility_range(self, min_visibility: float, max_visibility: float) -> List[Report]:
"""Obtiene reportes dentro de un rango de visibilidad"""
docs = self.collection.find({
"visibilidad": {"$gte": min_visibility, "$lte": max_visibility}
})
return [self._to_domain(doc) for doc in docs]
def update_visibility(self, report_id: str, new_visibility: float) -> None:
"""Actualiza la visibilidad de un reporte"""
self.collection.update_one(
{"id_reporte": report_id},
{"$set": {"visibilidad": new_visibility}}
)
def delete(self, report_id: str) -> bool:
"""Elimina un reporte"""
result = self.collection.delete_one({"id_reporte": report_id})
return result.deleted_count > 0
def find_shadowbanned(self, visibility_threshold: float = 20) -> List[Report]:
"""Obtiene reportes con baja visibilidad (shadowbaneados)"""
docs = self.collection.find({
"visibilidad": {"$lt": visibility_threshold}
})
return [self._to_domain(doc) for doc in docs]
def _to_domain(self, doc: dict) -> Report:
"""Convierte un documento de MongoDB a un objeto de dominio"""
return Report(
id_reporte=doc.get("id_reporte"),
id_usuario=doc.get("id_usuario"),
tipo_reporte=doc.get("tipo_reporte"),
descripcion=doc.get("descripcion"),
ubicacion=doc.get("ubicacion"),
visibilidad=doc.get("visibilidad"),
fecha_creacion=doc.get("fecha_creacion")
)

View File

@@ -0,0 +1,104 @@
from application.ports.user_repository import UserRepository
from domain.users import User
from infrastructure.adapters.persistence.models import UserModel
from infrastructure.adapters.persistence.db import SessionLocal
from typing import List, Optional
class UserRepositorySQL(UserRepository):
"""Implementación del repositorio de Usuarios usando SQLAlchemy (MySQL)"""
def __init__(self, db_session=None):
self.db = db_session or SessionLocal()
def save(self, user: User) -> User:
"""Guarda un nuevo usuario"""
db_user = UserModel(
nombre=user.nombre,
apellido=user.apellido,
email=user.email,
fecha_nacimiento=user.fecha_nacimiento,
fecha_creacion=user.fecha_creacion,
calificacion=user.calificacion,
numero_reportes=user.numero_reportes,
url_foto_perfil=user.url_foto_perfil,
biografia=user.biografia
)
self.db.add(db_user)
self.db.commit()
self.db.refresh(db_user)
# Convertir de vuelta a dominio
return self._to_domain(db_user)
def find_by_id(self, user_id: int) -> Optional[User]:
"""Obtiene un usuario por ID"""
db_user = self.db.query(UserModel).filter(UserModel.user_id == user_id).first()
if db_user:
return self._to_domain(db_user)
return None
def find_by_email(self, email: str) -> Optional[User]:
"""Obtiene un usuario por email"""
db_user = self.db.query(UserModel).filter(UserModel.email == email).first()
if db_user:
return self._to_domain(db_user)
return None
def find_all(self) -> List[User]:
"""Obtiene todos los usuarios"""
db_users = self.db.query(UserModel).all()
return [self._to_domain(user) for user in db_users]
def update(self, user: User) -> User:
"""Actualiza un usuario"""
db_user = self.db.query(UserModel).filter(UserModel.user_id == user.user_id).first()
if db_user:
db_user.nombre = user.nombre
db_user.apellido = user.apellido
db_user.calificacion = user.calificacion
db_user.numero_reportes = user.numero_reportes
db_user.url_foto_perfil = user.url_foto_perfil
db_user.biografia = user.biografia
self.db.commit()
self.db.refresh(db_user)
return self._to_domain(db_user)
return user
def delete(self, user_id: int) -> bool:
"""Elimina un usuario"""
db_user = self.db.query(UserModel).filter(UserModel.user_id == user_id).first()
if db_user:
self.db.delete(db_user)
self.db.commit()
return True
return False
def increment_reports(self, user_id: int) -> None:
"""Incrementa el contador de reportes de un usuario"""
db_user = self.db.query(UserModel).filter(UserModel.user_id == user_id).first()
if db_user:
db_user.numero_reportes += 1
self.db.commit()
def update_rating(self, user_id: int, new_rating: float) -> None:
"""Actualiza la calificación de un usuario"""
db_user = self.db.query(UserModel).filter(UserModel.user_id == user_id).first()
if db_user:
# Asegurar que la calificación esté en el rango 0-100
db_user.calificacion = max(0, min(100, new_rating))
self.db.commit()
def _to_domain(self, db_user: UserModel) -> User:
"""Convierte un modelo SQLAlchemy a un objeto de dominio"""
return User(
user_id=db_user.user_id,
nombre=db_user.nombre,
apellido=db_user.apellido,
email=db_user.email,
fecha_nacimiento=db_user.fecha_nacimiento,
fecha_creacion=db_user.fecha_creacion,
calificacion=db_user.calificacion,
numero_reportes=db_user.numero_reportes,
url_foto_perfil=db_user.url_foto_perfil,
biografia=db_user.biografia
)