diff --git a/cosiap_api/solicitudes/views.py b/cosiap_api/solicitudes/views.py index 842d86edd014761c2b28606d0a44ca0bf0f23b1a..d7c164cadc269d4d5ff9bb75c69ae7f30051387b 100644 --- a/cosiap_api/solicitudes/views.py +++ b/cosiap_api/solicitudes/views.py @@ -28,6 +28,7 @@ from dynamic_forms.serializers import RespuestaFormularioSerializer 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 @@ -55,61 +56,6 @@ class SolicitarAPIView(BasePermissionAPIView): permission_classes_create = [IsAuthenticated, primer_login] permission_classes_update = [IsAuthenticated, primer_login] - permission_classes_list = [IsAuthenticated] - - def get(self, request, *args, **kwargs): - ''' - Metodo GET para obtener el formulario a contestar de la modalidad - ''' - data = {} - - try: - if request.user.is_staff: - solicitante = Solicitante( - nombre = 'temporal_user' - ) - else: - solicitante = Solicitante.objects.get(id=request.user.id) - - # Obtener el id de la modalidad desde los parámetros de la solicitud - modalidad_id = request.query_params.get('modalidad_id', None) - if not modalidad_id: - Mensaje.error(data, 'El parámetro modalidad_id es requerido.') - return Response(data, status=status.HTTP_400_BAD_REQUEST) - - # Buscar la modalidad por su id - modalidad = Modalidad.objects.get(id=modalidad_id) - - # Crear una instancia temporal de Solicitud (sin guardarla en la base de datos) - solicitud_temporal = Solicitud( - solicitante=solicitante, - modalidad=modalidad, - # Otros campos pueden inicializarse aquí si es necesario - ) - - solicitud_temporal.id = -1 - - # Serializar el formulario basado en la modalidad dinámica - form = RespuestaFormularioSerializer(solicitud_temporal, dynamic_form_source='modalidad__dynamic_form') - form_data = form.data - - # Devolver el formulario serializado - return Response(form_data, status=status.HTTP_200_OK) - - except Modalidad.DoesNotExist: - Mensaje.error(data, 'Modalidad no encontrada.') - return Response(data, status=status.HTTP_404_NOT_FOUND) - - except Solicitante.DoesNotExist: - Mensaje.error(data, 'Solicitante no encontrado.') - return Response(data, status=status.HTTP_404_NOT_FOUND) - - except Exception as e: - # Captura de otros errores - Mensaje.error(data, str(e)) - return Response(data, status=status.HTTP_400_BAD_REQUEST) - - def post(self, request, *args, **kwargs): ''' diff --git a/cosiap_api/users/serializers.py b/cosiap_api/users/serializers.py index 5ad3124508f01f7020986d501d362eb9ce442f35..abdbb1de0ca71928d0054ed9e29823d85fa05921 100644 --- a/cosiap_api/users/serializers.py +++ b/cosiap_api/users/serializers.py @@ -3,7 +3,7 @@ # Versión: 1.0 from rest_framework import serializers -from .models import Usuario, Solicitante, DatosBancarios +from .models import Usuario, Solicitante, DatosBancarios, Municipio, Estado class AdminSerializer(serializers.ModelSerializer): @@ -160,4 +160,17 @@ class SolicitanteSerializer(serializers.ModelSerializer): # Guardar el objeto Solicitante actualizado instance.save() # Retornamos la instancia actualizada - return instance \ No newline at end of file + return instance + + +class MunicipioSerializer(serializers.ModelSerializer): + ''' Serializer para serializar los municipios''' + class Meta: + model = Municipio + fields = '__all__' + +class EstadoSerializer(serializers.ModelSerializer): + ''' clase para serializar los estados''' + class Meta: + model = Estado + fields = '__all__' diff --git a/cosiap_api/users/urls.py b/cosiap_api/users/urls.py index 5cd077cb8e0add8b160ef7233d90f7d7b341684a..4fa218a60e732e9346998324f49dfcb1130443aa 100644 --- a/cosiap_api/users/urls.py +++ b/cosiap_api/users/urls.py @@ -14,6 +14,9 @@ urlpatterns = [ path('user-complete-data/', views.SolicitanteDatosCompletos.as_view(), name='user_complete_data'), path('logout/', views.LogoutAPIView.as_view(), name='logout'), + path('municipios/', views.RetreiveMunicipioAPIView.as_view(), name='municipios'), + path('estados/', views.RetreiveEstadoAPIView.as_view(), name='estados'), + path('', views.UsuarioAPIView.as_view(), name = 'usuarios'), path('/', views.UsuarioAPIView.as_view(), name = 'usuarios_pk'), path('solicitantes/', views.SolicitanteAPIView.as_view(), name = 'solicitantes'), diff --git a/cosiap_api/users/views.py b/cosiap_api/users/views.py index 3e6163fb9bf168cc5dd88081294597689be9b2d0..ff1dfea64a099527450ca129896296b4ea735656 100644 --- a/cosiap_api/users/views.py +++ b/cosiap_api/users/views.py @@ -7,9 +7,9 @@ from rest_framework import status, permissions from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import AllowAny, IsAuthenticated -from .models import Usuario, Solicitante, DatosBancarios +from .models import Usuario, Solicitante, DatosBancarios, Municipio, Estado from django.contrib import messages -from .serializers import UsuarioSerializer, SolicitanteSerializer, DatosBancariosSerializer +from .serializers import UsuarioSerializer, SolicitanteSerializer, DatosBancariosSerializer, MunicipioSerializer, EstadoSerializer from django.contrib.auth import authenticate from django.core.mail import send_mail from django.conf import settings @@ -64,6 +64,42 @@ class CustomTokenRefreshView(TokenRefreshView): return response +class RetreiveMunicipioAPIView(BasePermissionAPIView): + ''' + Clase para obtener los municipios de la base de datos + ''' + permission_classes_list = [IsAuthenticated] + + def get(self, request, *args, **kwargs): + data = {} + try: + queryset = Municipio.objects.all() + serializer = MunicipioSerializer(queryset, many=True) + data = serializer.data + 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) + + +class RetreiveEstadoAPIView(BasePermissionAPIView): + ''' + Clase para obtener los estados de la base de datos + ''' + permission_classes_list = [IsAuthenticated] + + def get(self, request, *args, **kwargs): + data = {} + try: + queryset = Estado.objects.all() + serializer = EstadoSerializer(queryset, many=True) + data = serializer.data + 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) + + class LogoutAPIView(APIView): ''' APIView que maneja el cierre de sesión ''' permission_classes = [AllowAny] diff --git a/cosiap_frontend/src/api.js b/cosiap_frontend/src/api.js index 663be533d4257424483c79067d344142b5a8bd31..990e5f5df2064e1f55f13d1f06c0a700f2bd33aa 100644 --- a/cosiap_frontend/src/api.js +++ b/cosiap_frontend/src/api.js @@ -113,7 +113,6 @@ const api = { getById: (id) => ax.get(`api/solicitudes/reportes/${id}`), }, solicitar:{ - get: (params) => ax.get('api/solicitudes/solicitar', {params}), post: (data) => ax.post('api/solicitudes/solicitar', data), update: (id,data) => ax.put(`api/solicitudes/solicitar/${id}`, data) } @@ -130,12 +129,14 @@ const api = { post: (data) => ax.post('api/formularios/opciones/', data), getById: (id) => ax.get(`api/formularios/opciones/${id}`), update: (id, data) => ax.put(`api/formularios/opciones/${id}`, data), + delete: (id) => ax.delete(`api/formularios/opciones/${id}`) }, elementos: { get: () => ax.get('api/formularios/elementos'), post: (data) => ax.post('api/formularios/elementos/', data), getById: (id) => ax.get(`api/formularios/elementos/${id}`), update: (id, data) => ax.put(`api/formularios/elementos/${id}`, data), + delete: (id) => ax.delete(`api/formularios/elementos/${id}`), postElementOption: (elementId, optionId) => ax.post(`/api/formularios/elementos/${elementId}/opcion/${optionId}/`), }, secciones: { @@ -143,13 +144,15 @@ const api = { post: (data) => ax.post('api/formularios/secciones/', data), getById: (id) => ax.get(`api/formularios/secciones/${id}`), update: (id, data) => ax.put(`api/formularios/secciones/${id}`, data), + delete: (id) => ax.delete(`api/formularios/secciones/${id}`), postSectionElement: (sectionId, elementId) => ax.post(`/api/formularios/secciones/${sectionId}/elementos/${elementId}`), }, dynamicForms: { get: () => ax.get('api/formularios'), post: (data) => ax.post('api/formularios/', data), getById: (id) => ax.get(`api/formularios/${id}`), - update: (id, data) => ax.put(`api/formularios/${id}`, data), + update: (id, data) => ax.put(`api/formularios/${id}/`, data), + delete: (id) => ax.delete(`api/formularios/${id}`), postFormSection: (formId, sectionId) => ax.post(`/api/formularios/${formId}/secciones/${sectionId}`), }, respuestas: { diff --git a/cosiap_frontend/src/components/modalidades/CrearModalidad.css b/cosiap_frontend/src/components/modalidades/CrearModalidad.css index 35cec7d50fa0847ae9e595861f9d499a123fe5b5..bb5b4fc4e3328414de29195baf9a308447273934 100644 --- a/cosiap_frontend/src/components/modalidades/CrearModalidad.css +++ b/cosiap_frontend/src/components/modalidades/CrearModalidad.css @@ -165,4 +165,28 @@ input[type="checkbox"] { object-fit: cover; border: 1px solid #ccc; margin-top: 10px; +} + +.card { + border: 1px solid #ddd; + border-radius: 5px; + margin: 15px 0; + padding: 10px; + background-color: #f9f9f9; +} + +.card-header { + font-weight: bold; +} + +.card-body { + padding: 10px; +} + +.option-card { + margin-left: 20px; + border: 1px solid #bbb; + padding: 5px; + border-radius: 5px; + background-color: #e9e9e9; } \ No newline at end of file diff --git a/cosiap_frontend/src/components/modalidades/CrearModalidad.jsx b/cosiap_frontend/src/components/modalidades/CrearModalidad.jsx index ecdb4a7193796b46feb36b486203529bd20c2b4e..b76498b4f69c6fef8e8b3987c84cdc374ab4da67 100644 --- a/cosiap_frontend/src/components/modalidades/CrearModalidad.jsx +++ b/cosiap_frontend/src/components/modalidades/CrearModalidad.jsx @@ -57,13 +57,6 @@ const CreateModalidad = () => { setSections(newSections); }; - // Actualizar el orden de una sección - const updateSectionOrden = (index, orden) => { - const newSections = [...sections]; - newSections[index].orden = Number(orden); // Convertir a número - setSections(newSections); - }; - // Añadir un elemento a una sección const addElementToSection = (sectionIndex) => { const newElement = {name:'', type:'texto_corto', options:[]}; @@ -135,8 +128,8 @@ const CreateModalidad = () => { const sectionIds = sectionResponses.map(res => res.data.data.id); // 3. Asociamos las secciones con el formulario creado - const formSectionsPromises = sectionIds.map((sectionId, index) => - api.dynamicForms.dynamicForms.postFormSection(FormId, sectionId, {orden: sections[index].orden,}) + const formSectionsPromises = sectionIds.map((sectionId) => + api.dynamicForms.dynamicForms.postFormSection(FormId, sectionId) ); await Promise.all(formSectionsPromises); @@ -148,8 +141,8 @@ const CreateModalidad = () => { const elementosResponses = await Promise.all(elementPromises); const elementIds = elementosResponses.map(res => res.data.data.id); - const elementAssociationPromises = elementIds.map((elementId, elementIndex) => - api.dynamicForms.secciones.postSectionElement(sectionIds[sectionIndex], elementId, {orden: section.elements[elementIndex].orden,}) + const elementAssociationPromises = elementIds.map((elementId) => + api.dynamicForms.secciones.postSectionElement(sectionIds[sectionIndex], elementId) ) await Promise.all(elementAssociationPromises); @@ -157,13 +150,13 @@ const CreateModalidad = () => { for (const [elementIndex, element] of section.elements.entries()) { if (element.type === 'opcion_multiple' || element.type === 'desplegable' || element.type === 'casillas') { const optionPromises = element.options.map(option => - api.dynamicForms.opciones.post({ nombre: option }) + api.dynamicForms.opciones.post({ nombre: option.name }) ); const optionResponses = await Promise.all(optionPromises); const optionIds = optionResponses.map(res => res.data.data.id); - const elementOptionPromises = optionIds.map((optionId, optionIndex) => - api.dynamicForms.elementos.postElementOption(elementIds[elementIndex], optionId, {orden: element.options[optionIndex].orden,}) + const elementOptionPromises = optionIds.map((optionId) => + api.dynamicForms.elementos.postElementOption(elementIds[elementIndex], optionId) ); await Promise.all(elementOptionPromises); } @@ -282,17 +275,6 @@ const CreateModalidad = () => { /> -
- - updateSectionOrden(sectionIndex, e.target.value)} - placeholder="Orden de la sección" - required - /> -
- {/* Botón para eliminar sección */}