mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-04-03 16:51:26 +00:00
feat: Envoi mail d'inscription aux enseignants [N3WTS-1]
This commit is contained in:
@ -25,7 +25,7 @@ class ProfileRole(models.Model):
|
||||
profile = models.ForeignKey('Profile', on_delete=models.CASCADE, related_name='roles')
|
||||
role_type = models.IntegerField(choices=RoleType.choices, default=RoleType.PROFIL_UNDEFINED)
|
||||
establishment = models.ForeignKey('Establishment.Establishment', on_delete=models.CASCADE, related_name='profile_roles')
|
||||
is_active = models.BooleanField(default=False)
|
||||
is_active = models.BooleanField(default=False, blank=True)
|
||||
updated_date = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
from django.core.mail import send_mail, get_connection, EmailMultiAlternatives, EmailMessage
|
||||
from django.core.mail import get_connection, EmailMultiAlternatives, EmailMessage
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.html import strip_tags
|
||||
from django.conf import settings
|
||||
@ -207,4 +207,22 @@ def isValid(message, fiche_inscription):
|
||||
responsable = eleve.getMainGuardian()
|
||||
mailReponsableAVerifier = responsable.mail
|
||||
|
||||
return responsableMail == mailReponsableAVerifier and str(idMail) == str(fiche_inscription.eleve.id)
|
||||
return responsableMail == mailReponsableAVerifier and str(idMail) == str(fiche_inscription.eleve.id)
|
||||
|
||||
def sendRegisterTeacher(recipients, establishment_id):
|
||||
errorMessage = ''
|
||||
try:
|
||||
EMAIL_INSCRIPTION_SUBJECT = '[N3WT-SCHOOL] Bienvenue sur N3wt School (Enseignant)'
|
||||
context = {
|
||||
'BASE_URL': settings.BASE_URL,
|
||||
'URL_DJANGO': settings.URL_DJANGO,
|
||||
'email': recipients,
|
||||
'establishment': establishment_id
|
||||
}
|
||||
connection = getConnection(establishment_id)
|
||||
subject = EMAIL_INSCRIPTION_SUBJECT
|
||||
html_message = render_to_string('emails/inscription_teacher.html', context)
|
||||
sendMail(subject=subject, message=html_message, recipients=recipients, connection=connection)
|
||||
except Exception as e:
|
||||
errorMessage = str(e)
|
||||
return errorMessage
|
||||
@ -35,6 +35,7 @@ from collections import defaultdict
|
||||
from Subscriptions.models import Student, StudentCompetency
|
||||
from Subscriptions.util import getCurrentSchoolYear
|
||||
import logging
|
||||
from N3wtSchool.mailManager import sendRegisterForm, sendRegisterTeacher
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -102,8 +103,17 @@ class TeacherListCreateView(APIView):
|
||||
teacher_serializer = TeacherSerializer(data=teacher_data)
|
||||
|
||||
if teacher_serializer.is_valid():
|
||||
teacher_serializer.save()
|
||||
|
||||
teacher_instance = teacher_serializer.save()
|
||||
# Envoi du mail d'inscription enseignant uniquement à la création
|
||||
email = None
|
||||
establishment_id = None
|
||||
if hasattr(teacher_instance, "profile_role") and teacher_instance.profile_role:
|
||||
if hasattr(teacher_instance.profile_role, "profile") and teacher_instance.profile_role.profile:
|
||||
email = teacher_instance.profile_role.profile.email
|
||||
if hasattr(teacher_instance.profile_role, "establishment") and teacher_instance.profile_role.establishment:
|
||||
establishment_id = teacher_instance.profile_role.establishment.id
|
||||
if email and establishment_id:
|
||||
sendRegisterTeacher(email, establishment_id)
|
||||
return JsonResponse(teacher_serializer.data, safe=False)
|
||||
|
||||
return JsonResponse(teacher_serializer.errors, safe=False)
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
<!-- Nouveau template pour l'inscription d'un enseignant -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Bienvenue sur N3wt School</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
}
|
||||
.container {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
}
|
||||
.header {
|
||||
background-color: #f4f4f4;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
.content {
|
||||
padding: 20px;
|
||||
}
|
||||
.footer {
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
margin-top: 30px;
|
||||
color: #777;
|
||||
}
|
||||
.logo {
|
||||
width: 120px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<!-- Utilisation d'un lien absolu pour le logo -->
|
||||
<img src="{{URL_DJANGO}}/static/img/logo_min.svg" alt="Logo N3wt School" class="logo" style="display:block;margin:auto;" />
|
||||
<h1>Bienvenue sur N3wt School</h1>
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>Bonjour,</p>
|
||||
<p>Votre compte enseignant a été créé sur la plateforme N3wt School.</p>
|
||||
<p>Pour accéder à votre espace personnel, veuillez vous connecter à l'adresse suivante :<br>
|
||||
<a href="{{BASE_URL}}/users/login">{{BASE_URL}}/users/login</a>
|
||||
</p>
|
||||
<p>Votre identifiant est : <b>{{ email }}</b></p>
|
||||
<p>Si c'est votre première connexion, veuillez activer votre compte ici :<br>
|
||||
<a href="{{BASE_URL}}/users/subscribe?establishment_id={{establishment}}">{{BASE_URL}}/users/subscribe</a>
|
||||
</p>
|
||||
<p>Nous vous souhaitons une excellente prise en main de l'outil.<br>
|
||||
L'équipe N3wt School reste à votre disposition pour toute question.</p>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<p>Ce message est généré automatiquement, merci de ne pas y répondre.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@ -140,38 +140,19 @@ const TeachersSection = ({
|
||||
const [removePopupMessage, setRemovePopupMessage] = useState('');
|
||||
const [removePopupOnConfirm, setRemovePopupOnConfirm] = useState(() => {});
|
||||
|
||||
const [confirmPopupVisible, setConfirmPopupVisible] = useState(false);
|
||||
const [confirmPopupMessage, setConfirmPopupMessage] = useState('');
|
||||
const [confirmPopupOnConfirm, setConfirmPopupOnConfirm] = useState(() => {});
|
||||
|
||||
const { selectedEstablishmentId } = useEstablishment();
|
||||
|
||||
// --- UTILS ---
|
||||
|
||||
// Retourne le profil existant pour un email, utilisé par un teacher actif ou le teacher en cours d'édition
|
||||
const getUsedProfileForEmail = (email, teacherId = null) => {
|
||||
const usedProfileIds = new Set(
|
||||
teachers.map(t => t.profile_role && t.profile).filter(Boolean)
|
||||
);
|
||||
// Ajoute le profil du teacher en cours d'édition si besoin
|
||||
if (teacherId) {
|
||||
const currentTeacher = teachers.find(t => t.id === teacherId);
|
||||
if (currentTeacher && currentTeacher.profile_role && currentTeacher.profile) {
|
||||
const profileObj = profiles.find(p => p.id === currentTeacher.profile);
|
||||
if (profileObj && profileObj.email === email) {
|
||||
usedProfileIds.add(profileObj.id);
|
||||
}
|
||||
} else {
|
||||
// Cas création immédiate : on cherche le profil par email dans profiles
|
||||
const profileObj = profiles.find(p => p.email === email);
|
||||
if (profileObj) {
|
||||
usedProfileIds.add(profileObj.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
return profiles.find(
|
||||
(profile) => profile.email === email && usedProfileIds.has(profile.id)
|
||||
);
|
||||
// Retourne le profil existant pour un email
|
||||
const getUsedProfileForEmail = (email) => {
|
||||
// On cherche tous les profils dont l'email correspond
|
||||
const matchingProfiles = profiles.filter(p => p.email === email);
|
||||
|
||||
// On retourne le premier profil correspondant (ou undefined)
|
||||
const result = matchingProfiles.length > 0 ? matchingProfiles[0] : undefined;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// Met à jour le formData et newTeacher si besoin
|
||||
@ -189,7 +170,7 @@ const TeachersSection = ({
|
||||
|
||||
const handleEmailChange = (e) => {
|
||||
const email = e.target.value;
|
||||
const existingProfile = getUsedProfileForEmail(email, editingTeacher);
|
||||
const existingProfile = getUsedProfileForEmail(email);
|
||||
|
||||
if (existingProfile) {
|
||||
logger.info(`Adresse email déjà utilisée pour le profil ${existingProfile.id}`);
|
||||
@ -290,9 +271,6 @@ const TeachersSection = ({
|
||||
};
|
||||
|
||||
const handleUpdateTeacher = (id, updatedData) => {
|
||||
// Simplification : le profil est forcément existant, on utilise directement existingProfileId du formData
|
||||
const currentTeacher = teachers.find((teacher) => teacher.id === id);
|
||||
|
||||
if (
|
||||
updatedData.last_name &&
|
||||
updatedData.first_name &&
|
||||
@ -302,7 +280,6 @@ const TeachersSection = ({
|
||||
id: updatedData.profile_role,
|
||||
establishment: selectedEstablishmentId,
|
||||
role_type: updatedData.role_type || 0,
|
||||
is_active: true,
|
||||
profile: updatedData.existingProfileId,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user