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 fastapi.responses import StreamingResponse from io import BytesIO import pandas as pd from sqlalchemy.future import select from database import AsyncSessionLocal from models import Fatura from processor import ( fila_processamento, processar_em_lote, status_arquivos, limpar_arquivos_processados ) app = FastAPI() templates = Jinja2Templates(directory="templates") app.mount("/static", StaticFiles(directory="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): return templates.TemplateResponse("upload.html", {"request": request}) @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}) @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(): files.append({ "nome": nome, "status": status, "mensagem": "---" if status == "Concluído" else status }) 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"} )