Aplicação para gerenciamento de NFSe com backend FastAPI, frontend web estático e empacotamento desktop com Tauri.
O projeto armazena clientes e notas em um banco SQLite local, sincroniza dados com o portal de NFSe, baixa XML/PDF, gera relatórios e exibe indicadores no dashboard.
- Web app servido pelo próprio FastAPI em
backend/main.py. - Frontend SPA em
frontend/, com páginas carregadas dinamicamente. - Desktop app em
ui/, usando Tauri como shell nativo. - Banco local:
nfse.db.
- Cadastro, edição e remoção de clientes.
- Sincronização de notas emitidas e recebidas por período.
- Download de XML e PDF.
- Recuperação de arquivos ausentes usando as URLs salvas no banco.
- Exportação de relatórios em JSON, CSV e XLSX.
- Dashboard com estatísticas, gráfico temporal e ranking.
- Verificação de atualização do sistema via GitHub Releases.
- Navegação de pastas para seleção de diretórios de saída.
- Python 3.12+
- FastAPI
- SQLAlchemy
- SQLite
- Pydantic
- Uvicorn
- OpenPyXL
- HTTPX
- Frontend em HTML/CSS/JavaScript puro
- Tauri para desktop
nfse_manager/
├── 📁 backend/ # API, modelos, schemas e rotas
├── 🎨 frontend/ # UI web servida pelo FastAPI
├── 🖥️ ui/ # Shell desktop com Tauri
├── 📚 docs/ # Documentação do projeto
├── 🗃️ nfse.db # Banco SQLite local
├── 🧩 pyproject.toml # Dependências e configuração do Poetry
├── ▶️ run_web.sh # Inicializa a versão web
└── 🚀 run_ui.sh # Inicializa a versão desktop
Leia também:
docs/arquitetura-e-uso.md
Os exemplos abaixo foram condensados do USAGE_EXAMPLES.md para facilitar o uso direto pelo README.
python -m uvicorn backend.main:app --host 0.0.0.0 --port 8000 --reloadimport uvicorn
from backend.main import app
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)python -c "from backend.main import app; import uvicorn; uvicorn.run(app, port=8000)"Use sempre os caminhos do pacote backend:
from backend.models import Client, Note
from backend.schemas import ClientResponse, SyncRequest, DashboardStats
from backend.database import get_db, SessionLocal
from backend.main import app
from backend.api.deps import get_nfse_client
from backend.api.state import tasks_statuscurl -X POST "http://localhost:8000/api/clients" \
-F "cnpj=19.495.981/0001-13" \
-F "razao_social=Minha Empresa" \
-F "username=usuario" \
-F "password=senha123" \
-F "description=Cliente de teste"Com certificado:
curl -X POST "http://localhost:8000/api/clients" \
-F "cnpj=19.495.981/0001-13" \
-F "razao_social=Minha Empresa" \
-F "username=usuario" \
-F "password=senha123" \
-F "cert_file=@certificado.pfx"curl "http://localhost:8000/api/clients"curl -X POST "http://localhost:8000/api/sync" \
-H "Content-Type: application/json" \
-d '{
"client_id": 1,
"data_inicio": "01/01/2026",
"data_fim": "31/05/2026",
"tipo": "emitidas"
}'curl "http://localhost:8000/api/tasks/{task_id}"curl "http://localhost:8000/api/analytics/stats?client_id=1"# JSON
curl "http://localhost:8000/api/reports/export?format=json&period=30d" > relatorio.json
# CSV
curl "http://localhost:8000/api/reports/export?format=csv&period=30d" > relatorio.csv
# XLSX
curl "http://localhost:8000/api/reports/export?format=xlsx&period=30d" > relatorio.xlsx- Swagger UI:
http://localhost:8000/docs - ReDoc:
http://localhost:8000/redoc
Para adicionar um novo domínio de negócio:
- criar o arquivo em
backend/api/routers/; - declarar um
APIRoutercom prefixo próprio; - importar e registrar o router em
backend/main.py.
Exemplo mínimo:
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from backend.database import get_db
router = APIRouter(prefix="/api/novo_dominio", tags=["novo_dominio"])
@router.get("/rota-1")
def exemplo(db: Session = Depends(get_db)):
return {"status": "ok"}python -c "from backend.main import app; print('✓ OK')"
curl "http://localhost:8000/openapi.json" | python -m json.tool
pytest tests/ -vpoetry install --with devO projeto não usa requirements.txt; a referência oficial de dependências é o pyproject.toml.
chmod +x run_web.sh
./run_web.shOu, manualmente:
poetry run python -m uvicorn backend.main:app --host 0.0.0.0 --port 8000 --reloadA aplicação ficará disponível em:
http://localhost:8000- documentação automática da API em
http://localhost:8000/docs - alternativa em
http://localhost:8000/redoc
chmod +x run_ui.sh
./run_ui.shO script entra na pasta ui/ e chama o fluxo de desenvolvimento do Tauri.
O backend principal está em backend/main.py e:
- inicializa o banco com
init_db(); - registra os routers da API;
- monta a pasta
frontend/na raiz da aplicação; - aplica CORS liberado para facilitar o uso local.
backend/api/routers/clients.py— CRUD de clientes.backend/api/routers/notes.py— sincronização e listagem de notas.backend/api/routers/downloads.py— download de arquivos e lote ZIP.backend/api/routers/analytics.py— estatísticas e gráficos.backend/api/routers/reports.py— exportação de relatórios.backend/api/routers/system.py— suporte, update check e navegação de pastas.
GET /api/clientsPOST /api/clientsPUT /api/clients/{client_id}DELETE /api/clients/{client_id}
POST /api/syncGET /api/tasks/{task_id}GET /api/notes
POST /api/download/sync-portalGET /api/download/file?path=...POST /api/download/batch
GET /api/analytics/statsGET /api/analytics/chartPOST /api/analytics/enrich-xmlGET /api/analytics/ranking
GET /api/reports/export?format=json|csv|xlsx
POST /api/support/messageGET /api/system/check-updateGET /api/system/list-folders
Guarda credenciais e configuração de cada cliente:
- CNPJ
- razão social
- usuário/senha do portal
- certificado A1 opcional
- caminho base de salvamento
- estrutura personalizada de diretórios
Guarda as notas sincronizadas:
- identificador interno
- cliente vinculado
- chave da nota
- número
- status
- tipo (
emitidas/recebidas) - valor
- caminhos do XML e PDF
- URLs de download do portal
- Abrir a aplicação web ou desktop.
- Cadastrar um cliente na área de clientes.
- Sincronizar notas por período.
- Baixar XML/PDF quando necessário.
- Gerar relatórios ou acompanhar o dashboard.
- Datas de filtro e sincronização usam o formato
DD/MM/AAAA. - O progresso das tarefas é guardado em memória; reiniciar o processo limpa o status.
- O sistema depende da estrutura atual do portal de NFSe; mudanças no HTML podem exigir ajustes.
- Os arquivos baixados seguem a estrutura configurada por cliente.
ModuleNotFoundError: No module named 'backend': execute os comandos a partir da raiz do projeto.- Porta já em uso: altere a porta no comando do Uvicorn.
- Banco não encontrado: o arquivo
nfse.dbé criado automaticamente ao inicializar a aplicação. - Se estiver importando módulos antigos, troque por
backend.models,backend.schemasebackend.database.
./run_web.sh # sobe a API + frontend
./run_ui.sh # inicia o desktop Tauribackend/
├── 🚪 main.py # inicia a API e serve o frontend
├── 🗄️ database.py # engine, sessão e get_db()
├── 🧱 models.py # Client, Note e init_db()
├── 🧾 schemas.py # modelos Pydantic
└── api/
├── 🔌 deps.py # cliente NFSe a partir do banco
├── 🧠 state.py # status de tarefas em memória
└── routers/
├── 👥 clients.py
├── 📝 notes.py
├── ⬇️ downloads.py
├── 📊 analytics.py
├── 📤 reports.py
└── ⚙️ system.py
| Área | Arquivo | Função |
|---|---|---|
| API principal | backend/main.py |
Sobe o FastAPI e monta o frontend |
| Banco | backend/database.py |
Conexão SQLite e sessão SQLAlchemy |
| Modelos | backend/models.py |
Tabelas Client e Note |
| Schemas | backend/schemas.py |
Validação de dados |
| Clientes | backend/api/routers/clients.py |
CRUD de clientes |
| Notas | backend/api/routers/notes.py |
Sincronização e listagem |
| Downloads | backend/api/routers/downloads.py |
Baixa arquivos e gera ZIP |
| Analytics | backend/api/routers/analytics.py |
Estatísticas e ranking |
| Relatórios | backend/api/routers/reports.py |
Exportação JSON/CSV/XLSX |
| Sistema | backend/api/routers/system.py |
Update, suporte e pastas |
Contribuições, melhorias e correções são bem-vindas.
Cleiton Leonel Creton — cleiton.leonel@gmail.com