Atualiza exibição do tempo por processo e garante consistência da estrutura em app/
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -3,13 +3,14 @@ import os
|
||||
import shutil
|
||||
import asyncio
|
||||
from sqlalchemy.future import select
|
||||
from utils import extrair_dados_pdf
|
||||
from database import AsyncSessionLocal
|
||||
from models import Fatura, LogProcessamento
|
||||
from app.utils import extrair_dados_pdf
|
||||
from app.database import AsyncSessionLocal
|
||||
from app.models import Fatura, LogProcessamento
|
||||
import time
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
UPLOADS_DIR = os.path.join(os.getcwd(), "uploads")
|
||||
UPLOADS_DIR = os.path.join("app", "uploads")
|
||||
TEMP_DIR = os.path.join(UPLOADS_DIR, "temp")
|
||||
|
||||
fila_processamento = asyncio.Queue()
|
||||
@@ -35,56 +36,92 @@ def salvar_em_uploads(caminho_pdf_temp, nome_original, nota_fiscal):
|
||||
return caminho_pdf_temp
|
||||
|
||||
async def process_single_file(caminho_pdf_temp: str, nome_original: str):
|
||||
inicio = time.perf_counter()
|
||||
|
||||
async with AsyncSessionLocal() as session:
|
||||
try:
|
||||
dados = extrair_dados_pdf(caminho_pdf_temp)
|
||||
dados['arquivo_pdf'] = nome_original
|
||||
|
||||
# Verifica se a fatura já existe
|
||||
existente_result = await session.execute(
|
||||
select(Fatura).filter_by(nota_fiscal=dados['nota_fiscal'], unidade_consumidora=dados['unidade_consumidora'])
|
||||
select(Fatura).filter_by(
|
||||
nota_fiscal=dados['nota_fiscal'],
|
||||
unidade_consumidora=dados['unidade_consumidora']
|
||||
)
|
||||
)
|
||||
if existente_result.scalar_one_or_none():
|
||||
duracao = round(time.perf_counter() - inicio, 2)
|
||||
remover_arquivo_temp(caminho_pdf_temp)
|
||||
return {"status": "Duplicado", "dados": dados}
|
||||
return {
|
||||
"status": "Duplicado",
|
||||
"dados": dados,
|
||||
"tempo": f"{duracao}s"
|
||||
}
|
||||
|
||||
# Salva arquivo final
|
||||
caminho_final = salvar_em_uploads(caminho_pdf_temp, nome_original, dados['nota_fiscal'])
|
||||
dados['link_arquivo'] = caminho_final
|
||||
|
||||
|
||||
# Salva fatura
|
||||
fatura = Fatura(**dados)
|
||||
session.add(fatura)
|
||||
|
||||
session.add(LogProcessamento(
|
||||
status="Sucesso",
|
||||
mensagem="Fatura processada com sucesso",
|
||||
nome_arquivo=nome_original,
|
||||
acao="PROCESSAMENTO"
|
||||
))
|
||||
|
||||
await session.commit()
|
||||
remover_arquivo_temp(caminho_pdf_temp)
|
||||
return {"status": "Concluído", "dados": dados}
|
||||
duracao = round(time.perf_counter() - inicio, 2)
|
||||
|
||||
return {
|
||||
"status": "Concluído",
|
||||
"dados": dados,
|
||||
"tempo": f"{duracao}s"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
erro_str = traceback.format_exc()
|
||||
duracao = round(time.perf_counter() - inicio, 2)
|
||||
await session.rollback()
|
||||
session.add(LogProcessamento(
|
||||
status="Erro",
|
||||
mensagem=str(e),
|
||||
nome_arquivo=nome_original,
|
||||
acao="PROCESSAMENTO"
|
||||
))
|
||||
await session.commit()
|
||||
logger.error(f"Erro ao processar fatura: {e}", exc_info=True)
|
||||
remover_arquivo_temp(caminho_pdf_temp)
|
||||
return {"status": "Erro", "mensagem": str(e)}
|
||||
|
||||
print(f"\n📄 ERRO no arquivo: {nome_original}")
|
||||
print(f"⏱ Tempo até erro: {duracao}s")
|
||||
print(f"❌ Erro detalhado:\n{erro_str}")
|
||||
|
||||
return {
|
||||
"status": "Erro",
|
||||
"mensagem": str(e),
|
||||
"tempo": f"{duracao}s",
|
||||
"trace": erro_str
|
||||
}
|
||||
|
||||
|
||||
async def processar_em_lote():
|
||||
import traceback # para exibir erros
|
||||
resultados = []
|
||||
while not fila_processamento.empty():
|
||||
item = await fila_processamento.get()
|
||||
resultado = await process_single_file(item['caminho_pdf'], item['nome_original'])
|
||||
status_arquivos[item['nome_original']] = resultado.get("status", "Erro")
|
||||
resultados.append(resultado)
|
||||
try:
|
||||
resultado = await process_single_file(item['caminho_pdf'], item['nome_original'])
|
||||
status_arquivos[item['nome_original']] = {
|
||||
"status": resultado.get("status"),
|
||||
"mensagem": resultado.get("mensagem", ""),
|
||||
"tempo": resultado.get("tempo", "---")
|
||||
}
|
||||
resultados.append(status_arquivos[item['nome_original']])
|
||||
except Exception as e:
|
||||
status_arquivos[item['nome_original']] = {
|
||||
"status": "Erro",
|
||||
"mensagem": str(e),
|
||||
"tempo": "---"
|
||||
}
|
||||
|
||||
resultados.append({
|
||||
"nome": item['nome_original'],
|
||||
"status": "Erro",
|
||||
"mensagem": str(e)
|
||||
})
|
||||
print(f"Erro ao processar {item['nome_original']}: {e}")
|
||||
print(traceback.format_exc())
|
||||
return resultados
|
||||
|
||||
def limpar_arquivos_processados():
|
||||
|
||||
Reference in New Issue
Block a user