Allow different compensation forms (experts/mentors)
This commit is contained in:
parent
fa519cddff
commit
95a30d6731
5 changed files with 105 additions and 48 deletions
|
|
@ -42,19 +42,22 @@ urlpatterns = [
|
|||
name='candidate-validation'),
|
||||
path('candidate/<int:pk>/summary/', candidats_views.inscription_summary, name='candidate-summary'),
|
||||
|
||||
path('student/<int:pk>/examination/mentor/', views.PrintCompensationForm.as_view(), {'typ': 'mentor'},
|
||||
name='print-mentor-compens-form'),
|
||||
path('exam/<int:pk>/indemn/<slug:typ>/', views.PrintCompensationForm.as_view(),
|
||||
name='print-compens-form'),
|
||||
|
||||
# Qualification EDE
|
||||
path('student_ede/<int:pk>/send_convocation/', views.StudentConvocationExaminationView.as_view(),
|
||||
name='student-ede-convocation'),
|
||||
path('student_ede/<int:pk>/examination/expert/', views.PrintExpertEDECompensationForm.as_view(),
|
||||
name='print-expert-compens-ede'),
|
||||
path('student_ede/<int:pk>/examination/mentor/', views.PrintMentorEDECompensationForm.as_view(),
|
||||
name='print-mentor-compens-ede'),
|
||||
name='print-expert-letter-ede'),
|
||||
|
||||
# Qualification EDS
|
||||
path('student_eds/<int:pk>/send_convocation/', views.StudentConvocationEDSView.as_view(),
|
||||
name='student-eds-convocation'),
|
||||
path('student_eds/<int:pk>/examination/expert/', views.PrintExpertEDSCompensationForm.as_view(),
|
||||
name='print-expert-compens-eds'),
|
||||
name='print-expert-letter-eds'),
|
||||
|
||||
path('student/export_qualif/<slug:section>/', views.export.export_qualification,
|
||||
name='export-qualif'),
|
||||
|
|
|
|||
|
|
@ -130,10 +130,12 @@ class ExaminationInline(admin.StackedInline):
|
|||
return format_html(
|
||||
'<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.pk]),
|
||||
'<a class="button" href="{}">Indemnité EP</a> '
|
||||
'<a class="button" href="{}">Indemnité soutenance</a>',
|
||||
reverse('print-expert-letter-ede', args=[obj.pk]),
|
||||
reverse('student-ede-convocation', args=[obj.pk]),
|
||||
reverse('print-mentor-compens-ede', args=[obj.student.pk]),
|
||||
reverse('print-compens-form', args=[obj.pk, 'ep']),
|
||||
reverse('print-compens-form', args=[obj.pk, 'sout']),
|
||||
)
|
||||
elif obj and obj.student.is_eds_3():
|
||||
if obj.missing_examination_data():
|
||||
|
|
@ -142,10 +144,12 @@ class ExaminationInline(admin.StackedInline):
|
|||
return format_html(
|
||||
'<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.pk]),
|
||||
'<a class="button" href="{}">Indemnité EP</a> '
|
||||
'<a class="button" href="{}">Indemnité soutenance</a>',
|
||||
reverse('print-expert-letter-eds', args=[obj.pk]),
|
||||
reverse('student-eds-convocation', args=[obj.pk]),
|
||||
reverse('print-mentor-compens-ede', args=[obj.student.pk]),
|
||||
reverse('print-compens-form', args=[obj.pk, 'ep']),
|
||||
reverse('print-compens-form', args=[obj.pk, 'sout']),
|
||||
)
|
||||
else:
|
||||
return missing_message
|
||||
|
|
@ -158,7 +162,7 @@ class StudentAdmin(admin.ModelAdmin):
|
|||
list_filter = (('archived', ArchivedListFilter), ('klass', KlassRelatedListFilter))
|
||||
search_fields = ('last_name', 'first_name', 'pcode', 'city', 'klass__name')
|
||||
autocomplete_fields = ('corporation', 'instructor', 'supervisor', 'mentor')
|
||||
readonly_fields = ('report_sem1_sent', 'report_sem2_sent')
|
||||
readonly_fields = ('report_sem1_sent', 'report_sem2_sent', 'mentor_indemn')
|
||||
fieldsets = [
|
||||
(None, {
|
||||
'fields': (
|
||||
|
|
@ -176,13 +180,23 @@ class StudentAdmin(admin.ModelAdmin):
|
|||
'fields': (
|
||||
('supervisor', 'supervision_attest_received'),
|
||||
('subject', 'title'),
|
||||
('training_referent', 'referent', 'mentor'),
|
||||
('training_referent', 'referent'),
|
||||
('mentor', 'mentor_indemn'),
|
||||
)
|
||||
}),
|
||||
]
|
||||
actions = ['archive']
|
||||
inlines = [ExaminationInline, SupervisionBillInline]
|
||||
|
||||
def mentor_indemn(self, obj):
|
||||
if obj is None or not obj.mentor:
|
||||
return '-'
|
||||
return format_html(
|
||||
'<a class="button" href="{}">Indemnité au mentor</a>',
|
||||
reverse('print-mentor-compens-form', args=[obj.pk]),
|
||||
)
|
||||
mentor_indemn.short_description = 'Indemnité'
|
||||
|
||||
def get_inlines(self, request, obj=None):
|
||||
if obj is None:
|
||||
return []
|
||||
|
|
|
|||
|
|
@ -286,6 +286,7 @@ class UpdateDataFormPDF(EpcBaseDocTemplate):
|
|||
|
||||
class CompensationForm:
|
||||
"""Mixin class to host paiement formdata."""
|
||||
AMOUNT = ''
|
||||
EXPERT_MANDAT = 'EXPERT'
|
||||
MENTOR_MANDAT = 'MENTOR'
|
||||
EXPERT_ACCOUNT = MENTOR_ACCOUNT = "3'130'0003"
|
||||
|
|
@ -336,12 +337,12 @@ class CompensationForm:
|
|||
self.story.append(Spacer(0, 0.5 * cm))
|
||||
|
||||
def add_accounting_stamp(self, student, mandat=None):
|
||||
account = otp = total = ''
|
||||
account = otp = ''
|
||||
total = self.AMOUNT
|
||||
if mandat == self.EXPERT_MANDAT:
|
||||
account = self.EXPERT_ACCOUNT
|
||||
elif mandat == self.MENTOR_MANDAT:
|
||||
account = self.MENTOR_ACCOUNT
|
||||
total = '500.-'
|
||||
|
||||
if student.klass.is_Ede_pe():
|
||||
otp = self.OTP_EDE_PE_OTP
|
||||
|
|
@ -535,32 +536,59 @@ class ExpertEdsLetterPdf(ExpertEdeLetterPdf):
|
|||
"""
|
||||
|
||||
|
||||
class MentorCompensationPdfForm(CompensationForm, EpcBaseDocTemplate):
|
||||
def __init__(self, out, student):
|
||||
self.student = student
|
||||
super().__init__(out)
|
||||
class CompensationPDFForm(CompensationForm, EpcBaseDocTemplate):
|
||||
def __init__(self, out, *args, **kwargs):
|
||||
super().__init__(out, *args, **kwargs)
|
||||
self.addPageTemplates([
|
||||
PageTemplate(id='FirstPage', frames=[self.page_frame], onPage=self.header_iso)
|
||||
])
|
||||
|
||||
def produce(self):
|
||||
self.add_private_data(self.student.mentor)
|
||||
self.add_private_data(self.expert)
|
||||
|
||||
self.story.append(Paragraph(
|
||||
"Mandat : Mentoring de {0} {1}, classe {2}".format(
|
||||
self.mandat_template.format(
|
||||
self.student.civility, self.student.full_name, self.student.klass
|
||||
), style_normal_center
|
||||
))
|
||||
self.story.append(Paragraph(
|
||||
"Montant forfaitaire de Fr 500.- payable à la fin de la session d'examen", style_normal_center
|
||||
))
|
||||
self.story.append(Paragraph(self.montant_template, style_normal_center))
|
||||
self.story.append(Spacer(0, 3 * cm))
|
||||
|
||||
self.add_accounting_stamp(self.student, self.MENTOR_MANDAT)
|
||||
self.add_accounting_stamp(self.student, self.mandat_type)
|
||||
|
||||
self.build(self.story)
|
||||
|
||||
|
||||
class MentorCompensationPdfForm(CompensationPDFForm):
|
||||
mandat_type = CompensationPDFForm.MENTOR_MANDAT
|
||||
mandat_template = "Mandat : Mentoring de {0} {1}, classe {2}"
|
||||
montant_template = "Montant forfaitaire de Fr 500.- payable à la fin de la session d’examen"
|
||||
AMOUNT = '500.-'
|
||||
|
||||
def __init__(self, out, student):
|
||||
self.student = student
|
||||
self.expert = student.mentor
|
||||
super().__init__(out)
|
||||
|
||||
|
||||
class EntretienProfCompensationPdfForm(CompensationPDFForm):
|
||||
mandat_type = CompensationPDFForm.EXPERT_MANDAT
|
||||
mandat_template = "Mandat : Entretien professionnel pour {0} {1}, classe {2}"
|
||||
montant_template = "Montant forfaitaire de Fr 200.- payable à la fin de la session d’examen"
|
||||
AMOUNT = '200.-'
|
||||
|
||||
def __init__(self, out, exam):
|
||||
self.student = exam.student
|
||||
self.expert = exam.external_expert
|
||||
super().__init__(out)
|
||||
|
||||
|
||||
class SoutenanceCompensationPdfForm(EntretienProfCompensationPdfForm):
|
||||
mandat_template = "Mandat : Soutenance pour {0} {1}, classe {2}"
|
||||
montant_template = "Montant forfaitaire de Fr 200.- payable à la fin de la session d’examen"
|
||||
AMOUNT = '200.-'
|
||||
|
||||
|
||||
class KlassListPDF(EpcBaseDocTemplate):
|
||||
"""
|
||||
Génération des rôles de classes en pdf.
|
||||
|
|
|
|||
|
|
@ -334,7 +334,7 @@ tél. 032 886 33 00
|
|||
def test_print_ede_compensation_forms(self):
|
||||
st = Student.objects.get(first_name="Albin")
|
||||
exam = Examination.objects.create(student=st, session=ExamEDESession.objects.create(year=2020, season='1'))
|
||||
url = reverse('print-expert-compens-ede', args=[exam.pk])
|
||||
url = reverse('print-expert-letter-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")
|
||||
|
|
@ -361,7 +361,7 @@ tél. 032 886 33 00
|
|||
# Mentor form
|
||||
st.mentor = CorpContact.objects.get(last_name="Horner")
|
||||
st.save()
|
||||
response = self.client.get(reverse('print-mentor-compens-ede', args=[st.pk]), follow=True)
|
||||
response = self.client.get(reverse('print-mentor-compens-form', args=[st.pk]), follow=True)
|
||||
self.assertEqual(
|
||||
response['Content-Disposition'],
|
||||
'attachment; filename="dupond_albin_Indemn_mentor.pdf"'
|
||||
|
|
@ -378,7 +378,7 @@ tél. 032 886 33 00
|
|||
pcode="2000", city="Neuchâtel", klass=klass
|
||||
)
|
||||
exam = Examination.objects.create(student=st, session=ExamEDESession.objects.create(year=2020, season='1'))
|
||||
url = reverse('print-expert-compens-eds', args=[exam.pk])
|
||||
url = reverse('print-expert-letter-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")
|
||||
|
|
|
|||
|
|
@ -26,10 +26,7 @@ from ..models import (
|
|||
Klass, Section, Student, Teacher, Corporation, CorpContact, Period,
|
||||
Training, Availability, Examination,
|
||||
)
|
||||
from ..pdf import (
|
||||
ChargeSheetPDF, ExpertEdeLetterPdf, ExpertEdsLetterPdf, UpdateDataFormPDF,
|
||||
MentorCompensationPdfForm, KlassListPDF,
|
||||
)
|
||||
from .. import pdf
|
||||
from ..utils import school_year_start
|
||||
|
||||
|
||||
|
|
@ -501,8 +498,8 @@ class PrintUpdateForm(ZippedFilesBaseView):
|
|||
for klass in Klass.objects.filter(level__gte=2
|
||||
).exclude(section__name='MP_ASSC').exclude(section__name='MP_ASE'):
|
||||
buff = io.BytesIO()
|
||||
pdf = UpdateDataFormPDF(buff, self.return_date)
|
||||
pdf.produce(klass)
|
||||
pdf_doc = pdf.UpdateDataFormPDF(buff, self.return_date)
|
||||
pdf_doc.produce(klass)
|
||||
yield ('{0}.pdf'.format(klass.name), buff.getvalue())
|
||||
|
||||
|
||||
|
|
@ -511,7 +508,7 @@ class PrintExpertEDECompensationForm(PDFBaseView):
|
|||
Imprime le PDF à envoyer à l'expert EDE en accompagnement du
|
||||
travail de diplôme
|
||||
"""
|
||||
pdf_class = ExpertEdeLetterPdf
|
||||
pdf_class = pdf.ExpertEdeLetterPdf
|
||||
|
||||
def filename(self, exam):
|
||||
return slugify('{0}_{1}'.format(exam.student.last_name, exam.student.first_name)) + '_Expert.pdf'
|
||||
|
|
@ -536,25 +533,40 @@ class PrintExpertEDECompensationForm(PDFBaseView):
|
|||
return super().get(request, *args, **kwargs)
|
||||
|
||||
|
||||
class PrintMentorEDECompensationForm(PDFBaseView):
|
||||
class PrintCompensationForm(PDFBaseView):
|
||||
"""
|
||||
Imprime le PDF à envoyer au mentor EDE pour le mentoring
|
||||
"""
|
||||
pdf_class = MentorCompensationPdfForm
|
||||
@property
|
||||
def pdf_class(self):
|
||||
return {
|
||||
'mentor': pdf.MentorCompensationPdfForm,
|
||||
'ep': pdf.EntretienProfCompensationPdfForm,
|
||||
'sout': pdf.SoutenanceCompensationPdfForm,
|
||||
}.get(self.typ)
|
||||
|
||||
def filename(self, student):
|
||||
def filename(self, obj):
|
||||
student = obj if self.typ == 'mentor' else obj.student
|
||||
return slugify(
|
||||
'{0}_{1}'.format(student.last_name, student.first_name)
|
||||
) + '_Indemn_mentor.pdf'
|
||||
) + f'_Indemn_{self.typ}.pdf'
|
||||
|
||||
def get_object(self):
|
||||
return Student.objects.get(pk=self.kwargs['pk'])
|
||||
model = Student if self.typ == 'mentor' else Examination
|
||||
return model.objects.get(pk=self.kwargs['pk'])
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
student = self.get_object()
|
||||
if not student.mentor:
|
||||
messages.error(request, "Aucun mentor n'est attribué à cet étudiant")
|
||||
return redirect(reverse("admin:stages_student_change", args=(student.pk,)))
|
||||
self.typ = self.kwargs['typ']
|
||||
if self.typ == 'mentor':
|
||||
student = self.get_object()
|
||||
if not student.mentor:
|
||||
messages.error(request, "Aucun mentor n’est attribué à cet étudiant")
|
||||
return redirect(reverse("admin:stages_student_change", args=(student.pk,)))
|
||||
else:
|
||||
exam = self.get_object()
|
||||
if not exam.external_expert:
|
||||
messages.error(request, "Aucun expert n’est attribué à cet examen")
|
||||
return redirect(reverse("admin:stages_student_change", args=(exam.student.pk,)))
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
|
||||
|
|
@ -563,7 +575,7 @@ class PrintExpertEDSCompensationForm(PrintExpertEDECompensationForm):
|
|||
Imprime le PDF à envoyer à l'expert EDS en accompagnement du
|
||||
travail final.
|
||||
"""
|
||||
pdf_class = ExpertEdsLetterPdf
|
||||
pdf_class = pdf.ExpertEdsLetterPdf
|
||||
|
||||
def check_object(self, exam):
|
||||
missing = exam.missing_examination_data()
|
||||
|
|
@ -581,8 +593,8 @@ class PrintKlassList(ZippedFilesBaseView):
|
|||
def generate_files(self):
|
||||
for klass in Klass.active.order_by('section', 'name'):
|
||||
buff = io.BytesIO()
|
||||
pdf = KlassListPDF(buff, klass)
|
||||
pdf.produce(klass)
|
||||
pdf_doc = pdf.KlassListPDF(buff, klass)
|
||||
pdf_doc.produce(klass)
|
||||
filename = slugify(klass.name + '.pdf')
|
||||
yield (filename, buff.getvalue())
|
||||
|
||||
|
|
@ -599,7 +611,7 @@ class PrintChargeSheet(ZippedFilesBaseView):
|
|||
for teacher in queryset:
|
||||
activities = teacher.calc_activity()
|
||||
buff = io.BytesIO()
|
||||
pdf = ChargeSheetPDF(buff, teacher)
|
||||
pdf.produce(activities)
|
||||
pdf_doc = pdf.ChargeSheetPDF(buff, teacher)
|
||||
pdf_doc.produce(activities)
|
||||
filename = slugify('{0}_{1}'.format(teacher.last_name, teacher.first_name)) + '.pdf'
|
||||
yield (filename, buff.getvalue())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue