Backend v1.0.76:

- 🎨 Rediseñado PDF primera página con diseño moderno y profesional (cuadros con encabezados separados y coloreados, bordes redondeados, separadores internos, mejor jerarquía visual)
- 🔒 Eliminado nombre de mecánico del PDF por privacidad (solo código de operario)
- 🐛 Corregido bug: PDF mostraba valores técnicos en lugar de etiquetas legibles (implementada función get_readable_answer() que convierte "option1" → "Bueno", "pass" → "Pasa", soporta boolean, single_choice y multiple_choice)

Frontend v1.0.75:
-  Sin cambios
This commit is contained in:
2025-11-27 17:12:45 -03:00
parent 32c7f79dd6
commit 416588a327

View File

@@ -204,7 +204,7 @@ def send_completed_inspection_to_n8n(inspection, db):
# No lanzamos excepción para no interrumpir el flujo normal # No lanzamos excepción para no interrumpir el flujo normal
BACKEND_VERSION = "1.0.75" BACKEND_VERSION = "1.0.76"
app = FastAPI(title="Checklist Inteligente API", version=BACKEND_VERSION) app = FastAPI(title="Checklist Inteligente API", version=BACKEND_VERSION)
# S3/MinIO configuration # S3/MinIO configuration
@@ -1538,6 +1538,41 @@ def generate_inspection_pdf(inspection_id: int, db: Session) -> str:
models.Question.order models.Question.order
).all() ).all()
# Función helper para convertir valores técnicos a etiquetas legibles
def get_readable_answer(answer_value, question_options):
"""
Convierte el valor técnico de la respuesta a su etiqueta legible.
Ej: 'option1' -> 'Bueno', 'pass' -> 'Pasa'
"""
if not answer_value or not question_options:
return answer_value or 'Sin respuesta'
config = question_options
question_type = config.get('type', '')
# Para tipos con choices (boolean, single_choice, multiple_choice)
if question_type in ['boolean', 'single_choice', 'multiple_choice'] and config.get('choices'):
# Si es multiple_choice, puede tener varios valores separados por coma
if question_type == 'multiple_choice' and ',' in answer_value:
values = answer_value.split(',')
labels = []
for val in values:
val = val.strip()
choice = next((c for c in config['choices'] if c.get('value') == val), None)
if choice:
labels.append(choice.get('label', val))
else:
labels.append(val)
return ', '.join(labels)
else:
# Buscar la etiqueta correspondiente al valor
choice = next((c for c in config['choices'] if c.get('value') == answer_value), None)
if choice:
return choice.get('label', answer_value)
# Para tipos scale, text, number, date, time - devolver el valor tal cual
return answer_value
current_section = None current_section = None
for ans in answers: for ans in answers:
question = ans.question question = ans.question
@@ -1572,8 +1607,8 @@ def generate_inspection_pdf(inspection_id: int, db: Session) -> str:
Paragraph(f"<b>{status_icon} {question.text}</b>", info_style), Paragraph(f"<b>{status_icon} {question.text}</b>", info_style),
]) ])
# Fila 2: Respuesta y estado # Fila 2: Respuesta y estado - Convertir valor técnico a etiqueta legible
answer_text = ans.answer_value or 'Sin respuesta' answer_text = get_readable_answer(ans.answer_value, question.options)
question_data.append([ question_data.append([
Table([ Table([
[ [