On applique à la main les changements de catégorie

This commit is contained in:
Jean-Marie Favreau 2024-04-16 11:49:35 +02:00
parent 96143c03a4
commit 6bcc72884d
5 changed files with 176 additions and 16 deletions

View File

@ -1,4 +1,4 @@
from django.forms import ModelForm, ValidationError, TextInput, Form, URLField, MultipleHiddenInput, Textarea, CharField, ChoiceField, RadioSelect, MultipleChoiceField
from django.forms import ModelForm, ValidationError, TextInput, Form, URLField, MultipleHiddenInput, Textarea, CharField, ChoiceField, RadioSelect, MultipleChoiceField, BooleanField, HiddenInput
from datetime import date
from django_better_admin_arrayfield.forms.widgets import DynamicArrayWidget
@ -270,3 +270,27 @@ class ModerateForm(ModelForm):
if a.question == q and a.valid_event(self.instance):
self.fields[q.complete_id()].initial = a.pk
break
class CategorisationForm(Form):
def __init__(self, *args, **kwargs):
if "events" in kwargs:
events = kwargs.pop('events', None)
else:
events = []
for f in args[0]:
logger.warning('fff: ' + f)
if '_' not in f:
if f + '_cat' in args[0]:
events.append((Event.objects.get(pk=int(f)), args[0][f + '_cat']))
# TODO
super().__init__(*args, **kwargs)
for e, c in events:
self.fields[str(e.pk)] = BooleanField(initial=False, label=_('Apply category {} to the event {}').format(c, e.title), required=False)
self.fields[str(e.pk) + "_cat"] = CharField(initial=c, widget=HiddenInput())
def get_validated(self):
return [(e, self.cleaned_data.get(e + '_cat')) for e in self.fields if '_' not in e and self.cleaned_data.get(e)]

View File

@ -834,7 +834,7 @@ class CategorisationRule(models.Model):
permissions = [("apply_categorisationrules", "Apply a categorisation rule")]
# on applique toutes les règles, de la première à la dernière
# all rules are applied, starting from the first to the last
def apply_rules(event):
rules = CategorisationRule.objects.all().order_by("weight", "pk")
@ -845,6 +845,16 @@ class CategorisationRule(models.Model):
return 0
def match_rules(event):
rules = CategorisationRule.objects.all().order_by("weight", "pk")
for rule in rules:
if rule.match(event):
return rule.category
return None
def match(self, event):
if self.description_contains:
if self.desc_exact:

View File

@ -0,0 +1,79 @@
{% extends "agenda_culturel/page.html" %}
{% load static %}
{% load utils_extra %}
{% load cat_extra %}
{% load event_extra %}
{% load tag_extra %}
{% block title %}Appliquer les catégorisations{% endblock %}
{% block entete_header %}
<script src="/static/admin/js/vendor/jquery/jquery.js"></script>
<script src="/static/admin/js/jquery.init.js"></script>
<link href="{% static 'css/django_better_admin_arrayfield.min.css' %}" type="text/css" media="all" rel="stylesheet">
<script src="{% static 'js/django_better_admin_arrayfield.min.js' %}"></script>
{% css_categories %}
{% endblock %}
{% block content %}
<h1>Appliquer les catégorisations</h1>
<p>Les règles de catégorisation proposent de modifier comme suit les événements suivants. Sélectionnez les modifications qui vous conviennent.</p>
<form method="post">{% csrf_token %}
{% for field in form %}
{% if not field.is_hidden %}
<article>
{{ field.errors }}
{% with eid=field.auto_id|remove_id_prefix %}
{% with event=events|get_item:eid %}
{% with altcat=categories|get_item:eid %}
<header>
{{ field }} Changer {{ event.category|small_cat }} en {{ altcat|small_cat }} pour l'événement
<a href="#event-{{ event.id }}"
aria-label="Fermer"
class="close"
data-target="event-{{ event.id }}"
onClick="toggleModal(event)"></a>
<h3>{{ event|picto_status }} {{ event.title }}</h3>
<p>
{% picto_from_name "map-pin" %}
{{ event.location }}
</p>
<p>
{% picto_from_name "calendar" %}
{% if event.end_day %}du{% else %}le{% endif %}
{% include "agenda_culturel/date-times-inc.html" with event=event %}
</p>
</header>
<div class="body-fixed">{{ event.description |linebreaks }}</div>
<p>
{% for tag in event.tags %}
{{ tag | tag_button }}
{% endfor %}
</p>
{% endwith %}
{% endwith %}
{% endwith %}
</article>
{% else %}
{{ field }}
{% endif %}
{% endfor %}
<div class="grid">
<a href="{% if request.META.HTTP_REFERER %}{{ request.META.HTTP_REFERER }}{% else %}{% url 'categorisation_rules' %}{% endif %}" role="button" class="secondary">Annuler</a>
<input type="submit" value="Envoyer">
</div>
</form>
{% endblock %}

