From 7a3c0a5bd161c5c8548ca4a7e557abaf5b20c519 Mon Sep 17 00:00:00 2001 From: AdalbertoCV <34152734@uaz.edu.mx> Date: Fri, 30 Aug 2024 21:24:14 -0600 Subject: [PATCH] =?UTF-8?q?Calificar=20documentos=20y=20solucion=20de=20bu?= =?UTF-8?q?gs=20en=20tablas=20din=C3=A1micas=20de=20usuarios?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ..._verbose_name_dynamicformat_dynamicform.py | 20 ++++++ cosiap_api/dynamic_forms/models.py | 2 +- cosiap_api/dynamic_tables/views.py | 12 ++-- ..._verbose_name_dynamicformat_dynamicform.py | 18 +++++ cosiap_api/solicitudes/models.py | 6 +- cosiap_api/solicitudes/urls.py | 1 + cosiap_api/solicitudes/views.py | 66 +++++++++++++++++-- 7 files changed, 112 insertions(+), 13 deletions(-) create mode 100644 cosiap_api/dynamic_forms/migrations/0005_verbose_name_dynamicformat_dynamicform.py create mode 100644 cosiap_api/solicitudes/migrations/0005_verbose_name_dynamicformat_dynamicform.py diff --git a/cosiap_api/dynamic_forms/migrations/0005_verbose_name_dynamicformat_dynamicform.py b/cosiap_api/dynamic_forms/migrations/0005_verbose_name_dynamicformat_dynamicform.py new file mode 100644 index 0000000..311b1ba --- /dev/null +++ b/cosiap_api/dynamic_forms/migrations/0005_verbose_name_dynamicformat_dynamicform.py @@ -0,0 +1,20 @@ +# Generated by Django 5.0.7 on 2024-08-31 03:16 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dynamic_formats', '0001_initial'), + ('dynamic_forms', '0004_registro_formulario_foreignkey'), + ] + + operations = [ + migrations.AlterField( + model_name='elemento', + name='formato', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dynamic_formats.dynamicformat', verbose_name='Formato'), + ), + ] diff --git a/cosiap_api/dynamic_forms/models.py b/cosiap_api/dynamic_forms/models.py index def86c1..2d6b294 100644 --- a/cosiap_api/dynamic_forms/models.py +++ b/cosiap_api/dynamic_forms/models.py @@ -53,7 +53,7 @@ class Elemento(models.Model): max_digits = models.IntegerField(default=10, verbose_name='Máximo de dígitos') opciones = models.ManyToManyField(Opcion, through='ElementosOpciones', verbose_name='Opciones', blank=True) - formato = models.ForeignKey(DynamicFormat, on_delete=models.SET_NULL, verbose_name='Elemento', default=None, null=True, blank=True) + formato = models.ForeignKey(DynamicFormat, on_delete=models.SET_NULL, verbose_name='Formato', default=None, null=True, blank=True) class Meta: verbose_name_plural = '05. Elementos' diff --git a/cosiap_api/dynamic_tables/views.py b/cosiap_api/dynamic_tables/views.py index 64cee79..da67c20 100644 --- a/cosiap_api/dynamic_tables/views.py +++ b/cosiap_api/dynamic_tables/views.py @@ -39,11 +39,10 @@ class DynamicTableAPIView(BasePermissionAPIView): dynamic_form_exist = False - def check_user_permissions(self, request, pk): + def check_user_permissions(self, user, pk): ''' Verificamos el acceso de un usuario a una instancia en específico ''' - user = request.user if not user.is_staff: solicitante = Solicitante.objects.get(id=user.id) @@ -110,13 +109,17 @@ class DynamicTableAPIView(BasePermissionAPIView): ''' response_data = {} + user = request.user + print(user.is_staff) if pk is not None: try: - instance = self.check_user_permissions(request, pk) + instance = self.check_user_permissions(user, pk) if instance is not None: if self.dynamic_form_exist: serializer = DynamicTableDynamicForm(model_class=self.model_class) + instance_data = serializer.retrieve_instance_data(instance) + return Response(instance_data, status=status.HTTP_200_OK) else: serializer = DynamicTable(model_class=self.model_class) instance_data = serializer.retrieve_instance_data(instance) @@ -153,11 +156,12 @@ class DynamicTableAPIView(BasePermissionAPIView): Permite a un admin modificar manualmente varias columnas de una fila en la tabla dinámica. ''' response_data = {} + user = request.user instance = None # Obtener la instancia del modelo por el id proporcionado en la URL o un 404 en caso de no existir if pk is not None: try: - instance = self.check_user_permissions(request, pk) + instance = self.check_user_permissions(user, pk) if instance is None: Mensaje.error(response_data, 'No tienes permisos para realizar esta acción.') return Response(response_data, status = status.HTTP_400_BAD_REQUEST) diff --git a/cosiap_api/solicitudes/migrations/0005_verbose_name_dynamicformat_dynamicform.py b/cosiap_api/solicitudes/migrations/0005_verbose_name_dynamicformat_dynamicform.py new file mode 100644 index 0000000..d2f9d06 --- /dev/null +++ b/cosiap_api/solicitudes/migrations/0005_verbose_name_dynamicformat_dynamicform.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.7 on 2024-08-31 03:16 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('solicitudes', '0004_solicitud_status_choices'), + ] + + operations = [ + migrations.AlterField( + model_name='solicitud', + name='status', + field=models.CharField(choices=[('Pendiente', 'En revisión'), ('Aprobado', 'Aprobado'), ('Rechazado', 'Rechazado')], max_length=255, verbose_name='Status'), + ), + ] diff --git a/cosiap_api/solicitudes/models.py b/cosiap_api/solicitudes/models.py index 5bb62a6..c7a10d1 100644 --- a/cosiap_api/solicitudes/models.py +++ b/cosiap_api/solicitudes/models.py @@ -108,9 +108,9 @@ class Solicitud(models.Model): """ STATUS_CHOICES = [ - ('1', 'En revisión'), - ('2', 'Aprobado'), - ('3', 'Rechazado'), + ('Pendiente', 'En revisión'), + ('Aprobado', 'Aprobado'), + ('Rechazado', 'Rechazado'), ] status = models.CharField(verbose_name='Status', max_length=255, choices= STATUS_CHOICES) diff --git a/cosiap_api/solicitudes/urls.py b/cosiap_api/solicitudes/urls.py index 0d1eae7..9dcf2f8 100644 --- a/cosiap_api/solicitudes/urls.py +++ b/cosiap_api/solicitudes/urls.py @@ -15,4 +15,5 @@ urlpatterns = [ path('reportes//', views.ReportesSolicitudesAPIView.as_view(), name='reportes_solicitudes_pk'), path('reportes/exportar/', views.ExportarReporteSolicitudes.as_view(), name='exportar_reportes'), path('reportes/exportar//', views.ExportarReporteSolicitudes.as_view(), name='exportar_reportes_pk'), + path('calificar//', views.CalificarDocumento.as_view(), name='calificar_documentos'), ] \ No newline at end of file diff --git a/cosiap_api/solicitudes/views.py b/cosiap_api/solicitudes/views.py index f03f6f9..db5e5c8 100644 --- a/cosiap_api/solicitudes/views.py +++ b/cosiap_api/solicitudes/views.py @@ -25,14 +25,15 @@ from django.db import transaction from .respuestas_serializer import RespuestaSerializer from django.utils import timezone from dynamic_forms.serializers import RespuestaFormularioSerializer -from dynamic_forms.models import Elemento, RegistroFormulario, RegistroSeccion, Respuesta +from dynamic_forms.models import Elemento, RegistroFormulario, RegistroSeccion, Respuesta, RDocumento +from django.core.exceptions import ValidationError class SolicitudAPIView(DynamicTableAPIView): ''' Clase para el manejo de la lista de solicitudes y la aplicación de sus filtros - ''' - + ''' + model_class = Solicitud model_name = 'Solicitud' columns = '__all__' @@ -117,7 +118,7 @@ class SolicitarAPIView(BasePermissionAPIView): solicitante=solicitante, monto_solicitado=monto_solicitado, modalidad=modalidad, - status='1' + status='Pendiente' ) nueva_solicitud.solicitud_n = nueva_solicitud.id nueva_solicitud.save() @@ -163,7 +164,7 @@ class SolicitarAPIView(BasePermissionAPIView): with transaction.atomic(): solicitud.monto_solicitado = monto_solicitado - solicitud.status = '1' + solicitud.status = 'Pendiente' solicitud.save() registro_formulario = solicitud.registro_formulario @@ -265,3 +266,58 @@ class ExportarReporteSolicitudes(Exportar_CSV): ''' model_class = Solicitud + +class CalificarDocumento(BasePermissionAPIView): + ''' + APIView para dar retroalimentación a un documento enviado a la solicitud. + ''' + permission_classes_update = [IsAuthenticated, es_admin] + + def put(self, request, *args, **kwargs): + ''' + Método para calificar uno o varios documentos a la vez de una solicitud. + + Espera una lista de dicts en el formato check_documents = [{"id_respuesta":"n","nuevo_status":"status" }] + ''' + data = {} + + try: + id_solicitud = kwargs['pk'] + respuestas_calificar = request.data.get('check_documents') + if not respuestas_calificar: + raise ValueError("No se proporcionaron documentos para calificar.") + + # Obtener el registro_formulario de la solicitud + solicitud = get_object_or_404(Solicitud, pk=id_solicitud) + registro_formulario_solicitud = solicitud.registro_formulario + + for respuesta_data in respuestas_calificar: + id_respuesta = respuesta_data.get("id_respuesta") + nuevo_status = respuesta_data.get("nuevo_status") + + # Verificar que los datos necesarios están presentes + if not id_respuesta or not nuevo_status: + raise ValueError("El 'id_respuesta' y 'nuevo_status' son obligatorios para cada documento.") + + # Obtener la respuesta del documento + respuesta = get_object_or_404(RDocumento, pk=id_respuesta) + + # Validar que la respuesta pertenece a la solicitud dada + if respuesta.registro_seccion.registro_formulario != registro_formulario_solicitud: + raise ValidationError("La respuesta no pertenece a la solicitud proporcionada.") + + # Validar el nuevo status + if nuevo_status not in RDocumento.Status.values: + raise ValueError(f"El status '{nuevo_status}' no es válido.") + + # Actualizar el status del documento + respuesta.status = nuevo_status + respuesta.save() + + data['mensaje'] = "Documentos calificados correctamente." + return Response(data, status=status.HTTP_200_OK) + + except Exception as e: + Mensaje.error(data, str(e)) + return Response(data, status=status.HTTP_400_BAD_REQUEST) + -- GitLab