Skip to content

Commit abc50c3

Browse files
fix: conditional fields
1 parent c860644 commit abc50c3

10 files changed

Lines changed: 445 additions & 80 deletions

File tree

uniticket/uni_ticket/dynamic_form.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def __init__(self, constructor_dict={}, custom_params={}, *args, **kwargs):
5757
"help_text": TICKET_SUBJECT_HELP_TEXT,
5858
"initial": subject_initial,
5959
"max_length": subject_max_length,
60-
"min_length": subject_min_length
60+
"min_length": subject_min_length,
6161
}
6262
subject_field = getattr(
6363
dynamic_fields, "CustomCharField")(**subject_data)
@@ -95,6 +95,7 @@ def __init__(self, constructor_dict={}, custom_params={}, *args, **kwargs):
9595
captcha_field.define_value(custom_value="", **custom_params)
9696
for single_field in captcha_field.get_fields():
9797
self.final_fields[single_field.name] = single_field
98+
9899
super().__init__(
99100
initial_fields=self.initial_fields,
100101
final_fields=self.final_fields,
@@ -137,6 +138,7 @@ def serialize_form(form, api_source = 'api_source'):
137138
field_dict['initial'] = field.initial
138139
field_dict['disabled'] = field.disabled
139140
field_dict['required'] = True if field.required else False
141+
field_dict['visible'] = True if field.visible else False
140142
field_dict['error_messages'] = field.error_messages
141143
field_dict['help_text'] = field.help_text
142144
field_dict['api_source'] = getattr(field, api_source, '')

uniticket/uni_ticket/forms.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class Meta:
128128
"pre_text",
129129
"aiuto",
130130
"is_required",
131+
"visible",
131132
"ordinamento",
132133
]
133134
labels = {
@@ -836,3 +837,47 @@ class Meta:
836837

837838
class Media:
838839
js = ("js/textarea-autosize.js",)
840+
841+
842+
class TicketCategoryModuleRuleForm(ModelForm):
843+
""" """
844+
def __init__(self, *args, **kwargs):
845+
module = kwargs.pop("module", None)
846+
super().__init__(*args, **kwargs)
847+
allowed_types = [
848+
'CustomRadioBoxField',
849+
'CustomSelectBoxField',
850+
# ~ 'CheckBoxField'
851+
]
852+
source_choices = []
853+
target_choices = []
854+
if module:
855+
fields = TicketCategoryInputList.objects.filter(
856+
category_module=module,
857+
)
858+
for f in fields:
859+
if f.field_type in allowed_types:
860+
source_choices.append((f.pk, f.name))
861+
target_choices.append((f.pk, f.name))
862+
self.fields['source_field'].choices = source_choices
863+
self.fields['target_field'].choices = target_choices
864+
865+
class Meta:
866+
model = TicketCategoryModuleRule
867+
fields = [
868+
"source_field",
869+
"condition",
870+
"action",
871+
"target_field",
872+
#"value",
873+
"is_active"
874+
]
875+
labels = {"visibility": _("Visibilità"),}
876+
widgets = {
877+
"source_field": BootstrapItaliaSelectWidget,
878+
"target_field": BootstrapItaliaSelectWidget,
879+
"value": forms.Textarea(attrs={"rows": 2}),
880+
}
881+
882+
class Media:
883+
js = ("js/textarea-autosize.js",)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Generated by Django 5.2.8 on 2026-04-10 10:07
2+
3+
import django.db.models.deletion
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
("uni_ticket", "0035_alter_compiledticket_id_alter_log_id_and_more"),
11+
]
12+
13+
operations = [
14+
migrations.AddField(
15+
model_name="ticketcategoryinputlist",
16+
name="visible",
17+
field=models.BooleanField(default=True),
18+
),
19+
migrations.CreateModel(
20+
name="TicketCategoryModuleRule",
21+
fields=[
22+
(
23+
"id",
24+
models.BigAutoField(
25+
auto_created=True,
26+
primary_key=True,
27+
serialize=False,
28+
verbose_name="ID",
29+
),
30+
),
31+
(
32+
"action",
33+
models.IntegerField(
34+
choices=[
35+
(1, "Nascondi il campo"),
36+
(2, "Mostra il campo"),
37+
(3, "Modifica il valore"),
38+
]
39+
),
40+
),
41+
("value", models.TextField(blank=True, default="", max_length=20000)),
42+
("created", models.DateTimeField(auto_now_add=True)),
43+
("is_active", models.BooleanField(default=False)),
44+
(
45+
"category_module",
46+
models.ForeignKey(
47+
on_delete=django.db.models.deletion.CASCADE,
48+
to="uni_ticket.ticketcategorymodule",
49+
),
50+
),
51+
(
52+
"source_field",
53+
models.ForeignKey(
54+
on_delete=django.db.models.deletion.PROTECT,
55+
related_name="source_rules",
56+
to="uni_ticket.ticketcategoryinputlist",
57+
),
58+
),
59+
(
60+
"target_field",
61+
models.ForeignKey(
62+
on_delete=django.db.models.deletion.PROTECT,
63+
related_name="target_rules",
64+
to="uni_ticket.ticketcategoryinputlist",
65+
),
66+
),
67+
],
68+
),
69+
]
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Generated by Django 5.2.8 on 2026-04-10 11:00
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("uni_ticket", "0036_ticketcategoryinputlist_visible_and_more"),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name="ticketcategorymodulerule",
15+
name="condition",
16+
field=models.CharField(default=1, max_length=255),
17+
preserve_default=False,
18+
),
19+
]