View File

@ -88,3 +88,12 @@ def truncatechars_middle(value, arg):
@register.filter
def frdate(d):
return ('!' + d).replace(" 1 ", " 1er ").replace("!1 ", "!1er ")[1:]
@register.filter
def get_item(dictionary, key):
return dictionary.get(key)
@register.filter
def remove_id_prefix(value):
return int(value.replace("id_", ""))

View File

@ -11,7 +11,7 @@ from django.http import HttpResponseRedirect, HttpResponse, HttpResponseNotFound
from django.urls import reverse
import urllib
from .forms import EventSubmissionForm, EventForm, BatchImportationForm, FixDuplicates, SelectEventInList, MergeDuplicates, RecurrentImportForm, CategorisationRuleImportForm, ModerationQuestionForm, ModerationAnswerForm, ModerateForm
from .forms import EventSubmissionForm, EventForm, BatchImportationForm, FixDuplicates, SelectEventInList, MergeDuplicates, RecurrentImportForm, CategorisationRuleImportForm, ModerationQuestionForm, ModerationAnswerForm, ModerateForm, CategorisationForm
from .models import Event, Category, StaticContent, ContactMessage, BatchImportation, DuplicatedEvents, RecurrentImport, CategorisationRule, remove_accents, ModerationQuestion, ModerationAnswer
from django.utils import timezone
@ -895,13 +895,17 @@ class CategorisationRuleDeleteView(SuccessMessageMixin, PermissionRequiredMixin,
@permission_required('agenda_culturel.apply_categorisationrules')
def apply_categorisation_rules(request):
if request.method == 'POST':
form = CategorisationForm(request.POST)
if form.is_valid():
nb = 0
for e in Event.objects.filter(category=Category.get_default_category_id()):
success = CategorisationRule.apply_rules(e)
if success:
nb += 1
for epk, c in form.get_validated():
e = Event.objects.get(pk=epk)
logger.warning("cat " + c)
cat = Category.objects.get(name=c)
e.category = cat
e.save()
nb += 1
if nb != 0:
if nb == 1:
@ -911,7 +915,41 @@ def apply_categorisation_rules(request):
else:
messages.info(request, _("The rules were successfully applied and no events were categorised."))
return HttpResponseRedirect(reverse_lazy("categorisation_rules"))
else:
return render(request, 'agenda_culturel/categorise_events_form.html', context={'form': form})
else:
# first we check if events are not correctly categorised
to_categorise = []
for e in Event.objects.exclude(category=Category.get_default_category_id()).filter(start_day__gt=timezone.now().date()):
c = CategorisationRule.match_rules(e)
if c and c != e.category:
to_categorise.append((e, c))
# then we apply rules on events without category
nb = 0
for e in Event.objects.filter(category=Category.get_default_category_id()):
success = CategorisationRule.apply_rules(e)
if success:
nb += 1
e.save()
# set messages
if nb != 0:
if nb == 1:
messages.success(request, _("The rules were successfully applied and 1 event was categorised."))
else:
messages.success(request, _("The rules were successfully applied and {} events were categorised.").format(nb))
else:
messages.info(request, _("The rules were successfully applied and no events were categorised."))
if len(to_categorise) != 0:
form = CategorisationForm(events=to_categorise)
return render(request, 'agenda_culturel/categorise_events_form.html', context={'form': form,
'events': dict((e.pk, e) for e, c in to_categorise),
'categories': dict((e.pk, c) for e, c in to_categorise)})
else:
return HttpResponseRedirect(reverse_lazy("categorisation_rules"))