import uuid from fastapi import FastAPI, Request, UploadFile, File 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 from app.processor import ( fila_processamento, processar_em_lote, status_arquivos, limpar_arquivos_processados ) from app.parametros import router as parametros_router app = FastAPI() templates = Jinja2Templates(directory="app/templates") app.mount("/static", StaticFiles(directory="app/static"), name="static") UPLOAD_DIR = "uploads/temp" os.makedirs(UPLOAD_DIR, exist_ok=True) @app.get("/", response_class=HTMLResponse) def dashboard(request: Request): indicadores = [ {"titulo": "Total de Faturas", "valor": 124}, {"titulo": "Faturas com ICMS", "valor": "63%"}, {"titulo": "Valor Total", "valor": "R$ 280.000,00"}, ] analise_stf = { "antes": {"percentual_com_icms": 80, "media_valor": 1200}, "depois": {"percentual_com_icms": 20, "media_valor": 800}, } return templates.TemplateResponse("dashboard.html", { "request": request, "cliente_atual": "", "clientes": ["Cliente A", "Cliente B"], "indicadores": indicadores, "analise_stf": analise_stf }) @app.get("/upload", response_class=HTMLResponse) def upload_page(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) 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(...)): for file in files: temp_path = os.path.join(UPLOAD_DIR, f"{uuid.uuid4()}_{file.filename}") with open(temp_path, "wb") as f: shutil.copyfileobj(file.file, f) await fila_processamento.put({ "caminho_pdf": temp_path, "nome_original": file.filename }) return {"message": "Arquivos enviados para fila"} @app.post("/process-queue") async def process_queue(): resultados = await processar_em_lote() return {"message": "Processamento concluído", "resultados": resultados} @app.get("/get-status") async def get_status(): files = [] for nome, status in status_arquivos.items(): if isinstance(status, dict): files.append({ "nome": nome, "status": status.get("status", "Erro"), "mensagem": status.get("mensagem", "---"), "tempo": status.get("tempo", "---") # ✅ AQUI }) else: files.append({ "nome": nome, "status": status, "mensagem": "---" if status == "Concluído" else status, "tempo": "---" # ✅ AQUI também }) is_processing = not fila_processamento.empty() return JSONResponse(content={"is_processing": is_processing, "files": files}) @app.post("/clear-all") async def clear_all(): limpar_arquivos_processados() for f in os.listdir(UPLOAD_DIR): os.remove(os.path.join(UPLOAD_DIR, f)) return {"message": "Fila e arquivos limpos"} @app.get("/export-excel") async def export_excel(): async with AsyncSessionLocal() as session: result = await session.execute(select(Fatura)) faturas = result.scalars().all() dados = [] for f in faturas: dados.append({ "Nome": f.nome, "UC": f.unidade_consumidora, "Referência": f.referencia, "Nota Fiscal": f.nota_fiscal, "Valor Total": f.valor_total, "ICMS (%)": f.icms_aliq, "ICMS (R$)": f.icms_valor, "Base ICMS": f.icms_base, "PIS (%)": f.pis_aliq, "PIS (R$)": f.pis_valor, "Base PIS": f.pis_base, "COFINS (%)": f.cofins_aliq, "COFINS (R$)": f.cofins_valor, "Base COFINS": f.cofins_base, "Consumo (kWh)": f.consumo, "Tarifa": f.tarifa, "Cidade": f.cidade, "Estado": f.estado, "Distribuidora": f.distribuidora, "Data Processamento": f.data_processamento, }) df = pd.DataFrame(dados) output = BytesIO() df.to_excel(output, index=False, sheet_name="Faturas") output.seek(0) return StreamingResponse( output, 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."}