From e9ed45ba2189cd01827379d05f130ea764b2be12 Mon Sep 17 00:00:00 2001 From: "ewerton.almeida" Date: Tue, 29 Jul 2025 14:10:14 -0300 Subject: [PATCH] =?UTF-8?q?Ajustes=20gerais:=20overlay=20visual,=20valida?= =?UTF-8?q?=C3=A7=C3=A3o=20por=20banco=20e=20limpeza=20segura=20em=20homol?= =?UTF-8?q?oga=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/main.py | 45 +++++++++++++- app/processor.py | 3 +- app/templates/upload.html | 120 +++++++++++++++++++++++++++++++------- 3 files changed, 142 insertions(+), 26 deletions(-) diff --git a/app/main.py b/app/main.py index f23af4c..2dd3e77 100644 --- a/app/main.py +++ b/app/main.py @@ -4,9 +4,12 @@ from fastapi.templating import Jinja2Templates from fastapi.responses import HTMLResponse, JSONResponse from fastapi.staticfiles import StaticFiles import os, shutil +from sqlalchemy import text +from fastapi import Depends from fastapi.responses import StreamingResponse from io import BytesIO import pandas as pd +from app.models import ParametrosFormula from sqlalchemy.future import select from app.database import AsyncSessionLocal from app.models import Fatura @@ -16,6 +19,7 @@ from app.processor import ( status_arquivos, limpar_arquivos_processados ) +from app.parametros import router as parametros_router app = FastAPI() templates = Jinja2Templates(directory="app/templates") @@ -47,15 +51,25 @@ def dashboard(request: Request): @app.get("/upload", response_class=HTMLResponse) def upload_page(request: Request): - return templates.TemplateResponse("upload.html", {"request": request}) + app_env = os.getenv("APP_ENV", "dev") # Captura variável de ambiente + return templates.TemplateResponse("upload.html", { + "request": request, + "app_env": app_env # Passa para o template + }) @app.get("/relatorios", response_class=HTMLResponse) def relatorios_page(request: Request): return templates.TemplateResponse("relatorios.html", {"request": request}) @app.get("/parametros", response_class=HTMLResponse) -def parametros_page(request: Request): - return templates.TemplateResponse("parametros.html", {"request": request}) +async def parametros_page(request: Request): + async with AsyncSessionLocal() as session: + result = await session.execute(select(ParametrosFormula)) + parametros = result.scalars().first() + return templates.TemplateResponse("parametros.html", { + "request": request, + "parametros": parametros or {} + }) @app.post("/upload-files") async def upload_files(files: list[UploadFile] = File(...)): @@ -144,3 +158,28 @@ async def export_excel(): media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", headers={"Content-Disposition": "attachment; filename=relatorio_faturas.xlsx"} ) + +from app.parametros import router as parametros_router +app.include_router(parametros_router) + +def is_homolog(): + return os.getenv("APP_ENV", "dev") == "homolog" + +@app.post("/limpar-faturas") +async def limpar_faturas(): + app_env = os.getenv("APP_ENV", "dev") + if app_env not in ["homolog", "dev", "local"]: + return JSONResponse(status_code=403, content={"message": "Operação não permitida neste ambiente."}) + + async with AsyncSessionLocal() as session: + print("🧪 Limpando faturas do banco...") + await session.execute(text("DELETE FROM faturas.faturas")) + await session.commit() + + upload_path = os.path.join("app", "uploads") + for nome in os.listdir(upload_path): + caminho = os.path.join(upload_path, nome) + if os.path.isfile(caminho): + os.remove(caminho) + + return {"message": "Faturas e arquivos apagados com sucesso."} \ No newline at end of file diff --git a/app/processor.py b/app/processor.py index c4c03c1..f01c0b9 100644 --- a/app/processor.py +++ b/app/processor.py @@ -8,6 +8,7 @@ from app.database import AsyncSessionLocal from app.models import Fatura, LogProcessamento import time import traceback +import uuid logger = logging.getLogger(__name__) @@ -29,7 +30,7 @@ def remover_arquivo_temp(caminho_pdf): def salvar_em_uploads(caminho_pdf_temp, nome_original, nota_fiscal): try: extensao = os.path.splitext(nome_original)[1].lower() - nome_destino = f"{nota_fiscal}{extensao}" + nome_destino = f"{nota_fiscal}_{uuid.uuid4().hex[:6]}{extensao}" destino_final = os.path.join(UPLOADS_DIR, nome_destino) shutil.copy2(caminho_pdf_temp, destino_final) return destino_final diff --git a/app/templates/upload.html b/app/templates/upload.html index f80fed9..f7f730b 100755 --- a/app/templates/upload.html +++ b/app/templates/upload.html @@ -17,8 +17,12 @@ + {% if app_env != "producao" %} + + {% endif %} + @@ -124,38 +128,54 @@ function renderTable(statusList = []) { window.open('/generate-report', '_blank'); } - const dropZone = document.body; - dropZone.addEventListener('dragover', (e) => { - e.preventDefault(); - dropZone.classList.add('dragover'); +window.addEventListener('DOMContentLoaded', () => { + updateStatus(); + + const dragOverlay = document.getElementById("drag-overlay"); + let dragCounter = 0; + + window.addEventListener("dragenter", e => { + dragCounter++; + dragOverlay.classList.add("active"); }); - dropZone.addEventListener('dragleave', () => { - dropZone.classList.remove('dragover'); + + window.addEventListener("dragleave", e => { + dragCounter--; + if (dragCounter <= 0) { + dragOverlay.classList.remove("active"); + dragCounter = 0; + } }); - dropZone.addEventListener('drop', (e) => { + + window.addEventListener("dragover", e => { e.preventDefault(); - dropZone.classList.remove('dragover'); + }); + + window.addEventListener("drop", e => { + e.preventDefault(); + dragOverlay.classList.remove("active"); + dragCounter = 0; handleFiles(e.dataTransfer.files); }); +}); - window.addEventListener('DOMContentLoaded', updateStatus); - // Adiciona destaque visual à caixa ao arrastar arquivos na tela toda - window.addEventListener('dragover', (e) => { - e.preventDefault(); - document.getElementById('upload-box').classList.add('dragover'); - }); +async function limparFaturas() { + if (!confirm("Deseja realmente limpar todas as faturas e arquivos (somente homologação)?")) return; - window.addEventListener('dragleave', () => { - document.getElementById('upload-box').classList.remove('dragover'); - }); + const res = await fetch("/limpar-faturas", { method: "POST" }); + const data = await res.json(); + alert(data.message || "Concluído"); + updateStatus(); // atualiza visual +} - window.addEventListener('drop', (e) => { - e.preventDefault(); - document.getElementById('upload-box').classList.remove('dragover'); - handleFiles(e.dataTransfer.files); - }); +window.addEventListener("dragover", e => { + e.preventDefault(); +}); +window.addEventListener("drop", e => { + e.preventDefault(); +}); +
+
+ + + +

Solte os arquivos para enviar

+
+
+ {% endblock %} \ No newline at end of file