mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
feat: Messagerie WIP [#17]
This commit is contained in:
@ -25,7 +25,7 @@ from django.db.models import Q
|
||||
|
||||
from Auth.serializers import ProfileSerializer, ProfileRoleSerializer
|
||||
from Subscriptions.models import RegistrationForm, Guardian
|
||||
import Subscriptions.mailManager as mailer
|
||||
import N3wtSchool.mailManager as mailer
|
||||
import Subscriptions.util as util
|
||||
import logging
|
||||
from N3wtSchool import bdd, error, settings
|
||||
@ -538,7 +538,7 @@ class ProfileRoleView(APIView):
|
||||
profiles_roles_List = profiles_roles_List.filter(role_type=ProfileRole.RoleType.PROFIL_PARENT)
|
||||
elif filter == 'school':
|
||||
profiles_roles_List = profiles_roles_List.filter(
|
||||
Q(role_type=ProfileRole.RoleType.PROFIL_ECOLE) |
|
||||
Q(role_type=ProfileRole.RoleType.PROFIL_ECOLE) |
|
||||
Q(role_type=ProfileRole.RoleType.PROFIL_ADMIN)
|
||||
)
|
||||
else:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
from django.urls import path, re_path
|
||||
from .views import SendEmailView
|
||||
from .views import SendEmailView, search_recipients
|
||||
from GestionMessagerie.views import MessagerieView, MessageView, MessageSimpleView
|
||||
|
||||
urlpatterns = [
|
||||
@ -7,4 +7,5 @@ urlpatterns = [
|
||||
re_path(r'^messages$', MessageView.as_view(), name="messages"),
|
||||
re_path(r'^messages/(?P<id>[0-9]+)$', MessageSimpleView.as_view(), name="messages"),
|
||||
path('send-email/', SendEmailView.as_view(), name='send_email'),
|
||||
path('search-recipients/', search_recipients, name='search_recipients'),
|
||||
]
|
||||
@ -6,12 +6,18 @@ from django.utils.html import strip_tags
|
||||
from django.conf import settings
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status
|
||||
from django.db.models import Q
|
||||
from Auth.models import Profile # Assurez-vous que le modèle Profile contient les informations nécessaires
|
||||
|
||||
from .models import *
|
||||
from School.models import Teacher, ProfileRole
|
||||
from Settings.models import SMTPSettings # Assurez-vous que le chemin est correct
|
||||
|
||||
from GestionMessagerie.serializers import MessageSerializer
|
||||
from School.serializers import TeacherSerializer
|
||||
|
||||
from N3wtSchool import bdd
|
||||
import N3wtSchool.mailManager as mailer
|
||||
|
||||
class MessagerieView(APIView):
|
||||
def get(self, request, profile_id):
|
||||
@ -46,21 +52,89 @@ class SendEmailView(APIView):
|
||||
recipients = data.get('recipients', [])
|
||||
subject = data.get('subject', 'Notification')
|
||||
message = data.get('message', '')
|
||||
establishment_id = data.get('establishment_id', '')
|
||||
|
||||
if not recipients or not message:
|
||||
return Response({'error': 'Les destinataires et le message sont requis.'}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
try:
|
||||
plain_message = strip_tags(message)
|
||||
send_mail(
|
||||
subject,
|
||||
plain_message,
|
||||
settings.EMAIL_HOST_USER,
|
||||
recipients,
|
||||
html_message=message,
|
||||
fail_silently=False,
|
||||
# Récupérer la connexion SMTP
|
||||
connection = mailer.getConnection(establishment_id)
|
||||
|
||||
# Envoyer l'email
|
||||
return mailer.sendMail(
|
||||
recipients=recipients,
|
||||
subject=subject,
|
||||
message=message,
|
||||
connection=connection
|
||||
)
|
||||
return Response({'message': 'Email envoyé avec succès.'}, status=status.HTTP_200_OK)
|
||||
except NotFound as e:
|
||||
return Response({'error': str(e)}, status=status.HTTP_404_NOT_FOUND)
|
||||
except Exception as e:
|
||||
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
class ContactsView(APIView):
|
||||
"""
|
||||
API pour récupérer les contacts associés à un établissement.
|
||||
"""
|
||||
def get(self, request, establishment_id):
|
||||
try:
|
||||
# Récupérer les enseignants associés à l'établissement
|
||||
teachers = Teacher.objects.filter(profile_role__establishment_id=establishment_id)
|
||||
teachers_serializer = TeacherSerializer(teachers, many=True)
|
||||
|
||||
# Ajouter un contact pour l'administration
|
||||
admin_contact = {
|
||||
"id": "admin",
|
||||
"name": "Administration",
|
||||
"email": "admin@etablissement.com",
|
||||
"profilePic": "https://www.gravatar.com/avatar/admin"
|
||||
}
|
||||
|
||||
contacts = [admin_contact] + teachers_serializer.data
|
||||
return Response(contacts, status=status.HTTP_200_OK)
|
||||
except Exception as e:
|
||||
return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
def search_recipients(request):
|
||||
"""
|
||||
API pour rechercher des destinataires en fonction d'un terme de recherche et d'un établissement.
|
||||
"""
|
||||
query = request.GET.get('q', '').strip() # Récupérer le terme de recherche depuis les paramètres GET
|
||||
establishment_id = request.GET.get('establishment_id', None) # Récupérer l'ID de l'établissement
|
||||
|
||||
if not query:
|
||||
return JsonResponse([], safe=False) # Retourner une liste vide si aucun terme n'est fourni
|
||||
|
||||
if not establishment_id:
|
||||
return JsonResponse({'error': 'establishment_id est requis'}, safe=False, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
# Rechercher dans les champs pertinents (nom, prénom, email) et filtrer par establishment_id
|
||||
profiles = Profile.objects.filter(
|
||||
Q(first_name__icontains=query) |
|
||||
Q(last_name__icontains=query) |
|
||||
Q(email__icontains=query),
|
||||
roles__establishment_id=establishment_id, # Utiliser 'roles' au lieu de 'profilerole'
|
||||
roles__is_active=True # Filtrer uniquement les ProfileRole actifs
|
||||
).distinct()
|
||||
|
||||
# Construire la réponse avec les rôles associés
|
||||
results = []
|
||||
for profile in profiles:
|
||||
profile_roles = ProfileRole.objects.filter(
|
||||
profile=profile,
|
||||
establishment_id=establishment_id,
|
||||
is_active=True # Inclure uniquement les ProfileRole actifs
|
||||
).values(
|
||||
'id', 'role_type', 'establishment__name', 'is_active'
|
||||
)
|
||||
results.append({
|
||||
'id': profile.id,
|
||||
'first_name': profile.first_name,
|
||||
'last_name': profile.last_name,
|
||||
'email': profile.email,
|
||||
'roles': list(profile_roles) # Inclure tous les rôles actifs associés pour cet établissement
|
||||
})
|
||||
|
||||
return JsonResponse(results, safe=False)
|
||||
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
{
|
||||
"hostSMTP": "",
|
||||
"portSMTP": 25,
|
||||
"username": "",
|
||||
"password": "",
|
||||
"useSSL": false,
|
||||
"useTLS": false
|
||||
}
|
||||
@ -1,8 +1,50 @@
|
||||
from django.core.mail import send_mail, EmailMultiAlternatives, EmailMessage
|
||||
from django.core.mail import send_mail, get_connection, EmailMultiAlternatives, EmailMessage
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.html import strip_tags
|
||||
from django.conf import settings
|
||||
import re
|
||||
from N3wtSchool import settings
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status
|
||||
from rest_framework.exceptions import NotFound
|
||||
from Settings.models import SMTPSettings
|
||||
from Establishment.models import Establishment # Importer le modèle Establishment
|
||||
|
||||
def getConnection(id_establishement):
|
||||
try:
|
||||
# Récupérer l'instance de l'établissement
|
||||
establishment = Establishment.objects.get(id=id_establishement)
|
||||
|
||||
# Récupérer les paramètres SMTP associés à l'établissement
|
||||
smtp_settings = SMTPSettings.objects.get(establishment=establishment)
|
||||
|
||||
# Créer une connexion SMTP avec les paramètres récupérés
|
||||
connection = get_connection(
|
||||
host=smtp_settings.smtp_server,
|
||||
port=smtp_settings.smtp_port,
|
||||
username=smtp_settings.smtp_user,
|
||||
password=smtp_settings.smtp_password,
|
||||
use_tls=smtp_settings.use_tls,
|
||||
use_ssl=smtp_settings.use_ssl
|
||||
)
|
||||
return connection
|
||||
|
||||
except Establishment.DoesNotExist:
|
||||
raise NotFound(f"Aucun établissement trouvé avec l'ID {id_establishement}")
|
||||
except SMTPSettings.DoesNotExist:
|
||||
raise NotFound(f"Aucun paramètre SMTP trouvé pour l'établissement {id_establishement}")
|
||||
|
||||
|
||||
def sendMail(recipients, subject, message, connection=None):
|
||||
try:
|
||||
plain_message = strip_tags(message)
|
||||
from_email = settings.EMAIL_HOST_USER
|
||||
if connection is None:
|
||||
send_mail(subject, plain_message, from_email, recipients, html_message=message, fail_silently=False)
|
||||
else:
|
||||
send_mail(subject, plain_message, from_email, recipients, html_message=message, connection=connection, fail_silently=False)
|
||||
return Response({'message': 'Email envoyé avec succès.'}, status=status.HTTP_200_OK)
|
||||
except Exception as e:
|
||||
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
def envoieReinitMotDePasse(recipients, code):
|
||||
errorMessage = ''
|
||||
@ -14,9 +56,8 @@ def envoieReinitMotDePasse(recipients, code):
|
||||
}
|
||||
subject = EMAIL_REINIT_SUBJECT
|
||||
html_message = render_to_string('emails/resetPassword.html', context)
|
||||
plain_message = strip_tags(html_message)
|
||||
from_email = settings.EMAIL_HOST_USER
|
||||
send_mail(subject, plain_message, from_email, [recipients], html_message=html_message)
|
||||
sendMail(recipients, subject, html_message)
|
||||
|
||||
except Exception as e:
|
||||
errorMessage = str(e)
|
||||
|
||||
@ -36,10 +77,8 @@ def sendRegisterForm(recipients, establishment_id):
|
||||
|
||||
subject = EMAIL_INSCRIPTION_SUBJECT
|
||||
html_message = render_to_string('emails/inscription.html', context)
|
||||
plain_message = strip_tags(html_message)
|
||||
from_email = settings.EMAIL_HOST_USER
|
||||
sendMail(recipients, subject, html_message)
|
||||
|
||||
send_mail(subject, plain_message, from_email, [recipients], html_message=html_message)
|
||||
|
||||
except Exception as e:
|
||||
errorMessage = str(e)
|
||||
@ -59,10 +98,7 @@ def sendMandatSEPA(recipients, establishment_id):
|
||||
|
||||
subject = EMAIL_INSCRIPTION_SUBJECT
|
||||
html_message = render_to_string('emails/sepa.html', context)
|
||||
plain_message = strip_tags(html_message)
|
||||
from_email = settings.EMAIL_HOST_USER
|
||||
|
||||
send_mail(subject, plain_message, from_email, [recipients], html_message=html_message)
|
||||
sendMail(recipients, subject, html_message)
|
||||
|
||||
except Exception as e:
|
||||
errorMessage = str(e)
|
||||
@ -74,13 +110,8 @@ def envoieRelanceDossierInscription(recipients, code):
|
||||
EMAIL_RELANCE_CORPUS = 'Bonjour,\nN\'ayant pas eu de retour de votre part, nous vous renvoyons le lien vers le formulaire d\'inscription : ' + BASE_URL + '/users/login\nCordialement'
|
||||
errorMessage = ''
|
||||
try:
|
||||
send_mail(
|
||||
EMAIL_RELANCE_SUBJECT,
|
||||
EMAIL_RELANCE_CORPUS%str(code),
|
||||
settings.EMAIL_HOST_USER,
|
||||
[recipients],
|
||||
fail_silently=False,
|
||||
)
|
||||
sendMail(recipients, EMAIL_RELANCE_SUBJECT, EMAIL_RELANCE_CORPUS%str(code))
|
||||
|
||||
except Exception as e:
|
||||
errorMessage = str(e)
|
||||
|
||||
@ -14,6 +14,10 @@ from pathlib import Path
|
||||
import json
|
||||
import os
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
# Configuration du logger
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
@ -219,23 +223,29 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
#################### Application Settings ##############################
|
||||
########################################################################
|
||||
|
||||
with open('Subscriptions/Configuration/application.json', 'r') as f:
|
||||
jsonObject = json.load(f)
|
||||
|
||||
|
||||
DJANGO_SUPERUSER_PASSWORD='admin'
|
||||
DJANGO_SUPERUSER_USERNAME='admin'
|
||||
DJANGO_SUPERUSER_EMAIL='admin@n3wtschool.com'
|
||||
# Configuration de l'email de l'application
|
||||
smtp_config_file = 'N3wtSchool/Configuration/application.json'
|
||||
|
||||
EMAIL_HOST='smtp.gmail.com'
|
||||
EMAIL_PORT=587
|
||||
EMAIL_HOST_USER=jsonObject['mailFrom']
|
||||
EMAIL_HOST_PASSWORD=jsonObject['password']
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
||||
EMAIL_USE_TLS = True
|
||||
EMAIL_USE_SSL = False
|
||||
|
||||
|
||||
|
||||
if os.path.exists(smtp_config_file):
|
||||
try:
|
||||
with open(smtp_config_file, 'r') as f:
|
||||
smtpSettings = json.load(f)
|
||||
EMAIL_HOST = smtpSettings.get('hostSMTP', '')
|
||||
EMAIL_PORT = smtpSettings.get('portSMTP', 587)
|
||||
EMAIL_HOST_USER = smtpSettings.get('username', '')
|
||||
EMAIL_HOST_PASSWORD = smtpSettings.get('password', '')
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
||||
EMAIL_USE_TLS = smtpSettings.get('useTLS', True)
|
||||
EMAIL_USE_SSL = smtpSettings.get('useSSL', False)
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur lors de la lecture du fichier de configuration SMTP : {e}")
|
||||
else:
|
||||
logger.error(f"Fichier de configuration SMTP introuvable : {smtp_config_file}")
|
||||
|
||||
DOCUMENT_DIR = 'documents'
|
||||
|
||||
|
||||
@ -12,25 +12,51 @@ class SMTPSettingsView(APIView):
|
||||
"""
|
||||
|
||||
@swagger_auto_schema(
|
||||
operation_description="Récupérer les paramètres SMTP",
|
||||
operation_description="Récupérer les paramètres SMTP pour un établissement spécifique ou tous les paramètres si aucun ID n'est fourni",
|
||||
manual_parameters=[
|
||||
openapi.Parameter(
|
||||
'establishment_id',
|
||||
openapi.IN_QUERY,
|
||||
description="ID de l'établissement (facultatif)",
|
||||
type=openapi.TYPE_INTEGER,
|
||||
required=False
|
||||
)
|
||||
],
|
||||
responses={
|
||||
200: SMTPSettingsSerializer(),
|
||||
200: SMTPSettingsSerializer(many=True),
|
||||
404: openapi.Response(description="Aucun paramètre SMTP trouvé."),
|
||||
500: openapi.Response(description="Erreur interne du serveur."),
|
||||
},
|
||||
)
|
||||
def get(self, request):
|
||||
establishment_id = request.query_params.get('establishment_id')
|
||||
|
||||
try:
|
||||
smtp_settings = SMTPSettings.objects.first()
|
||||
if not smtp_settings:
|
||||
return Response({'error': 'Aucun paramètre SMTP trouvé.'}, status=status.HTTP_404_NOT_FOUND)
|
||||
serializer = SMTPSettingsSerializer(smtp_settings)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
if establishment_id:
|
||||
# Récupérer les paramètres SMTP pour un établissement spécifique
|
||||
smtp_settings = SMTPSettings.objects.filter(establishment_id=establishment_id).first()
|
||||
if not smtp_settings:
|
||||
return Response(
|
||||
{'error': f"Aucun paramètre SMTP trouvé pour l'établissement {establishment_id}."},
|
||||
status=status.HTTP_404_NOT_FOUND
|
||||
)
|
||||
serializer = SMTPSettingsSerializer(smtp_settings)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
else:
|
||||
# Récupérer tous les paramètres SMTP
|
||||
smtp_settings = SMTPSettings.objects.all()
|
||||
if not smtp_settings.exists():
|
||||
return Response(
|
||||
{'error': "Aucun paramètre SMTP trouvé."},
|
||||
status=status.HTTP_404_NOT_FOUND
|
||||
)
|
||||
serializer = SMTPSettingsSerializer(smtp_settings, many=True)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
except Exception as e:
|
||||
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
@swagger_auto_schema(
|
||||
operation_description="Créer ou mettre à jour les paramètres SMTP",
|
||||
operation_description="Créer ou mettre à jour les paramètres SMTP pour un établissement spécifique",
|
||||
request_body=SMTPSettingsSerializer,
|
||||
responses={
|
||||
200: SMTPSettingsSerializer(),
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
{
|
||||
"mailFrom":"",
|
||||
"password":""
|
||||
}
|
||||
@ -11,7 +11,7 @@ import json
|
||||
import os
|
||||
from django.core.files import File
|
||||
|
||||
import Subscriptions.mailManager as mailer
|
||||
import N3wtSchool.mailManager as mailer
|
||||
import Subscriptions.util as util
|
||||
|
||||
from Subscriptions.serializers import RegistrationFormSerializer, RegistrationSchoolFileTemplateSerializer, RegistrationParentFileTemplateSerializer
|
||||
@ -302,7 +302,7 @@ class RegisterFormWithIdView(APIView):
|
||||
initial_pdf = f"{base_dir}/Inscription_{registerForm.student.last_name}_{registerForm.student.first_name}.pdf"
|
||||
registerForm.registration_file = util.rfToPDF(registerForm, initial_pdf)
|
||||
registerForm.save()
|
||||
|
||||
|
||||
# Mise à jour de l'automate
|
||||
# Vérification de la présence du fichier SEPA
|
||||
if registerForm.sepa_file:
|
||||
@ -331,7 +331,7 @@ class RegisterFormWithIdView(APIView):
|
||||
# Le parent a rempli le dossier d'inscription en sélectionnant "Prélèvement par Mandat SEPA"
|
||||
# L'école doit désormais envoyer le mandat SEPA pour poursuivre l'inscription
|
||||
updateStateMachine(registerForm, 'EVENT_WAITING_FOR_SEPA')
|
||||
|
||||
|
||||
elif _status == RegistrationForm.RegistrationFormStatus.RF_VALIDATED:
|
||||
# Vérifier si le paramètre fusion est activé via l'URL
|
||||
fusion = data.get('fusionParam', False)
|
||||
@ -486,15 +486,15 @@ def get_school_file_templates_by_rf(request, id):
|
||||
try:
|
||||
# Récupérer les templates associés au RegistrationForm donné
|
||||
templates = RegistrationSchoolFileTemplate.objects.filter(registration_form=id)
|
||||
|
||||
|
||||
# Sérialiser les données
|
||||
serializer = RegistrationSchoolFileTemplateSerializer(templates, many=True)
|
||||
|
||||
|
||||
# Retourner les données sérialisées
|
||||
return JsonResponse(serializer.data, safe=False)
|
||||
except RegistrationSchoolFileTemplate.DoesNotExist:
|
||||
return JsonResponse({'error': 'Aucun template trouvé pour ce dossier d\'inscription'}, status=status.HTTP_404_NOT_FOUND)
|
||||
|
||||
|
||||
@swagger_auto_schema(
|
||||
method='get',
|
||||
responses={200: openapi.Response('Success', schema=openapi.Schema(
|
||||
@ -511,12 +511,11 @@ def get_parent_file_templates_by_rf(request, id):
|
||||
try:
|
||||
# Récupérer les pièces à fournir associés au RegistrationForm donné
|
||||
parent_files = RegistrationParentFileTemplate.objects.filter(registration_form=id)
|
||||
|
||||
|
||||
# Sérialiser les données
|
||||
serializer = RegistrationParentFileTemplateSerializer(parent_files, many=True)
|
||||
|
||||
|
||||
# Retourner les données sérialisées
|
||||
return JsonResponse(serializer.data, safe=False)
|
||||
except RegistrationParentFileTemplate.DoesNotExist:
|
||||
return JsonResponse({'error': 'Aucune pièce à fournir trouvée pour ce dossier d\'inscription'}, status=status.HTTP_404_NOT_FOUND)
|
||||
|
||||
Reference in New Issue
Block a user