Generacion de estructura ddd para backend

feat: Refactor API structure by consolidating endpoints and removing deprecated files
This commit is contained in:
2025-06-16 22:22:41 +02:00
parent 43f6fb03fe
commit 9c638fc3e5
10 changed files with 16 additions and 14 deletions
@@ -0,0 +1,113 @@
from fastapi import APIRouter, Depends, HTTPException
from fastapi import Path
from backend.domains.text_manager.text_manager_schema import BibliotecaInput, NotaInput
from fastapi.concurrency import run_in_threadpool
from backend.db.conexion import get_conexion
from backend.domains.text_manager.text_manager_srvc import *
from src.ConexionSql.Postgres_conexion import PostgresConexion
from entrypoint.init_db import db_credencial
from src.Logger.logger_db import LoggerDB, logger
LoggerDB(db_credencial, "logger_textos", created_by="sistema")
router = APIRouter()
@router.post("/biblioteca", summary="Crear una nueva biblioteca")
async def crear_biblioteca_endpoint(
data: BibliotecaInput,
conexion: PostgresConexion = Depends(get_conexion)
):
try:
return await run_in_threadpool(
crear_biblioteca,
data.nombre_biblioteca,
conexion,
data.descripcion,
)
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error interno al crear la biblioteca: {str(e)}")
@router.get("/list", summary="Listar todas las bibliotecas")
def listar_todas_bibliotecas(
conexion: PostgresConexion = Depends(get_conexion)
):
try:
return listar_bibliotecas(conexion=conexion)
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail="Error interno al listar las bibliotecas")
@router.post("/nota/{biblioteca_id}", summary="Agregar una nota a una biblioteca")
def agregar_nota(
biblioteca_id: str = Path(..., description="ID de la biblioteca a la que se agregará la nota"),
nota: NotaInput = ..., # viene del body
conexion: PostgresConexion = Depends(get_conexion)
):
try:
return agregar_nota_a_biblioteca(
conexion=conexion,
biblioteca_id=biblioteca_id,
titulo=nota.titulo,
texto=nota.texto,
tags=nota.tags,
conexiones=nota.conexiones,
resumen=nota.resumen
)
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail="Error interno al agregar la nota")
@router.get("/nota/list/{biblioteca_id}", summary="Listar todas las notas de una biblioteca")
def listar_notas(
biblioteca_id: str,
conexion: PostgresConexion = Depends(get_conexion)
):
try:
return listar_notas_de_biblioteca(conexion, biblioteca_id)
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail="Error interno al listar las notas")
@router.delete("/nota/{biblioteca_id}/{nota_id}", summary="Eliminar una nota por ID")
def eliminar_nota_endpoint(
biblioteca_id: str = Path(..., description="ID de la biblioteca"),
nota_id: str = Path(..., description="ID de la nota a eliminar"),
conexion: PostgresConexion = Depends(get_conexion)
):
try:
return eliminar_nota(conexion=conexion, biblioteca_id=biblioteca_id, nota_id=nota_id)
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except Exception:
raise HTTPException(status_code=500, detail="Error interno al eliminar la nota")
@router.put("/nota/{biblioteca_id}/{nota_id}", summary="Actualizar una nota por ID")
def actualizar_nota_endpoint(
biblioteca_id: str = Path(..., description="ID de la biblioteca"),
nota_id: str = Path(..., description="ID de la nota a actualizar"),
nota: NotaInput = ..., # body
conexion: PostgresConexion = Depends(get_conexion)
):
try:
return actualizar_nota(conexion=conexion, biblioteca_id=biblioteca_id, nota_id=nota_id, nota_input=nota)
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except Exception:
raise HTTPException(status_code=500, detail="Error interno al actualizar la nota")
@@ -0,0 +1,15 @@
from pydantic import BaseModel
from typing import List, Optional
class NotaInput(BaseModel):
titulo: str
texto: str = ""
tags: Optional[List[str]] = []
conexiones: Optional[List[str]] = []
resumen: Optional[str] = ""
class BibliotecaInput(BaseModel):
nombre_biblioteca: str
descripcion: str
@@ -0,0 +1,188 @@
from src.TextManager.biblioteca import Biblioteca
from src.TextManager.biblioteca_mmr import BibliotecaRepo
from src.Llms.Embedders.Openai_embedder import OpenAIEmbedder
from src.ApiKeys.openai_apikey_mmr import OpenAICredencialRepo
from src.ConexionSql.Postgres_conexion import PostgresConexion
from src.TextManager.nota import Nota
from src.TextManager.notas_mmr import generar_tabla_nota_para_biblioteca, NotaRepo
from sqlalchemy import MetaData
from backend.domains.text_manager.text_manager_schema import NotaInput
from entrypoint.init_db import db_credencial
from src.Logger.logger_db import LoggerDB, logger
LoggerDB(db_credencial, "logger_textos", created_by="sistema")
def crear_biblioteca(nombre_biblioteca: str, conexion: PostgresConexion, descripcion: str = None):
logger.info("[INICIO] Creando biblioteca...")
try:
logger.info("[Paso 1] Obteniendo credencial...")
cred_repo = OpenAICredencialRepo(conexion)
credencial = cred_repo.get_by_id("OPAK20250513-61b29978b7604031014")
logger.debug(f"[OK] Credencial obtenida: {credencial.titulo if credencial else '❌ None'}")
logger.info("[Paso 2] Instanciando embedder...")
embedder = OpenAIEmbedder(credencial, model="text-embedding-3-large")
logger.debug("[OK] Embedder instanciado")
logger.info("[Paso 3] Instanciando biblioteca...")
biblioteca = Biblioteca(
nombre=nombre_biblioteca,
embedder=embedder,
descripcion=descripcion
)
logger.debug(f"[OK] Biblioteca instanciada con ID: {biblioteca.id}")
logger.info("[Paso 4] Guardando en base de datos...")
repo = BibliotecaRepo(conexion)
repo.add(biblioteca=biblioteca)
logger.success("[OK] Biblioteca guardada")
logger.info("[Paso 5] Generando modelo de notas...")
biblioteca.generar_modelo_notas(conexion)
logger.success("[OK] Modelo de notas generado")
logger.success("[FIN] Biblioteca creada correctamente")
return {
"mensaje": f"Biblioteca '{nombre_biblioteca}' creada con éxito.",
"id": biblioteca.id
}
except Exception as e:
logger.exception("[ERROR] Ocurrió una excepción:")
raise
def listar_bibliotecas(conexion: PostgresConexion) -> list[dict]:
repo = BibliotecaRepo(conexion)
bibliotecas: list[Biblioteca] = repo.get_all()
return [
{
"id": b.id,
"nombre": b.nombre,
"descripcion": b.descripcion,
"vector_dim": b.vector_dim
}
for b in bibliotecas
]
def agregar_nota_a_biblioteca(
conexion: PostgresConexion,
biblioteca_id: str,
titulo: str,
texto: str = "",
tags: list[str] = None,
conexiones: list[str] = None,
resumen: str = ""
):
repo_biblioteca = BibliotecaRepo(conexion)
biblioteca = repo_biblioteca.get_by_id(biblioteca_id)
if biblioteca is None:
raise ValueError(f"No se encontró la biblioteca con ID {biblioteca_id}")
nota = Nota(
titulo=titulo,
texto=texto,
tags=tags or [],
conexiones=conexiones or [],
resumen=resumen or "",
)
logger.debug(
f"[DEBUG] Nota creada: titulo='{nota.titulo}', "
f"texto_len={len(nota.texto)}, "
f"tags={len(nota.tags)}, "
f"conexiones={len(nota.conexiones)}, "
f"resumen_len={len(nota.resumen)}"
)
metadata = MetaData()
tabla, ModeloNota = generar_tabla_nota_para_biblioteca(
biblioteca.nombre,
biblioteca.vector_dim,
metadata
)
metadata.create_all(conexion.get_engine())
repo_nota = NotaRepo(conexion.get_session(), ModeloNota)
nota_id = repo_nota.add(nota)
resultado = {
"mensaje": f"Nota '{titulo}' agregada con éxito a la biblioteca '{biblioteca.nombre}'.",
"nota_id": nota_id
}
logger.success(f"[SUCCESS] {resultado['mensaje']}")
return resultado
def listar_notas_de_biblioteca(conexion: PostgresConexion, biblioteca_id: str) -> list[dict]:
repo_biblioteca = BibliotecaRepo(conexion)
biblioteca = repo_biblioteca.get_by_id(biblioteca_id)
if not biblioteca:
raise ValueError(f"No se encontró la biblioteca con ID: {biblioteca_id}")
metadata = MetaData()
tabla, ModeloNota = generar_tabla_nota_para_biblioteca(biblioteca.nombre, biblioteca.vector_dim, metadata)
metadata.create_all(conexion.get_engine())
repo_nota = NotaRepo(conexion.get_session(), ModeloNota)
notas = repo_nota.get_all()
return [
{
"id": n.id,
"titulo": n.titulo,
"tags": n.tags,
"texto": n.texto,
"resumen": n.resumen,
"conexiones": n.conexiones
}
for n in notas
]
def eliminar_nota(conexion: PostgresConexion, biblioteca_id: str, nota_id: str) -> dict:
repo_biblioteca = BibliotecaRepo(conexion)
biblioteca = repo_biblioteca.get_by_id(biblioteca_id)
if not biblioteca:
raise ValueError(f"No se encontró la biblioteca con ID: {biblioteca_id}")
metadata = MetaData()
_, ModeloNota = generar_tabla_nota_para_biblioteca(biblioteca.nombre, biblioteca.vector_dim, metadata)
metadata.create_all(conexion.get_engine())
repo_nota = NotaRepo(conexion.get_session(), ModeloNota)
fue_eliminada = repo_nota.delete_by_id(nota_id)
if fue_eliminada:
logger.success(f"Nota '{nota_id}' eliminada correctamente.")
return {"mensaje": f"Nota '{nota_id}' eliminada correctamente."}
else:
raise ValueError(f"No se encontró la nota con ID: {nota_id}")
def actualizar_nota(conexion: PostgresConexion, biblioteca_id: str, nota_id: str, nota_input: NotaInput) -> dict:
repo_biblioteca = BibliotecaRepo(conexion)
biblioteca = repo_biblioteca.get_by_id(biblioteca_id)
if not biblioteca:
raise ValueError(f"No se encontró la biblioteca con ID: {biblioteca_id}")
metadata = MetaData()
_, ModeloNota = generar_tabla_nota_para_biblioteca(biblioteca.nombre, biblioteca.vector_dim, metadata)
metadata.create_all(conexion.get_engine())
repo_nota = NotaRepo(conexion.get_session(), ModeloNota)
nota_actualizada = Nota(
titulo=nota_input.titulo,
texto=nota_input.texto,
tags=nota_input.tags or [],
conexiones=nota_input.conexiones or [],
resumen=nota_input.resumen or ""
)
fue_actualizada = repo_nota.update(nota_id, nota_actualizada)
if fue_actualizada:
logger.success(f"Nota '{nota_id}' actualizada correctamente.")
return {"mensaje": f"Nota '{nota_id}' actualizada correctamente."}
else:
raise ValueError(f"No se encontró la nota con ID: {nota_id}")