diff --git a/backend/app/main.py b/backend/app/main.py
index 1711db9..8d351b3 100644
--- a/backend/app/main.py
+++ b/backend/app/main.py
@@ -204,7 +204,7 @@ def send_completed_inspection_to_n8n(inspection, db):
# No lanzamos excepción para no interrumpir el flujo normal
-BACKEND_VERSION = "1.0.82"
+BACKEND_VERSION = "1.0.83"
app = FastAPI(title="Checklist Inteligente API", version=BACKEND_VERSION)
# S3/MinIO configuration
diff --git a/frontend/package.json b/frontend/package.json
index 729bdd7..e0838da 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,7 +1,7 @@
{
"name": "checklist-frontend",
"private": true,
- "version": "1.0.80",
+ "version": "1.0.81",
"type": "module",
"scripts": {
"dev": "vite",
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index 0ca7a2c..11ae342 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -3373,6 +3373,36 @@ function InspectionDetailModal({ inspection, user, onClose, onUpdate, onContinue
)}
+ {/* AI Analysis - SOLO VISIBLE PARA ADMIN */}
+ {user?.role === 'admin' && answer.ai_analysis && (
+
@@ -4396,131 +4426,23 @@ function InspectionModal({ checklist, existingInspection, user, onClose, onCompl
if (analyses.length > 0) {
console.log('✅ Análisis recibidos:', analyses.length)
- let suggestedAnswer = null
- let observationsText = ''
- let worstStatus = 'ok' // Track the worst status across all images
-
- if (analyses.length === 1) {
- // Single image analysis
- const firstResult = analyses[0]
- const analysis = firstResult.analysis
- console.log('📊 Análisis de imagen única:', analysis)
-
- // Check if analysis is an object (structured JSON response)
- if (typeof analysis === 'object' && analysis !== null) {
- // Extract structured information
- const status = analysis.status || 'ok'
- const observations = analysis.observations || ''
- const recommendation = analysis.recommendation || ''
- const confidence = analysis.confidence || 0.7
-
- // Build observations text
- observationsText = `Análisis Automático (${(confidence * 100).toFixed(0)}% confianza):\n${observations}`
- if (recommendation) {
- observationsText += `\n\n💡 Recomendación: ${recommendation}`
- }
- worstStatus = status
- } else if (typeof analysis === 'string') {
- observationsText = `Análisis Automático:\n${analysis}`
+ // Guardar el análisis de IA en un campo separado (NO en observaciones)
+ // El mecánico NO verá esto, solo el admin
+ setAnswers(prev => ({
+ ...prev,
+ [questionId]: {
+ ...(prev[questionId] || { value: '', observations: '', photos: [] }),
+ photos: files,
+ aiAnalysis: analyses, // Guardar análisis separado
+ documentsLoaded: true // Marcar que se procesaron los documentos
}
- } else {
- // Multiple images - summarize all analyses
- console.log('📊 Resumen de', analyses.length, 'análisis:')
- observationsText = `Análisis Automático de ${analyses.length} imágenes:\n\n`
-
- const statusPriority = { 'critical': 3, 'minor': 2, 'warning': 2, 'ok': 1 }
- let maxPriority = 0
-
- analyses.forEach((result, index) => {
- const analysis = result.analysis
- observationsText += `📸 Imagen ${result.imageIndex}:\n`
-
- if (typeof analysis === 'object' && analysis !== null) {
- const status = analysis.status || 'ok'
- const observations = analysis.observations || ''
- const confidence = analysis.confidence || 0.7
-
- observationsText += ` Estado: ${status.toUpperCase()}`
- observationsText += ` (${(confidence * 100).toFixed(0)}% confianza)\n`
- observationsText += ` ${observations}\n`
-
- // Track worst status
- const priority = statusPriority[status] || 1
- if (priority > maxPriority) {
- maxPriority = priority
- worstStatus = status
- }
- } else if (typeof analysis === 'string') {
- observationsText += ` ${analysis}\n`
- }
- observationsText += '\n'
- })
-
- // Add overall recommendation
- observationsText += `📋 Resumen General:\n`
- observationsText += ` Estado más crítico detectado: ${worstStatus.toUpperCase()}\n`
- }
+ }))
- // Map worst status to answer
- if (question.type === 'pass_fail') {
- if (worstStatus === 'ok') {
- suggestedAnswer = 'pass'
- } else if (worstStatus === 'critical' || worstStatus === 'minor') {
- suggestedAnswer = 'fail'
- }
- } else if (question.type === 'good_bad') {
- if (worstStatus === 'ok') {
- suggestedAnswer = 'good'
- } else if (worstStatus === 'minor' || worstStatus === 'warning') {
- suggestedAnswer = 'regular'
- } else if (worstStatus === 'critical') {
- suggestedAnswer = 'bad'
- }
- }
+ console.log(`✅ Análisis IA guardado (${analyses.length} análisis)`)
+ console.log(`📝 Las observaciones quedan para que el mecánico las escriba manualmente`)
-
- // In FULL mode, auto-fill the answer
- if (checklist.ai_mode === 'full' && suggestedAnswer) {
- setAnswers(prev => ({
- ...prev,
- [questionId]: {
- ...(prev[questionId] || { value: '', observations: '', photos: [] }),
- value: suggestedAnswer,
- observations: observationsText,
- photos: files,
- aiAnalysis: analyses // Guardar todos los análisis
- }
- }))
- console.log(`🤖 FULL MODE: Respuesta auto-completada con: ${suggestedAnswer}`)
- console.log(`📝 Observaciones guardadas:`, observationsText)
- }
- // In ASSISTED mode, suggest in observations
- else if (checklist.ai_mode === 'assisted') {
- setAnswers(prev => ({
- ...prev,
- [questionId]: {
- ...(prev[questionId] || { value: '', observations: '', photos: [] }),
- observations: `${suggestedAnswer ? `[IA Sugiere: ${suggestedAnswer}]\n` : ''}${observationsText}`,
- photos: files,
- aiAnalysis: analyses // Guardar todos los análisis
- }
- }))
- console.log(`🤖 ASSISTED MODE: Sugerencia agregada a observaciones`)
- console.log(`📝 Observaciones guardadas:`, `${suggestedAnswer ? `[IA Sugiere: ${suggestedAnswer}]\n` : ''}${observationsText}`)
- }
- // Siempre guardar observaciones incluso si no hay modo específico o sugerencia
- else if (observationsText) {
- setAnswers(prev => ({
- ...prev,
- [questionId]: {
- ...(prev[questionId] || { value: '', observations: '', photos: [] }),
- observations: observationsText,
- photos: files,
- aiAnalysis: analyses // Guardar todos los análisis
- }
- }))
- console.log(`🤖 Análisis IA guardado en observaciones:`, observationsText)
- }
+ // Mostrar popup de confirmación en vez de llenar observaciones
+ alert('✅ Documentos cargados correctamente')
}
} catch (error) {
console.error('❌ Error al analizar fotos con IA:', error)
@@ -4921,12 +4843,12 @@ function InspectionModal({ checklist, existingInspection, user, onClose, onCompl
{aiAnalyzing ? (
<>
-
Analizando...
+
Procesando...
>
) : (
<>
-
🤖
-
Analizar Pregunta
+
📁
+
Cargar Documentos
>
)}
@@ -4938,16 +4860,12 @@ function InspectionModal({ checklist, existingInspection, user, onClose, onCompl
-
Analizando {answers[currentQuestion.id]?.photos?.length || 0} imagen(es) con IA...
+
Procesando {answers[currentQuestion.id]?.photos?.length || 0} documento(s)...
)}
- {answers[currentQuestion.id]?.photos?.length > 0 && !aiAnalyzing && (
-
- {checklist.ai_mode === 'full' && answers[currentQuestion.id]?.value && (
-
✓ Analizada
- )}
+ {/* Comentarios removidos que revelaban IA */}
{checklist.ai_mode === 'assisted' && answers[currentQuestion.id]?.observations.includes('[IA Sugiere') && (
✓ Sugerencia generada
)}
@@ -4980,6 +4898,13 @@ function InspectionModal({ checklist, existingInspection, user, onClose, onCompl
alert('⚠️ Debes subir al menos una fotografía para esta pregunta')
return
}
+ // Validar que se hayan cargado documentos si hay fotos y está en modo IA
+ if ((checklist.ai_mode === 'assisted' || checklist.ai_mode === 'full') &&
+ answers[currentQuestion.id]?.photos?.length > 0 &&
+ !answers[currentQuestion.id]?.documentsLoaded) {
+ alert('⚠️ Debes presionar "Cargar Documentos" antes de continuar')
+ return
+ }
saveAnswer(currentQuestion.id)
goToQuestion(currentQuestionIndex + 1)
}}
@@ -4995,6 +4920,13 @@ function InspectionModal({ checklist, existingInspection, user, onClose, onCompl
alert('⚠️ Debes subir al menos una fotografía para esta pregunta')
return
}
+ // Validar que se hayan cargado documentos si hay fotos y está en modo IA
+ if ((checklist.ai_mode === 'assisted' || checklist.ai_mode === 'full') &&
+ answers[currentQuestion.id]?.photos?.length > 0 &&
+ !answers[currentQuestion.id]?.documentsLoaded) {
+ alert('⚠️ Debes presionar "Cargar Documentos" antes de continuar')
+ return
+ }
saveAnswer(currentQuestion.id)
proceedToSignatures()
}}
@@ -5009,7 +4941,7 @@ function InspectionModal({ checklist, existingInspection, user, onClose, onCompl
{answers[currentQuestion.id]?.value && (
✓
- Respuesta guardada automáticamente
+ Respuesta guardada
)}