Remove exam fields on Student (replaced by Examination)
This commit is contained in:
parent
1b0b759c59
commit
fa519cddff
10 changed files with 189 additions and 160 deletions
|
|
@ -131,8 +131,8 @@ class ExaminationInline(admin.StackedInline):
|
|||
'<a class="button" href="{}">Courrier pour l’expert</a> '
|
||||
'<a class="button" href="{}">Mail convocation soutenance</a> '
|
||||
'<a class="button" href="{}">Indemnité au mentor</a>',
|
||||
reverse('print-expert-compens-ede', args=[obj.student.pk]),
|
||||
reverse('student-ede-convocation', args=[obj.student.pk]),
|
||||
reverse('print-expert-compens-ede', args=[obj.pk]),
|
||||
reverse('student-ede-convocation', args=[obj.pk]),
|
||||
reverse('print-mentor-compens-ede', args=[obj.student.pk]),
|
||||
)
|
||||
elif obj and obj.student.is_eds_3():
|
||||
|
|
@ -143,8 +143,8 @@ class ExaminationInline(admin.StackedInline):
|
|||
'<a class="button" href="{}">Courrier pour l’expert</a> '
|
||||
'<a class="button" href="{}">Mail convocation soutenance</a> '
|
||||
'<a class="button" href="{}">Indemnité au mentor</a>',
|
||||
reverse('print-expert-compens-eds', args=[obj.student.pk]),
|
||||
reverse('student-eds-convocation', args=[obj.student.pk]),
|
||||
reverse('print-expert-compens-eds', args=[obj.pk]),
|
||||
reverse('student-eds-convocation', args=[obj.pk]),
|
||||
reverse('print-mentor-compens-ede', args=[obj.student.pk]),
|
||||
)
|
||||
else:
|
||||
|
|
@ -157,7 +157,7 @@ class StudentAdmin(admin.ModelAdmin):
|
|||
ordering = ('last_name', 'first_name')
|
||||
list_filter = (('archived', ArchivedListFilter), ('klass', KlassRelatedListFilter))
|
||||
search_fields = ('last_name', 'first_name', 'pcode', 'city', 'klass__name')
|
||||
autocomplete_fields = ('corporation', 'instructor', 'supervisor', 'mentor', 'expert', 'expert_ep')
|
||||
autocomplete_fields = ('corporation', 'instructor', 'supervisor', 'mentor')
|
||||
readonly_fields = ('report_sem1_sent', 'report_sem2_sent')
|
||||
fieldsets = [
|
||||
(None, {
|
||||
|
|
|
|||
84
stages/migrations/0029_delete_exam_fields_on_student.py
Normal file
84
stages/migrations/0029_delete_exam_fields_on_student.py
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('stages', '0028_remove_last_appointment'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='examedesession',
|
||||
options={'ordering': ['-year', 'season'], 'verbose_name': 'Session d’examen'},
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='student',
|
||||
name='date_confirm_ep_received',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='student',
|
||||
name='date_confirm_received',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='student',
|
||||
name='date_exam',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='student',
|
||||
name='date_exam_ep',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='student',
|
||||
name='date_soutenance_ep_mailed',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='student',
|
||||
name='date_soutenance_mailed',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='student',
|
||||
name='expert_ep',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='student',
|
||||
name='internal_expert',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='student',
|
||||
name='internal_expert_ep',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='student',
|
||||
name='mark',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='student',
|
||||
name='mark_acq',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='student',
|
||||
name='mark_ep',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='student',
|
||||
name='mark_ep_acq',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='student',
|
||||
name='room',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='student',
|
||||
name='room_ep',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='student',
|
||||
name='session',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='student',
|
||||
name='session_ep',
|
||||
),
|
||||
]
|
||||
|
|
@ -252,7 +252,8 @@ class ExamEDESession(models.Model):
|
|||
season = models.CharField('saison', max_length=10)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Session d’examen EDE"
|
||||
verbose_name = "Session d’examen"
|
||||
ordering = ['-year', 'season']
|
||||
|
||||
def __str__(self):
|
||||
return '{0} {1}'.format(self.year, self.season)
|
||||
|
|
@ -315,36 +316,6 @@ class Student(models.Model):
|
|||
on_delete=models.SET_NULL, verbose_name='Référent de PP')
|
||||
referent = models.ForeignKey(Teacher, null=True, blank=True, related_name='rel_referent',
|
||||
on_delete=models.SET_NULL, verbose_name='Référent avant-projet')
|
||||
internal_expert = models.ForeignKey(Teacher, related_name='rel_internal_expert', verbose_name='Expert interne',
|
||||
null=True, blank=True, on_delete=models.SET_NULL)
|
||||
session = models.ForeignKey(
|
||||
ExamEDESession, null=True, blank=True, on_delete=models.SET_NULL, related_name='students_es',
|
||||
)
|
||||
date_exam = models.DateTimeField(blank=True, null=True)
|
||||
room = models.CharField('Salle', max_length=15, blank=True)
|
||||
mark = models.DecimalField('Note', max_digits=3, decimal_places=2, blank=True, null=True)
|
||||
mark_acq = models.CharField('Note', max_length=5, choices=ACQ_MARK_CHOICES, blank=True)
|
||||
date_soutenance_mailed = models.DateTimeField("Convoc. env.", blank=True, null=True)
|
||||
date_confirm_received = models.DateTimeField("Récept. confirm", blank=True, null=True)
|
||||
# ============== Fields for Entretien professionnel =========
|
||||
session_ep = models.ForeignKey(
|
||||
ExamEDESession, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='Session EP',
|
||||
related_name='students_ep',
|
||||
)
|
||||
date_exam_ep = models.DateTimeField("Date exam. EP", blank=True, null=True)
|
||||
room_ep = models.CharField('Salle EP', max_length=15, blank=True)
|
||||
mark_ep = models.DecimalField('Note EP', max_digits=3, decimal_places=2, blank=True, null=True)
|
||||
mark_ep_acq = models.CharField('Note EP', max_length=5, choices=ACQ_MARK_CHOICES, blank=True)
|
||||
internal_expert_ep = models.ForeignKey(
|
||||
Teacher, related_name='rel_internal_expert_ep', verbose_name='Expert interne EP',
|
||||
null=True, blank=True, on_delete=models.SET_NULL
|
||||
)
|
||||
expert_ep = models.ForeignKey(
|
||||
'CorpContact', related_name='rel_expert_ep', verbose_name='Expert externe EP',
|
||||
null=True, blank=True, on_delete=models.SET_NULL
|
||||
)
|
||||
date_soutenance_ep_mailed = models.DateTimeField("Convoc. env.", blank=True, null=True)
|
||||
date_confirm_ep_received = models.DateTimeField("Récept. confirm", blank=True, null=True)
|
||||
# ===============
|
||||
mc_comment = models.TextField("Commentaires", blank=True)
|
||||
|
||||
|
|
@ -411,30 +382,6 @@ class Student(models.Model):
|
|||
def is_eds_3(self):
|
||||
return self.klass and self.klass.section.name == 'EDS' and self.klass.level.name == '3'
|
||||
|
||||
def missing_examination_data(self):
|
||||
missing = []
|
||||
if not self.date_exam:
|
||||
missing.append("La date d’examen est manquante")
|
||||
if not self.room:
|
||||
missing.append("La salle d’examen n’est pas définie")
|
||||
if not self.expert:
|
||||
missing.append("L’expert externe n’est pas défini")
|
||||
if not self.internal_expert:
|
||||
missing.append("L’expert interne n’est pas défini")
|
||||
return missing
|
||||
|
||||
def missing_examination_ep_data(self):
|
||||
missing = []
|
||||
if not self.date_exam_ep:
|
||||
missing.append("La date d’examen est manquante")
|
||||
if not self.room_ep:
|
||||
missing.append("La salle d’examen n’est pas définie")
|
||||
if not self.expert_ep:
|
||||
missing.append("L’expert externe n’est pas défini")
|
||||
if not self.internal_expert_ep:
|
||||
missing.append("L’expert interne n’est pas défini")
|
||||
return missing
|
||||
|
||||
|
||||
class Examination(models.Model):
|
||||
ACQ_MARK_CHOICES = (
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ class CompensationForm:
|
|||
self.story.append(t)
|
||||
self.story.append(Spacer(0, 0.5 * cm))
|
||||
|
||||
def add_accounting_stamp(self, mandat=None):
|
||||
def add_accounting_stamp(self, student, mandat=None):
|
||||
account = otp = total = ''
|
||||
if mandat == self.EXPERT_MANDAT:
|
||||
account = self.EXPERT_ACCOUNT
|
||||
|
|
@ -343,9 +343,9 @@ class CompensationForm:
|
|||
account = self.MENTOR_ACCOUNT
|
||||
total = '500.-'
|
||||
|
||||
if self.student.klass.is_Ede_pe():
|
||||
if student.klass.is_Ede_pe():
|
||||
otp = self.OTP_EDE_PE_OTP
|
||||
elif self.student.klass.is_Ede_ps():
|
||||
elif student.klass.is_Ede_ps():
|
||||
otp = self.OTP_EDE_PS_OTP
|
||||
|
||||
self.story.append((Paragraph(self.points * 2, style_normal)))
|
||||
|
|
@ -433,8 +433,8 @@ class ExpertEdeLetterPdf(CompensationForm, EpcBaseDocTemplate):
|
|||
<br/><br/><br/>
|
||||
"""
|
||||
|
||||
def __init__(self, out, student):
|
||||
self.student = student
|
||||
def __init__(self, out, exam):
|
||||
self.exam = exam
|
||||
super().__init__(out)
|
||||
self.addPageTemplates([
|
||||
PageTemplate(id='FirstPage', frames=[self.page_frame], onPage=self.header),
|
||||
|
|
@ -443,10 +443,10 @@ class ExpertEdeLetterPdf(CompensationForm, EpcBaseDocTemplate):
|
|||
|
||||
def exam_data(self):
|
||||
return {
|
||||
'expert': self.student.expert,
|
||||
'internal_expert': self.student.internal_expert,
|
||||
'date_exam': self.student.date_exam,
|
||||
'room': self.student.room,
|
||||
'expert': self.exam.external_expert,
|
||||
'internal_expert': self.exam.internal_expert,
|
||||
'date_exam': self.exam.date_exam,
|
||||
'room': self.exam.room,
|
||||
}
|
||||
|
||||
def produce(self):
|
||||
|
|
@ -471,7 +471,7 @@ class ExpertEdeLetterPdf(CompensationForm, EpcBaseDocTemplate):
|
|||
title_lower=self.title.lower(),
|
||||
expert_civility=exam_data['expert'].civility,
|
||||
expert_accord=exam_data['expert'].adjective_ending,
|
||||
student_civility_full_name=self.student.civility_full_name,
|
||||
student_civility_full_name=self.exam.student.civility_full_name,
|
||||
), style_normal))
|
||||
|
||||
date_text = "<br/>{0} à l'Ecole Santé-social Pierre-Coullery, salle {1}<br/><br/>"
|
||||
|
|
@ -507,7 +507,7 @@ class ExpertEdeLetterPdf(CompensationForm, EpcBaseDocTemplate):
|
|||
|
||||
self.story.append(Paragraph(
|
||||
"Mandat: Soutenance de {0} {1}, classe {2}".format(
|
||||
self.student.civility, self.student.full_name, self.student.klass
|
||||
self.exam.student.civility, self.exam.student.full_name, self.exam.student.klass
|
||||
), style_normal
|
||||
))
|
||||
self.story.append(Paragraph(
|
||||
|
|
@ -515,7 +515,7 @@ class ExpertEdeLetterPdf(CompensationForm, EpcBaseDocTemplate):
|
|||
))
|
||||
self.story.append(Spacer(0, 2 * cm))
|
||||
|
||||
self.add_accounting_stamp(self.EXPERT_MANDAT)
|
||||
self.add_accounting_stamp(self.exam.student, self.EXPERT_MANDAT)
|
||||
|
||||
self.build(self.story)
|
||||
|
||||
|
|
@ -556,7 +556,7 @@ class MentorCompensationPdfForm(CompensationForm, EpcBaseDocTemplate):
|
|||
))
|
||||
self.story.append(Spacer(0, 3 * cm))
|
||||
|
||||
self.add_accounting_stamp(self.MENTOR_MANDAT)
|
||||
self.add_accounting_stamp(self.student, self.MENTOR_MANDAT)
|
||||
|
||||
self.build(self.story)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ from django.utils.html import escape
|
|||
from candidats.models import Candidate
|
||||
from .models import (
|
||||
Level, Domain, Section, Klass, Option, Period, Student, Corporation, Availability,
|
||||
CorpContact, Teacher, Training, Course,
|
||||
CorpContact, Teacher, Training, Course, Examination, ExamEDESession,
|
||||
)
|
||||
from .utils import school_year
|
||||
|
||||
|
|
@ -211,23 +211,24 @@ class StagesTests(TestCase):
|
|||
|
||||
def test_send_ede_convocation(self):
|
||||
st = Student.objects.get(first_name="Albin")
|
||||
exam = Examination.objects.create(student=st, session=ExamEDESession.objects.create(year=2020, season='1'))
|
||||
self.client.login(username='me', password='mepassword')
|
||||
url = reverse('student-ede-convocation', args=[st.pk])
|
||||
url = reverse('student-ede-convocation', args=[exam.pk])
|
||||
response = self.client.get(url, follow=True)
|
||||
for err in ("La date d’examen est manquante",
|
||||
"La salle d’examen n’est pas définie",
|
||||
"L’expert externe n’est pas défini",
|
||||
"L’expert interne n’est pas défini"):
|
||||
self.assertContains(response, err)
|
||||
st.date_exam = datetime(2018, 6, 28, 12, 00)
|
||||
st.room = "B123"
|
||||
st.expert = CorpContact.objects.get(last_name="Horner")
|
||||
st.internal_expert = Teacher.objects.get(last_name="Caux")
|
||||
st.save()
|
||||
exam.date_exam = datetime(2018, 6, 28, 12, 00)
|
||||
exam.room = "B123"
|
||||
exam.external_expert = CorpContact.objects.get(last_name="Horner")
|
||||
exam.internal_expert = Teacher.objects.get(last_name="Caux")
|
||||
exam.save()
|
||||
response = self.client.get(url, follow=True)
|
||||
self.assertContains(response, "L’expert externe n’a pas de courriel valide !")
|
||||
st.expert.email = "horner@example.org"
|
||||
st.expert.save()
|
||||
exam.external_expert.email = "horner@example.org"
|
||||
exam.external_expert.save()
|
||||
response = self.client.get(url)
|
||||
expected_message = """ Albin Dupond,
|
||||
Madame Julie Caux,
|
||||
|
|
@ -261,8 +262,8 @@ tél. 032 886 33 00
|
|||
'sender': 'me@example.org',
|
||||
})
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
st.refresh_from_db()
|
||||
self.assertIsNotNone(st.date_soutenance_mailed)
|
||||
exam.refresh_from_db()
|
||||
self.assertIsNotNone(exam.date_soutenance_mailed)
|
||||
|
||||
def test_send_eds_convocation(self):
|
||||
klass = Klass.objects.create(
|
||||
|
|
@ -272,9 +273,10 @@ tél. 032 886 33 00
|
|||
first_name="Laurent", last_name="Hots", birth_date="1994-07-12",
|
||||
pcode="2000", city="Neuchâtel", klass=klass
|
||||
)
|
||||
exam = Examination.objects.create(student=st, session=ExamEDESession.objects.create(year=2020, season='1'))
|
||||
|
||||
self.client.login(username='me', password='mepassword')
|
||||
url = reverse('student-eds-convocation', args=[st.pk])
|
||||
url = reverse('student-eds-convocation', args=[exam.pk])
|
||||
response = self.client.get(url, follow=True)
|
||||
for err in ("L’étudiant-e n’a pas de courriel valide",
|
||||
"La date d’examen est manquante",
|
||||
|
|
@ -283,15 +285,16 @@ tél. 032 886 33 00
|
|||
"L’expert interne n’est pas défini"):
|
||||
self.assertContains(response, err)
|
||||
st.email = 'hots@example.org'
|
||||
st.date_exam = datetime(2018, 6, 28, 12, 00)
|
||||
st.room = "B123"
|
||||
st.expert = CorpContact.objects.get(last_name="Horner")
|
||||
st.internal_expert = Teacher.objects.get(last_name="Caux")
|
||||
st.save()
|
||||
exam.date_exam = datetime(2018, 6, 28, 12, 00)
|
||||
exam.room = "B123"
|
||||
exam.external_expert = CorpContact.objects.get(last_name="Horner")
|
||||
exam.internal_expert = Teacher.objects.get(last_name="Caux")
|
||||
exam.save()
|
||||
response = self.client.get(url, follow=True)
|
||||
self.assertContains(response, "L’expert externe n’a pas de courriel valide !")
|
||||
st.expert.email = "horner@example.org"
|
||||
st.expert.save()
|
||||
exam.external_expert.email = "horner@example.org"
|
||||
exam.external_expert.save()
|
||||
response = self.client.get(url)
|
||||
expected_message = """ Laurent Hots,
|
||||
Madame Julie Caux,
|
||||
|
|
@ -325,21 +328,22 @@ tél. 032 886 33 00
|
|||
'sender': 'me@example.org',
|
||||
})
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
st.refresh_from_db()
|
||||
self.assertIsNotNone(st.date_soutenance_mailed)
|
||||
exam.refresh_from_db()
|
||||
self.assertIsNotNone(exam.date_soutenance_mailed)
|
||||
|
||||
def test_print_ede_compensation_forms(self):
|
||||
st = Student.objects.get(first_name="Albin")
|
||||
url = reverse('print-expert-compens-ede', args=[st.pk])
|
||||
exam = Examination.objects.create(student=st, session=ExamEDESession.objects.create(year=2020, season='1'))
|
||||
url = reverse('print-expert-compens-ede', args=[exam.pk])
|
||||
self.client.login(username='me', password='mepassword')
|
||||
response = self.client.get(url, follow=True)
|
||||
self.assertContains(response, "Toutes les informations ne sont pas disponibles")
|
||||
|
||||
st.expert = CorpContact.objects.get(last_name="Horner")
|
||||
st.internal_expert = Teacher.objects.get(last_name="Caux")
|
||||
st.date_exam = datetime(2018, 6, 28, 12, 00)
|
||||
st.room = "B123"
|
||||
st.save()
|
||||
exam.external_expert = CorpContact.objects.get(last_name="Horner")
|
||||
exam.internal_expert = Teacher.objects.get(last_name="Caux")
|
||||
exam.date_exam = datetime(2018, 6, 28, 12, 00)
|
||||
exam.room = "B123"
|
||||
exam.save()
|
||||
self.client.login(username='me', password='mepassword')
|
||||
response = self.client.get(url, follow=True)
|
||||
self.assertEqual(
|
||||
|
|
@ -349,8 +353,8 @@ tél. 032 886 33 00
|
|||
self.assertEqual(response['Content-Type'], 'application/pdf')
|
||||
self.assertGreater(int(response['Content-Length']), 1000)
|
||||
# Expert without corporation
|
||||
st.expert = CorpContact.objects.create(first_name='James', last_name='Bond')
|
||||
st.save()
|
||||
exam.external_expert = CorpContact.objects.create(first_name='James', last_name='Bond')
|
||||
exam.save()
|
||||
response = self.client.get(url, follow=True)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
|
|
@ -373,16 +377,17 @@ tél. 032 886 33 00
|
|||
first_name="Laurent", last_name="Hots", birth_date="1994-07-12",
|
||||
pcode="2000", city="Neuchâtel", klass=klass
|
||||
)
|
||||
url = reverse('print-expert-compens-eds', args=[st.pk])
|
||||
exam = Examination.objects.create(student=st, session=ExamEDESession.objects.create(year=2020, season='1'))
|
||||
url = reverse('print-expert-compens-eds', args=[exam.pk])
|
||||
self.client.login(username='me', password='mepassword')
|
||||
response = self.client.get(url, follow=True)
|
||||
self.assertContains(response, "Toutes les informations ne sont pas disponibles")
|
||||
|
||||
st.expert = CorpContact.objects.get(last_name="Horner")
|
||||
st.internal_expert = Teacher.objects.get(last_name="Caux")
|
||||
st.date_exam = datetime(2018, 6, 28, 12, 00)
|
||||
st.room = "B123"
|
||||
st.save()
|
||||
exam.external_expert = CorpContact.objects.get(last_name="Horner")
|
||||
exam.internal_expert = Teacher.objects.get(last_name="Caux")
|
||||
exam.date_exam = datetime(2018, 6, 28, 12, 00)
|
||||
exam.room = "B123"
|
||||
exam.save()
|
||||
|
||||
response = self.client.get(url, follow=True)
|
||||
self.assertEqual(
|
||||
|
|
@ -392,8 +397,8 @@ tél. 032 886 33 00
|
|||
self.assertEqual(response['Content-Type'], 'application/pdf')
|
||||
self.assertGreater(int(response['Content-Length']), 1000)
|
||||
# Expert without corporation
|
||||
st.expert = CorpContact.objects.create(first_name='James', last_name='Bond')
|
||||
st.save()
|
||||
exam.external_expert = CorpContact.objects.create(first_name='James', last_name='Bond')
|
||||
exam.save()
|
||||
response = self.client.get(url, follow=True)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ from .imports import HPContactsImportView, HPImportView, ImportReportsView, Stud
|
|||
from ..forms import CorporationMergeForm, EmailBaseForm, StudentCommentForm
|
||||
from ..models import (
|
||||
Klass, Section, Student, Teacher, Corporation, CorpContact, Period,
|
||||
Training, Availability
|
||||
Training, Availability, Examination,
|
||||
)
|
||||
from ..pdf import (
|
||||
ChargeSheetPDF, ExpertEdeLetterPdf, ExpertEdsLetterPdf, UpdateDataFormPDF,
|
||||
|
|
@ -401,53 +401,41 @@ class StudentConvocationExaminationView(EmailConfirmationView):
|
|||
title = "Convocation à la soutenance du travail de diplôme"
|
||||
email_template = 'email/student_convocation_EDE.txt'
|
||||
|
||||
@property
|
||||
def expert(self):
|
||||
return self.student.expert
|
||||
|
||||
@property
|
||||
def internal_expert(self):
|
||||
return self.student.internal_expert
|
||||
|
||||
@property
|
||||
def date_soutenance_mailed(self):
|
||||
return self.student.date_soutenance_mailed
|
||||
|
||||
def missing_examination_data(self):
|
||||
return self.student.missing_examination_data()
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.student = Student.objects.get(pk=self.kwargs['pk'])
|
||||
errors = self.missing_examination_data()
|
||||
self.exam = Examination.objects.get(pk=self.kwargs['pk'])
|
||||
errors = self.exam.missing_examination_data()
|
||||
errors.extend(self.check_errors())
|
||||
if errors:
|
||||
messages.error(request, "\n".join(errors))
|
||||
return redirect(reverse("admin:stages_student_change", args=(self.student.pk,)))
|
||||
return redirect(reverse("admin:stages_student_change", args=(self.exam.student.pk,)))
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_person(self):
|
||||
return self.exam.student
|
||||
|
||||
def check_errors(self):
|
||||
errors = []
|
||||
if not self.student.email:
|
||||
if not self.exam.student.email:
|
||||
errors.append("L’étudiant-e n’a pas de courriel valide !")
|
||||
if self.expert and not self.expert.email:
|
||||
if self.exam.external_expert and not self.exam.external_expert.email:
|
||||
errors.append("L’expert externe n’a pas de courriel valide !")
|
||||
if self.internal_expert and not self.internal_expert.email:
|
||||
if self.exam.internal_expert and not self.exam.internal_expert.email:
|
||||
errors.append("L’expert interne n'a pas de courriel valide !")
|
||||
if self.date_soutenance_mailed is not None:
|
||||
if self.exam.date_soutenance_mailed is not None:
|
||||
errors.append("Une convocation a déjà été envoyée !")
|
||||
return errors
|
||||
|
||||
def msg_context(self):
|
||||
# Recipients with ladies first!
|
||||
recip_names = sorted([
|
||||
self.student.civility_full_name,
|
||||
self.expert.civility_full_name,
|
||||
self.internal_expert.civility_full_name,
|
||||
self.exam.student.civility_full_name,
|
||||
self.exam.external_expert.civility_full_name,
|
||||
self.exam.internal_expert.civility_full_name,
|
||||
])
|
||||
titles = [
|
||||
self.student.civility,
|
||||
self.expert.civility,
|
||||
self.internal_expert.civility,
|
||||
self.exam.student.civility,
|
||||
self.exam.external_expert.civility,
|
||||
self.exam.internal_expert.civility,
|
||||
]
|
||||
mme_count = titles.count('Madame')
|
||||
# Civilities, with ladies first!
|
||||
|
|
@ -463,16 +451,18 @@ class StudentConvocationExaminationView(EmailConfirmationView):
|
|||
'recipient1': recip_names[0],
|
||||
'recipient2': recip_names[1],
|
||||
'recipient3': recip_names[2],
|
||||
'student': self.student,
|
||||
'student': self.exam.student,
|
||||
'sender': self.request.user,
|
||||
'global_civilities': civilities,
|
||||
'date_examen': django_format(self.student.date_exam, 'l j F Y à H\hi') if self.student.date_exam else '-',
|
||||
'salle': self.student.room,
|
||||
'date_examen': django_format(self.exam.date_exam, 'l j F Y à H\hi') if self.exam.date_exam else '-',
|
||||
'salle': self.exam.room,
|
||||
'internal_expert': self.exam.internal_expert,
|
||||
'external_expert': self.exam.external_expert,
|
||||
}
|
||||
|
||||
def get_initial(self):
|
||||
initial = super().get_initial()
|
||||
to = [self.student.email, self.expert.email, self.internal_expert.email]
|
||||
to = [self.exam.student.email, self.exam.external_expert.email, self.exam.internal_expert.email]
|
||||
|
||||
initial.update({
|
||||
'cci': self.request.user.email,
|
||||
|
|
@ -484,8 +474,8 @@ class StudentConvocationExaminationView(EmailConfirmationView):
|
|||
return initial
|
||||
|
||||
def on_success(self, student):
|
||||
self.student.date_soutenance_mailed = timezone.now()
|
||||
self.student.save()
|
||||
self.exam.date_soutenance_mailed = timezone.now()
|
||||
self.exam.save()
|
||||
|
||||
|
||||
class StudentConvocationEDSView(StudentConvocationExaminationView):
|
||||
|
|
@ -523,24 +513,24 @@ class PrintExpertEDECompensationForm(PDFBaseView):
|
|||
"""
|
||||
pdf_class = ExpertEdeLetterPdf
|
||||
|
||||
def filename(self, student):
|
||||
return slugify('{0}_{1}'.format(student.last_name, student.first_name)) + '_Expert.pdf'
|
||||
def filename(self, exam):
|
||||
return slugify('{0}_{1}'.format(exam.student.last_name, exam.student.first_name)) + '_Expert.pdf'
|
||||
|
||||
def get_object(self):
|
||||
return Student.objects.get(pk=self.kwargs['pk'])
|
||||
return Examination.objects.get(pk=self.kwargs['pk'])
|
||||
|
||||
def check_object(self, student):
|
||||
missing = student.missing_examination_data()
|
||||
def check_object(self, exam):
|
||||
missing = exam.missing_examination_data()
|
||||
if missing:
|
||||
messages.error(self.request, "\n".join(
|
||||
["Toutes les informations ne sont pas disponibles pour la lettre à l’expert!"]
|
||||
+ missing
|
||||
))
|
||||
return redirect(reverse("admin:stages_student_change", args=(student.pk,)))
|
||||
return redirect(reverse("admin:stages_student_change", args=(exam.student.pk,)))
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
student = self.get_object()
|
||||
response = self.check_object(student)
|
||||
exam = self.get_object()
|
||||
response = self.check_object(exam)
|
||||
if response:
|
||||
return response
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
|
@ -575,14 +565,14 @@ class PrintExpertEDSCompensationForm(PrintExpertEDECompensationForm):
|
|||
"""
|
||||
pdf_class = ExpertEdsLetterPdf
|
||||
|
||||
def check_object(self, student):
|
||||
missing = student.missing_examination_data()
|
||||
def check_object(self, exam):
|
||||
missing = exam.missing_examination_data()
|
||||
if missing:
|
||||
messages.error(self.request, "\n".join(
|
||||
["Toutes les informations ne sont pas disponibles pour la lettre à l’expert!"]
|
||||
+ missing
|
||||
))
|
||||
return redirect(reverse("admin:stages_student_change", args=(student.pk,)))
|
||||
return redirect(reverse("admin:stages_student_change", args=[exam.student.pk]))
|
||||
|
||||
|
||||
class PrintKlassList(ZippedFilesBaseView):
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ class EmailConfirmationBaseView(FormView):
|
|||
success_message = "Le message a été envoyé pour {person}"
|
||||
error_message = "Échec d’envoi pour {person} ({err})"
|
||||
|
||||
def get_person(self):
|
||||
return self.person_model.objects.get(pk=self.kwargs['pk'])
|
||||
|
||||
def form_valid(self, form):
|
||||
email = EmailMessage(
|
||||
subject=form.cleaned_data['subject'],
|
||||
|
|
@ -29,7 +32,7 @@ class EmailConfirmationBaseView(FormView):
|
|||
to=form.cleaned_data['to'].split(';'),
|
||||
bcc=form.cleaned_data['cci'].split(';'),
|
||||
)
|
||||
person = self.person_model.objects.get(pk=self.kwargs['pk'])
|
||||
person = self.get_person()
|
||||
try:
|
||||
email.send()
|
||||
except Exception as err:
|
||||
|
|
@ -46,7 +49,7 @@ class EmailConfirmationBaseView(FormView):
|
|||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'person': self.person_model.objects.get(pk=self.kwargs['pk']),
|
||||
'person': self.get_person(),
|
||||
'title': self.title,
|
||||
})
|
||||
return context
|
||||
|
|
|
|||
|
|
@ -432,7 +432,7 @@ def export_qualification(request, section='ede'):
|
|||
# Data
|
||||
empty_values = [''] * 7
|
||||
for student in Student.objects.filter(klass__name__startswith='3%s' % section.upper(), archived=False
|
||||
).select_related('klass', 'referent', 'training_referent', 'mentor', 'expert', 'internal_expert',
|
||||
).select_related('klass', 'referent', 'training_referent', 'mentor',
|
||||
).prefetch_related('examination_set'
|
||||
).order_by('klass__name', 'last_name'):
|
||||
stud_values = [
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Nous vous informons que la soutenance du travail de diplôme de {{ student.civil
|
|||
- {{ date_examen }} en salle {{ salle }}
|
||||
|
||||
|
||||
Nous informons également {{ student.expert.civility }} {{ student.expert.last_name }} que le mémoire lui est adressé ce jour par courrier postal.
|
||||
Nous informons également {{ external_expert.civility }} {{ external_expert.last_name }} que le mémoire lui est adressé ce jour par courrier postal.
|
||||
|
||||
|
||||
Nous vous remercions de nous confirmer par retour de courriel que vous avez bien reçu ce message et dans l’attente du plaisir de vous rencontrer prochainement, nous vous prions d’agréer, {{ global_civilities }}, nos salutations les meilleures.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Nous vous informons que la soutenance du travail final de {{ student.civility_fu
|
|||
- {{ date_examen }} en salle {{ salle }}
|
||||
|
||||
|
||||
Nous informons également {{ student.expert.civility }} {{ student.expert.last_name }} que le mémoire lui est adressé ce jour par courrier postal.
|
||||
Nous informons également {{ external_expert.civility }} {{ external_expert.last_name }} que le mémoire lui est adressé ce jour par courrier postal.
|
||||
|
||||
|
||||
Nous vous remercions de nous confirmer par retour de courriel que vous avez bien reçu ce message et dans l’attente du plaisir de vous rencontrer prochainement, nous vous prions d’agréer, {{ global_civilities }}, nos salutations les meilleures.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue