Cambios realizados v1.2.11 (Backend) + v1.3.8 (Frontend):
Backend v1.2.11:
Nueva Funcionalidad - Control de Generación de PDF:
Campo nuevo: generate_pdf en modelo Checklist (Boolean, default: True)
Lógica modificada: Al completar inspección se verifica si el checklist tiene habilitada la generación de PDF
Comportamiento:
Si generate_pdf = True → Se genera y guarda el PDF automáticamente
Si generate_pdf = False → No se genera PDF, pdf_url queda en NULL
Logs informativos: Muestra en consola si el PDF se generó o se omitió
Frontend v1.3.8:
Interfaz para Control de PDF:
Checkbox nuevo en modal de edición de checklist: "Generar PDF automáticamente al completar inspección"
Estado por defecto: Activado (mantiene comportamiento actual)
Persistencia: El valor se guarda en la base de datos al editar checklist
Dónde está:
Admin → Checklists → Click en "✏️ Editar" de cualquier checklist
Debajo del checkbox de "Habilitar sistema de puntuación"
This commit is contained in:
@@ -278,7 +278,7 @@ def extract_pdf_text_smart(pdf_content: bytes, max_chars: int = None) -> dict:
|
||||
}
|
||||
|
||||
|
||||
BACKEND_VERSION = "1.2.9"
|
||||
BACKEND_VERSION = "1.2.11"
|
||||
app = FastAPI(title="Checklist Inteligente API", version=BACKEND_VERSION)
|
||||
|
||||
# S3/MinIO configuration
|
||||
@@ -2049,54 +2049,30 @@ def generate_inspection_pdf(inspection_id: int, db: Session) -> str:
|
||||
|
||||
# ===== LÓGICA ESPECIAL PARA AI_ASSISTANT =====
|
||||
if is_ai_assistant and ans.chat_history:
|
||||
# Generar resumen estructurado del chat
|
||||
import asyncio
|
||||
# Mostrar resumen simple SIN generar con IA (para evitar lentitud y peso)
|
||||
try:
|
||||
# Ejecutar función async de forma sincrónica
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
chat_summary = loop.run_until_complete(
|
||||
generate_chat_summary(ans.chat_history, question.text)
|
||||
)
|
||||
loop.close()
|
||||
chat_data = ans.chat_history if isinstance(ans.chat_history, list) else json.loads(ans.chat_history)
|
||||
total_messages = len(chat_data)
|
||||
user_messages = sum(1 for m in chat_data if m.get('role') == 'user')
|
||||
assistant_messages = sum(1 for m in chat_data if m.get('role') == 'assistant')
|
||||
|
||||
# Renderizar informe narrativo
|
||||
question_data.append([
|
||||
Paragraph(f"<b>💬 INFORME DE DIAGNÓSTICO ASISTIDO</b>",
|
||||
Paragraph(f"<b>💬 DIAGNÓSTICO ASISTIDO POR IA</b>",
|
||||
ParagraphStyle('chat_title', parent=answer_style, fontSize=11,
|
||||
textColor=colors.HexColor('#2563eb'), fontName='Helvetica-Bold'))
|
||||
])
|
||||
|
||||
# Problema identificado
|
||||
question_data.append([
|
||||
Paragraph(f"<b>🔍 Problema Identificado:</b><br/>{chat_summary.get('problema_identificado', 'N/A')}",
|
||||
Paragraph(f"<b>📊 Resumen de Conversación:</b><br/>"
|
||||
f"• Total de mensajes: {total_messages}<br/>"
|
||||
f"• Consultas del mecánico: {user_messages}<br/>"
|
||||
f"• Respuestas del asistente: {assistant_messages}<br/><br/>"
|
||||
f"<i>Nota: El historial completo está disponible en el sistema para administradores.</i>",
|
||||
comment_style)
|
||||
])
|
||||
|
||||
# Hallazgos
|
||||
if chat_summary.get('hallazgos') and len(chat_summary['hallazgos']) > 0:
|
||||
hallazgos_text = "<br/>".join([f"• {h}" for h in chat_summary['hallazgos']])
|
||||
question_data.append([
|
||||
Paragraph(f"<b>📋 Hallazgos:</b><br/>{hallazgos_text}", comment_style)
|
||||
])
|
||||
|
||||
# Diagnóstico
|
||||
question_data.append([
|
||||
Paragraph(f"<b>🔧 Diagnóstico:</b><br/>{chat_summary.get('diagnostico', 'N/A')}",
|
||||
comment_style)
|
||||
])
|
||||
|
||||
# Recomendaciones
|
||||
if chat_summary.get('recomendaciones') and len(chat_summary['recomendaciones']) > 0:
|
||||
recomendaciones_text = "<br/>".join([f"• {r}" for r in chat_summary['recomendaciones']])
|
||||
question_data.append([
|
||||
Paragraph(f"<b>✅ Recomendaciones:</b><br/>{recomendaciones_text}",
|
||||
ParagraphStyle('recommendations', parent=comment_style,
|
||||
textColor=colors.HexColor('#16a34a')))
|
||||
])
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error generando resumen de chat en PDF: {e}")
|
||||
print(f"❌ Error procesando chat en PDF: {e}")
|
||||
# Fallback: mostrar que hubo conversación
|
||||
question_data.append([
|
||||
Table([
|
||||
@@ -2284,9 +2260,15 @@ def complete_inspection(
|
||||
inspection.status = "completed"
|
||||
inspection.completed_at = datetime.utcnow()
|
||||
|
||||
# Generar PDF usando función reutilizable
|
||||
pdf_url = generate_inspection_pdf(inspection_id, db)
|
||||
inspection.pdf_url = pdf_url
|
||||
# Generar PDF solo si el checklist lo tiene habilitado
|
||||
if inspection.checklist.generate_pdf:
|
||||
pdf_url = generate_inspection_pdf(inspection_id, db)
|
||||
inspection.pdf_url = pdf_url
|
||||
print(f"✅ PDF generado para inspección #{inspection_id}")
|
||||
else:
|
||||
inspection.pdf_url = None
|
||||
print(f"⏭️ PDF NO generado (deshabilitado en checklist) para inspección #{inspection_id}")
|
||||
|
||||
db.commit()
|
||||
db.refresh(inspection)
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ class Checklist(Base):
|
||||
scoring_enabled = Column(Boolean, default=True)
|
||||
max_score = Column(Integer, default=0)
|
||||
logo_url = Column(String(500))
|
||||
generate_pdf = Column(Boolean, default=True) # Controla si se genera PDF al completar
|
||||
is_active = Column(Boolean, default=True)
|
||||
created_by = Column(Integer, ForeignKey("users.id"))
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
@@ -71,6 +71,7 @@ class ChecklistBase(BaseModel):
|
||||
ai_mode: str = "off"
|
||||
scoring_enabled: bool = True
|
||||
logo_url: Optional[str] = None
|
||||
generate_pdf: bool = True
|
||||
|
||||
class ChecklistCreate(ChecklistBase):
|
||||
mechanic_ids: Optional[List[int]] = [] # IDs de mecánicos autorizados
|
||||
@@ -81,12 +82,14 @@ class ChecklistUpdate(BaseModel):
|
||||
ai_mode: Optional[str] = None
|
||||
scoring_enabled: Optional[bool] = None
|
||||
logo_url: Optional[str] = None
|
||||
generate_pdf: Optional[bool] = None
|
||||
is_active: Optional[bool] = None
|
||||
mechanic_ids: Optional[List[int]] = None # IDs de mecánicos autorizados
|
||||
|
||||
class Checklist(ChecklistBase):
|
||||
id: int
|
||||
max_score: int
|
||||
generate_pdf: bool
|
||||
is_active: bool
|
||||
created_by: int
|
||||
created_at: datetime
|
||||
|
||||
Reference in New Issue
Block a user