Add EDE convocation form

This commit is contained in:
Claude Paroz 2018-01-26 18:19:16 +01:00
parent 1f49b198ec
commit ffb54c9f78
9 changed files with 207 additions and 2 deletions

View file

@ -6,6 +6,7 @@ from django.contrib import admin
from django.core.mail import EmailMessage
from django.db.models import BooleanField
from django.template import loader
from django.urls import reverse
from stages.exports import OpenXMLExport
from .models import Candidate, Interview, GENDER_CHOICES
@ -119,7 +120,7 @@ class CandidateAdminForm(forms.ModelForm):
class CandidateAdmin(admin.ModelAdmin):
form = CandidateAdminForm
list_display = ('last_name', 'first_name', 'section', 'confirm_mail')
list_display = ('last_name', 'first_name', 'section', 'confirm_mail', 'convocation')
list_filter = ('section', 'option')
readonly_fields = ('total_result_points', 'total_result_mark', 'date_confirmation_mail')
actions = [export_candidates, send_confirmation_mail]
@ -157,6 +158,17 @@ class CandidateAdmin(admin.ModelAdmin):
return obj.date_confirmation_mail is not None
confirm_mail.boolean = True
def convocation(self, obj):
if obj.interview is None:
return '???'
elif obj.interview and obj.convocation_date:
return obj.interview
else:
url = reverse('candidate-convocation', args=[obj.pk])
return '<a href="' + url + '">Envoyer convocation</a>'
convocation.short_description = 'Convoc. aux examens'
convocation.allow_tags = True
class InterviewAdmin(admin.ModelAdmin):
pass

View file

@ -166,7 +166,11 @@ class Interview(models.Model):
def __str__(self):
return '{0} : {1}/{2} - ({3}) -salle:{4}-{5}'.format(
django_format(self.date, "l j F Y à H\hi"),
self.date_formatted,
self.teacher_int or '?', self.teacher_file or '?',
self.status, self.room, self.candidat or '???'
)
@property
def date_formatted(self):
return django_format(self.date, "l j F Y à H\hi")

View file

@ -113,3 +113,53 @@ me@example.org
self.assertContains(response, "Échec denvoi pour le candidat Dupond Henri (Error sending mail)")
henri.refresh_from_db()
self.assertIsNone(henri.date_confirmation_mail)
def test_convocation_ede(self):
ede = Section.objects.create(name='EDE')
henri = Candidate.objects.create(
first_name='Henri', last_name='Dupond', gender='M', section=ede,
email='henri@example.org', deposite_date=date.today()
)
inter = Interview.objects.create(date=datetime(2018, 3, 10, 10, 30), room='B103', candidat=henri)
self.client.login(username='me', password='mepassword')
response = self.client.get(reverse('candidate-convocation', args=[henri.pk]))
self.assertContains(response, '<h2>Dupond Henri</h2>')
self.assertContains(response, '<input type="text" name="to" value="henri@example.org" size="60" id="id_to" required>', html=True)
self.assertContains(response, """
Monsieur Henri Dupond,
Nous vous adressons par la présente votre convocation personnelle à la procédure dadmission de la filière Education de lenfance, dipl. ES.
Vous êtes attendu-e à lEcole Santé-social Pierre-Coullery, rue de la Prévoyance 82, 2300 La Chaux-de-Fonds aux dates suivantes:
- mercredi 7 mars 2018, à 13h30, salle 405, pour lexamen écrit (durée approx. 4 heures)
- samedi 10 mars 2018 à 10h30, en salle B103, pour lentretien dadmission (durée approx. 45 min.).
En cas dempêchement de dernière minute, nous vous remercions dannoncer votre absence au secrétariat (Tél. 032 886 33 00).
De plus, afin que nous puissions enregistrer définitivement votre inscription, nous vous remercions par avance
de nous faire parvenir, dans les meilleurs délais, le ou les documents suivants:
- Formulaire d&#39;inscription, Attest. de paiement, Casier judic., CV, Texte réflexif, Photo passeport, Bilan act. prof./dernier stage, Bull. de notes
Dans lintervalle, nous vous adressons, Monsieur, nos salutations les plus cordiales.
Secrétariat de la filière Education de lenfance, dipl. ES
Hans Schmid
me@example.org
tél. 032 886 33 00"""
)
response = self.client.post(reverse('candidate-convocation', args=[henri.pk]), data={
'id_candidate': str(henri.pk),
'cci': 'me@example.org',
'to': henri.email,
'subject': "Procédure de qualification",
'message': "Monsieur Henri Dupond, ...",
'sender': 'me@example.org',
})
self.assertRedirects(response, reverse('admin:candidats_candidate_changelist'))
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].recipients(), ['henri@example.org', 'me@example.org'])
self.assertEqual(mail.outbox[0].subject, "Procédure de qualification")
henri.refresh_from_db()
self.assertIsNotNone(henri.convocation_date)

90
candidats/views.py Normal file
View file

