diff --git a/backend/app/main.py b/backend/app/main.py index b5d3d30..a6a85a3 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -749,7 +749,86 @@ def complete_inspection( inspection.flagged_items_count = flagged_count inspection.status = "completed" inspection.completed_at = datetime.utcnow() - + + # Generar PDF con miniaturas de imágenes y subir a MinIO + from reportlab.lib.pagesizes import A4 + from reportlab.lib import colors + from reportlab.lib.units import inch + from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer, Image as RLImage + from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle + from reportlab.lib.enums import TA_CENTER + from io import BytesIO + import requests + buffer = BytesIO() + doc = SimpleDocTemplate(buffer, pagesize=A4, rightMargin=30, leftMargin=30, topMargin=30, bottomMargin=30) + elements = [] + styles = getSampleStyleSheet() + title_style = styles['Title'] + 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)) + mechanic = db.query(models.User).filter(models.User.id == inspection.mechanic_id).first() + checklist = db.query(models.Checklist).filter(models.Checklist.id == inspection.checklist_id).first() + 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 con miniaturas + answers = db.query(models.Answer).options(joinedload(models.Answer.media_files)).join(models.Question).filter(models.Answer.inspection_id == inspection_id).order_by(models.Question.section, models.Question.order).all() + 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: + 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) + 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)) + elements.append(Paragraph(f"Generado por Checklist Inteligente - {datetime.now().strftime('%d/%m/%Y %H:%M')}", header_style)) + try: + doc.build(elements) + except Exception as e: + print(f"Error al generar PDF: {e}") + buffer.seek(0) + now = datetime.now() + folder = f"{now.year}/{now.month:02d}" + filename = f"inspeccion_{inspection_id}_{inspection.vehicle_plate or 'sin-patente'}.pdf" + s3_key = f"{folder}/{filename}" + buffer.seek(0) + s3_client.upload_fileobj(buffer, S3_PDF_BUCKET, s3_key, ExtraArgs={"ContentType": "application/pdf"}) + pdf_url = f"{S3_ENDPOINT}/{S3_PDF_BUCKET}/{s3_key}" + inspection.pdf_url = pdf_url db.commit() db.refresh(inspection) return inspection