uniticket/uni_ticket/models.py

Lines changed: 79 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
from django_form_builder.forms import BaseDynamicForm
2525
from django_form_builder.models import DynamicFieldMap, SavedFormContent
26-
from django_form_builder.utils import get_as_dict, set_as_dict
26+
from django_form_builder.utils import format_field_name, get_as_dict, set_as_dict
2727

2828
from organizational_area.models import (
2929
OrganizationalStructure,
@@ -36,6 +36,7 @@
3636
from .settings import (
3737
CATEGORY_CONDITIONS_ATTACHMENT_SUBFOLDER,
3838
CLOSING_LEVELS,
39+
INPUT_MODULE_ACTIONS,
3940
MAX_DAILY_TICKET_PER_USER,
4041
NEW_TICKET_CREATED_ALERT,
4142
ORGANIZATION_EMPLOYEE_LABEL,
@@ -62,10 +63,12 @@
6263

6364
_protocollo_titolario_list = settings.TITOLARIO_DICT
6465
_protocollo_uo_list = settings.UO_DICT
66+
_input_module_rules_action_list = INPUT_MODULE_ACTIONS
6567
if 'makemigrations' in sys.argv or 'migrate' in sys.argv: # pragma: no cover
6668
_protocollo_titolario_list = [('', '-')]
6769
_protocollo_uo_list = [('', '-')]
68-
70+
_input_module_rules_action_list = [('', '-')]
71+
6972

7073
def _attachment_upload(instance, filename):
7174
"""
@@ -416,14 +419,59 @@ def get_form(
416419
show_conditions=False,
417420
**kwargs
418421
):
419-
ticket_input_list = self.ticketcategoryinputlist_set.all().order_by(
420-
"ordinamento"
421-
)
422+
423+
copy_data = data.copy() if data else None
424+
print(data)
425+
# after post
426+
if copy_data:
427+
fields_to_exclude = list(self.ticketcategoryinputlist_set.filter(visible=False).values_list('pk', flat=True))
428+
labels_to_exclude = []
429+
430+
rules = self.ticketcategorymodulerule_set.filter(is_active=True)
431+
# check rules on fields
432+
for rule in rules:
433+
source = rule.source_field
434+
target = rule.target_field
435+
source_label = format_field_name(source.name)
436+
target_label = format_field_name(target.name)
437+
if source.pk in fields_to_exclude:
438+
continue
439+
if copy_data.get(source_label, None) and copy_data[source_label] in rule.condition:
440+
# show
441+
if rule.action == 2 and target.pk in fields_to_exclude:
442+
fields_to_exclude.remove(target.pk)
443+
if target_label in labels_to_exclude:
444+
labels_to_exclude.remove(target_label)
445+
# hide
446+
if rule.action == 1 and not target.pk in fields_to_exclude:
447+
fields_to_exclude.append(target.pk)
448+
if target_label not in labels_to_exclude:
449+
labels_to_exclude.append(target_label)
450+
451+
for lte in labels_to_exclude:
452+
copy_data.pop(lte, None)
453+
print("labels_to_exclude", labels_to_exclude)
454+
print("fields_to_exclude", fields_to_exclude)
455+
print("data", data)
456+
print("copy_data", copy_data)
457+
458+
ticket_input_list = self.ticketcategoryinputlist_set.all().exclude(pk__in=fields_to_exclude).order_by(
459+
"ordinamento"
460+
)
461+
print("ticket_input_list", ticket_input_list)
462+
print()
463+
print()
464+
print()
465+
# blank form
466+
else:
467+
ticket_input_list = self.ticketcategoryinputlist_set.filter(visible=True).order_by(
468+
"ordinamento"
469+
)
422470

423471
# Static method of BaseDynamicForm
424472
constructor_dict = BaseDynamicForm.build_constructor_dict(
425473
ticket_input_list)
426-
474+
427475
custom_params = {}
428476
custom_params["show_conditions"] = show_conditions
429477
custom_params["category_owner"] = self.ticket_category
@@ -438,7 +486,7 @@ def get_form(
438486
class_obj=DynamicForm,
439487
constructor_dict=constructor_dict,
440488
custom_params=custom_params,
441-
data=data,
489+
data=copy_data,
442490
files=files,
443491
remove_filefields=remove_filefields,
444492
remove_datafields=remove_datafields,
@@ -459,7 +507,8 @@ class TicketCategoryInputList(DynamicFieldMap):
459507

460508
category_module = models.ForeignKey(
461509
TicketCategoryModule, on_delete=models.CASCADE)
462-
510+
visible = models.BooleanField(default=True)
511+
463512
class Meta:
464513
verbose_name = _("Modulo di inserimento")
465514
verbose_name_plural = _("Moduli di inserimento")
@@ -475,6 +524,28 @@ def field_exist(module, field_name):
475524
return False
476525

477526

527+
class TicketCategoryModuleRule(models.Model):
528+
category_module = models.ForeignKey(
529+
TicketCategoryModule, on_delete=models.CASCADE)
530+
source_field = models.ForeignKey(
531+
TicketCategoryInputList,
532+
on_delete=models.PROTECT,
533+
related_name="source_rules"
534+
)
535+
target_field = models.ForeignKey(
536+
TicketCategoryInputList,
537+
on_delete=models.PROTECT,
538+
related_name="target_rules"
539+
)
540+
condition = models.CharField(max_length=255)
541+
action = models.IntegerField(
542+
choices=INPUT_MODULE_ACTIONS
543+
)
544+
value = models.TextField(max_length=20000, default="", blank=True)
545+
created = models.DateTimeField(auto_now_add=True)
546+
is_active = models.BooleanField(default=False)
547+
548+
478549
class Ticket(SavedFormContent):
479550
"""
480551
Ticket

uniticket/uni_ticket/settings.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,17 @@
146146
),
147147
)
148148

149+
# input modules rules actions
150+
INPUT_MODULE_ACTIONS = getattr(
151+
settings,
152+
"INPUT_MODULE_ACTIONS",
153+
(
154+
(1, _("Nascondi il campo")),
155+
(2, _("Mostra il campo")),
156+
# ~ (3, _("Modifica il valore")),
157+
),
158+
)
159+
149160
# If 0 = Unlimited
150161
MAX_DAILY_TICKET_PER_USER = getattr(settings, "MAX_DAILY_TICKET_PER_USER", 10)
151162

0 commit comments

Comments
 (0)