@ -0,0 +1,90 @@
from django import forms
from django.conf import settings
from django.contrib import messages
from django.core.mail import EmailMessage
from django.template import loader
from django.urls import reverse_lazy
from django.utils import timezone
from django.views.generic import FormView
from candidats.models import Candidate
class ConvocationForm(forms.Form):
id_candidate = forms.CharField(widget=forms.HiddenInput())
sender = forms.CharField(widget=forms.HiddenInput())
to = forms.CharField(widget=forms.TextInput(attrs={'size': '60'}))
cci = forms.CharField(widget=forms.TextInput(attrs={'size': '60'}))
subject = forms.CharField(widget=forms.TextInput(attrs={'size': '60'}))
message = forms.CharField(widget=forms.Textarea(attrs={'rows': 25, 'cols': 120}))
class SendConvocationView(FormView):
template_name = 'candidats/convocation.html'
form_class = ConvocationForm
success_url = reverse_lazy('admin:candidats_candidate_changelist')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
candidate = Candidate.objects.get(pk=self.kwargs['pk'])
docs = [
'registration_form', 'certificate_of_payement', 'police_record', 'cv', 'reflexive_text',
'has_photo', 'work_certificate', 'marks_certificate',
]
if candidate.option == 'PE-5400h':
docs.append('promise', 'contract', 'certif_of_800h')
elif candidate.option == 'PE-3600h':
docs.append('certif_of_cfc', 'promise', 'contract')
elif candidate.option == 'PS':
docs.append('certif_of_800h')
missing_documents = {'documents': ', '.join([
Candidate._meta.get_field(doc).verbose_name for doc in docs if not getattr(candidate, doc)
])}
msg_context = {
'candidate_name': " ".join([candidate.civility, candidate.first_name, candidate.last_name]),
'candidate_civility': candidate.civility,
'date_lieu_examen': settings.DATE_LIEU_EXAMEN_EDE,
'date_entretien': candidate.interview.date_formatted,
'salle_entretien': candidate.interview.room,
'rappel': loader.render_to_string('email/rappel_document_EDE.txt', missing_documents),
'sender_name': " ".join([self.request.user.first_name, self.request.user.last_name]),
'sender_email': self.request.user.email,
}
form = ConvocationForm(initial={
'id_candidate': candidate.pk,
'cci': self.request.user.email,
'to': candidate.email,
'subject': "Procédure de qualification",
'message': loader.render_to_string('email/candidate_convocation_EDE.txt', msg_context),
'sender': self.request.user.email,
})
context.update({
'candidat': candidate,
'form': form,
})
return context
def form_valid(self, form):
email = EmailMessage(
subject=form.cleaned_data['subject'],
body=form.cleaned_data['message'],
from_email=form.cleaned_data['sender'],
to=form.cleaned_data['to'].split(';'),
bcc=form.cleaned_data['cci'].split(';'),
)
candidate = Candidate.objects.get(pk=self.kwargs['pk'])
try:
email.send()
except Exception as err:
messages.error(self.request, "Échec denvoi pour le candidat {0} ({1})".format(candidate, err))
else:
candidate.convocation_date = timezone.now()
candidate.save()
messages.success(self.request,
"Le message de convocation a été envoyé pour le candidat {0}".format(candidate)
)
return super().form_valid(form)

View file

@ -146,6 +146,8 @@ CHARGE_SHEET_TITLE = "Feuille de charge pour l'année scolaire 2017-2018"
MAX_ENS_PERIODS = 1900
MAX_ENS_FORMATION = 250
DATE_LIEU_EXAMEN_EDE = "mercredi 7 mars 2018, à 13h30, salle 405"
if 'TRAVIS' in os.environ:
SECRET_KEY = 'secretkeyfortravistests'
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'

View file

@ -2,6 +2,7 @@ from django.conf.urls import include, url
from django.contrib import admin
from django.views.generic import RedirectView
from candidats import views as candidats_views
from stages import views
urlpatterns = [
@ -21,6 +22,9 @@ urlpatterns = [
url(r'^classes/$', views.KlassListView.as_view(), name='classes'),
url(r'^classes/(?P<pk>\d+)/$', views.KlassView.as_view(), name='class'),
url(r'^candidate/(?P<pk>\d+)/send_convocation/$', candidats_views.SendConvocationView.as_view(),
name='candidate-convocation'),
url(r'^imputations/export/$', views.imputations_export, name='imputations_export'),
url(r'^print/update_form/$', views.print_update_form, name='print_update_form'),
url(r'^general_export/$', views.general_export, name='general-export'),

View file

@ -0,0 +1,20 @@
{% extends "admin/base_site.html" %}
{% load i18n static %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
&rsaquo; Envoi de la convocation EDE
</div>
{% endblock %}
{% block content %}
<h2>{{ candidat }}</h2>
<form name="convocation" action="." method="post">{% csrf_token %}
<table>
{{ form.as_table }}
<tr><td><input type="submit" value="Envoyer"></td></tr>
</table>
</form>
{% endblock %}

View file

@ -0,0 +1,19 @@
{{ candidate_name }},
Nous vous adressons par la présente votre convocation personnelle à la procédure dadmission de la filière Education de lenfance, dipl. ES.
Vous êtes attendu-e à lEcole Santé-social Pierre-Coullery, rue de la Prévoyance 82, 2300 La Chaux-de-Fonds aux dates suivantes:
- {{ date_lieu_examen }}, pour lexamen écrit (durée approx. 4 heures)
- {{ date_entretien }}, en salle {{ salle_entretien }}, pour lentretien dadmission (durée approx. 45 min.).
En cas dempêchement de dernière minute, nous vous remercions dannoncer votre absence au secrétariat (Tél. 032 886 33 00).
{{ rappel }}
Dans lintervalle, nous vous adressons, {{ candidate_civility }}, nos salutations les plus cordiales.
Secrétariat de la filière Education de lenfance, dipl. ES
{{ sender_name }}
{{ sender_email }}
tél. 032 886 33 00

View file

@ -0,0 +1,4 @@
De plus, afin que nous puissions enregistrer définitivement votre inscription, nous vous remercions par avance
de nous faire parvenir, dans les meilleurs délais, le ou les documents suivants:
- {{ documents }}