C

Kit PDF Completo · NutriPlan SaaS

Automatizacion de informes mensuales · CULTIVA IA

manipulacion-pdf-completa Python · v1.0 Apache-2.0

NutriPlan — Automatizacion de Informes PDF

SaaS B2B de planificacion nutricional · Mayo 2026 · Cliente Growth 47 €/mes

Problema: 6 h/mes manuales 12 clinicas activas ~200 PDF/mes
99 €
ahorro mensual estimado
5.5 h × 18 €/h
Pipeline de automatizacion
01
Leer CSV
Importar datos de pacientes desde exportacion de BBDD
pandas
02
Crear PDF
Generar informe por clinica con portada, tabla y KPIs
reportlab
03
Fusionar
Combinar informes parciales en un solo PDF mensual
pypdf
04
Proteger
Cifrar con contrasena unica por clinica antes de enviar
pypdf
05
Extraer tablas
Parsear facturas de proveedores para conciliacion
pdfplumber
200
PDFs generados / mes
antes: 100% manual
<30s
tiempo total del pipeline
vs 6 horas manuales
5
librerias necesarias
pypdf · pdfplumber · reportlab · pandas · pytesseract
Scripts de produccion
generar_informe.py CREAR PDF
# NutriPlan — Generador de informes mensuales
from reportlab.lib.pagesizes import A4
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Table,
    TableStyle, Spacer
)
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet
import pandas as pd
from datetime import datetime

def crear_informe_clinica(csv_path, clinica, mes):
    df = pd.read_csv(csv_path)
    df_clinica = df[df['clinica'] == clinica]

    doc = SimpleDocTemplate(
        f"informes/{clinica}_{mes}.pdf",
        pagesize=A4, topMargin=36
    )
    styles = getSampleStyleSheet()
    story = []

    # Portada
    story.append(Paragraph(
        f"Informe NutriPlan — {mes}",
        styles['Title']
    ))
    story.append(Paragraph(
        clinica, styles['Heading2']
    ))
    story.append(Spacer(1, 20))

    # Tabla de pacientes
    data = [['Paciente','Objetivo','Adherencia','Delta']]
    for _, row in df_clinica.iterrows():
        data.append([
            row['nombre'], row['objetivo'],
            f"{row['adherencia']}%",
            f"{row['delta_kg']:+.1f} kg"
        ])

    t = Table(data, colWidths=[160,80,80,70])
    t.setStyle(TableStyle([
        ('BACKGROUND',(0,0),(-1,0),colors.HexColor('#2563eb')),
        ('TEXTCOLOR',(0,0),(-1,0),colors.white),
        ('ROWBACKGROUNDS',(0,1),(-1,-1),
            [colors.white, colors.HexColor('#f0f9ff')])
    ]))
    story.append(t)
    doc.build(story)
    return f"informes/{clinica}_{mes}.pdf"
fusionar_proteger.py MERGE + ENCRYPT
# Fusionar parciales y cifrar con contraseña
from pypdf import PdfWriter, PdfReader
from pathlib import Path
import secrets, json

def fusionar_pdfs(archivos: list[str], salida: str):
    """Une varios PDFs en uno."""
    writer = PdfWriter()
    for archivo in archivos:
        reader = PdfReader(archivo)
        for page in reader.pages:
            writer.add_page(page)
    with open(salida, 'wb') as f:
        writer.write(f)
    return salida

def cifrar_pdf(entrada: str, clinica_id: str) -> dict:
    """Cifra PDF y devuelve ruta + contraseña."""
    password = secrets.token_urlsafe(12)
    salida = entrada.replace('.pdf', '_secure.pdf')

    reader = PdfReader(entrada)
    writer = PdfWriter()
    for page in reader.pages:
        writer.add_page(page)
    writer.encrypt(password, algorithm="AES-256")

    with open(salida, 'wb') as f:
        writer.write(f)

    # Guardar contraseña de forma segura
    credentials = json.load(open('credentials.json'))
    credentials[clinica_id] = {
        'pdf': salida, 'pwd': password,
        'generado': datetime.now().isoformat()
    }
    json.dump(credentials, open('credentials.json','w'))
    return {'archivo': salida, 'password': password}

# Uso en produccion
if __name__ == '__main__':
    clinicas = ['centro-salud-mediterraneo',
                'clinica-bienestar-norte']
    for c in clinicas:
        pdf = fusionar_pdfs(
            [f"informes/{c}_parcial_{i}.pdf"
             for i in range(1,4)],
            f"output/{c}_mayo2026.pdf"
        )
        resultado = cifrar_pdf(pdf, c)
        print(f"✓ {c}: {resultado['archivo']}")
extraer_facturas.py EXTRACT TABLES
# Conciliacion automatica de facturas PDF
import pdfplumber
import pandas as pd
from pathlib import Path

