mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-12-07 15:25:41 +01:00
fix(ai-suggestions): mejora manejo de errores y permisos
Mejoras en frontend TypeScript: - Agrega notificaciones de error al usuario usando ToastService cuando falla la carga de metadatos (tags, correspondents, document types, etc.) - Mantiene console.error para debugging pero ahora también muestra mensajes visibles al usuario - Mensajes localizados con $localize para soporte multiidioma Mejoras en backend Python: - Agrega CanApplyAISuggestionsPermission al action apply_suggestion - Mejora logging de errores con información específica sobre qué objeto no se encontró y qué usuario intentó aplicar la sugerencia - Separa las excepciones DoesNotExist para proporcionar mensajes de error más específicos (Tag, Correspondent, DocumentType, StoragePath) - Agrega comentarios explicativos sobre validación de permisos Estos cambios aseguran que: 1. Los usuarios reciben feedback visible cuando algo falla 2. Se verifican permisos apropiados antes de aplicar sugerencias AI 3. Los logs contienen información detallada para debugging 4. Los mensajes de error son específicos y útiles Relacionado con: mejoras de CI/CD y calidad de código
This commit is contained in:
parent
c61a000597
commit
b3969464b1
2 changed files with 56 additions and 8 deletions
|
|
@ -140,6 +140,9 @@ export class AiSuggestionsPanelComponent implements OnChanges, OnDestroy {
|
|||
takeUntil(this.destroy$),
|
||||
catchError((error) => {
|
||||
console.error('Failed to load tags:', error)
|
||||
this.toastService.showError(
|
||||
$localize`Failed to load tags for AI suggestions. Please refresh the page.`
|
||||
)
|
||||
return of({ results: [] })
|
||||
})
|
||||
)
|
||||
|
|
@ -160,6 +163,9 @@ export class AiSuggestionsPanelComponent implements OnChanges, OnDestroy {
|
|||
takeUntil(this.destroy$),
|
||||
catchError((error) => {
|
||||
console.error('Failed to load correspondents:', error)
|
||||
this.toastService.showError(
|
||||
$localize`Failed to load correspondents for AI suggestions. Please refresh the page.`
|
||||
)
|
||||
return of({ results: [] })
|
||||
})
|
||||
)
|
||||
|
|
@ -180,6 +186,9 @@ export class AiSuggestionsPanelComponent implements OnChanges, OnDestroy {
|
|||
takeUntil(this.destroy$),
|
||||
catchError((error) => {
|
||||
console.error('Failed to load document types:', error)
|
||||
this.toastService.showError(
|
||||
$localize`Failed to load document types for AI suggestions. Please refresh the page.`
|
||||
)
|
||||
return of({ results: [] })
|
||||
})
|
||||
)
|
||||
|
|
@ -200,6 +209,9 @@ export class AiSuggestionsPanelComponent implements OnChanges, OnDestroy {
|
|||
takeUntil(this.destroy$),
|
||||
catchError((error) => {
|
||||
console.error('Failed to load storage paths:', error)
|
||||
this.toastService.showError(
|
||||
$localize`Failed to load storage paths for AI suggestions. Please refresh the page.`
|
||||
)
|
||||
return of({ results: [] })
|
||||
})
|
||||
)
|
||||
|
|
@ -220,6 +232,9 @@ export class AiSuggestionsPanelComponent implements OnChanges, OnDestroy {
|
|||
takeUntil(this.destroy$),
|
||||
catchError((error) => {
|
||||
console.error('Failed to load custom fields:', error)
|
||||
this.toastService.showError(
|
||||
$localize`Failed to load custom fields for AI suggestions. Please refresh the page.`
|
||||
)
|
||||
return of({ results: [] })
|
||||
})
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1413,17 +1413,24 @@ class UnifiedSearchViewSet(DocumentViewSet):
|
|||
status=500,
|
||||
)
|
||||
|
||||
@action(detail=True, methods=["POST"], name="Apply AI Suggestion")
|
||||
@action(
|
||||
detail=True,
|
||||
methods=["POST"],
|
||||
name="Apply AI Suggestion",
|
||||
permission_classes=[IsAuthenticated, CanApplyAISuggestionsPermission],
|
||||
)
|
||||
def apply_suggestion(self, request, pk=None):
|
||||
"""
|
||||
Apply an AI suggestion to a document.
|
||||
|
||||
Records user feedback and applies the suggested change.
|
||||
Requires 'can_apply_ai_suggestions' permission.
|
||||
"""
|
||||
from documents.models import AISuggestionFeedback
|
||||
from documents.serializers.ai_suggestions import ApplySuggestionSerializer
|
||||
|
||||
try:
|
||||
# Check permissions - get_object() validates object-level permissions
|
||||
document = self.get_object()
|
||||
|
||||
# Validate input
|
||||
|
|
@ -1496,14 +1503,40 @@ class UnifiedSearchViewSet(DocumentViewSet):
|
|||
status=400,
|
||||
)
|
||||
|
||||
except (
|
||||
Tag.DoesNotExist,
|
||||
Correspondent.DoesNotExist,
|
||||
DocumentType.DoesNotExist,
|
||||
StoragePath.DoesNotExist,
|
||||
):
|
||||
except Tag.DoesNotExist:
|
||||
logger.error(
|
||||
f"Tag {value_id} not found when applying suggestion to document {pk} "
|
||||
f"by user {request.user.username}",
|
||||
)
|
||||
return Response(
|
||||
{"detail": "Referenced object not found"},
|
||||
{"detail": f"Tag with ID {value_id} not found"},
|
||||
status=404,
|
||||
)
|
||||
except Correspondent.DoesNotExist:
|
||||
logger.error(
|
||||
f"Correspondent {value_id} not found when applying suggestion to document {pk} "
|
||||
f"by user {request.user.username}",
|
||||
)
|
||||
return Response(
|
||||
{"detail": f"Correspondent with ID {value_id} not found"},
|
||||
status=404,
|
||||
)
|
||||
except DocumentType.DoesNotExist:
|
||||
logger.error(
|
||||
f"DocumentType {value_id} not found when applying suggestion to document {pk} "
|
||||
f"by user {request.user.username}",
|
||||
)
|
||||
return Response(
|
||||
{"detail": f"Document type with ID {value_id} not found"},
|
||||
status=404,
|
||||
)
|
||||
except StoragePath.DoesNotExist:
|
||||
logger.error(
|
||||
f"StoragePath {value_id} not found when applying suggestion to document {pk} "
|
||||
f"by user {request.user.username}",
|
||||
)
|
||||
return Response(
|
||||
{"detail": f"Storage path with ID {value_id} not found"},
|
||||
status=404,
|
||||
)
|
||||
except Exception as e:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue