chartManD commited on
Commit
efaa8a7
·
1 Parent(s): 7189a9b

Se crea formulario para productos y orden

Browse files
tecnicas/forms/__init__.py CHANGED
@@ -1,3 +1,4 @@
1
- from .sesion_basic import SesionBasicForm
2
- from .sesion_tags import SesionTagsForm
3
- from .etiqueta import EtiquetaForm
 
 
1
+ from .sesion_basic_form import SesionBasicForm
2
+ from .sesion_tags_form import SesionTagsForm
3
+ from .etiqueta_form import EtiquetaForm
4
+ from .palabras_form import PalabrasForm
tecnicas/forms/{etiqueta.py → etiqueta_form.py} RENAMED
File without changes
tecnicas/forms/palabras_form.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ from django import forms
2
+
3
+ class PalabrasForm(forms.Form):
4
+ def __init__(self, *args, codes = [], **kwargs):
5
+ super().__init__(*args, **kwargs)
6
+
7
+ for index, code in enumerate(codes):
8
+ self.fields[f'producto_{index+1}'] = forms.CharField(max_length=3, required=True, min_length=3, initial=code, label=f"codigo {index+1}", widget=forms.TextInput(attrs={
9
+ "class": "ct-palabra bg-gray-300 p-1 border-b-1 text-center w-full disabled:bg-gray-500 uppercase"
10
+ }))
tecnicas/forms/{sesion_basic.py → sesion_basic_form.py} RENAMED
File without changes
tecnicas/forms/{sesion_tags.py → sesion_tags_form.py} RENAMED
@@ -1,6 +1,4 @@
1
  from django import forms
2
- from django.shortcuts import redirect
3
- from django.urls import reverse
4
 
5
  from ..models import Etiqueta
6
 
@@ -10,7 +8,7 @@ class SesionTagsForm(forms.Form):
10
 
11
  if tipo_escala == "estructurada":
12
  for i in range(longitud):
13
- self.fields[f'segmento_{i}'] = forms.ModelChoiceField(queryset=Etiqueta.objects.all(), required=True,label=f"segmento {i+1}", empty_label="Selecione opcion", widget=forms.Select(attrs={
14
  "class":"ct-select-op p-1 rounded bg-gray-200 [*]:capitalize"
15
  }))
16
  else:
 
1
  from django import forms
 
 
2
 
3
  from ..models import Etiqueta
4
 
 
8
 
9
  if tipo_escala == "estructurada":
10
  for i in range(longitud):
11
+ self.fields[f'segmento_{i}'] = forms.ModelChoiceField(queryset=Etiqueta.objects.all(), required=True, label=f"segmento {i+1}", empty_label="Selecione opcion", widget=forms.Select(attrs={
12
  "class":"ct-select-op p-1 rounded bg-gray-200 [*]:capitalize"
13
  }))
14
  else:
tecnicas/migrations/0009_alter_orden_id_catador_and_more.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 5.2.1 on 2025-08-01 21:27
2
+
3
+ import django.db.models.deletion
4
+ import shortuuid.main
5
+ from django.db import migrations, models
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ dependencies = [
11
+ ('tecnicas', '0008_alter_etiqueta_valor_etiqueta_and_more'),
12
+ ]
13
+
14
+ operations = [
15
+ migrations.AlterField(
16
+ model_name='orden',
17
+ name='id_catador',
18
+ field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='orden_catador', to='tecnicas.catador'),
19
+ ),
20
+ migrations.AlterField(
21
+ model_name='sesionsensorial',
22
+ name='codigo_sesion',
23
+ field=models.CharField(default=shortuuid.main.ShortUUID.uuid, editable=False, max_length=22, primary_key=True, serialize=False),
24
+ ),
25
+ ]
tecnicas/models/orden.py CHANGED
@@ -6,7 +6,7 @@ from .producto import Producto
6
 
7
  class Orden(models.Model):
8
  id_tecnica = models.ForeignKey(Tecnica, on_delete=models.CASCADE, related_name="orden_tecnica")
9
- id_catador = models.ForeignKey(Catador, on_delete=models.CASCADE, related_name="orden_catador")
10
 
11
  class Posicion(models.Model):
12
  id_producto = models.ForeignKey(Producto, on_delete=models.CASCADE, related_name="posicion_producto")
 
6
 
7
  class Orden(models.Model):
8
  id_tecnica = models.ForeignKey(Tecnica, on_delete=models.CASCADE, related_name="orden_tecnica")
9
+ id_catador = models.ForeignKey(Catador, on_delete=models.CASCADE, related_name="orden_catador", null=True)
10
 
11
  class Posicion(models.Model):
12
  id_producto = models.ForeignKey(Producto, on_delete=models.CASCADE, related_name="posicion_producto")
tecnicas/static/js/panel-words.js ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ let inWords = document
2
+ .getElementsByClassName("ct-palabras-form")[0]
3
+ .getElementsByClassName("ct-palabra");
4
+ let codes = [];
5
+ let numCata = document.getElementsByClassName("ct-num-cata")[0].value;
6
+
7
+ let sortData;
8
+
9
+ initIU();
10
+
11
+ function submitData(e) {
12
+ const codesInput = document.createElement("input");
13
+ codesInput.type = "hidden";
14
+ codesInput.name = "sort_codes";
15
+ codesInput.value = JSON.stringify(sortData);
16
+ this.appendChild(codesInput);
17
+ }
18
+
19
+ function initIU() {
20
+ setCodes();
21
+ definePermutations();
22
+ addIUPermutations();
23
+
24
+ const formWords = document.getElementsByClassName("ct-palabras-form")[0];
25
+ formWords.addEventListener("submit", submitData);
26
+ }
27
+
28
+ function setCodes() {
29
+ if (codes) {
30
+ codes = [];
31
+ }
32
+ for (let i = 0; i < inWords.length; i++) {
33
+ codes.push(inWords.item(i).value.toUpperCase());
34
+ }
35
+ }
36
+
37
+ function setPermutations() {
38
+ definePermutations();
39
+ addIUPermutations();
40
+ }
41
+
42
+ function definePermutations() {
43
+ setCodes();
44
+ const permutations = generatePermutations(codes);
45
+ const newPer = shuffle(permutations);
46
+
47
+ const usePermutations = [];
48
+ let index = 0;
49
+
50
+ while (true) {
51
+ if (usePermutations.length == numCata) {
52
+ break;
53
+ } else if (index < newPer.length) {
54
+ usePermutations.push(newPer[index]);
55
+ index++;
56
+ } else if (index >= newPer.length) {
57
+ index = 0;
58
+ }
59
+ }
60
+
61
+ const permutationsSort = [];
62
+
63
+ usePermutations.forEach((permutation) => {
64
+ let newValue = [];
65
+ let index = 1;
66
+
67
+ permutation.forEach((cod) => {
68
+ newValue.push({
69
+ code: cod,
70
+ position: index,
71
+ });
72
+
73
+ index++;
74
+ });
75
+
76
+ permutationsSort.push(newValue);
77
+ });
78
+
79
+ sortData = permutationsSort.slice();
80
+ }
81
+
82
+ function generatePermutations(objetos) {
83
+ var result = [];
84
+
85
+ var backtrack = (index, objetos) => {
86
+ if (index === objetos.length) {
87
+ result.push(objetos.slice());
88
+ return;
89
+ }
90
+
91
+ for (let j = index; j < objetos.length; j++) {
92
+ [objetos[index], objetos[j]] = [objetos[j], objetos[index]];
93
+ backtrack(index + 1, objetos);
94
+ [objetos[index], objetos[j]] = [objetos[j], objetos[index]];
95
+ }
96
+ };
97
+
98
+ backtrack(0, objetos);
99
+ return result;
100
+ }
101
+
102
+ function shuffle(arr) {
103
+ const arrSuffle = arr.slice();
104
+
105
+ for (let i = arrSuffle.length - 1; i > 0; i--) {
106
+ const j = Math.floor(Math.random() * (i + 1));
107
+ [arrSuffle[i], arrSuffle[j]] = [arrSuffle[j], arrSuffle[i]];
108
+ }
109
+
110
+ return arrSuffle;
111
+ }
112
+
113
+ function addIUPermutations() {
114
+ const container = document.getElementsByClassName("ct-orden-list")[0];
115
+ const itemsChild = [];
116
+ container.replaceChildren();
117
+
118
+ let index = 1;
119
+
120
+ sortData.forEach((permuta) => {
121
+ const paragraph = document.createElement("p");
122
+ paragraph.classList.add("px-3", "font-bold", "text-xl", "text-black");
123
+ paragraph.textContent = `orden ${index}`;
124
+
125
+ const unlist = document.createElement("ul");
126
+ unlist.classList.add(
127
+ "flex",
128
+ "flex-wrap",
129
+ "gap-3",
130
+ "px-3",
131
+ "py-1",
132
+ "text-white"
133
+ );
134
+
135
+ permuta.forEach((obj) => {
136
+ const itemList = document.createElement("li");
137
+ itemList.classList.add(
138
+ "px-2",
139
+ "bg-gray-600",
140
+ "font-bold",
141
+ "tracking-wide"
142
+ );
143
+ itemList.textContent = `${obj.position}: ${obj.code}`;
144
+ unlist.appendChild(itemList);
145
+ });
146
+
147
+ const section = document.createElement("section");
148
+ section.classList.add("bg-gray-400", "py-2");
149
+
150
+ section.appendChild(paragraph);
151
+ section.appendChild(unlist);
152
+
153
+ container.appendChild(section);
154
+ index++;
155
+ });
156
+ }
tecnicas/templates/tecnicas/configuracion-panel-palabras.html CHANGED
@@ -1,4 +1,5 @@
1
  {% extends 'tecnicas/base.html' %}
 
2
 
3
  {% block title %}Panel Configuracion{% endblock %}
4
 
@@ -6,6 +7,49 @@
6
  <article class="w-full flex flex-col justify-center items-center bg-gray-600 my-10">
7
  <article class="flex flex-col gap-4 bg-gray-400 md:p-10 p-5 rounded-2xl lg:w-4xl w-full">
8
  <h1 class="text-center font-bold text-4xl">Panel de configuración</h1>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  </article>
10
  </article>
 
 
 
 
11
  {% endblock %}
 
1
  {% extends 'tecnicas/base.html' %}
2
+ {% load static %}
3
 
4
  {% block title %}Panel Configuracion{% endblock %}
5
 
 
7
  <article class="w-full flex flex-col justify-center items-center bg-gray-600 my-10">
8
  <article class="flex flex-col gap-4 bg-gray-400 md:p-10 p-5 rounded-2xl lg:w-4xl w-full">
9
  <h1 class="text-center font-bold text-4xl">Panel de configuración</h1>
10
+ {% if error %}
11
+ <p class="text-2xl">{{ error }}</p>
12
+ {% endif %}
13
+ <form method="post" action="" class="ct-palabras-form flex flex-col gap-5">
14
+ {% csrf_token %}
15
+ <h2 class="text-2xl mb-2 font-bold">Codificar productos</h2>
16
+ <article class="flex flex-row flex-wrap gap-4 items-center justify-center">
17
+ <p class="text-center font-bold tracking-wide text-xl bg-gray-500 text-white px-3 py-3 pb-4 rounded">
18
+ Puede dejar los campos como están para usar los códigos predefinidos.
19
+ </p>
20
+ {% for field in form_worlds %}
21
+ <label for="{{ field.id_for_label }}"
22
+ class="text-lg flex flex-col items-center px-2 font-medium tracking-wide">
23
+ <p class="tracking-normal capitalize text-base font-bold">{{ field.label }}</p>
24
+ {{ field }}
25
+ </label>
26
+ {% endfor %}
27
+ </article>
28
+ <article class="flex justify-center gap-5">
29
+ <button type="button"
30
+ class="ct-gen-or text-lg tracking-wider font-medium p-2 px-4 border-b-2 active:border-b-0 active:border-t-2 active:border-yellow-500 border-yellow-800 transition-all rounded-xl bg-yellow-500 text-white w-fit capitalize"
31
+ onclick="setPermutations()">
32
+ regenerar ordenes
33
+ </button>
34
+ </article>
35
+ <article>
36
+ <h2 class="text-2xl mb-2 font-bold">Ordenes</h2>
37
+ <section class="flex justify-center">
38
+ <article
39
+ class="ct-orden-list flex flex-wrap px-3 py-4 justify-center items-center capitalize text-lg bg-gray-500 gap-5 w-fit">
40
+ </article>
41
+ </section>
42
+ </article>
43
+ <article class="flex justify-center items-center py-3 rounded">
44
+ <button type="submit"
45
+ class="ct-btn-submit uppercase text-lg tracking-wider font-medium p-2 px-4 border-b-2 active:border-b-0 active:border-t-2 active:border-yellow-500 border-yellow-800 transition-all rounded-xl bg-yellow-500 text-white w-fit disabled:bg-amber-600">Continuar</button>
46
+ </article>
47
+ </form>
48
+ <input type="number" value="{{ num_cata }}" class="ct-num-cata hidden" disabled>
49
  </article>
50
  </article>
51
+ {% endblock %}
52
+
53
+ {% block extra_js %}
54
+ <script src="{% static 'js/panel-words.js' %}"></script>
55
  {% endblock %}
tecnicas/utils/__init__.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ from .code_generate import generarCodigo
2
+ from .code_generate import generarCodigos
tecnicas/utils/code_generate.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import string
2
+ import random
3
+
4
+ def generarCodigo():
5
+ caracteres = string.ascii_letters + string.digits
6
+ codigo = ''.join(random.choice(caracteres) for _ in range(3))
7
+ codigo = codigo.upper()
8
+ return codigo
9
+
10
+ def generarCodigos(numCodes):
11
+ codes_products = []
12
+ for i in range(numCodes):
13
+ while True:
14
+ code = generarCodigo()
15
+ if not codes_products.__contains__(code):
16
+ codes_products.append(code)
17
+ break
18
+
19
+ return codes_products
tecnicas/views/configuration_panel_tags.py CHANGED
@@ -37,7 +37,7 @@ def configuracionPanelTags(req: HttpRequest):
37
  values[name] = value.id
38
 
39
  req.session["form_tags"] = values
40
- return render(req, "tecnicas/configuracion-panel-tags.html", context_tags)
41
  else:
42
  context_tags["error"] = "ha ocurrido un error"
43
  return render(req, "tecnicas/configuracion-panel-tags.html", context_tags)
 
37
  values[name] = value.id
38
 
39
  req.session["form_tags"] = values
40
+ return redirect(reverse("cata_system:panel_configuracion_words"))
41
  else:
42
  context_tags["error"] = "ha ocurrido un error"
43
  return render(req, "tecnicas/configuracion-panel-tags.html", context_tags)
tecnicas/views/configuration_panel_words.py CHANGED
@@ -1,5 +1,58 @@
1
  from django.http import HttpRequest
2
- from django.shortcuts import render
 
 
 
 
3
 
4
  def configurationsPanelWords(req:HttpRequest):
5
- return render(req, "tecnicas/configuracion-panel-palabras.html")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from django.http import HttpRequest
2
+ from django.shortcuts import render, redirect
3
+ from django.urls import reverse
4
+ from ..utils import generarCodigos
5
+ from ..forms import PalabrasForm
6
+ import json
7
 
8
  def configurationsPanelWords(req:HttpRequest):
9
+ data_basic = req.session["form_basic"]
10
+ data_tags = req.session["form_tags"]
11
+
12
+ if not data_basic or not data_tags:
13
+ redirect(reverse("cata_system:seleccion_tecnica") + "?error=datos del formulario requerido no encontrados")
14
+
15
+ num_products = data_basic["numero_productos"]
16
+ num_cata = data_basic["numero_jueces"]
17
+
18
+ if req.method == "GET":
19
+ codes_products = generarCodigos(num_products)
20
+
21
+ form_worlds = PalabrasForm(codes=codes_products)
22
+
23
+ context_worlds_form = {
24
+ "form_worlds" : form_worlds,
25
+ "num_cata": num_cata
26
+ }
27
+
28
+ return render(req, "tecnicas/configuracion-panel-palabras.html", context_worlds_form)
29
+ elif req.method == "POST":
30
+ sorts_code = json.loads(req.POST.get("sort_codes"))
31
+ codes = []
32
+
33
+ for name, value in req.POST.items():
34
+ if name.__contains__("producto_"):
35
+ codes.append(value)
36
+
37
+ form_worlds = PalabrasForm(req.POST, codes=codes)
38
+
39
+ if form_worlds.is_valid():
40
+ code_sort = {"product_codes":[]}
41
+
42
+ for name, value in form_worlds.cleaned_data.items():
43
+ code_sort["product_codes"].append({name: value})
44
+
45
+ code_sort["sort_codes"] = sorts_code
46
+
47
+ print(code_sort)
48
+ print("Todo ok")
49
+ else:
50
+ print("datos no validos")
51
+
52
+ context_worlds_form = {
53
+ "form_worlds" : form_worlds,
54
+ "num_cata": num_cata,
55
+ "error": "error en los datos recibidos"
56
+ }
57
+
58
+ return render(req, "tecnicas/configuracion-panel-palabras.html", context_worlds_form)