diff --git a/cosiap_api/common/nombres_archivos.py b/cosiap_api/common/nombres_archivos.py index 21e00339c3a365577cd88f6d8360b660feeae750..06cb6cdf712d4c028e0721bf8eadda35f2237304 100644 --- a/cosiap_api/common/nombres_archivos.py +++ b/cosiap_api/common/nombres_archivos.py @@ -29,6 +29,9 @@ def nombre_archivo_minuta(instance, filename): def nombre_archivo_convenio(instance, filename): return generar_nombre_archivo(filename, 'convenios/',) +def nombre_archivo_respuesta_doc(instance, filename): + return generar_nombre_archivo(filename, 'respuesta_documentos/',) + def nombre_archivo_modalidad(instance, filename): return generar_nombre_archivo(filename, 'modalidades/', protected=False) diff --git a/cosiap_api/dynamic_forms/admin.py b/cosiap_api/dynamic_forms/admin.py index 8c38f3f3dad51e4585f3984282c2a4bec5349c1e..ffe0913c82a513d2e503bbf4b89e2fbbc608fd74 100644 --- a/cosiap_api/dynamic_forms/admin.py +++ b/cosiap_api/dynamic_forms/admin.py @@ -1,3 +1,25 @@ from django.contrib import admin +from dynamic_forms.models import DynamicForm, DynamicFormsSecciones, \ + Seccion, SeccionesElementos, Elemento, ElementosOpciones, Opcion, \ + RAgregacion, Respuesta, RTextoCorto, RTextoParrafo, RNumerico, \ + RHora, RFecha, ROpcionMultiple, RDesplegable, RCasillas, RDocumento # Register your models here. +admin.site.register(DynamicForm) +admin.site.register(DynamicFormsSecciones) +admin.site.register(Seccion) +admin.site.register(SeccionesElementos) +admin.site.register(Elemento) +admin.site.register(ElementosOpciones) +admin.site.register(Opcion) +admin.site.register(RAgregacion) +admin.site.register(Respuesta) +admin.site.register(RTextoCorto) +admin.site.register(RTextoParrafo) +admin.site.register(RNumerico) +admin.site.register(RHora) +admin.site.register(RFecha) +admin.site.register(ROpcionMultiple) +admin.site.register(RDesplegable) +admin.site.register(RCasillas) +admin.site.register(RDocumento) \ No newline at end of file diff --git a/cosiap_api/dynamic_forms/migrations/0001_creacion_modelos_formularios_dinamicos.py b/cosiap_api/dynamic_forms/migrations/0001_creacion_modelos_formularios_dinamicos.py new file mode 100644 index 0000000000000000000000000000000000000000..4a6fc84f95db915192207a28d7a35bbc6da35591 --- /dev/null +++ b/cosiap_api/dynamic_forms/migrations/0001_creacion_modelos_formularios_dinamicos.py @@ -0,0 +1,214 @@ +# Generated by Django 5.0.7 on 2024-07-24 19:20 + +import common.nombres_archivos +import django.db.models.deletion +from django.db import migrations, models + +def create_otro_option(apps, schema_editor): + Opcion = apps.get_model('dynamic_forms', 'Opcion') + Opcion.objects.create(nombre='Otro') + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('dynamic_formats', '0001_creacion_inicial_modulos_dynamic_formats__modalidades__solicitudes'), + ('solicitudes', '0003_merge_migrations'), + ] + + operations = [ + migrations.CreateModel( + name='DynamicForm', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nombre', models.CharField(max_length=100, verbose_name='Nombre del formulario')), + ], + ), + migrations.CreateModel( + name='Opcion', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nombre', models.CharField(max_length=100, verbose_name='Nombre de la opción')), + ], + ), + migrations.CreateModel( + name='RAgregacion', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ], + ), + migrations.CreateModel( + name='Respuesta', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ], + options={ + 'verbose_name': 'Respuesta', + 'verbose_name_plural': 'Respuestas', + }, + ), + migrations.CreateModel( + name='Seccion', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nombre', models.CharField(max_length=100, verbose_name='Nombre de la sección')), + ('tipo', models.CharField(choices=[('unico', 'Único'), ('agregacion', 'Agregación')], default='unico', max_length=20, verbose_name='Tipo de sección')), + ], + ), + migrations.CreateModel( + name='Elemento', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nombre', models.CharField(max_length=100, verbose_name='Nombre del elemento')), + ('tipo', models.CharField(choices=[('separador', 'Separador'), ('numerico', 'Numérico'), ('texto_corto', 'Texto Corto'), ('texto_parrafo', 'Texto Párrafo'), ('hora', 'Hora'), ('fecha', 'Fecha'), ('opcion_multiple', 'Opción Múltiple'), ('casillas', 'Casillas'), ('desplegable', 'Desplegable'), ('documento', 'Documento')], default='texto_corto', max_length=20, verbose_name='Tipo de elemento')), + ('obligatorio', models.BooleanField(default=True, verbose_name='¿Es obligatorio?')), + ('opcion_otro', models.BooleanField(default=False, verbose_name='¿Opción "otro"?')), + ('min_digits', models.IntegerField(default=0, verbose_name='Mínimo de dígitos')), + ('max_digits', models.IntegerField(default=10, verbose_name='Máximo de dígitos')), + ('formato', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dynamic_formats.dynamicformat', verbose_name='Elemento')), + ], + ), + migrations.CreateModel( + name='ElementosOpciones', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('orden', models.IntegerField(verbose_name='Orden')), + ('elemento', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dynamic_forms.elemento', verbose_name='Elemento')), + ('opcion', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dynamic_forms.opcion', verbose_name='Opción')), + ], + options={ + 'unique_together': {('elemento', 'opcion')}, + }, + ), + migrations.AddField( + model_name='elemento', + name='opciones', + field=models.ManyToManyField(through='dynamic_forms.ElementosOpciones', to='dynamic_forms.opcion', verbose_name='Opciones'), + ), + migrations.CreateModel( + name='RDocumento', + fields=[ + ('respuesta_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='dynamic_forms.respuesta')), + ('valor', models.FileField(blank=True, null=True, upload_to=common.nombres_archivos.nombre_archivo_respuesta_doc, verbose_name='Subir Documento')), + ], + bases=('dynamic_forms.respuesta',), + ), + migrations.CreateModel( + name='RFecha', + fields=[ + ('respuesta_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='dynamic_forms.respuesta')), + ('valor', models.DateField(blank=True, null=True)), + ], + bases=('dynamic_forms.respuesta',), + ), + migrations.CreateModel( + name='RHora', + fields=[ + ('respuesta_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='dynamic_forms.respuesta')), + ('valor', models.TimeField(blank=True, null=True)), + ], + bases=('dynamic_forms.respuesta',), + ), + migrations.CreateModel( + name='RNumerico', + fields=[ + ('respuesta_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='dynamic_forms.respuesta')), + ('valor', models.CharField(blank=True, max_length=255, null=True)), + ], + bases=('dynamic_forms.respuesta',), + ), + migrations.CreateModel( + name='RTextoCorto', + fields=[ + ('respuesta_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='dynamic_forms.respuesta')), + ('valor', models.CharField(blank=True, max_length=255, null=True)), + ], + bases=('dynamic_forms.respuesta',), + ), + migrations.CreateModel( + name='RTextoParrafo', + fields=[ + ('respuesta_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='dynamic_forms.respuesta')), + ('valor', models.TextField(blank=True, null=True)), + ], + bases=('dynamic_forms.respuesta',), + ), + migrations.AddField( + model_name='respuesta', + name='elemento', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dynamic_forms.elemento'), + ), + migrations.AddField( + model_name='respuesta', + name='rAgregacion', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dynamic_forms.ragregacion'), + ), + migrations.AddField( + model_name='respuesta', + name='solicitud', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='solicitudes.solicitud'), + ), + migrations.CreateModel( + name='DynamicFormsSecciones', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('orden', models.IntegerField(verbose_name='Orden')), + ('dynamic_form', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dynamic_forms.dynamicform', verbose_name='Formulario dinámico')), + ('seccion', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dynamic_forms.seccion', verbose_name='Sección')), + ], + options={ + 'unique_together': {('dynamic_form', 'seccion')}, + }, + ), + migrations.AddField( + model_name='dynamicform', + name='secciones', + field=models.ManyToManyField(through='dynamic_forms.DynamicFormsSecciones', to='dynamic_forms.seccion', verbose_name='Secciones'), + ), + migrations.CreateModel( + name='SeccionesElementos', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('orden', models.IntegerField(verbose_name='Orden')), + ('elemento', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dynamic_forms.elemento', verbose_name='Elemento')), + ('seccion', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dynamic_forms.seccion', verbose_name='Sección')), + ], + options={ + 'unique_together': {('seccion', 'elemento')}, + }, + ), + migrations.AddField( + model_name='seccion', + name='elementos', + field=models.ManyToManyField(through='dynamic_forms.SeccionesElementos', to='dynamic_forms.elemento', verbose_name='Elementos'), + ), + migrations.CreateModel( + name='RCasillas', + fields=[ + ('respuesta_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='dynamic_forms.respuesta')), + ('otro', models.CharField(blank=True, max_length=255, null=True, verbose_name='Otro')), + ('valor', models.ManyToManyField(blank=True, to='dynamic_forms.opcion')), + ], + bases=('dynamic_forms.respuesta',), + ), + migrations.CreateModel( + name='RDesplegable', + fields=[ + ('respuesta_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='dynamic_forms.respuesta')), + ('otro', models.CharField(blank=True, max_length=255, null=True, verbose_name='Otro')), + ('valor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dynamic_forms.opcion')), + ], + bases=('dynamic_forms.respuesta',), + ), + migrations.CreateModel( + name='ROpcionMultiple', + fields=[ + ('respuesta_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='dynamic_forms.respuesta')), + ('otro', models.CharField(blank=True, max_length=255, null=True, verbose_name='Otro')), + ('valor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dynamic_forms.opcion')), + ], + bases=('dynamic_forms.respuesta',), + ), + migrations.RunPython(create_otro_option), + ] diff --git a/cosiap_api/dynamic_forms/migrations/0002_creacion_modelos_formularios_dinamicos_02.py b/cosiap_api/dynamic_forms/migrations/0002_creacion_modelos_formularios_dinamicos_02.py new file mode 100644 index 0000000000000000000000000000000000000000..57e16227dd02196c700a402266ebbaca20084ca1 --- /dev/null +++ b/cosiap_api/dynamic_forms/migrations/0002_creacion_modelos_formularios_dinamicos_02.py @@ -0,0 +1,85 @@ +# Generated by Django 5.0.7 on 2024-07-24 19:56 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('dynamic_forms', '0001_creacion_modelos_formularios_dinamicos'), + ] + + operations = [ + migrations.AlterModelOptions( + name='dynamicform', + options={'verbose_name_plural': '01. Formularios'}, + ), + migrations.AlterModelOptions( + name='dynamicformssecciones', + options={'verbose_name_plural': '02. Rel ormulario - Secciones'}, + ), + migrations.AlterModelOptions( + name='elemento', + options={'verbose_name_plural': '05. Elementos'}, + ), + migrations.AlterModelOptions( + name='elementosopciones', + options={'verbose_name_plural': '06. Rel Elemento - Opciones'}, + ), + migrations.AlterModelOptions( + name='opcion', + options={'verbose_name_plural': '07. Opciones'}, + ), + migrations.AlterModelOptions( + name='ragregacion', + options={'verbose_name_plural': '08. Rel Respuestas Agrecacion'}, + ), + migrations.AlterModelOptions( + name='rcasillas', + options={'verbose_name_plural': '16. R Casillas'}, + ), + migrations.AlterModelOptions( + name='rdesplegable', + options={'verbose_name_plural': '17. R Desplegables'}, + ), + migrations.AlterModelOptions( + name='rdocumento', + options={'verbose_name_plural': '18. R Documentos'}, + ), + migrations.AlterModelOptions( + name='respuesta', + options={'verbose_name': 'Respuesta', 'verbose_name_plural': '09. Respuestas'}, + ), + migrations.AlterModelOptions( + name='rfecha', + options={'verbose_name_plural': '14. R Fechas'}, + ), + migrations.AlterModelOptions( + name='rhora', + options={'verbose_name_plural': '13. R Horas'}, + ), + migrations.AlterModelOptions( + name='rnumerico', + options={'verbose_name_plural': '10. R Numericos'}, + ), + migrations.AlterModelOptions( + name='ropcionmultiple', + options={'verbose_name_plural': '15. R Opcion Multiples'}, + ), + migrations.AlterModelOptions( + name='rtextocorto', + options={'verbose_name_plural': '11. R TextoCortos'}, + ), + migrations.AlterModelOptions( + name='rtextoparrafo', + options={'verbose_name_plural': '12. R TextoParrafos'}, + ), + migrations.AlterModelOptions( + name='seccion', + options={'verbose_name_plural': '03. Secciones'}, + ), + migrations.AlterModelOptions( + name='seccioneselementos', + options={'verbose_name_plural': '04. Rel Secciones - Elementos'}, + ), + ] diff --git a/cosiap_api/dynamic_forms/models.py b/cosiap_api/dynamic_forms/models.py index 71a836239075aa6e6e4ecb700e9c42c95c022d91..a439c3ea0acd26fd0abed04391a37e56a6d8c18a 100644 --- a/cosiap_api/dynamic_forms/models.py +++ b/cosiap_api/dynamic_forms/models.py @@ -1,3 +1,304 @@ from django.db import models +from solicitudes.models import Solicitud +from model_utils.managers import InheritanceManager +from django.db import IntegrityError +from dynamic_formats.models import DynamicFormat +from common.nombres_archivos import nombre_archivo_respuesta_doc -# Create your models here. +class Opcion(models.Model): + """ + Modelo con la información de las opciones de los elementos de opción múltiple. + + Campos: + - nombre (str, nombre de la opción.) + """ + nombre = models.CharField(max_length=100, verbose_name='Nombre de la opción') + class Meta: + verbose_name_plural = "" + verbose_name_plural = '07. Opciones' + + +class Elemento(models.Model): + """ + Modelo que define la información de los elementos. + + Campos: + - nombre (str, Nombre del elemento.) + - tipo (str, Indica qué tipo de elemento del formulario es, default Elemento.Tipo.TEXTO_CORTO.) + - obligatorio (bool, Indica si la pregunta es obligatoria, default True.) + - opcion_otro (bool, Indica si está habilitada la opción "otro" en preguntas de opción múltiple, default False.) + - min_digits (int, Indica el número mínimo de dígitos permitido para un campo de tipo numérico, default 0.) + - max_digits (int, Indica el número máximo de dígitos permitido para un campo de tipo numérico, default 10.) + """ + class Tipo(models.TextChoices): + SEPARADOR = 'separador', 'Separador' + NUMERICO = 'numerico', 'Numérico' + TEXTO_CORTO = 'texto_corto', 'Texto Corto' + TEXT_PARRAFO = 'texto_parrafo', 'Texto Párrafo' + HORA = 'hora', 'Hora' + FECHA = 'fecha', 'Fecha' + OPCION_MULTIPLE = 'opcion_multiple', 'Opción Múltiple' + CASILLAS = 'casillas', 'Casillas' + DESPLEGABLE = 'desplegable', 'Desplegable' + DOCUMENTO = 'documento', 'Documento' + + nombre = models.CharField(max_length=100, verbose_name='Nombre del elemento') + tipo = models.CharField(max_length=20, choices=Tipo.choices, default=Tipo.TEXTO_CORTO, verbose_name='Tipo de elemento') + obligatorio = models.BooleanField(default=True, verbose_name='¿Es obligatorio?') + opcion_otro = models.BooleanField(default=False, verbose_name='¿Opción "otro"?') + min_digits = models.IntegerField(default=0, verbose_name='Mínimo de dígitos') + max_digits = models.IntegerField(default=10, verbose_name='Máximo de dígitos') + + opciones = models.ManyToManyField(Opcion, through='ElementosOpciones', verbose_name='Opciones') + formato = models.ForeignKey(DynamicFormat, on_delete=models.SET_NULL, verbose_name='Elemento', default=None, null=True, blank=True) + class Meta: + verbose_name_plural = '05. Elementos' + + +class ElementosOpciones(models.Model): + """ + Modelo que contiene la información de las relaciones ManyToMany entre Elemento y Opcion. + + Campos: + - elemento (Elemento, Elemento de la relación.) + - opcion (Opcion, Opción de la relación.) + - orden (int, Orden de la Opción en el elemento.) + """ + elemento = models.ForeignKey(Elemento, on_delete=models.CASCADE, verbose_name='Elemento') + opcion = models.ForeignKey(Opcion, on_delete=models.CASCADE, verbose_name='Opción') + orden = models.IntegerField(verbose_name='Orden') + class Meta: + unique_together = ('elemento', 'opcion') + verbose_name_plural = '06. Rel Elemento - Opciones' + +class Seccion(models.Model): + """ + Modelo que contiene la información de una Sección de un formulario dinámico. + + Campos: + - nombre (str, Nombre de la sección.) + - tipo (str, Tipo de sección, default Seccion.Tipo.UNICO) + """ + class Tipo(models.TextChoices): + UNICO = 'unico', 'Único' + AGREGACION = 'agregacion', 'Agregación' + + nombre = models.CharField(max_length=100, verbose_name='Nombre de la sección') + tipo = models.CharField(max_length=20, choices=Tipo.choices, default=Tipo.UNICO, verbose_name='Tipo de sección') + + elementos = models.ManyToManyField(Elemento, through='SeccionesElementos', verbose_name='Elementos') + class Meta: + verbose_name_plural = '03. Secciones' + + +class SeccionesElementos(models.Model): + """ + Modelo que contiene la información de las relaciones ManyToMany entre Sección y Elemento. + + Campos: + - seccion (Seccion, Sección de la relación.) + - elemento (Elemento, Elemento de la relación.) + - orden (int, Orden del Elemento en la sección.) + """ + seccion = models.ForeignKey(Seccion, on_delete=models.CASCADE, verbose_name='Sección') + elemento = models.ForeignKey(Elemento, on_delete=models.CASCADE, verbose_name='Elemento') + orden = models.IntegerField(verbose_name='Orden') + class Meta: + unique_together = ('seccion', 'elemento') + verbose_name_plural = '04. Rel Secciones - Elementos' + + +class DynamicForm(models.Model): + """ + Modelo que contiene la información de un DynamicForm. + + Campos: + - nombre (str, Nombre del formulario dinámico) + """ + nombre = models.CharField(max_length=100, verbose_name='Nombre del formulario') + secciones = models.ManyToManyField(Seccion, through='DynamicFormsSecciones', verbose_name='Secciones') + class Meta: + verbose_name_plural = "01. Formularios" + +class DynamicFormsSecciones(models.Model): + """ + Modelo que contiene la información de las relaciones ManyToMany entre DynamicForm y Sección. + + Campos: + - dynamic_form (DynamicForm, DynamicForm de la relación.) + - seccion (Seccion, Sección de la relación.) + - orden (int, Orden de la Sección en el formulario.) + """ + dynamic_form = models.ForeignKey(DynamicForm, on_delete=models.CASCADE, verbose_name='Formulario dinámico') + seccion = models.ForeignKey(Seccion, on_delete=models.CASCADE, verbose_name='Sección') + orden = models.IntegerField(verbose_name='Orden') + class Meta: + unique_together = ('dynamic_form', 'seccion') + verbose_name_plural = '02. Rel ormulario - Secciones' + + +class RAgregacion(models.Model): + ''' + Modelo que define el id de una lista de respuestas de una seccion de agregcion + Campos: + -id (id) has + ''' + class Meta: + verbose_name_plural = '08. Rel Respuestas Agrecacion' + +class Respuesta(models.Model): + ''' + Modelo que define la infromacion abstracta de una respuesta. + + Campos: + - rAgregacion (RAgregacion, lista de seccion Agregacion a la que pertenece la respuesta.) + - solicitud (Solicitud, solicitud a la que pertenece la respuesta.) + - elemento (Elemento, elemento al que pertenece la respuesta.) + - otro (None, Campo donde se almacena la opcion otro, no definido en esta clase) + ''' + rAgregacion = models.ForeignKey(RAgregacion, on_delete=models.CASCADE, null=True, blank=True) + solicitud = models.ForeignKey(Solicitud, on_delete=models.CASCADE) + elemento = models.ForeignKey(Elemento, on_delete=models.CASCADE) + valor = None + otro = None + + objects = InheritanceManager() + + def __str__(self): + return f"Respuesta {type(self)} - Elemento: {self.elemento} - Solicitante: {self.solicitante_id}" + + def save(self, *args, **kwargs): + if self._state.adding: + # Solo realiza la verificación si estás creando una respuesta nueva + if self.elemento.seccion.tipo == 'unico': + # Verificar si ya existe una respuesta para esta combinación + if Respuesta.objects.filter(elemento=self.elemento, solicitante=self.solicitante).exists(): + raise IntegrityError('Ya existe una respuesta para este elemento y solicitante') + super().save(*args, **kwargs) + + class Meta: + verbose_name = 'Respuesta' + verbose_name_plural = '09. Respuestas' + + + def getStringValue(self): + return 'Respuesta no Implementado' + + +class RNumerico(Respuesta): + valor = models.CharField(max_length=255, null=True, blank=True) + + def getStringValue(self): + if self.valor is None: + return '-----' + else : + return str(self.valor) + class Meta: + verbose_name_plural = '10. R Numericos' + + +class RTextoCorto(Respuesta): + valor = models.CharField(max_length=255, null=True, blank=True) + + def getStringValue(self): + if self.valor is None: + return '-----' + else : + return str(self.valor) + class Meta: + verbose_name_plural = '11. R TextoCortos' + + +class RTextoParrafo(Respuesta): + valor = models.TextField(null=True, blank=True) + + def getStringValue(self): + if self.valor is None: + return '-----' + else : + return str(self.valor) + class Meta: + verbose_name_plural = '12. R TextoParrafos' + + +class RHora(Respuesta): + valor = models.TimeField(null=True, blank=True) + + def getStringValue(self): + if self.valor is None: + return '-----' + else : + return str(self.valor) + class Meta: + verbose_name_plural = '13. R Horas' + + +class RFecha(Respuesta): + valor = models.DateField(null=True, blank=True) + + def getStringValue(self): + if self.valor is None: + return '-----' + else : + return str(self.valor) + class Meta: + verbose_name_plural = '14. R Fechas' + +class ROpcionMultiple(Respuesta): + valor = models.ForeignKey(Opcion, on_delete=models.CASCADE, 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': + return str(self.valor)+': '+str(self.otro) + else : + if self.valor is None: + return '-----' + else : + return str(self.valor) + class Meta: + verbose_name_plural = '15. R Opcion Multiples' + +class RCasillas(Respuesta): + valor = models.ManyToManyField(Opcion, blank=True) + otro = models.CharField(max_length=255, verbose_name="Otro", null=True, blank=True) + + def getStringValue(self): + string = '' + objs = self.valor.all() + for i, obj in enumerate(objs): + string += str(obj) + if obj.nombre == 'Otro': + string += ': '+ str(self.otro) + if i < len(objs) - 1: + string += ', ' + if string == '': + return '-----' + else : + return string + class Meta: + verbose_name_plural = '16. R Casillas' + + +class RDesplegable(Respuesta): + valor = models.ForeignKey(Opcion, on_delete=models.CASCADE, 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': + return str(self.valor)+': '+str(self.otro) + else : + if self.valor is None: + return '-----' + else : + return str(self.valor) + class Meta: + verbose_name_plural = '17. R Desplegables' + +class RDocumento(Respuesta): + valor = models.FileField(verbose_name='Subir Documento', upload_to=nombre_archivo_respuesta_doc , null=True, blank=True) + + def getStringValue(self): + return self.valor.name if self.valor else '-----' + class Meta: + verbose_name_plural = '18. R Documentos'