diff --git a/app/api/routes/__init__.py b/app/api/routes/__init__.py deleted file mode 100644 index 7e05fc6..0000000 --- a/app/api/routes/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -from fastapi import APIRouter - -from app.api.routes.chat import router as chat_router -from app.api.routes.mock import router as mock_router -from app.api.routes.tools import router as tool_router - -router = APIRouter() -router.include_router(chat_router) -router.include_router(mock_router) - -__all__ = ["router", "tool_router"] diff --git a/app/api/routes/chat.py b/app/api/routes/chat.py deleted file mode 100644 index 2746a88..0000000 --- a/app/api/routes/chat.py +++ /dev/null @@ -1,31 +0,0 @@ -from fastapi import APIRouter, Depends, HTTPException -from sqlalchemy.exc import SQLAlchemyError -from sqlalchemy.orm import Session - -from app.api.routes.dependencies import db_error_detail, get_db -from app.api.schemas import ChatRequest, ChatResponse -from app.services.orchestration.orquestrador_service import OrquestradorService - -router = APIRouter(tags=["Chat"]) - - -@router.post("/chat", response_model=ChatResponse) -async def chat(request: ChatRequest, db: Session = Depends(get_db)): - """Processa mensagem do usuario via orquestrador e retorna resposta do chat.""" - try: - service = OrquestradorService(db) - result = await service.handle_message( - message=request.message, - user_id=request.user_id, - ) - return ChatResponse(response=result) - except SQLAlchemyError as exc: - raise HTTPException( - status_code=503, - detail=db_error_detail(exc), - ) - except ValueError as exc: - # Erros de configuracao de Vertex (regiao/projeto/modelo) - raise HTTPException(status_code=500, detail=f"Configuracao invalida do Vertex AI: {exc}") - except RuntimeError as exc: - raise HTTPException(status_code=503, detail=f"Falha temporaria no LLM/Vertex AI: {exc}") diff --git a/app/api/routes/dependencies.py b/app/api/routes/dependencies.py deleted file mode 100644 index f63e24c..0000000 --- a/app/api/routes/dependencies.py +++ /dev/null @@ -1,33 +0,0 @@ -from sqlalchemy.exc import SQLAlchemyError - -from app.db.database import SessionLocal - - -def get_db(): - """Fornece uma sessao de banco para a request e garante o fechamento.""" - db = SessionLocal() - try: - yield db - finally: - db.close() - - -def db_error_detail(exc: SQLAlchemyError) -> str: - """Converte erros de banco em mensagens amigaveis para a API.""" - text = str(exc).lower() - - # Heuristica para identificar falhas no MySQL de tools. - tools_markers = ("tools", "tool") - if any(marker in text for marker in tools_markers): - return "Servico temporariamente indisponivel: banco MySQL (tools) inacessivel." - - # Heuristica para identificar falhas no MySQL (base ficticia). - mysql_mock_markers = ("mock", "vehicles", "customers", "orders", "review_schedules") - if any(marker in text for marker in mysql_mock_markers): - return "Servico temporariamente indisponivel: banco MySQL (dados ficticios) inacessivel." - - mysql_generic_markers = ("mysql", "pymysql", "(2003", "3306") - if any(marker in text for marker in mysql_generic_markers): - return "Servico temporariamente indisponivel: banco MySQL inacessivel." - - return "Servico temporariamente indisponivel: erro de acesso ao banco de dados." diff --git a/app/api/routes/mock.py b/app/api/routes/mock.py deleted file mode 100644 index 9b4341d..0000000 --- a/app/api/routes/mock.py +++ /dev/null @@ -1,185 +0,0 @@ -from typing import Any, Dict, List - -from fastapi import APIRouter, HTTPException -from sqlalchemy.exc import SQLAlchemyError - -from app.api.routes.dependencies import db_error_detail -from app.api.schemas import ( - AgendarRevisaoRequest, - AvaliarVeiculoTrocaRequest, - CancelarAgendamentoRevisaoRequest, - CancelarPedidoRequest, - ConsultarEstoqueRequest, - EditarDataRevisaoRequest, - HidratarClienteMockRequest, - ListarAgendamentosRevisaoRequest, - RealizarPedidoRequest, - ValidarClienteVendaRequest, -) -from app.services.user.mock_customer_service import hydrate_mock_customer_from_cpf -from app.services.tools.handlers import ( - agendar_revisao, - avaliar_veiculo_troca, - cancelar_agendamento_revisao, - cancelar_pedido, - editar_data_revisao, - listar_agendamentos_revisao, - consultar_estoque, - realizar_pedido, - validar_cliente_venda, -) - -router = APIRouter(prefix="/mock", tags=["Mock"]) - - -@router.post("/consultar-estoque") -async def consultar_estoque_endpoint( - body: ConsultarEstoqueRequest, -) -> List[Dict[str, Any]]: - """Consulta estoque de veiculos mock com filtros opcionais.""" - try: - return await consultar_estoque( - preco_max=body.preco_max, - categoria=body.categoria, - ordenar_preco=body.ordenar_preco, - limite=body.limite, - ) - except SQLAlchemyError as exc: - raise HTTPException(status_code=503, detail=db_error_detail(exc)) - - -@router.post("/validar-cliente-venda") -async def validar_cliente_venda_endpoint( - body: ValidarClienteVendaRequest, -) -> Dict[str, Any]: - """Valida elegibilidade de cliente para uma venda.""" - try: - return await validar_cliente_venda( - cpf=body.cpf, - valor_veiculo=body.valor_veiculo, - ) - except SQLAlchemyError as exc: - raise HTTPException(status_code=503, detail=db_error_detail(exc)) - - -@router.post("/hidratar-cliente-mock") -async def hidratar_cliente_mock_endpoint( - body: HidratarClienteMockRequest, -) -> Dict[str, Any]: - """Cria ou vincula um cliente mock a partir do CPF informado, simulando consulta externa.""" - try: - return await hydrate_mock_customer_from_cpf( - cpf=body.cpf, - user_id=body.user_id, - ) - except ValueError as exc: - raise HTTPException(status_code=400, detail=str(exc)) - except SQLAlchemyError as exc: - raise HTTPException(status_code=503, detail=db_error_detail(exc)) - - -@router.post("/avaliar-veiculo-troca") -async def avaliar_veiculo_troca_endpoint( - body: AvaliarVeiculoTrocaRequest, -) -> Dict[str, Any]: - """Avalia valor de troca de um veiculo com base em modelo, ano e quilometragem.""" - return await avaliar_veiculo_troca( - modelo=body.modelo, - ano=body.ano, - km=body.km, - ) - - -@router.post("/agendar-revisao") -async def agendar_revisao_endpoint( - body: AgendarRevisaoRequest, -) -> Dict[str, Any]: - """Agenda revisao para uma placa em data/hora informada.""" - try: - return await agendar_revisao( - placa=body.placa, - data_hora=body.data_hora, - modelo=body.modelo, - ano=body.ano, - km=body.km, - revisao_previa_concessionaria=body.revisao_previa_concessionaria, - user_id=body.user_id, - ) - except SQLAlchemyError as exc: - raise HTTPException(status_code=503, detail=db_error_detail(exc)) - - -@router.post("/listar-agendamentos-revisao") -async def listar_agendamentos_revisao_endpoint( - body: ListarAgendamentosRevisaoRequest, -) -> List[Dict[str, Any]]: - """Lista os agendamentos de revisao do usuario autenticado.""" - try: - return await listar_agendamentos_revisao( - user_id=body.user_id, - placa=body.placa, - status=body.status, - limite=body.limite, - ) - except SQLAlchemyError as exc: - raise HTTPException(status_code=503, detail=db_error_detail(exc)) - - -@router.post("/cancelar-agendamento-revisao") -async def cancelar_agendamento_revisao_endpoint( - body: CancelarAgendamentoRevisaoRequest, -) -> Dict[str, Any]: - """Cancela agendamento de revisao usando o protocolo.""" - try: - return await cancelar_agendamento_revisao( - protocolo=body.protocolo, - motivo=body.motivo, - user_id=body.user_id, - ) - except SQLAlchemyError as exc: - raise HTTPException(status_code=503, detail=db_error_detail(exc)) - - -@router.post("/editar-data-revisao") -async def editar_data_revisao_endpoint( - body: EditarDataRevisaoRequest, -) -> Dict[str, Any]: - """Edita data e hora de um agendamento de revisao existente.""" - try: - return await editar_data_revisao( - protocolo=body.protocolo, - nova_data_hora=body.nova_data_hora, - user_id=body.user_id, - ) - except SQLAlchemyError as exc: - raise HTTPException(status_code=503, detail=db_error_detail(exc)) - - -@router.post("/cancelar-pedido") -async def cancelar_pedido_endpoint( - body: CancelarPedidoRequest, -) -> Dict[str, Any]: - """Cancela pedido de venda existente registrando o motivo.""" - try: - return await cancelar_pedido( - numero_pedido=body.numero_pedido, - motivo=body.motivo, - user_id=body.user_id, - ) - except SQLAlchemyError as exc: - raise HTTPException(status_code=503, detail=db_error_detail(exc)) - - -@router.post("/realizar-pedido") -async def realizar_pedido_endpoint( - body: RealizarPedidoRequest, -) -> Dict[str, Any]: - """Cria um pedido de compra para cliente aprovado no valor informado.""" - try: - return await realizar_pedido( - cpf=body.cpf, - valor_veiculo=body.valor_veiculo, - user_id=body.user_id, - ) - except SQLAlchemyError as exc: - raise HTTPException(status_code=503, detail=db_error_detail(exc)) diff --git a/app/api/routes/tools.py b/app/api/routes/tools.py deleted file mode 100644 index e516d34..0000000 --- a/app/api/routes/tools.py +++ /dev/null @@ -1,50 +0,0 @@ -from fastapi import APIRouter, Depends, HTTPException -from sqlalchemy.orm import Session - -from app.api.routes.dependencies import get_db -from app.api.schemas import ToolCreate, ToolResponse -from app.repositories.tool_repository import ToolRepository - -router = APIRouter(prefix="/tools", tags=["Tools"]) - - -@router.post("/", response_model=ToolResponse) -def create_tool(tool: ToolCreate, db: Session = Depends(get_db)): - """Cria uma nova tool persistida no banco.""" - repo = ToolRepository(db) - return repo.create( - name=tool.name, - description=tool.description, - parameters=tool.parameters, - ) - - -@router.get("/", response_model=list[ToolResponse]) -def list_tools(db: Session = Depends(get_db)): - """Lista todas as tools cadastradas.""" - repo = ToolRepository(db) - return repo.get_all() - - -@router.get("/{tool_id}", response_model=ToolResponse) -def get_tool(tool_id: int, db: Session = Depends(get_db)): - """Busca uma tool por ID e retorna 404 quando inexistente.""" - repo = ToolRepository(db) - tool = repo.get_by_id(tool_id) - - if not tool: - raise HTTPException(status_code=404, detail="Tool nao encontrada") - - return tool - - -@router.delete("/{tool_id}") -def delete_tool(tool_id: int, db: Session = Depends(get_db)): - """Remove uma tool por ID e retorna 404 quando nao encontrada.""" - repo = ToolRepository(db) - tool = repo.delete(tool_id) - - if not tool: - raise HTTPException(status_code=404, detail="Tool nao encontrada") - - return {"message": "Tool removida com sucesso"} diff --git a/app/main.py b/app/main.py index 2e27857..5363601 100644 --- a/app/main.py +++ b/app/main.py @@ -1,6 +1,5 @@ from fastapi import FastAPI -from app.api.routes import router, tool_router from app.core.settings import settings from app.db.database import Base, engine from app.db.mock_database import MockBase, mock_engine @@ -10,9 +9,6 @@ from app.services.ai.llm_service import LLMService app = FastAPI(title="AI Orquestrador") -app.include_router(router) -app.include_router(tool_router) - @app.on_event("startup") async def startup_event():