diff --git a/tecnicas/admin.py b/tecnicas/admin.py index d7219cac074557f3e2a7359c6f1a2715c630a8f3..44ab063ed71fdc05d3134bc4ebf6998ace41d14a 100644 --- a/tecnicas/admin.py +++ b/tecnicas/admin.py @@ -14,7 +14,7 @@ from .models import Producto, Participacion from .models import Orden, Posicion -from .models import Dato, ValorDecimal, ValorBooleano, Calificacion, ListaPalabras +from .models import Dato, ValorDecimal, ValorBooleano, Calificacion, ListaPalabras, GrupoProducto # Register your models here. admin.site.register(CategoriaTecnica) @@ -47,3 +47,4 @@ admin.site.register(ValorDecimal) admin.site.register(ValorBooleano) admin.site.register(Calificacion) admin.site.register(ListaPalabras) +admin.site.register(GrupoProducto) diff --git a/tecnicas/controllers/__init__.py b/tecnicas/controllers/__init__.py index 0ee51c10274ba128f39f4ec81cc8d8e959616bf8..9221c48c567fe62e62100d0ac07d5d2c1393c1e2 100644 --- a/tecnicas/controllers/__init__.py +++ b/tecnicas/controllers/__init__.py @@ -16,18 +16,26 @@ from .views_controller.create_session.panel_basic_controller import PanelBasicCo from .views_controller.create_session.panel_tags_controller import PanelTagsController from .views_controller.create_session.panel_codes_controller import PanelCodesController from .views_controller.create_session.panel_words_controller import PanelWordsController -from .views_controller.create_session.panel_create_controller import PanelCreateController -from .views_controller.session_management.details_controller import DetallesController -from .views_controller.session_management.details_escala_controller import DetallesEscalasController -from .views_controller.session_management.details_rata_controller import DetallesRATAController -from .views_controller.session_management.details_cata_controller import DetallesCATAController -from .views_controller.session_management.details_pf_controller import DetallesPFController +from .views_controller.create_session.panels_create.panel_create_escalas_controller import PanelCreateEscalasController +from .views_controller.create_session.panels_create.panel_create_rata_controller import PanelCreateRataController +from .views_controller.create_session.panels_create.panel_create_cata_controller import PanelCreateCataController +from .views_controller.create_session.panels_create.panel_create_pf_controller import PanelCreatePFController +from .views_controller.create_session.panels_create.panel_create_sort_controller import PanelCreateSortController +from .views_controller.create_session.panels_create.panel_create_napping_controller import PanelCreateNappingController -from .views_controller.session_management.monitor_controller import MonitorController -from .views_controller.session_management.monitor_escalas_controller import MonitorEscalasController -from .views_controller.session_management.monitor_rata_controller import MonitorRATAController -from .views_controller.session_management.monitor_pf_controller import MonitorPFController + +from .views_controller.session_management.details.details_controller import DetallesController +from .views_controller.session_management.details.details_escala_controller import DetallesEscalasController +from .views_controller.session_management.details.details_rata_controller import DetallesRATAController +from .views_controller.session_management.details.details_cata_controller import DetallesCATAController +from .views_controller.session_management.details.details_pf_controller import DetallesPFController +from .views_controller.session_management.details.details_sort_controller import DetallesSortController + +from .views_controller.session_management.monitor.monitor_escalas_controller import MonitorEscalasController +from .views_controller.session_management.monitor.monitor_rata_controller import MonitorRATAController +from .views_controller.session_management.monitor.monitor_pf_controller import MonitorPFController +from .views_controller.session_management.monitor.monitor_sort_controller import MonitorSortController from .views_controller.sessions_tester.login_session_tester_controller import LoginSessionTesterController from .views_controller.sessions_tester.list_sessions_tester_controller import ListSessionsTesterController @@ -36,10 +44,12 @@ from .views_controller.sessions_tester.tests_forms.test_scales_controller import from .views_controller.sessions_tester.tests_forms.test_rata_controller import TestRataController from .views_controller.sessions_tester.tests_forms.test_cata_controller import TestCataController from .views_controller.sessions_tester.tests_forms.test_pf_controller import TestPFController +from .views_controller.sessions_tester.tests_forms.test_sort_controller import TestSortController from .views_controller.sessions_tester.init_session.init_session_escalas_controller import InitSessionEscalasController from .views_controller.sessions_tester.init_session.init_session_rata_controller import InitSessionRATAController from .views_controller.sessions_tester.init_session.init_session_pf_controller import InitSessionPFController +from .views_controller.sessions_tester.init_session.init_session_sort_controller import InitSessionSortController from .views_controller.vocabulary_manage.create_vocabulary_controller import CreateVocabularyController from .views_controller.vocabulary_manage.list_vocabulary_controller import ListVocabularyController @@ -48,3 +58,4 @@ from .api_controller.rating_sacales_controller import RatingScalesController from .api_controller.rating_cata_controller import RatingCataController from .api_controller.rating_pf_list_controller import RatingPFListController from .views_controller.tester_list_controller import TesterListController +from .api_controller.rating_sort_controller import RatingSortController diff --git a/tecnicas/controllers/api_controller/rating_sort_controller.py b/tecnicas/controllers/api_controller/rating_sort_controller.py new file mode 100644 index 0000000000000000000000000000000000000000..c7f105bbabb19f9b7ab091596c55a144179301c9 --- /dev/null +++ b/tecnicas/controllers/api_controller/rating_sort_controller.py @@ -0,0 +1,67 @@ +from django.http import JsonResponse, HttpRequest +from django.db import transaction +from tecnicas.models import Participacion, Palabra, GrupoProducto, Producto + + +class RatingSortController(): + def __init__(self): + pass + + @staticmethod + def saveRating(request: HttpRequest, data: list[dict]): + try: + with transaction.atomic(): + participation = Participacion.objects.get( + id=request.session["id_participation"]) + + technique = participation.tecnica + catador = participation.catador + + # Obtener productos de la técnica + technique_products = Producto.objects.filter( + id_tecnica=technique) + technique_product_ids = set(p.id for p in technique_products) + + # Recolectar IDs de productos enviados + sent_product_ids = set() + for group in data: + for product in group["products"]: + sent_product_ids.add(int(product["id"])) + + # Validar que los productos enviados existan en la técnica + if not sent_product_ids.issubset(technique_product_ids): + return JsonResponse({"error": "Productos enviados no pertenecen a la técnica"}) + + # Validar que todos los productos de la técnica estén presentes + if sent_product_ids != technique_product_ids: + return JsonResponse({"error": "Faltan productos por clasificar"}) + + for group in data: + words_data = group["words"] + products_data = group["products"] + + # Crear u obtener palabras + words_objs = [] + for word_name in words_data: + word, created = Palabra.objects.get_or_create(nombre_palabra=word_name) + words_objs.append(word) + + # Crear GrupoProducto + group_product = GrupoProducto.objects.create( + tecnica=technique, + catador=catador + ) + + # Asignar palabras + group_product.palabras.set(words_objs) + + # Asignar productos + product_ids = [p["id"] for p in products_data] + group_product.productos.set(product_ids) + + return JsonResponse({"message": "Valores guardados"}) + except Participacion.DoesNotExist: + return JsonResponse({"error": "Participación no encontrada"}) + except Exception as e: + print(f"Error de calificacion: {e}") + return JsonResponse({"error": "Error al guardar los datos"}) diff --git a/tecnicas/controllers/models_controller/tecnica_controller.py b/tecnicas/controllers/models_controller/tecnica_controller.py index 71265258841e5c3bcbc1843d6438bfa749275262..30403356cf310c8ed2b1bf57790a2d140657eafb 100644 --- a/tecnicas/controllers/models_controller/tecnica_controller.py +++ b/tecnicas/controllers/models_controller/tecnica_controller.py @@ -16,7 +16,7 @@ class TecnicaController(): def setTechniqueFromBasicData(self, basic): self.technique = Tecnica( tipo_tecnica=TipoTecnica.objects.get(nombre_tecnica=basic["name_tecnica"]), - id_estilo=EstiloPalabra.objects.get(id=basic["estilo_palabras"]), + id_estilo=EstiloPalabra.objects.get(nombre_estilo=basic["estilo_palabras"]), repeticiones_max=basic["numero_repeticiones"] or 1, limite_catadores=basic["numero_catadores"], instrucciones=basic["instrucciones"] or "Espere instrucciones del Presentador", diff --git a/tecnicas/controllers/views_controller/create_session/panel_basic_controller.py b/tecnicas/controllers/views_controller/create_session/panel_basic_controller.py index 4b336e39a3e41fba805fe7d1dd38a7ab7ea69549..ff5aef6023629a56c115dff41cc7b6259696c469 100644 --- a/tecnicas/controllers/views_controller/create_session/panel_basic_controller.py +++ b/tecnicas/controllers/views_controller/create_session/panel_basic_controller.py @@ -1,4 +1,4 @@ -from tecnicas.forms import SesionBasicForm, SesionBasicCATAForm, SesionBasicPFForm +from tecnicas.forms import SesionBasicForm, SesionBasicCATAForm, SesionBasicPFForm, SesionBasicSortForm, SesionBasicNappingForm from django.http import HttpRequest from django.shortcuts import redirect, render from django.urls import reverse @@ -10,9 +10,11 @@ class PanelBasicController(): "numero_repeticiones": 1 } - url_panel_basic = "tecnicas/create_sesion/configuracion-panel-basic.html" + url_panel_basic = "tecnicas/create_sesion/conf-panel-basic.html" url_panel_basic_cata = "tecnicas/create_sesion/panel-basic-cata.html" url_panel_basic_pf = "tecnicas/create_sesion/panel-basic-pf.html" + url_panel_basic_sort = "tecnicas/create_sesion/panel-basic-sort.html" + url_panel_basic_napping = "tecnicas/create_sesion/panel-basic-napping.html" url_next_panel_tags = "cata_system:panel_configuracion_tags" url_next_panel_codes = "cata_system:panel_configuracion_codes" @@ -43,7 +45,7 @@ class PanelBasicController(): if form.is_valid(): values = {} for name, value in form.cleaned_data.items(): - if name == "estilo_palabras" or name == "tipo_escala": + if name == "tipo_escala": values[name] = value.id else: values[name] = value @@ -84,7 +86,7 @@ class PanelBasicController(): if form.is_valid(): values = {} for name, value in form.cleaned_data.items(): - if name == "estilo_palabras" or name == "tipo_escala": + if name == "tipo_escala": values[name] = value.id else: values[name] = value @@ -132,10 +134,7 @@ class PanelBasicController(): if form.is_valid(): values = {} for name, value in form.cleaned_data.items(): - if name == "estilo_palabras": - values[name] = value.id - else: - values[name] = value + values[name] = value values["name_tecnica"] = name_tecnica request.session['form_basic'] = values @@ -164,7 +163,6 @@ class PanelBasicController(): form = SesionBasicPFForm(request.POST) if form.is_valid(): - print(form.cleaned_data) values = {} for name, value in form.cleaned_data.items(): values[name] = value @@ -178,3 +176,65 @@ class PanelBasicController(): "form_sesion": form, "error": "Información no valida"}) return response + + @staticmethod + def controllGetSort(request: HttpRequest): + form_sesion = SesionBasicSortForm() + + view_context = { + "form_sesion": form_sesion, + "use_technique": "sort" + } + + return render( + request, PanelBasicController.url_panel_basic_sort, view_context) + + @staticmethod + def controllPostSort(request: HttpRequest, name_tecnica: str): + form = SesionBasicSortForm(request.POST) + + if form.is_valid(): + values = {} + for name, value in form.cleaned_data.items(): + values[name] = value + + values["name_tecnica"] = name_tecnica + request.session['form_basic'] = values + response = redirect( + reverse(PanelBasicController.url_next_panel_codes)) + else: + response = render(request, PanelBasicController.url_panel_basic_sort, { + "form_sesion": form, "error": "Información no valida"}) + + return response + + @staticmethod + def controllGetNapping(request: HttpRequest): + form_sesion = SesionBasicNappingForm() + + view_context = { + "form_sesion": form_sesion, + "use_technique": "napping" + } + + return render( + request, PanelBasicController.url_panel_basic_napping, view_context) + + @staticmethod + def controllPostNapping(request: HttpRequest, name_tecnica: str): + form = SesionBasicNappingForm(request.POST) + + if form.is_valid(): + values = {} + for name, value in form.cleaned_data.items(): + values[name] = value + + values["name_tecnica"] = name_tecnica + request.session['form_basic'] = values + response = redirect( + reverse(PanelBasicController.url_next_panel_codes)) + else: + response = render(request, PanelBasicController.url_panel_basic_napping, { + "form_sesion": form, "error": "Información no valida"}) + + return response diff --git a/tecnicas/controllers/views_controller/create_session/panel_codes_controller.py b/tecnicas/controllers/views_controller/create_session/panel_codes_controller.py index 1bf68ba805beee53dcd109f6b75e851e018513a1..9488be3de2ee34951e292860c64d59ccd920f398 100644 --- a/tecnicas/controllers/views_controller/create_session/panel_codes_controller.py +++ b/tecnicas/controllers/views_controller/create_session/panel_codes_controller.py @@ -7,7 +7,7 @@ import json class PanelCodesController(): - url_current_panel = "tecnicas/create_sesion/configuracion-panel-codes.html" + url_current_panel = "tecnicas/create_sesion/conf-panel-codes.html" url_words = "cata_system:panel_configuracion_words" url_create_session = "cata_system:creando_sesion" @@ -66,7 +66,7 @@ class PanelCodesController(): return render(request, PanelCodesController.url_current_panel, context_codes_form) @staticmethod - def controllGetRATA(request: HttpRequest, data, name_technique: str): + def controllGetWithoutOrders(request: HttpRequest, data, name_technique: str): num_products = data["numero_productos"] codes_products = generarCodigos(num_products) form_codes = CodesForm(codes=codes_products) @@ -80,7 +80,7 @@ class PanelCodesController(): return render(request, PanelCodesController.url_current_panel, context_codes_form) @staticmethod - def controllPostRATA(request: HttpRequest, is_rata=True): + def controllPostWithWords(request: HttpRequest, name_technique: str): codes = [] context_codes_form = {} @@ -92,7 +92,7 @@ class PanelCodesController(): context_codes_form = { "form_codes": form_codes, - "use_technique": "rata" if is_rata else "cata" + "use_technique": name_technique } if form_codes.is_valid(): @@ -117,7 +117,7 @@ class PanelCodesController(): return render(request, PanelCodesController.url_current_panel, context_codes_form) @staticmethod - def controllPostPF(request: HttpRequest): + def controllPostWithoutOrdersWords(request: HttpRequest, name_technique: str): codes = [] context_codes_form = {} @@ -129,7 +129,7 @@ class PanelCodesController(): context_codes_form = { "form_codes": form_codes, - "use_technique": "perfil flash" + "use_technique": name_technique } if form_codes.is_valid(): diff --git a/tecnicas/controllers/views_controller/create_session/panel_create_controller.py b/tecnicas/controllers/views_controller/create_session/panel_create_controller.py deleted file mode 100644 index afa0f59014213ec847e4219fdf576e1b846424e7..0000000000000000000000000000000000000000 --- a/tecnicas/controllers/views_controller/create_session/panel_create_controller.py +++ /dev/null @@ -1,540 +0,0 @@ -from django.http import HttpRequest, JsonResponse -from django.db import transaction -from django.shortcuts import render -from tecnicas.utils import general_error -from tecnicas.models import EsAtributo, EsVocabulario, Vocabulario, Tecnica, TipoTecnica, EstiloPalabra, Producto, Palabra, SesionSensorial, Escala, TipoEscala, EtiquetasEscala -from tecnicas.controllers import TecnicaController, EscalaController, ProductosController, OrdenesController, EstiloPalabrasController, PalabrasController, SesionController -from tecnicas.utils import deleteDataSession - - -class PanelCreateController(): - def __init__(self): - pass - - @staticmethod - def controllGetEscalas(request: HttpRequest): - return render( - request, 'tecnicas/create_sesion/creando_sesion.html') - - @staticmethod - def controllPostEscalas(request: HttpRequest): - if request.POST.get('action') == 'create_session': - if not request.session.get("form_tags") or not request.session.get("form_codes") or not request.session.get("form_words"): - deleteDataSession(request) - return general_error("No se ha especificado información necesaria para la creación de la sesión, por favor, vuelve a intentarlo") - try: - with transaction.atomic(): - # ////////////////////////////////////////////////////// # - # - # First step: Create technique and scale with their tags # - # - # ////////////////////////////////////////////////////// # - data_basic = request.session["form_basic"] - controllerTechnique = TecnicaController() - controllerTechnique.setTechniqueFromBasicData( - basic=data_basic) - technique = controllerTechnique.saveTechnique() - if not technique: - raise ValueError("Error al guardar la técnica") - - data_scale = { - "id_scale": data_basic["tipo_escala"], - "size": data_basic["tamano_escala"], - "technique": technique - } - - controllerScale = EscalaController(data=data_scale) - - scale = controllerScale.saveScale() - if isinstance(scale, dict): - raise ValueError(scale["error"]) - - dict_tags = request.session["form_tags"] - saved_related_tags = controllerScale.realteTags(dict_tags) - if "error" in saved_related_tags: - raise ValueError(saved_related_tags["error"]) - - # ////////////////////////////////////////////////////////// # - # - # Second step: Create orders, productos and set the position # - # - # ////////////////////////////////////////////////////////// # - data_codes = request.session["form_codes"] - - list_codes_dict = data_codes["product_codes"] - - codes = [] - for product in list_codes_dict: - code = next(iter(product.values())) - codes.append(code) - - controllerProducts = ProductosController( - codes=codes, - technique=technique - ) - - controllerProducts.setProductsNoSave() - saved_prodcuts = controllerProducts.saveProducts() - if isinstance(saved_prodcuts, dict): - raise ValueError(saved_prodcuts["error"]) - - raw_sort_codes = data_codes["sort_codes"] - controllerOrdes = OrdenesController( - raw_orders=raw_sort_codes, - list_products=saved_prodcuts, - technique=technique - ) - - controllerOrdes.setOrdersToSave() - saved_orders = controllerOrdes.saveOrders() - if isinstance(saved_orders, dict): - raise ValueError(saved_orders["error"]) - - seded_positions = controllerOrdes.setPositions() - if isinstance(seded_positions, dict): - raise ValueError(seded_positions["error"]) - - saved_postions = controllerOrdes.savePositions() - if isinstance(saved_postions, dict): - raise ValueError(saved_prodcuts["error"]) - - # /////////////////////////////////////////////////////// # - # - # Third step: Create relations technique with Words Style # - # - # /////////////////////////////////////////////////////// # - style_words = technique.id_estilo.nombre_estilo - if style_words == "atributos": - ids_words = request.session["form_words"] - words_controller = PalabrasController(ids=ids_words) - - words_to_use = words_controller.setWords() - if isinstance(words_to_use, dict): - raise ValueError(words_to_use["error"]) - - style_controller = EstiloPalabrasController( - technique=technique, words=words_to_use) - - instace_style = style_controller.createAndSaveInstaceStyle() - if isinstance(instace_style, dict): - raise ValueError(instace_style["error"]) - - words_using = style_controller.relatedWords() - if isinstance(words_using, dict): - raise ValueError(words_using["error"]) - elif style_words == "vocabulario": - name_vocabulary = request.session["form_words"] - vocabulary = Vocabulario.objects.get( - nombre_vocabulario=name_vocabulary) - - es_vocabulary = EsVocabulario.objects.create( - id_tecnica=technique, - id_vocabulario=vocabulary - ) - else: - raise ValueError("Estilo de palabas no permitido") - - # //////////////////////////////////////////////////////// # - # - # Fourth step: Create session and relat with the technique # - # - # //////////////////////////////////////////////////////// # - session_controller = SesionController( - name_session=data_basic["nombre_sesion"] if data_basic["nombre_sesion"] != "" else None, - technique=technique, - creator=request.user.user_presentador - ) - - setting_session = session_controller.setSession() - if isinstance(setting_session, dict): - raise ValueError(setting_session["error"]) - - saved_session = session_controller.saveSession() - if isinstance(saved_session, dict): - raise ValueError(saved_session["error"]) - - context = { - "message": "sesión creada", - "data": { - "codigo_sesion": saved_session.codigo_sesion, - "nombre_sesion": saved_session.nombre_sesion - } - } - - # ////////////////////////////////// # - # - # Final step: Delete date in session # - # - # ////////////////////////////////// # - - deleteDataSession(request) - return JsonResponse(context) - except ValueError as e: - return general_error(f"Error: {e}") - else: - return general_error("No se ha establecido acción") - - @staticmethod - def controllPostRATA(request: HttpRequest): - if request.POST.get('action') == 'create_session': - if not request.session.get("form_tags") or not request.session.get("form_codes") or not request.session.get("form_words"): - deleteDataSession(request) - return general_error("No se ha especificado información necesaria para la creación de la sesión, por favor, vuelve a intentarlo") - try: - with transaction.atomic(): - # ////////////////////////////////////////////////////// # - # - # First step: Create technique and scale with their tags # - # - # ////////////////////////////////////////////////////// # - data_basic = request.session["form_basic"] - data_basic["numero_catadores"] = 0 - data_basic["numero_repeticiones"] = 1 - - technique = Tecnica.objects.create( - tipo_tecnica=TipoTecnica.objects.get( - nombre_tecnica=data_basic["name_tecnica"]), - id_estilo=EstiloPalabra.objects.get( - id=data_basic["estilo_palabras"]), - repeticiones_max=data_basic["numero_repeticiones"] or 1, - limite_catadores=data_basic["numero_catadores"], - instrucciones=data_basic["instrucciones"] or "Espere instrucciones del Presentador", - ) - - if not technique: - raise ValueError("Error al guardar la técnica") - - data_scale = { - "id_scale": data_basic["tipo_escala"], - "size": data_basic["tamano_escala"], - "technique": technique - } - - controllerScale = EscalaController(data=data_scale) - - scale = controllerScale.saveScale() - if isinstance(scale, dict): - raise ValueError(scale["error"]) - - dict_tags = request.session["form_tags"] - saved_related_tags = controllerScale.realteTags(dict_tags) - if "error" in saved_related_tags: - raise ValueError(saved_related_tags["error"]) - - # ////////////////////////////////////////////// # - # - # Second step: Create productos with their codes # - # - # ////////////////////////////////////////////// # - codes = request.session["form_codes"] - - if not codes: - raise ValueError("No hay códigos de productos") - - products_without_save = [] - for code in codes: - product = Producto( - codigoProducto=code, - id_tecnica=technique - ) - products_without_save.append(product) - - Producto.objects.bulk_create(products_without_save) - - # /////////////////////////////////////////////////////// # - # - # Third step: Create relations technique with Words Style # - # - # /////////////////////////////////////////////////////// # - style_words = technique.id_estilo.nombre_estilo - - if style_words == "atributos": - raw_ids_words = request.session["form_words"] - ids_words = [int(id_w) for id_w in raw_ids_words] - - words = Palabra.objects.filter(id__in=ids_words) - - style_atribute = EsAtributo.objects.create( - id_tecnica=technique - ) - - if not style_atribute: - raise ValueError( - "Error al intentar relacionar las palabras con la técnica") - - style_atribute.palabras.set(words) - - elif style_words == "vocabulario": - name_vocabulary = request.session["form_words"] - try: - vocabulary = Vocabulario.objects.get( - nombre_vocabulario=name_vocabulary) - except Vocabulario.DoesNotExist: - raise ValueError("Vocabulario no encontrado") - - es_vocabulary = EsVocabulario.objects.create( - id_tecnica=technique, - id_vocabulario=vocabulary - ) - if not es_vocabulary: - raise ValueError( - "Error al intentar relacionar el vocabulario con la técnica") - - else: - raise ValueError("Estilo de palabas no permitido") - - # //////////////////////////////////////////////////////// # - # - # Fourth step: Create session and relat with the technique # - # - # //////////////////////////////////////////////////////// # - session = SesionSensorial.objects.create( - nombre_sesion=data_basic["nombre_sesion"] if data_basic["nombre_sesion"] != "" else "", - tecnica=technique, - creadoPor=request.user.user_presentador - ) - - if not session: - raise ValueError("Error al crear sesion sensorial") - - context = { - "message": "sesión creada", - "data": { - "codigo_sesion": session.codigo_sesion, - "nombre_sesion": session.nombre_sesion - } - } - - # ////////////////////////////////// # - # - # Final step: Delete date en session # - # - # ////////////////////////////////// # - - deleteDataSession(request) - return JsonResponse(context) - except ValueError as e: - return general_error(f"Error: {e}") - else: - return general_error("No se ha establecido acción") - - @staticmethod - def controllPostCATA(request: HttpRequest): - if request.POST.get('action') == 'create_session': - if not request.session.get("form_codes") or not request.session.get("form_words"): - deleteDataSession(request) - return general_error("No se ha especificado información necesaria para la creación de la sesión, por favor, vuelve a intentarlo") - try: - with transaction.atomic(): - # //////////////////////////// # - # - # First step: Create technique # - # - # //////////////////////////// # - data_basic = request.session["form_basic"] - data_basic["numero_catadores"] = 0 - data_basic["numero_repeticiones"] = 1 - - technique = Tecnica.objects.create( - tipo_tecnica=TipoTecnica.objects.get( - nombre_tecnica=data_basic["name_tecnica"]), - id_estilo=EstiloPalabra.objects.get( - id=data_basic["estilo_palabras"]), - repeticiones_max=data_basic["numero_repeticiones"] or 1, - limite_catadores=data_basic["numero_catadores"], - instrucciones=data_basic["instrucciones"] or "Espere instrucciones del Presentador", - ) - - if not technique: - raise ValueError("Error al guardar la técnica") - - # ////////////////////////////////////////////// # - # - # Second step: Create productos with their codes # - # - # ////////////////////////////////////////////// # - codes = request.session["form_codes"] - - if not codes: - raise ValueError("No hay códigos de productos") - - products_without_save = [] - for code in codes: - product = Producto( - codigoProducto=code, - id_tecnica=technique - ) - products_without_save.append(product) - - Producto.objects.bulk_create(products_without_save) - - # /////////////////////////////////////////////////////// # - # - # Third step: Create relations technique with Words Style # - # - # /////////////////////////////////////////////////////// # - style_words = technique.id_estilo.nombre_estilo - - if style_words == "atributos": - raw_ids_words = request.session["form_words"] - ids_words = [int(id_w) for id_w in raw_ids_words] - - words = Palabra.objects.filter(id__in=ids_words) - - style_atribute = EsAtributo.objects.create( - id_tecnica=technique - ) - - if not style_atribute: - raise ValueError( - "Error al intentar relacionar las palabras con la técnica") - - style_atribute.palabras.set(words) - - elif style_words == "vocabulario": - name_vocabulary = request.session["form_words"] - try: - vocabulary = Vocabulario.objects.get( - nombre_vocabulario=name_vocabulary) - except Vocabulario.DoesNotExist: - raise ValueError("Vocabulario no encontrado") - - es_vocabulary = EsVocabulario.objects.create( - id_tecnica=technique, - id_vocabulario=vocabulary - ) - if not es_vocabulary: - raise ValueError( - "Error al intentar relacionar el vocabulario con la técnica") - - else: - raise ValueError("Estilo de palabas no permitido") - - # //////////////////////////////////////////////////////// # - # - # Fourth step: Create session and relat with the technique # - # - # //////////////////////////////////////////////////////// # - session = SesionSensorial.objects.create( - nombre_sesion=data_basic["nombre_sesion"] if data_basic["nombre_sesion"] != "" else None, - tecnica=technique, - creadoPor=request.user.user_presentador - ) - - if not session: - raise ValueError("Error al crear sesion sensorial") - - context = { - "message": "sesión creada", - "data": { - "codigo_sesion": session.codigo_sesion, - "nombre_sesion": session.nombre_sesion - } - } - - # ////////////////////////////////// # - # - # Final step: Delete date en session # - # - # ////////////////////////////////// # - deleteDataSession(request) - return JsonResponse(context) - - except ValueError as e: - return general_error(f"Error: {e}") - else: - return general_error("No se ha establecido acción") - - @staticmethod - def controllPostPF(request: HttpRequest): - if request.POST.get('action') == 'create_session': - if not request.session.get("form_codes"): - deleteDataSession(request) - return general_error("No se ha especificado información necesaria para la creación de la sesión, por favor, vuelve a intentarlo") - try: - with transaction.atomic(): - # ////////////////////////////////////// # - # - # First step: Create technique and scale # - # - # ////////////////////////////////////// # - data_basic = request.session["form_basic"] - phases_before_reptition = 2 - - technique = Tecnica.objects.create( - tipo_tecnica=TipoTecnica.objects.get( - nombre_tecnica=data_basic["name_tecnica"]), - id_estilo=EstiloPalabra.objects.get( - nombre_estilo="vocabulario"), - repeticiones_max=data_basic["numero_repeticiones"] + phases_before_reptition, - limite_catadores=data_basic["numero_catadores"], - instrucciones=data_basic["instrucciones"] or "Espere instrucciones del Analista", - ) - - if not technique: - raise ValueError("Error al guardar la técnica") - - created_scale = Escala.objects.create( - id_tipo_escala=TipoEscala.objects.get( - nombre_escala="estructurada"), - longitud=data_basic["numero_productos"], - tecnica=technique - ) - - if not created_scale: - raise ValueError("No se ha podido crear la escala") - - # ////////////////////////////////////////////// # - # - # Second step: Create productos with their codes # - # - # ////////////////////////////////////////////// # - codes = request.session["form_codes"] - - if not codes: - raise ValueError("No hay códigos de productos") - - products_without_save = [] - for code in codes: - product = Producto( - codigoProducto=code, - id_tecnica=technique - ) - products_without_save.append(product) - - Producto.objects.bulk_create(products_without_save) - - # /////////////////////////////////////////////////////// # - # - # Third step: Create session and relat with the technique # - # - # /////////////////////////////////////////////////////// # - session = SesionSensorial.objects.create( - nombre_sesion=data_basic["nombre_sesion"] if data_basic["nombre_sesion"] != "" else None, - tecnica=technique, - creadoPor=request.user.user_presentador - ) - - if not session: - raise ValueError("Error al crear sesion sensorial") - - context = { - "message": "sesión creada", - "data": { - "codigo_sesion": session.codigo_sesion, - "nombre_sesion": session.nombre_sesion - } - } - - # ////////////////////////////////// # - # - # Final step: Delete date en session # - # - # ////////////////////////////////// # - deleteDataSession(request) - return JsonResponse(context) - - except ValueError as e: - return general_error(f"Error: {e}") - else: - return general_error("No se ha establecido acción") diff --git a/tecnicas/controllers/views_controller/create_session/panel_tags_controller.py b/tecnicas/controllers/views_controller/create_session/panel_tags_controller.py index 852bd7d245c22894b486e2fd0f5a65e462a8b201..c41da248ea799117732f622804a8918f762de421 100644 --- a/tecnicas/controllers/views_controller/create_session/panel_tags_controller.py +++ b/tecnicas/controllers/views_controller/create_session/panel_tags_controller.py @@ -25,7 +25,7 @@ class PanelTagsController(): "form_new_tag": form_new_etiqueta } - return render(request, "tecnicas/create_sesion/configuracion-panel-tags.html", context_tags) + return render(request, "tecnicas/create_sesion/conf-panel-tags.html", context_tags) @staticmethod def controllPostEscalas(request: HttpRequest, data): @@ -54,7 +54,7 @@ class PanelTagsController(): else: context_tags["error"] = "ha ocurrido un error" response = render( - request, "tecnicas/create_sesion/configuracion-panel-tags.html", context_tags) + request, "tecnicas/create_sesion/conf-panel-tags.html", context_tags) return response diff --git a/tecnicas/controllers/views_controller/create_session/panel_words_controller.py b/tecnicas/controllers/views_controller/create_session/panel_words_controller.py index 92d454c44096a43608ec5fbe936f3d873e99d5ff..d748614782dcac27a93bedb03f1ee355447adea6 100644 --- a/tecnicas/controllers/views_controller/create_session/panel_words_controller.py +++ b/tecnicas/controllers/views_controller/create_session/panel_words_controller.py @@ -7,7 +7,7 @@ import json class PanelWordsController(): - current_url_escalas_atribute = "tecnicas/create_sesion/configuracion-panel-words.html" + current_url_escalas_atribute = "tecnicas/create_sesion/conf-panel-words.html" current_url_escalas_vocabulary = "tecnicas/create_sesion/conf-panel-vocabulary.html" def __init__(self): diff --git a/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_cata_controller.py b/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_cata_controller.py new file mode 100644 index 0000000000000000000000000000000000000000..79a6329a92f3a51852a670792a14a9fa778ea687 --- /dev/null +++ b/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_cata_controller.py @@ -0,0 +1,137 @@ +from .panel_create_controller import PanelCreateController +from django.http import HttpRequest, JsonResponse +from django.db import transaction +from tecnicas.models import EsVocabulario, Tecnica, TipoTecnica, EstiloPalabra, EsAtributo, Vocabulario, Palabra, SesionSensorial, Producto +from tecnicas.utils import deleteDataSession, general_error + + +class PanelCreateCataController(PanelCreateController): + def __init__(self): + super().__init__() + + @staticmethod + def controllPost(request: HttpRequest): + if request.POST.get('action') == 'create_session': + if not request.session.get("form_codes") or not request.session.get("form_words"): + deleteDataSession(request) + return general_error("No se ha especificado información necesaria para la creación de la sesión, por favor, vuelve a intentarlo") + try: + with transaction.atomic(): + # //////////////////////////// # + # + # First step: Create technique # + # + # //////////////////////////// # + data_basic = request.session["form_basic"] + data_basic["numero_catadores"] = 0 + data_basic["numero_repeticiones"] = 1 + + technique = Tecnica.objects.create( + tipo_tecnica=TipoTecnica.objects.get( + nombre_tecnica=data_basic["name_tecnica"]), + id_estilo=EstiloPalabra.objects.get( + nombre_estilo=data_basic["estilo_palabras"]), + repeticiones_max=data_basic["numero_repeticiones"] or 1, + limite_catadores=data_basic["numero_catadores"], + instrucciones=data_basic["instrucciones"] or "Espere instrucciones del Presentador", + ) + + if not technique: + raise ValueError("Error al guardar la técnica") + + # ////////////////////////////////////////////// # + # + # Second step: Create productos with their codes # + # + # ////////////////////////////////////////////// # + codes = request.session["form_codes"] + + if not codes: + raise ValueError("No hay códigos de productos") + + products_without_save = [] + for code in codes: + product = Producto( + codigoProducto=code, + id_tecnica=technique + ) + products_without_save.append(product) + + Producto.objects.bulk_create(products_without_save) + + # /////////////////////////////////////////////////////// # + # + # Third step: Create relations technique with Words Style # + # + # /////////////////////////////////////////////////////// # + style_words = technique.id_estilo.nombre_estilo + + if style_words == "atributos": + raw_ids_words = request.session["form_words"] + ids_words = [int(id_w) for id_w in raw_ids_words] + + words = Palabra.objects.filter(id__in=ids_words) + + style_atribute = EsAtributo.objects.create( + id_tecnica=technique + ) + + if not style_atribute: + raise ValueError( + "Error al intentar relacionar las palabras con la técnica") + + style_atribute.palabras.set(words) + + elif style_words == "vocabulario": + name_vocabulary = request.session["form_words"] + try: + vocabulary = Vocabulario.objects.get( + nombre_vocabulario=name_vocabulary) + except Vocabulario.DoesNotExist: + raise ValueError("Vocabulario no encontrado") + + es_vocabulary = EsVocabulario.objects.create( + id_tecnica=technique, + id_vocabulario=vocabulary + ) + if not es_vocabulary: + raise ValueError( + "Error al intentar relacionar el vocabulario con la técnica") + + else: + raise ValueError("Estilo de palabas no permitido") + + # //////////////////////////////////////////////////////// # + # + # Fourth step: Create session and relat with the technique # + # + # //////////////////////////////////////////////////////// # + session = SesionSensorial.objects.create( + nombre_sesion=data_basic["nombre_sesion"] if data_basic["nombre_sesion"] != "" else None, + tecnica=technique, + creadoPor=request.user.user_presentador + ) + + if not session: + raise ValueError("Error al crear sesion sensorial") + + context = { + "message": "sesión creada", + "data": { + "codigo_sesion": session.codigo_sesion, + "nombre_sesion": session.nombre_sesion + } + } + + # ////////////////////////////////// # + # + # Final step: Delete date en session # + # + # ////////////////////////////////// # + deleteDataSession(request) + return JsonResponse(context) + + except ValueError as e: + return general_error(f"Error: {e}") + else: + return general_error("No se ha establecido acción") diff --git a/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_controller.py b/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_controller.py new file mode 100644 index 0000000000000000000000000000000000000000..ea4a8559c91137c4b8a6c6e27f8f1f9293461869 --- /dev/null +++ b/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_controller.py @@ -0,0 +1,17 @@ +from django.http import JsonResponse, HttpRequest +from django.shortcuts import render + +class PanelCreateController(): + url_template = 'tecnicas/create_sesion/creating_session.html' + + def __init__(self): + pass + + @staticmethod + def controllGet(request: HttpRequest): + return render( + request, PanelCreateController.url_template) + + @staticmethod + def controllPost(request: HttpRequest): + return JsonResponse({"message": "Método no permitido"}) diff --git a/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_escalas_controller.py b/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_escalas_controller.py new file mode 100644 index 0000000000000000000000000000000000000000..727ebde507273373c4746ded1290bde26c3aed81 --- /dev/null +++ b/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_escalas_controller.py @@ -0,0 +1,169 @@ +from .panel_create_controller import PanelCreateController +from django.http import HttpRequest, JsonResponse +from django.db import transaction +from tecnicas.controllers import TecnicaController, EscalaController, ProductosController, OrdenesController, PalabrasController, EstiloPalabrasController, SesionController +from tecnicas.models import EsVocabulario, Vocabulario +from tecnicas.utils import deleteDataSession, general_error + + +class PanelCreateEscalasController(PanelCreateController): + def __init__(self): + super().__init__() + + @staticmethod + def controllPost(request: HttpRequest): + if request.POST.get('action') == 'create_session': + if not request.session.get("form_tags") or not request.session.get("form_codes") or not request.session.get("form_words"): + deleteDataSession(request) + return general_error("No se ha especificado información necesaria para la creación de la sesión, por favor, vuelve a intentarlo") + try: + with transaction.atomic(): + # ////////////////////////////////////////////////////// # + # + # First step: Create technique and scale with their tags # + # + # ////////////////////////////////////////////////////// # + data_basic = request.session["form_basic"] + controllerTechnique = TecnicaController() + controllerTechnique.setTechniqueFromBasicData( + basic=data_basic) + technique = controllerTechnique.saveTechnique() + if not technique: + raise ValueError("Error al guardar la técnica") + + data_scale = { + "id_scale": data_basic["tipo_escala"], + "size": data_basic["tamano_escala"], + "technique": technique + } + + controllerScale = EscalaController(data=data_scale) + + scale = controllerScale.saveScale() + if isinstance(scale, dict): + raise ValueError(scale["error"]) + + dict_tags = request.session["form_tags"] + saved_related_tags = controllerScale.realteTags(dict_tags) + if "error" in saved_related_tags: + raise ValueError(saved_related_tags["error"]) + + # ////////////////////////////////////////////////////////// # + # + # Second step: Create orders, productos and set the position # + # + # ////////////////////////////////////////////////////////// # + data_codes = request.session["form_codes"] + + list_codes_dict = data_codes["product_codes"] + + codes = [] + for product in list_codes_dict: + code = next(iter(product.values())) + codes.append(code) + + controllerProducts = ProductosController( + codes=codes, + technique=technique + ) + + controllerProducts.setProductsNoSave() + saved_prodcuts = controllerProducts.saveProducts() + if isinstance(saved_prodcuts, dict): + raise ValueError(saved_prodcuts["error"]) + + raw_sort_codes = data_codes["sort_codes"] + controllerOrdes = OrdenesController( + raw_orders=raw_sort_codes, + list_products=saved_prodcuts, + technique=technique + ) + + controllerOrdes.setOrdersToSave() + saved_orders = controllerOrdes.saveOrders() + if isinstance(saved_orders, dict): + raise ValueError(saved_orders["error"]) + + seded_positions = controllerOrdes.setPositions() + if isinstance(seded_positions, dict): + raise ValueError(seded_positions["error"]) + + saved_postions = controllerOrdes.savePositions() + if isinstance(saved_postions, dict): + raise ValueError(saved_prodcuts["error"]) + + # /////////////////////////////////////////////////////// # + # + # Third step: Create relations technique with Words Style # + # + # /////////////////////////////////////////////////////// # + style_words = technique.id_estilo.nombre_estilo + if style_words == "atributos": + ids_words = request.session["form_words"] + words_controller = PalabrasController(ids=ids_words) + + words_to_use = words_controller.setWords() + if isinstance(words_to_use, dict): + raise ValueError(words_to_use["error"]) + + style_controller = EstiloPalabrasController( + technique=technique, words=words_to_use) + + instace_style = style_controller.createAndSaveInstaceStyle() + if isinstance(instace_style, dict): + raise ValueError(instace_style["error"]) + + words_using = style_controller.relatedWords() + if isinstance(words_using, dict): + raise ValueError(words_using["error"]) + elif style_words == "vocabulario": + name_vocabulary = request.session["form_words"] + vocabulary = Vocabulario.objects.get( + nombre_vocabulario=name_vocabulary) + + es_vocabulary = EsVocabulario.objects.create( + id_tecnica=technique, + id_vocabulario=vocabulary + ) + else: + raise ValueError("Estilo de palabas no permitido") + + # //////////////////////////////////////////////////////// # + # + # Fourth step: Create session and relat with the technique # + # + # //////////////////////////////////////////////////////// # + session_controller = SesionController( + name_session=data_basic["nombre_sesion"] if data_basic["nombre_sesion"] != "" else None, + technique=technique, + creator=request.user.user_presentador + ) + + setting_session = session_controller.setSession() + if isinstance(setting_session, dict): + raise ValueError(setting_session["error"]) + + saved_session = session_controller.saveSession() + if isinstance(saved_session, dict): + raise ValueError(saved_session["error"]) + + context = { + "message": "sesión creada", + "data": { + "codigo_sesion": saved_session.codigo_sesion, + "nombre_sesion": saved_session.nombre_sesion + } + } + + # ////////////////////////////////// # + # + # Final step: Delete date in session # + # + # ////////////////////////////////// # + + deleteDataSession(request) + return JsonResponse(context) + except ValueError as e: + return general_error(f"Error: {e}") + else: + return general_error("No se ha establecido acción") diff --git a/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_napping_controller.py b/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_napping_controller.py new file mode 100644 index 0000000000000000000000000000000000000000..5d9729dff0bc2c033046f5079b33606a971dc53c --- /dev/null +++ b/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_napping_controller.py @@ -0,0 +1,95 @@ +from .panel_create_controller import PanelCreateController +from django.http import HttpRequest, JsonResponse +from tecnicas.models import Tecnica, TipoTecnica, EstiloPalabra, Producto, SesionSensorial +from django.db import transaction +from tecnicas.utils import deleteDataSession + + +class PanelCreateNappingController(PanelCreateController): + def __init__(self): + super().__init__() + + @staticmethod + def controllPost(request: HttpRequest): + if request.POST.get('action') == 'create_session': + if not request.session.get("form_basic") or not request.session.get("form_codes"): + deleteDataSession(request) + return general_error("No se ha especificado información necesaria para la creación de la sesión, por favor, vuelve a intentarlo") + try: + with transaction.atomic(): + # //////////////////////////// # + # + # First step: Create technique # + # + # //////////////////////////// # + data_basic = request.session["form_basic"] + data_basic["numero_catadores"] = data_basic["numero_catadores"] or 2 + data_basic["numero_repeticiones"] = 0 + + technique = Tecnica.objects.create( + tipo_tecnica=TipoTecnica.objects.get( + nombre_tecnica=data_basic["name_tecnica"]), + id_estilo=EstiloPalabra.objects.get( + nombre_estilo="napping"), + repeticiones_max=data_basic["numero_repeticiones"], + limite_catadores=data_basic["numero_catadores"], + instrucciones=data_basic["instrucciones"] or "Espere instrucciones del Presentador", + ) + + if not technique: + raise ValueError("Error al guardar la técnica") + + # ////////////////////////////////////////////// # + # + # Second step: Create productos with their codes # + # + # ////////////////////////////////////////////// # + codes = request.session["form_codes"] + + if not codes: + raise ValueError("No hay códigos de productos") + + products_without_save = [] + for code in codes: + product = Producto( + codigoProducto=code, + id_tecnica=technique + ) + products_without_save.append(product) + + Producto.objects.bulk_create(products_without_save) + + # /////////////////////////////////////////////////////// # + # + # Third step: Create session and relat with the technique # + # + # /////////////////////////////////////////////////////// # + session = SesionSensorial.objects.create( + nombre_sesion=data_basic["nombre_sesion"] if data_basic["nombre_sesion"] != "" else None, + tecnica=technique, + creadoPor=request.user.user_presentador + ) + + if not session: + raise ValueError("Error al crear sesion sensorial") + + context = { + "message": "sesión creada", + "data": { + "codigo_sesion": session.codigo_sesion, + "nombre_sesion": session.nombre_sesion + } + } + + # ////////////////////////////////// # + # + # Final step: Delete date en session # + # + # ////////////////////////////////// # + deleteDataSession(request) + return JsonResponse(context) + + except ValueError as e: + return general_error(f"Error: {e}") + else: + return general_error("No se ha establecido acción") diff --git a/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_pf_controller.py b/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_pf_controller.py new file mode 100644 index 0000000000000000000000000000000000000000..b6e368c0f62f1919f6d5c082a2b852d482aa319d --- /dev/null +++ b/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_pf_controller.py @@ -0,0 +1,105 @@ +from .panel_create_controller import PanelCreateController +from django.http import HttpRequest, JsonResponse +from django.db import transaction +from tecnicas.models import Tecnica, TipoTecnica, EstiloPalabra, SesionSensorial, Escala, TipoEscala, Producto +from tecnicas.utils import deleteDataSession, general_error + + +class PanelCreatePFController(PanelCreateController): + def __init__(self): + super().__init__() + + @staticmethod + def controllPost(request: HttpRequest): + if request.POST.get('action') == 'create_session': + if not request.session.get("form_codes"): + deleteDataSession(request) + return general_error("No se ha especificado información necesaria para la creación de la sesión, por favor, vuelve a intentarlo") + try: + with transaction.atomic(): + # ////////////////////////////////////// # + # + # First step: Create technique and scale # + # + # ////////////////////////////////////// # + data_basic = request.session["form_basic"] + phases_before_reptition = 2 + + technique = Tecnica.objects.create( + tipo_tecnica=TipoTecnica.objects.get( + nombre_tecnica=data_basic["name_tecnica"]), + id_estilo=EstiloPalabra.objects.get( + nombre_estilo="perfil flash"), + repeticiones_max=data_basic["numero_repeticiones"] + + phases_before_reptition, + limite_catadores=data_basic["numero_catadores"], + instrucciones=data_basic["instrucciones"] or "Espere instrucciones del Analista", + ) + + if not technique: + raise ValueError("Error al guardar la técnica") + + created_scale = Escala.objects.create( + id_tipo_escala=TipoEscala.objects.get( + nombre_escala="estructurada"), + longitud=data_basic["numero_productos"], + tecnica=technique + ) + + if not created_scale: + raise ValueError("No se ha podido crear la escala") + + # ////////////////////////////////////////////// # + # + # Second step: Create productos with their codes # + # + # ////////////////////////////////////////////// # + codes = request.session["form_codes"] + + if not codes: + raise ValueError("No hay códigos de productos") + + products_without_save = [] + for code in codes: + product = Producto( + codigoProducto=code, + id_tecnica=technique + ) + products_without_save.append(product) + + Producto.objects.bulk_create(products_without_save) + + # /////////////////////////////////////////////////////// # + # + # Third step: Create session and relat with the technique # + # + # /////////////////////////////////////////////////////// # + session = SesionSensorial.objects.create( + nombre_sesion=data_basic["nombre_sesion"] if data_basic["nombre_sesion"] != "" else None, + tecnica=technique, + creadoPor=request.user.user_presentador + ) + + if not session: + raise ValueError("Error al crear sesion sensorial") + + context = { + "message": "sesión creada", + "data": { + "codigo_sesion": session.codigo_sesion, + "nombre_sesion": session.nombre_sesion + } + } + + # ////////////////////////////////// # + # + # Final step: Delete date en session # + # + # ////////////////////////////////// # + deleteDataSession(request) + return JsonResponse(context) + + except ValueError as e: + return general_error(f"Error: {e}") + else: + return general_error("No se ha establecido acción") diff --git a/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_rata_controller.py b/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_rata_controller.py new file mode 100644 index 0000000000000000000000000000000000000000..eee8462ae591dc099c787e9d964230173cb98209 --- /dev/null +++ b/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_rata_controller.py @@ -0,0 +1,155 @@ +from .panel_create_controller import PanelCreateController +from django.http import HttpRequest, JsonResponse +from django.db import transaction +from tecnicas.controllers import EscalaController +from tecnicas.models import EsVocabulario, Tecnica, TipoTecnica, EstiloPalabra, EsAtributo, Vocabulario, Palabra, SesionSensorial, Producto +from tecnicas.utils import deleteDataSession, general_error + + +class PanelCreateRataController(PanelCreateController): + def __init__(self): + super().__init__() + + @staticmethod + def controllPost(request: HttpRequest): + if request.POST.get('action') == 'create_session': + if not request.session.get("form_tags") or not request.session.get("form_codes") or not request.session.get("form_words"): + deleteDataSession(request) + return general_error("No se ha especificado información necesaria para la creación de la sesión, por favor, vuelve a intentarlo") + try: + with transaction.atomic(): + # ////////////////////////////////////////////////////// # + # + # First step: Create technique and scale with their tags # + # + # ////////////////////////////////////////////////////// # + data_basic = request.session["form_basic"] + data_basic["numero_catadores"] = 0 + data_basic["numero_repeticiones"] = 1 + + technique = Tecnica.objects.create( + tipo_tecnica=TipoTecnica.objects.get( + nombre_tecnica=data_basic["name_tecnica"]), + id_estilo=EstiloPalabra.objects.get( + nombre_estilo=data_basic["estilo_palabras"]), + repeticiones_max=data_basic["numero_repeticiones"] or 1, + limite_catadores=data_basic["numero_catadores"], + instrucciones=data_basic["instrucciones"] or "Espere instrucciones del Presentador", + ) + + if not technique: + raise ValueError("Error al guardar la técnica") + + data_scale = { + "id_scale": data_basic["tipo_escala"], + "size": data_basic["tamano_escala"], + "technique": technique + } + + controllerScale = EscalaController(data=data_scale) + + scale = controllerScale.saveScale() + if isinstance(scale, dict): + raise ValueError(scale["error"]) + + dict_tags = request.session["form_tags"] + saved_related_tags = controllerScale.realteTags(dict_tags) + if "error" in saved_related_tags: + raise ValueError(saved_related_tags["error"]) + + # ////////////////////////////////////////////// # + # + # Second step: Create productos with their codes # + # + # ////////////////////////////////////////////// # + codes = request.session["form_codes"] + + if not codes: + raise ValueError("No hay códigos de productos") + + products_without_save = [] + for code in codes: + product = Producto( + codigoProducto=code, + id_tecnica=technique + ) + products_without_save.append(product) + + Producto.objects.bulk_create(products_without_save) + + # /////////////////////////////////////////////////////// # + # + # Third step: Create relations technique with Words Style # + # + # /////////////////////////////////////////////////////// # + style_words = technique.id_estilo.nombre_estilo + + if style_words == "atributos": + raw_ids_words = request.session["form_words"] + ids_words = [int(id_w) for id_w in raw_ids_words] + + words = Palabra.objects.filter(id__in=ids_words) + + style_atribute = EsAtributo.objects.create( + id_tecnica=technique + ) + + if not style_atribute: + raise ValueError( + "Error al intentar relacionar las palabras con la técnica") + + style_atribute.palabras.set(words) + + elif style_words == "vocabulario": + name_vocabulary = request.session["form_words"] + try: + vocabulary = Vocabulario.objects.get( + nombre_vocabulario=name_vocabulary) + except Vocabulario.DoesNotExist: + raise ValueError("Vocabulario no encontrado") + + es_vocabulary = EsVocabulario.objects.create( + id_tecnica=technique, + id_vocabulario=vocabulary + ) + if not es_vocabulary: + raise ValueError( + "Error al intentar relacionar el vocabulario con la técnica") + + else: + raise ValueError("Estilo de palabas no permitido") + + # //////////////////////////////////////////////////////// # + # + # Fourth step: Create session and relat with the technique # + # + # //////////////////////////////////////////////////////// # + session = SesionSensorial.objects.create( + nombre_sesion=data_basic["nombre_sesion"] if data_basic["nombre_sesion"] != "" else "", + tecnica=technique, + creadoPor=request.user.user_presentador + ) + + if not session: + raise ValueError("Error al crear sesion sensorial") + + context = { + "message": "sesión creada", + "data": { + "codigo_sesion": session.codigo_sesion, + "nombre_sesion": session.nombre_sesion + } + } + + # ////////////////////////////////// # + # + # Final step: Delete date en session # + # + # ////////////////////////////////// # + + deleteDataSession(request) + return JsonResponse(context) + except ValueError as e: + return general_error(f"Error: {e}") + else: + return general_error("No se ha establecido acción") diff --git a/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_sort_controller.py b/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_sort_controller.py new file mode 100644 index 0000000000000000000000000000000000000000..4d98ce32fe5948f299738bf230be6783c1d13080 --- /dev/null +++ b/tecnicas/controllers/views_controller/create_session/panels_create/panel_create_sort_controller.py @@ -0,0 +1,95 @@ +from .panel_create_controller import PanelCreateController +from django.http import HttpRequest, JsonResponse +from django.db import transaction +from tecnicas.models import Tecnica, TipoTecnica, EstiloPalabra, SesionSensorial, Producto +from tecnicas.utils import deleteDataSession, general_error + + +class PanelCreateSortController(PanelCreateController): + def __init__(self): + super().__init__() + + @staticmethod + def controllPost(request: HttpRequest): + if request.POST.get('action') == 'create_session': + if not request.session.get("form_basic") or not request.session.get("form_codes"): + deleteDataSession(request) + return general_error("No se ha especificado información necesaria para la creación de la sesión, por favor, vuelve a intentarlo") + try: + with transaction.atomic(): + # //////////////////////////// # + # + # First step: Create technique # + # + # //////////////////////////// # + data_basic = request.session["form_basic"] + data_basic["numero_catadores"] = data_basic["numero_catadores"] or 1 + data_basic["numero_repeticiones"] = 1 + + technique = Tecnica.objects.create( + tipo_tecnica=TipoTecnica.objects.get( + nombre_tecnica=data_basic["name_tecnica"]), + id_estilo=EstiloPalabra.objects.get( + nombre_estilo="sort"), + repeticiones_max=data_basic["numero_repeticiones"], + limite_catadores=data_basic["numero_catadores"], + instrucciones=data_basic["instrucciones"] or "Espere instrucciones del Presentador", + ) + + if not technique: + raise ValueError("Error al guardar la técnica") + + # ////////////////////////////////////////////// # + # + # Second step: Create productos with their codes # + # + # ////////////////////////////////////////////// # + codes = request.session["form_codes"] + + if not codes: + raise ValueError("No hay códigos de productos") + + products_without_save = [] + for code in codes: + product = Producto( + codigoProducto=code, + id_tecnica=technique + ) + products_without_save.append(product) + + Producto.objects.bulk_create(products_without_save) + + # /////////////////////////////////////////////////////// # + # + # Third step: Create session and relat with the technique # + # + # /////////////////////////////////////////////////////// # + session = SesionSensorial.objects.create( + nombre_sesion=data_basic["nombre_sesion"] if data_basic["nombre_sesion"] != "" else None, + tecnica=technique, + creadoPor=request.user.user_presentador + ) + + if not session: + raise ValueError("Error al crear sesion sensorial") + + context = { + "message": "sesión creada", + "data": { + "codigo_sesion": session.codigo_sesion, + "nombre_sesion": session.nombre_sesion + } + } + + # ////////////////////////////////// # + # + # Final step: Delete date en session # + # + # ////////////////////////////////// # + deleteDataSession(request) + return JsonResponse(context) + + except ValueError as e: + return general_error(f"Error: {e}") + else: + return general_error("No se ha establecido acción") diff --git a/tecnicas/controllers/views_controller/session_management/details_cata_controller.py b/tecnicas/controllers/views_controller/session_management/details/details_cata_controller.py similarity index 97% rename from tecnicas/controllers/views_controller/session_management/details_cata_controller.py rename to tecnicas/controllers/views_controller/session_management/details/details_cata_controller.py index e1d5442b594b93687846535d092620c649dc4c1b..4b21cde747f701a2ed7ab95a6737339954c638a2 100644 --- a/tecnicas/controllers/views_controller/session_management/details_cata_controller.py +++ b/tecnicas/controllers/views_controller/session_management/details/details_cata_controller.py @@ -9,7 +9,7 @@ from collections import defaultdict class DetallesCATAController(DetallesController): def __init__(self, session: SesionSensorial): super().__init__(session) - self.url_template = "tecnicas/manage_sesions/detalles-sesion-cata.html" + self.url_template = "tecnicas/manage_sesions/details-session-cata.html" self.url_next = "cata_system:monitor_sesion" def getContext(self): diff --git a/tecnicas/controllers/views_controller/session_management/details_controller.py b/tecnicas/controllers/views_controller/session_management/details/details_controller.py similarity index 98% rename from tecnicas/controllers/views_controller/session_management/details_controller.py rename to tecnicas/controllers/views_controller/session_management/details/details_controller.py index f03aea65e6dc205c2ea332ca51658ee73de46f55..78c404de0c9c86b776d59016853e2bcec1c3e46f 100644 --- a/tecnicas/controllers/views_controller/session_management/details_controller.py +++ b/tecnicas/controllers/views_controller/session_management/details/details_controller.py @@ -7,7 +7,7 @@ from tecnicas.controllers import ParticipacionController class DetallesController(): url_template: str - url_next: str + url_next = "cata_system:monitor_sesion" def __init__(self, session: SesionSensorial): self.session = session diff --git a/tecnicas/controllers/views_controller/session_management/details_escala_controller.py b/tecnicas/controllers/views_controller/session_management/details/details_escala_controller.py similarity index 87% rename from tecnicas/controllers/views_controller/session_management/details_escala_controller.py rename to tecnicas/controllers/views_controller/session_management/details/details_escala_controller.py index 9fd3b1b712a42f442131bbe1bf566ba606dd933b..d9534e3d6c327ee72bd0f80bb15424cb8f3f57f1 100644 --- a/tecnicas/controllers/views_controller/session_management/details_escala_controller.py +++ b/tecnicas/controllers/views_controller/session_management/details/details_escala_controller.py @@ -11,20 +11,17 @@ Encabezados de como deben de aparecer los datos juntos | Repeticion | Codigo Producto | Catador | P1 | P2 | P3 | Pn | ''' -from django.http import HttpRequest -from django.shortcuts import render, redirect -from django.urls import reverse -from tecnicas.models import SesionSensorial, Presentador, Participacion, Calificacion, Escala -from tecnicas.controllers import DatoController, PalabrasController, ParticipacionController +from tecnicas.models import SesionSensorial, Calificacion, Escala +from tecnicas.controllers import DatoController, PalabrasController from .details_controller import DetallesController -from tecnicas.utils import defaultdict_to_dict, controller_error +from tecnicas.utils import defaultdict_to_dict from collections import defaultdict class DetallesEscalasController(DetallesController): def __init__(self, session: SesionSensorial): super().__init__(session) - self.url_template = "tecnicas/manage_sesions/detalles-sesion.html" + self.url_template = "tecnicas/manage_sesions/details-session.html" self.url_next = "cata_system:monitor_sesion" def getContext(self): diff --git a/tecnicas/controllers/views_controller/session_management/details_pf_controller.py b/tecnicas/controllers/views_controller/session_management/details/details_pf_controller.py similarity index 94% rename from tecnicas/controllers/views_controller/session_management/details_pf_controller.py rename to tecnicas/controllers/views_controller/session_management/details/details_pf_controller.py index 325fa14addaacedb3985b75ecc42b236d0539c6d..988373bcc5aad10007aedac6779ca1591bf6afff 100644 --- a/tecnicas/controllers/views_controller/session_management/details_pf_controller.py +++ b/tecnicas/controllers/views_controller/session_management/details/details_pf_controller.py @@ -1,8 +1,5 @@ -from django.http import HttpRequest -from django.shortcuts import redirect -from django.urls import reverse -from tecnicas.models import SesionSensorial, Presentador, Participacion, ListaPalabras, Calificacion, Catador -from tecnicas.controllers import ParticipacionController, DatoController +from tecnicas.models import SesionSensorial, ListaPalabras, Calificacion, Catador +from tecnicas.controllers import DatoController from tecnicas.utils import defaultdict_to_dict from .details_controller import DetallesController from collections import defaultdict @@ -20,9 +17,7 @@ class DetallesPFController(DetallesController): self.context = { "sesion": self.session, "use_technique": technique, - "existen_calificaciones": False, "tipo_escala": technique.escala_tecnica.id_tipo_escala.nombre_escala, - "valor_max": technique.escala_tecnica.longitud, "repeticiones_max": technique.repeticiones_max - 2 } diff --git a/tecnicas/controllers/views_controller/session_management/details/details_rata_controller.py b/tecnicas/controllers/views_controller/session_management/details/details_rata_controller.py new file mode 100644 index 0000000000000000000000000000000000000000..71dae2b469f24c2dd1a2ec969a32a329d62c574a --- /dev/null +++ b/tecnicas/controllers/views_controller/session_management/details/details_rata_controller.py @@ -0,0 +1,7 @@ +from tecnicas.models import SesionSensorial +from .details_controller import DetallesController + + +class DetallesRATAController(DetallesController): + def __init__(self, session: SesionSensorial): + super().__init__(session) diff --git a/tecnicas/controllers/views_controller/session_management/details/details_sort_controller.py b/tecnicas/controllers/views_controller/session_management/details/details_sort_controller.py new file mode 100644 index 0000000000000000000000000000000000000000..542df448c230782658ce5d12142c38e733b60405 --- /dev/null +++ b/tecnicas/controllers/views_controller/session_management/details/details_sort_controller.py @@ -0,0 +1,91 @@ +from .details_controller import DetallesController +from tecnicas.models import SesionSensorial, GrupoProducto, Producto, Participacion +from collections import defaultdict + + +class DetallesSortController(DetallesController): + def __init__(self, session: SesionSensorial): + super().__init__(session) + self.url_template = "tecnicas/manage_sesions/details-session-sort.html" + self.url_next = "cata_system:monitor_sesion" + + def getContext(self): + technique = self.session.tecnica + + finished = False + status = "" + + if technique.repeticion < technique.repeticiones_max and not self.session.activo: + status = "En espera para iniciar la sesión" + elif technique.repeticion >= technique.repeticiones_max and not self.session.activo: + status = "Esta sesión ha sido finalizada" + finished = True + else: + status = "La sesión está en progreso" + + self.context = { + "sesion": self.session, + "technique": technique, + "status": status, + "finished": finished + } + + self.context["data_groups"] = { + "data": self.setDataSort(), + "testers": self.setHeaders() + } + + return self.context + + def setDataSort(self): + data = [] + technique = self.session.tecnica + + products = Producto.objects.filter(id_tecnica=technique) + + groups = GrupoProducto.objects.select_related("catador").filter( + tecnica=technique + ) + + if len(groups): + self.context["there_data"] = True + else: + self.context["there_data"] = False + return [] + + for product in products: + product_data = { + "codigo_producto": product.codigoProducto, + "palabras": {} + } + + related_groups = groups.filter(productos=product).select_related( + "catador__user" + ).prefetch_related("palabras") + + data_words = defaultdict(set) + + for group in related_groups: + catador_username = group.catador.user.username + + for word in group.palabras.all(): + data_words[catador_username].add(word.nombre_palabra) + + product_data["palabras"] = { + username: list(words) + for username, words in data_words.items() + } + + data.append(product_data) + + return data + + def setHeaders(self): + participacions = list(Participacion.objects.filter( + tecnica=self.session.tecnica + ).only("catador").select_related("catador__user")) + + testers = [ + participacion.catador.user.username for participacion in participacions] + + return testers diff --git a/tecnicas/controllers/views_controller/session_management/details_rata_controller.py b/tecnicas/controllers/views_controller/session_management/details_rata_controller.py deleted file mode 100644 index a6f7e2e6e26d3685899a1cdc552b9e647c5ef302..0000000000000000000000000000000000000000 --- a/tecnicas/controllers/views_controller/session_management/details_rata_controller.py +++ /dev/null @@ -1,12 +0,0 @@ -from django.http import HttpRequest -from django.shortcuts import render, redirect -from tecnicas.models import SesionSensorial -from tecnicas.controllers import PalabrasController, DatoController, CalificacionController -from tecnicas.utils import defaultdict_to_dict -from .details_controller import DetallesController -from collections import defaultdict - - -class DetallesRATAController(DetallesController): - def __init__(self, session: SesionSensorial): - super().__init__(session) diff --git a/tecnicas/controllers/views_controller/session_management/monitor_controller.py b/tecnicas/controllers/views_controller/session_management/monitor/monitor_controller.py similarity index 88% rename from tecnicas/controllers/views_controller/session_management/monitor_controller.py rename to tecnicas/controllers/views_controller/session_management/monitor/monitor_controller.py index c1c8b97f260f14d640b2b81e6c1aafb5e856e2b6..16aa77587372d74b5abcf710927f69fce4143cc2 100644 --- a/tecnicas/controllers/views_controller/session_management/monitor_controller.py +++ b/tecnicas/controllers/views_controller/session_management/monitor/monitor_controller.py @@ -1,9 +1,7 @@ from django.http import HttpRequest from django.shortcuts import render, redirect from django.urls import reverse -from tecnicas.models import SesionSensorial, Producto, EsAtributo, EsVocabulario -from tecnicas.controllers import ParticipacionController, SesionController -from tecnicas.utils import controller_error +from tecnicas.models import SesionSensorial, Producto, EsAtributo, EsVocabulario, Participacion class MonitorController(): @@ -14,20 +12,20 @@ class MonitorController(): self.sensorial_session = session def controllPostFinishSession(self, request: HttpRequest): - self.setContext() (is_all_end, message) = self.checkAllFinish() if not is_all_end: + self.setContext() self.context["error"] = message return render(request, self.url_view, self.context) self.finishSession() return redirect(reverse(self.previus_view, kwargs={"session_code": self.sensorial_session.codigo_sesion})) - def checkAllFinish(self): + def checkAllFinish(self) -> (bool, str): return (False, "Función sin implementar") def setContext(self): - self.participations = ParticipacionController.getParticipationsInTechinique( - self.sensorial_session.tecnica) + self.participations = Participacion.objects.filter( + tecnica=self.sensorial_session.tecnica) self.context = { "code_session": self.sensorial_session.codigo_sesion, diff --git a/tecnicas/controllers/views_controller/session_management/monitor_escalas_controller.py b/tecnicas/controllers/views_controller/session_management/monitor/monitor_escalas_controller.py similarity index 100% rename from tecnicas/controllers/views_controller/session_management/monitor_escalas_controller.py rename to tecnicas/controllers/views_controller/session_management/monitor/monitor_escalas_controller.py diff --git a/tecnicas/controllers/views_controller/session_management/monitor_pf_controller.py b/tecnicas/controllers/views_controller/session_management/monitor/monitor_pf_controller.py similarity index 96% rename from tecnicas/controllers/views_controller/session_management/monitor_pf_controller.py rename to tecnicas/controllers/views_controller/session_management/monitor/monitor_pf_controller.py index 1b32905a6d6bf6e0791ef0bf2b30c0a2e2ded406..d15d1356635910a50e8ea628a7d3fcac337952a4 100644 --- a/tecnicas/controllers/views_controller/session_management/monitor_pf_controller.py +++ b/tecnicas/controllers/views_controller/session_management/monitor/monitor_pf_controller.py @@ -1,6 +1,3 @@ -from django.http import HttpRequest -from django.shortcuts import render, redirect -from django.urls import reverse from tecnicas.models import Dato, Participacion, Catador, ListaPalabras, Producto from tecnicas.controllers import SesionController from .monitor_controller import MonitorController diff --git a/tecnicas/controllers/views_controller/session_management/monitor_rata_controller.py b/tecnicas/controllers/views_controller/session_management/monitor/monitor_rata_controller.py similarity index 100% rename from tecnicas/controllers/views_controller/session_management/monitor_rata_controller.py rename to tecnicas/controllers/views_controller/session_management/monitor/monitor_rata_controller.py diff --git a/tecnicas/controllers/views_controller/session_management/monitor/monitor_sort_controller.py b/tecnicas/controllers/views_controller/session_management/monitor/monitor_sort_controller.py new file mode 100644 index 0000000000000000000000000000000000000000..faf9890bf613eb704b8a9556d6f4c54307622891 --- /dev/null +++ b/tecnicas/controllers/views_controller/session_management/monitor/monitor_sort_controller.py @@ -0,0 +1,27 @@ +from tecnicas.models import SesionSensorial +from tecnicas.models import Participacion +from .monitor_controller import MonitorController + + +class MonitorSortController(MonitorController): + def __init__(self, session: SesionSensorial): + super().__init__(session) + self.url_view = "tecnicas/manage_sesions/monitor-session-sort.html" + self.previus_view = "cata_system:detalles_sesion" + + def checkAllFinish(self): + technique = self.sensorial_session.tecnica + + num_participations = Participacion.objects.filter( + tecnica=technique).count() + + if num_participations < technique.limite_catadores: + return (False, "No se ha alcanzado el número máximo de catadores") + + unfinished_participations = Participacion.objects.filter( + tecnica=technique, finalizado=False).count() + + if unfinished_participations > 0: + return (False, "No todos los catadores han finalizado su evaluación") + + return (True, "Puedes finalizar la sesión") \ No newline at end of file diff --git a/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_controller.py b/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_controller.py index 5d89da3a05492aef4d39813dba33e32296e28fbb..3aae41371be88f624386caa5841f8277d6495eed 100644 --- a/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_controller.py +++ b/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_controller.py @@ -11,7 +11,7 @@ class InitSessionController(): session: SesionSensorial order: Orden | dict current_direction: str - current_direction = "tecnicas/forms_tester/init_session.html" + current_direction = "tecnicas/forms_tester/init_scales_test.html" escalas_direction = "cata_system:session_convencional" def __init__(self, sensorial_session: SesionSensorial, user_tester: Catador): diff --git a/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_escalas_controller.py b/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_escalas_controller.py index 271577d22927c7cb0b9a23c4722080d3b6c84b21..2fb4e970f749193123cb785775eed700a21cfa7a 100644 --- a/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_escalas_controller.py +++ b/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_escalas_controller.py @@ -13,7 +13,7 @@ class InitSessionEscalasController(InitSessionController): def __init__(self, sensorial_session, user_tester): super().__init__(sensorial_session, user_tester) - self.current_direction = "tecnicas/forms_tester/init_session.html" + self.current_direction = "tecnicas/forms_tester/init_scales_test.html" self.escalas_direction = "cata_system:session_convencional" self.cata_direction = "cata_system:session_cata" diff --git a/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_pf_controller.py b/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_pf_controller.py index 991fcc19107622835b2e4ad32da6a0a945f2c4a5..299272eb21efb751ecec9362a0f0cbe9b7f324a0 100644 --- a/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_pf_controller.py +++ b/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_pf_controller.py @@ -9,7 +9,7 @@ from .init_session_controller import InitSessionController class InitSessionPFController(InitSessionController): def __init__(self, sensorial_session, user_tester): super().__init__(sensorial_session, user_tester) - self.current_direction = "tecnicas/forms_tester/init_session_pf.html" + self.current_direction = "tecnicas/forms_tester/init_pf_test.html" self.pf_direction = "cata_system:session_pf" def controllGet(self, request: HttpRequest): diff --git a/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_rata_controller.py b/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_rata_controller.py index 9eea35cd6c5f67102b8f296995aca5814e82f270..405986dbfbd0a93c1b00c61f0b0d2bd7e1068876 100644 --- a/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_rata_controller.py +++ b/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_rata_controller.py @@ -6,7 +6,7 @@ from .init_session_controller import InitSessionController class InitSessionRATAController(InitSessionController): def __init__(self, sensorial_session, user_tester): super().__init__(sensorial_session, user_tester) - self.current_direction = "tecnicas/forms_tester/init_session.html" + self.current_direction = "tecnicas/forms_tester/init_scales_test.html" def controllGet(self, request: HttpRequest): context = { diff --git a/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_sort_controller.py b/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_sort_controller.py new file mode 100644 index 0000000000000000000000000000000000000000..7d21f8c5f23157563b2dfbb826118980ac426b2f --- /dev/null +++ b/tecnicas/controllers/views_controller/sessions_tester/init_session/init_session_sort_controller.py @@ -0,0 +1,77 @@ +from django.http import HttpRequest +from django.shortcuts import render, redirect +from django.urls import reverse +from tecnicas.models import Participacion +from tecnicas.controllers import ParticipacionController +from .init_session_controller import InitSessionController + + +class InitSessionSortController(InitSessionController): + def __init__(self, sensorial_session, user_tester): + super().__init__(sensorial_session, user_tester) + self.current_direction = "tecnicas/forms_tester/init_test_sort.html" + self.sort_direction = "cata_system:session_sort" + + def controllGet(self, request: HttpRequest, error=""): + context = { + "session": self.session, + "type_technique": self.session.tecnica.tipo_tecnica.nombre_tecnica + } + + is_end = self.isEndedSession() + + context["has_ended"] = is_end + + if is_end: + context["message"] = "El catador ha terminado de realizar su evaluación, espere instrucciones del presentador" + + if "error" in request.GET: + context["error"] = request.GET["error"] + + return render(request, self.current_direction, context) + + def isEndedSession(self): + participation = Participacion.objects.get( + catador=self.tester, tecnica=self.session.tecnica) + + return participation.finalizado + + def controllPost(self, request: HttpRequest): + context = { + "session": self.session, + "type_technique": self.session.tecnica.tipo_tecnica.nombre_tecnica + } + + use_action = request.POST["action"] + + if use_action == "start_posting": + parameters = { + "code_sesion": self.session.codigo_sesion + } + + is_end = self.isEndedSession() + if is_end: + context["message"] = "El catador ha terminado de realizar su evaluación, espere instrucciones del presentador" + return render(request, self.current_direction, context) + + update_participation = ParticipacionController.enterSession( + tester=request.user.user_catador, session=self.session) + + if isinstance(update_participation, dict): + context["error"] = update_participation["error"] + return render(request, self.current_direction, context) + + request.session["id_participation"] = update_participation.id + + return redirect(reverse(self.sort_direction, kwargs=parameters)) + + elif use_action == "exit_session": + response = ParticipacionController.outSession( + tester=request.user.user_catador, session=self.session) + if isinstance(response, dict): + context["error"] = response["error"] + return render(request, self.current_direction, context) + + else: + context["error"] = "Acción sin especificar" + return render(request, self.current_direction, context) diff --git a/tecnicas/controllers/views_controller/sessions_tester/login_session_tester_controller.py b/tecnicas/controllers/views_controller/sessions_tester/login_session_tester_controller.py index 611c106d2815da8ea9c4b18f9a3b9fcb57c0525d..f8dbdd7a62d656a51d931d49996707afe791950d 100644 --- a/tecnicas/controllers/views_controller/sessions_tester/login_session_tester_controller.py +++ b/tecnicas/controllers/views_controller/sessions_tester/login_session_tester_controller.py @@ -98,5 +98,51 @@ class LoginSessionTesterController(): context["error"] = "Imposible acceder a esta sesión" return render(request, self.current_direcction, context) + def validateEntrySort(self, request: HttpRequest): + context = {} + if not self.session.activo: + context["error"] = "La sesión no está activa actualmente" + return render(request, self.current_direcction, context) + + if self.session.tecnica.repeticion == 1: + try: + self.taster_participation = Participacion.objects.get( + tecnica=self.session.tecnica, catador=self.tester) + context["error"] = "Usted ya esta dentro de la sesión" + return render(request, self.current_direcction, context) + + except Participacion.DoesNotExist: + try: + with transaction.atomic(): + code_session = self.session.codigo_sesion + self.session = SesionSensorial.objects.select_for_update().get( + codigo_sesion=code_session) + + max_testers = self.session.tecnica.limite_catadores + current_num_testers = Participacion.objects.filter( + tecnica=self.session.tecnica).count() + + if current_num_testers >= max_testers: + raise ValueError( + "La sesión ha alcanzado el número máximo de catadores") + + self.taster_participation = Participacion.objects.create( + tecnica=self.session.tecnica, + catador=self.tester, + finalizado=False + ) + params = { + "code_sesion": self.session.codigo_sesion + } + return redirect(reverse(self.destinity_direcction, kwargs=params)) + + except ValueError as e: + context["error"] = str(e) + return render(request, self.current_direcction, context) + + else: + context["error"] = "Ya no es posible ingresar a la sesión" + return render(request, self.current_direcction, context) + def validateEntryPF(self, request=HttpRequest): return self.validateEntryEscalas(request=request) diff --git a/tecnicas/controllers/views_controller/sessions_tester/tests_forms/general_test_controller.py b/tecnicas/controllers/views_controller/sessions_tester/tests_forms/general_test_controller.py index 5cfc2e37746557838b9947caa7de4abc098c348a..ddfc0941a4c6cd166456f1eb4170c232a97d1fbc 100644 --- a/tecnicas/controllers/views_controller/sessions_tester/tests_forms/general_test_controller.py +++ b/tecnicas/controllers/views_controller/sessions_tester/tests_forms/general_test_controller.py @@ -1,7 +1,8 @@ from django.http import HttpRequest from django.shortcuts import redirect, render from django.urls import reverse -from tecnicas.models import SesionSensorial, Catador +from tecnicas.models import SesionSensorial, Catador, Participacion +from tecnicas.controllers import ParticipacionController class GenetalTestController(): @@ -12,3 +13,16 @@ class GenetalTestController(): def __init__(self, sensorial_session: SesionSensorial, user_tester: Catador): self.tester = user_tester self.session = sensorial_session + + def controllPost(self, request: HttpRequest): + action = request.POST["action"] + + if action == "finish_session": + self.participation = Participacion.objects.get( + tecnica=self.session.tecnica, catador=request.user.user_catador) + ParticipacionController.finishSession(self.participation) + params = {"code_sesion": self.session.codigo_sesion} + return redirect(reverse(self.previus_directory, kwargs=params)) + + else: + return self.controllGet(request, error="Acción no permitida") diff --git a/tecnicas/controllers/views_controller/sessions_tester/tests_forms/test_cata_controller.py b/tecnicas/controllers/views_controller/sessions_tester/tests_forms/test_cata_controller.py index 19743636e3075434a97face6c0005c9f87099560..13f1badfa70504e81dce9a1819170e24031c311c 100644 --- a/tecnicas/controllers/views_controller/sessions_tester/tests_forms/test_cata_controller.py +++ b/tecnicas/controllers/views_controller/sessions_tester/tests_forms/test_cata_controller.py @@ -9,7 +9,7 @@ from .general_test_controller import GenetalTestController class TestCataController(GenetalTestController): def __init__(self, sensorial_session, user_tester): super().__init__(sensorial_session, user_tester) - self.current_directory = "tecnicas/forms_tester/cata.html" + self.current_directory = "tecnicas/forms_tester/test_cata.html" def controllGet(self, request: HttpRequest): technique = self.session.tecnica diff --git a/tecnicas/controllers/views_controller/sessions_tester/tests_forms/test_rata_controller.py b/tecnicas/controllers/views_controller/sessions_tester/tests_forms/test_rata_controller.py index fbbb570973d83ab5b8860e1c75c4b18c0075dbbc..ed51287a1f54f164cb93011693d689a097136019 100644 --- a/tecnicas/controllers/views_controller/sessions_tester/tests_forms/test_rata_controller.py +++ b/tecnicas/controllers/views_controller/sessions_tester/tests_forms/test_rata_controller.py @@ -9,7 +9,7 @@ from .general_test_controller import GenetalTestController class TestRataController(GenetalTestController): def __init__(self, sensorial_session, user_tester): super().__init__(sensorial_session, user_tester) - self.current_directory = "tecnicas/forms_tester/convencional.html" + self.current_directory = "tecnicas/forms_tester/test_convencional.html" def controllGet(self, request: HttpRequest): technique = self.session.tecnica diff --git a/tecnicas/controllers/views_controller/sessions_tester/tests_forms/test_scales_controller.py b/tecnicas/controllers/views_controller/sessions_tester/tests_forms/test_scales_controller.py index 2e0e60f82acb8b1516126bc7697b5c2a14e23d9b..19985ddd5d666bc206c8f9e2d11f6226d96a2800 100644 --- a/tecnicas/controllers/views_controller/sessions_tester/tests_forms/test_scales_controller.py +++ b/tecnicas/controllers/views_controller/sessions_tester/tests_forms/test_scales_controller.py @@ -9,7 +9,7 @@ from .general_test_controller import GenetalTestController class TestScalesController(GenetalTestController): def __init__(self, sensorial_session, user_tester): super().__init__(sensorial_session, user_tester) - self.current_directory = "tecnicas/forms_tester/convencional.html" + self.current_directory = "tecnicas/forms_tester/test_convencional.html" def controllGet(self, request: HttpRequest): technique = self.session.tecnica diff --git a/tecnicas/controllers/views_controller/sessions_tester/tests_forms/test_sort_controller.py b/tecnicas/controllers/views_controller/sessions_tester/tests_forms/test_sort_controller.py new file mode 100644 index 0000000000000000000000000000000000000000..51956d64a1f58ce084f33e5425eab2b3de3fbe08 --- /dev/null +++ b/tecnicas/controllers/views_controller/sessions_tester/tests_forms/test_sort_controller.py @@ -0,0 +1,50 @@ +from django.http import HttpRequest +from django.shortcuts import redirect, render +from django.urls import reverse +from tecnicas.models import Participacion, Producto, Calificacion, Palabra, GrupoProducto +from tecnicas.controllers import ParticipacionController, PalabrasController, EscalaController +from tecnicas.forms import ListWordsForm +from .general_test_controller import GenetalTestController + + +class TestSortController(GenetalTestController): + def __init__(self, sensorial_session, user_tester): + super().__init__(sensorial_session, user_tester) + self.current_directory = "tecnicas/forms_tester/test_sort.html" + + def controllGet(self, request: HttpRequest): + ''' + Objetivo: Entregar al cliente los grupos de productos guardados hechos por el catador en una lista, de lo contrario solo mandar una lista vacia + - Comprobar que el Catador aun no finalice su la sesion + - Obtener todos los productos en la tecnica + - Obtener todos los grupos creadas por el usuario + - Si hay grupos, cada item de la lista a mandar debe incluir los productos asociados al grupo como las palabras que describen al grupo + - Si no hay grupos, solo mandar una lista vacia + - Mandar la lista de grupos como la lista de productos + - Agregar el formulario para describir los grupo + ''' + self.context["session"] = self.session + technique = self.session.tecnica + + self.participation = Participacion.objects.get( + tecnica=technique, catador=request.user.user_catador) + + # Comprobar que el Catador no haya finalizado + if self.participation.finalizado: + params = { + "code_sesion": self.session.codigo_sesion + } + return redirect(reverse(self.previus_directory, kwargs=params)) + + products_in_technique = Producto.objects.filter(id_tecnica=technique) + self.context["products"] = products_in_technique + + grups_products = GrupoProducto.objects.filter( + tecnica=technique, catador=request.user.user_catador).select_related("productos", "palabras") + + self.context["grups_products"] = grups_products if grups_products else [] + + self.context["form_word"] = ListWordsForm() + + return render(request, self.current_directory, self.context) + diff --git a/tecnicas/forms/__init__.py b/tecnicas/forms/__init__.py index ff154ded014eb604b67d8688abd8ddfbfe11cbd7..1add46c25cd8a274807116652797d50b80795081 100644 --- a/tecnicas/forms/__init__.py +++ b/tecnicas/forms/__init__.py @@ -2,6 +2,8 @@ from .create_session.sesion_basic_form import SesionBasicForm from .create_session.sesiob_basic_cata_form import SesionBasicCATAForm from .create_session.sesion_basic_pf_form import SesionBasicPFForm from .create_session.sesion_tags_form import SesionTagsForm +from .create_session.sesion_basic_sort_form import SesionBasicSortForm +from .create_session.sesion_basic_napping import SesionBasicNappingForm from .etiqueta_form import EtiquetaForm from .codes_form import CodesForm diff --git a/tecnicas/forms/create_session/sesiob_basic_cata_form.py b/tecnicas/forms/create_session/sesiob_basic_cata_form.py index b578857573b1257f2dc2dc27b36d488def2f559a..4a58d9be5dcbbe55aff7bda0b2f684cce657f293 100644 --- a/tecnicas/forms/create_session/sesiob_basic_cata_form.py +++ b/tecnicas/forms/create_session/sesiob_basic_cata_form.py @@ -22,6 +22,11 @@ class SesionBasicCATAForm(forms.Form): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.fields['estilo_palabras'] = forms.ModelChoiceField(queryset=EstiloPalabra.objects.all(), widget=forms.RadioSelect(attrs={ + options = [ + ("atributos", "atributos"), + ("vocabulario", "vocabulario") + ] + + self.fields['estilo_palabras'] = forms.ChoiceField(choices=options, widget=forms.RadioSelect(attrs={ "class": "uppercase text-lg tracking-wider font-medium p-2 px-4 active:px-5 transition-all rounded-xl bg-blue-500 text-white", - }), required=True, initial=EstiloPalabra.objects.first()) + }), required=True, initial=options[0]) diff --git a/tecnicas/forms/create_session/sesion_basic_form.py b/tecnicas/forms/create_session/sesion_basic_form.py index 34fef6e39575562583ac21e8e470be0eeb7874af..1fd90dcac0ce54d36a342d3af94080f08aa5da47 100644 --- a/tecnicas/forms/create_session/sesion_basic_form.py +++ b/tecnicas/forms/create_session/sesion_basic_form.py @@ -38,9 +38,14 @@ class SesionBasicForm(forms.Form): if initial_conf is None: initial_conf = {} - self.fields['estilo_palabras'] = forms.ModelChoiceField(queryset=EstiloPalabra.objects.all(), widget=forms.RadioSelect(attrs={ + options = [ + ("atributos", "atributos"), + ("vocabulario", "vocabulario") + ] + + self.fields['estilo_palabras'] = forms.ChoiceField(choices=options, widget=forms.RadioSelect(attrs={ "class": "uppercase text-lg tracking-wider font-medium p-2 px-4 active:px-5 transition-all rounded-xl bg-blue-500 text-white", - }), required=True, initial=EstiloPalabra.objects.first()) + }), required=True, initial=options[0]) self.fields['tipo_escala'] = forms.ModelChoiceField(queryset=TipoEscala.objects.all(), widget=forms.RadioSelect(attrs={ "class": "uppercase text-lg tracking-wider font-medium p-2 px-4 active:px-5 transition-all rounded-xl bg-blue-500 text-white", diff --git a/tecnicas/forms/create_session/sesion_basic_napping.py b/tecnicas/forms/create_session/sesion_basic_napping.py new file mode 100644 index 0000000000000000000000000000000000000000..22854573bd93aeea285ef95f25b687df17cd828a --- /dev/null +++ b/tecnicas/forms/create_session/sesion_basic_napping.py @@ -0,0 +1,24 @@ +from django import forms + + +class SesionBasicNappingForm(forms.Form): + nombre_sesion = forms.CharField(max_length=255, widget=forms.TextInput(attrs={ + "class": "bg-surface-ligt border-b-1 text-center w-full p-1", + "name": "nombre_sesion", + "placeholder": "Ej. Mermelada de mango picante" + }), required=False) + + numero_productos = forms.IntegerField(widget=forms.NumberInput(attrs={ + "class": "bg-surface-ligt p-1 border-b-1 text-center w-full", + "placeholder": "Solo números" + }), required=True) + + numero_catadores = forms.IntegerField(widget=forms.NumberInput(attrs={ + "class": "bg-surface-ligt p-1 border-b-1 text-center w-full", + "placeholder": "Solo números" + }), required=True) + + instrucciones = forms.CharField(max_length=255, widget=forms.TextInput(attrs={ + "class": "bg-surface-ligt border-b-1 text-center w-full p-1", + "placeholder": "Este campo es opcional" + }), required=False) diff --git a/tecnicas/forms/create_session/sesion_basic_pf_form.py b/tecnicas/forms/create_session/sesion_basic_pf_form.py index 819d44d89a188a5002b3873f236629ac5efe242c..d1609d4b8e95a3dc7cc405ca1b095f2fc7420ff2 100644 --- a/tecnicas/forms/create_session/sesion_basic_pf_form.py +++ b/tecnicas/forms/create_session/sesion_basic_pf_form.py @@ -1,5 +1,4 @@ from django import forms -from tecnicas.models import TipoEscala class SesionBasicPFForm(forms.Form): diff --git a/tecnicas/forms/create_session/sesion_basic_sort_form.py b/tecnicas/forms/create_session/sesion_basic_sort_form.py new file mode 100644 index 0000000000000000000000000000000000000000..bb2f0c70775cd838a064c4670b04a2ab587d5fce --- /dev/null +++ b/tecnicas/forms/create_session/sesion_basic_sort_form.py @@ -0,0 +1,24 @@ +from django import forms + + +class SesionBasicSortForm(forms.Form): + nombre_sesion = forms.CharField(max_length=255, widget=forms.TextInput(attrs={ + "class": "bg-surface-ligt border-b-1 text-center w-full p-1", + "name": "nombre_sesion", + "placeholder": "Ej. Mermelada de mango picante" + }), required=False) + + numero_productos = forms.IntegerField(widget=forms.NumberInput(attrs={ + "class": "bg-surface-ligt p-1 border-b-1 text-center w-full", + "placeholder": "Solo números" + }), required=True) + + numero_catadores = forms.IntegerField(widget=forms.NumberInput(attrs={ + "class": "bg-surface-ligt p-1 border-b-1 text-center w-full", + "placeholder": "Solo números" + }), required=True) + + instrucciones = forms.CharField(max_length=255, widget=forms.TextInput(attrs={ + "class": "bg-surface-ligt border-b-1 text-center w-full p-1", + "placeholder": "Este campo es opcional" + }), required=False) diff --git a/tecnicas/migrations/0024_alter_sesionsensorial_codigo_sesion_grupoproducto.py b/tecnicas/migrations/0024_alter_sesionsensorial_codigo_sesion_grupoproducto.py new file mode 100644 index 0000000000000000000000000000000000000000..0504ee42d9cada10afede1de43c835e2ff75b8ae --- /dev/null +++ b/tecnicas/migrations/0024_alter_sesionsensorial_codigo_sesion_grupoproducto.py @@ -0,0 +1,30 @@ +# Generated by Django 5.2.1 on 2025-11-25 01:18 + +import django.db.models.deletion +import shortuuid.main +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('tecnicas', '0023_alter_sesionsensorial_codigo_sesion_listapalabras'), + ] + + operations = [ + migrations.AlterField( + model_name='sesionsensorial', + name='codigo_sesion', + field=models.CharField(default=shortuuid.main.ShortUUID.uuid, editable=False, max_length=22, primary_key=True, serialize=False), + ), + migrations.CreateModel( + name='GrupoProducto', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('catador', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='catador_grupo_producto', to='tecnicas.catador')), + ('palabras', models.ManyToManyField(related_name='grupo_producto', to='tecnicas.palabra')), + ('productos', models.ManyToManyField(related_name='grupo_producto', to='tecnicas.producto')), + ('tecnica', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tecnica_grupo_producto', to='tecnicas.tecnica')), + ], + ), + ] diff --git a/tecnicas/models/__init__.py b/tecnicas/models/__init__.py index b642d98eb1d61d58cae1e397890c3daeab492f23..8f81308d70330373dd54f858cbb50c4b9be8d9bf 100644 --- a/tecnicas/models/__init__.py +++ b/tecnicas/models/__init__.py @@ -30,3 +30,4 @@ from .orden import Posicion from .participacion import Participacion from .lista_palabras import ListaPalabras +from .grupo_producto import GrupoProducto diff --git a/tecnicas/models/grupo_producto.py b/tecnicas/models/grupo_producto.py new file mode 100644 index 0000000000000000000000000000000000000000..ae21abdb5ef2d69322bf8dec4880b74d7f5bf166 --- /dev/null +++ b/tecnicas/models/grupo_producto.py @@ -0,0 +1,19 @@ +from django.db import models +from tecnicas.models import Tecnica, Catador, Palabra, Producto + + +class GrupoProducto(models.Model): + tecnica = models.ForeignKey( + Tecnica, on_delete=models.CASCADE, related_name="tecnica_grupo_producto") + + catador = models.ForeignKey( + Catador, on_delete=models.CASCADE, related_name="catador_grupo_producto") + + productos = models.ManyToManyField( + Producto, related_name="grupo_producto") + + palabras = models.ManyToManyField( + Palabra, related_name="grupo_producto") + + def __str__(self): + return f"{self.tecnica.sesion_tecnica.codigo_sesion} - {self.catador.user.username}" diff --git a/tecnicas/static/js/download-table-csv.js b/tecnicas/static/js/download-table-csv.js index 1e525453c2a5aa0bf5fbe1a55babcf923d65a13a..27afdf85556badce4f412b9da43405f8d50c8f16 100644 --- a/tecnicas/static/js/download-table-csv.js +++ b/tecnicas/static/js/download-table-csv.js @@ -4,7 +4,7 @@ document.addEventListener("DOMContentLoaded", function () { btn.addEventListener("click", function () { // Try set the table in the page - let table = document.getElementById("convencional-table"); + let table = document.getElementById("generic-donwload-table"); if (!table) { const section = btn.closest("section"); if (section) table = section.querySelector("table"); diff --git a/tecnicas/static/js/download-table-sort-csv.js b/tecnicas/static/js/download-table-sort-csv.js new file mode 100644 index 0000000000000000000000000000000000000000..0253a18129d6369de6a96b5b99e841800f292b03 --- /dev/null +++ b/tecnicas/static/js/download-table-sort-csv.js @@ -0,0 +1,79 @@ +document.addEventListener("DOMContentLoaded", function () { + const btn = document.getElementById("download-csv-btn"); + if (!btn) return; + + btn.addEventListener("click", function () { + // Try set the table in the page + let table = document.getElementById("generic-donwload-table"); + if (!table) { + const section = btn.closest("section"); + if (section) table = section.querySelector("table"); + } + if (!table) { + console.warn("No se encontró la tabla para descargar."); + return; + } + + // helper to trim and normalize cell text + const cellText = (cell) => { + if (!cell) return ""; + return String(cell.textContent || "").trim(); + }; + + // Collect headers + const headers = []; + const ths = table.querySelectorAll("thead th"); + ths.forEach((th) => headers.push(cellText(th))); + + // Collect rows + const rows = []; + const trs = table.querySelectorAll("tbody tr"); + trs.forEach((tr) => { + const cols = []; + const tds = tr.querySelectorAll("td"); + tds.forEach((td) => cols.push(cellText(td))); + rows.push(cols); + }); + + // Convert to CSV string (escape quotes, wrap in quotes if needed) + const escapeValue = (val) => { + if (val == null) return ""; + let normalVal = val.replace(/[\u0300-\u036f]/g, ""); + normalVal = normalVal.replace(/(\r\n|\n|\r|\s)/gm, ''); + const needsQuotes = /[",\n,;]/.test(normalVal); + let v = normalVal.replace(/"/g, '""'); + if (needsQuotes) v = `"${v}"`; + return v; + }; + + const lines = []; + if (headers.length) lines.push(headers.map(escapeValue).join(",")); + rows.forEach((r) => lines.push(r.map(escapeValue).join(","))); + + const csvContent = lines.join("\n"); + + // File name: data_{nombre_sesion or codigo_sesion} + const rawName = (btn.dataset.sessionName || "").trim(); + const code = (btn.dataset.sessionCode || "").trim() || "session"; + const namePart = rawName + ? rawName.replace(/[^a-zA-Z0-9-_áéíóúÁÉÍÓÚ ]/g, "").replace(/\s+/g, "_") + : code; + const fileName = `data_${namePart}.csv`; + + // Create blob and force download + const blob = new Blob([csvContent], { type: "text/csv;charset=UTF-8;" }); + if (navigator.msSaveBlob) { + navigator.msSaveBlob(blob, fileName); + } else { + const link = document.createElement("a"); + const url = URL.createObjectURL(blob); + link.setAttribute("href", url); + link.setAttribute("download", fileName); + link.style.visibility = "hidden"; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + URL.revokeObjectURL(url); + } + }); +}); diff --git a/tecnicas/static/js/test-sort.js b/tecnicas/static/js/test-sort.js new file mode 100644 index 0000000000000000000000000000000000000000..0d46731c1b35bc5d8c3e4d6627a5267db9579347 --- /dev/null +++ b/tecnicas/static/js/test-sort.js @@ -0,0 +1,554 @@ +let dragged = null; + +const productsPlaceHolder = ` +

