[petitscours] Extrait la proposition de profs dans une méthode

Ce patch simplifie le code (dupliqué) de calcul des proposition de profs
pour une demande dans une méthode du modèle`Demande`, et l'utilise.  Il
s'agit d'un préparatif pour #208; ce code devra être réutilisé dans le
nouveau système.

J'en ai également profité pour nettoyer deux vues de `petitscours`,
`retraitement` et `demande_raw`, qui dupliquaient les vues `traitement`
et `demande`, en utilisant des arguments nommés.

petitscours/
 * models.py:
    Définition de `get_proposals` pour calculer les propositions de
    profs pour une demande.
 * views.py:
    Utilise `get_proposals` à la place du code copié-collé.  La fonction
    `_finalize_traitement` est maintenant responsable du calcul des
    `proposed_for` et `attribdata` à fournir aux templates.
 * urls.py:
    Passe directement les arguments aux vues plutôt que de faire deux
    fonctions séparées.
This commit is contained in:
Basile Clement 2018-11-25 17:05:55 +01:00
parent c960d97b67
commit 2b8f81c94b
3 changed files with 78 additions and 129 deletions

View file

@ -53,64 +53,27 @@ def traitement(request, demande_id, redo=False):
return _traitement_other(request, demande, redo)
if request.method == "POST":
return _traitement_post(request, demande)
proposals = {}
proposed_for = {}
unsatisfied = []
attribdata = {}
for matiere, candidates in demande.get_candidates(redo):
if candidates:
tuples = []
for candidate in candidates:
user = candidate.user
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))]
attribdata[matiere.id] = []
proposals[matiere] = []
for candidate in candidates:
user = candidate.user
proposals[matiere].append(user)
attribdata[matiere.id].append(user.id)
if user not in proposed_for:
proposed_for[user] = [matiere]
else:
proposed_for[user].append(matiere)
else:
unsatisfied.append(matiere)
return _finalize_traitement(
request, demande, proposals, proposed_for, unsatisfied, attribdata, redo
)
@buro_required
def retraitement(request, demande_id):
return traitement(request, demande_id, redo=True)
proposals, unsatisfied = demande.get_proposals(redo=redo, max_candidates=3)
return _finalize_traitement(request, demande, proposals, unsatisfied, redo)
def _finalize_traitement(
request,
demande,
proposals,
proposed_for,
unsatisfied,
attribdata,
redo=False,
errors=None,
request, demande, proposals, unsatisfied, redo=False, errors=None
):
proposals = proposals.items()
proposed_for = proposed_for.items()
attribdata = list(attribdata.items())
attribdata = [
(matiere.id, [user.id for user in users])
for matiere, users in proposals.items()
]
proposed_for = {}
for matiere, users in proposals.items():
for user in users:
proposed_for.setdefault(user, []).append(matiere)
proposed_mails = _generate_eleve_email(demande, proposed_for)
mainmail = render_custom_mail(
"petits-cours-mail-demandeur",
{
"proposals": proposals,
"proposals": proposals.items(),
"unsatisfied": unsatisfied,
"extra": '<textarea name="extra" '
'style="width:99%; height: 90px;">'
@ -126,8 +89,8 @@ def _finalize_traitement(
{
"demande": demande,
"unsatisfied": unsatisfied,
"proposals": proposals,
"proposed_for": proposed_for,
"proposals": proposals.items(),
"proposed_for": proposed_for.items(),
"proposed_mails": proposed_mails,
"mainmail": mainmail,
"attribdata": json.dumps(attribdata),
@ -144,7 +107,7 @@ def _generate_eleve_email(demande, proposed_for):
"petit-cours-mail-eleve", {"demande": demande, "matieres": matieres}
),
)
for user, matieres in proposed_for
for user, matieres in proposed_for.items()
]
@ -152,15 +115,12 @@ def _traitement_other_preparing(request, demande):
redo = "redo" in request.POST
unsatisfied = []
proposals = {}
proposed_for = {}
attribdata = {}
errors = []
for matiere, candidates in demande.get_candidates(redo):
if candidates:
candidates = dict(
[(candidate.user.id, candidate.user) for candidate in candidates]
)
attribdata[matiere.id] = []
proposals[matiere] = []
for choice_id in range(min(3, len(candidates))):
choice = int(
@ -183,11 +143,6 @@ def _traitement_other_preparing(request, demande):
)
continue
proposals[matiere].append(user)
attribdata[matiere.id].append(user.id)
if user not in proposed_for:
proposed_for[user] = [matiere]
else:
proposed_for[user].append(matiere)
if not proposals[matiere]:
errors.append("Aucune proposition pour {!s}".format(matiere))
elif len(proposals[matiere]) < 3:
@ -200,15 +155,7 @@ def _traitement_other_preparing(request, demande):
)
else:
unsatisfied.append(matiere)
return _finalize_traitement(
request,
demande,
proposals,
proposed_for,
unsatisfied,
attribdata,
errors=errors,
)
return _finalize_traitement(request, demande, proposals, unsatisfied, errors=errors)
def _traitement_other(request, demande, redo):
@ -217,45 +164,14 @@ def _traitement_other(request, demande, redo):
return _traitement_other_preparing(request, demande)
else:
return _traitement_post(request, demande)
proposals = {}
proposed_for = {}
unsatisfied = []
attribdata = {}
for matiere, candidates in demande.get_candidates(redo):
if candidates:
tuples = []
for candidate in candidates:
user = candidate.user
tuples.append(
(
candidate,
PetitCoursAttributionCounter.get_uptodate(user, matiere),
)
)
tuples = sorted(tuples, key=lambda c: c[1].count)
candidates, _ = zip(*tuples)
attribdata[matiere.id] = []
proposals[matiere] = []
for candidate in candidates:
user = candidate.user
proposals[matiere].append(user)
attribdata[matiere.id].append(user.id)
if user not in proposed_for:
proposed_for[user] = [matiere]
else:
proposed_for[user].append(matiere)
else:
unsatisfied.append(matiere)
proposals = proposals.items()
proposed_for = proposed_for.items()
proposals, unsatisfied = demande.get_proposals(redo=redo)
return render(
request,
"petitscours/traitement_demande_autre_niveau.html",
{
"demande": demande,
"unsatisfied": unsatisfied,
"proposals": proposals,
"proposed_for": proposed_for,
"proposals": proposals.items(),
},
)
@ -280,12 +196,10 @@ def _traitement_post(request, demande):
proposed_for[user] = [matiere]
else:
proposed_for[user].append(matiere)
proposals_list = proposals.items()
proposed_for = proposed_for.items()
proposed_mails = _generate_eleve_email(demande, proposed_for)
mainmail_object, mainmail_body = render_custom_mail(
"petits-cours-mail-demandeur",
{"proposals": proposals_list, "unsatisfied": unsatisfied, "extra": extra},
{"proposals": proposals.items(), "unsatisfied": unsatisfied, "extra": extra},
)
frommail = settings.MAIL_DATA["petits_cours"]["FROM"]
bccaddress = settings.MAIL_DATA["petits_cours"]["BCC"]
@ -314,8 +228,8 @@ def _traitement_post(request, demande):
connection = mail.get_connection(fail_silently=False)
connection.send_messages(mails_to_send)
with transaction.atomic():
for matiere in proposals:
for rank, user in enumerate(proposals[matiere]):
for matiere, users in proposals.items():
for rank, user in enumerate(users):
# TODO(AD): Prefer PetitCoursAttributionCounter.get_uptodate()
counter = PetitCoursAttributionCounter.objects.get(
user=user, matiere=matiere
@ -373,7 +287,7 @@ def inscription(request):
@csrf_exempt
def demande(request):
def demande(request, *, raw: bool = False):
success = False
if request.method == "POST":
form = DemandeForm(request.POST)
@ -382,21 +296,7 @@ def demande(request):
success = True
else:
form = DemandeForm()
return render(
request, "petitscours/demande.html", {"form": form, "success": success}
)
@csrf_exempt
def demande_raw(request):
success = False
if request.method == "POST":
form = DemandeForm(request.POST)
if form.is_valid():
form.save()
success = True
else:
form = DemandeForm()
return render(
request, "petitscours/demande_raw.html", {"form": form, "success": success}
)
template_name = "petitscours/demande.html"
if raw:
template_name = "petitscours/demande_raw.html"
return render(request, template_name, {"form": form, "success": success})