-
Notifications
You must be signed in to change notification settings - Fork 55
Project focus_api #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| DATABASE_URL="sqlite:///./focus_log.db" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| # Byte-compiled / optimized / DLL files | ||
| __pycache__/ | ||
| *.pyc | ||
| *.pyo | ||
| *.pyd | ||
|
|
||
| # Virtual environment | ||
| venv/ | ||
| .venv/ | ||
| env/ | ||
| ENV/ | ||
|
|
||
| # Database files | ||
| *.db | ||
| *.sqlite3 | ||
| focus_log.db | ||
| test.db | ||
|
|
||
| # Environment variables | ||
| .env | ||
|
|
||
| # Pytest cache | ||
| .pytest_cache/ | ||
|
|
||
| # VSCode | ||
| .vscode/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| # Focus Log API - v2.0 | ||
|
|
||
| Uma API robusta e inteligente para registrar, analisar e gamificar suas sessões de foco, construída com FastAPI e SQLite. Este projeto vai além de um simples CRUD, incorporando uma arquitetura profissional e funcionalidades criativas para se destacar. | ||
|
|
||
| ## Filosofia do Projeto | ||
|
|
||
| O objetivo não é apenas armazenar dados, mas transformá-los em **insights acionáveis** e **motivação**. A API foi desenhada para ajudar o usuário a entender seus próprios padrões de produtividade e a construir o hábito da consistência através de mecânicas de gamificação. | ||
|
|
||
| ## Funcionalidades Principais | ||
|
|
||
| - **Registro de Foco**: Endpoint para registrar sessões de trabalho ou estudo. | ||
| - **Diagnóstico de Produtividade**: Uma análise completa com métricas como média de foco, tempo total e as melhores/piores sessões. | ||
| - **Feedback Inteligente**: Mensagens didáticas que explicam *por que* o feedback está sendo dado e sugerem ações. | ||
| - **Gamificação (Streaks)**: Sistema de "sequências" que incentiva o registro diário, recompensando a consistência. | ||
| - **Análise de Tags**: Correlaciona as tags usadas nos registros com o nível de foco, revelando o que te ajuda ou atrapalha a ser produtivo. | ||
|
|
||
| --- | ||
|
|
||
| ## Decisões de Arquitetura e Design | ||
|
|
||
| A estrutura do projeto foi escolhida para garantir **clareza, manutenibilidade e escalabilidade**. | ||
|
|
||
| - **FastAPI**: Escolhido pela sua alta performance, sintaxe moderna com type hints (que reduz bugs) e a geração automática de documentação interativa (Swagger UI), que é excelente para desenvolvimento e testes. | ||
|
|
||
| - **Arquitetura em Camadas**: | ||
| - `main.py`: Ponto de entrada. Mínimo de lógica, apenas configurações globais e inclusão dos roteadores. | ||
| - `routers/`: Responsáveis por definir os endpoints HTTP. Sua única função é receber requisições, chamar a camada de serviço e retornar respostas. Não contêm lógica de negócio. | ||
| - `service.py`: O "cérebro" da aplicação. Contém toda a lógica de negócio (como gerar feedbacks, calcular streaks, analisar tags). Não tem conhecimento sobre HTTP ou o banco de dados diretamente, o que a torna reutilizável e fácil de testar. | ||
| - `repository.py`: A única camada que interage com o banco de dados. Abstrai as queries do SQLAlchemy, centralizando o acesso aos dados. | ||
| - `models.py` e `schemas.py`: Separação clara entre o modelo do banco de dados (SQLAlchemy) e o modelo da API (Pydantic). Isso permite que a API evolua de forma independente do banco. | ||
|
|
||
| - **SQLite**: Selecionado pela simplicidade. É um banco de dados baseado em arquivo, que não exige instalação ou configuração de um servidor, tornando o projeto extremamente fácil de rodar localmente. Para um ambiente de produção, a troca para um banco como PostgreSQL seria simples, bastando alterar a `DATABASE_URL` e instalar o driver `psycopg2`. | ||
|
|
||
| - **Pydantic para Validação**: Usado extensivamente para validar os dados de entrada (`RegistroFocoCreate`) e garantir a estrutura dos dados de saída (`*Out` schemas). As mensagens de erro customizadas e o handler de exceção global em `main.py` melhoram a experiência de quem consome a API. | ||
|
|
||
| - **Tarefas em Background (`BackgroundTasks`)**: A atualização da gamificação é feita em segundo plano. Isso proporciona uma resposta mais rápida ao usuário no momento do registro, pois ele não precisa esperar o cálculo da sequência ser finalizado. | ||
|
|
||
| --- | ||
|
|
||
| ## Como Usar | ||
|
|
||
| ### Pré-requisitos | ||
|
|
||
| - Python 3.11 ou superior | ||
|
|
||
| ### Instalação e Execução | ||
|
|
||
| 1. **Clone o repositório e entre na pasta:** | ||
| ```bash | ||
| git clone https://github.com/seu-usuario/focus_log.git | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Atualize a URL do repositório com o endereço real. A URL contém um placeholder 📝 Sugestão de correção- git clone https://github.com/seu-usuario/focus_log.git
+ git clone https://github.com/SouJunior/teste-tecnico-python-backend.git🤖 Prompt for AI Agents |
||
| cd focus_log | ||
| ``` | ||
|
|
||
| 2. **Crie e ative um ambiente virtual:** | ||
| ```bash | ||
| python -m venv venv | ||
| # Windows: | ||
| venv\Scripts\activate | ||
| # macOS/Linux: | ||
| source venv/bin/activate | ||
| ``` | ||
|
|
||
| 3. **Instale as dependências:** | ||
| ```bash | ||
| pip install -r requirements.txt | ||
| ``` | ||
|
|
||
| 4. **Crie o arquivo de ambiente local:** | ||
| Este passo é crucial para definir a conexão com o banco de dados. | ||
| ```bash | ||
| # Windows | ||
| copy .env.example .env | ||
| # macOS/Linux | ||
| cp .env.example .env | ||
| ``` | ||
|
|
||
| 5. **Execute a aplicação:** | ||
| ```bash | ||
| uvicorn app.main:app --reload | ||
| ``` | ||
| A API estará disponível em `http://127.0.0.1:8000`. | ||
|
|
||
| ### Testando a API | ||
|
|
||
| A forma mais fácil de interagir com a API é através da **documentação interativa (Swagger UI)**, disponível em: | ||
|
|
||
| [**http://127.0.0.1:8000/docs**](http://127.0.0.1:8000/docs) | ||
|
|
||
| Lá você pode testar todos os endpoints diretamente do seu navegador. | ||
|
|
||
| --- | ||
|
|
||
| ## Exemplos de Uso (cURL) | ||
|
|
||
| 1. **Registrar uma nova sessão de foco:** | ||
| ```bash | ||
| curl -X 'POST' \ | ||
| 'http://127.0.0.1:8000/registro-foco' \ | ||
| -H 'accept: application/json' \ | ||
| -H 'Content-Type: application/json' \ | ||
| -d '{ | ||
| "nivel_foco": 5, | ||
| "tempo_minutos": 90, | ||
| "comentario": "Desenvolvendo a funcionalidade de diagnóstico com foco total!", | ||
| "categoria": "coding", | ||
| "tags": "backend,python,api" | ||
| }' | ||
| ``` | ||
|
|
||
| 2. **Verificar o status da sua sequência (gamificação):** | ||
| ```bash | ||
| curl -X 'GET' 'http://127.0.0.1:8000/analise/status' -H 'accept: application/json' | ||
| ``` | ||
|
|
||
| 3. **Obter a análise de tags:** | ||
| ```bash | ||
| curl -X 'GET' 'http://127.0.0.1:8000/analise/tags' -H 'accept: application/json' | ||
| ``` | ||
|
|
||
| 4. **Obter o diagnóstico de produtividade:** | ||
| ```bash | ||
| curl -X 'GET' \ | ||
| 'http://127.0.0.1:8000/diagnostico-produtividade' \ | ||
| -H 'accept: application/json' | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Como Rodar os Testes | ||
|
|
||
| Para garantir a qualidade e o funcionamento correto da API, execute os testes automatizados com `pytest`. | ||
|
|
||
| ```bash | ||
| pytest | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,29 @@ | ||||||||||||||||||
| import os | ||||||||||||||||||
| from sqlalchemy import create_engine | ||||||||||||||||||
| from sqlalchemy.ext.declarative import declarative_base | ||||||||||||||||||
| from sqlalchemy.orm import sessionmaker | ||||||||||||||||||
| from dotenv import load_dotenv | ||||||||||||||||||
|
|
||||||||||||||||||
| load_dotenv() | ||||||||||||||||||
|
|
||||||||||||||||||
| DATABASE_URL = os.getenv("DATABASE_URL") | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Valide que DATABASE_URL está definida antes de usar. Se a variável de ambiente 🛡️ Correção sugerida com validação DATABASE_URL = os.getenv("DATABASE_URL")
+
+if not DATABASE_URL:
+ raise ValueError(
+ "DATABASE_URL não está definida. "
+ "Certifique-se de criar o arquivo .env a partir de .env.example"
+ )📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| engine = create_engine( | ||||||||||||||||||
| DATABASE_URL, connect_args={"check_same_thread": False} | ||||||||||||||||||
| ) | ||||||||||||||||||
| SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) | ||||||||||||||||||
|
|
||||||||||||||||||
| Base = declarative_base() | ||||||||||||||||||
|
|
||||||||||||||||||
| def get_db(): | ||||||||||||||||||
| """ | ||||||||||||||||||
| Obtém uma sessão do banco de dados. | ||||||||||||||||||
|
|
||||||||||||||||||
| Yields: | ||||||||||||||||||
| Session: A sessão do banco de dados. | ||||||||||||||||||
| """ | ||||||||||||||||||
| db = SessionLocal() | ||||||||||||||||||
| try: | ||||||||||||||||||
| yield db | ||||||||||||||||||
| finally: | ||||||||||||||||||
| db.close() | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| from fastapi import FastAPI, Request, status | ||
| from fastapi.responses import JSONResponse | ||
| from fastapi.exceptions import RequestValidationError | ||
| from .database import engine, Base | ||
| from .routers import registro, diagnostico, analise | ||
|
|
||
| Base.metadata.create_all(bind=engine) | ||
|
|
||
| app = FastAPI( | ||
| title="Focus Log API", | ||
| description="Uma API para registrar e analisar sessões de foco, com gamificação e análise inteligente.", | ||
| version="2.0.0" | ||
| ) | ||
|
|
||
| @app.exception_handler(RequestValidationError) | ||
| async def validation_exception_handler(request: Request, exc: RequestValidationError): | ||
| """ | ||
| Handler global para erros de validação do Pydantic. | ||
| """ | ||
| detalhes = [] | ||
| for error in exc.errors(): | ||
| campo = " -> ".join(map(str, error["loc"])) | ||
| mensagem = error["msg"] | ||
| detalhes.append({"campo": campo, "mensagem": mensagem}) | ||
| return JSONResponse( | ||
| status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, | ||
| content={"erro": "Dados inválidos", "detalhes": detalhes}, | ||
| ) | ||
|
|
||
| app.include_router(registro.router, tags=["Registros de Foco"]) | ||
| app.include_router(diagnostico.router, tags=["Diagnóstico de Produtividade"]) | ||
| app.include_router(analise.router) | ||
|
|
||
| @app.get("/", include_in_schema=False) | ||
| def read_root(): | ||
| return {"message": "Bem-vindo à Focus Log API v2! Acesse /docs para a documentação."} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| import enum | ||
| from sqlalchemy import ( | ||
| Column, | ||
| Integer, | ||
| String, | ||
| DateTime, | ||
| Enum, | ||
| func, | ||
| ) | ||
| from .database import Base | ||
|
|
||
|
|
||
| class StatusApp(Base): | ||
| """ | ||
| Modelo da tabela `status_app` para gamificação. | ||
| Armazena a sequência de dias com registros. | ||
| """ | ||
| __tablename__ = "status_app" | ||
|
|
||
| id = Column(Integer, primary_key=True) | ||
| sequencia_atual = Column(Integer, default=0) | ||
| sequencia_maxima = Column(Integer, default=0) | ||
| data_ultimo_registro = Column(DateTime, nullable=True) | ||
|
|
||
|
|
||
| class CategoriaEnum(str, enum.Enum): | ||
| coding = "coding" | ||
| reuniao = "reuniao" | ||
| estudo = "estudo" | ||
| outro = "outro" | ||
|
|
||
| class RegistroFoco(Base): | ||
| """ | ||
| Modelo da tabela `registros_foco`. | ||
| """ | ||
| __tablename__ = "registros_foco" | ||
|
|
||
| id = Column(Integer, primary_key=True, index=True) | ||
| nivel_foco = Column(Integer, nullable=False) | ||
| tempo_minutos = Column(Integer, nullable=False) | ||
| comentario = Column(String(500), nullable=False) | ||
| categoria = Column(Enum(CategoriaEnum), default=CategoriaEnum.outro, nullable=False) | ||
| tags = Column(String(200), nullable=True) | ||
| criado_em = Column(DateTime, default=func.now(), nullable=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remova as aspas ao redor do valor da variável de ambiente.
Em arquivos
.env, as aspas são tratadas como parte literal do valor. Quandopython-dotenvcarregar esta configuração,DATABASE_URLterá o valor"sqlite:///./focus_log.db"(incluindo as aspas), o que causará erro ao tentar criar a conexão SQLAlchemy.🔧 Correção sugerida
📝 Committable suggestion
🧰 Tools
🪛 dotenv-linter (4.0.0)
[warning] 1-1: [QuoteCharacter] The value has quote characters (', ")
(QuoteCharacter)
🤖 Prompt for AI Agents