diff --git a/cosiap_api/common/custom_tests.py b/cosiap_api/common/custom_tests.py index 86b8de6810ccdd60fb8df4a079940ecf4e7e4a54..6585495ff7aa09785121bf77a84977d9184007ea 100644 --- a/cosiap_api/common/custom_tests.py +++ b/cosiap_api/common/custom_tests.py @@ -8,6 +8,7 @@ from rest_framework.response import Response from django.urls import reverse from django.test import tag from urllib.parse import urlencode +from django.db import transaction from users.permisos import es_admin, primer_login from rest_framework.permissions import AllowAny, IsAuthenticated @@ -222,22 +223,23 @@ class PermissionTestCase(BasePerUserTestCase): url_kwargs = self.get_url_kwargs() for method, responses in self.methods_responses.items(): with self.subTest(method=method): - response = self.perform_request(method, self.url_name, url_kwargs=url_kwargs, token=self.user_token, user=self.user) - self.assertEqual(response.status_code, responses.get('user', None), f"Fallo user con metodo {method}") - if response.status_code == responses.get('user', None): - print(f"Exito para user con metodo {method}") - - response = self.perform_request(method, self.url_name, url_kwargs=url_kwargs, token=self.admin_token, user=self.admin_user) - self.assertEqual(response.status_code, responses.get('admin', None), f"Fallo admin con metodo {method}") - if response.status_code == responses.get('admin', None): - print(f"Exito para admin con metodo {method}") - - response = self.perform_request(method, self.url_name, url_kwargs=url_kwargs, token=self.solicitante_token, user=self.solicitante_user) - self.assertEqual(response.status_code, responses.get('solicitante', None), f"Fallo solicitante con metodo {method}") - if response.status_code == responses.get('solicitante', None): - print(f"Exito para solicitante con metodo {method}") - - response = self.perform_request(method, self.url_name, url_kwargs=url_kwargs) - self.assertEqual(response.status_code, responses.get('anonymous', None), f"Fallo anonymous con metodo {method}") - if response.status_code == responses.get('anonymous', None): - print(f"Exito para anonymous con metodo {method}") \ No newline at end of file + with transaction.atomic(): + response = self.perform_request(method, self.url_name, url_kwargs=url_kwargs, token=self.user_token, user=self.user) + self.assertEqual(response.status_code, responses.get('user', None), f"Fallo user con metodo {method}") + if response.status_code == responses.get('user', None): + print(f"Exito para user con metodo {method} ({response.status_code})") + + response = self.perform_request(method, self.url_name, url_kwargs=url_kwargs, token=self.admin_token, user=self.admin_user) + self.assertEqual(response.status_code, responses.get('admin', None), f"Fallo admin con metodo {method}") + if response.status_code == responses.get('admin', None): + print(f"Exito para admin con metodo {method} ({response.status_code})") + + response = self.perform_request(method, self.url_name, url_kwargs=url_kwargs, token=self.solicitante_token, user=self.solicitante_user) + self.assertEqual(response.status_code, responses.get('solicitante', None), f"Fallo solicitante con metodo {method}") + if response.status_code == responses.get('solicitante', None): + print(f"Exito para solicitante con metodo {method} ({response.status_code})") + + response = self.perform_request(method, self.url_name, url_kwargs=url_kwargs) + self.assertEqual(response.status_code, responses.get('anonymous', None), f"Fallo anonymous con metodo {method}") + if response.status_code == responses.get('anonymous', None): + print(f"Exito para anonymous con metodo {method} ({response.status_code})") \ No newline at end of file diff --git a/cosiap_api/common/utils.py b/cosiap_api/common/utils.py index e63ba45c9870a48515eebab68403ac673dc24570..37ce5905695658bacbc0cc7235729f71cdd6e9c3 100644 --- a/cosiap_api/common/utils.py +++ b/cosiap_api/common/utils.py @@ -1,5 +1,5 @@ import json def printDict(diccionario): - #print(json.dumps(diccionario, indent=4, separators=(",", ": "), ensure_ascii=False)) + print(json.dumps(diccionario, indent=2, separators=(",", ": "), ensure_ascii=False)) pass \ No newline at end of file diff --git a/cosiap_api/dynamic_forms/serializers.py b/cosiap_api/dynamic_forms/serializers.py index 2e95c3ff513e7d5efc348d7cc475f10230023443..f6ac41285687c377574e93502630bf0ea012496c 100644 --- a/cosiap_api/dynamic_forms/serializers.py +++ b/cosiap_api/dynamic_forms/serializers.py @@ -9,15 +9,7 @@ from dynamic_forms.models import ( from django.core.validators import MinLengthValidator, MaxLengthValidator from common.serializers import DynamicModelSerializer -class BaseDynamicFormSerializer(serializers.ModelSerializer): - def get_child_queryset(self, obj, lookup_str, debug=False): - child_objs = getattr(obj, lookup_str) - child_objs = child_objs.all() if isinstance(child_objs, models.manager.BaseManager) else child_objs - if debug: - print(f'\nPREFETCH DATA {self.__class__.__name__}({obj}) ::: {obj._prefetched_objects_cache}') if hasattr(obj, '_prefetched_objects_cache') else print(f"\n> {self.__class__.__name__}({obj}) no tiene _prefetched_objects_cache") - print(f'|-CHILD OBJECTS {obj}: {child_objs}') - return child_objs - +class BaseDynamicFormSerializer(serializers.ModelSerializer): def __str__(self): # Representa la clase y el objeto relacionado si existe instance_str = f"{self.instance}" if self.instance else "No instance" @@ -31,85 +23,88 @@ class OpcionSerializer(BaseDynamicFormSerializer): class ElementosOpcionesSerializer(BaseDynamicFormSerializer): - opcion = serializers.SerializerMethodField() + opcion = serializers.PrimaryKeyRelatedField( + queryset=Opcion.objects.all() + ) + elemento = serializers.PrimaryKeyRelatedField( + queryset=Elemento.objects.all(), + write_only=True + ) class Meta: model = ElementosOpciones - fields = ['opcion','orden'] + fields = ['elemento','opcion','orden'] - def get_opcion(self, obj): - ''' Definimos la logica para obtener la representacion de opcion''' - instance = self.get_child_queryset(obj, 'opcion') - return OpcionSerializer(instance).data + def to_representation(self, instance): + representation = super().to_representation(instance) + representation['opcion'] = OpcionSerializer(instance.opcion).data + return representation class ElementoSerializer(BaseDynamicFormSerializer): - opciones = serializers.SerializerMethodField() + opciones = ElementosOpcionesSerializer(source='elementosopciones_set', many=True, read_only=True) class Meta: model = Elemento fields = '__all__' - def get_opciones(self, obj): - ''' Definimos la logica para obtener la representacion de opciones''' - queryset = self.get_child_queryset(obj, 'elementosopciones_set') - return ElementosOpcionesSerializer(queryset, many=True).data + # Serializer para SeccionesElementos class SeccionesElementosSerializer(BaseDynamicFormSerializer): - elemento = serializers.SerializerMethodField() + elemento = serializers.PrimaryKeyRelatedField( + queryset=Elemento.objects.all() + ) + seccion = serializers.PrimaryKeyRelatedField( + queryset=Seccion.objects.all(), + write_only=True + ) class Meta: model = SeccionesElementos - fields = ['elemento','orden'] + fields = ['seccion','elemento','orden'] - def get_elemento(self, obj): - ''' Definimos la logica para obtener la representacion de elemento''' - instance = self.get_child_queryset(obj, 'elemento') - return ElementoSerializer(instance).data + def to_representation(self, instance): + representation = super().to_representation(instance) + representation['elemento'] = ElementoSerializer(instance.elemento).data + return representation # Serializer para Seccion class SeccionSerializer(BaseDynamicFormSerializer): - elementos = serializers.SerializerMethodField() + elementos = SeccionesElementosSerializer(source='seccioneselementos_set', many=True, read_only=True) class Meta: model = Seccion - fields = '__all__' - - def get_elementos(self, obj): - ''' Definimos la logica para obtener la representacion de elementos''' - queryset = self.get_child_queryset(obj, 'seccioneselementos_set') - return SeccionesElementosSerializer(queryset, many=True).data + fields = '__all__' # Serializer para DynamicFormsSecciones class DynamicFormsSeccionesSerializer(BaseDynamicFormSerializer): - seccion = serializers.SerializerMethodField() + seccion = serializers.PrimaryKeyRelatedField( + queryset=Seccion.objects.all() + ) + dynamic_form = serializers.PrimaryKeyRelatedField( + queryset=DynamicForm.objects.all(), + write_only=True + ) class Meta: model = DynamicFormsSecciones - fields = ['seccion','orden'] + fields = ['dynamic_form', 'seccion','orden'] - def get_seccion(self, obj): - ''' Definimos la logica para obtener la representacion de seccion''' - instance = self.get_child_queryset(obj, 'seccion') - return SeccionSerializer(instance).data + def to_representation(self, instance): + representation = super().to_representation(instance) + representation['seccion'] = SeccionSerializer(instance.seccion).data + return representation # Serializer para DynamicForm class DynamicFormSerializer(BaseDynamicFormSerializer): - secciones = serializers.SerializerMethodField() + secciones = DynamicFormsSeccionesSerializer(source='dynamicformssecciones_set', many=True, read_only=True) class Meta: model = DynamicForm fields = '__all__' - def get_secciones(self, obj): - ''' Definimos la logica para obtener la representacion de secciones''' - queryset = self.get_child_queryset(obj, 'dynamicformssecciones_set') - return DynamicFormsSeccionesSerializer(queryset, many=True).data - - - RESPUESTA_MODELOS = { 'RNumerico': RNumerico, diff --git a/cosiap_api/dynamic_forms/tests.py b/cosiap_api/dynamic_forms/tests.py index 4f4866a7e167eaf3cea4c7dd806dc817e849ec79..097493b28e286733eb54aec35c960cf4dd50b772 100644 --- a/cosiap_api/dynamic_forms/tests.py +++ b/cosiap_api/dynamic_forms/tests.py @@ -383,8 +383,150 @@ class ElementoTests(OpcionTests): self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) self.assertEqual(Elemento.objects.count(), self.elemento_count-1) -#TESTS para SeccionAPIView +class TestsPermisosElementosOpciones(c_tests.PermissionTestCase): + url_name = 'dynamic_forms:elementos_opciones' + + def setUp(self): + super().setUp() + self.opcion_t = Opcion.objects.create(nombre='Opcion de Prueba 0') + self.elemento_t = Elemento.objects.create(nombre='Elemento de Prueba 0', tipo=Elemento.Tipo.TEXTO_CORTO) + self.el_op = ElementosOpciones.objects.create(elemento=self.elemento_t, opcion=self.opcion_t, orden=1) + + def get_url_kwargs(self): + return {'elemento': self.elemento_t.pk, 'opcion': self.opcion_t.pk} + + methods_responses = { + 'post': { + 'user': status.HTTP_403_FORBIDDEN, + 'admin': status.HTTP_400_BAD_REQUEST, + 'solicitante': status.HTTP_403_FORBIDDEN, + 'anonymous': status.HTTP_401_UNAUTHORIZED + }, + 'get': { + 'user': status.HTTP_403_FORBIDDEN, + 'admin': status.HTTP_200_OK, + 'solicitante': status.HTTP_200_OK, + 'anonymous': status.HTTP_401_UNAUTHORIZED + }, + 'put': { + 'user': status.HTTP_403_FORBIDDEN, + 'admin': status.HTTP_200_OK, + 'solicitante': status.HTTP_403_FORBIDDEN, + 'anonymous': status.HTTP_401_UNAUTHORIZED + }, + 'delete': { + 'user': status.HTTP_403_FORBIDDEN, + 'admin': status.HTTP_204_NO_CONTENT, + 'solicitante': status.HTTP_403_FORBIDDEN, + 'anonymous': status.HTTP_401_UNAUTHORIZED + } + } + + +class ElementosOpcionesTests(ElementoTests): + def reset(self): + super().reset() + ElementosOpciones.objects.all().delete() + + # Crear instancias de elementos y opciones para las pruebas + self.elemento1 = Elemento.objects.create(nombre='Elemento prueba 1', tipo=Elemento.Tipo.TEXTO_CORTO) + self.elemento2 = Elemento.objects.create(nombre='Elemento prueba 2', tipo=Elemento.Tipo.NUMERICO) + self.opcion1 = Opcion.objects.create(nombre='Opción prueba 1') + self.opcion2 = Opcion.objects.create(nombre='Opción prueba 2') + self.opcion3 = Opcion.objects.create(nombre='Opción prueba 3') + self.opcion4 = Opcion.objects.create(nombre='Opción prueba 4') + self.opcion5 = Opcion.objects.create(nombre='Opción prueba 5') + self.opcion6 = Opcion.objects.create(nombre='Opción prueba 6') + self.opcion7 = Opcion.objects.create(nombre='Opción prueba 7') + + self.elementos_opciones1 = ElementosOpciones.objects.create(elemento=self.elemento1, opcion=self.opcion1) + self.elementos_opciones2 = ElementosOpciones.objects.create(elemento=self.elemento1, opcion=self.opcion2) + self.elementos_opciones_count = 2 + + def tests(self): + subtest_name = 'test_get_elementos_opciones' + with self.subTest(subtest_name): + self.reset() + with CaptureQueriesContext(connection) as ctx: + print(subtest_name) + response = self.perform_request('get', url_name='dynamic_forms:elementos_opciones', url_kwargs={'elemento': self.elemento1.pk, 'opcion': self.opcion1.pk}, token=self.solicitante_token, user=self.solicitante_user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(len(response.data['data']), 2) #esto representa unicamente una opcion: la opcion y su orden + + print(f'\nRENDIMIENTO QUERYS: {len(ctx.captured_queries)}') + + subtest_name = 'test_get_elementos_opciones_incorrect_user' + with self.subTest(subtest_name): + self.reset() + print(subtest_name) + response = self.perform_request('get', url_name='dynamic_forms:elementos_opciones', url_kwargs={'elemento': self.elemento1.pk, 'opcion': self.opcion1.pk}, token=self.user_token, user=self.user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + self.assertFalse('data' in response.data) + + subtest_name = 'test_post_elementos_opciones' + with self.subTest(subtest_name): + self.reset() + print(subtest_name) + data = { + 'elemento': self.elemento1.pk, + 'opcion': self.opcion3.pk + } + response = self.perform_request('post', url_name='dynamic_forms:elementos_opciones', url_kwargs={'elemento': self.elemento1.pk, 'opcion': self.opcion3.pk} , data=data, token=self.admin_token, user=self.admin_user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(ElementosOpciones.objects.count(), self.elementos_opciones_count+1) + + subtest_name = 'test_post_elementos_opciones_bad_request' + with self.subTest(subtest_name): + self.reset() + print(subtest_name) + data = {} + response = self.perform_request('post', url_name='dynamic_forms:elementos_opciones', url_kwargs={'elemento': self.elemento1.pk, 'opcion': 999999999}, data=data, token=self.admin_token, user=self.admin_user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertEqual(ElementosOpciones.objects.count(), self.elementos_opciones_count) + + subtest_name = 'test_put_elementos_opciones' + with self.subTest(subtest_name): + self.reset() + print(subtest_name) + dict_original = self.elementos_opciones1.__dict__.copy() + dict_original.pop('_state', None) + print(dict_original) + data = { + 'orden': 22 + } + response = self.perform_request('put', url_name='dynamic_forms:elementos_opciones', url_kwargs={'elemento': dict_original['elemento_id'], 'opcion': dict_original['opcion_id']}, data=data, token=self.admin_token, user=self.admin_user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(ElementosOpciones.objects.get(pk=self.elementos_opciones1.pk).orden, 22) + + subtest_name = 'test_put_elementos_opciones_bad_request' + with self.subTest(subtest_name): + self.reset() + print(subtest_name) + dict_original = self.elementos_opciones1.__dict__.copy() + dict_original.pop('_state', None) + print(dict_original) + data = { + } + response = self.perform_request('put', url_name='dynamic_forms:elementos_opciones', url_kwargs={'elemento': dict_original['elemento_id'], 'opcion': dict_original['opcion_id']}, data=data, token=self.admin_token, user=self.admin_user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + subtest_name = 'test_delete_elementos_opciones' + with self.subTest(subtest_name): + self.reset() + print(subtest_name) + response = self.perform_request('delete', url_name='dynamic_forms:elementos_opciones', url_kwargs={'elemento': self.elemento1.pk, 'opcion': self.opcion1.pk}, token=self.admin_token, user=self.admin_user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + self.assertEqual(ElementosOpciones.objects.count(), self.elementos_opciones_count-1) + + +#TESTS para SeccionAPIView class TestsPermisosSeccion(c_tests.PermissionTestCase): url_name = 'dynamic_forms:secciones' @@ -553,6 +695,142 @@ class SeccionTests(ElementoTests): self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) self.assertEqual(Seccion.objects.count(), self.seccion_count-1) +class TestsPermisosSeccionesElementos(c_tests.PermissionTestCase): + url_name = 'dynamic_forms:secciones_elementos' + + def setUp(self): + super().setUp() + self.elemento_t = Elemento.objects.create(nombre='Elemento de Prueba 0', tipo=Elemento.Tipo.TEXTO_CORTO) + self.seccion_t = Seccion.objects.create(nombre='Sección de Prueba 0', tipo=Seccion.Tipo.UNICO) + self.sec_el = SeccionesElementos.objects.create(seccion=self.seccion_t, elemento=self.elemento_t, orden=1) + + def get_url_kwargs(self): + return {'seccion': self.seccion_t.pk, 'elemento': self.elemento_t.pk} + + methods_responses = { + 'post': { + 'user': status.HTTP_403_FORBIDDEN, + 'admin': status.HTTP_400_BAD_REQUEST, + 'solicitante': status.HTTP_403_FORBIDDEN, + 'anonymous': status.HTTP_401_UNAUTHORIZED + }, + 'get': { + 'user': status.HTTP_403_FORBIDDEN, + 'admin': status.HTTP_200_OK, + 'solicitante': status.HTTP_200_OK, + 'anonymous': status.HTTP_401_UNAUTHORIZED + }, + 'put': { + 'user': status.HTTP_403_FORBIDDEN, + 'admin': status.HTTP_200_OK, + 'solicitante': status.HTTP_403_FORBIDDEN, + 'anonymous': status.HTTP_401_UNAUTHORIZED + }, + 'delete': { + 'user': status.HTTP_403_FORBIDDEN, + 'admin': status.HTTP_204_NO_CONTENT, + 'solicitante': status.HTTP_403_FORBIDDEN, + 'anonymous': status.HTTP_401_UNAUTHORIZED + } + } + +class SeccionesElementosTests(SeccionTests): + def reset(self): + super().reset() + SeccionesElementos.objects.all().delete() + + # Crear instancias de secciones y elementos para las pruebas + self.seccion1 = Seccion.objects.create(nombre='Sección prueba 1') + self.seccion2 = Seccion.objects.create(nombre='Sección prueba 2') + self.elemento1 = Elemento.objects.create(nombre='Elemento prueba 1', tipo=Elemento.Tipo.TEXTO_CORTO) + self.elemento2 = Elemento.objects.create(nombre='Elemento prueba 2', tipo=Elemento.Tipo.NUMERICO) + + self.secciones_elementos1 = SeccionesElementos.objects.create(seccion=self.seccion1, elemento=self.elemento1) + self.secciones_elementos2 = SeccionesElementos.objects.create(seccion=self.seccion1, elemento=self.elemento2) + self.secciones_elementos_count = 2 + + def tests(self): + subtest_name = 'test_get_secciones_elementos' + with self.subTest(subtest_name): + self.reset() + with CaptureQueriesContext(connection) as ctx: + print(subtest_name) + response = self.perform_request('get', url_name='dynamic_forms:secciones_elementos', url_kwargs={'seccion': self.seccion1.pk, 'elemento': self.elemento1.pk}, token=self.solicitante_token, user=self.solicitante_user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(len(response.data['data']), 2) + + print(f'\nRENDIMIENTO QUERYS: {len(ctx.captured_queries)}') + + subtest_name = 'test_get_secciones_elementos_incorrect_user' + with self.subTest(subtest_name): + self.reset() + print(subtest_name) + response = self.perform_request('get', url_name='dynamic_forms:secciones_elementos', url_kwargs={'seccion': self.seccion1.pk, 'elemento': self.elemento1.pk}, token=self.user_token, user=self.user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + self.assertFalse('data' in response.data) + + subtest_name = 'test_post_secciones_elementos' + with self.subTest(subtest_name): + self.reset() + print(subtest_name) + data = { + 'orden': 44 + } + response = self.perform_request('post', url_name='dynamic_forms:secciones_elementos', url_kwargs={'seccion': self.seccion2.pk, 'elemento': self.elemento2.pk} , data=data, token=self.admin_token, user=self.admin_user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(SeccionesElementos.objects.count(), self.secciones_elementos_count+1) + + subtest_name = 'test_post_secciones_elementos_bad_request' + with self.subTest(subtest_name): + self.reset() + print(subtest_name) + data = {} + response = self.perform_request('post', url_name='dynamic_forms:secciones_elementos', url_kwargs={'seccion': self.seccion2.pk, 'elemento': 999999999}, data=data, token=self.admin_token, user=self.admin_user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertEqual(SeccionesElementos.objects.count(), self.secciones_elementos_count) + + subtest_name = 'test_put_secciones_elementos' + with self.subTest(subtest_name): + self.reset() + print(subtest_name) + dict_original = self.secciones_elementos1.__dict__.copy() + dict_original.pop('_state', None) + print(dict_original) + data = { + 'orden': 22 + } + response = self.perform_request('put', url_name='dynamic_forms:secciones_elementos', url_kwargs={'seccion': dict_original['seccion_id'], 'elemento': dict_original['elemento_id']}, data=data, token=self.admin_token, user=self.admin_user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(SeccionesElementos.objects.get(pk=self.secciones_elementos1.pk).orden, 22) + + subtest_name = 'test_put_secciones_elementos_bad_request' + with self.subTest(subtest_name): + self.reset() + print(subtest_name) + dict_original = self.secciones_elementos1.__dict__.copy() + dict_original.pop('_state', None) + print(dict_original) + data = { + } + response = self.perform_request('put', url_name='dynamic_forms:secciones_elementos', url_kwargs={'seccion': dict_original['seccion_id'], 'elemento': dict_original['elemento_id']}, data=data, token=self.admin_token, user=self.admin_user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + subtest_name = 'test_delete_secciones_elementos' + with self.subTest(subtest_name): + self.reset() + print(subtest_name) + response = self.perform_request('delete', url_name='dynamic_forms:secciones_elementos', url_kwargs={'seccion': self.seccion1.pk, 'elemento': self.elemento1.pk}, token=self.admin_token, user=self.admin_user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + self.assertEqual(SeccionesElementos.objects.count(), self.secciones_elementos_count-1) + + #TESTS para DynamicFormAPIView class TestsPermisosDynamicForm(c_tests.PermissionTestCase): url_name = 'dynamic_forms:dynamic_forms' @@ -668,8 +946,7 @@ class DynamicFormTests(SeccionTests): self.reset() print(subtest_name) data = { - 'nombre': 'Nuevo form', - 'seccion': self.seccion1.pk + 'nombre': 'Nuevo form', } response = self.perform_request('post', url_name='dynamic_forms:dynamic_forms', data=data, token=self.admin_token, user=self.admin_user) printDict(response.data) @@ -725,4 +1002,137 @@ class DynamicFormTests(SeccionTests): self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) self.assertEqual(DynamicForm.objects.count(), self.dynamic_form_count-1) +class TestsPermisosDynamicFormsSecciones(c_tests.PermissionTestCase): + url_name = 'dynamic_forms:dynamic_forms_secciones' + + def setUp(self): + super().setUp() + self.seccion_t = Seccion.objects.create(nombre='Sección de Prueba 0', tipo=Seccion.Tipo.UNICO) + self.formulario_t = DynamicForm.objects.create(nombre='Formulario de Prueba 0') + self.form_sec = DynamicFormsSecciones.objects.create(dynamic_form=self.formulario_t, seccion=self.seccion_t, orden=1) + def get_url_kwargs(self): + return {'formulario': self.formulario_t.pk, 'seccion': self.seccion_t.pk} + + methods_responses = { + 'post': { + 'user': status.HTTP_403_FORBIDDEN, + 'admin': status.HTTP_400_BAD_REQUEST, + 'solicitante': status.HTTP_403_FORBIDDEN, + 'anonymous': status.HTTP_401_UNAUTHORIZED + }, + 'get': { + 'user': status.HTTP_403_FORBIDDEN, + 'admin': status.HTTP_200_OK, + 'solicitante': status.HTTP_200_OK, + 'anonymous': status.HTTP_401_UNAUTHORIZED + }, + 'put': { + 'user': status.HTTP_403_FORBIDDEN, + 'admin': status.HTTP_200_OK, + 'solicitante': status.HTTP_403_FORBIDDEN, + 'anonymous': status.HTTP_401_UNAUTHORIZED + }, + 'delete': { + 'user': status.HTTP_403_FORBIDDEN, + 'admin': status.HTTP_204_NO_CONTENT, + 'solicitante': status.HTTP_403_FORBIDDEN, + 'anonymous': status.HTTP_401_UNAUTHORIZED + } + } + +class DynamicFormsSeccionesTests(DynamicFormTests): + def reset(self): + super().reset() + DynamicFormsSecciones.objects.all().delete() + + # Crear instancias de formularios y secciones para las pruebas + self.formulario1 = DynamicForm.objects.create(nombre='Formulario prueba 1') + self.formulario2 = DynamicForm.objects.create(nombre='Formulario prueba 2') + self.seccion1 = Seccion.objects.create(nombre='Sección prueba 1') + self.seccion2 = Seccion.objects.create(nombre='Sección prueba 2') + + self.forms_secciones1 = DynamicFormsSecciones.objects.create(dynamic_form=self.formulario1, seccion=self.seccion1) + self.forms_secciones2 = DynamicFormsSecciones.objects.create(dynamic_form=self.formulario1, seccion=self.seccion2) + self.forms_secciones_count = 2 + + def tests(self): + subtest_name = 'test_get_forms_secciones' + with self.subTest(subtest_name): + self.reset() + with CaptureQueriesContext(connection) as ctx: + print(subtest_name) + response = self.perform_request('get', url_name='dynamic_forms:dynamic_forms_secciones', url_kwargs={'formulario': self.formulario1.pk, 'seccion': self.seccion1.pk}, token=self.solicitante_token, user=self.solicitante_user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(len(response.data['data']), 2) + + print(f'\nRENDIMIENTO QUERYS: {len(ctx.captured_queries)}') + + subtest_name = 'test_get_forms_secciones_incorrect_user' + with self.subTest(subtest_name): + self.reset() + print(subtest_name) + response = self.perform_request('get', url_name='dynamic_forms:dynamic_forms_secciones', url_kwargs={'formulario': self.formulario1.pk, 'seccion': self.seccion1.pk}, token=self.user_token, user=self.user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + self.assertFalse('data' in response.data) + + + subtest_name = 'test_post_dynamic_forms_secciones' + with self.subTest(subtest_name): + self.reset() + print(subtest_name) + data = { + 'orden': 66 + } + response = self.perform_request('post', url_name='dynamic_forms:dynamic_forms_secciones', url_kwargs={'formulario': self.formulario2.pk, 'seccion': self.seccion2.pk}, data=data, token=self.admin_token, user=self.admin_user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(DynamicFormsSecciones.objects.count(), self.forms_secciones_count + 1) + + subtest_name = 'test_post_dynamic_forms_secciones_bad_request' + with self.subTest(subtest_name): + self.reset() + print(subtest_name) + data = {} + response = self.perform_request('post', url_name='dynamic_forms:dynamic_forms_secciones', url_kwargs={'formulario': self.formulario2.pk, 'seccion': 999999999}, data=data, token=self.admin_token, user=self.admin_user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertEqual(DynamicFormsSecciones.objects.count(), self.forms_secciones_count) + + subtest_name = 'test_put_dynamic_forms_secciones' + with self.subTest(subtest_name): + self.reset() + print(subtest_name) + dict_original = self.forms_secciones1.__dict__.copy() + dict_original.pop('_state', None) + print(dict_original) + data = { + 'orden': 22 + } + response = self.perform_request('put', url_name='dynamic_forms:dynamic_forms_secciones', url_kwargs={'formulario': dict_original['dynamic_form_id'], 'seccion': dict_original['seccion_id']}, data=data, token=self.admin_token, user=self.admin_user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(DynamicFormsSecciones.objects.get(pk=self.forms_secciones1.pk).orden, 22) + + subtest_name = 'test_put_dynamic_forms_secciones_bad_request' + with self.subTest(subtest_name): + self.reset() + print(subtest_name) + dict_original = self.forms_secciones1.__dict__.copy() + dict_original.pop('_state', None) + print(dict_original) + data = {} + response = self.perform_request('put', url_name='dynamic_forms:dynamic_forms_secciones', url_kwargs={'formulario': dict_original['dynamic_form_id'], 'seccion': dict_original['seccion_id']}, data=data, token=self.admin_token, user=self.admin_user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + subtest_name = 'test_delete_dynamic_forms_secciones' + with self.subTest(subtest_name): + self.reset() + print(subtest_name) + response = self.perform_request('delete', url_name='dynamic_forms:dynamic_forms_secciones', url_kwargs={'formulario': self.formulario1.pk, 'seccion': self.seccion1.pk}, token=self.admin_token, user=self.admin_user) + printDict(response.data) + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + self.assertEqual(DynamicFormsSecciones.objects.count(), self.forms_secciones_count - 1) \ No newline at end of file diff --git a/cosiap_api/dynamic_forms/urls.py b/cosiap_api/dynamic_forms/urls.py index 9c81ba69c9bdb9c2e6d9ff253ebaa626da16af50..bcb60100a9ca84cb5702282f542ae66eac173547 100644 --- a/cosiap_api/dynamic_forms/urls.py +++ b/cosiap_api/dynamic_forms/urls.py @@ -1,7 +1,7 @@ from django.urls import path from dynamic_forms.views import ( OpcionAPIView, ElementoAPIView, SeccionAPIView, DynamicFormAPIView, RespuestaAPIView, - #DynamicFormsSeccionesAPIView, ElementosOpcionesAPIView, SeccionesElementosAPIView, + DynamicFormsSeccionesAPIView, ElementosOpcionesAPIView, SeccionesElementosAPIView, ) app_name = 'dynamic_forms' @@ -9,20 +9,17 @@ urlpatterns = [ path('opciones/', OpcionAPIView.as_view(), name='opciones'), path('opciones//', OpcionAPIView.as_view(), name='opciones_pk'), - #path('elementos-opciones/', ElementosOpcionesAPIView.as_view(), name='elementos-opciones'), - #path('elementos-opciones//', ElementosOpcionesAPIView.as_view(), name='elementos-opciones_pk'), + path('elementos//opcion//', ElementosOpcionesAPIView.as_view(), name='elementos_opciones'), path('elementos/', ElementoAPIView.as_view(), name='elementos'), path('elementos//', ElementoAPIView.as_view(), name='elementos_pk'), - - #path('secciones-elementos/', SeccionesElementosAPIView.as_view(), name='secciones_elementos'), - #path('secciones-elementos//', SeccionesElementosAPIView.as_view(), name='secciones_elementos_pk'), + + path('secciones//elementos/', SeccionesElementosAPIView.as_view(), name='secciones_elementos'), path('secciones/', SeccionAPIView.as_view(), name='secciones'), path('secciones//', SeccionAPIView.as_view(), name='secciones_pk'), - #path('forms-secciones/', DynamicFormsSeccionesAPIView.as_view(), name='dynamic_forms_secciones'), - #path('forms-secciones//', DynamicFormsSeccionesAPIView.as_view(), name='dynamic-forms-secciones_pk'), + path('/secciones/', DynamicFormsSeccionesAPIView.as_view(), name='dynamic_forms_secciones'), path('', DynamicFormAPIView.as_view(), name='dynamic_forms'), path('/', DynamicFormAPIView.as_view(), name='dynamic_forms_pk'), diff --git a/cosiap_api/dynamic_forms/views.py b/cosiap_api/dynamic_forms/views.py index b8188927837eb254e6ab5c5424b4484713940819..fc90720438ea52eb5a5c7f2e82ae3f07f05d2bd4 100644 --- a/cosiap_api/dynamic_forms/views.py +++ b/cosiap_api/dynamic_forms/views.py @@ -103,14 +103,32 @@ class OpcionAPIView(BaseFormAPIView): str_plural = 'Opciones' # APIView para ElementosOpciones -''' class ElementosOpcionesAPIView(BaseFormAPIView): model_class = ElementosOpciones serializer_class = ElementosOpcionesSerializer genero_gramatical = True #False masculino, True Femenino str_simple = 'Relación Elemento Opción' str_plural = 'Relaciones Elemento Opción' -''' + + def get(self, request, elemento, opcion): + instance = get_object_or_404(ElementosOpciones, elemento_id=elemento, opcion_id=opcion) + return super().get(request, pk=instance.pk) + + def post(self, request, elemento, opcion): + request.data['elemento'] = elemento + request.data['opcion'] = opcion + return super().post(request) + + def put(self, request, elemento, opcion): + request.data['elemento'] = elemento + request.data['opcion'] = opcion + instance = get_object_or_404(ElementosOpciones, elemento_id=elemento, opcion_id=opcion) + return super().put(request, pk=instance.pk) + + def delete(self, request, elemento, opcion): + instance = get_object_or_404(ElementosOpciones, elemento_id=elemento, opcion_id=opcion) + return super().delete(request, pk=instance.pk) + # APIView para Elemento class ElementoAPIView(BaseFormAPIView): @@ -122,14 +140,31 @@ class ElementoAPIView(BaseFormAPIView): str_plural = 'Elementos' # APIView para SeccionesElementos -''' class SeccionesElementosAPIView(BaseFormAPIView): model_class = SeccionesElementos serializer_class = SeccionesElementosSerializer genero_gramatical = True #False masculino, True Femenino str_simple = 'Relación Sección Elemento' - str_plural = 'Relaciones Sección Elemento' - ''' + str_plural = 'Relaciones Sección Elemento' + + def get(self, request, seccion, elemento): + instance = get_object_or_404(SeccionesElementos, seccion_id=seccion, elemento_id=elemento) + return super().get(request, pk=instance.pk) + + def post(self, request, seccion, elemento): + request.data['seccion'] = seccion + request.data['elemento'] = elemento + return super().post(request) + + def put(self, request, seccion, elemento): + request.data['seccion'] = seccion + request.data['elemento'] = elemento + instance = get_object_or_404(SeccionesElementos, seccion_id=seccion, elemento_id=elemento) + return super().put(request, pk=instance.pk) + + def delete(self, request, seccion, elemento): + instance = get_object_or_404(SeccionesElementos, seccion_id=seccion, elemento_id=elemento) + return super().delete(request, pk=instance.pk) # APIView para Seccion class SeccionAPIView(BaseFormAPIView): @@ -141,14 +176,31 @@ class SeccionAPIView(BaseFormAPIView): str_plural = 'Secciones' # APIView para DynamicFormsSecciones -''' class DynamicFormsSeccionesAPIView(BaseFormAPIView): model_class = DynamicFormsSecciones serializer_class = DynamicFormsSeccionesSerializer genero_gramatical = True #False masculino, True Femenino str_simple = 'Relación Formulario Sección' - str_plural = 'Relaciones Formulario Sección' - ''' + str_plural = 'Relaciones Formulario Sección' + + def get(self, request, formulario, seccion): + instance = get_object_or_404(DynamicFormsSecciones, dynamic_form_id=formulario, seccion_id=seccion) + return super().get(request, pk=instance.pk) + + def post(self, request, formulario, seccion): + request.data['dynamic_form'] = formulario + request.data['seccion'] = seccion + return super().post(request) + + def put(self, request, formulario, seccion): + request.data['dynamic_form'] = formulario + request.data['seccion'] = seccion + instance = get_object_or_404(DynamicFormsSecciones, dynamic_form_id=formulario, seccion_id=seccion) + return super().put(request, pk=instance.pk) + + def delete(self, request, formulario, seccion): + instance = get_object_or_404(DynamicFormsSecciones, dynamic_form_id=formulario, seccion_id=seccion) + return super().delete(request, pk=instance.pk) # APIView para DynamicForm class DynamicFormAPIView(BaseFormAPIView): diff --git a/cosiap_api/entrypoint.sh b/cosiap_api/entrypoint.sh index b25058d09909fe96d9f07d4787af298b41f41396..914602aab7bcc9dca8f29022e89a359e0b954ce5 100644 --- a/cosiap_api/entrypoint.sh +++ b/cosiap_api/entrypoint.sh @@ -18,7 +18,7 @@ done #Django commands >&2 echo "Ejecutando Migraciones" #python3 manage.py makemigrations --name -#python3 manage.py migrate +python3 manage.py migrate #python3 manage.py collectstatic --no-input cron diff --git a/cosiap_api/modalidades/migrations/0002_dynamic_form_modalidades.py b/cosiap_api/modalidades/migrations/0002_dynamic_form_modalidades.py deleted file mode 100644 index a8fd08838fd23cc952a8694356dc85df578e10f2..0000000000000000000000000000000000000000 --- a/cosiap_api/modalidades/migrations/0002_dynamic_form_modalidades.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 5.0.7 on 2024-07-29 17:17 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('dynamic_forms', '0002_creacion_modelos_formularios_dinamicos_02'), - ('modalidades', '0001_creacion_inicial_modulos_dynamic_formats__modalidades__solicitudes'), - ] - - operations = [ - migrations.AddField( - model_name='modalidad', - name='dynamic_form', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='dynamic_forms.dynamicform', verbose_name='Dynamic Form'), - ), - ] diff --git a/cosiap_api/modalidades/migrations/0002_modalidad_dynamic_form.py b/cosiap_api/modalidades/migrations/0002_modalidad_dynamic_form.py deleted file mode 100644 index 76a4d1e6cd9b021526fce327d2beb3709e22e60b..0000000000000000000000000000000000000000 --- a/cosiap_api/modalidades/migrations/0002_modalidad_dynamic_form.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 5.0.7 on 2024-08-08 16:51 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('dynamic_forms', '0006_merge_migrations'), - ('modalidades', '0001_creacion_inicial_modulos_dynamic_formats__modalidades__solicitudes'), - ] - - operations = [ - migrations.AddField( - model_name='modalidad', - name='dynamic_form', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='dynamic_forms.dynamicform', verbose_name='Formulario'), - ), - ]