|
|
import os |
|
|
import re |
|
|
from datetime import datetime |
|
|
from typing import List |
|
|
|
|
|
import streamlit as st |
|
|
from pypdf import PdfReader |
|
|
|
|
|
from reportlab.lib.pagesizes import A4 |
|
|
from reportlab.pdfgen import canvas |
|
|
from reportlab.lib.units import mm |
|
|
|
|
|
|
|
|
KEY_RE = re.compile(r"\b\d{44}\b") |
|
|
|
|
|
|
|
|
def extract_keys_from_pdf(pdf_path: str) -> List[str]: |
|
|
reader = PdfReader(pdf_path) |
|
|
found: List[str] = [] |
|
|
seen = set() |
|
|
|
|
|
for page in reader.pages: |
|
|
text = page.extract_text() or "" |
|
|
for k in KEY_RE.findall(text): |
|
|
if k not in seen: |
|
|
seen.add(k) |
|
|
found.append(k) |
|
|
|
|
|
return found |
|
|
|
|
|
|
|
|
def safe_date_default() -> str: |
|
|
return datetime.now().strftime("%d/%m/%Y") |
|
|
|
|
|
|
|
|
def normalize_hora(hora_input: str) -> str: |
|
|
if not hora_input: |
|
|
return "_____ : _____" |
|
|
s = hora_input.strip() |
|
|
if s in {"_____:_____", "_____ : _____", "____ : ____"}: |
|
|
return "_____ : _____" |
|
|
return s |
|
|
|
|
|
|
|
|
def render_print_pdf(out_path: str, data_coleta: str, hora_coleta: str, keys: List[str]): |
|
|
c = canvas.Canvas(out_path, pagesize=A4) |
|
|
_, h = A4 |
|
|
|
|
|
left = 20 * mm |
|
|
top = h - 20 * mm |
|
|
line_h = 6.2 * mm |
|
|
|
|
|
def draw(text: str, y: float, size=11, bold=False) -> float: |
|
|
c.setFont("Helvetica-Bold" if bold else "Helvetica", size) |
|
|
c.drawString(left, y, text) |
|
|
return y - line_h |
|
|
|
|
|
y = top |
|
|
|
|
|
|
|
|
y = draw("CLIENTE:", y) |
|
|
y -= line_h * 1.3 |
|
|
|
|
|
y = draw("DATA DA COLETA:", y) |
|
|
y = draw(data_coleta, y) |
|
|
y -= line_h * 0.6 |
|
|
|
|
|
y = draw("HORA DA COLETA:", y) |
|
|
y = draw(hora_coleta, y) |
|
|
y -= line_h * 0.9 |
|
|
|
|
|
|
|
|
y = draw("CHAVES DE ACESSO:", y) |
|
|
y -= line_h * 0.2 |
|
|
|
|
|
c.setFont("Helvetica", 10.8) |
|
|
for k in keys: |
|
|
if y < 40 * mm: |
|
|
c.showPage() |
|
|
y = top |
|
|
c.setFont("Helvetica", 10.8) |
|
|
c.drawString(left, y, k) |
|
|
y -= line_h * 0.85 |
|
|
|
|
|
y -= line_h * 0.8 |
|
|
y = draw(f"TOTAL DA REMESSA: {len(keys)} VOLUMES", y) |
|
|
|
|
|
|
|
|
if y < 55 * mm: |
|
|
c.showPage() |
|
|
|
|
|
y_sig = 25 * mm |
|
|
c.setFont("Helvetica", 9.5) |
|
|
c.drawString(left + 70 * mm, y_sig + 12, "ASSINATURA DO REPRESENTANTE") |
|
|
c.drawString(left + 140 * mm, y_sig + 12, "ASSINATURA DO MOTORISTA") |
|
|
c.line(left + 55 * mm, y_sig + 10, left + 118 * mm, y_sig + 10) |
|
|
c.line(left + 130 * mm, y_sig + 10, left + 193 * mm, y_sig + 10) |
|
|
|
|
|
c.save() |
|
|
|
|
|
|
|
|
st.set_page_config(page_title="Extrator de Chaves NF-e", layout="centered") |
|
|
st.title("Extrator de Chaves NF-e (PDF → PDF para imprimir)") |
|
|
|
|
|
pdf = st.file_uploader("Envie o PDF", type=["pdf"]) |
|
|
data_coleta = st.text_input("Data da coleta", value=safe_date_default()) |
|
|
hora_coleta = st.text_input("Hora da coleta", value="_____ : _____") |
|
|
|
|
|
if pdf is not None: |
|
|
st.caption(f"Arquivo: {pdf.name}") |
|
|
|
|
|
if st.button("Gerar arquivos", disabled=(pdf is None)): |
|
|
tmp_in = os.path.join("/tmp", f"entrada_{datetime.now().strftime('%Y%m%d-%H%M%S')}.pdf") |
|
|
with open(tmp_in, "wb") as f: |
|
|
f.write(pdf.read()) |
|
|
|
|
|
keys = extract_keys_from_pdf(tmp_in) |
|
|
if not keys: |
|
|
st.error("Não encontrei chaves de acesso (44 dígitos) no PDF.") |
|
|
st.stop() |
|
|
|
|
|
data_coleta = (data_coleta or safe_date_default()).strip() |
|
|
hora_coleta_norm = normalize_hora(hora_coleta) |
|
|
|
|
|
ts = datetime.now().strftime("%Y%m%d-%H%M%S") |
|
|
out_pdf = os.path.join("/tmp", f"chaves_prontas_{ts}.pdf") |
|
|
out_txt = os.path.join("/tmp", f"chaves_{ts}.txt") |
|
|
|
|
|
render_print_pdf(out_pdf, data_coleta, hora_coleta_norm, keys) |
|
|
|
|
|
with open(out_txt, "w", encoding="utf-8") as f: |
|
|
f.write("\n".join(keys) + "\n") |
|
|
|
|
|
st.success(f"{len(keys)} chaves encontradas.") |
|
|
|
|
|
with open(out_pdf, "rb") as f: |
|
|
st.download_button( |
|
|
"Baixar PDF pronto para imprimir", |
|
|
data=f, |
|
|
file_name=os.path.basename(out_pdf), |
|
|
mime="application/pdf", |
|
|
) |
|
|
|
|
|
with open(out_txt, "rb") as f: |
|
|
st.download_button( |
|
|
"Baixar TXT (opcional)", |
|
|
data=f, |
|
|
file_name=os.path.basename(out_txt), |
|
|
mime="text/plain", |
|
|
) |
|
|
|
|
|
st.text_area("Prévia (primeiras 10 chaves)", value="\n".join(keys[:10]), height=200) |
|
|
|