Refactorizacion de PDFs y cambio de biblioteca backend 1.0.18
This commit is contained in:
@@ -34,7 +34,18 @@ from app import models, schemas
|
|||||||
# Crear tablas
|
# Crear tablas
|
||||||
Base.metadata.create_all(bind=engine)
|
Base.metadata.create_all(bind=engine)
|
||||||
|
|
||||||
app = FastAPI(title="Checklist Inteligente API", version="1.0.0")
|
BACKEND_VERSION = "1.0.17"
|
||||||
|
app = FastAPI(title="Checklist Inteligente API", version=BACKEND_VERSION)
|
||||||
|
|
||||||
|
# Información visual al iniciar el backend
|
||||||
|
import sys
|
||||||
|
from app.core import config as app_config
|
||||||
|
print("\n================ BACKEND STARTUP INFO ================")
|
||||||
|
print(f"Backend version: {BACKEND_VERSION}")
|
||||||
|
print(f"Database URL: {app_config.settings.DATABASE_URL}")
|
||||||
|
print(f"Environment: {app_config.settings.ENVIRONMENT}")
|
||||||
|
print(f"MinIO endpoint: {app_config.MINIO_ENDPOINT}")
|
||||||
|
print("====================================================\n", flush=True)
|
||||||
|
|
||||||
# CORS
|
# CORS
|
||||||
app.add_middleware(
|
app.add_middleware(
|
||||||
@@ -1694,12 +1705,74 @@ def export_inspection_to_pdf(
|
|||||||
doc = SimpleDocTemplate(buffer, pagesize=A4, rightMargin=30, leftMargin=30, topMargin=30, bottomMargin=30)
|
doc = SimpleDocTemplate(buffer, pagesize=A4, rightMargin=30, leftMargin=30, topMargin=30, bottomMargin=30)
|
||||||
elements = []
|
elements = []
|
||||||
styles = getSampleStyleSheet()
|
styles = getSampleStyleSheet()
|
||||||
# ...existing code for PDF generation...
|
title_style = styles['Title']
|
||||||
doc.build(elements)
|
normal_style = styles['Normal']
|
||||||
|
header_style = ParagraphStyle('Header', parent=styles['Heading2'], alignment=TA_CENTER, spaceAfter=12)
|
||||||
|
# Portada
|
||||||
|
elements.append(Paragraph(f"Informe de Inspección #{inspection.id}", title_style))
|
||||||
|
elements.append(Spacer(1, 12))
|
||||||
|
elements.append(Paragraph(f"Vehículo: {inspection.vehicle_brand or ''} {inspection.vehicle_model or ''} - Placa: {inspection.vehicle_plate}", normal_style))
|
||||||
|
elements.append(Paragraph(f"Cliente: {inspection.client_name or ''}", normal_style))
|
||||||
|
elements.append(Paragraph(f"Mecánico: {mechanic.full_name if mechanic else ''}", normal_style))
|
||||||
|
elements.append(Paragraph(f"Checklist: {checklist.name if checklist else ''}", normal_style))
|
||||||
|
elements.append(Paragraph(f"Fecha: {inspection.started_at.strftime('%d/%m/%Y %H:%M') if inspection.started_at else ''}", normal_style))
|
||||||
|
elements.append(Spacer(1, 18))
|
||||||
|
# Tabla de respuestas
|
||||||
|
table_data = [["Sección", "Pregunta", "Respuesta", "Estado", "Comentario", "Miniaturas"]]
|
||||||
|
for ans in answers:
|
||||||
|
question = ans.question
|
||||||
|
media_imgs = []
|
||||||
|
for media in ans.media_files:
|
||||||
|
if media.file_type == "image":
|
||||||
|
try:
|
||||||
|
# Descargar imagen y agregar miniatura
|
||||||
|
import requests
|
||||||
|
img_resp = requests.get(media.file_path)
|
||||||
|
if img_resp.status_code == 200:
|
||||||
|
img_bytes = BytesIO(img_resp.content)
|
||||||
|
rl_img = RLImage(img_bytes, width=0.7*inch, height=0.7*inch)
|
||||||
|
media_imgs.append(rl_img)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error cargando imagen {media.file_path}: {e}")
|
||||||
|
row = [
|
||||||
|
question.section or "",
|
||||||
|
question.text,
|
||||||
|
ans.answer_value,
|
||||||
|
ans.status,
|
||||||
|
ans.comment or "",
|
||||||
|
media_imgs if media_imgs else ""
|
||||||
|
]
|
||||||
|
table_data.append(row)
|
||||||
|
# Construir tabla con miniaturas
|
||||||
|
table = Table(table_data, colWidths=[1.2*inch, 2.5*inch, 1*inch, 0.8*inch, 2*inch, 1.5*inch])
|
||||||
|
table.setStyle(TableStyle([
|
||||||
|
('BACKGROUND', (0,0), (-1,0), colors.lightgrey),
|
||||||
|
('TEXTCOLOR', (0,0), (-1,0), colors.black),
|
||||||
|
('ALIGN', (0,0), (-1,-1), 'LEFT'),
|
||||||
|
('VALIGN', (0,0), (-1,-1), 'TOP'),
|
||||||
|
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
|
||||||
|
('FONTSIZE', (0,0), (-1,0), 10),
|
||||||
|
('BOTTOMPADDING', (0,0), (-1,0), 8),
|
||||||
|
('GRID', (0,0), (-1,-1), 0.5, colors.grey),
|
||||||
|
]))
|
||||||
|
elements.append(table)
|
||||||
|
elements.append(Spacer(1, 18))
|
||||||
|
# Pie de página
|
||||||
|
elements.append(Paragraph(f"Generado por Checklist Inteligente - {datetime.now().strftime('%d/%m/%Y %H:%M')}", header_style))
|
||||||
|
# Construir PDF
|
||||||
|
try:
|
||||||
|
doc.build(elements)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error al generar PDF: {e}")
|
||||||
buffer.seek(0)
|
buffer.seek(0)
|
||||||
|
pdf_size = len(buffer.getvalue())
|
||||||
|
print(f"PDF generado, tamaño: {pdf_size} bytes")
|
||||||
# Guardar localmente para depuración
|
# Guardar localmente para depuración
|
||||||
with open(f"/tmp/test_inspeccion_{inspection_id}.pdf", "wb") as f:
|
try:
|
||||||
f.write(buffer.getvalue())
|
with open(f"/tmp/test_inspeccion_{inspection_id}.pdf", "wb") as f:
|
||||||
|
f.write(buffer.getvalue())
|
||||||
|
except Exception as e:
|
||||||
|
print(f"No se pudo guardar PDF local: {e}")
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
folder = f"{now.year}/{now.month:02d}"
|
folder = f"{now.year}/{now.month:02d}"
|
||||||
filename = f"inspeccion_{inspection_id}_{inspection.vehicle_plate or 'sin-patente'}.pdf"
|
filename = f"inspeccion_{inspection_id}_{inspection.vehicle_plate or 'sin-patente'}.pdf"
|
||||||
|
|||||||
@@ -15,4 +15,5 @@ google-generativeai==0.3.2
|
|||||||
Pillow==10.2.0
|
Pillow==10.2.0
|
||||||
reportlab==4.0.9
|
reportlab==4.0.9
|
||||||
python-dotenv==1.0.0
|
python-dotenv==1.0.0
|
||||||
boto3==1.34.89
|
boto3==1.34.89
|
||||||
|
requests==2.31.0
|
||||||
Reference in New Issue
Block a user