2018-01-26 19:15:10 +01:00
|
|
|
|
import os
|
|
|
|
|
|
import tempfile
|
|
|
|
|
|
import zipfile
|
2017-10-19 09:29:08 +02:00
|
|
|
|
from collections import OrderedDict
|
2017-11-24 08:39:10 +01:00
|
|
|
|
from datetime import date
|
2017-10-19 09:29:08 +02:00
|
|
|
|
|
2017-10-18 18:52:59 +02:00
|
|
|
|
from django import forms
|
|
|
|
|
|
from django.contrib import admin
|
2018-01-24 11:06:22 +01:00
|
|
|
|
from django.core.mail import EmailMessage
|
2017-10-19 09:29:08 +02:00
|
|
|
|
from django.db.models import BooleanField
|
2018-01-26 19:15:10 +01:00
|
|
|
|
from django.http import HttpResponse
|
2017-11-24 08:39:10 +01:00
|
|
|
|
from django.template import loader
|
2018-01-26 18:19:16 +01:00
|
|
|
|
from django.urls import reverse
|
2017-10-19 09:29:08 +02:00
|
|
|
|
|
|
|
|
|
|
from stages.exports import OpenXMLExport
|
2018-01-25 15:51:51 +01:00
|
|
|
|
from .models import Candidate, Interview, GENDER_CHOICES
|
2018-01-26 19:15:10 +01:00
|
|
|
|
from .pdf import InscriptionSummaryPDF
|
2017-10-19 09:29:08 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def export_candidates(modeladmin, request, queryset):
|
|
|
|
|
|
"""
|
|
|
|
|
|
Export all candidates fields.
|
|
|
|
|
|
"""
|
|
|
|
|
|
export_fields = OrderedDict(
|
|
|
|
|
|
[(f.verbose_name, f.name) for f in Candidate._meta.get_fields() if f.name != 'ID']
|
|
|
|
|
|
)
|
|
|
|
|
|
boolean_fields = [f.name for f in Candidate._meta.get_fields() if isinstance(f, BooleanField)]
|
|
|
|
|
|
export_fields['Employeur'] = 'corporation__name'
|
|
|
|
|
|
export_fields['Employeur_localite'] = 'corporation__city'
|
|
|
|
|
|
export_fields['FEE/FPP'] = 'instructor__last_name'
|
|
|
|
|
|
|
|
|
|
|
|
export = OpenXMLExport('Exportation')
|
|
|
|
|
|
export.write_line(export_fields.keys(), bold=True)
|
|
|
|
|
|
for cand in queryset.values_list(*export_fields.values()):
|
|
|
|
|
|
values = []
|
|
|
|
|
|
for value, field_name in zip(cand, export_fields.values()):
|
|
|
|
|
|
if field_name == 'gender':
|
|
|
|
|
|
value = dict(GENDER_CHOICES)[value]
|
|
|
|
|
|
if field_name in boolean_fields:
|
|
|
|
|
|
value = 'Oui' if value else ''
|
|
|
|
|
|
values.append(value)
|
|
|
|
|
|
export.write_line(values)
|
|
|
|
|
|
return export.get_http_response('candidats_export')
|
2017-10-18 18:52:59 +02:00
|
|
|
|
|
2017-10-19 09:29:08 +02:00
|
|
|
|
export_candidates.short_description = "Exporter les candidats sélectionnés"
|
2017-10-18 18:52:59 +02:00
|
|
|
|
|
|
|
|
|
|
|
2017-11-24 08:39:10 +01:00
|
|
|
|
def send_confirmation_mail(modeladmin, request, queryset):
|
|
|
|
|
|
from_email = request.user.email
|
|
|
|
|
|
subject = "Confirmation de votre inscription à l'Ecole Santé-social Pierre-Coullery"
|
2018-01-12 15:15:15 +01:00
|
|
|
|
email_sent = 0
|
2017-11-24 08:39:10 +01:00
|
|
|
|
|
|
|
|
|
|
for candidate in queryset.filter(
|
|
|
|
|
|
deposite_date__isnull=False, date_confirmation_mail__isnull=True, canceled_file=False):
|
|
|
|
|
|
to = [candidate.email]
|
2017-12-05 15:51:28 +01:00
|
|
|
|
|
2017-11-24 08:39:10 +01:00
|
|
|
|
if candidate.corporation and candidate.corporation.email:
|
|
|
|
|
|
to.append(candidate.corporation.email)
|
|
|
|
|
|
if candidate.instructor and candidate.instructor.email:
|
|
|
|
|
|
to.append(candidate.instructor.email)
|
|
|
|
|
|
|
|
|
|
|
|
context = {
|
2017-12-05 15:51:28 +01:00
|
|
|
|
'candidate_civility': candidate.civility,
|
2017-11-24 08:39:10 +01:00
|
|
|
|
'candidate_name': " ".join([candidate.civility, candidate.first_name, candidate.last_name]),
|
|
|
|
|
|
'section': candidate.section,
|
|
|
|
|
|
'sender_name': " ".join([request.user.first_name, request.user.last_name]),
|
|
|
|
|
|
'sender_email': from_email,
|
|
|
|
|
|
}
|
2017-12-05 15:51:28 +01:00
|
|
|
|
|
|
|
|
|
|
if candidate.section == 'EDE':
|
|
|
|
|
|
body = loader.render_to_string('email/candidate_confirm_EDE.txt', context)
|
|
|
|
|
|
else:
|
|
|
|
|
|
body = loader.render_to_string('email/candidate_confirm_FE.txt', context)
|
2018-01-24 11:06:22 +01:00
|
|
|
|
|
|
|
|
|
|
email = EmailMessage(
|
|
|
|
|
|
subject=subject,
|
|
|
|
|
|
body=body,
|
|
|
|
|
|
from_email=from_email,
|
|
|
|
|
|
to=to,
|
|
|
|
|
|
bcc=[from_email]
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2017-11-24 08:39:10 +01:00
|
|
|
|
try:
|
2018-01-24 11:06:22 +01:00
|
|
|
|
email.send()
|
2018-01-12 15:15:15 +01:00
|
|
|
|
email_sent += 1
|
2017-11-24 08:39:10 +01:00
|
|
|
|
except Exception as err:
|
2017-12-06 12:23:12 +01:00
|
|
|
|
modeladmin.message_user(request, "Échec d’envoi pour le candidat {0} ({1})".format(candidate, err))
|
2017-11-24 08:39:10 +01:00
|
|
|
|
else:
|
|
|
|
|
|
candidate.date_confirmation_mail = date.today()
|
|
|
|
|
|
candidate.save()
|
2018-01-12 15:15:15 +01:00
|
|
|
|
modeladmin.message_user(request, "%d messages de confirmation ont été envoyés." % email_sent)
|
2017-11-24 08:39:10 +01:00
|
|
|
|
send_confirmation_mail.short_description = "Envoyer email de confirmation"
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-01-26 19:15:10 +01:00
|
|
|
|
def print_summary(modeladmin, request, queryset):
|
|
|
|
|
|
"""
|
|
|
|
|
|
Print a summary of inscription
|
|
|
|
|
|
"""
|
|
|
|
|
|
filename = 'archive_InscriptionResumes.zip'
|
|
|
|
|
|
path = os.path.join(tempfile.gettempdir(), filename)
|
|
|
|
|
|
|
|
|
|
|
|
with zipfile.ZipFile(path, mode='w', compression=zipfile.ZIP_DEFLATED) as filezip:
|
|
|
|
|
|
for candidate in queryset:
|
|
|
|
|
|
pdf = InscriptionSummaryPDF(candidate)
|
|
|
|
|
|
pdf.produce(candidate)
|
|
|
|
|
|
filezip.write(pdf.filename)
|
|
|
|
|
|
|
|
|
|
|
|
with open(filezip.filename, mode='rb') as fh:
|
|
|
|
|
|
response = HttpResponse(fh.read(), content_type='application/zip')
|
|
|
|
|
|
response['Content-Disposition'] = 'attachment; filename="{0}"'.format(filename)
|
|
|
|
|
|
return response
|
|
|
|
|
|
print_summary.short_description = 'Imprimer résumé'
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-10-18 18:52:59 +02:00
|
|
|
|
class CandidateAdminForm(forms.ModelForm):
|
2018-01-25 15:51:51 +01:00
|
|
|
|
interview = forms.ModelChoiceField(queryset=Interview.objects.all(), required=False)
|
|
|
|
|
|
|
2017-10-18 18:52:59 +02:00
|
|
|
|
class Meta:
|
|
|
|
|
|
model = Candidate
|
|
|
|
|
|
widgets = {
|
|
|
|
|
|
'comment': forms.Textarea(attrs={'cols': 100, 'rows': 1}),
|
|
|
|
|
|
'pcode': forms.TextInput(attrs={'size': 10}),
|
|
|
|
|
|
}
|
|
|
|
|
|
fields = '__all__'
|
|
|
|
|
|
|
2018-01-25 15:51:51 +01:00
|
|
|
|
def __init__(self, *args, **kwargs):
|
2018-01-30 09:32:32 +01:00
|
|
|
|
if kwargs.get('instance'):
|
|
|
|
|
|
try:
|
|
|
|
|
|
kwargs['initial'] = {'interview': kwargs['instance'].interview}
|
|
|
|
|
|
except Interview.DoesNotExist:
|
|
|
|
|
|
pass
|
2018-01-25 15:51:51 +01:00
|
|
|
|
return super().__init__(*args, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
def save(self, **kwargs):
|
|
|
|
|
|
obj = super().save(**kwargs)
|
|
|
|
|
|
if 'interview' in self.changed_data:
|
|
|
|
|
|
if self.cleaned_data['interview'] is None:
|
|
|
|
|
|
self.initial['interview'].candidat = None
|
|
|
|
|
|
self.initial['interview'].save()
|
|
|
|
|
|
else:
|
|
|
|
|
|
self.cleaned_data['interview'].candidat = obj
|
|
|
|
|
|
self.cleaned_data['interview'].save()
|
|
|
|
|
|
return obj
|
|
|
|
|
|
|
2017-10-18 18:52:59 +02:00
|
|
|
|
|
|
|
|
|
|
class CandidateAdmin(admin.ModelAdmin):
|
|
|
|
|
|
form = CandidateAdminForm
|
2018-01-26 18:19:16 +01:00
|
|
|
|
list_display = ('last_name', 'first_name', 'section', 'confirm_mail', 'convocation')
|
2017-10-18 18:52:59 +02:00
|
|
|
|
list_filter = ('section', 'option')
|
|
|
|
|
|
readonly_fields = ('total_result_points', 'total_result_mark', 'date_confirmation_mail')
|
2018-01-26 19:15:10 +01:00
|
|
|
|
actions = [export_candidates, send_confirmation_mail, print_summary]
|
2017-10-18 18:52:59 +02:00
|
|
|
|
fieldsets = (
|
|
|
|
|
|
(None, {
|
|
|
|
|
|
'fields': (('first_name', 'last_name', 'gender'),
|
|
|
|
|
|
('street', 'pcode', 'city', 'district'),
|
|
|
|
|
|
('mobile', 'email'),
|
2017-11-21 17:34:15 +01:00
|
|
|
|
('birth_date', 'avs', 'handicap', 'has_photo'),
|
2017-10-18 18:52:59 +02:00
|
|
|
|
('section', 'option'),
|
|
|
|
|
|
('corporation', 'instructor'),
|
|
|
|
|
|
('deposite_date', 'date_confirmation_mail', 'canceled_file'),
|
|
|
|
|
|
'comment',
|
|
|
|
|
|
),
|
|
|
|
|
|
}),
|
|
|
|
|
|
("FE", {
|
|
|
|
|
|
'classes': ('collapse',),
|
|
|
|
|
|
'fields': (('exemption_ecg', 'integration_second_year', 'validation_sfpo'),),
|
|
|
|
|
|
}),
|
|
|
|
|
|
("EDE/EDS", {
|
|
|
|
|
|
'classes': ('collapse',),
|
2018-01-26 16:14:00 +01:00
|
|
|
|
'fields': (('diploma', 'diploma_detail', 'diploma_status'),
|
|
|
|
|
|
('registration_form', 'certificate_of_payement', 'cv', 'police_record', 'reflexive_text',
|
|
|
|
|
|
'marks_certificate', 'residence_permits', 'aes_accords'),
|
2018-02-01 10:09:18 +01:00
|
|
|
|
('certif_of_800_childhood', 'certif_of_800_general', 'work_certificate'),
|
2018-01-26 16:14:00 +01:00
|
|
|
|
('promise', 'contract', 'activity_rate'),
|
|
|
|
|
|
('interview',),
|
|
|
|
|
|
('examination_result', 'interview_result', 'file_result', 'total_result_points',
|
|
|
|
|
|
'total_result_mark')
|
|
|
|
|
|
),
|
2017-10-18 18:52:59 +02:00
|
|
|
|
}),
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2017-11-23 18:09:59 +01:00
|
|
|
|
def confirm_mail(self, obj):
|
2017-10-18 18:52:59 +02:00
|
|
|
|
return obj.date_confirmation_mail is not None
|
2017-11-23 18:09:59 +01:00
|
|
|
|
confirm_mail.boolean = True
|
2017-10-18 18:52:59 +02:00
|
|
|
|
|
2018-01-26 18:19:16 +01:00
|
|
|
|
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
|
|
|
|
|
|
|
2018-01-25 15:51:51 +01:00
|
|
|
|
|
|
|
|
|
|
class InterviewAdmin(admin.ModelAdmin):
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-10-18 18:52:59 +02:00
|
|
|
|
admin.site.register(Candidate, CandidateAdmin)
|
2018-01-25 15:51:51 +01:00
|
|
|
|
admin.site.register(Interview, InterviewAdmin)
|