2018-08-15 15:47:44 +02:00
|
|
|
|
from collections import OrderedDict
|
2019-10-15 09:54:38 +02:00
|
|
|
|
from copy import deepcopy
|
2018-08-15 15:47:44 +02:00
|
|
|
|
|
2012-11-13 16:55:46 +01:00
|
|
|
|
from django import forms
|
2012-11-06 17:54:33 +01:00
|
|
|
|
from django.contrib import admin
|
2020-09-11 14:58:28 +02:00
|
|
|
|
from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME
|
2019-02-21 09:46:44 +01:00
|
|
|
|
from django.contrib.auth.admin import GroupAdmin as AuthGroupAdmin
|
|
|
|
|
|
from django.contrib.auth.models import Group
|
2012-11-13 16:55:46 +01:00
|
|
|
|
from django.db import models
|
2018-06-16 19:57:27 +02:00
|
|
|
|
from django.http import HttpResponse, HttpResponseRedirect
|
2018-04-12 12:17:37 +02:00
|
|
|
|
from django.urls import reverse
|
2019-02-21 09:46:44 +01:00
|
|
|
|
from django.utils.html import format_html, format_html_join
|
2019-10-15 09:54:38 +02:00
|
|
|
|
from django.utils.safestring import mark_safe
|
2012-11-06 17:54:33 +01:00
|
|
|
|
|
2018-02-05 09:38:14 +01:00
|
|
|
|
from .models import (
|
2019-02-06 17:02:09 +01:00
|
|
|
|
Teacher, Option, Student, StudentFile, Section, Level, Klass, Corporation,
|
2017-07-14 10:19:12 +02:00
|
|
|
|
CorpContact, Domain, Period, Availability, Training, Course,
|
2020-02-13 09:39:27 +01:00
|
|
|
|
LogBookReason, LogBook, ExamEDESession, Examination, SupervisionBill
|
2017-07-11 23:01:46 +02:00
|
|
|
|
)
|
2018-08-15 15:47:44 +02:00
|
|
|
|
from .views.export import OpenXMLExport
|
2017-07-14 18:47:56 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def print_charge_sheet(modeladmin, request, queryset):
|
2018-06-16 19:57:27 +02:00
|
|
|
|
return HttpResponseRedirect(
|
|
|
|
|
|
reverse('print-charge-sheet') + '?ids=%s' % ",".join(
|
2020-09-11 14:58:28 +02:00
|
|
|
|
request.POST.getlist(ACTION_CHECKBOX_NAME)
|
2018-06-16 19:57:27 +02:00
|
|
|
|
)
|
|
|
|
|
|
)
|
2017-07-14 18:47:56 +02:00
|
|
|
|
print_charge_sheet.short_description = "Imprimer les feuilles de charge"
|
2012-11-06 17:54:33 +01:00
|
|
|
|
|
|
|
|
|
|
|
2016-01-19 11:30:56 +01:00
|
|
|
|
class ArchivedListFilter(admin.BooleanFieldListFilter):
|
|
|
|
|
|
"""
|
|
|
|
|
|
Default filter that shows by default unarchived elements.
|
|
|
|
|
|
"""
|
|
|
|
|
|
def __init__(self, request, params, *args, **kwargs):
|
|
|
|
|
|
super().__init__(request, params, *args, **kwargs)
|
|
|
|
|
|
if self.lookup_val is None:
|
|
|
|
|
|
self.lookup_val = '0'
|
|
|
|
|
|
|
|
|
|
|
|
def choices(self, cl):
|
|
|
|
|
|
# Removing the "all" choice
|
|
|
|
|
|
return list(super().choices(cl))[1:]
|
|
|
|
|
|
|
|
|
|
|
|
def queryset(self, request, queryset):
|
|
|
|
|
|
if not self.used_parameters:
|
|
|
|
|
|
self.used_parameters[self.lookup_kwarg] = '0'
|
|
|
|
|
|
return super().queryset(request, queryset)
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-08-21 14:37:11 +02:00
|
|
|
|
class KlassRelatedListFilter(admin.RelatedFieldListFilter):
|
|
|
|
|
|
def field_choices(self, field, request, model_admin):
|
|
|
|
|
|
return [
|
2018-06-16 18:14:29 +02:00
|
|
|
|
(k.pk, k.name) for k in Klass.active.order_by('name')
|
2017-08-21 14:37:11 +02:00
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-02-05 09:46:36 +01:00
|
|
|
|
class StudentInline(admin.StackedInline):
|
|
|
|
|
|
model = Student
|
|
|
|
|
|
ordering = ('last_name', 'first_name')
|
|
|
|
|
|
fields = (
|
|
|
|
|
|
('last_name', 'first_name', 'birth_date'),
|
|
|
|
|
|
('pcode', 'city', 'tel', 'mobile', 'email'),
|
|
|
|
|
|
)
|
|
|
|
|
|
can_delete = False
|
|
|
|
|
|
extra = 0
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-11-09 12:12:44 +01:00
|
|
|
|
@admin.register(Section)
|
|
|
|
|
|
class SectionAdmin(admin.ModelAdmin):
|
|
|
|
|
|
list_display = ['name', 'has_stages']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@admin.register(Klass)
|
2013-01-02 14:40:24 +01:00
|
|
|
|
class KlassAdmin(admin.ModelAdmin):
|
2022-07-07 15:59:55 +02:00
|
|
|
|
list_display = ('name', 'section', 'level')
|
2013-01-02 14:40:24 +01:00
|
|
|
|
ordering = ('name',)
|
2017-07-11 23:15:00 +02:00
|
|
|
|
list_filter = ('section', 'level',)
|
2019-02-06 17:46:24 +01:00
|
|
|
|
fields = (
|
|
|
|
|
|
('name',),
|
|
|
|
|
|
('section', 'level'),
|
|
|
|
|
|
('teacher', 'teacher_ecg', 'teacher_eps'),
|
|
|
|
|
|
)
|
2018-02-05 09:46:36 +01:00
|
|
|
|
inlines = [StudentInline]
|
2013-01-02 14:40:24 +01:00
|
|
|
|
|
|
|
|
|
|
|
2018-02-19 10:28:14 +01:00
|
|
|
|
class LogBookInline(admin.TabularInline):
|
|
|
|
|
|
model = LogBook
|
|
|
|
|
|
ordering = ('input_date',)
|
|
|
|
|
|
fields = ('start_date', 'end_date', 'reason', 'comment', 'nb_period')
|
|
|
|
|
|
extra = 0
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-11-09 12:12:44 +01:00
|
|
|
|
@admin.register(Teacher)
|
2017-07-11 23:01:46 +02:00
|
|
|
|
class TeacherAdmin(admin.ModelAdmin):
|
2018-02-19 10:28:14 +01:00
|
|
|
|
list_display = ('__str__', 'abrev', 'email', 'contract', 'rate', 'total_logbook', 'archived')
|
2018-02-19 09:37:13 +01:00
|
|
|
|
list_filter = (('archived', ArchivedListFilter), 'contract')
|
2020-02-13 09:39:27 +01:00
|
|
|
|
search_fields = ('last_name', 'first_name', 'email')
|
2018-02-19 09:37:13 +01:00
|
|
|
|
fields = (('civility', 'last_name', 'first_name', 'abrev'),
|
|
|
|
|
|
('birth_date', 'email', 'ext_id'),
|
2019-04-03 18:01:20 +02:00
|
|
|
|
('contract', 'rate', 'can_examinate', 'archived'),
|
2019-02-07 09:47:44 +01:00
|
|
|
|
('previous_report', 'next_report', 'total_logbook'),
|
|
|
|
|
|
('user'))
|
2018-02-19 10:28:14 +01:00
|
|
|
|
readonly_fields = ('total_logbook',)
|
2017-07-14 18:47:56 +02:00
|
|
|
|
actions = [print_charge_sheet]
|
2018-02-19 10:28:14 +01:00
|
|
|
|
inlines = [LogBookInline]
|
2017-07-11 23:01:46 +02:00
|
|
|
|
|
|
|
|
|
|
|
2018-04-26 07:54:29 +02:00
|
|
|
|
class SupervisionBillInline(admin.TabularInline):
|
|
|
|
|
|
model = SupervisionBill
|
|
|
|
|
|
extra = 0
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-02-13 09:39:27 +01:00
|
|
|
|
class ExaminationInline(admin.StackedInline):
|
|
|
|
|
|
model = Examination
|
|
|
|
|
|
extra = 1
|
|
|
|
|
|
verbose_name = "Procédure de qualification"
|
|
|
|
|
|
verbose_name_plural = "Procédures de qualification"
|
|
|
|
|
|
autocomplete_fields = ('internal_expert', 'external_expert')
|
|
|
|
|
|
fields = (('session', 'type_exam', 'date_exam', 'room'),
|
|
|
|
|
|
('internal_expert', 'external_expert'),
|
|
|
|
|
|
('mark', 'mark_acq'),
|
|
|
|
|
|
('examination_actions'),
|
|
|
|
|
|
('date_soutenance_mailed', 'date_confirm_received'),)
|
|
|
|
|
|
readonly_fields = (
|
|
|
|
|
|
'examination_actions', 'date_soutenance_mailed'
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def examination_actions(self, obj):
|
|
|
|
|
|
missing_message = mark_safe(
|
|
|
|
|
|
'<div class="warning">Veuillez compléter les informations '
|
|
|
|
|
|
'd’examen (date/salle/experts) pour accéder aux boutons d’impression.</div>'
|
|
|
|
|
|
)
|
2020-08-31 17:58:34 +02:00
|
|
|
|
if obj and obj.student.is_ede():
|
2020-02-13 09:39:27 +01:00
|
|
|
|
if obj.missing_examination_data():
|
|
|
|
|
|
return missing_message
|
|
|
|
|
|
else:
|
|
|
|
|
|
return format_html(
|
|
|
|
|
|
'<a class="button" href="{}">Courrier pour l’expert</a> '
|
|
|
|
|
|
'<a class="button" href="{}">Mail convocation soutenance</a> '
|
2020-04-23 12:08:18 +02:00
|
|
|
|
'<a class="button" href="{}">Indemnité EP</a> '
|
|
|
|
|
|
'<a class="button" href="{}">Indemnité soutenance</a>',
|
|
|
|
|
|
reverse('print-expert-letter-ede', args=[obj.pk]),
|
2020-04-21 15:29:28 +02:00
|
|
|
|
reverse('student-ede-convocation', args=[obj.pk]),
|
2020-04-23 12:08:18 +02:00
|
|
|
|
reverse('print-compens-form', args=[obj.pk, 'ep']),
|
|
|
|
|
|
reverse('print-compens-form', args=[obj.pk, 'sout']),
|
2020-02-13 09:39:27 +01:00
|
|
|
|
)
|
2020-08-31 17:58:34 +02:00
|
|
|
|
elif obj and obj.student.is_eds():
|
2020-02-13 09:39:27 +01:00
|
|
|
|
if obj.missing_examination_data():
|
|
|
|
|
|
return missing_message
|
|
|
|
|
|
else:
|
|
|
|
|
|
return format_html(
|
|
|
|
|
|
'<a class="button" href="{}">Courrier pour l’expert</a> '
|
|
|
|
|
|
'<a class="button" href="{}">Mail convocation soutenance</a> '
|
2020-04-23 12:08:18 +02:00
|
|
|
|
'<a class="button" href="{}">Indemnité EP</a> '
|
|
|
|
|
|
'<a class="button" href="{}">Indemnité soutenance</a>',
|
|
|
|
|
|
reverse('print-expert-letter-eds', args=[obj.pk]),
|
2020-04-21 15:29:28 +02:00
|
|
|
|
reverse('student-eds-convocation', args=[obj.pk]),
|
2020-04-23 12:08:18 +02:00
|
|
|
|
reverse('print-compens-form', args=[obj.pk, 'ep']),
|
|
|
|
|
|
reverse('print-compens-form', args=[obj.pk, 'sout']),
|
2020-02-13 09:39:27 +01:00
|
|
|
|
)
|
|
|
|
|
|
else:
|
|
|
|
|
|
return missing_message
|
|
|
|
|
|
examination_actions.short_description = 'Actions pour la procédure'
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-11-09 12:12:44 +01:00
|
|
|
|
@admin.register(Student)
|
2012-11-06 17:54:33 +01:00
|
|
|
|
class StudentAdmin(admin.ModelAdmin):
|
2015-09-22 20:52:35 +02:00
|
|
|
|
list_display = ('__str__', 'pcode', 'city', 'klass', 'archived')
|
2013-01-02 14:40:24 +01:00
|
|
|
|
ordering = ('last_name', 'first_name')
|
2017-08-21 14:37:11 +02:00
|
|
|
|
list_filter = (('archived', ArchivedListFilter), ('klass', KlassRelatedListFilter))
|
2013-02-04 10:24:02 +01:00
|
|
|
|
search_fields = ('last_name', 'first_name', 'pcode', 'city', 'klass__name')
|
2020-09-11 11:42:24 +02:00
|
|
|
|
autocomplete_fields = ('corporation', 'instructor', 'instructor2', 'supervisor', 'mentor')
|
2023-07-10 17:22:41 +02:00
|
|
|
|
readonly_fields = (
|
|
|
|
|
|
'report_sem1_sent', 'report_sem2_sent', 'mentor_indemn', 'superv_indemn',
|
|
|
|
|
|
)
|
2019-10-15 09:54:38 +02:00
|
|
|
|
fieldsets = [
|
2018-04-12 12:17:37 +02:00
|
|
|
|
(None, {
|
2020-02-13 09:39:27 +01:00
|
|
|
|
'fields': (
|
|
|
|
|
|
('last_name', 'first_name', 'ext_id'), ('street', 'pcode', 'city', 'district'),
|
|
|
|
|
|
('email', 'tel', 'mobile'), ('gender', 'avs', 'birth_date'),
|
|
|
|
|
|
('archived', 'dispense_ecg', 'dispense_eps', 'soutien_dys'),
|
2023-11-09 13:51:09 +01:00
|
|
|
|
('klass', 'option_ase', 'start_educ'),
|
2020-02-13 09:39:27 +01:00
|
|
|
|
('report_sem1', 'report_sem1_sent'),
|
|
|
|
|
|
('report_sem2', 'report_sem2_sent'),
|
2020-09-11 11:42:24 +02:00
|
|
|
|
('corporation', 'instructor', 'instructor2')
|
2020-02-13 09:39:27 +01:00
|
|
|
|
)}
|
|
|
|
|
|
),
|
|
|
|
|
|
("Procédure de qualification", {
|
2019-10-15 09:54:38 +02:00
|
|
|
|
'classes': ['collapse'],
|
2018-04-12 12:17:37 +02:00
|
|
|
|
'fields': (
|
2023-07-10 12:44:03 +02:00
|
|
|
|
('supervisor', 'supervision_attest_received', 'superv_indemn'),
|
2018-04-12 12:17:37 +02:00
|
|
|
|
('subject', 'title'),
|
2020-04-23 12:08:18 +02:00
|
|
|
|
('training_referent', 'referent'),
|
|
|
|
|
|
('mentor', 'mentor_indemn'),
|
2018-04-12 12:17:37 +02:00
|
|
|
|
)
|
|
|
|
|
|
}),
|
2019-10-15 09:54:38 +02:00
|
|
|
|
]
|
2013-08-23 16:41:51 +02:00
|
|
|
|
actions = ['archive']
|
2020-02-13 09:39:27 +01:00
|
|
|
|
inlines = [ExaminationInline, SupervisionBillInline]
|
2018-04-26 07:54:29 +02:00
|
|
|
|
|
2020-04-23 12:08:18 +02:00
|
|
|
|
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é'
|
|
|
|
|
|
|
2023-07-10 12:44:03 +02:00
|
|
|
|
def superv_indemn(self, obj):
|
|
|
|
|
|
if obj is None or not obj.supervisor:
|
|
|
|
|
|
return '-'
|
|
|
|
|
|
return format_html(
|
2023-07-10 17:22:41 +02:00
|
|
|
|
'<a class="button" href="{}">Indemnité au superviseur</a> '
|
|
|
|
|
|
'<a class="button" href="{}">Fiche info</a>',
|
2023-07-10 12:44:03 +02:00
|
|
|
|
reverse('print-supervisor-compens-form', args=[obj.pk]),
|
2023-07-10 17:22:41 +02:00
|
|
|
|
reverse('print-supervisor-info', args=[obj.supervisor.pk]),
|
2023-07-10 12:44:03 +02:00
|
|
|
|
)
|
|
|
|
|
|
superv_indemn.short_description = 'Indemnité'
|
|
|
|
|
|
|
2020-02-13 09:39:27 +01:00
|
|
|
|
def get_inlines(self, request, obj=None):
|
|
|
|
|
|
if obj is None:
|
2018-04-26 07:54:29 +02:00
|
|
|
|
return []
|
2020-02-13 09:39:27 +01:00
|
|
|
|
inlines = super().get_inlines(request, obj=obj)
|
|
|
|
|
|
# SupervisionBillInline is only adequate for EDE students
|
|
|
|
|
|
if not obj.klass or obj.klass.section.name != 'EDE':
|
|
|
|
|
|
inlines = [inl for inl in inlines if inl != SupervisionBillInline]
|
2020-08-31 17:58:34 +02:00
|
|
|
|
if not obj.is_ede() and not obj.is_eds():
|
2020-02-13 09:39:27 +01:00
|
|
|
|
inlines = [inl for inl in inlines if inl != ExaminationInline]
|
2021-08-19 11:13:44 +02:00
|
|
|
|
if request.method == 'POST':
|
|
|
|
|
|
# Special case where inlines would be different before and after POST
|
|
|
|
|
|
if SupervisionBillInline in inlines and not 'supervisionbill_set-TOTAL_FORMS' in request.POST:
|
|
|
|
|
|
inlines.remove(SupervisionBillInline)
|
|
|
|
|
|
if ExaminationInline in inlines and not 'examination_set-TOTAL_FORMS' in request.POST:
|
|
|
|
|
|
inlines.remove(ExaminationInline)
|
2020-02-13 09:39:27 +01:00
|
|
|
|
return inlines
|
2018-04-26 07:54:29 +02:00
|
|
|
|
|
2019-10-15 09:54:38 +02:00
|
|
|
|
def get_fieldsets(self, request, obj=None):
|
2020-08-31 17:58:34 +02:00
|
|
|
|
if not obj or (not obj.is_ede() and not obj.is_eds()):
|
2020-02-13 09:39:27 +01:00
|
|
|
|
# Hide group "Procédure de qualification"
|
2019-10-15 09:54:38 +02:00
|
|
|
|
fieldsets = deepcopy(self.fieldsets)
|
|
|
|
|
|
fieldsets[1][1]['classes'] = ['hidden']
|
|
|
|
|
|
return fieldsets
|
|
|
|
|
|
return super().get_fieldsets(request, obj)
|
|
|
|
|
|
|
2021-08-25 14:35:14 +02:00
|
|
|
|
def formfield_for_foreignkey(self, db_field, request, **kwargs):
|
|
|
|
|
|
ffield = super().formfield_for_foreignkey(db_field, request, **kwargs)
|
|
|
|
|
|
if db_field.name in self.autocomplete_fields:
|
|
|
|
|
|
ffield.widget.attrs.update({'data-minimum-input-length': 3})
|
|
|
|
|
|
return ffield
|
|
|
|
|
|
|
2013-08-23 16:41:51 +02:00
|
|
|
|
def archive(self, request, queryset):
|
2017-08-21 11:49:14 +02:00
|
|
|
|
for student in queryset:
|
|
|
|
|
|
# Save each item individually to allow for custom save() logic.
|
|
|
|
|
|
student.archived = True
|
|
|
|
|
|
student.save()
|
2013-08-23 16:41:51 +02:00
|
|
|
|
archive.short_description = "Marquer les étudiants sélectionnés comme archivés"
|
2012-11-06 17:54:33 +01:00
|
|
|
|
|
|
|
|
|
|
|
2023-11-09 12:12:44 +01:00
|
|
|
|
@admin.register(CorpContact)
|
2012-11-06 17:54:33 +01:00
|
|
|
|
class CorpContactAdmin(admin.ModelAdmin):
|
2015-09-22 20:52:35 +02:00
|
|
|
|
list_display = ('__str__', 'corporation', 'role')
|
2023-06-08 12:06:32 +02:00
|
|
|
|
list_filter = (('archived', ArchivedListFilter), 'sections')
|
2015-10-01 13:36:19 +02:00
|
|
|
|
ordering = ('last_name', 'first_name')
|
|
|
|
|
|
search_fields = ('last_name', 'first_name', 'role')
|
2018-04-24 12:01:44 +02:00
|
|
|
|
fields = (('civility', 'last_name', 'first_name'),
|
2018-04-12 10:12:24 +02:00
|
|
|
|
('street', 'pcode', 'city'),
|
2020-06-05 11:53:51 +02:00
|
|
|
|
('birth_date', 'nation'),
|
2022-08-24 14:57:31 +02:00
|
|
|
|
('etat_civil', 'etat_depuis'),
|
2022-02-15 10:33:23 +01:00
|
|
|
|
('permis_sejour', 'date_validite'),
|
2018-04-12 10:12:24 +02:00
|
|
|
|
('corporation',),
|
2016-01-18 12:55:57 +01:00
|
|
|
|
('sections', 'is_main', 'always_cc', 'archived'),
|
2020-04-30 11:06:57 +02:00
|
|
|
|
('role', 'ext_id'), ('tel', 'email'), ('avs',),
|
2020-04-30 11:25:38 +02:00
|
|
|
|
('iban', 'bank', 'clearing' ),
|
2018-04-12 10:12:24 +02:00
|
|
|
|
('qualification', 'fields_of_interest'),
|
|
|
|
|
|
)
|
2023-06-08 10:59:42 +02:00
|
|
|
|
actions = ['export_contacts']
|
2016-01-15 21:01:07 +01:00
|
|
|
|
formfield_overrides = {
|
|
|
|
|
|
models.ManyToManyField: {'widget': forms.CheckboxSelectMultiple},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
def get_form(self, *args, **kwargs):
|
|
|
|
|
|
form = super().get_form(*args, **kwargs)
|
|
|
|
|
|
form.base_fields['sections'].widget.can_add_related = False
|
|
|
|
|
|
return form
|
|
|
|
|
|
|
2018-02-14 18:13:22 +01:00
|
|
|
|
def get_search_results(self, request, qs, term):
|
|
|
|
|
|
qs, distinct = super().get_search_results(request, qs, term)
|
|
|
|
|
|
return qs.exclude(archived=True), distinct
|
2012-11-06 17:54:33 +01:00
|
|
|
|
|
2023-06-08 10:59:42 +02:00
|
|
|
|
def export_contacts(self, request, queryset):
|
|
|
|
|
|
"""
|
|
|
|
|
|
Export all CorpContact in Excel file.
|
|
|
|
|
|
"""
|
|
|
|
|
|
field_names = (
|
|
|
|
|
|
'ext_id', 'civility', 'last_name', 'first_name', 'birth_date',
|
|
|
|
|
|
'street', 'pcode', 'city', 'etat_civil', 'etat_depuis', 'nation',
|
|
|
|
|
|
'tel', 'email', 'corporation', 'is_main', 'always_cc', 'role',
|
|
|
|
|
|
'permis_sejour', 'date_validite', 'avs', 'bank', 'clearing', 'iban',
|
|
|
|
|
|
'qualification', 'fields_of_interest',
|
|
|
|
|
|
)
|
|
|
|
|
|
fields = [CorpContact._meta.get_field(fname) for fname in field_names]
|
|
|
|
|
|
export_fields = {
|
|
|
|
|
|
getattr(f, 'verbose_name', f.name):
|
|
|
|
|
|
('corporation__name' if f.name == 'corporation' else f.name) for f in fields
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export = OpenXMLExport('Exportation')
|
|
|
|
|
|
export.write_line(export_fields.keys(), bold=True)
|
|
|
|
|
|
for corp in queryset.values_list(*export_fields.values()):
|
|
|
|
|
|
values = []
|
|
|
|
|
|
for value, field_name in zip(corp, export_fields.values()):
|
|
|
|
|
|
if field_name in ['is_main', 'always_cc']:
|
|
|
|
|
|
value = 'Oui' if value else ''
|
|
|
|
|
|
values.append(value)
|
|
|
|
|
|
export.write_line(values)
|
|
|
|
|
|
return export.get_http_response('contacts_export')
|
|
|
|
|
|
export_contacts.short_description = 'Exportation Excel'
|
|
|
|
|
|
|
2018-02-15 16:05:25 +01:00
|
|
|
|
|
2012-11-09 15:32:00 +01:00
|
|
|
|
class ContactInline(admin.StackedInline):
|
2012-11-06 17:54:33 +01:00
|
|
|
|
model = CorpContact
|
2018-04-24 12:01:44 +02:00
|
|
|
|
fields = (('civility', 'last_name', 'first_name'),
|
2016-01-18 12:55:57 +01:00
|
|
|
|
('sections', 'is_main', 'always_cc', 'archived'),
|
2012-11-09 15:32:00 +01:00
|
|
|
|
('role', 'tel', 'email'))
|
2012-11-06 17:54:33 +01:00
|
|
|
|
extra = 1
|
2016-01-15 21:01:07 +01:00
|
|
|
|
formfield_overrides = {
|
|
|
|
|
|
models.ManyToManyField: {'widget': forms.CheckboxSelectMultiple},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-11-06 17:54:33 +01:00
|
|
|
|
|
2023-11-09 12:12:44 +01:00
|
|
|
|
@admin.register(Corporation)
|
2012-11-06 17:54:33 +01:00
|
|
|
|
class CorporationAdmin(admin.ModelAdmin):
|
2018-06-08 15:31:20 +02:00
|
|
|
|
list_display = ('name', 'short_name', 'pcode', 'city', 'district', 'ext_id')
|
2015-10-01 17:02:19 +02:00
|
|
|
|
list_editable = ('short_name',) # Temporarily?
|
2016-01-19 11:30:56 +01:00
|
|
|
|
list_filter = (('archived', ArchivedListFilter),)
|
2017-07-19 18:58:53 +02:00
|
|
|
|
search_fields = ('name', 'street', 'pcode', 'city')
|
2012-11-13 16:55:46 +01:00
|
|
|
|
ordering = ('name',)
|
2018-06-08 15:31:20 +02:00
|
|
|
|
fields = (
|
|
|
|
|
|
('name', 'short_name'),
|
|
|
|
|
|
'parent',
|
|
|
|
|
|
('sector', 'typ', 'ext_id'),
|
|
|
|
|
|
'street',
|
|
|
|
|
|
('pcode', 'city', 'district'),
|
|
|
|
|
|
('tel', 'email'),
|
|
|
|
|
|
'web',
|
|
|
|
|
|
'archived',
|
|
|
|
|
|
)
|
2012-11-06 17:54:33 +01:00
|
|
|
|
inlines = [ContactInline]
|
2018-08-15 15:47:44 +02:00
|
|
|
|
actions = ['export_corporations']
|
2012-11-06 17:54:33 +01:00
|
|
|
|
|
2018-02-14 18:13:22 +01:00
|
|
|
|
def get_search_results(self, request, qs, term):
|
|
|
|
|
|
qs, distinct = super().get_search_results(request, qs, term)
|
|
|
|
|
|
return qs.exclude(archived=True), distinct
|
|
|
|
|
|
|
2018-08-15 15:47:44 +02:00
|
|
|
|
def export_corporations(self, request, queryset):
|
|
|
|
|
|
"""
|
|
|
|
|
|
Export all Corporations in Excel file.
|
|
|
|
|
|
"""
|
|
|
|
|
|
export_fields = OrderedDict([
|
|
|
|
|
|
(getattr(f, 'verbose_name', f.name), f.name)
|
|
|
|
|
|
for f in Corporation._meta.get_fields() if f.name in (
|
|
|
|
|
|
'name', 'short_name', 'sector', 'typ', 'street', 'pcode',
|
|
|
|
|
|
'city', 'district', 'tel', 'email', 'web', 'ext_id', 'archived'
|
|
|
|
|
|
)
|
|
|
|
|
|
])
|
|
|
|
|
|
export = OpenXMLExport('Exportation')
|
|
|
|
|
|
export.write_line(export_fields.keys(), bold=True)
|
|
|
|
|
|
for corp in queryset.values_list(*export_fields.values()):
|
|
|
|
|
|
values = []
|
|
|
|
|
|
for value, field_name in zip(corp, export_fields.values()):
|
|
|
|
|
|
if field_name == 'archived':
|
|
|
|
|
|
value = 'Oui' if value else ''
|
|
|
|
|
|
values.append(value)
|
|
|
|
|
|
export.write_line(values)
|
|
|
|
|
|
return export.get_http_response('corporations_export')
|
|
|
|
|
|
export_corporations.short_description = 'Exportation Excel'
|
|
|
|
|
|
|
2012-11-06 17:54:33 +01:00
|
|
|
|
|
2012-11-22 17:49:12 +01:00
|
|
|
|
class AvailabilityAdminForm(forms.ModelForm):
|
|
|
|
|
|
"""
|
|
|
|
|
|
Custom avail form to create several availabilities at once when inlined in
|
|
|
|
|
|
the PeriodAdmin interface
|
|
|
|
|
|
"""
|
2013-07-11 12:50:41 +02:00
|
|
|
|
num_avail = forms.IntegerField(label="Nombre de places", initial=1, required=False)
|
|
|
|
|
|
|
|
|
|
|
|
class Media:
|
2019-08-30 15:01:11 +02:00
|
|
|
|
js = ('admin/js/jquery.init.js', 'js/avail_form.js',)
|
2013-07-11 12:50:41 +02:00
|
|
|
|
|
2012-11-22 17:49:12 +01:00
|
|
|
|
class Meta:
|
|
|
|
|
|
model = Availability
|
2015-09-22 18:26:04 +02:00
|
|
|
|
fields = '__all__'
|
2012-11-22 17:49:12 +01:00
|
|
|
|
widgets = {
|
|
|
|
|
|
'num_avail': forms.TextInput(attrs={'size': 3}),
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2013-07-11 12:50:41 +02:00
|
|
|
|
def __init__(self, data=None, files=None, **kwargs):
|
2019-08-30 15:03:44 +02:00
|
|
|
|
super().__init__(data=data, files=files, **kwargs)
|
2012-11-22 17:49:12 +01:00
|
|
|
|
if self.instance.pk is not None:
|
|
|
|
|
|
# Hide num_avail on existing instances
|
|
|
|
|
|
self.fields['num_avail'].widget = forms.HiddenInput()
|
2013-07-11 12:50:41 +02:00
|
|
|
|
# Limit CorpContact objects to contacts of chosen corporation
|
|
|
|
|
|
if data is None and self.instance.corporation_id:
|
|
|
|
|
|
self.fields['contact'].queryset = self.instance.corporation.corpcontact_set
|
2012-11-22 17:49:12 +01:00
|
|
|
|
|
|
|
|
|
|
def save(self, **kwargs):
|
2019-08-30 15:03:44 +02:00
|
|
|
|
instance = super().save(**kwargs)
|
2012-11-22 17:49:12 +01:00
|
|
|
|
# Create supplementary availabilities depending on num_avail
|
2013-07-11 12:50:41 +02:00
|
|
|
|
num_avail = self.cleaned_data.get('num_avail', 1) or 1
|
|
|
|
|
|
for i in range(1, num_avail):
|
2012-11-22 17:49:12 +01:00
|
|
|
|
Availability.objects.create(
|
|
|
|
|
|
corporation=instance.corporation,
|
|
|
|
|
|
period=instance.period,
|
|
|
|
|
|
domain=instance.domain,
|
2013-07-11 12:50:41 +02:00
|
|
|
|
contact=instance.contact,
|
2012-11-22 17:49:12 +01:00
|
|
|
|
comment=instance.comment)
|
|
|
|
|
|
return instance
|
|
|
|
|
|
|
2018-02-05 09:38:14 +01:00
|
|
|
|
|
2016-01-19 12:07:14 +01:00
|
|
|
|
class AvailabilityInline(admin.StackedInline):
|
2012-11-07 17:45:53 +01:00
|
|
|
|
model = Availability
|
2012-11-22 17:49:12 +01:00
|
|
|
|
form = AvailabilityAdminForm
|
2013-04-05 16:18:18 +02:00
|
|
|
|
ordering = ('corporation__name',)
|
2012-11-07 17:45:53 +01:00
|
|
|
|
extra = 1
|
2012-11-13 16:55:46 +01:00
|
|
|
|
formfield_overrides = {
|
|
|
|
|
|
models.TextField: {'widget': forms.Textarea(attrs={'rows':2, 'cols':40})},
|
|
|
|
|
|
}
|
2019-01-10 15:49:20 +01:00
|
|
|
|
autocomplete_fields = ['corporation']
|
2012-11-13 16:55:46 +01:00
|
|
|
|
|
2021-08-25 14:35:14 +02:00
|
|
|
|
def formfield_for_foreignkey(self, db_field, request, **kwargs):
|
|
|
|
|
|
ffield = super().formfield_for_foreignkey(db_field, request, **kwargs)
|
|
|
|
|
|
if db_field.name in self.autocomplete_fields:
|
|
|
|
|
|
ffield.widget.attrs.update({'data-minimum-input-length': 3})
|
|
|
|
|
|
return ffield
|
|
|
|
|
|
|
2012-11-07 17:45:53 +01:00
|
|
|
|
|
2023-11-09 12:12:44 +01:00
|
|
|
|
@admin.register(Period)
|
2012-11-06 17:54:33 +01:00
|
|
|
|
class PeriodAdmin(admin.ModelAdmin):
|
2012-11-23 11:31:06 +01:00
|
|
|
|
list_display = ('title', 'dates', 'section', 'level')
|
|
|
|
|
|
list_filter = ('section', 'level')
|
2012-11-07 17:45:53 +01:00
|
|
|
|
inlines = [AvailabilityInline]
|
2012-11-06 17:54:33 +01:00
|
|
|
|
|
|
|
|
|
|
|
2023-11-09 12:12:44 +01:00
|
|
|
|
@admin.register(Availability)
|
2012-11-06 17:54:33 +01:00
|
|
|
|
class AvailabilityAdmin(admin.ModelAdmin):
|
2019-11-20 14:53:24 +01:00
|
|
|
|
list_display = ('corporation', 'period', 'domain', 'contact')
|
2012-11-07 17:45:53 +01:00
|
|
|
|
list_filter = ('period',)
|
2016-01-19 12:07:14 +01:00
|
|
|
|
fields = (('corporation', 'period'), 'domain', 'contact', 'priority', 'comment')
|
2013-07-11 12:50:41 +02:00
|
|
|
|
form = AvailabilityAdminForm
|
2012-11-06 17:54:33 +01:00
|
|
|
|
|
2012-11-13 16:55:46 +01:00
|
|
|
|
def formfield_for_foreignkey(self, db_field, request, **kwargs):
|
|
|
|
|
|
if db_field.name == "corporation":
|
|
|
|
|
|
kwargs["queryset"] = Corporation.objects.filter(archived=False).order_by('name')
|
2016-01-18 12:55:57 +01:00
|
|
|
|
if db_field.name == "contact":
|
|
|
|
|
|
kwargs["queryset"] = CorpContact.objects.filter(archived=False)
|
2019-11-20 14:53:24 +01:00
|
|
|
|
return super().formfield_for_foreignkey(db_field, request, **kwargs)
|
2012-11-13 16:55:46 +01:00
|
|
|
|
|
2012-11-06 17:54:33 +01:00
|
|
|
|
|
2023-11-09 12:12:44 +01:00
|
|
|
|
@admin.register(Training)
|
2012-12-13 00:00:04 +01:00
|
|
|
|
class TrainingAdmin(admin.ModelAdmin):
|
|
|
|
|
|
search_fields = ('student__first_name', 'student__last_name', 'availability__corporation__name')
|
2013-07-11 15:26:44 +02:00
|
|
|
|
raw_id_fields = ('availability',)
|
2012-12-13 00:00:04 +01:00
|
|
|
|
|
2020-12-08 15:04:46 +01:00
|
|
|
|
def formfield_for_foreignkey(self, db_field, request, **kwargs):
|
|
|
|
|
|
if db_field.name == "referent":
|
|
|
|
|
|
kwargs["queryset"] = Teacher.objects.filter(archived=False).order_by('last_name', 'first_name')
|
|
|
|
|
|
return super().formfield_for_foreignkey(db_field, request, **kwargs)
|
|
|
|
|
|
|
2012-12-13 00:00:04 +01:00
|
|
|
|
|
2023-11-09 12:12:44 +01:00
|
|
|
|
@admin.register(Course)
|
2017-07-19 18:58:53 +02:00
|
|
|
|
class CourseAdmin(admin.ModelAdmin):
|
|
|
|
|
|
list_display = ('teacher', 'public', 'subject', 'period', 'imputation')
|
2017-08-22 08:41:06 +02:00
|
|
|
|
list_filter = ('imputation', )
|
|
|
|
|
|
search_fields = ('teacher__last_name', 'public', 'subject')
|
2017-07-19 18:58:53 +02:00
|
|
|
|
|
|
|
|
|
|
|
2019-02-21 09:46:44 +01:00
|
|
|
|
|
|
|
|
|
|
class GroupAdmin(AuthGroupAdmin):
|
|
|
|
|
|
list_display = ['name', 'membres']
|
|
|
|
|
|
|
|
|
|
|
|
def membres(self, grp):
|
|
|
|
|
|
return format_html_join(', ', '<a href="{}">{}</a>', [
|
|
|
|
|
|
(reverse('admin:auth_user_change', args=(user.pk,)), user.username)
|
|
|
|
|
|
for user in grp.user_set.all().order_by('username')
|
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-11-23 11:31:06 +01:00
|
|
|
|
admin.site.register(Level)
|
2017-08-29 16:28:31 +02:00
|
|
|
|
admin.site.register(Option)
|
2019-02-06 17:02:09 +01:00
|
|
|
|
admin.site.register(StudentFile)
|
2012-11-06 17:54:33 +01:00
|
|
|
|
admin.site.register(Domain)
|
2018-02-19 10:08:46 +01:00
|
|
|
|
admin.site.register(LogBookReason)
|
|
|
|
|
|
admin.site.register(LogBook)
|
2018-03-19 18:36:28 +01:00
|
|
|
|
admin.site.register(ExamEDESession)
|
2020-02-13 09:39:27 +01:00
|
|
|
|
admin.site.register(Examination)
|
2019-02-21 09:46:44 +01:00
|
|
|
|
|
|
|
|
|
|
admin.site.unregister(Group)
|
|
|
|
|
|
admin.site.register(Group, GroupAdmin)
|