diff --git a/Back-End/Auth/models.py b/Back-End/Auth/models.py index 408d702..eaef8dc 100644 --- a/Back-End/Auth/models.py +++ b/Back-End/Auth/models.py @@ -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): diff --git a/Back-End/N3wtSchool/mailManager.py b/Back-End/N3wtSchool/mailManager.py index 7bf9cce..e3eacbe 100644 --- a/Back-End/N3wtSchool/mailManager.py +++ b/Back-End/N3wtSchool/mailManager.py @@ -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) \ No newline at end of file + 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 \ No newline at end of file diff --git a/Back-End/School/views.py b/Back-End/School/views.py index 97b0cc3..298d662 100644 --- a/Back-End/School/views.py +++ b/Back-End/School/views.py @@ -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) diff --git a/Back-End/Subscriptions/templates/emails/inscription_teacher.html b/Back-End/Subscriptions/templates/emails/inscription_teacher.html new file mode 100644 index 0000000..fe534d5 --- /dev/null +++ b/Back-End/Subscriptions/templates/emails/inscription_teacher.html @@ -0,0 +1,63 @@ + + + + + + Bienvenue sur N3wt School + + + +
+
+ + +

Bienvenue sur N3wt School

+
+
+

Bonjour,

+

Votre compte enseignant a été créé sur la plateforme N3wt School.

+

Pour accéder à votre espace personnel, veuillez vous connecter à l'adresse suivante :
+ {{BASE_URL}}/users/login +

+

Votre identifiant est : {{ email }}

+

Si c'est votre première connexion, veuillez activer votre compte ici :
+ {{BASE_URL}}/users/subscribe +

+

Nous vous souhaitons une excellente prise en main de l'outil.
+ L'équipe N3wt School reste à votre disposition pour toute question.

+
+ +
+ + diff --git a/Front-End/src/components/Structure/Configuration/TeachersSection.js b/Front-End/src/components/Structure/Configuration/TeachersSection.js index 9cffc51..86d75fe 100644 --- a/Front-End/src/components/Structure/Configuration/TeachersSection.js +++ b/Front-End/src/components/Structure/Configuration/TeachersSection.js @@ -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, };