diff --git a/src/agenda_culturel/forms.py b/src/agenda_culturel/forms.py index 1613ec9..f6fe7d4 100644 --- a/src/agenda_culturel/forms.py +++ b/src/agenda_culturel/forms.py @@ -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)] + diff --git a/src/agenda_culturel/models.py b/src/agenda_culturel/models.py index 9c4d76d..c6ab41e 100644 --- a/src/agenda_culturel/models.py +++ b/src/agenda_culturel/models.py @@ -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: diff --git a/src/agenda_culturel/templates/agenda_culturel/categorise_events_form.html b/src/agenda_culturel/templates/agenda_culturel/categorise_events_form.html new file mode 100644 index 0000000..595aa7d --- /dev/null +++ b/src/agenda_culturel/templates/agenda_culturel/categorise_events_form.html @@ -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 %} + + + + +{% css_categories %} +{% endblock %} + +{% block content %} + +
Les règles de catégorisation proposent de modifier comme suit les événements suivants. Sélectionnez les modifications qui vous conviennent.
+ + + + +{% endblock %} \ No newline at end of file diff --git a/src/agenda_culturel/templatetags/utils_extra.py b/src/agenda_culturel/templatetags/utils_extra.py index 2b360ed..2b808be 100644 --- a/src/agenda_culturel/templatetags/utils_extra.py +++ b/src/agenda_culturel/templatetags/utils_extra.py @@ -87,4 +87,13 @@ def truncatechars_middle(value, arg): @register.filter def frdate(d): - return ('!' + d).replace(" 1 ", " 1er ").replace("!1 ", "!1er ")[1:] \ No newline at end of file + 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_", "")) + \ No newline at end of file diff --git a/src/agenda_culturel/views.py b/src/agenda_culturel/views.py index f5bb801..6ce93af 100644 --- a/src/agenda_culturel/views.py +++ b/src/agenda_culturel/views.py @@ -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,24 +895,62 @@ class CategorisationRuleDeleteView(SuccessMessageMixin, PermissionRequiredMixin, @permission_required('agenda_culturel.apply_categorisationrules') def apply_categorisation_rules(request): - 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() + if request.method == 'POST': + form = CategorisationForm(request.POST) + if form.is_valid(): + nb = 0 + 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: + 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 nb != 0: - if nb == 1: - messages.success(request, _("The rules were successfully applied and 1 event was categorised.")) + return HttpResponseRedirect(reverse_lazy("categorisation_rules")) else: - messages.success(request, _("The rules were successfully applied and {} events were categorised.").format(nb)) + return render(request, 'agenda_culturel/categorise_events_form.html', context={'form': form}) else: - messages.info(request, _("The rules were successfully applied and no events were categorised.")) + # 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)) - return HttpResponseRedirect(reverse_lazy("categorisation_rules")) + # 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")) #########################