def extraer_tablas_factura(pdf_path: str) -> pd.DataFrame:
    """Extrae todas las tablas de un PDF de factura."""
    tablas = []
    with pdfplumber.open(pdf_path) as pdf:
        for n_pag, pag in enumerate(pdf.pages, 1):
            for tabla in pag.extract_tables():
                if tabla and len(tabla) > 1:
                    df = pd.DataFrame(
                        tabla[1:],
                        columns=tabla[0]
                    )
                    df['fuente_pdf'] = Path(pdf_path).stem
                    df['pagina'] = n_pag
                    tablas.append(df)
    return pd.concat(tablas, ignore_index=True) if tablas else pd.DataFrame()

def conciliar_facturas(carpeta: str) -> None:
    """Procesa todos los PDFs de una carpeta."""
    pdfs = list(Path(carpeta).glob('*.pdf'))
    print(f"Procesando {len(pdfs)} facturas...")

    resultados = []
    for pdf in pdfs:
        try:
            df = extraer_tablas_factura(str(pdf))
            resultados.append(df)
            print(f"  ✓ {pdf.name}: {len(df)} filas")
        except Exception as e:
            print(f"  ✗ {pdf.name}: {e}")

    combined = pd.concat(resultados, ignore_index=True)
    combined.to_excel(
        "conciliacion_mayo2026.xlsx",
        index=False, sheet_name="Facturas"
    )
    print(f"\n✅ Excel generado: {len(combined)} filas totales")
ocr_escaneados.py OCR
# OCR para PDFs escaneados (ej. analíticas antiguas)
import pytesseract
from pdf2image import convert_from_path
from PIL import Image
import re

def ocr_pdf(pdf_path: str, idioma: str = 'spa') -> str:
    """Extrae texto de PDF escaneado via OCR."""
    imagenes = convert_from_path(
        pdf_path,
        dpi=300,      # Alta resolución = mejor OCR
        thread_count=4   # Paralelizar conversión
    )
    texto_completo = []
    for i, img in enumerate(imagenes, 1):
        # Preprocesar: escala grises + contraste
        img_gray = img.convert('L')
        texto = pytesseract.image_to_string(
            img_gray, lang=idioma,
            config='--psm 6'   # Asumir bloque de texto
        )
        texto_completo.append(f"\n--- Página {i} ---\n{texto}")
    return "\n".join(texto_completo)

def extraer_valores(texto: str) -> dict:
    """Parsea texto OCR buscando métricas de salud."""
    patrones = {
        'peso':    r'Peso[:\s]+(\d+\.?\d*)\s*kg',
        'imc':     r'IMC[:\s]+(\d+\.?\d*)',
        'glucosa': r'Glucosa[:\s]+(\d+)\s*mg',
    }
    return {
        k: re.search(v, texto, re.I).group(1)
        if re.search(v, texto, re.I) else None
        for k, v in patrones.items()
    }
Muestra de datos — Centro Salud Mediterraneo (Mayo 2026)
# Paciente Objetivo Adherencia al plan Delta peso Estado
01 Ana Torres Perdida de peso
94%
-2.4 kg En objetivo
02 Carlos Medina Control glucemico
87%
-1.1 kg En objetivo
03 Maria Ruiz Ganancia muscular
71%
+0.3 kg Seguimiento
04 Pedro Alonso Perdida de peso
58%
+0.8 kg Alerta
05 Sofia Navarro Colesterol
96%
-1.9 kg En objetivo
06 Luis Garcia Mantenimiento
83%
+0.1 kg En objetivo
Referencia rapida de operaciones
📄
Leer PDF
pypdf · PdfReader
Extrae texto, metadatos y paginas de cualquier PDF digital.
✏️
Crear PDF
reportlab · Platypus
Genera documentos con tablas, imagenes, graficos y estilos.
🔗
Fusionar
pypdf · PdfWriter
Une multiples PDFs en uno solo en segundos.
✂️
Dividir
pypdf / qpdf
Separa paginas o rangos concretos en archivos independientes.
📊
Extraer tablas
pdfplumber
Parsea tablas a DataFrames listos para Excel o BBDD.
🔍
OCR
pytesseract + pdf2image
Digitaliza PDFs escaneados con reconocimiento de texto.
📝
Rellenar formularios
pypdf / pdf-lib (JS)
Rellena campos de PDFs interactivos desde datos estructurados.
🔒
Cifrar
pypdf AES-256
Protege PDFs con contrasena unica por destinatario.
Instalacion
setup.sh
# Instalar todas las dependencias Python
pip install pypdf pdfplumber reportlab pytesseract pdf2image pandas openpyxl

# macOS: herramientas CLI + Tesseract OCR
brew install poppler qpdf tesseract tesseract-lang

# Verificar instalacion
python -c "import pypdf, pdfplumber, reportlab; print('✅ Listo')"