From 81681ad0e567e4565a3c4ed1e1a9f208ea153d93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sun, 5 Feb 2017 17:07:58 +0100 Subject: [PATCH] Turn 2 functions into class/objects methods - `_get_attrib_counter` become a classmethod of `PetitCoursAttributionCounter` - `_get_demande_candidates` become a method of `PetitCoursDemande` --- gestioncof/petits_cours_models.py | 46 ++++++++++++++++++++++++++++ gestioncof/petits_cours_views.py | 51 +++++++++---------------------- 2 files changed, 61 insertions(+), 36 deletions(-) diff --git a/gestioncof/petits_cours_models.py b/gestioncof/petits_cours_models.py index 6d9dac82..753e8674 100644 --- a/gestioncof/petits_cours_models.py +++ b/gestioncof/petits_cours_models.py @@ -3,6 +3,7 @@ from functools import reduce from django.db import models +from django.db.models import Min from django.contrib.auth.models import User from django.utils.translation import ugettext_lazy as _ @@ -88,6 +89,32 @@ class PetitCoursDemande(models.Model): blank=True, null=True) created = models.DateTimeField(_("Date de création"), auto_now_add=True) + def get_candidates(self, redo=False): + """ + Donne la liste des profs disponibles pour chaque matière de la demande. + - On ne donne que les agrégés si c'est demandé + - Si ``redo`` vaut ``True``, cela signifie qu'on retraite la demande et + il ne faut pas proposer à nouveau des noms qui ont déjà été proposés + """ + for matiere in self.matieres.all(): + candidates = PetitCoursAbility.objects.filter( + matiere=matiere, + niveau=self.niveau, + user__profile__is_cof=True, + user__profile__petits_cours_accept=True + ) + if self.agrege_requis: + candidates = candidates.filter(agrege=True) + if redo: + attrs = self.petitcoursattribution_set.filter(matiere=matiere) + already_proposed = [ + attr.user + for attr in attrs + ] + candidates = candidates.exclude(user__in=already_proposed) + candidates = candidates.order_by('?').select_related().all() + yield (matiere, candidates) + class Meta: verbose_name = "Demande de petits cours" verbose_name_plural = "Demandes de petits cours" @@ -122,6 +149,25 @@ class PetitCoursAttributionCounter(models.Model): matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_("Matiere")) count = models.IntegerField("Nombre d'envois", default=0) + @classmethod + def get_uptodate(cls, user, matiere): + """ + Donne le compteur de l'utilisateur pour cette matière. Si le compteur + n'existe pas encore, il est initialisé avec le minimum des valeurs des + compteurs de tout le monde. + """ + counter, created = cls.objects.get_or_create( + user=user, matiere=matiere) + if created: + mincount = ( + cls.objects.filter(matiere=matiere).exclude(user=user) + .aggregate(Min('count')) + ['count__min'] + ) + counter.count = mincount + counter.save() + return counter + class Meta: verbose_name = "Compteur d'attribution de petits cours" verbose_name_plural = "Compteurs d'attributions de petits cours" diff --git a/gestioncof/petits_cours_views.py b/gestioncof/petits_cours_views.py index f9a038a7..68befaf7 100644 --- a/gestioncof/petits_cours_views.py +++ b/gestioncof/petits_cours_views.py @@ -16,7 +16,6 @@ from django.views.decorators.csrf import csrf_exempt from django.template import loader from django.conf import settings from django.contrib.auth.decorators import login_required -from django.db.models import Min from gestioncof.models import CofProfile from gestioncof.petits_cours_models import ( @@ -51,35 +50,6 @@ def details(request, demande_id): "attributions": attributions}) -def _get_attrib_counter(user, matiere): - counter, created = PetitCoursAttributionCounter \ - .objects.get_or_create(user=user, matiere=matiere) - if created: - mincount = PetitCoursAttributionCounter.objects \ - .filter(matiere=matiere).exclude(user=user).all() \ - .aggregate(Min('count')) - counter.count = mincount['count__min'] - counter.save() - return counter - - -def _get_demande_candidates(demande, redo=False): - for matiere in demande.matieres.all(): - candidates = PetitCoursAbility.objects.filter(matiere=matiere, - niveau=demande.niveau) - candidates = candidates.filter(user__profile__is_cof=True, - user__profile__petits_cours_accept=True) - if demande.agrege_requis: - candidates = candidates.filter(agrege=True) - if redo: - attributions = PetitCoursAttribution.objects \ - .filter(demande=demande, matiere=matiere).all() - for attrib in attributions: - candidates = candidates.exclude(user=attrib.user) - candidates = candidates.order_by('?').select_related().all() - yield (matiere, candidates) - - @buro_required def traitement(request, demande_id, redo=False): demande = get_object_or_404(PetitCoursDemande, id=demande_id) @@ -91,12 +61,15 @@ def traitement(request, demande_id, redo=False): proposed_for = {} unsatisfied = [] attribdata = {} - for matiere, candidates in _get_demande_candidates(demande, redo): + for matiere, candidates in demande.get_candidates(redo): if candidates: tuples = [] for candidate in candidates: user = candidate.user - tuples.append((candidate, _get_attrib_counter(user, matiere))) + tuples.append(( + candidate, + PetitCoursAttributionCounter.get_uptodate(user, matiere) + )) tuples = sorted(tuples, key=lambda c: c[1].count) candidates, _ = zip(*tuples) candidates = candidates[0:min(3, len(candidates))] @@ -166,7 +139,7 @@ def _traitement_other_preparing(request, demande): proposed_for = {} attribdata = {} errors = [] - for matiere, candidates in _get_demande_candidates(demande, redo): + for matiere, candidates in demande.get_candidates(redo): if candidates: candidates = dict([(candidate.user.id, candidate.user) for candidate in candidates]) @@ -218,12 +191,15 @@ def _traitement_other(request, demande, redo): proposed_for = {} unsatisfied = [] attribdata = {} - for matiere, candidates in _get_demande_candidates(demande, redo): + for matiere, candidates in demande.get_candidates(redo): if candidates: tuples = [] for candidate in candidates: user = candidate.user - tuples.append((candidate, _get_attrib_counter(user, matiere))) + tuples.append(( + candidate, + PetitCoursAttributionCounter.get_uptodate(user, matiere) + )) tuples = sorted(tuples, key=lambda c: c[1].count) candidates, _ = zip(*tuples) attribdata[matiere.id] = [] @@ -357,7 +333,10 @@ def inscription(request): PetitCoursAbility.objects.filter(user=request.user).all() ) for ability in abilities: - _get_attrib_counter(ability.user, ability.matiere) + PetitCoursAttributionCounter.get_uptodate( + ability.user, + ability.matiere + ) unlock_tables() success = True formset = MatieresFormSet(instance=request.user)