+ Agrupación de productos +

`; + +const wordsPlaceHolder = ` +

+ Lista de atributos +

`; + +const products = document.querySelectorAll(".draggable"); +const zonesDrop = document.querySelectorAll(".dropzone"); + +const DATA_GRUPS = {}; + +products.forEach(manageDragables); +zonesDrop.forEach(manageDropZone); + + +/* +//// +////// +//////// Add new grups +////// +//// +*/ + +function addNewGrup() { + const container = document.getElementById("containers"); + const newGrup = document.createElement("section"); + const styles = "w-fit space-y-4 border rounded p-2 bg-surface-sweet"; + newGrup.classList.add(...styles.split(" ")); + + const formWord = document.getElementById("form-word"); + const formWordClone = formWord.cloneNode(true); + formWordClone.classList.remove("hidden"); + + newGrup.innerHTML = ` +
+ ${productsPlaceHolder} +
+ ${formWordClone.outerHTML} +
+ ${wordsPlaceHolder} +
+
+ + + +
`; + + manageDropZone(newGrup.querySelector(".dropzone")); + container.appendChild(newGrup); +} + + +/* +//// +////// +//////// Manage products' drags and remove drags +////// +//// +*/ + +/** + * + * @param {HTMLElement} zone + */ +function manageDropZone(zone) { + /* + //// + ////// Trash Zone product + //// + */ + if (zone.classList.contains("trash-products")) { + zone.addEventListener("dragover", (e) => e.preventDefault()); + + zone.addEventListener("drop", (event) => { + const codeDrag = dragged.dataset.code + const oldParent = dragged.parentNode; + const oldCodeZone = oldParent.getAttribute("id") + + if (oldParent.classList.contains("original-products")) { + spanNotifaction("No puedes borrar este producto"); + return + } + + dragged.remove() + removeProduct(codeDrag, oldCodeZone) + + spanNotifaction("Producto removido del grupo", false); + dragged = null + + if (oldParent.classList.contains("dropzone") && oldParent.children.length === 0) { + oldParent.innerHTML = productsPlaceHolder; + } + }) + return + } + + /* + //// + ////// Identificate grups and creata dinamic data + //// + */ + + // Create id for grup + const idZone = generateSimpleID() + + // Add products if there en the page + const products = [] + const productsElements = zone.querySelectorAll(".draggable") || None; + + if (productsElements) { + productsElements.forEach((proEle) => { + products.push({ + id: proEle.dataset.idProduct, + code: proEle.dataset.code + }) + }) + } + + const parentZone = zone.parentNode; + const wordsInGrup = parentZone.querySelectorAll(".item-word") || None + + // Add words if there en the page + const words = [] + if (wordsInGrup) { + wordsInGrup.forEach((wordElement) => { + words.push(wordElement.textContent) + }) + } + + DATA_GRUPS[idZone] = { + products: products, + words: words + } + + /* + //// + ////// Drop Zone product + //// + */ + + zone.setAttribute("id", idZone) + zone.addEventListener("dragover", (e) => e.preventDefault()); + + zone.addEventListener("drop", () => { + const codeDrag = dragged.dataset.code + const zoneCode = zone.getAttribute("id") + + // Check that new produck is not in currents products of the group + const obj = DATA_GRUPS[zoneCode].products.find((product) => product.code == codeDrag) + if (obj) { + spanNotifaction("Ese producto ya está en el grupo"); + return + } + + DATA_GRUPS[zoneCode].products.push({ + id: dragged.dataset.idProduct, + code: dragged.dataset.code + }) + + const oldParent = dragged.parentNode; + + const p = zone.querySelector("p"); + if (p) { + p.remove(); + } + + // Move original or clone product in zone + if (oldParent.classList.contains("dropzone")) { + zone.appendChild(dragged); + } else { + const clone = dragged.cloneNode(true); + clone.classList.remove("opacity-50"); + manageDragables(clone); + zone.appendChild(clone); + } + + if (oldParent.classList.contains("dropzone")) { + if (oldParent.children.length === 0) oldParent.innerHTML = productsPlaceHolder; + const zoneCodeOld = oldParent.getAttribute("id") + removeProduct(codeDrag, zoneCodeOld) + } + }); + + // Add listeners to elements options and WordForm for the list words + addListenersButtonQuestionGrup(zone.parentNode) + manageFormWord(parentZone.querySelector("form"), parentZone.querySelector(".words-container"), idZone) + + if (DATA_GRUPS[idZone].words.length) { + parentZone.querySelector(".words-container").innerHTML = ""; + DATA_GRUPS[idZone].words.forEach((word) => { + const itemWord = getItemWord(word, idZone); + parentZone.querySelector(".words-container").appendChild(itemWord); + }) + } +} + +/* +//// +////// +//////// Management Drags and FormWord +////// +//// +*/ + +/** + * + * @param {HTMLElement} el + */ +function manageDragables(el) { + el.addEventListener("dragstart", () => { + dragged = el; + setTimeout(() => el.classList.add("opacity-50"), 0); + }); + + el.addEventListener("dragend", () => { + dragged = null; + el.classList.remove("opacity-50"); + }); +} + +/** + * + * @param {HTMLFormElementt} form + * @param {HTMLElement} containerWords + */ +function manageFormWord(form, containerWords, codeGrup) { + form.addEventListener("submit", (e) => { + e.preventDefault(); + + if (!form.reportValidity()) { + return; + } + + const input = form.querySelector('input[type="text"]'); + + if (!input) return; + + const name = input.value.trim(); + if (!name) return; + + if (DATA_GRUPS[codeGrup].words.includes(name)) { + input.value = ""; + input.focus(); + spanNotifaction("Esa palabra ya está en la lista"); + return; + } + + DATA_GRUPS[codeGrup].words.push(name) + const wordItem = getItemWord(name, codeGrup) + + const p = containerWords.querySelector("p"); + if (p) { + p.remove(); + } + + containerWords.appendChild(wordItem) + + input.value = ""; + input.focus(); + }); +} + +/* +//// +////// +//////// Management Drags and FormWord +////// +//// +*/ + +/** + * + * @param {HTMLElement} grup + */ +function removeGrup(grup) { + delete DATA_GRUPS[grup.querySelector(".dropzone").getAttribute("id")] + grup.remove() +} + +function removeWord(code, wordName) { + const newWords = DATA_GRUPS[code].words.filter(word => word != wordName) + DATA_GRUPS[code].words = newWords + if (!newWords.length) { + const containerWords = document.getElementById(code).parentNode.querySelector(".words-container") + containerWords.innerHTML = wordsPlaceHolder; + } +} + +function removeProduct(codeProduct, codeZone) { + const newProducts = DATA_GRUPS[codeZone].products.filter((product) => product.code != codeProduct) + DATA_GRUPS[codeZone].products = newProducts +} + +function getItemWord(wordName, code) { + const STYLES_DIV = "cts-item-words bg-surface-ligt text-black rounded font-bold text-lg p-1 flex flex-wrap flex-row flex-1 min-w-fit justify-center items-center gap-3"; + const STYLES_BTN = "cts-remove-word cts-btn-general-compress px-2 cts-btn-error" + + const btn = document.createElement("button"); + btn.setAttribute("data-code", code); + btn.setAttribute("data-word", wordName); + btn.classList.add(...STYLES_BTN.split(" ")); + btn.textContent = "➖"; + + const span = document.createElement("span"); + span.classList.add("item-word"); + span.textContent = wordName; + + const div = document.createElement("div"); + div.setAttribute("id", `word-${code}-${wordName}`); + div.classList.add(...STYLES_DIV.split(" ")); + + div.appendChild(span); + div.appendChild(btn); + + btn.addEventListener("click", (e) => { + removeWord(code, wordName) + div.remove() + }) + + return div; +}; + +/** + * + * @param {HTMLElement} grupContainer + */ +function addListenersButtonQuestionGrup(grupContainer) { + // Function hidden question + grupContainer.querySelector(".cts-question").addEventListener("click", (event) => { + hiddenQuestionRemoveGroup(grupContainer) + }) + + // Function cancel remove + grupContainer.querySelector(".cts-no-remove").addEventListener("click", (event) => { + hiddenQuestionRemoveGroup(grupContainer, false) + }) + + // Function remove grup + grupContainer.querySelector(".cts-remove").addEventListener("click", (event) => { + removeGrup(grupContainer) + }) +} + +/* +//// +////// +//////// Management Options Save and remove groups +////// +//// +*/ + +/** + * + * @param {HTMLDivElement} container + * @param {boolean} hiddenQuestion + */ +function hiddenQuestionRemoveGroup(container, hiddenQuestion = true) { + const question = container.querySelector(".cts-question") + const remove = container.querySelector(".cts-remove") + const noRemove = container.querySelector(".cts-no-remove") + + + if (hiddenQuestion) { + question.classList.add("hidden") + remove.classList.remove("hidden") + noRemove.classList.remove("hidden") + } else { + question.classList.remove("hidden") + remove.classList.add("hidden") + noRemove.classList.add("hidden") + } +} + +function generateSimpleID() { + const first = Date.now().toString(35); + const second = Math.random().toString(36).slice(2); + return first + second; +} + +function showOptionsSave() { + document.getElementById("question-save").classList.add("hidden"); + document.getElementById("finish-session").classList.remove("hidden"); + document.getElementById("cancel-save").classList.remove("hidden"); +} + +function showQuestionSave() { + document.getElementById("question-save").classList.remove("hidden"); + document.getElementById("finish-session").classList.add("hidden"); + document.getElementById("cancel-save").classList.add("hidden"); +} + +document + .getElementById("question-save") + .addEventListener("click", showOptionsSave); + +document + .getElementById("cancel-save") + .addEventListener("click", showQuestionSave); + +/* +//// +////// +//////// Save data +////// +//// +*/ + +async function saveData() { + const keysDataGrups = Object.keys(DATA_GRUPS); + const allCodesProducts = new Set() + + products.forEach((productElement) => { + allCodesProducts.add(productElement.getAttribute("data-code")) + }) + + if (keysDataGrups.length === 0) { + spanNotifaction("No hay grupos para guardar") + return false; + } + + const data = [] + let thereError = false; + const codesProducts = [] + + keysDataGrups.forEach((key) => { + if (thereError) return + + const dataGrup = DATA_GRUPS[key]; + if (!dataGrup) { + spanNotifaction("No hay datos para guardar") + thereError = true; + return + } + + if (dataGrup.products.length === 0) { + spanNotifaction("Los grupos deben tener por lo menos un producto para guardar") + thereError = true; + return + } + + if (dataGrup.words.length === 0) { + spanNotifaction("Los grupos deben tener por lo menos una palabra para guardar") + thereError = true; + return + } + + const words = dataGrup.words; + const products = dataGrup.products; + + codesProducts.push(...products.map((product) => product.code)) + + data.push({ + words, + products + }) + }) + + if (thereError) return false; + + const currentCodesProducts = new Set(codesProducts) + const difference = symmetricDifference(currentCodesProducts, allCodesProducts) + + if (difference.size > 0) { + spanNotifaction("Falta un producto que debe ser ordenado") + return false + } + + const URL = "/cata/testers/api/rating-sort" + const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value; + + try { + const response = await fetch(URL, { + method: "POST", + headers: { + "Content-Type": "application/json", + "X-CSRFToken": csrfToken, + }, + body: JSON.stringify(data), + }) + + if (!response.ok) { + spanNotifaction("Error en la respuesta del servidor") + return false; + } + + const result = await response.json() + + if (result.error) { + spanNotifaction(result.error) + return false + } else { + spanNotifaction(result.message, false) + return true + } + } catch (error) { + spanNotifaction("Error en proceso de guardar los datos") + return false + } +} + +const buttonSaveData = document.getElementById("save-progress") +buttonSaveData.addEventListener("click", saveData) + +function symmetricDifference(setA, setB) { + let _difference = new Set(setA); + for (let elem of setB) { + if (_difference.has(elem)) { + _difference.delete(elem); + } else { + _difference.add(elem); + } + } + return _difference; +} + +/* +//// +////// +//////// Finish session +////// +//// +*/ + +document + .getElementById("finish-session") + .addEventListener("click", finishSession); + +async function finishSession() { + const save = await saveData(); + if (!save) { + spanNotifaction("Error al guardar los datos") + return + }; + + const FORM_ACTION = document.querySelector(".form-actions") + + const inputAction = FORM_ACTION.querySelector(".action-input"); + FORM_ACTION.action = ""; + inputAction.value = "finish_session"; + FORM_ACTION.submit(); +} \ No newline at end of file diff --git a/tecnicas/templates/tecnicas/components/table-scales.html b/tecnicas/templates/tecnicas/components/table-scales.html index 57ea9cd2db4b6d8ddacb9fface6ad5a72ee6fa32..8c331debc39b94332fda6935ed2d4a825b6e45e8 100644 --- a/tecnicas/templates/tecnicas/components/table-scales.html +++ b/tecnicas/templates/tecnicas/components/table-scales.html @@ -1,7 +1,7 @@ {% load static %}
- +
{% if sesion.tecnica.tipo_tecnica.nombre_tecnica != "rata" %} diff --git a/tecnicas/templates/tecnicas/components/table-sort.html b/tecnicas/templates/tecnicas/components/table-sort.html new file mode 100644 index 0000000000000000000000000000000000000000..9a4eb37a7d76ae20e8817c6301d2af1f53c6b666 --- /dev/null +++ b/tecnicas/templates/tecnicas/components/table-sort.html @@ -0,0 +1,42 @@ +{% load custom_filters %} +{% load static %} +
+
+
+ + + + {% for tester in data_groups.testers %} + + {% endfor %} + + + + {% for data_words in data_groups.data %} + + + {% for tester in data_groups.testers %} + + {% endfor %} + + {% endfor %} + +
Producto + Consumidor {{ forloop.counter }}: {{ tester }} +
{{ data_words.codigo_producto }} + + {% for word in data_words.palabras|get_item:tester %} + {{word}}{% if not forloop.last %} ;{% endif %} + {% endfor %} +
+
+ +
+ +
+
+ + \ No newline at end of file diff --git a/tecnicas/templates/tecnicas/components/table_cata.html b/tecnicas/templates/tecnicas/components/table_cata.html index 2b45e7d6274e7b05eb2845955665ba1c3bdd9df6..95f8ac78dad88cd38c7955ce18324bef2c131fea 100644 --- a/tecnicas/templates/tecnicas/components/table_cata.html +++ b/tecnicas/templates/tecnicas/components/table_cata.html @@ -1,7 +1,7 @@ {% load static %}
- +
diff --git a/tecnicas/templates/tecnicas/components/table_pf.html b/tecnicas/templates/tecnicas/components/table_pf.html index 4f640fd4102293ed5d38365e86f622e3d49ebfb3..6a4bff6e25eefdd0f0ab5447fcdce4a7138208f4 100644 --- a/tecnicas/templates/tecnicas/components/table_pf.html +++ b/tecnicas/templates/tecnicas/components/table_pf.html @@ -5,7 +5,7 @@

Datos de usuario {{ data.tester }}

-
Usuario
+
diff --git a/tecnicas/templates/tecnicas/create_sesion/configuracion-panel-basic.html b/tecnicas/templates/tecnicas/create_sesion/conf-panel-basic.html similarity index 100% rename from tecnicas/templates/tecnicas/create_sesion/configuracion-panel-basic.html rename to tecnicas/templates/tecnicas/create_sesion/conf-panel-basic.html diff --git a/tecnicas/templates/tecnicas/create_sesion/configuracion-panel-codes.html b/tecnicas/templates/tecnicas/create_sesion/conf-panel-codes.html similarity index 100% rename from tecnicas/templates/tecnicas/create_sesion/configuracion-panel-codes.html rename to tecnicas/templates/tecnicas/create_sesion/conf-panel-codes.html diff --git a/tecnicas/templates/tecnicas/create_sesion/configuracion-panel-tags.html b/tecnicas/templates/tecnicas/create_sesion/conf-panel-tags.html similarity index 100% rename from tecnicas/templates/tecnicas/create_sesion/configuracion-panel-tags.html rename to tecnicas/templates/tecnicas/create_sesion/conf-panel-tags.html diff --git a/tecnicas/templates/tecnicas/create_sesion/configuracion-panel-words.html b/tecnicas/templates/tecnicas/create_sesion/conf-panel-words.html similarity index 100% rename from tecnicas/templates/tecnicas/create_sesion/configuracion-panel-words.html rename to tecnicas/templates/tecnicas/create_sesion/conf-panel-words.html diff --git a/tecnicas/templates/tecnicas/create_sesion/creando_sesion.html b/tecnicas/templates/tecnicas/create_sesion/creating_session.html similarity index 100% rename from tecnicas/templates/tecnicas/create_sesion/creando_sesion.html rename to tecnicas/templates/tecnicas/create_sesion/creating_session.html diff --git a/tecnicas/templates/tecnicas/create_sesion/panel-basic-napping.html b/tecnicas/templates/tecnicas/create_sesion/panel-basic-napping.html new file mode 100644 index 0000000000000000000000000000000000000000..dfcc30a68152cac87120fca90b5283ad483b7a36 --- /dev/null +++ b/tecnicas/templates/tecnicas/create_sesion/panel-basic-napping.html @@ -0,0 +1,71 @@ +{% extends 'tecnicas/layouts/base.html' %} +{% load static %} + +{% block title %}Panel Configuracion{% endblock %} + +{% block content %} +
+
+

Panel de configuración

+ + {% if error %} + {% include "../components/error-message.html" with message=error %} + {% endif %} + {% if message %} + {% include "../components/error-message.html" with message=message %} + {% endif %} + +
+ {% csrf_token %} +
+

Información Basica

+
+ +
+
+ + +
+
+ +
+
+ + + +
+
+{% endblock %} + +{% block extra_js %} + +{% endblock %} \ No newline at end of file diff --git a/tecnicas/templates/tecnicas/create_sesion/panel-basic-sort.html b/tecnicas/templates/tecnicas/create_sesion/panel-basic-sort.html new file mode 100644 index 0000000000000000000000000000000000000000..dfcc30a68152cac87120fca90b5283ad483b7a36 --- /dev/null +++ b/tecnicas/templates/tecnicas/create_sesion/panel-basic-sort.html @@ -0,0 +1,71 @@ +{% extends 'tecnicas/layouts/base.html' %} +{% load static %} + +{% block title %}Panel Configuracion{% endblock %} + +{% block content %} +
+
+

Panel de configuración

+ + {% if error %} + {% include "../components/error-message.html" with message=error %} + {% endif %} + {% if message %} + {% include "../components/error-message.html" with message=message %} + {% endif %} + +
+ {% csrf_token %} +
+

Información Basica

+
+ +
+
+ + +
+
+ +
+
+ + + +
+
+{% endblock %} + +{% block extra_js %} + +{% endblock %} \ No newline at end of file diff --git a/tecnicas/templates/tecnicas/create_sesion/seleccion-tecnica.html b/tecnicas/templates/tecnicas/create_sesion/select-tecnica.html similarity index 100% rename from tecnicas/templates/tecnicas/create_sesion/seleccion-tecnica.html rename to tecnicas/templates/tecnicas/create_sesion/select-tecnica.html diff --git a/tecnicas/templates/tecnicas/forms_tester/init_session_pf.html b/tecnicas/templates/tecnicas/forms_tester/init_pf_test.html similarity index 100% rename from tecnicas/templates/tecnicas/forms_tester/init_session_pf.html rename to tecnicas/templates/tecnicas/forms_tester/init_pf_test.html diff --git a/tecnicas/templates/tecnicas/forms_tester/init_session.html b/tecnicas/templates/tecnicas/forms_tester/init_scales_test.html similarity index 100% rename from tecnicas/templates/tecnicas/forms_tester/init_session.html rename to tecnicas/templates/tecnicas/forms_tester/init_scales_test.html diff --git a/tecnicas/templates/tecnicas/forms_tester/init_test_sort.html b/tecnicas/templates/tecnicas/forms_tester/init_test_sort.html new file mode 100644 index 0000000000000000000000000000000000000000..5c53e2f765783dd45de9cf3bbcbbce7c709e44e0 --- /dev/null +++ b/tecnicas/templates/tecnicas/forms_tester/init_test_sort.html @@ -0,0 +1,108 @@ +{% extends 'tecnicas/layouts/base.html' %} +{% load static %} + +{% block title %}Detalles Sesion{% endblock %} + +{% block content %} +
+
+
+

+ Panel principal de Catadores +

+
+ +
+

+ Información sobre la sesión en la que participa +

+
+ + {% if error %} + {% include "../components/error-message.html" with message=error %} + {% endif %} + {% if message %} + {% include "../components/error-message.html" with message=message %} + {% endif %} +
+ +
+
+

+ Código: +

+

+ {{ session.codigo_sesion }} +

+
+ +
+

+ {% if session.nombre_sesion %} + {{ session.nombre_sesion }} + {% else %} + Sin nombre + {% endif %} +

+
+ +
+

+ Esta sesión usa la técnica {{ session.tecnica.tipo_tecnica }} +

+
+ +
+

+ Sesión Única +

+
+ +
+

+ {{ session.tecnica.instrucciones }} +

+
+
+ +
+ + + + + {% csrf_token %} + + +
+
+{% endblock %} + +{% block extra_js %} + +{% endblock %} \ No newline at end of file diff --git a/tecnicas/templates/tecnicas/forms_tester/cata.html b/tecnicas/templates/tecnicas/forms_tester/test_cata.html similarity index 100% rename from tecnicas/templates/tecnicas/forms_tester/cata.html rename to tecnicas/templates/tecnicas/forms_tester/test_cata.html diff --git a/tecnicas/templates/tecnicas/forms_tester/convencional.html b/tecnicas/templates/tecnicas/forms_tester/test_convencional.html similarity index 100% rename from tecnicas/templates/tecnicas/forms_tester/convencional.html rename to tecnicas/templates/tecnicas/forms_tester/test_convencional.html diff --git a/tecnicas/templates/tecnicas/forms_tester/test_sort.html b/tecnicas/templates/tecnicas/forms_tester/test_sort.html new file mode 100644 index 0000000000000000000000000000000000000000..88f499c966b25a24e7602b10899a299534e1b48a --- /dev/null +++ b/tecnicas/templates/tecnicas/forms_tester/test_sort.html @@ -0,0 +1,258 @@ +{% extends 'tecnicas/layouts/base.html' %} + +{% load static %} + +{% block title %}Convencional{% endblock %} + +{% block content %} +
+
+
+

+ Sesión usando
técnica + {{ session.tecnica.tipo_tecnica }} +

+ +
+ + + + + + {% if error %} + {% include "../components/error-message.html" with message=error %} + {% endif %} + +
+
+

+ {{ session.tecnica.instrucciones }} +

+
+ +
+

+ Agrupación de productos +

+
+ +
+
+

+ Repetición única +

+
+
+
+ + + + + + +
+ +

Productos en la sesión

+
+ {% for product in products %} +
+ {{ product.codigoProducto }} +
+ {% endfor %} +
+ +
+ + +

Puedes crear los grupos aquí

+ +
+
+

+ Arrastra aquí para borrar +

+
+ bote de basura +
+
+ +
+ +
+
+ + +
+ + {% if grups_products %} + {% for group in grups_products %} +
+
+ {% for product in group.productos.all %} +
+ {{ product.codigoProducto }} +
+ {% endfor %} +
+ +
+ + + + +
+ {% for word in group.palabras.all %} +
+ {{ word.nombre_palabra }} + +
+ {% endfor %} + +
+ +
+ + + +
+
+ {% endfor %} + + {% else %} +
+
+

+ Agrupación de productos +

+
+ +
+ + + + +
+

+ Lista de atributos +

+
+ +
+ + + +
+
+ {% endif %} + +
+
+ + + + + +
+ +
+ + + +
+ +
+
+ + {% include "../components/toast-container.html" %} +
+
+{% endblock %} + +{% block extra_js %} + + +{% endblock %} \ No newline at end of file diff --git a/tecnicas/templates/tecnicas/manage_sesions/detalles-sesion-cata.html b/tecnicas/templates/tecnicas/manage_sesions/details-session-cata.html similarity index 97% rename from tecnicas/templates/tecnicas/manage_sesions/detalles-sesion-cata.html rename to tecnicas/templates/tecnicas/manage_sesions/details-session-cata.html index f94ebdb4fbb33ac250d56529ad2949c7aba97c61..dc9e8a86af1b381640b1ca4e39882d983c4273b9 100644 --- a/tecnicas/templates/tecnicas/manage_sesions/detalles-sesion-cata.html +++ b/tecnicas/templates/tecnicas/manage_sesions/details-session-cata.html @@ -146,7 +146,7 @@

- Máximo número de repeticiones alcanzado + Sesión finalizada

{% else %} @@ -218,9 +218,9 @@

{% if existen_calificaciones %} - {% include "../components/table_cata.html" with calificaciones=calificaciones palabras=palabras sesion=sesion %} + {% include "../components/table_cata.html" with calificaciones=calificaciones palabras=palabras sesion=sesion %} {% else %} - {% include "../components/error-message.html" with message='Sin calificaciones que mostrar aún' %} + {% include "../components/error-message.html" with message='Sin calificaciones que mostrar aún' %} {% endif %} diff --git a/tecnicas/templates/tecnicas/manage_sesions/details-session-sort.html b/tecnicas/templates/tecnicas/manage_sesions/details-session-sort.html new file mode 100644 index 0000000000000000000000000000000000000000..ee1beaf40b7cc3473b79154aa9d40ee9f1c5ec7e --- /dev/null +++ b/tecnicas/templates/tecnicas/manage_sesions/details-session-sort.html @@ -0,0 +1,206 @@ +{% extends 'tecnicas/layouts/base.html' %} +{% load static %} + +{% block title %}Detalles Sesion{% endblock %} + +{% block content %} +
+
+
+

+ Detalles de la sesión +

+ + + +
+ + {% if message %} + {% include "../components/error-message.html" with message=message %} + {% endif %} + {% if error %} + {% include "../components/error-message.html" with message=error %} + {% endif %} + +

+ Información general +

+
+
+

+ Código: +

+

+ {{ sesion.codigo_sesion }} +

+
+ +
+

+ Nombre: +

+

+ {% if sesion.nombre_sesion %} + {{ sesion.nombre_sesion }} + {% else %} + Sin nombre + {% endif %} +

+
+ +
+

+ Fecha creación: +

+

+ {{ sesion.fechaCreacion }} +

+
+ +
+

+ Estado: +

+

+ {{ status }} +

+
+ +
+

+ Técnica: +

+

+ {{ technique.tipo_tecnica }} +

+
+ +
+

+ Catadores Max. {{ technique.limite_catadores }} +

+
+ +
+

+ Repetición: Única +

+
+ +
+
+ +
+

+ Instrucciones: +

+

+ {{ sesion.tecnica.instrucciones }} +

+
+
+ +

+ Acciones disponibles +

+
+ {% if finished %} +
+

+ Sesión finalizada +

+
+ {% else %} + {% if not sesion.activo %} + + {% else %} + + + + {% endif %} + {% endif %} + +
+ + + +

+ Datos obtenidos +

+ + {% if there_data %} + {% include "../components/table-sort.html" with data_groups=data_groups sesion=sesion %} + {% else %} + {% include "../components/error-message.html" with message='Sin datos por mostrar aún' %} + {% endif %} + + + + {% csrf_token %} + +
+
+{% endblock %} + +{% block extra_js %} + + +{% endblock %} \ No newline at end of file diff --git a/tecnicas/templates/tecnicas/manage_sesions/detalles-sesion.html b/tecnicas/templates/tecnicas/manage_sesions/details-session.html similarity index 100% rename from tecnicas/templates/tecnicas/manage_sesions/detalles-sesion.html rename to tecnicas/templates/tecnicas/manage_sesions/details-session.html diff --git a/tecnicas/templates/tecnicas/manage_sesions/monitor-session-sort.html b/tecnicas/templates/tecnicas/manage_sesions/monitor-session-sort.html new file mode 100644 index 0000000000000000000000000000000000000000..30c9234ba447f03a643deb32056ee760c1bfc6d8 --- /dev/null +++ b/tecnicas/templates/tecnicas/manage_sesions/monitor-session-sort.html @@ -0,0 +1,126 @@ +{% extends 'tecnicas/layouts/base.html' %} +{% load static %} + +{% block title %}Monitoreo{% endblock %} + +{% block content %} +
+
+
+

Sesión sensorial en curso

+
+ +
+

+ Código de sesión:
+ {{ code_session }} +

+
+ + + + +
+
+ + + + {% csrf_token %} + + + {% if error %} + {% include "../components/error-message.html" with message=error %} + {% endif %} + + {% if message %} + {% include "../components/error-message.html" with message=message %} + {% endif %} + +
+
+ +

+ Catadores activos +

+
+ +
+
+

Participantes

+
+
+
+ Máximo: + {{ max_testers }} +
+
+ + Actuales: + + {{ current_testers }} +
+
+ Activos: + {{ active_testers }} +
+
+
+ +
+
+
+
Usuario
+
Nombre
+
Estado
+
Finalizado
+
+ +
    + {% for parti in participations %} +
  • +

    {{ parti.catador.user.username }}

    +

    + {{ parti.catador.user.first_name }} + {{ parti.catador.user.last_name}} +

    + + {% if parti.activo %} +

    Activo

    + {% else %} +

    No activo

    + {% endif %} + + {% if parti.finalizado %} +

    Si

    + {% else %} +

    No

    + {% endif %} +
  • + {% endfor %} +
+
+
+
+
+
+{% endblock %} + +{% block extra_js %} + + +{% endblock %} \ No newline at end of file diff --git a/tecnicas/templates/tecnicas/manage_sesions/sesiones-panel.html b/tecnicas/templates/tecnicas/manage_sesions/sessions-panel.html similarity index 100% rename from tecnicas/templates/tecnicas/manage_sesions/sesiones-panel.html rename to tecnicas/templates/tecnicas/manage_sesions/sessions-panel.html diff --git a/tecnicas/templates/tecnicas/manage_tester/catador-crear.html b/tecnicas/templates/tecnicas/manage_tester/tester-create.html similarity index 100% rename from tecnicas/templates/tecnicas/manage_tester/catador-crear.html rename to tecnicas/templates/tecnicas/manage_tester/tester-create.html diff --git a/tecnicas/templates/tecnicas/manage_tester/catador-lista.html b/tecnicas/templates/tecnicas/manage_tester/tester-list.html similarity index 100% rename from tecnicas/templates/tecnicas/manage_tester/catador-lista.html rename to tecnicas/templates/tecnicas/manage_tester/tester-list.html diff --git a/tecnicas/templates/tecnicas/manage_tester/catador-buscar.html b/tecnicas/templates/tecnicas/manage_tester/tester-search.html similarity index 100% rename from tecnicas/templates/tecnicas/manage_tester/catador-buscar.html rename to tecnicas/templates/tecnicas/manage_tester/tester-search.html diff --git a/tecnicas/templates/tecnicas/manage_tester/catadores-panel.html b/tecnicas/templates/tecnicas/manage_tester/testers-panel.html similarity index 100% rename from tecnicas/templates/tecnicas/manage_tester/catadores-panel.html rename to tecnicas/templates/tecnicas/manage_tester/testers-panel.html diff --git a/tecnicas/urls.py b/tecnicas/urls.py index 78f3fab51621732666ea982261957018c9ebf555..8b5ca07464f9f045931499e3547ff1e670dd6cb8 100644 --- a/tecnicas/urls.py +++ b/tecnicas/urls.py @@ -118,6 +118,10 @@ urlpatterns = [ views.pfTest, name="session_pf"), + path("testers/init-session//sort", + views.sortTest, + name="session_sort"), + # APIs path("presenter/api/nueva-etiqueta", @@ -143,4 +147,8 @@ urlpatterns = [ path("testers/api/ratingword/pf/list", views.apiListWordsPF, name="api_rating_word_pf_list"), + + path("testers/api/rating-sort", + views.ratingSort, + name="api_rating_sort"), ] diff --git a/tecnicas/views/__init__.py b/tecnicas/views/__init__.py index 660f5bf04f4726cf125372a4010482e1bb03ba40..d19e9157498291cf3d80ac1d9e04fe9452f10512 100644 --- a/tecnicas/views/__init__.py +++ b/tecnicas/views/__init__.py @@ -28,6 +28,7 @@ from .apis.api_words import wordsVocabulary from .apis.api_list_words_pf import apiListWordsPF from .apis.rating_word_scales import ratingWordScales from .apis.rating_word_cata import ratingWordCata +from .apis.rating_sort import ratingSort from .tester_forms.init_tester_form import initTesterForm from .tester_forms.panel_main_tester import mainPanelTester @@ -36,3 +37,4 @@ from .tester_forms.sessions_list_tester import sessionsListTester from .tester_forms.convencional_scales import convencionalScales from .tester_forms.cata_test import cataTest from .tester_forms.pf_test import pfTest +from .tester_forms.sort_test import sortTest diff --git a/tecnicas/views/apis/rating_sort.py b/tecnicas/views/apis/rating_sort.py new file mode 100644 index 0000000000000000000000000000000000000000..ff6cd36718a52cf8a2569142e9ca70ae4f48fbb8 --- /dev/null +++ b/tecnicas/views/apis/rating_sort.py @@ -0,0 +1,16 @@ +from django.http import HttpRequest, JsonResponse +from tecnicas.controllers import RatingSortController +import json + + +def ratingSort(req: HttpRequest): + if req.method == "POST": + try: + data = json.loads(req.body.decode("utf-8")) + response = RatingSortController.saveRating( + request=req, data=data) + return response + except Exception as e: + return JsonResponse({"error": "Error al procesar datos"}) + else: + return JsonResponse({"error": "Método no permitido"}) diff --git a/tecnicas/views/sessions_config/configuration_panel_basic.py b/tecnicas/views/sessions_config/configuration_panel_basic.py index 69c5bad2e5fc612fdb0a523ddff39a5b302ddb87..fc0f9f9632e3534d9a0bbe895cd94de11a98792c 100644 --- a/tecnicas/views/sessions_config/configuration_panel_basic.py +++ b/tecnicas/views/sessions_config/configuration_panel_basic.py @@ -19,6 +19,10 @@ def configurationPanelBasic(req: HttpRequest): response = PanelBasicController.controllGetCATA(request=req) elif name_tecnica == "perfil flash": response = PanelBasicController.controllGetPF(request=req) + elif name_tecnica == "sort": + response = PanelBasicController.controllGetSort(request=req) + elif name_tecnica == "napping": + response = PanelBasicController.controllGetNapping(request=req) else: response = redirect( reverse("cata_system:seleccion_tecnica") + "?error=Técnica no valida o sin implementar") @@ -39,6 +43,12 @@ def configurationPanelBasic(req: HttpRequest): elif name_tecnica == "perfil flash": response = PanelBasicController.controllPostPF( request=req, name_tecnica=name_tecnica) + elif name_tecnica == "sort": + response = PanelBasicController.controllPostSort( + request=req, name_tecnica=name_tecnica) + elif name_tecnica == "napping": + response = PanelBasicController.controllPostNapping( + request=req, name_tecnica=name_tecnica) else: response = redirect( reverse("cata_system:seleccion_tecnica") + "?error=¡Oh, vaya! Cambio de técnica repentino, vuelve a elegir otra vez") diff --git a/tecnicas/views/sessions_config/configuration_panel_codes.py b/tecnicas/views/sessions_config/configuration_panel_codes.py index fca27f0d71ca742ddad768ada6b5a05189a1011a..d68d10e94ee79a90ea35b5a1886c453183db5db0 100644 --- a/tecnicas/views/sessions_config/configuration_panel_codes.py +++ b/tecnicas/views/sessions_config/configuration_panel_codes.py @@ -18,8 +18,8 @@ def configurationPanelCodes(req: HttpRequest): if name_technique == "escalas": response = PanelCodesController.controllGetEscalas( req, data_basic) - elif name_technique == "rata" or name_technique == "cata" or "perfil flash": - response = PanelCodesController.controllGetRATA( + elif name_technique in ["rata", "cata", "perfil flash", "sort", "napping"]: + response = PanelCodesController.controllGetWithoutOrders( request=req, data=data_basic, name_technique=name_technique) else: response = redirect( @@ -30,14 +30,12 @@ def configurationPanelCodes(req: HttpRequest): if name_technique == "escalas": response = PanelCodesController.controllPostEscalas( req, data_basic) - elif name_technique == "rata": - response = PanelCodesController.controllPostRATA(request=req) - elif name_technique == "cata": - response = PanelCodesController.controllPostRATA( - request=req, is_rata=False) - elif name_technique == "perfil flash": - response = PanelCodesController.controllPostPF( - request=req) + elif name_technique in ["rata", "cata"]: + response = PanelCodesController.controllPostWithWords( + request=req, name_technique=name_technique) + elif name_technique in ["perfil flash", "sort", "napping"]: + response = PanelCodesController.controllPostWithoutOrdersWords( + request=req, name_technique=name_technique) else: response = redirect( reverse("cata_system:seleccion_tecnica") + "?error=Técnica no valida") diff --git a/tecnicas/views/sessions_config/configuration_panel_words.py b/tecnicas/views/sessions_config/configuration_panel_words.py index 2898f6309b1e933d44e06d1980edc9a95cf6ce66..5f6d7c661f385ff56ef7838fe8b60801a38566e6 100644 --- a/tecnicas/views/sessions_config/configuration_panel_words.py +++ b/tecnicas/views/sessions_config/configuration_panel_words.py @@ -14,12 +14,10 @@ def configurationPanelWords(req: HttpRequest): basic_data = req.session["form_basic"] name_technique = basic_data["name_tecnica"] - style_words = EstiloPalabra.objects.get( - id=basic_data["estilo_palabras"]).nombre_estilo + style_words = basic_data["estilo_palabras"] if req.method == "GET": if name_technique == "escalas" or name_technique == "rata" or name_technique == "cata": - print() if style_words == "atributos": response = PanelWordsController.controllGetEscalasAtributes( req) diff --git a/tecnicas/views/sessions_config/create_session.py b/tecnicas/views/sessions_config/create_session.py index 4edb792de771ddd20ba6d0b6a5d891d686e4ee09..7e6fce964faf7f750f1505c8a9ffc6f00ee4f243 100644 --- a/tecnicas/views/sessions_config/create_session.py +++ b/tecnicas/views/sessions_config/create_session.py @@ -1,7 +1,7 @@ from django.http import HttpRequest, JsonResponse from django.shortcuts import render, redirect from django.urls import reverse -from tecnicas.controllers import PanelCreateController +from tecnicas.controllers import PanelCreateEscalasController, PanelCreateRataController, PanelCreateCataController, PanelCreatePFController, PanelCreateSortController, PanelCreateNappingController from tecnicas.utils import deleteDataSession @@ -15,8 +15,18 @@ def createSession(req: HttpRequest): name_technique = basic_data["name_tecnica"] if req.method == "GET": - if name_technique == "escalas" or name_technique == "rata" or name_technique == "cata" or name_technique == "perfil flash": - response = PanelCreateController.controllGetEscalas(req) + if name_technique == "escalas": + response = PanelCreateEscalasController.controllGet(req) + elif name_technique == "rata": + response = PanelCreateRataController.controllGet(req) + elif name_technique == "cata": + response = PanelCreateCataController.controllGet(req) + elif name_technique == "perfil flash": + response = PanelCreatePFController.controllGet(req) + elif name_technique == "sort": + response = PanelCreateSortController.controllGet(req) + elif name_technique == "napping": + response = PanelCreateNappingController.controllGet(req) else: response = redirect( reverse("cata_system:seleccion_tecnica") + "?error=Técnica no valida") @@ -24,13 +34,17 @@ def createSession(req: HttpRequest): return response if req.method == "POST": if name_technique == "escalas": - response = PanelCreateController.controllPostEscalas(req) + response = PanelCreateEscalasController.controllPost(req) elif name_technique == "rata": - response = PanelCreateController.controllPostRATA(req) + response = PanelCreateRataController.controllPost(req) elif name_technique == "cata": - response = PanelCreateController.controllPostCATA(req) + response = PanelCreateCataController.controllPost(req) elif name_technique == "perfil flash": - response = PanelCreateController.controllPostPF(req) + response = PanelCreatePFController.controllPost(req) + elif name_technique == "sort": + response = PanelCreateSortController.controllPost(req) + elif name_technique == "napping": + response = PanelCreateNappingController.controllPost(req) else: response = redirect( reverse("cata_system:seleccion_tecnica") + "?error=Técnica no valida") diff --git a/tecnicas/views/sessions_config/seleccion_tecnica.py b/tecnicas/views/sessions_config/seleccion_tecnica.py index 3ddd04b309b1be527b98e6e2fee7f9ffebf93dce..e8f09605613f02ef029567e1f95433a3c25467e9 100644 --- a/tecnicas/views/sessions_config/seleccion_tecnica.py +++ b/tecnicas/views/sessions_config/seleccion_tecnica.py @@ -9,6 +9,6 @@ def selecionTecnica(req:HttpRequest): error = error.replace("_", " ") error = error.capitalize() - return render(req, "tecnicas/create_sesion/seleccion-tecnica.html", context={"tipos":tipos, "error":error}) + return render(req, "tecnicas/create_sesion/select-tecnica.html", context={"tipos":tipos, "error":error}) except KeyError: - return render(req, "tecnicas/create_sesion/seleccion-tecnica.html", context={"tipos":tipos}) \ No newline at end of file + return render(req, "tecnicas/create_sesion/select-tecnica.html", context={"tipos":tipos}) \ No newline at end of file diff --git a/tecnicas/views/sessions_management/session_details.py b/tecnicas/views/sessions_management/session_details.py index b0e1bdc72a1641987b9b62b0850157cedc60375f..e4432d5c8c6e06f9907a665829a6258a9e538c08 100644 --- a/tecnicas/views/sessions_management/session_details.py +++ b/tecnicas/views/sessions_management/session_details.py @@ -3,7 +3,7 @@ from django.shortcuts import redirect from django.urls import reverse from tecnicas.models import SesionSensorial from tecnicas.utils import noValidTechnique -from tecnicas.controllers import DetallesEscalasController, DetallesCATAController, DetallesPFController +from tecnicas.controllers import DetallesController, DetallesEscalasController, DetallesCATAController, DetallesPFController, DetallesSortController def sessionDetails(req: HttpRequest, session_code: str): @@ -13,8 +13,12 @@ def sessionDetails(req: HttpRequest, session_code: str): else: message = "" - sensorial_session = SesionSensorial.objects.get( - codigo_sesion=session_code) + try: + sensorial_session = SesionSensorial.objects.get( + codigo_sesion=session_code) + except SesionSensorial.DoesNotExist: + return noValidTechnique(params={"page": 1}, query_params={"message": "Sesión no encontrada"}, name_view="cata_system:panel_sesiones") + use_techinique = sensorial_session.tecnica.tipo_tecnica.nombre_tecnica if use_techinique == "escalas" or use_techinique == "rata": @@ -34,6 +38,11 @@ def sessionDetails(req: HttpRequest, session_code: str): response = controller_view.controllGetResponse( request=req, message=message) + elif use_techinique == "sort": + controller_view = DetallesSortController(session=sensorial_session) + response = controller_view.controllGetResponse( + request=req, message=message) + else: response = noValidTechnique( params={"page": 1}, @@ -47,28 +56,13 @@ def sessionDetails(req: HttpRequest, session_code: str): elif req.method == "POST": sensorial_session = SesionSensorial.objects.get( codigo_sesion=session_code) - use_techinique = sensorial_session.tecnica.tipo_tecnica.nombre_tecnica - - if use_techinique == "escalas" or use_techinique == "rata" or use_techinique == "cata": - controller_view = DetallesEscalasController(sensorial_session) - - if req.POST["action"] == "start_session": - response = controller_view.startRepetition( - presenter=req.user.user_presentador, request=req) - elif req.POST.get("action") == "delete_session": - controller_view.deleteSesorialSession() - response = redirect( - reverse("cata_system:panel_sesiones", kwargs={"page": 1})) - - else: - response = controller_view.controllGetResponse( - error="No se reconoce la acción a realizar") + use_techinique = sensorial_session.tecnica.tipo_tecnica.nombre_tecnica - elif use_techinique == "perfil flash": - controller_view = DetallesPFController(session=sensorial_session) + controller_view = DetallesController(sensorial_session) - if req.POST["action"] == "start_session": + if use_techinique in ["escalas", "rata", "cata", "perfil flash", "sort"]: + if req.POST.get("action") == "start_session": response = controller_view.startRepetition( presenter=req.user.user_presentador, request=req) @@ -77,12 +71,9 @@ def sessionDetails(req: HttpRequest, session_code: str): response = redirect( reverse("cata_system:panel_sesiones", kwargs={"page": 1})) - else: - response = controller_view.controllGetResponse( - error="No se reconoce la acción a realizar") - else: - response = noValidTechnique() + response = controller_view.controllGetResponse( + error="No se reconoce la acción a realizar") return response else: diff --git a/tecnicas/views/sessions_management/session_monitor.py b/tecnicas/views/sessions_management/session_monitor.py index 81dd3f1822c959247eacdfbcec0259d7ec863524..94f68ae4fe3175002b5efa2d1623f92b1d6a08ce 100644 --- a/tecnicas/views/sessions_management/session_monitor.py +++ b/tecnicas/views/sessions_management/session_monitor.py @@ -7,7 +7,7 @@ from django.http import HttpRequest, JsonResponse from django.shortcuts import render, redirect from django.urls import reverse from tecnicas.models import SesionSensorial -from tecnicas.controllers import MonitorEscalasController, MonitorRATAController, MonitorPFController +from tecnicas.controllers import MonitorEscalasController, MonitorRATAController, MonitorPFController, MonitorSortController from tecnicas.utils import noValidTechnique @@ -17,7 +17,7 @@ def sessionMonitor(req: HttpRequest, session_code: str): codigo_sesion=session_code) use_techinique = sensorial_session.tecnica.tipo_tecnica.nombre_tecnica - if use_techinique == "escalas" or use_techinique == "rata" or use_techinique == "cata": + if use_techinique in ["escalas", "rata", "cata"]: controll_view = MonitorEscalasController(sensorial_session) response = controll_view.controllGetResponse(request=req) @@ -25,6 +25,10 @@ def sessionMonitor(req: HttpRequest, session_code: str): controll_view = MonitorPFController(sensorial_session) response = controll_view.controllGetResponse(request=req) + elif use_techinique == "sort": + controll_view = MonitorSortController(sensorial_session) + response = controll_view.controllGetResponse(request=req) + else: response = noValidTechnique( params={ @@ -74,6 +78,17 @@ def sessionMonitor(req: HttpRequest, session_code: str): response = controll_view.controlGetResponse( request=req, error="No se ha definido la acción a realizar") + elif use_techinique == "sort": + controll_view = MonitorSortController(sensorial_session) + action = req.POST["action"] + + if action == "finish_session": + response = controll_view.controllPostFinishSession( + request=req) + else: + response = controll_view.controlGetResponse( + request=req, error="No se ha definido la acción a realizar") + else: response = noValidTechnique( params={ diff --git a/tecnicas/views/sessions_management/sessions_panel.py b/tecnicas/views/sessions_management/sessions_panel.py index c64ed878cf2cffd5bdbaf17bbbc6508995789330..690477e7763290161f7e430baa88a997f210fa12 100644 --- a/tecnicas/views/sessions_management/sessions_panel.py +++ b/tecnicas/views/sessions_management/sessions_panel.py @@ -12,7 +12,7 @@ def sesionsPanel(req: HttpRequest, page: int): if isinstance(response, dict): context["error"] = response["error"] - return render(req, "tecnicas/manage_sesions/sesiones-panel.html", context=context) + return render(req, "tecnicas/manage_sesions/sessions-panel.html", context=context) (sessions_in_page, is_last_page, current_page) = response @@ -22,6 +22,6 @@ def sesionsPanel(req: HttpRequest, page: int): if "message" in req.GET: context["message"] = req.GET.get("message") - return render(req, "tecnicas/manage_sesions/sesiones-panel.html", context=context) + return render(req, "tecnicas/manage_sesions/sessions-panel.html", context=context) else: return JsonResponse({"message": "Método no permitido"}) diff --git a/tecnicas/views/tester_forms/init_tester_form.py b/tecnicas/views/tester_forms/init_tester_form.py index b6c8563f9e2218d9a6b49e735620670112a61f1a..f9ceed4fbf87c8d122d14c301a67de759118ae0d 100644 --- a/tecnicas/views/tester_forms/init_tester_form.py +++ b/tecnicas/views/tester_forms/init_tester_form.py @@ -1,13 +1,13 @@ from django.http import HttpRequest, JsonResponse from django.shortcuts import render -from tecnicas.controllers import InitSessionEscalasController, InitSessionRATAController, InitSessionPFController +from tecnicas.controllers import InitSessionEscalasController, InitSessionRATAController, InitSessionPFController, InitSessionSortController from tecnicas.models import SesionSensorial def initTesterForm(req: HttpRequest, code_sesion: str): session = SesionSensorial.objects.get(codigo_sesion=code_sesion) type_technique = session.tecnica.tipo_tecnica.nombre_tecnica - template_url = "tecnicas/forms_tester/init_session.html" + template_url = "tecnicas/forms_tester/init_scales_test.html" if req.method == "GET": if type_technique == "escalas": @@ -25,6 +25,11 @@ def initTesterForm(req: HttpRequest, code_sesion: str): sensorial_session=session, user_tester=req.user.user_catador) response = view_controller.controllGet(request=req) + elif type_technique == "sort": + view_controller = InitSessionSortController( + sensorial_session=session, user_tester=req.user.user_catador) + response = view_controller.controllGet(request=req) + else: context = { "session": session, @@ -45,6 +50,12 @@ def initTesterForm(req: HttpRequest, code_sesion: str): view_controller = InitSessionPFController( sensorial_session=session, user_tester=req.user.user_catador) response = view_controller.controllPost(request=req) + + elif type_technique == "sort": + view_controller = InitSessionSortController( + sensorial_session=session, user_tester=req.user.user_catador) + response = view_controller.controllPost(request=req) + else: context = { "session": session, diff --git a/tecnicas/views/tester_forms/login_session.py b/tecnicas/views/tester_forms/login_session.py index c87e54687c521ba6b32e8ccf054620aa68e5e9e4..c566ebf2f6f9e198aaa7ff287fe52475be61e86d 100644 --- a/tecnicas/views/tester_forms/login_session.py +++ b/tecnicas/views/tester_forms/login_session.py @@ -35,6 +35,10 @@ def loginSessionTester(req: HttpRequest): elif type_technique == "perfil flash": response = login_controller.validateEntryRATA(request=req) + + elif type_technique == "sort": + response = login_controller.validateEntrySort(request=req) + else: context = { "error": "La técnica usada en esta sesión es invalida o no ha sido implementada para ingresar a ella" diff --git a/tecnicas/views/tester_forms/pf_test.py b/tecnicas/views/tester_forms/pf_test.py index 490844dafead3d1531ab6db34b4cde2e33e1c00e..32d6f762a4618e478f87285f2d7fe27c316722c9 100644 --- a/tecnicas/views/tester_forms/pf_test.py +++ b/tecnicas/views/tester_forms/pf_test.py @@ -12,8 +12,16 @@ def pfTest(req: HttpRequest, code_sesion: str): sensorial_session=session, user_tester=req.user.user_catador) return controll_view.controllGet(request=req) - if req.method == "POST": + elif req.method == "POST": session = SesionSensorial.objects.get(codigo_sesion=code_sesion) controll_view = TestPFController( sensorial_session=session, user_tester=req.user.user_catador) return controll_view.controllPost(request=req) + + else: + return noValidTechnique( + name_view="cata_system:catador_init_session", + query_params={ + "error": "Método no valido" + } + ) diff --git a/tecnicas/views/tester_forms/sort_test.py b/tecnicas/views/tester_forms/sort_test.py new file mode 100644 index 0000000000000000000000000000000000000000..3169302db67be6913e8376b28a0f7214cb889cc1 --- /dev/null +++ b/tecnicas/views/tester_forms/sort_test.py @@ -0,0 +1,26 @@ +from django.http import HttpRequest +from tecnicas.models import SesionSensorial +from tecnicas.controllers import TestSortController +from tecnicas.utils import noValidTechnique + + +def sortTest(req: HttpRequest, code_sesion: str): + if req.method == "GET": + session = SesionSensorial.objects.get(codigo_sesion=code_sesion) + controll_view = TestSortController( + sensorial_session=session, user_tester=req.user.user_catador) + return controll_view.controllGet(request=req) + + elif req.method == "POST": + session = SesionSensorial.objects.get(codigo_sesion=code_sesion) + controll_view = TestSortController( + sensorial_session=session, user_tester=req.user.user_catador) + return controll_view.controllPost(request=req) + + else: + return noValidTechnique( + name_view="cata_system:catador_init_session", + query_params={ + "error": "Método no valido" + } + ) diff --git a/tecnicas/views/tester_management/tester_create.py b/tecnicas/views/tester_management/tester_create.py index d5f61bdb86f0acd3325afc817187fe7cec45438d..9ae8e8cb2b347db2686c734222c31835b6ffd44f 100644 --- a/tecnicas/views/tester_management/tester_create.py +++ b/tecnicas/views/tester_management/tester_create.py @@ -8,6 +8,8 @@ from tecnicas.forms import CatadorForm def testerCreate(req: HttpRequest): + url_template = "tecnicas/manage_tester/tester-create.html" + if req.method == "GET": form_tester = CatadorForm() @@ -15,7 +17,7 @@ def testerCreate(req: HttpRequest): "form_cata": form_tester } - return render(req, "tecnicas/manage_tester/catador-crear.html", context) + return render(req, url_template, context) elif req.method == "POST": new_values = {} @@ -51,10 +53,10 @@ def testerCreate(req: HttpRequest): ) except (ValidationError, DatabaseError): context["error"] = "nombre de usuario en uso" - return render(req, "tecnicas/manage_tester/catador-crear.html", context) + return render(req, url_template, context) context["message"] = "Datos guardados, consúltelo en Listar Catadores" context["form_cata"] = CatadorForm() - return render(req, "tecnicas/manage_tester/catador-crear.html", context) + return render(req, url_template, context) else: context["error"] = "Datos no validos" - return render(req, "tecnicas/manage_tester/catador-crear.html", context) + return render(req, url_template, context) diff --git a/tecnicas/views/tester_management/tester_list.py b/tecnicas/views/tester_management/tester_list.py index a7be62c98b2e7bbff70a98e5d8b8b9a7a7d34812..c16b527a9683541a68fc2e55547d596880c791e4 100644 --- a/tecnicas/views/tester_management/tester_list.py +++ b/tecnicas/views/tester_management/tester_list.py @@ -8,6 +8,6 @@ def testerList(req: HttpRequest, num_page: int): if req.method == "GET": view_controller = TesterListController(page=num_page) view_context = view_controller.getContext() - return render(req, "tecnicas/manage_tester/catador-lista.html", view_context) + return render(req, "tecnicas/manage_tester/tester-list.html", view_context) else: return general_error("Método no permitido") diff --git a/tecnicas/views/tester_management/tester_menu.py b/tecnicas/views/tester_management/tester_menu.py index c36f677119d7a2ec19304d4a00e73266a0b189cc..a86adc059155e7c116d88d266b45427694fe4e28 100644 --- a/tecnicas/views/tester_management/tester_menu.py +++ b/tecnicas/views/tester_management/tester_menu.py @@ -1,4 +1,4 @@ from django.shortcuts import render def testerMenu(req): - return render(req, "tecnicas/manage_tester/catadores-panel.html") \ No newline at end of file + return render(req, "tecnicas/manage_tester/testers-panel.html") \ No newline at end of file diff --git a/tecnicas/views/tester_management/tester_search.py b/tecnicas/views/tester_management/tester_search.py index 9305fda489f064c9c928cfc1c4f0f0b3721e2f1c..d55dcaab5004767a58ad256fd85c339145e0b5f6 100644 --- a/tecnicas/views/tester_management/tester_search.py +++ b/tecnicas/views/tester_management/tester_search.py @@ -8,13 +8,14 @@ from tecnicas.models import Catador def testerSearch(req: HttpRequest): + url_template = "tecnicas/manage_tester/tester-search.html" if req.method == "GET": context = {} if "user" in req.GET: username = req.GET["user"] else: - return render(req, "tecnicas/manage_tester/catador-buscar.html") + return render(req, url_template) try: tester = Catador.objects.get(user__username=username) @@ -30,7 +31,7 @@ def testerSearch(req: HttpRequest): except Catador.DoesNotExist: context["error"] = "usuario no encontrado" - return render(req, "tecnicas/manage_tester/catador-buscar.html", context) + return render(req, url_template, context) elif req.method == "POST": context = {} @@ -63,10 +64,10 @@ def testerSearch(req: HttpRequest): tester.save() except (ValidationError, DatabaseError): context["error"] = "nombre de usuario en uso" - return render(req, "tecnicas/manage_tester/catador-crear.html", context) + return render(req, url_template, context) context["message"] = "Datos actualizados, consúltelo en Listar Catadores" context["form_cata"] = form_tester - return render(req, "tecnicas/manage_tester/catador-crear.html", context) + return render(req, url_template, context) else: context["error"] = "Datos no validos" - return render(req, "tecnicas/manage_tester/catador-crear.html", context) + return render(req, url_template, context)
Repetición