diff --git a/cosiap_api/cosiap_api/.env b/cosiap_api/cosiap_api/.env index efd2d313abce2ad842d937242cfe1013cdaab054..1b8c473086c249755da5edce9d772d86374b1358 100644 --- a/cosiap_api/cosiap_api/.env +++ b/cosiap_api/cosiap_api/.env @@ -14,8 +14,8 @@ DATABASES_DEFAULT_PORT="3306" EMAIL_HOST="sandbox.smtp.mailtrap.io" EMAIL_FROM="cosiap@example.com" -EMAIL_HOST_USER="dab27aa7ffd16a" -EMAIL_HOST_PASSWORD="59d827a27f4eda" +EMAIL_HOST_USER="3b48193365f615" +EMAIL_HOST_PASSWORD="37f89fc1d98f48" EMAIL_PORT="2525" EMAIL_USE_TLS=True diff --git a/cosiap_api/dynamic_forms/migrations/0006_valor_respuestas_string.py b/cosiap_api/dynamic_forms/migrations/0006_valor_respuestas_string.py new file mode 100644 index 0000000000000000000000000000000000000000..93c8a623fefd9b3ddaafa593112736d9df95d1c4 --- /dev/null +++ b/cosiap_api/dynamic_forms/migrations/0006_valor_respuestas_string.py @@ -0,0 +1,32 @@ +# Generated by Django 5.0.8 on 2024-09-30 19:45 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dynamic_forms', '0005_verbose_name_dynamicformat_dynamicform'), + ] + + operations = [ + migrations.RemoveField( + model_name='rcasillas', + name='valor', + ), + migrations.AlterField( + model_name='rdesplegable', + name='valor', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AlterField( + model_name='ropcionmultiple', + name='valor', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AddField( + model_name='rcasillas', + name='valor', + field=models.CharField(blank=True, max_length=100, null=True), + ), + ] diff --git a/cosiap_api/dynamic_forms/models.py b/cosiap_api/dynamic_forms/models.py index 2d6b294b1e756c4f1ea0bd17503b9ba1ac6694cd..f1be9a835ee1afaad6a0093a6d1aae50191cb0dc 100644 --- a/cosiap_api/dynamic_forms/models.py +++ b/cosiap_api/dynamic_forms/models.py @@ -327,7 +327,7 @@ class RFecha(Respuesta): raise ValidationError("Este campo es Obligatorio.") class ROpcionMultiple(Respuesta): - valor = models.ForeignKey(Opcion, on_delete=models.CASCADE, null=True, blank=True) + valor = models.CharField(max_length=100,null=True, blank=True) otro = models.CharField(max_length=255, verbose_name="Otro", null=True, blank=True) def getStringValue(self): @@ -350,15 +350,15 @@ class ROpcionMultiple(Respuesta): if (not respuesta) and obligatorio: raise ValidationError("Este campo es Obligatorio.") if obligatorio: - if not ((opcOtro and (otro and otro.strip())) or not opcOtro) and (respuesta and respuesta.nombre == 'Otro'): + if not ((opcOtro and (otro and otro.strip())) or not opcOtro) and (respuesta and respuesta == 'Otro'): raise ValidationError("Este campo es obligatorio") - if (otro and otro.strip()) and (respuesta and not respuesta.nombre == 'Otro'): + if (otro and otro.strip()) and (respuesta and not respuesta == 'Otro'): raise ValidationError("No esta seleccionada opcion Otro") - if respuesta and (respuesta.nombre == 'Otro' and not( otro and otro.strip())): + if respuesta and (respuesta == 'Otro' and not( otro and otro.strip())): raise ValidationError("Si eliges 'otro', debes proporcionar más detalles en el campo 'otro'.") class RCasillas(Respuesta): - valor = models.ManyToManyField(Opcion, blank=True) + valor = models.CharField(max_length=100,null=True, blank=True) otro = models.CharField(max_length=255, verbose_name="Otro", null=True, blank=True) def getStringValue(self): @@ -366,7 +366,7 @@ class RCasillas(Respuesta): objs = self.valor.all() for i, obj in enumerate(objs): string += str(obj) - if obj.nombre == 'Otro': + if obj == 'Otro': string += ': '+ str(self.otro) if i < len(objs) - 1: string += ', ' @@ -396,11 +396,11 @@ class RCasillas(Respuesta): class RDesplegable(Respuesta): - valor = models.ForeignKey(Opcion, on_delete=models.CASCADE, null=True, blank=True) + valor = models.CharField(max_length=100,null=True, blank=True) otro = models.CharField(max_length=255, verbose_name="Otro", null=True, blank=True) def getStringValue(self): - if self.valor and self.valor.nombre == 'Otro': + if self.valor and self.valor == 'Otro': return str(self.valor)+': '+str(self.otro) else : if self.valor is None: diff --git a/cosiap_api/solicitudes/respuestas_serializer.py b/cosiap_api/solicitudes/respuestas_serializer.py index d177d3c7c9bb7c4af6a077a1cbe98565e9459707..b6183a6db161a7b9640d79e98d0582618e64656e 100644 --- a/cosiap_api/solicitudes/respuestas_serializer.py +++ b/cosiap_api/solicitudes/respuestas_serializer.py @@ -1,5 +1,5 @@ from rest_framework import serializers -from dynamic_forms.models import Respuesta, Elemento, RegistroFormulario, RegistroSeccion, RNumerico, RCasillas, RDesplegable, RDocumento, RFecha, RHora, ROpcionMultiple, RTextoParrafo, RTextoCorto +from dynamic_forms.models import Opcion, Respuesta, Elemento, RegistroFormulario, RegistroSeccion, RNumerico, RCasillas, RDesplegable, RDocumento, RFecha, RHora, ROpcionMultiple, RTextoParrafo, RTextoCorto class RespuestaSerializer(serializers.Serializer): seccion_id = serializers.IntegerField() @@ -37,7 +37,7 @@ class RespuestaSerializer(serializers.Serializer): respuesta_instance = respuesta_class() if hasattr(respuesta_instance, 'valor'): if not self._validate_value(data.get('valor'), respuesta_instance): - raise serializers.ValidationError("El valor no cumple con el formato esperado.") + raise serializers.ValidationError("El valor del elemento no cumple con el formato esperado.") if hasattr(respuesta_instance, 'otro'): if not self._validate_value(data.get('otro'), respuesta_instance, field_name='otro'): @@ -59,21 +59,11 @@ class RespuestaSerializer(serializers.Serializer): return False return isinstance(value, (int, float)) - if isinstance(respuesta_instance, RTextoCorto) or isinstance(respuesta_instance, RTextoParrafo) or isinstance(respuesta_instance, RDesplegable): + if isinstance(respuesta_instance, RTextoCorto) or isinstance(respuesta_instance, RTextoParrafo) or isinstance(respuesta_instance, RDesplegable)or isinstance(respuesta_instance, ROpcionMultiple) or isinstance(respuesta_instance, RCasillas): return isinstance(value, str) if isinstance(respuesta_instance, RHora) or isinstance(respuesta_instance, RFecha): return isinstance(value, str) - - if isinstance(respuesta_instance, ROpcionMultiple): - try: - value = json.loads(value) - return isinstance(value, list) - except (ValueError, json.JSONDecodeError): - return False - - if isinstance(respuesta_instance, RDocumento): - return hasattr(value, 'read') return True diff --git a/cosiap_frontend/src/App.jsx b/cosiap_frontend/src/App.jsx index 36598c785aaab63dfb8952e9c3f4d401bf580b7c..aa35a90602e7c0af35c1a8245cf287b9c84f80aa 100644 --- a/cosiap_frontend/src/App.jsx +++ b/cosiap_frontend/src/App.jsx @@ -26,6 +26,7 @@ import LayoutBaseNavigation from "@/components/common/layouts/LayoutBaseNavigati import Modalidades from "@/components/modalidades/Modalidades"; import CreateModalidad from "./components/modalidades/CrearModalidad"; import EditModalidad from "./components/modalidades/EditarModalidad"; +import SolicitarModalidad from "./components/modalidades/Modalidad"; function App() { const [viewPageLoader, setViewPageLoader] = useState(false); @@ -95,6 +96,7 @@ function RoutesApp({ setViewPageLoader }) { path="/modalidades" element={} /> + } /> } /> } /> } /> diff --git a/cosiap_frontend/src/api.js b/cosiap_frontend/src/api.js index f819e5d6e132759f3db82f63b71ea0c66280708b..603a0e0ceb0b0ce0482088cb59b671452ddf7916 100644 --- a/cosiap_frontend/src/api.js +++ b/cosiap_frontend/src/api.js @@ -113,7 +113,7 @@ const api = { getById: (id) => ax.get(`api/solicitudes/reportes/${id}`), }, solicitar:{ - post: (data) => ax.post('api/solicitudes/solicitar', data), + post: (data) => ax.post('api/solicitudes/solicitar/', data), update: (id,data) => ax.put(`api/solicitudes/solicitar/${id}`, data) } }, diff --git a/cosiap_frontend/src/components/common/utility/RenderElemento.jsx b/cosiap_frontend/src/components/common/utility/RenderElemento.jsx new file mode 100644 index 0000000000000000000000000000000000000000..14d690ff44f36eb94dcf3c88e4b22a6dee99c3bd --- /dev/null +++ b/cosiap_frontend/src/components/common/utility/RenderElemento.jsx @@ -0,0 +1,120 @@ +import '@/components/modalidades/Modalidad.css' + +export const renderElemento = (seccionId, elemento, handleInputChange) => { + const { tipo, opciones, id, nombre } = elemento; + + const handleChange = (e) => { + const valor = e.target.value; + handleInputChange(seccionId, id, valor); + }; + + switch (tipo) { + case "texto_corto": + return ( + + ); + case "texto_parrafo": + return ( +