Turn 2 functions into class/objects methods

- `_get_attrib_counter` become a classmethod of
  `PetitCoursAttributionCounter`
- `_get_demande_candidates` become a method of `PetitCoursDemande`
This commit is contained in:
Martin Pépin 2017-02-05 17:07:58 +01:00
parent 2bc5f3d646
commit 81681ad0e5
2 changed files with 61 additions and 36 deletions

View file

@ -3,6 +3,7 @@
from functools import reduce from functools import reduce
from django.db import models from django.db import models
from django.db.models import Min
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -88,6 +89,32 @@ class PetitCoursDemande(models.Model):
blank=True, null=True) blank=True, null=True)
created = models.DateTimeField(_("Date de création"), auto_now_add=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: class Meta:
verbose_name = "Demande de petits cours" verbose_name = "Demande de petits cours"
verbose_name_plural = "Demandes 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")) matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_("Matiere"))
count = models.IntegerField("Nombre d'envois", default=0) 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: class Meta:
verbose_name = "Compteur d'attribution de petits cours" verbose_name = "Compteur d'attribution de petits cours"
verbose_name_plural = "Compteurs d'attributions de petits cours" verbose_name_plural = "Compteurs d'attributions de petits cours"

View file

@ -16,7 +16,6 @@ from django.views.decorators.csrf import csrf_exempt
from django.template import loader from django.template import loader
from django.conf import settings from django.conf import settings
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.db.models import Min
from gestioncof.models import CofProfile from gestioncof.models import CofProfile
from gestioncof.petits_cours_models import ( from gestioncof.petits_cours_models import (
@ -51,35 +50,6 @@ def details(request, demande_id):
"attributions": attributions}) "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 @buro_required
def traitement(request, demande_id, redo=False): def traitement(request, demande_id, redo=False):
demande = get_object_or_404(PetitCoursDemande, id=demande_id) demande = get_object_or_404(PetitCoursDemande, id=demande_id)
@ -91,12 +61,15 @@ def traitement(request, demande_id, redo=False):
proposed_for = {} proposed_for = {}
unsatisfied = [] unsatisfied = []
attribdata = {} attribdata = {}
for matiere, candidates in _get_demande_candidates(demande, redo): for matiere, candidates in demande.get_candidates(redo):
if candidates: if candidates:
tuples = [] tuples = []
for candidate in candidates: for candidate in candidates:
user = candidate.user 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) tuples = sorted(tuples, key=lambda c: c[1].count)
candidates, _ = zip(*tuples) candidates, _ = zip(*tuples)
candidates = candidates[0:min(3, len(candidates))] candidates = candidates[0:min(3, len(candidates))]
@ -166,7 +139,7 @@ def _traitement_other_preparing(request, demande):
proposed_for = {} proposed_for = {}
attribdata = {} attribdata = {}
errors = [] errors = []
for matiere, candidates in _get_demande_candidates(demande, redo): for matiere, candidates in demande.get_candidates(redo):
if candidates: if candidates:
candidates = dict([(candidate.user.id, candidate.user) candidates = dict([(candidate.user.id, candidate.user)
for candidate in candidates]) for candidate in candidates])
@ -218,12 +191,15 @@ def _traitement_other(request, demande, redo):
proposed_for = {} proposed_for = {}
unsatisfied = [] unsatisfied = []
attribdata = {} attribdata = {}
for matiere, candidates in _get_demande_candidates(demande, redo): for matiere, candidates in demande.get_candidates(redo):
if candidates: if candidates:
tuples = [] tuples = []
for candidate in candidates: for candidate in candidates:
user = candidate.user 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) tuples = sorted(tuples, key=lambda c: c[1].count)
candidates, _ = zip(*tuples) candidates, _ = zip(*tuples)
attribdata[matiere.id] = [] attribdata[matiere.id] = []
@ -357,7 +333,10 @@ def inscription(request):
PetitCoursAbility.objects.filter(user=request.user).all() PetitCoursAbility.objects.filter(user=request.user).all()
) )
for ability in abilities: for ability in abilities:
_get_attrib_counter(ability.user, ability.matiere) PetitCoursAttributionCounter.get_uptodate(
ability.user,
ability.matiere
)
unlock_tables() unlock_tables()
success = True success = True
formset = MatieresFormSet(instance=request.user) formset = MatieresFormSet(instance=request.user)