mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-29 16:03:21 +00:00
refactor: Traduction en anglais des modules "GestionInscription" et
"GestionLogin"
This commit is contained in:
@ -3,5 +3,5 @@ from django.db.models.signals import post_migrate
|
||||
|
||||
class GestionloginConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'GestionLogin'
|
||||
name = 'Auth'
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.backends import ModelBackend
|
||||
from GestionLogin.models import Profil
|
||||
from Auth.models import Profile
|
||||
from N3wtSchool import bdd
|
||||
|
||||
class EmailBackend(ModelBackend):
|
||||
def authenticate(self, request, username=None, password=None, **kwargs):
|
||||
|
||||
if username is None:
|
||||
username = kwargs.get(Profil.USERNAME_FIELD)
|
||||
username = kwargs.get(Profile.USERNAME_FIELD)
|
||||
|
||||
try:
|
||||
user = Profil.objects.get(email=username)
|
||||
user = Profile.objects.get(email=username)
|
||||
|
||||
# Vérifie le mot de passe de l'utilisateur
|
||||
if user.check_password(password):
|
||||
return user
|
||||
except Profil.DoesNotExist:
|
||||
except Profile.DoesNotExist:
|
||||
return None
|
||||
|
||||
@ -3,7 +3,7 @@ from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.core.validators import EmailValidator
|
||||
|
||||
class Profil(AbstractUser):
|
||||
class Profile(AbstractUser):
|
||||
class Droits(models.IntegerChoices):
|
||||
PROFIL_UNDEFINED = -1, _('NON DEFINI')
|
||||
PROFIL_ECOLE = 0, _('ECOLE')
|
||||
@ -1,18 +1,18 @@
|
||||
from rest_framework import serializers
|
||||
from GestionLogin.models import Profil
|
||||
from Auth.models import Profile
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
class ProfilSerializer(serializers.ModelSerializer):
|
||||
class ProfileSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False)
|
||||
password = serializers.CharField(write_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Profil
|
||||
model = Profile
|
||||
fields = ['id', 'password', 'email', 'code', 'datePeremption', 'estConnecte', 'droit', 'username', 'is_active']
|
||||
extra_kwargs = {'password': {'write_only': True}}
|
||||
|
||||
def create(self, validated_data):
|
||||
user = Profil(
|
||||
user = Profile(
|
||||
username=validated_data['username'],
|
||||
email=validated_data['email'],
|
||||
is_active=validated_data['is_active'],
|
||||
@ -29,7 +29,7 @@ class ProfilSerializer(serializers.ModelSerializer):
|
||||
|
||||
class ProfilUpdateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Profil
|
||||
model = Profile
|
||||
fields = ['id', 'password', 'email', 'code', 'datePeremption', 'estConnecte', 'droit', 'username', 'is_active']
|
||||
extra_kwargs = {
|
||||
'password': {'write_only': True, 'required': False}
|
||||
22
Back-End/Auth/urls.py
Normal file
22
Back-End/Auth/urls.py
Normal file
@ -0,0 +1,22 @@
|
||||
from django.urls import path, re_path
|
||||
|
||||
from . import views
|
||||
import Auth.views
|
||||
from Auth.views import ProfileView, ProfileListView, SessionView, LoginView, SubscribeView, NewPasswordView, ResetPasswordView
|
||||
|
||||
urlpatterns = [
|
||||
re_path(r'^csrf$', Auth.views.csrf, name='csrf'),
|
||||
|
||||
re_path(r'^login$', LoginView.as_view(), name="login"),
|
||||
re_path(r'^subscribe$', SubscribeView.as_view(), name='subscribe'),
|
||||
re_path(r'^newPassword$', NewPasswordView.as_view(), name='newPassword'),
|
||||
re_path(r'^resetPassword/([a-zA-Z]+)$', ResetPasswordView.as_view(), name='resetPassword'),
|
||||
re_path(r'^infoSession$', Auth.views.infoSession, name='infoSession'),
|
||||
|
||||
re_path(r'^profiles$', ProfileListView.as_view(), name="profile"),
|
||||
re_path(r'^profile$', ProfileView.as_view(), name="profile"),
|
||||
re_path(r'^profile/([0-9]+)$', ProfileView.as_view(), name="profile"),
|
||||
|
||||
# Test SESSION VIEW
|
||||
re_path(r'^session$', SessionView.as_view(), name="session"),
|
||||
]
|
||||
@ -15,13 +15,13 @@ import jwt
|
||||
import json
|
||||
|
||||
from . import validator
|
||||
from .models import Profil
|
||||
from .models import Profile
|
||||
|
||||
from GestionLogin.serializers import ProfilSerializer, ProfilUpdateSerializer
|
||||
from GestionInscriptions.models import FicheInscription
|
||||
from GestionInscriptions.signals import clear_cache
|
||||
import GestionInscriptions.mailManager as mailer
|
||||
import GestionInscriptions.util as util
|
||||
from Auth.serializers import ProfileSerializer, ProfilUpdateSerializer
|
||||
from Subscriptions.models import RegistrationForm
|
||||
from Subscriptions.signals import clear_cache
|
||||
import Subscriptions.mailManager as mailer
|
||||
import Subscriptions.util as util
|
||||
|
||||
from N3wtSchool import bdd, error
|
||||
|
||||
@ -38,7 +38,7 @@ class SessionView(APIView):
|
||||
decoded_token = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
|
||||
print(f'decode : {decoded_token}')
|
||||
user_id = decoded_token.get('id')
|
||||
user = Profil.objects.get(id=user_id)
|
||||
user = Profile.objects.get(id=user_id)
|
||||
|
||||
response_data = {
|
||||
'user': {
|
||||
@ -53,24 +53,24 @@ class SessionView(APIView):
|
||||
except jwt.InvalidTokenError:
|
||||
return JsonResponse({"error": "Invalid token"}, status=status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
class ListProfilView(APIView):
|
||||
class ProfileListView(APIView):
|
||||
def get(self, request):
|
||||
profilsList = bdd.getAllObjects(_objectName=Profil)
|
||||
profils_serializer = ProfilSerializer(profilsList, many=True)
|
||||
profilsList = bdd.getAllObjects(_objectName=Profile)
|
||||
profils_serializer = ProfileSerializer(profilsList, many=True)
|
||||
return JsonResponse(profils_serializer.data, safe=False)
|
||||
|
||||
@method_decorator(csrf_protect, name='dispatch')
|
||||
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
||||
class ProfilView(APIView):
|
||||
class ProfileView(APIView):
|
||||
def get(self, request, _id):
|
||||
profil=bdd.getObject(Profil, "id", _id)
|
||||
profil_serializer=ProfilSerializer(profil)
|
||||
profil=bdd.getObject(Profile, "id", _id)
|
||||
profil_serializer=ProfileSerializer(profil)
|
||||
return JsonResponse(profil_serializer.data, safe=False)
|
||||
|
||||
def post(self, request):
|
||||
profil_data=JSONParser().parse(request)
|
||||
print(f'{profil_data}')
|
||||
profil_serializer = ProfilSerializer(data=profil_data)
|
||||
profil_serializer = ProfileSerializer(data=profil_data)
|
||||
|
||||
if profil_serializer.is_valid():
|
||||
profil_serializer.save()
|
||||
@ -82,7 +82,7 @@ class ProfilView(APIView):
|
||||
|
||||
def put(self, request, _id):
|
||||
data=JSONParser().parse(request)
|
||||
profil = Profil.objects.get(id=_id)
|
||||
profil = Profile.objects.get(id=_id)
|
||||
profil_serializer = ProfilUpdateSerializer(profil, data=data)
|
||||
if profil_serializer.is_valid():
|
||||
profil_serializer.save()
|
||||
@ -95,7 +95,7 @@ def infoSession(request):
|
||||
if profilCache:
|
||||
return JsonResponse({"cacheSession":True,"typeProfil":profilCache.droit, "username":profilCache.email}, safe=False)
|
||||
else:
|
||||
return JsonResponse({"cacheSession":False,"typeProfil":Profil.Droits.PROFIL_UNDEFINED, "username":""}, safe=False)
|
||||
return JsonResponse({"cacheSession":False,"typeProfil":Profile.Droits.PROFIL_UNDEFINED, "username":""}, safe=False)
|
||||
|
||||
@method_decorator(csrf_protect, name='dispatch')
|
||||
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
||||
@ -170,7 +170,7 @@ class SubscribeView(APIView):
|
||||
if validationOk:
|
||||
|
||||
# On vérifie que l'email existe : si ce n'est pas le cas, on retourne une erreur
|
||||
profil = bdd.getProfile(Profil.objects.all(), newProfilConnection.get('email'))
|
||||
profil = bdd.getProfile(Profile.objects.all(), newProfilConnection.get('email'))
|
||||
if profil == None:
|
||||
retourErreur = error.returnMessage[error.PROFIL_NOT_EXISTS]
|
||||
else:
|
||||
@ -214,7 +214,7 @@ class NewPasswordView(APIView):
|
||||
validationOk, errorFields = validatorNewPassword.validate()
|
||||
if validationOk:
|
||||
|
||||
profil = bdd.getProfile(Profil.objects.all(), newProfilConnection.get('email'))
|
||||
profil = bdd.getProfile(Profile.objects.all(), newProfilConnection.get('email'))
|
||||
if profil == None:
|
||||
retourErreur = error.returnMessage[error.PROFIL_NOT_EXISTS]
|
||||
else:
|
||||
@ -247,7 +247,7 @@ class ResetPasswordView(APIView):
|
||||
validatorResetPassword = validator.ValidatorResetPassword(data=newProfilConnection)
|
||||
validationOk, errorFields = validatorResetPassword.validate()
|
||||
|
||||
profil = bdd.getObject(Profil, "code", _uuid)
|
||||
profil = bdd.getObject(Profile, "code", _uuid)
|
||||
if profil:
|
||||
|
||||
if datetime.strptime(util.convertToStr(util._now(), '%d-%m-%Y %H:%M'), '%d-%m-%Y %H:%M') > datetime.strptime(profil.datePeremption, '%d-%m-%Y %H:%M'):
|
||||
@ -1 +0,0 @@
|
||||
default_app_config = 'GestionEnseignants.apps.GestionenseignantsConfig'
|
||||
@ -1,14 +0,0 @@
|
||||
from django.apps import AppConfig
|
||||
from django.db.models.signals import post_migrate
|
||||
|
||||
def create_specialite(sender, **kwargs):
|
||||
from .models import Specialite
|
||||
if not Specialite.objects.filter(nom='GROUPE').exists():
|
||||
Specialite.objects.create(nom='GROUPE', codeCouleur='#FF0000')
|
||||
|
||||
class GestionenseignantsConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'GestionEnseignants'
|
||||
|
||||
def ready(self):
|
||||
post_migrate.connect(create_specialite, sender=self)
|
||||
@ -1,68 +0,0 @@
|
||||
from django.db import models
|
||||
from GestionLogin.models import Profil
|
||||
from django.db.models import JSONField
|
||||
from django.dispatch import receiver
|
||||
from django.contrib.postgres.fields import ArrayField
|
||||
|
||||
NIVEAU_CHOICES = [
|
||||
(1, 'Très Petite Section (TPS)'),
|
||||
(2, 'Petite Section (PS)'),
|
||||
(3, 'Moyenne Section (MS)'),
|
||||
(4, 'Grande Section (GS)'),
|
||||
(5, 'Cours Préparatoire (CP)'),
|
||||
(6, 'Cours Élémentaire 1 (CE1)'),
|
||||
(7, 'Cours Élémentaire 2 (CE2)'),
|
||||
(8, 'Cours Moyen 1 (CM1)'),
|
||||
(9, 'Cours Moyen 2 (CM2)')
|
||||
]
|
||||
|
||||
class Specialite(models.Model):
|
||||
nom = models.CharField(max_length=100)
|
||||
dateCreation = models.DateTimeField(auto_now=True)
|
||||
codeCouleur = models.CharField(max_length=7, default='#FFFFFF')
|
||||
|
||||
def __str__(self):
|
||||
return self.nom
|
||||
|
||||
class Enseignant(models.Model):
|
||||
nom = models.CharField(max_length=100)
|
||||
prenom = models.CharField(max_length=100)
|
||||
mail = models.EmailField(unique=True)
|
||||
specialites = models.ManyToManyField(Specialite, related_name='enseignants')
|
||||
profilAssocie = models.ForeignKey(Profil, on_delete=models.CASCADE, null=True, blank=True)
|
||||
dateCreation = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.nom} {self.prenom}"
|
||||
|
||||
class Classe(models.Model):
|
||||
PLANNING_TYPE_CHOICES = [
|
||||
(1, 'Annuel'),
|
||||
(2, 'Semestriel'),
|
||||
(3, 'Trimestriel')
|
||||
]
|
||||
|
||||
nom_ambiance = models.CharField(max_length=255, null=True, blank=True)
|
||||
tranche_age = models.JSONField()
|
||||
nombre_eleves = models.PositiveIntegerField()
|
||||
langue_enseignement = models.CharField(max_length=255)
|
||||
annee_scolaire = models.CharField(max_length=9)
|
||||
dateCreation = models.DateTimeField(auto_now_add=True)
|
||||
enseignants = models.ManyToManyField(Enseignant, related_name='classes')
|
||||
niveaux = ArrayField(models.IntegerField(choices=NIVEAU_CHOICES), default=list)
|
||||
type = models.IntegerField(choices=PLANNING_TYPE_CHOICES, default=1)
|
||||
plage_horaire = models.JSONField(default=list)
|
||||
jours_ouverture = ArrayField(models.IntegerField(), default=list)
|
||||
|
||||
def __str__(self):
|
||||
return self.nom_ambiance
|
||||
|
||||
class Planning(models.Model):
|
||||
niveau = models.IntegerField(choices=NIVEAU_CHOICES, null=True, blank=True)
|
||||
classe = models.ForeignKey(Classe, null=True, blank=True, related_name='plannings', on_delete=models.CASCADE)
|
||||
emploiDuTemps = JSONField(default=dict)
|
||||
|
||||
def __str__(self):
|
||||
return f'Planning de {self.niveau} pour {self.classe.nom_ambiance}'
|
||||
|
||||
|
||||
@ -1,236 +0,0 @@
|
||||
from rest_framework import serializers
|
||||
from .models import Enseignant, Specialite, Classe, Planning, NIVEAU_CHOICES
|
||||
from GestionInscriptions.models import FicheInscription
|
||||
from GestionInscriptions.serializers import EleveSerializer
|
||||
from GestionLogin.serializers import ProfilSerializer
|
||||
from GestionLogin.models import Profil
|
||||
from N3wtSchool import settings, bdd
|
||||
from django.utils import timezone
|
||||
import pytz
|
||||
|
||||
class SpecialiteSerializer(serializers.ModelSerializer):
|
||||
dateCreation_formattee = serializers.SerializerMethodField()
|
||||
class Meta:
|
||||
model = Specialite
|
||||
fields = '__all__'
|
||||
|
||||
def get_dateCreation_formattee(self, obj):
|
||||
utc_time = timezone.localtime(obj.dateCreation) # Convertir en heure locale
|
||||
local_tz = pytz.timezone(settings.TZ_APPLI)
|
||||
local_time = utc_time.astimezone(local_tz)
|
||||
|
||||
return local_time.strftime("%d-%m-%Y %H:%M")
|
||||
|
||||
class EnseignantDetailSerializer(serializers.ModelSerializer):
|
||||
specialites = SpecialiteSerializer(many=True, read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Enseignant
|
||||
fields = ['id', 'nom', 'prenom', 'mail', 'specialites']
|
||||
|
||||
class EnseignantSerializer(serializers.ModelSerializer):
|
||||
specialites = SpecialiteSerializer(many=True, read_only=True)
|
||||
specialites_ids = serializers.PrimaryKeyRelatedField(queryset=Specialite.objects.all(), many=True, source='specialites')
|
||||
profilAssocie_id = serializers.PrimaryKeyRelatedField(queryset=Profil.objects.all(), source='profilAssocie', write_only=False, read_only=False)
|
||||
classes_principal = serializers.PrimaryKeyRelatedField(many=True, read_only=True, source='classes')
|
||||
profilAssocie = ProfilSerializer(read_only=True)
|
||||
DroitLabel = serializers.SerializerMethodField()
|
||||
DroitValue = serializers.SerializerMethodField()
|
||||
dateCreation_formattee = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Enseignant
|
||||
fields = ['id', 'nom', 'prenom', 'mail', 'specialites', 'specialites_ids', 'classes_principal', 'profilAssocie', 'profilAssocie_id', 'DroitLabel', 'DroitValue', 'dateCreation', 'dateCreation_formattee']
|
||||
|
||||
def create(self, validated_data):
|
||||
specialites_data = validated_data.pop('specialites', None)
|
||||
profilAssocie = validated_data.pop('profilAssocie', None)
|
||||
enseignant = Enseignant.objects.create(**validated_data)
|
||||
enseignant.specialites.set(specialites_data)
|
||||
if profilAssocie:
|
||||
enseignant.profilAssocie = profilAssocie
|
||||
enseignant.save()
|
||||
return enseignant
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
specialites_data = validated_data.pop('specialites', [])
|
||||
instance.nom = validated_data.get('nom', instance.nom)
|
||||
instance.prenom = validated_data.get('prenom', instance.prenom)
|
||||
instance.mail = validated_data.get('mail', instance.mail)
|
||||
instance.profilAssocie = validated_data.get('profilAssocie', instance.profilAssocie)
|
||||
instance.save()
|
||||
instance.specialites.set(specialites_data)
|
||||
return instance
|
||||
|
||||
def get_DroitLabel(self, obj):
|
||||
return obj.profilAssocie.get_droit_display() if obj.profilAssocie else None
|
||||
|
||||
def get_DroitValue(self, obj):
|
||||
return obj.profilAssocie.droit if obj.profilAssocie else None
|
||||
|
||||
def get_dateCreation_formattee(self, obj):
|
||||
utc_time = timezone.localtime(obj.dateCreation) # Convertir en heure locale
|
||||
local_tz = pytz.timezone(settings.TZ_APPLI)
|
||||
local_time = utc_time.astimezone(local_tz)
|
||||
return local_time.strftime("%d-%m-%Y %H:%M")
|
||||
|
||||
class PlanningSerializer(serializers.ModelSerializer):
|
||||
# emploiDuTemps = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Planning
|
||||
fields = ['id', 'niveau', 'emploiDuTemps']
|
||||
|
||||
# def get_emploiDuTemps(self, obj):
|
||||
# emploi_du_temps = obj.emploiDuTemps
|
||||
# if obj.classe:
|
||||
# enseignants = obj.classe.enseignants.all() # Récupérer tous les enseignants associés à la classe
|
||||
|
||||
# # Dictionnaire pour accéder rapidement aux spécialités des enseignants
|
||||
# specialite_enseignants = {}
|
||||
# for enseignant in enseignants:
|
||||
# for specialite in enseignant.specialites.all():
|
||||
# if specialite.nom not in specialite_enseignants:
|
||||
# specialite_enseignants[specialite.nom] = []
|
||||
# specialite_enseignants[specialite.nom].append(f"{enseignant.prenom} {enseignant.nom}")
|
||||
|
||||
# if obj.classe.type == 1: # Planning annuel
|
||||
# for day, events in emploi_du_temps.items():
|
||||
# for event in events:
|
||||
# # Ajouter les enseignants associés à la spécialité
|
||||
# event['teachers'] = specialite_enseignants.get(event['matiere'], [])
|
||||
# # Ajouter la couleur de la spécialité
|
||||
# event['color'] = next(
|
||||
# (specialite.codeCouleur for enseignant in enseignants for specialite in enseignant.specialites.all() if specialite.nom == event['matiere']),
|
||||
# "#FFFFFF" # Couleur par défaut si non trouvée
|
||||
# )
|
||||
|
||||
# elif obj.classe.type in [2, 3]: # Planning semestriel ou trimestriel
|
||||
# for period_key, period_value in emploi_du_temps.items():
|
||||
# for day, events in period_value.items():
|
||||
# if day in ['DateDebut', 'DateFin']:
|
||||
# continue # Ignorer les clés DateDebut et DateFin
|
||||
# for event in events:
|
||||
# print(f'event : {event}')
|
||||
# # Ajouter les enseignants associés à la spécialité
|
||||
# event['teachers'] = specialite_enseignants.get(event['matiere'], [])
|
||||
# # Ajouter la couleur de la spécialité
|
||||
# event['color'] = next(
|
||||
# (specialite.codeCouleur for enseignant in enseignants for specialite in enseignant.specialites.all() if specialite.nom == event['matiere']),
|
||||
# "#FFFFFF" # Couleur par défaut si non trouvée
|
||||
# )
|
||||
|
||||
# return emploi_du_temps
|
||||
|
||||
def to_internal_value(self, data):
|
||||
internal_value = super().to_internal_value(data)
|
||||
internal_value['emploiDuTemps'] = data.get('emploiDuTemps', {})
|
||||
return internal_value
|
||||
|
||||
class ClasseSerializer(serializers.ModelSerializer):
|
||||
dateCreation_formattee = serializers.SerializerMethodField()
|
||||
enseignants = EnseignantSerializer(many=True, read_only=True)
|
||||
enseignants_ids = serializers.PrimaryKeyRelatedField(queryset=Enseignant.objects.all(), many=True, source='enseignants')
|
||||
eleves = serializers.SerializerMethodField()
|
||||
niveaux = serializers.ListField(child=serializers.ChoiceField(choices=NIVEAU_CHOICES))
|
||||
plannings_read = serializers.SerializerMethodField()
|
||||
plannings = PlanningSerializer(many=True, write_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Classe
|
||||
fields = [
|
||||
'id', 'nom_ambiance', 'tranche_age', 'nombre_eleves', 'langue_enseignement',
|
||||
'enseignants', 'enseignants_ids', 'annee_scolaire', 'dateCreation',
|
||||
'dateCreation_formattee', 'eleves', 'niveaux', 'type', 'plage_horaire',
|
||||
'jours_ouverture', 'plannings', 'plannings_read'
|
||||
]
|
||||
|
||||
def create(self, validated_data):
|
||||
enseignants_data = validated_data.pop('enseignants', [])
|
||||
niveaux_data = validated_data.pop('niveaux', [])
|
||||
plannings_data = validated_data.pop('plannings', [])
|
||||
|
||||
classe = Classe.objects.create(
|
||||
nom_ambiance=validated_data.get('nom_ambiance', ''),
|
||||
tranche_age=validated_data.get('tranche_age', []),
|
||||
nombre_eleves=validated_data.get('nombre_eleves', 0),
|
||||
langue_enseignement=validated_data.get('langue_enseignement', ''),
|
||||
annee_scolaire=validated_data.get('annee_scolaire', ''),
|
||||
niveaux=niveaux_data,
|
||||
type=validated_data.get('type', 1), # Ajouté ici
|
||||
plage_horaire=validated_data.get('plage_horaire', ['08:30', '17:30']), # Ajouté ici
|
||||
jours_ouverture=validated_data.get('jours_ouverture', [1, 2, 4, 5]) # Ajouté ici
|
||||
)
|
||||
|
||||
classe.enseignants.set(enseignants_data)
|
||||
|
||||
for planning_data in plannings_data:
|
||||
Planning.objects.create(
|
||||
classe=classe,
|
||||
niveau=planning_data['niveau'],
|
||||
emploiDuTemps=planning_data.get('emploiDuTemps', {})
|
||||
)
|
||||
|
||||
return classe
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
enseignants_data = validated_data.pop('enseignants', [])
|
||||
niveaux_data = validated_data.pop('niveaux', [])
|
||||
plannings_data = validated_data.pop('plannings', [])
|
||||
|
||||
instance.nom_ambiance = validated_data.get('nom_ambiance', instance.nom_ambiance)
|
||||
instance.tranche_age = validated_data.get('tranche_age', instance.tranche_age)
|
||||
instance.nombre_eleves = validated_data.get('nombre_eleves', instance.nombre_eleves)
|
||||
instance.langue_enseignement = validated_data.get('langue_enseignement', instance.langue_enseignement)
|
||||
instance.annee_scolaire = validated_data.get('annee_scolaire', instance.annee_scolaire)
|
||||
instance.niveaux = niveaux_data
|
||||
instance.type = validated_data.get('type', instance.type) # Ajouté ici
|
||||
instance.plage_horaire = validated_data.get('plage_horaire', instance.plage_horaire) # Ajouté ici
|
||||
instance.jours_ouverture = validated_data.get('jours_ouverture', instance.jours_ouverture) # Ajouté ici
|
||||
|
||||
instance.save()
|
||||
instance.enseignants.set(enseignants_data)
|
||||
|
||||
existing_plannings = {planning.niveau: planning for planning in instance.plannings.all()}
|
||||
|
||||
for planning_data in plannings_data:
|
||||
niveau = planning_data['niveau']
|
||||
if niveau in existing_plannings:
|
||||
# Mettre à jour le planning existant
|
||||
planning = existing_plannings[niveau]
|
||||
planning.emploiDuTemps = planning_data.get('emploiDuTemps', planning.emploiDuTemps)
|
||||
planning.save()
|
||||
else:
|
||||
# Créer un nouveau planning si niveau non existant
|
||||
Planning.objects.create(
|
||||
classe=instance,
|
||||
niveau=niveau,
|
||||
emploiDuTemps=planning_data.get('emploiDuTemps', {})
|
||||
)
|
||||
|
||||
return instance
|
||||
|
||||
def get_dateCreation_formattee(self, obj):
|
||||
utc_time = timezone.localtime(obj.dateCreation)
|
||||
local_tz = pytz.timezone(settings.TZ_APPLI)
|
||||
local_time = utc_time.astimezone(local_tz)
|
||||
return local_time.strftime("%d-%m-%Y %H:%M")
|
||||
|
||||
def get_eleves(self, obj):
|
||||
elevesList = obj.eleves.all()
|
||||
filtered_eleves = []
|
||||
for eleve in elevesList:
|
||||
ficheInscription = bdd.getObject(FicheInscription, "eleve__id", eleve.id)
|
||||
if ficheInscription.etat == ficheInscription.EtatDossierInscription.DI_VALIDE:
|
||||
filtered_eleves.append(eleve)
|
||||
return EleveSerializer(filtered_eleves, many=True, read_only=True).data
|
||||
|
||||
def get_plannings_read(self, obj):
|
||||
plannings = obj.plannings.all()
|
||||
niveaux_dict = {niveau: {'niveau': niveau, 'planning': None} for niveau in obj.niveaux}
|
||||
|
||||
for planning in plannings:
|
||||
if planning.niveau in niveaux_dict:
|
||||
niveaux_dict[planning.niveau]['planning'] = PlanningSerializer(planning).data
|
||||
|
||||
return list(niveaux_dict.values())
|
||||
@ -1,21 +0,0 @@
|
||||
from django.urls import path, re_path
|
||||
|
||||
from GestionEnseignants.views import EnseignantsView, EnseignantView, SpecialitesView, SpecialiteView, ClassesView, ClasseView, PlanningsView, PlanningView
|
||||
|
||||
urlpatterns = [
|
||||
re_path(r'^enseignants$', EnseignantsView.as_view(), name="enseignants"),
|
||||
re_path(r'^enseignant$', EnseignantView.as_view(), name="enseignant"),
|
||||
re_path(r'^enseignant/([0-9]+)$', EnseignantView.as_view(), name="enseignant"),
|
||||
|
||||
re_path(r'^specialites$', SpecialitesView.as_view(), name="specialites"),
|
||||
re_path(r'^specialite$', SpecialiteView.as_view(), name="specialite"),
|
||||
re_path(r'^specialite/([0-9]+)$', SpecialiteView.as_view(), name="specialite"),
|
||||
|
||||
re_path(r'^classes$', ClassesView.as_view(), name="classes"),
|
||||
re_path(r'^classe$', ClasseView.as_view(), name="classe"),
|
||||
re_path(r'^classe/([0-9]+)$', ClasseView.as_view(), name="classe"),
|
||||
|
||||
re_path(r'^plannings$', PlanningsView.as_view(), name="plannings"),
|
||||
re_path(r'^planning$', PlanningView.as_view(), name="planning"),
|
||||
re_path(r'^planning/([0-9]+)$', PlanningView.as_view(), name="planning"),
|
||||
]
|
||||
@ -1 +0,0 @@
|
||||
default_app_config = 'GestionInscriptions.apps.GestionInscriptionsConfig'
|
||||
@ -1,45 +0,0 @@
|
||||
# state_machine.py
|
||||
import json
|
||||
from GestionInscriptions.models import FicheInscription
|
||||
from GestionInscriptions.signals import clear_cache
|
||||
|
||||
state_mapping = {
|
||||
"ABSENT": FicheInscription.EtatDossierInscription.DI_ABSENT,
|
||||
"CREE": FicheInscription.EtatDossierInscription.DI_CREE,
|
||||
"ENVOYE": FicheInscription.EtatDossierInscription.DI_ENVOYE,
|
||||
"EN_VALIDATION": FicheInscription.EtatDossierInscription.DI_EN_VALIDATION,
|
||||
"A_RELANCER": FicheInscription.EtatDossierInscription.DI_A_RELANCER,
|
||||
"VALIDE": FicheInscription.EtatDossierInscription.DI_VALIDE,
|
||||
"ARCHIVE": FicheInscription.EtatDossierInscription.DI_ARCHIVE
|
||||
}
|
||||
|
||||
def load_config(config_file):
|
||||
with open(config_file, 'r') as file:
|
||||
config = json.load(file)
|
||||
return config
|
||||
|
||||
def getStateMachineObject(etat) :
|
||||
return Automate_DI_Inscription(etat)
|
||||
|
||||
def getStateMachineObjectState(etat):
|
||||
return Automate_DI_Inscription(etat).state
|
||||
|
||||
def updateStateMachine(di, transition) :
|
||||
automateModel = load_config('GestionInscriptions/Configuration/automate.json')
|
||||
state_machine = getStateMachineObject(di.etat)
|
||||
print(f'etat DI : {state_machine.state}')
|
||||
if state_machine.trigger(transition, automateModel):
|
||||
di.etat = state_machine.state
|
||||
di.save()
|
||||
clear_cache()
|
||||
|
||||
class Automate_DI_Inscription:
|
||||
def __init__(self, initial_state):
|
||||
self.state = initial_state
|
||||
|
||||
def trigger(self, transition_name, config):
|
||||
for transition in config["transitions"]:
|
||||
if transition["name"] == transition_name and self.state == state_mapping[transition["from"]]:
|
||||
self.state = state_mapping[transition["to"]]
|
||||
return True
|
||||
return False
|
||||
@ -1,179 +0,0 @@
|
||||
from django.db import models
|
||||
from django.utils.timezone import now
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from GestionLogin.models import Profil
|
||||
from GestionEnseignants.models import Classe
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
class FraisInscription(models.Model):
|
||||
class OptionsPaiements(models.IntegerChoices):
|
||||
PAIEMENT_1_FOIS = 0, _('Paiement en une seule fois')
|
||||
PAIEMENT_MENSUEL = 1, _('Paiement mensuel')
|
||||
PAIEMENT_TRIMESTRIEL = 2, _('Paiement trimestriel')
|
||||
|
||||
nom = models.CharField(max_length=255, unique=True)
|
||||
description = models.TextField(blank=True)
|
||||
montant_de_base = models.DecimalField(max_digits=10, decimal_places=2)
|
||||
reductions = models.JSONField(blank=True, null=True)
|
||||
supplements = models.JSONField(blank=True, null=True)
|
||||
date_debut_validite = models.DateField()
|
||||
date_fin_validite = models.DateField()
|
||||
options_paiement = models.IntegerField(choices=OptionsPaiements, default=OptionsPaiements.PAIEMENT_1_FOIS)
|
||||
|
||||
def __str__(self):
|
||||
return self.nom
|
||||
|
||||
class Langue(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
libelle = models.CharField(max_length=200, default="")
|
||||
|
||||
def __str__(self):
|
||||
return "LANGUE"
|
||||
|
||||
class Responsable(models.Model):
|
||||
nom = models.CharField(max_length=200, default="")
|
||||
prenom = models.CharField(max_length=200, default="")
|
||||
dateNaissance = models.CharField(max_length=200, default="", blank=True)
|
||||
adresse = models.CharField(max_length=200, default="", blank=True)
|
||||
mail = models.CharField(max_length=200, default="", blank=True)
|
||||
telephone = models.CharField(max_length=200, default="", blank=True)
|
||||
profession = models.CharField(max_length=200, default="", blank=True)
|
||||
profilAssocie = models.ForeignKey(Profil, on_delete=models.CASCADE)
|
||||
|
||||
def __str__(self):
|
||||
return self.nom + "_" + self.prenom
|
||||
|
||||
class Frere(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
nom = models.CharField(max_length=200, default="")
|
||||
prenom = models.CharField(max_length=200, default="")
|
||||
dateNaissance = models.CharField(max_length=200, default="", blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return "FRERE"
|
||||
|
||||
class Eleve(models.Model):
|
||||
|
||||
class GenreEleve(models.IntegerChoices):
|
||||
NONE = 0, _('Sélection du genre')
|
||||
MALE = 1, _('Garçon')
|
||||
FEMALE = 2, _('Fille')
|
||||
|
||||
class NiveauEleve(models.IntegerChoices):
|
||||
NONE = 0, _('Sélection du niveau')
|
||||
TPS = 1, _('TPS - Très Petite Section')
|
||||
PS = 2, _('PS - Petite Section')
|
||||
MS = 3, _('MS - Moyenne Section')
|
||||
GS = 4, _('GS - Grande Section')
|
||||
|
||||
class ModePaiement(models.IntegerChoices):
|
||||
NONE = 0, _('Sélection du mode de paiement')
|
||||
PRELEVEMENT_SEPA = 1, _('Prélèvement SEPA')
|
||||
CHEQUE = 2, _('Chèque')
|
||||
|
||||
nom = models.CharField(max_length=200, default="")
|
||||
prenom = models.CharField(max_length=200, default="")
|
||||
genre = models.IntegerField(choices=GenreEleve, default=GenreEleve.NONE, blank=True)
|
||||
niveau = models.IntegerField(choices=NiveauEleve, default=NiveauEleve.NONE, blank=True)
|
||||
nationalite = models.CharField(max_length=200, default="", blank=True)
|
||||
adresse = models.CharField(max_length=200, default="", blank=True)
|
||||
dateNaissance = models.DateField(null=True, blank=True)
|
||||
lieuNaissance = models.CharField(max_length=200, default="", blank=True)
|
||||
codePostalNaissance = models.IntegerField(default=0, blank=True)
|
||||
medecinTraitant = models.CharField(max_length=200, default="", blank=True)
|
||||
modePaiement = models.IntegerField(choices=ModePaiement, default=ModePaiement.NONE, blank=True)
|
||||
|
||||
# Relation N-N
|
||||
profils = models.ManyToManyField(Profil, blank=True)
|
||||
|
||||
# Relation N-N
|
||||
responsables = models.ManyToManyField(Responsable, blank=True)
|
||||
|
||||
# Relation N-N
|
||||
freres = models.ManyToManyField(Frere, blank=True)
|
||||
|
||||
# Relation N-N
|
||||
languesParlees = models.ManyToManyField(Langue, blank=True)
|
||||
|
||||
# Relation 1-N
|
||||
classeAssociee = models.ForeignKey(Classe, on_delete=models.SET_NULL, null=True, blank=True, related_name='eleves')
|
||||
|
||||
def __str__(self):
|
||||
return self.nom + "_" + self.prenom
|
||||
|
||||
def getLanguesParlees(self):
|
||||
return self.languesParlees.all()
|
||||
|
||||
def getResponsablePrincipal(self):
|
||||
return self.responsables.all()[0]
|
||||
|
||||
def getResponsables(self):
|
||||
return self.responsables.all()
|
||||
|
||||
def getProfils(self):
|
||||
return self.profils.all()
|
||||
|
||||
def getFreres(self):
|
||||
return self.freres.all()
|
||||
|
||||
def getNbFreres(self):
|
||||
return self.freres.count()
|
||||
|
||||
@property
|
||||
def age(self):
|
||||
if self.dateNaissance:
|
||||
today = datetime.today()
|
||||
years = today.year - self.dateNaissance.year
|
||||
months = today.month - self.dateNaissance.month
|
||||
if today.day < self.dateNaissance.day:
|
||||
months -= 1
|
||||
if months < 0:
|
||||
years -= 1
|
||||
months += 12
|
||||
|
||||
# Déterminer le format de l'âge
|
||||
if months >= 6 and months <= 12:
|
||||
return f"{years} ans 1/2"
|
||||
else:
|
||||
return f"{years} ans"
|
||||
return None
|
||||
|
||||
@property
|
||||
def dateNaissance_formattee(self):
|
||||
if self.dateNaissance:
|
||||
return self.dateNaissance.strftime('%d-%m-%Y')
|
||||
return None
|
||||
|
||||
class FicheInscription(models.Model):
|
||||
|
||||
class EtatDossierInscription(models.IntegerChoices):
|
||||
DI_ABSENT = 0, _('Pas de dossier d\'inscription')
|
||||
DI_CREE = 1, _('Dossier d\'inscription créé')
|
||||
DI_ENVOYE = 2, _('Dossier d\'inscription envoyé')
|
||||
DI_EN_VALIDATION = 3, _('Dossier d\'inscription en cours de validation')
|
||||
DI_A_RELANCER = 4, _('Dossier d\'inscription à relancer')
|
||||
DI_VALIDE = 5, _('Dossier d\'inscription validé')
|
||||
DI_ARCHIVE = 6, _('Dossier d\'inscription archivé')
|
||||
|
||||
# Relation 1-1
|
||||
eleve = models.OneToOneField(Eleve, on_delete=models.CASCADE, primary_key=True)
|
||||
etat = models.IntegerField(choices=EtatDossierInscription, default=EtatDossierInscription.DI_ABSENT)
|
||||
dateMAJ = models.DateTimeField(auto_now=True)
|
||||
notes = models.CharField(max_length=200, blank=True)
|
||||
codeLienInscription = models.CharField(max_length=200, default="", blank=True)
|
||||
fichierInscription = models.FileField(upload_to=settings.DOCUMENT_DIR, default="", blank=True)
|
||||
di_associe = models.CharField(max_length=200, default="", blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return "FI_" + self.eleve.nom + "_" + self.eleve.prenom
|
||||
|
||||
class FichierInscription(models.Model):
|
||||
name = models.CharField(max_length=255)
|
||||
file = models.FileField(upload_to='fichiers_inscription/')
|
||||
date_ajout = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.nom
|
||||
@ -1,202 +0,0 @@
|
||||
from rest_framework import serializers
|
||||
from GestionInscriptions.models import FichierInscription, FicheInscription, Eleve, Responsable, Frere, Langue, FraisInscription
|
||||
from GestionEnseignants.models import Classe
|
||||
from GestionLogin.models import Profil
|
||||
from GestionLogin.serializers import ProfilSerializer
|
||||
from GestionMessagerie.models import Messagerie
|
||||
from GestionNotification.models import Notification
|
||||
from N3wtSchool import settings
|
||||
from django.utils import timezone
|
||||
import pytz
|
||||
from datetime import datetime
|
||||
|
||||
class FichierInscriptionSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = FichierInscription
|
||||
fields = '__all__'
|
||||
class FraisInscriptionSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False)
|
||||
class Meta:
|
||||
model = FraisInscription
|
||||
fields = '__all__'
|
||||
|
||||
class LanguesSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False)
|
||||
class Meta:
|
||||
model = Langue
|
||||
fields = '__all__'
|
||||
|
||||
class FrereSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False)
|
||||
class Meta:
|
||||
model = Frere
|
||||
fields = '__all__'
|
||||
|
||||
class ResponsableSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False)
|
||||
profil_associe = serializers.SerializerMethodField()
|
||||
class Meta:
|
||||
model = Responsable
|
||||
fields = '__all__'
|
||||
|
||||
def get_profil_associe(self, obj):
|
||||
return obj.profilAssocie.email
|
||||
|
||||
class EleveSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False)
|
||||
responsables = ResponsableSerializer(many=True, required=False)
|
||||
freres = FrereSerializer(many=True, required=False)
|
||||
langues = LanguesSerializer(many=True, required=False)
|
||||
classeAssocie_id = serializers.PrimaryKeyRelatedField(queryset=Classe.objects.all(), source='classeAssociee', required=False, write_only=False, read_only=False)
|
||||
age = serializers.SerializerMethodField()
|
||||
dateNaissance_formattee = serializers.SerializerMethodField()
|
||||
dateNaissance = serializers.DateField(input_formats=['%d-%m-%Y', '%Y-%m-%d'], required=False, allow_null=True)
|
||||
classeAssocieeName = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Eleve
|
||||
fields = '__all__'
|
||||
|
||||
def get_or_create_packages(self, responsables_data):
|
||||
responsables_ids = []
|
||||
for responsable_data in responsables_data:
|
||||
responsable_instance, created = Responsable.objects.get_or_create( id=responsable_data.get('id'),
|
||||
defaults=responsable_data)
|
||||
responsables_ids.append(responsable_instance.id)
|
||||
return responsables_ids
|
||||
|
||||
def create(self, validated_data):
|
||||
responsables_data = validated_data.pop('responsables', [])
|
||||
freres_data = validated_data.pop('freres', [])
|
||||
langues_data = validated_data.pop('languesParlees', [])
|
||||
eleve = Eleve.objects.create(**validated_data)
|
||||
eleve.responsables.set(self.get_or_create_packages(responsables_data))
|
||||
eleve.freres.set(self.get_or_create_packages(freres_data))
|
||||
eleve.languesParlees.set(self.get_or_create_packages(langues_data))
|
||||
|
||||
return eleve
|
||||
|
||||
def create_or_update_packages(self, responsables_data):
|
||||
responsables_ids = []
|
||||
|
||||
|
||||
for responsable_data in responsables_data:
|
||||
responsable_instance, created = Responsable.objects.update_or_create( id=responsable_data.get('id'),
|
||||
defaults=responsable_data)
|
||||
|
||||
responsables_ids.append(responsable_instance.id)
|
||||
return responsables_ids
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
responsables_data = validated_data.pop('responsables', [])
|
||||
freres_data = validated_data.pop('freres', [])
|
||||
langues_data = validated_data.pop('languesParlees', [])
|
||||
if responsables_data:
|
||||
instance.responsables.set(self.create_or_update_packages(responsables_data))
|
||||
if freres_data:
|
||||
instance.freres.set(self.create_or_update_packages(freres_data))
|
||||
if langues_data:
|
||||
instance.freres.set(self.create_or_update_packages(langues_data))
|
||||
|
||||
for field in self.fields:
|
||||
try:
|
||||
setattr(instance, field, validated_data[field])
|
||||
except KeyError:
|
||||
pass
|
||||
instance.save()
|
||||
|
||||
return instance
|
||||
|
||||
def get_age(self, obj):
|
||||
return obj.age
|
||||
|
||||
def get_dateNaissance_formattee(self, obj):
|
||||
return obj.dateNaissance_formattee
|
||||
|
||||
def get_classeAssocieeName(self, obj):
|
||||
return obj.classeAssociee.nom_ambiance if obj.classeAssociee else None
|
||||
|
||||
class FicheInscriptionSerializer(serializers.ModelSerializer):
|
||||
eleve = EleveSerializer(many=False, required=True)
|
||||
fichierInscription = serializers.FileField(required=False)
|
||||
etat_label = serializers.SerializerMethodField()
|
||||
dateMAJ_formattee = serializers.SerializerMethodField()
|
||||
class Meta:
|
||||
model = FicheInscription
|
||||
fields = '__all__'
|
||||
|
||||
def create(self, validated_data):
|
||||
eleve_data = validated_data.pop('eleve')
|
||||
eleve = EleveSerializer.create(EleveSerializer(), eleve_data)
|
||||
ficheEleve = FicheInscription.objects.create(eleve=eleve, **validated_data)
|
||||
return ficheEleve
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
eleve_data = validated_data.pop('eleve')
|
||||
eleve = instance.eleve
|
||||
eleve_serializer = EleveSerializer.update(EleveSerializer(), eleve, eleve_data)
|
||||
|
||||
for field in self.fields:
|
||||
try:
|
||||
setattr(instance, field, validated_data[field])
|
||||
except KeyError:
|
||||
pass
|
||||
instance.save()
|
||||
|
||||
return instance
|
||||
|
||||
def get_etat_label(self, obj):
|
||||
return obj.get_etat_display()
|
||||
|
||||
def get_dateMAJ_formattee(self, obj):
|
||||
utc_time = timezone.localtime(obj.dateMAJ) # Convertir en heure locale
|
||||
local_tz = pytz.timezone(settings.TZ_APPLI)
|
||||
local_time = utc_time.astimezone(local_tz)
|
||||
|
||||
return local_time.strftime("%d-%m-%Y %H:%M")
|
||||
|
||||
class EleveByParentSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False)
|
||||
class Meta:
|
||||
model = Eleve
|
||||
fields = ['id', 'nom', 'prenom']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(EleveByParentSerializer , self).__init__(*args, **kwargs)
|
||||
for field in self.fields:
|
||||
self.fields[field].required = False
|
||||
|
||||
class FicheInscriptionByParentSerializer(serializers.ModelSerializer):
|
||||
eleve = EleveByParentSerializer(many=False, required=True)
|
||||
class Meta:
|
||||
model = FicheInscription
|
||||
fields = ['eleve', 'etat']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(FicheInscriptionByParentSerializer, self).__init__(*args, **kwargs)
|
||||
for field in self.fields:
|
||||
self.fields[field].required = False
|
||||
|
||||
class ResponsableByDICreationSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False)
|
||||
class Meta:
|
||||
model = Responsable
|
||||
fields = ['id', 'nom', 'prenom', 'mail', 'profilAssocie']
|
||||
|
||||
class EleveByDICreationSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False)
|
||||
responsables = ResponsableByDICreationSerializer(many=True, required=False)
|
||||
class Meta:
|
||||
model = Eleve
|
||||
fields = ['id', 'nom', 'prenom', 'responsables']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(EleveByDICreationSerializer , self).__init__(*args, **kwargs)
|
||||
for field in self.fields:
|
||||
self.fields[field].required = False
|
||||
|
||||
class NotificationSerializer(serializers.ModelSerializer):
|
||||
typeNotification_label = serializers.ReadOnlyField()
|
||||
class Meta:
|
||||
model = Notification
|
||||
fields = '__all__'
|
||||
@ -1,23 +0,0 @@
|
||||
from GestionInscriptions.models import FicheInscription, Eleve
|
||||
from django import template
|
||||
register = template.Library()
|
||||
|
||||
# @register.filter
|
||||
# def recupereFichiersDossierInscription(pk):
|
||||
# fichiers_list = FicheInscription.objects.filter(fiche_inscription=pk)
|
||||
# return fichiers_list
|
||||
|
||||
@register.filter
|
||||
def recupereModePaiement(pk):
|
||||
ficheInscription = FicheInscription.objects.get(eleve=pk)
|
||||
return Eleve.ModePaiement(int(ficheInscription.eleve.modePaiement)).label
|
||||
|
||||
@register.filter
|
||||
def recupereNiveauEleve(pk):
|
||||
ficheInscription = FicheInscription.objects.get(eleve=pk)
|
||||
return Eleve.NiveauEleve(int(ficheInscription.eleve.niveau)).label
|
||||
|
||||
@register.filter
|
||||
def recupereGenreEleve(pk):
|
||||
ficheInscription = FicheInscription.objects.get(eleve=pk)
|
||||
return Eleve.GenreEleve(int(ficheInscription.eleve.genre)).label
|
||||
@ -1,36 +0,0 @@
|
||||
from django.urls import path, re_path
|
||||
|
||||
from . import views
|
||||
from GestionInscriptions.views import FichierInscriptionView, ListFichesInscriptionView, FicheInscriptionView, EleveView, ResponsableView, ListeEnfantsView, ListeElevesView, FraisInscriptionView
|
||||
|
||||
urlpatterns = [
|
||||
re_path(r'^fichesInscription/([a-zA-z]+)$', ListFichesInscriptionView.as_view(), name="listefichesInscriptions"),
|
||||
re_path(r'^ficheInscription$', FicheInscriptionView.as_view(), name="fichesInscriptions"),
|
||||
re_path(r'^ficheInscription/([0-9]+)$', FicheInscriptionView.as_view(), name="fichesInscriptions"),
|
||||
|
||||
# Page de formulaire d'inscription - ELEVE
|
||||
re_path(r'^eleve/([0-9]+)$', EleveView.as_view(), name="eleves"),
|
||||
|
||||
# Page de formulaire d'inscription - RESPONSABLE
|
||||
re_path(r'^recupereDernierResponsable$', ResponsableView.as_view(), name="recupereDernierResponsable"),
|
||||
|
||||
# Envoi d'un dossier d'inscription
|
||||
re_path(r'^send/([0-9]+)$', views.send, name="send"),
|
||||
|
||||
# Archivage d'un dossier d'inscription
|
||||
re_path(r'^archive/([0-9]+)$', views.archive, name="archive"),
|
||||
|
||||
# Envoi d'une relance de dossier d'inscription
|
||||
re_path(r'^sendRelance/([0-9]+)$', views.relance, name="relance"),
|
||||
|
||||
# Page PARENT - Liste des enfants
|
||||
re_path(r'^enfants/([0-9]+)$', ListeEnfantsView.as_view(), name="enfants"),
|
||||
|
||||
# Page INSCRIPTION - Liste des élèves
|
||||
re_path(r'^eleves$', ListeElevesView.as_view(), name="enfants"),
|
||||
|
||||
# Frais d'inscription
|
||||
re_path(r'^tarifsInscription$', FraisInscriptionView.as_view(), name="fraisInscription"),
|
||||
re_path(r'^fichiersInscription$', FichierInscriptionView.as_view(), name='fichiersInscription'),
|
||||
re_path(r'^fichiersInscription/([0-9]+)$', FichierInscriptionView.as_view(), name="fichiersInscription"),
|
||||
]
|
||||
@ -1,201 +0,0 @@
|
||||
from django.shortcuts import render,get_object_or_404,get_list_or_404
|
||||
from .models import FicheInscription, Eleve, Responsable, Frere
|
||||
import time
|
||||
from datetime import date, datetime, timedelta
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.conf import settings
|
||||
from N3wtSchool import renderers
|
||||
from N3wtSchool import bdd
|
||||
|
||||
from io import BytesIO
|
||||
from django.core.files import File
|
||||
from pathlib import Path
|
||||
import os
|
||||
from enum import Enum
|
||||
|
||||
import random
|
||||
import string
|
||||
from rest_framework.parsers import JSONParser
|
||||
|
||||
def recupereListeFichesInscription():
|
||||
context = {
|
||||
"ficheInscriptions_list": bdd.getAllObjects(FicheInscription),
|
||||
}
|
||||
return context
|
||||
|
||||
def recupereListeFichesInscriptionEnAttenteSEPA():
|
||||
|
||||
ficheInscriptionsSEPA_list = FicheInscription.objects.filter(modePaiement="Prélèvement SEPA").filter(etat=FicheInscription.EtatDossierInscription['SEPA_ENVOYE'])
|
||||
return ficheInscriptionsSEPA_list
|
||||
|
||||
def updateEleve(eleve, inputs, erase=False):
|
||||
eleve.nom = inputs["nomEleve"]
|
||||
eleve.prenom = inputs["prenomEleve"]
|
||||
eleve.ambiance = inputs["ambiance"]
|
||||
eleve.genre = inputs["genre"]
|
||||
eleve.adresse = inputs["adresseEleve"]
|
||||
eleve.dateNaissance = inputs["dateNaissanceEleve"]
|
||||
eleve.lieuNaissance = inputs["lieuNaissanceEleve"]
|
||||
eleve.codePostalNaissance = inputs["codePostalNaissanceEleve"]
|
||||
eleve.nationalite = inputs["nationaliteEleve"]
|
||||
eleve.medecinTraitant = inputs["medecinTraitantEleve"]
|
||||
|
||||
|
||||
responsable=eleve.getResponsablePrincipal()
|
||||
responsable.adresse = inputs["adresseResponsable1"]
|
||||
responsable.dateNaissance = inputs["dateNaissanceResponsable1"]
|
||||
responsable.profession = inputs["professionResponsable1"]
|
||||
responsable.save()
|
||||
|
||||
# Création du 2ème responsable
|
||||
if inputs["nomResponsable2"] != "" and inputs["prenomResponsable2"] != "":
|
||||
responsable2 = Responsable.objects.create(nom=inputs["nomResponsable2"],
|
||||
prenom=inputs["prenomResponsable2"],
|
||||
dateNaissance=inputs["dateNaissanceResponsable2"],
|
||||
adresse=inputs["adresseResponsable2"],
|
||||
mail=inputs["mailResponsable2"],
|
||||
telephone=inputs["telephoneResponsable2"],
|
||||
profession=inputs["professionResponsable2"])
|
||||
responsable2.save()
|
||||
eleve.responsables.add(responsable2)
|
||||
|
||||
# Création du 1er frère
|
||||
if inputs["nomFrere1"] != "" and inputs["prenomFrere1"] != "":
|
||||
frere1 = Frere.objects.create(nom=inputs["nomFrere1"],
|
||||
prenom=inputs["prenomFrere1"],
|
||||
dateNaissance=inputs["dateNaissanceFrere1"])
|
||||
frere1.save()
|
||||
eleve.freres.add(frere1)
|
||||
|
||||
# Création du 2ème frère
|
||||
if inputs["nomFrere2"] != "" and inputs["prenomFrere2"] != "":
|
||||
frere2 = Frere.objects.create(nom=inputs["nomFrere2"],
|
||||
prenom=inputs["prenomFrere2"],
|
||||
dateNaissance=inputs["dateNaissanceFrere2"])
|
||||
frere2.save()
|
||||
eleve.freres.add(frere2)
|
||||
|
||||
eleve.save()
|
||||
|
||||
def _now():
|
||||
return datetime.now(ZoneInfo(settings.TZ_APPLI))
|
||||
|
||||
def convertToStr(dateValue, dateFormat):
|
||||
return dateValue.strftime(dateFormat)
|
||||
|
||||
def convertToDate(date_time):
|
||||
format = '%d-%m-%Y %H:%M'
|
||||
datetime_str = datetime.strptime(date_time, format)
|
||||
|
||||
return datetime_str
|
||||
|
||||
def convertTelephone(telephoneValue, separator='-'):
|
||||
return f"{telephoneValue[:2]}{separator}{telephoneValue[2:4]}{separator}{telephoneValue[4:6]}{separator}{telephoneValue[6:8]}{separator}{telephoneValue[8:10]}"
|
||||
|
||||
def generePDF(ficheEleve):
|
||||
data = {
|
||||
'pdf_title': "Dossier d'inscription de %s"%ficheEleve.eleve.prenom,
|
||||
'dateSignature': convertToStr(_now(), '%d-%m-%Y'),
|
||||
'heureSignature': convertToStr(_now(), '%H:%M'),
|
||||
'eleve':ficheEleve.eleve,
|
||||
}
|
||||
|
||||
pdf = renderers.render_to_pdf('pdfs/dossier_inscription.html', data)
|
||||
|
||||
nomFichierPDF = "Dossier_Inscription_%s_%s.pdf"%(ficheEleve.eleve.nom, ficheEleve.eleve.prenom)
|
||||
pathFichier = Path(settings.DOCUMENT_DIR + "/" + nomFichierPDF)
|
||||
if os.path.exists(str(pathFichier)):
|
||||
os.remove(str(pathFichier))
|
||||
|
||||
receipt_file = BytesIO(pdf.content)
|
||||
# fichier = Fichier.objects.create(fiche_inscription=ficheEleve)
|
||||
# fichier.document = File(receipt_file, nomFichierPDF)
|
||||
# fichier.save()
|
||||
|
||||
def genereRandomCode(length):
|
||||
return ''.join(random.choice(string.ascii_letters) for i in range(length))
|
||||
|
||||
def calculeDatePeremption(_start, nbDays):
|
||||
return convertToStr(_start + timedelta(days=nbDays), settings.DATE_FORMAT)
|
||||
|
||||
# Fonction permettant de retourner la valeur du QueryDict
|
||||
# QueryDict [ index ] -> Dernière valeur d'une liste
|
||||
# dict (QueryDict [ index ]) -> Toutes les valeurs de la liste
|
||||
def _(liste):
|
||||
return liste[0]
|
||||
|
||||
def toNewEleveJSONRequest(jsonOrigin):
|
||||
etat=FicheInscription.EtatDossierInscription.DI_CREE
|
||||
telephone = convertTelephone(_(jsonOrigin['telephoneResponsable']))
|
||||
finalJSON = {
|
||||
"eleve":
|
||||
{
|
||||
"nom" : _(jsonOrigin['nomEleve']),
|
||||
"prenom" : _(jsonOrigin['prenomEleve']),
|
||||
"responsables" : [
|
||||
{
|
||||
"nom" : _(jsonOrigin['nomResponsable']),
|
||||
"prenom" : _(jsonOrigin['prenomResponsable']),
|
||||
"mail" : _(jsonOrigin['mailResponsable']),
|
||||
"telephone" : telephone
|
||||
}
|
||||
],
|
||||
"profils" : [
|
||||
],
|
||||
},
|
||||
"etat": str(etat),
|
||||
"dateMAJ": str(convertToStr(_now(), '%d-%m-%Y %H:%M')),
|
||||
}
|
||||
print(finalJSON)
|
||||
return finalJSON
|
||||
|
||||
def toEditEleveJSONRequest(jsonOrigin):
|
||||
telephone = convertTelephone(_(jsonOrigin['telephoneResponsable']), '.')
|
||||
finalJSON = {
|
||||
"eleve":
|
||||
{
|
||||
"id" : _(jsonOrigin['fiche_id']),
|
||||
"nom" : _(jsonOrigin['nomEleve']),
|
||||
"prenom" : _(jsonOrigin['prenomEleve']),
|
||||
"responsables" : [
|
||||
{
|
||||
"id" : _(jsonOrigin['responsable_id']),
|
||||
"nom" : _(jsonOrigin['nomResponsable']),
|
||||
"prenom" : _(jsonOrigin['prenomResponsable']),
|
||||
"mail" : _(jsonOrigin['mailResponsable']),
|
||||
"telephone" : telephone
|
||||
}
|
||||
],
|
||||
"profils" : [
|
||||
],
|
||||
},
|
||||
"dateMAJ": str(convertToStr(_now(), '%d-%m-%Y %H:%M')),
|
||||
}
|
||||
print(finalJSON)
|
||||
return finalJSON
|
||||
|
||||
def getArgFromRequest(_argument, _request):
|
||||
resultat = None
|
||||
data=JSONParser().parse(_request)
|
||||
resultat = data[_argument]
|
||||
return resultat
|
||||
|
||||
def diToPDF(ficheEleve):
|
||||
# Ajout du fichier d'inscriptions
|
||||
data = {
|
||||
'pdf_title': "Dossier d'inscription de %s"%ficheEleve.eleve.prenom,
|
||||
'dateSignature': convertToStr(_now(), '%d-%m-%Y'),
|
||||
'heureSignature': convertToStr(_now(), '%H:%M'),
|
||||
'eleve':ficheEleve.eleve,
|
||||
}
|
||||
|
||||
pdf = renderers.render_to_pdf('pdfs/dossier_inscription.html', data)
|
||||
|
||||
nomFichierPDF = "Dossier_Inscription_%s_%s.pdf"%(ficheEleve.eleve.nom, ficheEleve.eleve.prenom)
|
||||
pathFichier = Path(settings.DOCUMENT_DIR + "/" + nomFichierPDF)
|
||||
if os.path.exists(str(pathFichier)):
|
||||
print(f'File exists : {str(pathFichier)}')
|
||||
os.remove(str(pathFichier))
|
||||
|
||||
receipt_file = BytesIO(pdf.content)
|
||||
ficheEleve.fichierInscription = File(receipt_file, nomFichierPDF)
|
||||
@ -1,282 +0,0 @@
|
||||
from django.http.response import JsonResponse
|
||||
from django.contrib.auth import login, authenticate, get_user_model
|
||||
from django.views.decorators.csrf import ensure_csrf_cookie, csrf_protect
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.core.cache import cache
|
||||
from django.core.paginator import Paginator
|
||||
from django.core.files import File
|
||||
from django.db.models import Q # Ajout de cet import
|
||||
from rest_framework.parsers import JSONParser,MultiPartParser, FormParser
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework import status
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
import os
|
||||
from io import BytesIO
|
||||
|
||||
import GestionInscriptions.mailManager as mailer
|
||||
import GestionInscriptions.util as util
|
||||
from GestionInscriptions.serializers import FichierInscriptionSerializer, FicheInscriptionSerializer, EleveSerializer, FicheInscriptionByParentSerializer, EleveByDICreationSerializer, FraisInscriptionSerializer
|
||||
from GestionInscriptions.pagination import CustomPagination
|
||||
from GestionInscriptions.signals import clear_cache
|
||||
from .models import Eleve, Responsable, FicheInscription, FraisInscription, FichierInscription
|
||||
|
||||
from GestionInscriptions.automate import Automate_DI_Inscription, load_config, getStateMachineObjectState, updateStateMachine
|
||||
|
||||
from GestionLogin.models import Profil
|
||||
|
||||
from N3wtSchool import settings, renderers, bdd
|
||||
|
||||
class ListFichesInscriptionView(APIView):
|
||||
pagination_class = CustomPagination
|
||||
|
||||
def get_fiche_inscriptions(self, _filter, search=None):
|
||||
"""
|
||||
Récupère les fiches d'inscriptions en fonction du filtre passé.
|
||||
_filter: Filtre pour déterminer l'état des fiches ('pending', 'archived', 'subscribed')
|
||||
search: Terme de recherche (optionnel)
|
||||
"""
|
||||
if _filter == 'pending':
|
||||
exclude_states = [FicheInscription.EtatDossierInscription.DI_VALIDE, FicheInscription.EtatDossierInscription.DI_ARCHIVE]
|
||||
return bdd.searchObjects(FicheInscription, search, _excludeStates=exclude_states)
|
||||
elif _filter == 'archived':
|
||||
return bdd.getObjects(FicheInscription, 'etat', FicheInscription.EtatDossierInscription.DI_ARCHIVE)
|
||||
elif _filter == 'subscribed':
|
||||
return bdd.getObjects(FicheInscription, 'etat', FicheInscription.EtatDossierInscription.DI_VALIDE)
|
||||
return None
|
||||
|
||||
def get(self, request, _filter):
|
||||
|
||||
# Récupération des paramètres
|
||||
search = request.GET.get('search', '').strip()
|
||||
page_size = request.GET.get('page_size', None)
|
||||
|
||||
# Gestion du page_size
|
||||
if page_size is not None:
|
||||
try:
|
||||
page_size = int(page_size)
|
||||
except ValueError:
|
||||
page_size = settings.NB_RESULT_PER_PAGE
|
||||
|
||||
# Définir le cache_key en fonction du filtre
|
||||
page_number = request.GET.get('page', 1)
|
||||
cache_key = f'N3WT_ficheInscriptions_{_filter}_page_{page_number}_search_{search if _filter == "pending" else ""}'
|
||||
cached_page = cache.get(cache_key)
|
||||
if cached_page:
|
||||
return JsonResponse(cached_page, safe=False)
|
||||
|
||||
# Récupérer les fiches d'inscriptions en fonction du filtre
|
||||
ficheInscriptions_List = self.get_fiche_inscriptions(_filter, search)
|
||||
|
||||
if not ficheInscriptions_List:
|
||||
return JsonResponse({'error' : 'aucune donnée trouvée', 'count' :0}, safe=False)
|
||||
|
||||
# Pagination
|
||||
paginator = self.pagination_class()
|
||||
page = paginator.paginate_queryset(ficheInscriptions_List, request)
|
||||
if page is not None:
|
||||
ficheInscriptions_serializer = FicheInscriptionSerializer(page, many=True)
|
||||
response_data = paginator.get_paginated_response(ficheInscriptions_serializer.data)
|
||||
cache.set(cache_key, response_data, timeout=60*15)
|
||||
return JsonResponse(response_data, safe=False)
|
||||
|
||||
return JsonResponse({'error' : 'aucune donnée trouvée', 'count' :0}, safe=False)
|
||||
|
||||
def post(self, request):
|
||||
fichesEleve_data=JSONParser().parse(request)
|
||||
for ficheEleve_data in fichesEleve_data:
|
||||
# Ajout de la date de mise à jour
|
||||
ficheEleve_data["dateMAJ"] = util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
|
||||
json.dumps(ficheEleve_data)
|
||||
# Ajout du code d'inscription
|
||||
code = util.genereRandomCode(12)
|
||||
ficheEleve_data["codeLienInscription"] = code
|
||||
ficheEleve_serializer = FicheInscriptionSerializer(data=ficheEleve_data)
|
||||
|
||||
if ficheEleve_serializer.is_valid():
|
||||
ficheEleve_serializer.save()
|
||||
|
||||
return JsonResponse(ficheEleve_serializer.errors, safe=False)
|
||||
|
||||
|
||||
@method_decorator(csrf_protect, name='dispatch')
|
||||
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
||||
class FicheInscriptionView(APIView):
|
||||
pagination_class = CustomPagination
|
||||
|
||||
def get(self, request, _id):
|
||||
ficheInscription=bdd.getObject(FicheInscription, "eleve__id", _id)
|
||||
fiche_serializer=FicheInscriptionSerializer(ficheInscription)
|
||||
return JsonResponse(fiche_serializer.data, safe=False)
|
||||
|
||||
def post(self, request):
|
||||
ficheEleve_data=JSONParser().parse(request)
|
||||
# Ajout de la date de mise à jour
|
||||
ficheEleve_data["dateMAJ"] = util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
|
||||
json.dumps(ficheEleve_data)
|
||||
# Ajout du code d'inscription
|
||||
code = util.genereRandomCode(12)
|
||||
ficheEleve_data["codeLienInscription"] = code
|
||||
|
||||
responsablesId = ficheEleve_data.pop('idResponsables', [])
|
||||
ficheEleve_serializer = FicheInscriptionSerializer(data=ficheEleve_data)
|
||||
|
||||
if ficheEleve_serializer.is_valid():
|
||||
di = ficheEleve_serializer.save()
|
||||
|
||||
# Mise à jour de l'automate
|
||||
updateStateMachine(di, 'creationDI')
|
||||
|
||||
# Récupération du reponsable associé
|
||||
for responsableId in responsablesId:
|
||||
responsable = Responsable.objects.get(id=responsableId)
|
||||
di.eleve.responsables.add(responsable)
|
||||
di.save()
|
||||
|
||||
return JsonResponse(ficheEleve_serializer.data, safe=False)
|
||||
|
||||
return JsonResponse(ficheEleve_serializer.errors, safe=False)
|
||||
|
||||
def put(self, request, id):
|
||||
ficheEleve_data=JSONParser().parse(request)
|
||||
etat = ficheEleve_data.pop('etat', 0)
|
||||
ficheEleve_data["dateMAJ"] = str(util.convertToStr(util._now(), '%d-%m-%Y %H:%M'))
|
||||
ficheEleve = bdd.getObject(_objectName=FicheInscription, _columnName='eleve__id', _value=id)
|
||||
|
||||
if etat == FicheInscription.EtatDossierInscription.DI_EN_VALIDATION:
|
||||
# Le parent a complété le dossier d'inscription, il est soumis à validation par l'école
|
||||
print('EN VALIDATION')
|
||||
json.dumps(ficheEleve_data)
|
||||
util.diToPDF(ficheEleve)
|
||||
# Mise à jour de l'automate
|
||||
updateStateMachine(ficheEleve, 'saisiDI')
|
||||
elif etat == FicheInscription.EtatDossierInscription.DI_VALIDE:
|
||||
# L'école a validé le dossier d'inscription
|
||||
# Mise à jour de l'automate
|
||||
print('VALIDATION')
|
||||
updateStateMachine(ficheEleve, 'valideDI')
|
||||
|
||||
|
||||
ficheEleve_serializer = FicheInscriptionSerializer(ficheEleve, data=ficheEleve_data)
|
||||
if ficheEleve_serializer.is_valid():
|
||||
ficheEleve_serializer.save()
|
||||
return JsonResponse(ficheEleve_serializer.data, safe=False)
|
||||
|
||||
return JsonResponse(ficheEleve_serializer.errors, safe=False)
|
||||
|
||||
def delete(self, request, id):
|
||||
fiche_inscription = bdd.getObject(_objectName=FicheInscription, _columnName='eleve__id', _value=id)
|
||||
if fiche_inscription != None:
|
||||
eleve = fiche_inscription.eleve
|
||||
eleve.responsables.clear()
|
||||
eleve.profils.clear()
|
||||
eleve.delete()
|
||||
clear_cache()
|
||||
|
||||
return JsonResponse("La suppression du dossier a été effectuée avec succès", safe=False)
|
||||
|
||||
return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False)
|
||||
|
||||
class EleveView(APIView):
|
||||
def get(self, request, _id):
|
||||
eleve = bdd.getObject(_objectName=Eleve, _columnName='id', _value=_id)
|
||||
eleve_serializer = EleveSerializer(eleve)
|
||||
return JsonResponse(eleve_serializer.data, safe=False)
|
||||
|
||||
class ResponsableView(APIView):
|
||||
def get(self, request):
|
||||
lastResponsable = bdd.getLastId(Responsable)
|
||||
return JsonResponse({"lastid":lastResponsable}, safe=False)
|
||||
|
||||
def send(request, id):
|
||||
fiche_inscription = bdd.getObject(_objectName=FicheInscription, _columnName='eleve__id', _value=id)
|
||||
if fiche_inscription != None:
|
||||
eleve = fiche_inscription.eleve
|
||||
responsable = eleve.getResponsablePrincipal()
|
||||
mail = responsable.mail
|
||||
errorMessage = mailer.envoieDossierInscription(mail)
|
||||
if errorMessage == '':
|
||||
fiche_inscription.dateMAJ=util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
|
||||
# Mise à jour de l'automate
|
||||
updateStateMachine(fiche_inscription, 'envoiDI')
|
||||
|
||||
return JsonResponse({"errorMessage":errorMessage}, safe=False)
|
||||
|
||||
return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False)
|
||||
|
||||
def archive(request, id):
|
||||
fiche_inscription = bdd.getObject(_objectName=FicheInscription, _columnName='eleve__id', _value=id)
|
||||
if fiche_inscription != None:
|
||||
fiche_inscription.dateMAJ=util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
|
||||
# Mise à jour de l'automate
|
||||
updateStateMachine(fiche_inscription, 'archiveDI')
|
||||
|
||||
return JsonResponse({"errorMessage":''}, safe=False)
|
||||
|
||||
return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False)
|
||||
|
||||
def relance(request, id):
|
||||
fiche_inscription = bdd.getObject(_objectName=FicheInscription, _columnName='eleve__id', _value=id)
|
||||
if fiche_inscription != None:
|
||||
eleve = fiche_inscription.eleve
|
||||
responsable = eleve.getResponsablePrincipal()
|
||||
mail = responsable.mail
|
||||
errorMessage = mailer.envoieRelanceDossierInscription(mail, fiche_inscription.codeLienInscription)
|
||||
if errorMessage == '':
|
||||
fiche_inscription.etat=FicheInscription.EtatDossierInscription.DI_ENVOYE
|
||||
fiche_inscription.dateMAJ=util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
|
||||
fiche_inscription.save()
|
||||
|
||||
return JsonResponse({"errorMessage":errorMessage}, safe=False)
|
||||
|
||||
return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False)
|
||||
|
||||
# API utilisée pour la vue parent
|
||||
class ListeEnfantsView(APIView):
|
||||
# Récupération des élèves d'un parent
|
||||
# idProfile : identifiant du profil connecté rattaché aux fiches d'élèves
|
||||
def get(self, request, _idProfile):
|
||||
students = bdd.getObjects(_objectName=FicheInscription, _columnName='eleve__responsables__profilAssocie__id', _value=_idProfile)
|
||||
students_serializer = FicheInscriptionByParentSerializer(students, many=True)
|
||||
return JsonResponse(students_serializer.data, safe=False)
|
||||
|
||||
# API utilisée pour la vue de création d'un DI
|
||||
class ListeElevesView(APIView):
|
||||
# Récupération de la liste des élèves inscrits ou en cours d'inscriptions
|
||||
def get(self, request):
|
||||
students = bdd.getAllObjects(_objectName=Eleve)
|
||||
students_serializer = EleveByDICreationSerializer(students, many=True)
|
||||
return JsonResponse(students_serializer.data, safe=False)
|
||||
|
||||
# API utilisée pour la vue de personnalisation des frais d'inscription pour la structure
|
||||
class FraisInscriptionView(APIView):
|
||||
def get(self, request):
|
||||
tarifs = bdd.getAllObjects(FraisInscription)
|
||||
tarifs_serializer = FraisInscriptionSerializer(tarifs, many=True)
|
||||
return JsonResponse(tarifs_serializer.data, safe=False)
|
||||
|
||||
class FichierInscriptionView(APIView):
|
||||
parser_classes = (MultiPartParser, FormParser)
|
||||
|
||||
def get(self, request):
|
||||
fichiers = FichierInscription.objects.all()
|
||||
serializer = FichierInscriptionSerializer(fichiers, many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
def post(self, request):
|
||||
serializer = FichierInscriptionSerializer(data=request.data)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
def delete(self, request, _id):
|
||||
fichierInscription = bdd.getObject(_objectName=FichierInscription, _columnName='id', _value=_id)
|
||||
if fichierInscription is not None:
|
||||
fichierInscription.file.delete() # Supprimer le fichier uploadé
|
||||
fichierInscription.delete()
|
||||
return JsonResponse({'message': 'La suppression du fichier d\'inscription a été effectuée avec succès'}, safe=False)
|
||||
else:
|
||||
return JsonResponse({'erreur': 'Le fichier d\'inscription n\'a pas été trouvé'}, safe=False)
|
||||
@ -1,22 +0,0 @@
|
||||
from django.urls import path, re_path
|
||||
|
||||
from . import views
|
||||
import GestionLogin.views
|
||||
from GestionLogin.views import ProfilView, ListProfilView, SessionView, LoginView, SubscribeView, NewPasswordView, ResetPasswordView
|
||||
|
||||
urlpatterns = [
|
||||
re_path(r'^csrf$', GestionLogin.views.csrf, name='csrf'),
|
||||
|
||||
re_path(r'^login$', LoginView.as_view(), name="login"),
|
||||
re_path(r'^subscribe$', SubscribeView.as_view(), name='subscribe'),
|
||||
re_path(r'^newPassword$', NewPasswordView.as_view(), name='newPassword'),
|
||||
re_path(r'^resetPassword/([a-zA-Z]+)$', ResetPasswordView.as_view(), name='resetPassword'),
|
||||
re_path(r'^infoSession$', GestionLogin.views.infoSession, name='infoSession'),
|
||||
|
||||
re_path(r'^profils$', ListProfilView.as_view(), name="profil"),
|
||||
re_path(r'^profil$', ProfilView.as_view(), name="profil"),
|
||||
re_path(r'^profil/([0-9]+)$', ProfilView.as_view(), name="profil"),
|
||||
|
||||
# Test SESSION VIEW
|
||||
re_path(r'^session$', SessionView.as_view(), name="session"),
|
||||
]
|
||||
@ -2,13 +2,13 @@ from django.contrib.auth.models import AbstractUser
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.conf import settings
|
||||
from GestionLogin.models import Profil
|
||||
from Auth.models import Profile
|
||||
|
||||
class Messagerie(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
objet = models.CharField(max_length=200, default="", blank=True)
|
||||
emetteur = models.ForeignKey(Profil, on_delete=models.PROTECT, related_name='messages_envoyes')
|
||||
destinataire = models.ForeignKey(Profil, on_delete=models.PROTECT, related_name='messages_recus')
|
||||
emetteur = models.ForeignKey(Profile, on_delete=models.PROTECT, related_name='messages_envoyes')
|
||||
destinataire = models.ForeignKey(Profile, on_delete=models.PROTECT, related_name='messages_recus')
|
||||
corpus = models.CharField(max_length=200, default="", blank=True)
|
||||
|
||||
def __str__(self):
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
from rest_framework import serializers
|
||||
from GestionLogin.models import Profil
|
||||
from Auth.models import Profile
|
||||
from GestionMessagerie.models import Messagerie
|
||||
|
||||
class MessageSerializer(serializers.ModelSerializer):
|
||||
|
||||
@ -2,7 +2,7 @@ from django.contrib.auth.models import AbstractUser
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.conf import settings
|
||||
from GestionLogin.models import Profil
|
||||
from Auth.models import Profile
|
||||
|
||||
class TypeNotif(models.IntegerChoices):
|
||||
NOTIF_NONE = 0, _('Aucune notification')
|
||||
@ -10,7 +10,7 @@ class TypeNotif(models.IntegerChoices):
|
||||
NOTIF_DI = 2, _('Le dossier d\'inscription a été mis à jour')
|
||||
|
||||
class Notification(models.Model):
|
||||
user = models.ForeignKey(Profil, on_delete=models.PROTECT)
|
||||
user = models.ForeignKey(Profile, on_delete=models.PROTECT)
|
||||
message = models.CharField(max_length=255)
|
||||
is_read = models.BooleanField(default=False)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
@ -2,7 +2,7 @@ from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
from .models import Notification, TypeNotif
|
||||
from GestionMessagerie.models import Messagerie
|
||||
from GestionInscriptions.models import FicheInscription
|
||||
from Subscriptions.models import RegistrationForm
|
||||
|
||||
@receiver(post_save, sender=Messagerie)
|
||||
def notification_MESSAGE(sender, instance, created, **kwargs):
|
||||
@ -13,11 +13,11 @@ def notification_MESSAGE(sender, instance, created, **kwargs):
|
||||
typeNotification=TypeNotif.NOTIF_MESSAGE
|
||||
)
|
||||
|
||||
@receiver(post_save, sender=FicheInscription)
|
||||
@receiver(post_save, sender=RegistrationForm)
|
||||
def notification_DI(sender, instance, created, **kwargs):
|
||||
for responsable in instance.eleve.responsables.all():
|
||||
for responsable in instance.student.guardians.all():
|
||||
Notification.objects.create(
|
||||
user=responsable.profilAssocie,
|
||||
user=responsable.associated_profile,
|
||||
message=(TypeNotif.NOTIF_DI).label,
|
||||
typeNotification=TypeNotif.NOTIF_DI
|
||||
)
|
||||
|
||||
@ -3,7 +3,7 @@ from rest_framework.views import APIView
|
||||
|
||||
from .models import *
|
||||
|
||||
from GestionInscriptions.serializers import NotificationSerializer
|
||||
from Subscriptions.serializers import NotificationSerializer
|
||||
|
||||
from N3wtSchool import bdd
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import logging
|
||||
from django.db.models import Q
|
||||
from GestionInscriptions.models import FicheInscription, Profil, Eleve
|
||||
from Subscriptions.models import RegistrationForm, Profile, Student
|
||||
|
||||
logger = logging.getLogger('N3wtSchool')
|
||||
|
||||
@ -43,12 +43,12 @@ def getProfile(objectList, valueToCheck):
|
||||
return result
|
||||
|
||||
def getEleveByCodeFI(_codeFI):
|
||||
eleve = None
|
||||
ficheInscriptions_List=getAllObjects(FicheInscription)
|
||||
for fi in ficheInscriptions_List:
|
||||
if fi.codeLienInscription == _codeFI:
|
||||
eleve = fi.eleve
|
||||
return eleve
|
||||
student = None
|
||||
ficheInscriptions_List=getAllObjects(RegistrationForm)
|
||||
for rf in ficheInscriptions_List:
|
||||
if rf.codeLienInscription == _codeFI:
|
||||
student = rf.student
|
||||
return student
|
||||
|
||||
def getLastId(_object):
|
||||
result = 1
|
||||
@ -61,7 +61,7 @@ def getLastId(_object):
|
||||
def searchObjects(_objectName, _searchTerm=None, _excludeStates=None):
|
||||
"""
|
||||
Recherche générique sur les objets avec possibilité d'exclure certains états
|
||||
_objectName: Classe du modèle
|
||||
_objectName: SchoolClass du modèle
|
||||
_searchTerm: Terme de recherche
|
||||
_excludeStates: Liste d'état à exclure de la recherche (optionnel)
|
||||
"""
|
||||
@ -70,18 +70,18 @@ def searchObjects(_objectName, _searchTerm=None, _excludeStates=None):
|
||||
|
||||
# Si on a un état à exclure
|
||||
if _excludeStates is not None:
|
||||
query = query.exclude(etat__in=_excludeStates)
|
||||
query = query.exclude(status__in=_excludeStates)
|
||||
|
||||
# Si on a un terme de recherche
|
||||
if _searchTerm and _searchTerm.strip():
|
||||
terms = _searchTerm.lower().strip().split()
|
||||
for term in terms:
|
||||
query = query.filter(
|
||||
Q(eleve__nom__icontains=term) |
|
||||
Q(eleve__prenom__icontains=term)
|
||||
Q(student__last_name__icontains=term) |
|
||||
Q(student__first_name__icontains=term)
|
||||
)
|
||||
|
||||
return query.order_by('eleve__nom', 'eleve__prenom')
|
||||
return query.order_by('student__last_name', 'student__first_name')
|
||||
|
||||
except _objectName.DoesNotExist:
|
||||
logging.error(f"Aucun résultat n'a été trouvé - {_objectName.__name__} (recherche: {_searchTerm})")
|
||||
|
||||
@ -19,7 +19,7 @@ BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
MEDIA_URL = '/data/'
|
||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'data')
|
||||
|
||||
LOGIN_REDIRECT_URL = '/GestionInscriptions/fichesInscriptions'
|
||||
LOGIN_REDIRECT_URL = '/Subscriptions/registerForms'
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
|
||||
@ -35,11 +35,11 @@ ALLOWED_HOSTS = ['*']
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'GestionInscriptions.apps.GestioninscriptionsConfig',
|
||||
'GestionLogin.apps.GestionloginConfig',
|
||||
'Subscriptions.apps.GestioninscriptionsConfig',
|
||||
'Auth.apps.GestionloginConfig',
|
||||
'GestionMessagerie.apps.GestionMessagerieConfig',
|
||||
'GestionNotification.apps.GestionNotificationConfig',
|
||||
'GestionEnseignants.apps.GestionenseignantsConfig',
|
||||
'School.apps.SchoolConfig',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
@ -133,12 +133,12 @@ LOGGING = {
|
||||
"level": os.getenv("GESTION_NOTIFICATION_LOG_LEVEL", "INFO"),
|
||||
"propagate": False,
|
||||
},
|
||||
"GestionLogin": {
|
||||
"Auth": {
|
||||
"handlers": ["console"],
|
||||
"level": os.getenv("GESTION_LOGIN_LOG_LEVEL", "INFO"),
|
||||
"propagate": False,
|
||||
},
|
||||
"GestionInscriptions": {
|
||||
"Subscriptions": {
|
||||
"handlers": ["console"],
|
||||
"level": os.getenv("GESTION_INSCRIPTIONS_LOG_LEVEL", "DEBUG"),
|
||||
"propagate": False,
|
||||
@ -148,7 +148,7 @@ LOGGING = {
|
||||
"level": os.getenv("GESTION_MESSAGERIE_LOG_LEVEL", "INFO"),
|
||||
"propagate": False,
|
||||
},
|
||||
"GestionEnseignants": {
|
||||
"School": {
|
||||
"handlers": ["console"],
|
||||
"level": os.getenv("GESTION_ENSEIGNANTS_LOG_LEVEL", "INFO"),
|
||||
"propagate": False,
|
||||
@ -211,7 +211,7 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
#################### Application Settings ##############################
|
||||
########################################################################
|
||||
|
||||
with open('GestionInscriptions/Configuration/application.json', 'r') as f:
|
||||
with open('Subscriptions/Configuration/application.json', 'r') as f:
|
||||
jsonObject = json.load(f)
|
||||
|
||||
DJANGO_SUPERUSER_PASSWORD='admin'
|
||||
@ -275,8 +275,8 @@ DATABASES = {
|
||||
}
|
||||
}
|
||||
|
||||
AUTH_USER_MODEL = 'GestionLogin.Profil'
|
||||
AUTHENTICATION_BACKENDS = ('GestionLogin.backends.EmailBackend', )
|
||||
AUTH_USER_MODEL = 'Auth.Profile'
|
||||
AUTHENTICATION_BACKENDS = ('Auth.backends.EmailBackend', )
|
||||
SILENCED_SYSTEM_CHECKS = ["auth.W004"]
|
||||
|
||||
EXPIRATION_URL_NB_DAYS = 7
|
||||
@ -289,7 +289,7 @@ NB_RESULT_PER_PAGE = 8
|
||||
NB_MAX_PAGE = 100
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_PAGINATION_CLASS': 'GestionInscriptions.pagination.CustomPagination',
|
||||
'DEFAULT_PAGINATION_CLASS': 'Subscriptions.pagination.CustomPagination',
|
||||
'PAGE_SIZE': NB_RESULT_PER_PAGE
|
||||
}
|
||||
|
||||
|
||||
@ -16,6 +16,6 @@ def setup_periodic_tasks(sender, **kwargs):
|
||||
PeriodicTask.objects.get_or_create(
|
||||
interval=schedule, # Utiliser l'intervalle défini ci-dessus
|
||||
name='Tâche périodique toutes les 5 secondes',
|
||||
task='GestionInscriptions.tasks.check_for_signature_deadlines', # Remplacer par le nom de ta tâche
|
||||
task='Subscriptions.tasks.check_for_signature_deadlines', # Remplacer par le nom de ta tâche
|
||||
kwargs=json.dumps({}) # Si nécessaire, ajoute
|
||||
)
|
||||
@ -7,7 +7,7 @@ Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||
Class-based views
|
||||
SchoolClass-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
@ -39,11 +39,11 @@ schema_view = get_schema_view(
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path("GestionInscriptions/", include(("GestionInscriptions.urls", 'GestionInscriptions'), namespace='GestionInscriptions')),
|
||||
path("GestionLogin/", include(("GestionLogin.urls", 'GestionLogin'), namespace='GestionLogin')),
|
||||
path("Subscriptions/", include(("Subscriptions.urls", 'Subscriptions'), namespace='Subscriptions')),
|
||||
path("Auth/", include(("Auth.urls", 'Auth'), namespace='Auth')),
|
||||
path("GestionMessagerie/", include(("GestionMessagerie.urls", 'GestionMessagerie'), namespace='GestionMessagerie')),
|
||||
path("GestionNotification/", include(("GestionNotification.urls", 'GestionNotification'), namespace='GestionNotification')),
|
||||
path("GestionEnseignants/", include(("GestionEnseignants.urls", 'GestionEnseignants'), namespace='GestionEnseignants')),
|
||||
path("School/", include(("School.urls", 'School'), namespace='School')),
|
||||
# Documentation Api
|
||||
re_path(r'^swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'),
|
||||
path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
|
||||
|
||||
1
Back-End/School/__init__.py
Normal file
1
Back-End/School/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
default_app_config = 'School.apps.SchoolConfig'
|
||||
14
Back-End/School/apps.py
Normal file
14
Back-End/School/apps.py
Normal file
@ -0,0 +1,14 @@
|
||||
from django.apps import AppConfig
|
||||
from django.db.models.signals import post_migrate
|
||||
|
||||
def create_speciality(sender, **kwargs):
|
||||
from .models import Speciality
|
||||
if not Speciality.objects.filter(name='GROUPE').exists():
|
||||
Speciality.objects.create(name='GROUPE', colorCode='#FF0000')
|
||||
|
||||
class SchoolConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'School'
|
||||
|
||||
def ready(self):
|
||||
post_migrate.connect(create_speciality, sender=self)
|
||||
66
Back-End/School/models.py
Normal file
66
Back-End/School/models.py
Normal file
@ -0,0 +1,66 @@
|
||||
from django.db import models
|
||||
from Auth.models import Profile
|
||||
from django.db.models import JSONField
|
||||
from django.dispatch import receiver
|
||||
from django.contrib.postgres.fields import ArrayField
|
||||
|
||||
LEVEL_CHOICES = [
|
||||
(1, 'Très Petite Section (TPS)'),
|
||||
(2, 'Petite Section (PS)'),
|
||||
(3, 'Moyenne Section (MS)'),
|
||||
(4, 'Grande Section (GS)'),
|
||||
(5, 'Cours Préparatoire (CP)'),
|
||||
(6, 'Cours Élémentaire 1 (CE1)'),
|
||||
(7, 'Cours Élémentaire 2 (CE2)'),
|
||||
(8, 'Cours Moyen 1 (CM1)'),
|
||||
(9, 'Cours Moyen 2 (CM2)')
|
||||
]
|
||||
|
||||
class Speciality(models.Model):
|
||||
name = models.CharField(max_length=100)
|
||||
updatedDate = models.DateTimeField(auto_now=True)
|
||||
colorCode = models.CharField(max_length=7, default='#FFFFFF')
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Teacher(models.Model):
|
||||
lastName = models.CharField(max_length=100)
|
||||
firstName = models.CharField(max_length=100)
|
||||
email = models.EmailField(unique=True)
|
||||
specialities = models.ManyToManyField(Speciality, related_name='teachers')
|
||||
associatedProfile = models.ForeignKey(Profile, on_delete=models.CASCADE, null=True, blank=True)
|
||||
updatedDate = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.lastName} {self.firstName}"
|
||||
|
||||
class SchoolClass(models.Model):
|
||||
PLANNING_TYPE_CHOICES = [
|
||||
(1, 'Annuel'),
|
||||
(2, 'Semestriel'),
|
||||
(3, 'Trimestriel')
|
||||
]
|
||||
|
||||
atmosphereName = models.CharField(max_length=255, null=True, blank=True)
|
||||
ageGroup = models.JSONField()
|
||||
numberOfStudents = models.PositiveIntegerField()
|
||||
teachingLanguage = models.CharField(max_length=255)
|
||||
schoolYear = models.CharField(max_length=9)
|
||||
updatedDate = models.DateTimeField(auto_now_add=True)
|
||||
teachers = models.ManyToManyField(Teacher, related_name='schoolClasses')
|
||||
levels = ArrayField(models.IntegerField(choices=LEVEL_CHOICES), default=list)
|
||||
type = models.IntegerField(choices=PLANNING_TYPE_CHOICES, default=1)
|
||||
schedule = models.JSONField(default=list)
|
||||
openingDays = ArrayField(models.IntegerField(), default=list)
|
||||
|
||||
def __str__(self):
|
||||
return self.atmosphereName
|
||||
|
||||
class Planning(models.Model):
|
||||
level = models.IntegerField(choices=LEVEL_CHOICES, null=True, blank=True)
|
||||
classModel = models.ForeignKey(SchoolClass, null=True, blank=True, related_name='plannings', on_delete=models.CASCADE)
|
||||
schedule = JSONField(default=dict)
|
||||
|
||||
def __str__(self):
|
||||
return f'Planning for {self.level} of {self.classModel.atmosphereName}'
|
||||
194
Back-End/School/serializers.py
Normal file
194
Back-End/School/serializers.py
Normal file
@ -0,0 +1,194 @@
|
||||
from rest_framework import serializers
|
||||
from .models import Teacher, Speciality, SchoolClass, Planning, LEVEL_CHOICES
|
||||
from Subscriptions.models import RegistrationForm
|
||||
from Subscriptions.serializers import StudentSerializer
|
||||
from Auth.serializers import ProfileSerializer
|
||||
from Auth.models import Profile
|
||||
from N3wtSchool import settings, bdd
|
||||
from django.utils import timezone
|
||||
import pytz
|
||||
|
||||
class SpecialitySerializer(serializers.ModelSerializer):
|
||||
creationDateFormatted = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Speciality
|
||||
fields = '__all__'
|
||||
|
||||
def get_creationDateFormatted(self, obj):
|
||||
utc_time = timezone.localtime(obj.updatedDate) # Convert to local time
|
||||
local_tz = pytz.timezone(settings.TZ_APPLI)
|
||||
local_time = utc_time.astimezone(local_tz)
|
||||
|
||||
return local_time.strftime("%d-%m-%Y %H:%M")
|
||||
|
||||
class TeacherDetailSerializer(serializers.ModelSerializer):
|
||||
specialities = SpecialitySerializer(many=True, read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Teacher
|
||||
fields = ['id', 'lastName', 'firstName', 'email', 'specialities']
|
||||
|
||||
class TeacherSerializer(serializers.ModelSerializer):
|
||||
specialities = SpecialitySerializer(many=True, read_only=True)
|
||||
specialties_ids = serializers.PrimaryKeyRelatedField(queryset=Speciality.objects.all(), many=True, source='specialities')
|
||||
associatedProfile_id = serializers.PrimaryKeyRelatedField(queryset=Profile.objects.all(), source='associatedProfile', write_only=False, read_only=False)
|
||||
mainClasses = serializers.PrimaryKeyRelatedField(many=True, read_only=True, source='schoolClasses')
|
||||
associatedProfile = ProfileSerializer(read_only=True)
|
||||
rightLabel = serializers.SerializerMethodField()
|
||||
rightValue = serializers.SerializerMethodField()
|
||||
creationDateFormatted = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Teacher
|
||||
fields = ['id', 'lastName', 'firstName', 'email', 'specialities', 'specialties_ids', 'mainClasses', 'associatedProfile', 'associatedProfile_id', 'rightLabel', 'rightValue', 'updatedDate', 'creationDateFormatted']
|
||||
|
||||
def create(self, validated_data):
|
||||
specialties_data = validated_data.pop('specialities', None)
|
||||
associatedProfile = validated_data.pop('associatedProfile', None)
|
||||
teacher = Teacher.objects.create(**validated_data)
|
||||
teacher.specialities.set(specialties_data)
|
||||
if associatedProfile:
|
||||
teacher.associatedProfile = associatedProfile
|
||||
teacher.save()
|
||||
return teacher
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
specialties_data = validated_data.pop('specialities', [])
|
||||
instance.lastName = validated_data.get('lastName', instance.lastName)
|
||||
instance.firstName = validated_data.get('firstName', instance.firstName)
|
||||
instance.email = validated_data.get('email', instance.email)
|
||||
instance.associatedProfile = validated_data.get('associatedProfile', instance.associatedProfile)
|
||||
instance.save()
|
||||
instance.specialities.set(specialties_data)
|
||||
return instance
|
||||
|
||||
def get_rightLabel(self, obj):
|
||||
return obj.associatedProfile.get_right_display() if obj.associatedProfile else None
|
||||
|
||||
def get_rightValue(self, obj):
|
||||
return obj.associatedProfile.right if obj.associatedProfile else None
|
||||
|
||||
def get_creationDateFormatted(self, obj):
|
||||
utc_time = timezone.localtime(obj.updatedDate) # Convert to local time
|
||||
local_tz = pytz.timezone(settings.TZ_APPLI)
|
||||
local_time = utc_time.astimezone(local_tz)
|
||||
return local_time.strftime("%d-%m-%Y %H:%M")
|
||||
|
||||
class PlanningSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Planning
|
||||
fields = ['id', 'level', 'schedule']
|
||||
|
||||
def to_internal_value(self, data):
|
||||
internal_value = super().to_internal_value(data)
|
||||
internal_value['schedule'] = data.get('schedule', {})
|
||||
return internal_value
|
||||
|
||||
class SchoolClassSerializer(serializers.ModelSerializer):
|
||||
creationDateFormatted = serializers.SerializerMethodField()
|
||||
teachers = TeacherSerializer(many=True, read_only=True)
|
||||
teachers_ids = serializers.PrimaryKeyRelatedField(queryset=Teacher.objects.all(), many=True, source='teachers')
|
||||
students = serializers.SerializerMethodField()
|
||||
levels = serializers.ListField(child=serializers.ChoiceField(choices=LEVEL_CHOICES))
|
||||
plannings_read = serializers.SerializerMethodField()
|
||||
plannings = PlanningSerializer(many=True, write_only=True)
|
||||
|
||||
class Meta:
|
||||
model = SchoolClass
|
||||
fields = [
|
||||
'id', 'atmosphereName', 'ageGroup', 'numberOfStudents', 'teachingLanguage',
|
||||
'teachers', 'teachers_ids', 'schoolYear', 'updatedDate',
|
||||
'creationDateFormatted', 'students', 'levels', 'type', 'schedule',
|
||||
'openingDays', 'plannings', 'plannings_read'
|
||||
]
|
||||
|
||||
def create(self, validated_data):
|
||||
teachers_data = validated_data.pop('teachers', [])
|
||||
levels_data = validated_data.pop('levels', [])
|
||||
plannings_data = validated_data.pop('plannings', [])
|
||||
|
||||
classModel = SchoolClass.objects.create(
|
||||
atmosphereName=validated_data.get('atmosphereName', ''),
|
||||
ageGroup=validated_data.get('ageGroup', []),
|
||||
numberOfStudents=validated_data.get('numberOfStudents', 0),
|
||||
teachingLanguage=validated_data.get('teachingLanguage', ''),
|
||||
schoolYear=validated_data.get('schoolYear', ''),
|
||||
levels=levels_data,
|
||||
type=validated_data.get('type', 1), # Added here
|
||||
schedule=validated_data.get('schedule', ['08:30', '17:30']), # Added here
|
||||
openingDays=validated_data.get('openingDays', [1, 2, 4, 5]) # Added here
|
||||
)
|
||||
|
||||
classModel.teachers.set(teachers_data)
|
||||
|
||||
for planning_data in plannings_data:
|
||||
Planning.objects.create(
|
||||
classModel=classModel,
|
||||
level=planning_data['level'],
|
||||
schedule=planning_data.get('schedule', {})
|
||||
)
|
||||
|
||||
return classModel
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
teachers_data = validated_data.pop('teachers', [])
|
||||
levels_data = validated_data.pop('levels', [])
|
||||
plannings_data = validated_data.pop('plannings', [])
|
||||
|
||||
instance.atmosphereName = validated_data.get('atmosphereName', instance.atmosphereName)
|
||||
instance.ageGroup = validated_data.get('ageGroup', instance.ageGroup)
|
||||
instance.numberOfStudents = validated_data.get('numberOfStudents', instance.numberOfStudents)
|
||||
instance.teachingLanguage = validated_data.get('teachingLanguage', instance.teachingLanguage)
|
||||
instance.schoolYear = validated_data.get('schoolYear', instance.schoolYear)
|
||||
instance.levels = levels_data
|
||||
instance.type = validated_data.get('type', instance.type) # Added here
|
||||
instance.schedule = validated_data.get('schedule', instance.schedule) # Added here
|
||||
instance.openingDays = validated_data.get('openingDays', instance.openingDays) # Added here
|
||||
|
||||
instance.save()
|
||||
instance.teachers.set(teachers_data)
|
||||
|
||||
existing_plannings = {planning.level: planning for planning in instance.plannings.all()}
|
||||
|
||||
for planning_data in plannings_data:
|
||||
level = planning_data['level']
|
||||
if level in existing_plannings:
|
||||
# Update existing planning
|
||||
planning = existing_plannings[level]
|
||||
planning.schedule = planning_data.get('schedule', planning.schedule)
|
||||
planning.save()
|
||||
else:
|
||||
# Create new planning if level not existing
|
||||
Planning.objects.create(
|
||||
classModel=instance,
|
||||
level=level,
|
||||
schedule=planning_data.get('schedule', {})
|
||||
)
|
||||
|
||||
return instance
|
||||
|
||||
def get_creationDateFormatted(self, obj):
|
||||
utc_time = timezone.localtime(obj.updatedDate)
|
||||
local_tz = pytz.timezone(settings.TZ_APPLI)
|
||||
local_time = utc_time.astimezone(local_tz)
|
||||
return local_time.strftime("%d-%m-%Y %H:%M")
|
||||
|
||||
def get_students(self, obj):
|
||||
studentsList = obj.students.all()
|
||||
filtered_students = []
|
||||
for student in studentsList:
|
||||
registrationForm = bdd.getObject(RegistrationForm, "student__id", student.id)
|
||||
if registrationForm.status == registrationForm.RegistrationFormStatus.RF_VALIDATED:
|
||||
filtered_students.append(student)
|
||||
return StudentSerializer(filtered_students, many=True, read_only=True).data
|
||||
|
||||
def get_plannings_read(self, obj):
|
||||
plannings = obj.plannings.all()
|
||||
levels_dict = {level: {'level': level, 'planning': None} for level in obj.levels}
|
||||
|
||||
for planning in plannings:
|
||||
if planning.level in levels_dict:
|
||||
levels_dict[planning.level]['planning'] = PlanningSerializer(planning).data
|
||||
|
||||
return list(levels_dict.values())
|
||||
21
Back-End/School/urls.py
Normal file
21
Back-End/School/urls.py
Normal file
@ -0,0 +1,21 @@
|
||||
from django.urls import path, re_path
|
||||
|
||||
from School.views import TeachersView, EnseignantView, SpecialitiesView, SpecialityView, ClassesView, ClasseView, PlanningsView, PlanningView
|
||||
|
||||
urlpatterns = [
|
||||
re_path(r'^teachers$', TeachersView.as_view(), name="teachers"),
|
||||
re_path(r'^teacher$', EnseignantView.as_view(), name="teacher"),
|
||||
re_path(r'^teacher/([0-9]+)$', EnseignantView.as_view(), name="teacher"),
|
||||
|
||||
re_path(r'^specialities$', SpecialitiesView.as_view(), name="specialities"),
|
||||
re_path(r'^speciality$', SpecialityView.as_view(), name="speciality"),
|
||||
re_path(r'^speciality/([0-9]+)$', SpecialityView.as_view(), name="speciality"),
|
||||
|
||||
re_path(r'^schoolClasses$', ClassesView.as_view(), name="schoolClasses"),
|
||||
re_path(r'^schoolClass$', ClasseView.as_view(), name="schoolClass"),
|
||||
re_path(r'^schoolClass/([0-9]+)$', ClasseView.as_view(), name="schoolClass"),
|
||||
|
||||
re_path(r'^plannings$', PlanningsView.as_view(), name="plannings"),
|
||||
re_path(r'^planning$', PlanningView.as_view(), name="planning"),
|
||||
re_path(r'^planning/([0-9]+)$', PlanningView.as_view(), name="planning"),
|
||||
]
|
||||
@ -4,121 +4,121 @@ from django.utils.decorators import method_decorator
|
||||
from rest_framework.parsers import JSONParser
|
||||
from rest_framework.views import APIView
|
||||
from django.core.cache import cache
|
||||
from .models import Enseignant, Specialite, Classe, Planning
|
||||
from .serializers import EnseignantSerializer, SpecialiteSerializer, ClasseSerializer, PlanningSerializer
|
||||
from .models import Teacher, Speciality, SchoolClass, Planning
|
||||
from .serializers import TeacherSerializer, SpecialitySerializer, SchoolClassSerializer, PlanningSerializer
|
||||
from N3wtSchool import bdd
|
||||
|
||||
class EnseignantsView(APIView):
|
||||
class TeachersView(APIView):
|
||||
def get(self, request):
|
||||
enseignantsList=bdd.getAllObjects(Enseignant)
|
||||
enseignants_serializer=EnseignantSerializer(enseignantsList, many=True)
|
||||
teachersList=bdd.getAllObjects(Teacher)
|
||||
teachers_serializer=TeacherSerializer(teachersList, many=True)
|
||||
|
||||
return JsonResponse(enseignants_serializer.data, safe=False)
|
||||
return JsonResponse(teachers_serializer.data, safe=False)
|
||||
|
||||
@method_decorator(csrf_protect, name='dispatch')
|
||||
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
||||
class EnseignantView(APIView):
|
||||
def get (self, request, _id):
|
||||
enseignant = bdd.getObject(_objectName=Enseignant, _columnName='id', _value=_id)
|
||||
enseignant_serializer=EnseignantSerializer(enseignant)
|
||||
teacher = bdd.getObject(_objectName=Teacher, _columnName='id', _value=_id)
|
||||
teacher_serializer=TeacherSerializer(teacher)
|
||||
|
||||
return JsonResponse(enseignant_serializer.data, safe=False)
|
||||
return JsonResponse(teacher_serializer.data, safe=False)
|
||||
|
||||
def post(self, request):
|
||||
enseignant_data=JSONParser().parse(request)
|
||||
enseignant_serializer = EnseignantSerializer(data=enseignant_data)
|
||||
teacher_data=JSONParser().parse(request)
|
||||
teacher_serializer = TeacherSerializer(data=teacher_data)
|
||||
|
||||
if enseignant_serializer.is_valid():
|
||||
enseignant_serializer.save()
|
||||
if teacher_serializer.is_valid():
|
||||
teacher_serializer.save()
|
||||
|
||||
return JsonResponse(enseignant_serializer.data, safe=False)
|
||||
return JsonResponse(teacher_serializer.data, safe=False)
|
||||
|
||||
return JsonResponse(enseignant_serializer.errors, safe=False)
|
||||
return JsonResponse(teacher_serializer.errors, safe=False)
|
||||
|
||||
def put(self, request, _id):
|
||||
enseignant_data=JSONParser().parse(request)
|
||||
enseignant = bdd.getObject(_objectName=Enseignant, _columnName='id', _value=_id)
|
||||
enseignant_serializer = EnseignantSerializer(enseignant, data=enseignant_data)
|
||||
if enseignant_serializer.is_valid():
|
||||
enseignant_serializer.save()
|
||||
return JsonResponse(enseignant_serializer.data, safe=False)
|
||||
teacher_data=JSONParser().parse(request)
|
||||
teacher = bdd.getObject(_objectName=Teacher, _columnName='id', _value=_id)
|
||||
teacher_serializer = TeacherSerializer(teacher, data=teacher_data)
|
||||
if teacher_serializer.is_valid():
|
||||
teacher_serializer.save()
|
||||
return JsonResponse(teacher_serializer.data, safe=False)
|
||||
|
||||
return JsonResponse(enseignant_serializer.errors, safe=False)
|
||||
return JsonResponse(teacher_serializer.errors, safe=False)
|
||||
|
||||
def delete(self, request, _id):
|
||||
enseignant = bdd.getObject(_objectName=Enseignant, _columnName='id', _value=_id)
|
||||
if enseignant is not None:
|
||||
if enseignant.profilAssocie:
|
||||
teacher = bdd.getObject(_objectName=Teacher, _columnName='id', _value=_id)
|
||||
if teacher is not None:
|
||||
if teacher.profilAssocie:
|
||||
print('Suppression du profil associé')
|
||||
enseignant.profilAssocie.delete()
|
||||
enseignant.delete()
|
||||
return JsonResponse({'message': 'La suppression de l\'enseignant a été effectuée avec succès'}, safe=False)
|
||||
teacher.profilAssocie.delete()
|
||||
teacher.delete()
|
||||
return JsonResponse({'message': 'La suppression de l\'teacher a été effectuée avec succès'}, safe=False)
|
||||
else:
|
||||
return JsonResponse({'erreur': 'L\'enseignant n\'a pas été trouvé'}, safe=False)
|
||||
return JsonResponse({'erreur': 'L\'teacher n\'a pas été trouvé'}, safe=False)
|
||||
|
||||
|
||||
@method_decorator(csrf_protect, name='dispatch')
|
||||
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
||||
class SpecialitesView(APIView):
|
||||
class SpecialitiesView(APIView):
|
||||
def get(self, request):
|
||||
specialitesList=bdd.getAllObjects(Specialite)
|
||||
specialites_serializer=SpecialiteSerializer(specialitesList, many=True)
|
||||
specialitiesList=bdd.getAllObjects(Speciality)
|
||||
specialities_serializer=SpecialitySerializer(specialitiesList, many=True)
|
||||
|
||||
return JsonResponse(specialites_serializer.data, safe=False)
|
||||
return JsonResponse(specialities_serializer.data, safe=False)
|
||||
|
||||
def post(self, request):
|
||||
specialites_data=JSONParser().parse(request)
|
||||
specialities_data=JSONParser().parse(request)
|
||||
all_valid = True
|
||||
for specialite_data in specialites_data:
|
||||
specialite_serializer = SpecialiteSerializer(data=specialite_data)
|
||||
for speciality_data in specialities_data:
|
||||
speciality_serializer = SpecialitySerializer(data=speciality_data)
|
||||
|
||||
if specialite_serializer.is_valid():
|
||||
specialite_serializer.save()
|
||||
if speciality_serializer.is_valid():
|
||||
speciality_serializer.save()
|
||||
else:
|
||||
all_valid = False
|
||||
break
|
||||
if all_valid:
|
||||
specialitesList = bdd.getAllObjects(Specialite)
|
||||
specialites_serializer = SpecialiteSerializer(specialitesList, many=True)
|
||||
specialitiesList = bdd.getAllObjects(Speciality)
|
||||
specialities_serializer = SpecialitySerializer(specialitiesList, many=True)
|
||||
|
||||
return JsonResponse(specialites_serializer.data, safe=False)
|
||||
return JsonResponse(specialities_serializer.data, safe=False)
|
||||
|
||||
return JsonResponse(specialite_serializer.errors, safe=False)
|
||||
return JsonResponse(speciality_serializer.errors, safe=False)
|
||||
|
||||
|
||||
@method_decorator(csrf_protect, name='dispatch')
|
||||
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
||||
class SpecialiteView(APIView):
|
||||
class SpecialityView(APIView):
|
||||
def get (self, request, _id):
|
||||
specialite = bdd.getObject(_objectName=Specialite, _columnName='id', _value=_id)
|
||||
specialite_serializer=SpecialiteSerializer(specialite)
|
||||
speciality = bdd.getObject(_objectName=Speciality, _columnName='id', _value=_id)
|
||||
speciality_serializer=SpecialitySerializer(speciality)
|
||||
|
||||
return JsonResponse(specialite_serializer.data, safe=False)
|
||||
return JsonResponse(speciality_serializer.data, safe=False)
|
||||
|
||||
def post(self, request):
|
||||
specialite_data=JSONParser().parse(request)
|
||||
specialite_serializer = SpecialiteSerializer(data=specialite_data)
|
||||
speciality_data=JSONParser().parse(request)
|
||||
speciality_serializer = SpecialitySerializer(data=speciality_data)
|
||||
|
||||
if specialite_serializer.is_valid():
|
||||
specialite_serializer.save()
|
||||
return JsonResponse(specialite_serializer.data, safe=False)
|
||||
if speciality_serializer.is_valid():
|
||||
speciality_serializer.save()
|
||||
return JsonResponse(speciality_serializer.data, safe=False)
|
||||
|
||||
return JsonResponse(specialite_serializer.errors, safe=False)
|
||||
return JsonResponse(speciality_serializer.errors, safe=False)
|
||||
|
||||
def put(self, request, _id):
|
||||
specialite_data=JSONParser().parse(request)
|
||||
specialite = bdd.getObject(_objectName=Specialite, _columnName='id', _value=_id)
|
||||
specialite_serializer = SpecialiteSerializer(specialite, data=specialite_data)
|
||||
if specialite_serializer.is_valid():
|
||||
specialite_serializer.save()
|
||||
return JsonResponse(specialite_serializer.data, safe=False)
|
||||
speciality_data=JSONParser().parse(request)
|
||||
speciality = bdd.getObject(_objectName=Speciality, _columnName='id', _value=_id)
|
||||
speciality_serializer = SpecialitySerializer(speciality, data=speciality_data)
|
||||
if speciality_serializer.is_valid():
|
||||
speciality_serializer.save()
|
||||
return JsonResponse(speciality_serializer.data, safe=False)
|
||||
|
||||
return JsonResponse(specialite_serializer.errors, safe=False)
|
||||
return JsonResponse(speciality_serializer.errors, safe=False)
|
||||
|
||||
def delete(self, request, _id):
|
||||
specialite = bdd.getObject(_objectName=Specialite, _columnName='id', _value=_id)
|
||||
if specialite != None:
|
||||
specialite.delete()
|
||||
speciality = bdd.getObject(_objectName=Speciality, _columnName='id', _value=_id)
|
||||
if speciality != None:
|
||||
speciality.delete()
|
||||
|
||||
return JsonResponse("La suppression de la spécialité a été effectuée avec succès", safe=False)
|
||||
|
||||
@ -126,15 +126,15 @@ class SpecialiteView(APIView):
|
||||
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
||||
class ClassesView(APIView):
|
||||
def get(self, request):
|
||||
classesList=bdd.getAllObjects(Classe)
|
||||
classes_serializer=ClasseSerializer(classesList, many=True)
|
||||
classesList=bdd.getAllObjects(SchoolClass)
|
||||
classes_serializer=SchoolClassSerializer(classesList, many=True)
|
||||
return JsonResponse(classes_serializer.data, safe=False)
|
||||
|
||||
def post(self, request):
|
||||
all_valid = True
|
||||
classes_data=JSONParser().parse(request)
|
||||
for classe_data in classes_data:
|
||||
classe_serializer = ClasseSerializer(data=classe_data)
|
||||
classe_serializer = SchoolClassSerializer(data=classe_data)
|
||||
|
||||
if classe_serializer.is_valid():
|
||||
classe_serializer.save()
|
||||
@ -143,8 +143,8 @@ class ClassesView(APIView):
|
||||
break
|
||||
|
||||
if all_valid:
|
||||
classesList = bdd.getAllObjects(Classe)
|
||||
classes_serializer = ClasseSerializer(classesList, many=True)
|
||||
classesList = bdd.getAllObjects(SchoolClass)
|
||||
classes_serializer = SchoolClassSerializer(classesList, many=True)
|
||||
|
||||
return JsonResponse(classes_serializer.data, safe=False)
|
||||
|
||||
@ -154,14 +154,14 @@ class ClassesView(APIView):
|
||||
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
||||
class ClasseView(APIView):
|
||||
def get (self, request, _id):
|
||||
classe = bdd.getObject(_objectName=Classe, _columnName='id', _value=_id)
|
||||
classe_serializer=ClasseSerializer(classe)
|
||||
schoolClass = bdd.getObject(_objectName=SchoolClass, _columnName='id', _value=_id)
|
||||
classe_serializer=SchoolClassSerializer(schoolClass)
|
||||
|
||||
return JsonResponse(classe_serializer.data, safe=False)
|
||||
|
||||
def post(self, request):
|
||||
classe_data=JSONParser().parse(request)
|
||||
classe_serializer = ClasseSerializer(data=classe_data)
|
||||
classe_serializer = SchoolClassSerializer(data=classe_data)
|
||||
|
||||
if classe_serializer.is_valid():
|
||||
classe_serializer.save()
|
||||
@ -171,8 +171,8 @@ class ClasseView(APIView):
|
||||
|
||||
def put(self, request, _id):
|
||||
classe_data=JSONParser().parse(request)
|
||||
classe = bdd.getObject(_objectName=Classe, _columnName='id', _value=_id)
|
||||
classe_serializer = ClasseSerializer(classe, data=classe_data)
|
||||
schoolClass = bdd.getObject(_objectName=SchoolClass, _columnName='id', _value=_id)
|
||||
classe_serializer = SchoolClassSerializer(schoolClass, data=classe_data)
|
||||
if classe_serializer.is_valid():
|
||||
classe_serializer.save()
|
||||
return JsonResponse(classe_serializer.data, safe=False)
|
||||
@ -180,23 +180,23 @@ class ClasseView(APIView):
|
||||
return JsonResponse(classe_serializer.errors, safe=False)
|
||||
|
||||
def delete(self, request, _id):
|
||||
classe = bdd.getObject(_objectName=Classe, _columnName='id', _value=_id)
|
||||
if classe is not None:
|
||||
# Supprimer les plannings associés à la classe
|
||||
for planning in classe.plannings.all():
|
||||
schoolClass = bdd.getObject(_objectName=SchoolClass, _columnName='id', _value=_id)
|
||||
if schoolClass is not None:
|
||||
# Supprimer les plannings associés à la schoolClass
|
||||
for planning in schoolClass.plannings.all():
|
||||
print(f'Planning à supprimer : {planning}')
|
||||
planning.delete()
|
||||
|
||||
# Retirer la classe des élèves associés
|
||||
for eleve in classe.eleves.all():
|
||||
print(f'Eleve à retirer de la classe : {eleve}')
|
||||
# Retirer la schoolClass des élèves associés
|
||||
for eleve in schoolClass.eleves.all():
|
||||
print(f'Student à retirer de la schoolClass : {eleve}')
|
||||
eleve.classeAssociee = None
|
||||
eleve.save()
|
||||
|
||||
# Supprimer la classe
|
||||
classe.delete()
|
||||
# Supprimer la schoolClass
|
||||
schoolClass.delete()
|
||||
|
||||
return JsonResponse("La suppression de la classe a été effectuée avec succès", safe=False)
|
||||
return JsonResponse("La suppression de la schoolClass a été effectuée avec succès", safe=False)
|
||||
|
||||
|
||||
@method_decorator(csrf_protect, name='dispatch')
|
||||
1
Back-End/Subscriptions/__init__.py
Normal file
1
Back-End/Subscriptions/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
default_app_config = 'Subscriptions.apps.GestionInscriptionsConfig'
|
||||
@ -2,8 +2,8 @@ from django.contrib import admin
|
||||
|
||||
from .models import *
|
||||
|
||||
admin.site.register(Eleve)
|
||||
admin.site.register(Responsable)
|
||||
admin.site.register(Student)
|
||||
admin.site.register(Guardian)
|
||||
|
||||
class EleveAdmin(admin.ModelAdmin):
|
||||
def save_model(self, request, obj, form, change):
|
||||
@ -3,8 +3,8 @@ from django.conf import settings
|
||||
|
||||
class GestioninscriptionsConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'GestionInscriptions'
|
||||
name = 'Subscriptions'
|
||||
|
||||
def ready(self):
|
||||
from GestionInscriptions.signals import clear_cache
|
||||
from Subscriptions.signals import clear_cache
|
||||
clear_cache()
|
||||
45
Back-End/Subscriptions/automate.py
Normal file
45
Back-End/Subscriptions/automate.py
Normal file
@ -0,0 +1,45 @@
|
||||
# state_machine.py
|
||||
import json
|
||||
from Subscriptions.models import RegistrationForm
|
||||
from Subscriptions.signals import clear_cache
|
||||
|
||||
state_mapping = {
|
||||
"ABSENT": RegistrationForm.RegistrationFormStatus.RF_ABSENT,
|
||||
"CREE": RegistrationForm.RegistrationFormStatus.RF_CREATED,
|
||||
"ENVOYE": RegistrationForm.RegistrationFormStatus.RF_SENT,
|
||||
"EN_VALIDATION": RegistrationForm.RegistrationFormStatus.RF_UNDER_REVIEW,
|
||||
"A_RELANCER": RegistrationForm.RegistrationFormStatus.RF_TO_BE_FOLLOWED_UP,
|
||||
"VALIDE": RegistrationForm.RegistrationFormStatus.RF_VALIDATED,
|
||||
"ARCHIVE": RegistrationForm.RegistrationFormStatus.RF_ARCHIVED
|
||||
}
|
||||
|
||||
def load_config(config_file):
|
||||
with open(config_file, 'r') as file:
|
||||
config = json.load(file)
|
||||
return config
|
||||
|
||||
def getStateMachineObject(etat) :
|
||||
return Automate_RF_Register(etat)
|
||||
|
||||
def getStateMachineObjectState(etat):
|
||||
return Automate_RF_Register(etat).state
|
||||
|
||||
def updateStateMachine(rf, transition) :
|
||||
automateModel = load_config('Subscriptions/Configuration/automate.json')
|
||||
state_machine = getStateMachineObject(rf.status)
|
||||
print(f'etat DI : {state_machine.state}')
|
||||
if state_machine.trigger(transition, automateModel):
|
||||
rf.status = state_machine.state
|
||||
rf.save()
|
||||
clear_cache()
|
||||
|
||||
class Automate_RF_Register:
|
||||
def __init__(self, initial_state):
|
||||
self.state = initial_state
|
||||
|
||||
def trigger(self, transition_name, config):
|
||||
for transition in config["transitions"]:
|
||||
if transition["name"] == transition_name and self.state == state_mapping[transition["from"]]:
|
||||
self.state = state_mapping[transition["to"]]
|
||||
return True
|
||||
return False
|
||||
@ -11,7 +11,7 @@ def envoieReinitMotDePasse(recipients, code):
|
||||
fail_silently=False,
|
||||
)
|
||||
|
||||
def envoieDossierInscription(recipients):
|
||||
def sendRegisterForm(recipients):
|
||||
errorMessage = ''
|
||||
try:
|
||||
print(f'{settings.EMAIL_HOST_USER}')
|
||||
@ -68,7 +68,7 @@ def isValid(message, fiche_inscription):
|
||||
idMail = result.group(1).strip()
|
||||
|
||||
eleve = fiche_inscription.eleve
|
||||
responsable = eleve.getResponsablePrincipal()
|
||||
responsable = eleve.getMainGuardian()
|
||||
mailReponsableAVerifier = responsable.mail
|
||||
|
||||
return responsableMail == mailReponsableAVerifier and str(idMail) == str(fiche_inscription.eleve.id)
|
||||
179
Back-End/Subscriptions/models.py
Normal file
179
Back-End/Subscriptions/models.py
Normal file
@ -0,0 +1,179 @@
|
||||
from django.db import models
|
||||
from django.utils.timezone import now
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from Auth.models import Profile
|
||||
from School.models import SchoolClass
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
class RegistrationFee(models.Model):
|
||||
class PaymentOptions(models.IntegerChoices):
|
||||
SINGLE_PAYMENT = 0, _('Paiement en une seule fois')
|
||||
MONTHLY_PAYMENT = 1, _('Paiement mensuel')
|
||||
QUARTERLY_PAYMENT = 2, _('Paiement trimestriel')
|
||||
|
||||
name = models.CharField(max_length=255, unique=True)
|
||||
description = models.TextField(blank=True)
|
||||
base_amount = models.DecimalField(max_digits=10, decimal_places=2)
|
||||
discounts = models.JSONField(blank=True, null=True)
|
||||
supplements = models.JSONField(blank=True, null=True)
|
||||
validity_start_date = models.DateField()
|
||||
validity_end_date = models.DateField()
|
||||
payment_option = models.IntegerField(choices=PaymentOptions, default=PaymentOptions.SINGLE_PAYMENT)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Language(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
label = models.CharField(max_length=200, default="")
|
||||
|
||||
def __str__(self):
|
||||
return "LANGUAGE"
|
||||
|
||||
class Guardian(models.Model):
|
||||
last_name = models.CharField(max_length=200, default="")
|
||||
first_name = models.CharField(max_length=200, default="")
|
||||
birth_date = models.CharField(max_length=200, default="", blank=True)
|
||||
address = models.CharField(max_length=200, default="", blank=True)
|
||||
email = models.CharField(max_length=200, default="", blank=True)
|
||||
phone = models.CharField(max_length=200, default="", blank=True)
|
||||
profession = models.CharField(max_length=200, default="", blank=True)
|
||||
associated_profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
|
||||
|
||||
def __str__(self):
|
||||
return self.last_name + "_" + self.first_name
|
||||
|
||||
class Sibling(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
last_name = models.CharField(max_length=200, default="")
|
||||
first_name = models.CharField(max_length=200, default="")
|
||||
birth_date = models.CharField(max_length=200, default="", blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return "SIBLING"
|
||||
|
||||
class Student(models.Model):
|
||||
|
||||
class StudentGender(models.IntegerChoices):
|
||||
NONE = 0, _('Sélection du genre')
|
||||
MALE = 1, _('Garçon')
|
||||
FEMALE = 2, _('Fille')
|
||||
|
||||
class StudentLevel(models.IntegerChoices):
|
||||
NONE = 0, _('Sélection du niveau')
|
||||
TPS = 1, _('TPS - Très Petite Section')
|
||||
PS = 2, _('PS - Petite Section')
|
||||
MS = 3, _('MS - Moyenne Section')
|
||||
GS = 4, _('GS - Grande Section')
|
||||
|
||||
class PaymentMethod(models.IntegerChoices):
|
||||
NONE = 0, _('Sélection du mode de paiement')
|
||||
SEPA_DIRECT_DEBIT = 1, _('Prélèvement SEPA')
|
||||
CHECK = 2, _('Chèques')
|
||||
|
||||
last_name = models.CharField(max_length=200, default="")
|
||||
first_name = models.CharField(max_length=200, default="")
|
||||
gender = models.IntegerField(choices=StudentGender, default=StudentGender.NONE, blank=True)
|
||||
level = models.IntegerField(choices=StudentLevel, default=StudentLevel.NONE, blank=True)
|
||||
nationality = models.CharField(max_length=200, default="", blank=True)
|
||||
address = models.CharField(max_length=200, default="", blank=True)
|
||||
birth_date = models.DateField(null=True, blank=True)
|
||||
birth_place = models.CharField(max_length=200, default="", blank=True)
|
||||
birth_postal_code = models.IntegerField(default=0, blank=True)
|
||||
attending_physician = models.CharField(max_length=200, default="", blank=True)
|
||||
payment_method = models.IntegerField(choices=PaymentMethod, default=PaymentMethod.NONE, blank=True)
|
||||
|
||||
# Many-to-Many Relationship
|
||||
profiles = models.ManyToManyField(Profile, blank=True)
|
||||
|
||||
# Many-to-Many Relationship
|
||||
guardians = models.ManyToManyField(Guardian, blank=True)
|
||||
|
||||
# Many-to-Many Relationship
|
||||
siblings = models.ManyToManyField(Sibling, blank=True)
|
||||
|
||||
# Many-to-Many Relationship
|
||||
spoken_languages = models.ManyToManyField(Language, blank=True)
|
||||
|
||||
# One-to-Many Relationship
|
||||
associated_class = models.ForeignKey(SchoolClass, on_delete=models.SET_NULL, null=True, blank=True, related_name='students')
|
||||
|
||||
def __str__(self):
|
||||
return self.last_name + "_" + self.first_name
|
||||
|
||||
def getSpokenLanguages(self):
|
||||
return self.spoken_languages.all()
|
||||
|
||||
def getMainGuardian(self):
|
||||
return self.guardians.all()[0]
|
||||
|
||||
def getGuardians(self):
|
||||
return self.guardians.all()
|
||||
|
||||
def getProfiles(self):
|
||||
return self.profiles.all()
|
||||
|
||||
def getSiblings(self):
|
||||
return self.siblings.all()
|
||||
|
||||
def getNumberOfSiblings(self):
|
||||
return self.siblings.count()
|
||||
|
||||
@property
|
||||
def age(self):
|
||||
if self.birth_date:
|
||||
today = datetime.today()
|
||||
years = today.year - self.birth_date.year
|
||||
months = today.month - self.birth_date.month
|
||||
if today.day < self.birth_date.day:
|
||||
months -= 1
|
||||
if months < 0:
|
||||
years -= 1
|
||||
months += 12
|
||||
|
||||
# Determine the age format
|
||||
if 6 <= months <= 12:
|
||||
return f"{years} years 1/2"
|
||||
else:
|
||||
return f"{years} years"
|
||||
return None
|
||||
|
||||
@property
|
||||
def formatted_birth_date(self):
|
||||
if self.birth_date:
|
||||
return self.birth_date.strftime('%d-%m-%Y')
|
||||
return None
|
||||
|
||||
class RegistrationForm(models.Model):
|
||||
|
||||
class RegistrationFormStatus(models.IntegerChoices):
|
||||
RF_ABSENT = 0, _('Pas de dossier d\'inscription')
|
||||
RF_CREATED = 1, _('Dossier d\'inscription créé')
|
||||
RF_SENT = 2, _('Dossier d\'inscription envoyé')
|
||||
RF_UNDER_REVIEW = 3, _('Dossier d\'inscription en cours de validation')
|
||||
RF_TO_BE_FOLLOWED_UP = 4, _('Dossier d\'inscription à relancer')
|
||||
RF_VALIDATED = 5, _('Dossier d\'inscription validé')
|
||||
RF_ARCHIVED = 6, _('Dossier d\'inscription archivé')
|
||||
|
||||
# One-to-One Relationship
|
||||
student = models.OneToOneField(Student, on_delete=models.CASCADE, primary_key=True)
|
||||
status = models.IntegerField(choices=RegistrationFormStatus, default=RegistrationFormStatus.RF_ABSENT)
|
||||
last_update = models.DateTimeField(auto_now=True)
|
||||
notes = models.CharField(max_length=200, blank=True)
|
||||
registration_link_code = models.CharField(max_length=200, default="", blank=True)
|
||||
registration_file = models.FileField(upload_to=settings.DOCUMENT_DIR, default="", blank=True)
|
||||
associated_rf = models.CharField(max_length=200, default="", blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return "RF_" + self.student.last_name + "_" + self.student.first_name
|
||||
|
||||
class RegistrationFile(models.Model):
|
||||
name = models.CharField(max_length=255)
|
||||
file = models.FileField(upload_to='registration_files/')
|
||||
date_added = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
@ -16,5 +16,5 @@ class CustomPagination(PageNumberPagination):
|
||||
'count': self.page.paginator.count,
|
||||
'page_size': self.page_size,
|
||||
'max_page_size' : self.max_page_size,
|
||||
'fichesInscriptions': data }
|
||||
'registerForms': data }
|
||||
)
|
||||
214
Back-End/Subscriptions/serializers.py
Normal file
214
Back-End/Subscriptions/serializers.py
Normal file
@ -0,0 +1,214 @@
|
||||
from rest_framework import serializers
|
||||
from .models import RegistrationFile, RegistrationForm, Student, Guardian, Sibling, Language, RegistrationFee
|
||||
from School.models import SchoolClass
|
||||
from Auth.models import Profile
|
||||
from Auth.serializers import ProfileSerializer
|
||||
from GestionMessagerie.models import Messagerie
|
||||
from GestionNotification.models import Notification
|
||||
from N3wtSchool import settings
|
||||
from django.utils import timezone
|
||||
import pytz
|
||||
from datetime import datetime
|
||||
|
||||
class RegistrationFileSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = RegistrationFile
|
||||
fields = '__all__'
|
||||
|
||||
class RegistrationFeeSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False)
|
||||
class Meta:
|
||||
model = RegistrationFee
|
||||
fields = '__all__'
|
||||
|
||||
class LanguageSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False)
|
||||
class Meta:
|
||||
model = Language
|
||||
fields = '__all__'
|
||||
|
||||
class SiblingSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False)
|
||||
class Meta:
|
||||
model = Sibling
|
||||
fields = '__all__'
|
||||
|
||||
class GuardianSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False)
|
||||
associated_profile = serializers.PrimaryKeyRelatedField(queryset=Profile.objects.all(), required=True)
|
||||
associated_profile_email = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Guardian
|
||||
fields = '__all__'
|
||||
|
||||
def get_associated_profile_email(self, obj):
|
||||
return obj.associated_profile.email
|
||||
|
||||
|
||||
class StudentSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False)
|
||||
guardians = GuardianSerializer(many=True, required=False)
|
||||
siblings = SiblingSerializer(many=True, required=False)
|
||||
languages = LanguageSerializer(many=True, required=False)
|
||||
associated_class_id = serializers.PrimaryKeyRelatedField(queryset=SchoolClass.objects.all(), source='associated_class', required=False, write_only=False, read_only=False)
|
||||
age = serializers.SerializerMethodField()
|
||||
formatted_birth_date = serializers.SerializerMethodField()
|
||||
birth_date = serializers.DateField(input_formats=['%d-%m-%Y', '%Y-%m-%d'], required=False, allow_null=True)
|
||||
associated_class_name = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Student
|
||||
fields = '__all__'
|
||||
|
||||
def get_or_create_packages(self, guardians_data):
|
||||
guardians_ids = []
|
||||
for guardian_data in guardians_data:
|
||||
guardian_instance, created = Guardian.objects.get_or_create(
|
||||
id=guardian_data.get('id'),
|
||||
defaults=guardian_data
|
||||
)
|
||||
guardians_ids.append(guardian_instance.id)
|
||||
return guardians_ids
|
||||
|
||||
def create(self, validated_data):
|
||||
guardians_data = validated_data.pop('guardians', [])
|
||||
siblings_data = validated_data.pop('siblings', [])
|
||||
languages_data = validated_data.pop('spoken_languages', [])
|
||||
student = Student.objects.create(**validated_data)
|
||||
student.guardians.set(self.get_or_create_packages(guardians_data))
|
||||
student.siblings.set(self.get_or_create_packages(siblings_data))
|
||||
student.spoken_languages.set(self.get_or_create_packages(languages_data))
|
||||
|
||||
return student
|
||||
|
||||
def create_or_update_packages(self, guardians_data):
|
||||
guardians_ids = []
|
||||
for guardian_data in guardians_data:
|
||||
guardian_instance, created = Guardian.objects.update_or_create(
|
||||
id=guardian_data.get('id'),
|
||||
defaults=guardian_data
|
||||
)
|
||||
guardians_ids.append(guardian_instance.id)
|
||||
return guardians_ids
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
guardians_data = validated_data.pop('guardians', [])
|
||||
siblings_data = validated_data.pop('siblings', [])
|
||||
languages_data = validated_data.pop('spoken_languages', [])
|
||||
if guardians_data:
|
||||
instance.guardians.set(self.create_or_update_packages(guardians_data))
|
||||
if siblings_data:
|
||||
instance.siblings.set(self.create_or_update_packages(siblings_data))
|
||||
if languages_data:
|
||||
instance.spoken_languages.set(self.create_or_update_packages(languages_data))
|
||||
|
||||
for field in self.fields:
|
||||
try:
|
||||
setattr(instance, field, validated_data[field])
|
||||
except KeyError:
|
||||
pass
|
||||
instance.save()
|
||||
|
||||
return instance
|
||||
|
||||
def get_age(self, obj):
|
||||
return obj.age
|
||||
|
||||
def get_formatted_birth_date(self, obj):
|
||||
return obj.formatted_birth_date
|
||||
|
||||
def get_associated_class_name(self, obj):
|
||||
return obj.associated_class.atmosphereName if obj.associated_class else None
|
||||
|
||||
class RegistrationFormSerializer(serializers.ModelSerializer):
|
||||
student = StudentSerializer(many=False, required=False)
|
||||
registration_file = serializers.FileField(required=False)
|
||||
status_label = serializers.SerializerMethodField()
|
||||
formatted_last_update = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = RegistrationForm
|
||||
fields = '__all__'
|
||||
|
||||
def create(self, validated_data):
|
||||
student_data = validated_data.pop('student')
|
||||
student = StudentSerializer.create(StudentSerializer(), student_data)
|
||||
registrationForm = RegistrationForm.objects.create(student=student, **validated_data)
|
||||
return registrationForm
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
student_data = validated_data.pop('student', None)
|
||||
if student_data:
|
||||
student = instance.student
|
||||
StudentSerializer.update(StudentSerializer(), student, student_data)
|
||||
|
||||
for field in self.fields:
|
||||
try:
|
||||
setattr(instance, field, validated_data[field])
|
||||
except KeyError:
|
||||
pass
|
||||
instance.save()
|
||||
|
||||
return instance
|
||||
|
||||
def get_status_label(self, obj):
|
||||
return obj.get_status_display()
|
||||
|
||||
def get_formatted_last_update(self, obj):
|
||||
utc_time = timezone.localtime(obj.last_update) # Convert to local time
|
||||
local_tz = pytz.timezone(settings.TZ_APPLI)
|
||||
local_time = utc_time.astimezone(local_tz)
|
||||
|
||||
return local_time.strftime("%d-%m-%Y %H:%M")
|
||||
|
||||
class StudentByParentSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False)
|
||||
|
||||
class Meta:
|
||||
model = Student
|
||||
fields = ['id', 'last_name', 'first_name']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(StudentByParentSerializer, self).__init__(*args, **kwargs)
|
||||
for field in self.fields:
|
||||
self.fields[field].required = False
|
||||
|
||||
class RegistrationFormByParentSerializer(serializers.ModelSerializer):
|
||||
student = StudentByParentSerializer(many=False, required=True)
|
||||
|
||||
class Meta:
|
||||
model = RegistrationForm
|
||||
fields = ['student', 'status']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(RegistrationFormByParentSerializer, self).__init__(*args, **kwargs)
|
||||
for field in self.fields:
|
||||
self.fields[field].required = False
|
||||
|
||||
class GuardianByDICreationSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False)
|
||||
|
||||
class Meta:
|
||||
model = Guardian
|
||||
fields = ['id', 'last_name', 'first_name', 'email', 'associated_profile']
|
||||
|
||||
class StudentByRFCreationSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False)
|
||||
guardians = GuardianByDICreationSerializer(many=True, required=False)
|
||||
|
||||
class Meta:
|
||||
model = Student
|
||||
fields = ['id', 'last_name', 'first_name', 'guardians']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(StudentByRFCreationSerializer, self).__init__(*args, **kwargs)
|
||||
for field in self.fields:
|
||||
self.fields[field].required = False
|
||||
|
||||
class NotificationSerializer(serializers.ModelSerializer):
|
||||
notification_type_label = serializers.ReadOnlyField()
|
||||
|
||||
class Meta:
|
||||
model = Notification
|
||||
fields = '__all__'
|
||||
@ -1,8 +1,8 @@
|
||||
from django.db.models.signals import post_save, post_delete, m2m_changed
|
||||
from django.dispatch import receiver
|
||||
from django.core.cache import cache
|
||||
from GestionInscriptions.models import FicheInscription, Eleve, Responsable
|
||||
from GestionLogin.models import Profil
|
||||
from .models import RegistrationForm, Student, Guardian
|
||||
from Auth.models import Profile
|
||||
from N3wtSchool import settings
|
||||
from N3wtSchool.redis_client import redis_client
|
||||
import logging
|
||||
@ -20,25 +20,25 @@ def clear_cache():
|
||||
redis_client.delete(key)
|
||||
logger.debug(f'deleting : {key}')
|
||||
|
||||
@receiver(post_save, sender=FicheInscription)
|
||||
@receiver(post_delete, sender=FicheInscription)
|
||||
@receiver(post_save, sender=RegistrationForm)
|
||||
@receiver(post_delete, sender=RegistrationForm)
|
||||
def clear_cache_after_change(sender, instance, **kwargs):
|
||||
clear_cache()
|
||||
|
||||
@receiver(m2m_changed, sender=Eleve.responsables.through)
|
||||
@receiver(m2m_changed, sender=Student.guardians.through)
|
||||
def check_orphan_reponsables(sender, **kwargs):
|
||||
action = kwargs.pop('action', None)
|
||||
instance = kwargs.pop('instance', None)
|
||||
# pre_clear : lors de la suppression d'une FI (on fait un "clear" sur chaque relation)
|
||||
if action in ('post_remove', 'post_clear'):
|
||||
if instance.responsables.all():
|
||||
Responsable.objects.filter(eleve=None).delete()
|
||||
if instance.guardians.all():
|
||||
Guardian.objects.filter(eleve=None).delete()
|
||||
|
||||
@receiver(m2m_changed, sender=Eleve.profils.through)
|
||||
@receiver(m2m_changed, sender=Student.profiles.through)
|
||||
def check_orphan_profils(sender, **kwargs):
|
||||
action = kwargs.pop('action', None)
|
||||
instance = kwargs.pop('instance', None)
|
||||
# pre_clear : lors de la suppression d'une FI (on fait un "clear" sur chaque relation)
|
||||
if action in ('post_remove', 'post_clear'):
|
||||
if instance.profils.all():
|
||||
Profil.objects.filter(eleve=None).delete()
|
||||
if instance.profiles.all():
|
||||
Profile.objects.filter(eleve=None).delete()
|
||||
@ -1,8 +1,8 @@
|
||||
# tasks.py
|
||||
from celery import shared_task
|
||||
from django.utils import timezone
|
||||
from GestionInscriptions.automate import Automate_DI_Inscription, updateStateMachine
|
||||
from .models import FicheInscription
|
||||
from Subscriptions.automate import Automate_RF_Register, updateStateMachine
|
||||
from .models import RegistrationForm
|
||||
from GestionMessagerie.models import Messagerie
|
||||
from N3wtSchool import settings, bdd
|
||||
import requests
|
||||
@ -15,7 +15,7 @@ def check_for_signature_deadlines():
|
||||
deadline = now - timezone.timedelta(days=settings.EXPIRATION_DI_NB_DAYS)
|
||||
# deadline = now - timezone.timedelta(seconds=settings.EXPIRATION_DI_NB_DAYS)
|
||||
|
||||
dossiers_en_attente = FicheInscription.objects.filter(etat=FicheInscription.EtatDossierInscription.DI_ENVOYE, dateMAJ__lt=deadline)
|
||||
dossiers_en_attente = RegistrationForm.objects.filter(etat=RegistrationForm.RegistrationFormStatus.DI_ENVOYE, dateMAJ__lt=deadline)
|
||||
|
||||
for dossier in dossiers_en_attente:
|
||||
send_notification(dossier)
|
||||
@ -28,7 +28,7 @@ def send_notification(dossier):
|
||||
|
||||
url = settings.URL_DJANGO + 'GestionMessagerie/message'
|
||||
|
||||
destinataires = dossier.eleve.profils.all()
|
||||
destinataires = dossier.eleve.profiles.all()
|
||||
for destinataire in destinataires:
|
||||
message = {
|
||||
"objet": "[RELANCE]",
|
||||
@ -3,7 +3,7 @@
|
||||
{% block content %}
|
||||
<h1>Création d'une nouvelle fiche d'inscription</h1>
|
||||
<br>
|
||||
<form action='{% url 'GestionInscriptions:nouvelEleve' %}' method="post">
|
||||
<form action='{% url 'Subscriptions:nouvelEleve' %}' method="post">
|
||||
{% csrf_token %}
|
||||
<ul>
|
||||
<li style="margin-bottom: 15px"><strong>ELEVE</strong></li>
|
||||
@ -2,7 +2,7 @@
|
||||
{% block content %}
|
||||
<h1>Configuration des dossiers d'inscriptions</h1>
|
||||
<br>
|
||||
<form action='{% url 'GestionInscriptions:index' %}' method="post">
|
||||
<form action='{% url 'Subscriptions:index' %}' method="post">
|
||||
{% csrf_token %}
|
||||
<ul>
|
||||
<div style="margin-bottom: 15px">
|
||||
@ -2,9 +2,9 @@
|
||||
{% block content %}
|
||||
<h1>Création du dossier d'inscription</h1>
|
||||
<br>
|
||||
<form action='{% url 'GestionInscriptions:validate' eleve.id %}' method="post" enctype="multipart/form-data">
|
||||
<form action='{% url 'Subscriptions:validate' eleve.id %}' method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{% with responsable=eleve.getResponsablePrincipal %}
|
||||
{% with responsable=eleve.getMainGuardian %}
|
||||
<ul>
|
||||
<li style="margin-bottom: 15px"><strong>ELEVE</strong></li>
|
||||
<div style="margin-bottom: 15px">
|
||||
@ -2,9 +2,9 @@
|
||||
{% block content %}
|
||||
<h1>Edition d'une fiche d'inscription</h1>
|
||||
<br>
|
||||
<form action='{% url 'GestionInscriptions:index' %}' method="post">
|
||||
<form action='{% url 'Subscriptions:index' %}' method="post">
|
||||
{% csrf_token %}
|
||||
{% with responsable=eleve.getResponsablePrincipal %}
|
||||
{% with responsable=eleve.getMainGuardian %}
|
||||
<ul>
|
||||
<div style="margin-bottom: 15px">
|
||||
<input type="hidden" name="fiche_id" value="{{ eleve.id }}">
|
||||
@ -47,22 +47,22 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{% for ficheInscription in ficheInscriptions_list %}
|
||||
{% with eleve=ficheInscription.eleve %}
|
||||
{% with responsable=eleve.getResponsablePrincipal %}
|
||||
{% with fichiers=ficheInscription|recupereFichiersDossierInscription %}
|
||||
{% for registerForm in ficheInscriptions_list %}
|
||||
{% with eleve=registerForm.eleve %}
|
||||
{% with responsable=eleve.getMainGuardian %}
|
||||
{% with fichiers=registerForm|recupereFichiersDossierInscription %}
|
||||
<tr>
|
||||
<td>{{ eleve.nom }}</td>
|
||||
<td>{{ eleve.prenom }}</td>
|
||||
<td>{{ responsable.mail }}</td>
|
||||
<td>{{ responsable.telephone }}</td>
|
||||
<td>{{ ficheInscription.dateMAJ }}</td>
|
||||
<td>{{ registerForm.dateMAJ }}</td>
|
||||
<td>
|
||||
{% if ficheInscription.etat == 0 %}
|
||||
{% if registerForm.etat == 0 %}
|
||||
<span class="tag blue"> Créé</span>
|
||||
{% elif ficheInscription.etat == 1 %}
|
||||
{% elif registerForm.etat == 1 %}
|
||||
<span class="tag orange"> Envoyé</span>
|
||||
{% elif ficheInscription.etat == 2 %}
|
||||
{% elif registerForm.etat == 2 %}
|
||||
<span class="tag purple"> En Validation</span>
|
||||
{% else %}
|
||||
<span class="tag green"> Validé</span>
|
||||
@ -74,7 +74,7 @@
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td class="actions">
|
||||
<button class="icon-btn" onclick="location.href='{% url 'GestionInscriptions:send' eleve.id %}'" type="submit"> <i class="icon directbox-send"></i></button>
|
||||
<button class="icon-btn" onclick="location.href='{% url 'Subscriptions:send' eleve.id %}'" type="submit"> <i class="icon directbox-send"></i></button>
|
||||
<button class="icon-btn"> <i class="icon edit"></i></button>
|
||||
<button class="icon-btn red"> <i class="icon user-minus"></i></button>
|
||||
</td>
|
||||
@ -45,49 +45,49 @@
|
||||
</div>
|
||||
<div>
|
||||
<div class='details'>
|
||||
Signé le : <b>{{ dateSignature }}</b> <br/>
|
||||
A : <b>{{ heureSignature }}</b>
|
||||
Signé le : <b>{{ signatureDate }}</b> <br/>
|
||||
A : <b>{{ signatureTime }}</b>
|
||||
<hr class='hrItem' />
|
||||
<h1>ELEVE</h1>
|
||||
{% with niveau=eleve|recupereNiveauEleve %}
|
||||
{% with genre=eleve|recupereGenreEleve %}
|
||||
NOM : <b>{{ eleve.nom }}</b> <br/>
|
||||
PRENOM : <b>{{ eleve.prenom }}</b> <br/>
|
||||
ADRESSE : <b>{{ eleve.adresse }}</b> <br/>
|
||||
GENRE : <b>{{ genre }}</b> <br/>
|
||||
NE(E) LE : <b>{{ eleve.dateNaissance }}</b> <br/>
|
||||
A : <b>{{ eleve.lieuNaissance }} ({{ eleve.codePostalNaissance }})</b> <br/>
|
||||
NATIONALITE : <b>{{ eleve.nationalite }}</b> <br/>
|
||||
NIVEAU : <b>{{ niveau }}</b> <br/>
|
||||
MEDECIN TRAITANT : <b>{{ eleve.medecinTraitant }}</b> <br/>
|
||||
{% with level=student|getStudentLevel %}
|
||||
{% with gender=student|getStudentGender %}
|
||||
NOM : <b>{{ student.last_name }}</b> <br/>
|
||||
PRENOM : <b>{{ student.first_name }}</b> <br/>
|
||||
ADRESSE : <b>{{ student.address }}</b> <br/>
|
||||
GENRE : <b>{{ gender }}</b> <br/>
|
||||
NE(E) LE : <b>{{ student.birth_date }}</b> <br/>
|
||||
A : <b>{{ student.birth_place }} ({{ student.birth_postal_code }})</b> <br/>
|
||||
NATIONALITE : <b>{{ student.nationality }}</b> <br/>
|
||||
NIVEAU : <b>{{ level }}</b> <br/>
|
||||
MEDECIN TRAITANT : <b>{{ student.attending_physician }}</b> <br/>
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
<hr class='hrItem' />
|
||||
<h1>RESPONSABLES</h1>
|
||||
{% with responsables_List=eleve.getResponsables %}
|
||||
{% with freres_List=eleve.getFreres %}
|
||||
{% for responsable in responsables_List%}
|
||||
<h2>Responsable {{ forloop.counter }}</h2>
|
||||
NOM : <b>{{ responsable.nom }}</b> <br/>
|
||||
PRENOM : <b>{{ responsable.prenom }}</b> <br/>
|
||||
ADRESSE : <b>{{ responsable.adresse }}</b> <br/>
|
||||
NE(E) LE : <b>{{ responsable.dateNaissance }}</b> <br/>
|
||||
MAIL : <b>{{ responsable.mail }}</b> <br/>
|
||||
TEL : <b>{{ responsable.telephone }}</b> <br/>
|
||||
PROFESSION : <b>{{ responsable.profession }}</b> <br/>
|
||||
{% with guardians=student.getGuardians %}
|
||||
{% with siblings=student.getGuardians %}
|
||||
{% for guardian in guardians%}
|
||||
<h2>Guardian {{ forloop.counter }}</h2>
|
||||
NOM : <b>{{ guardian.last_name }}</b> <br/>
|
||||
PRENOM : <b>{{ guardian.first_name }}</b> <br/>
|
||||
ADRESSE : <b>{{ guardian.address }}</b> <br/>
|
||||
NE(E) LE : <b>{{ guardian.birth_date }}</b> <br/>
|
||||
MAIL : <b>{{ guardian.email }}</b> <br/>
|
||||
TEL : <b>{{ guardian.phone }}</b> <br/>
|
||||
PROFESSION : <b>{{ guardian.profession }}</b> <br/>
|
||||
{% endfor %}
|
||||
<hr class='hrItem' />
|
||||
<h1>FRATRIE</h1>
|
||||
{% for frere in freres_List%}
|
||||
{% for sibling in siblings%}
|
||||
<h2>Frère - Soeur {{ forloop.counter }}</h2>
|
||||
NOM : <b>{{ frere.nom }}</b> <br/>
|
||||
PRENOM : <b>{{ frere.prenom }}</b> <br/>
|
||||
NE(E) LE : <b>{{ frere.dateNaissance }}</b> <br/>
|
||||
NOM : <b>{{ sibling.last_name }}</b> <br/>
|
||||
PRENOM : <b>{{ sibling.first_name }}</b> <br/>
|
||||
NE(E) LE : <b>{{ sibling.birth_date }}</b> <br/>
|
||||
{% endfor %}
|
||||
<hr class='hrItem' />
|
||||
<h1>MODALITES DE PAIEMENT</h1>
|
||||
{% with modePaiement=eleve|recupereModePaiement %}
|
||||
<b>{{ modePaiement }}</b> <br/>
|
||||
{% with paymentMethod=student|getStudentPaymentMethod %}
|
||||
<b>{{ paymentMethod }}</b> <br/>
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
18
Back-End/Subscriptions/templatetags/myTemplateTag.py
Normal file
18
Back-End/Subscriptions/templatetags/myTemplateTag.py
Normal file
@ -0,0 +1,18 @@
|
||||
from Subscriptions.models import RegistrationForm, Student
|
||||
from django import template
|
||||
register = template.Library()
|
||||
|
||||
@register.filter
|
||||
def getStudentPaymentMethod(pk):
|
||||
registerForm = RegistrationForm.objects.get(student=pk)
|
||||
return Student.PaymentMethod(int(registerForm.student.payment_method)).label
|
||||
|
||||
@register.filter
|
||||
def getStudentLevel(pk):
|
||||
registerForm = RegistrationForm.objects.get(student=pk)
|
||||
return Student.StudentLevel(int(registerForm.student.level)).label
|
||||
|
||||
@register.filter
|
||||
def getStudentGender(pk):
|
||||
registerForm = RegistrationForm.objects.get(student=pk)
|
||||
return Student.StudentGender(int(registerForm.student.gender)).label
|
||||
36
Back-End/Subscriptions/urls.py
Normal file
36
Back-End/Subscriptions/urls.py
Normal file
@ -0,0 +1,36 @@
|
||||
from django.urls import path, re_path
|
||||
|
||||
from . import views
|
||||
from Subscriptions.views import RegisterFileTemplateView, RegisterFormListView, RegisterFormView, StudentView, GuardianView, ChildrenListView, StudentListView, RegisterFeeView
|
||||
|
||||
urlpatterns = [
|
||||
re_path(r'^registerForms/([a-zA-z]+)$', RegisterFormListView.as_view(), name="listefichesInscriptions"),
|
||||
re_path(r'^registerForm$', RegisterFormView.as_view(), name="registerForms"),
|
||||
re_path(r'^registerForm/([0-9]+)$', RegisterFormView.as_view(), name="registerForms"),
|
||||
|
||||
# Page de formulaire d'inscription - ELEVE
|
||||
re_path(r'^student/([0-9]+)$', StudentView.as_view(), name="students"),
|
||||
|
||||
# Page de formulaire d'inscription - RESPONSABLE
|
||||
re_path(r'^fetchLastGuardian$', GuardianView.as_view(), name="fetchLastGuardian"),
|
||||
|
||||
# Envoi d'un dossier d'inscription
|
||||
re_path(r'^send/([0-9]+)$', views.send, name="send"),
|
||||
|
||||
# Archivage d'un dossier d'inscription
|
||||
re_path(r'^archive/([0-9]+)$', views.archive, name="archive"),
|
||||
|
||||
# Envoi d'une relance de dossier d'inscription
|
||||
re_path(r'^sendRelance/([0-9]+)$', views.relance, name="relance"),
|
||||
|
||||
# Page PARENT - Liste des children
|
||||
re_path(r'^children/([0-9]+)$', ChildrenListView.as_view(), name="children"),
|
||||
|
||||
# Page INSCRIPTION - Liste des élèves
|
||||
re_path(r'^students$', StudentListView.as_view(), name="students"),
|
||||
|
||||
# Frais d'inscription
|
||||
re_path(r'^registerFees$', RegisterFeeView.as_view(), name="registerFees"),
|
||||
re_path(r'^registerFilesTemplates$', RegisterFileTemplateView.as_view(), name='registerFilesTemplates'),
|
||||
re_path(r'^registerFilesTemplates/([0-9]+)$', RegisterFileTemplateView.as_view(), name="registerFilesTemplates"),
|
||||
]
|
||||
82
Back-End/Subscriptions/util.py
Normal file
82
Back-End/Subscriptions/util.py
Normal file
@ -0,0 +1,82 @@
|
||||
from django.shortcuts import render,get_object_or_404,get_list_or_404
|
||||
from .models import RegistrationForm, Student, Guardian, Sibling
|
||||
import time
|
||||
from datetime import date, datetime, timedelta
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.conf import settings
|
||||
from N3wtSchool import renderers
|
||||
from N3wtSchool import bdd
|
||||
|
||||
from io import BytesIO
|
||||
from django.core.files import File
|
||||
from pathlib import Path
|
||||
import os
|
||||
from enum import Enum
|
||||
|
||||
import random
|
||||
import string
|
||||
from rest_framework.parsers import JSONParser
|
||||
|
||||
def recupereListeFichesInscription():
|
||||
context = {
|
||||
"ficheInscriptions_list": bdd.getAllObjects(RegistrationForm),
|
||||
}
|
||||
return context
|
||||
|
||||
def recupereListeFichesInscriptionEnAttenteSEPA():
|
||||
|
||||
ficheInscriptionsSEPA_list = RegistrationForm.objects.filter(modePaiement="Prélèvement SEPA").filter(etat=RegistrationForm.RegistrationFormStatus['SEPA_ENVOYE'])
|
||||
return ficheInscriptionsSEPA_list
|
||||
|
||||
def _now():
|
||||
return datetime.now(ZoneInfo(settings.TZ_APPLI))
|
||||
|
||||
def convertToStr(dateValue, dateFormat):
|
||||
return dateValue.strftime(dateFormat)
|
||||
|
||||
def convertToDate(date_time):
|
||||
format = '%d-%m-%Y %H:%M'
|
||||
datetime_str = datetime.strptime(date_time, format)
|
||||
|
||||
return datetime_str
|
||||
|
||||
def convertTelephone(telephoneValue, separator='-'):
|
||||
return f"{telephoneValue[:2]}{separator}{telephoneValue[2:4]}{separator}{telephoneValue[4:6]}{separator}{telephoneValue[6:8]}{separator}{telephoneValue[8:10]}"
|
||||
|
||||
def genereRandomCode(length):
|
||||
return ''.join(random.choice(string.ascii_letters) for i in range(length))
|
||||
|
||||
def calculeDatePeremption(_start, nbDays):
|
||||
return convertToStr(_start + timedelta(days=nbDays), settings.DATE_FORMAT)
|
||||
|
||||
# Fonction permettant de retourner la valeur du QueryDict
|
||||
# QueryDict [ index ] -> Dernière valeur d'une liste
|
||||
# dict (QueryDict [ index ]) -> Toutes les valeurs de la liste
|
||||
def _(liste):
|
||||
return liste[0]
|
||||
|
||||
def getArgFromRequest(_argument, _request):
|
||||
resultat = None
|
||||
data=JSONParser().parse(_request)
|
||||
resultat = data[_argument]
|
||||
return resultat
|
||||
|
||||
def rfToPDF(registerForm):
|
||||
# Ajout du fichier d'inscriptions
|
||||
data = {
|
||||
'pdf_title': "Dossier d'inscription de %s"%registerForm.student.first_name,
|
||||
'signatureDate': convertToStr(_now(), '%d-%m-%Y'),
|
||||
'signatureTime': convertToStr(_now(), '%H:%M'),
|
||||
'student':registerForm.student,
|
||||
}
|
||||
|
||||
pdf = renderers.render_to_pdf('pdfs/dossier_inscription.html', data)
|
||||
|
||||
PDFFileName = "Dossier_Inscription_%s_%s.pdf"%(registerForm.student.last_name, registerForm.student.first_name)
|
||||
pathFichier = Path(settings.DOCUMENT_DIR + "/" + PDFFileName)
|
||||
if os.path.exists(str(pathFichier)):
|
||||
print(f'File exists : {str(pathFichier)}')
|
||||
os.remove(str(pathFichier))
|
||||
|
||||
receipt_file = BytesIO(pdf.content)
|
||||
registerForm.fichierInscription = File(receipt_file, PDFFileName)
|
||||
280
Back-End/Subscriptions/views.py
Normal file
280
Back-End/Subscriptions/views.py
Normal file
@ -0,0 +1,280 @@
|
||||
from django.http.response import JsonResponse
|
||||
from django.contrib.auth import login, authenticate, get_user_model
|
||||
from django.views.decorators.csrf import ensure_csrf_cookie, csrf_protect
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.core.cache import cache
|
||||
from django.core.paginator import Paginator
|
||||
from django.core.files import File
|
||||
from django.db.models import Q # Ajout de cet import
|
||||
from rest_framework.parsers import JSONParser,MultiPartParser, FormParser
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework import status
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
import os
|
||||
from io import BytesIO
|
||||
|
||||
import Subscriptions.mailManager as mailer
|
||||
import Subscriptions.util as util
|
||||
from Subscriptions.serializers import RegistrationFormSerializer, RegistrationFileSerializer, StudentSerializer, RegistrationFormByParentSerializer, StudentByRFCreationSerializer, RegistrationFeeSerializer
|
||||
from Subscriptions.pagination import CustomPagination
|
||||
from Subscriptions.signals import clear_cache
|
||||
from .models import Student, Guardian, RegistrationForm, RegistrationFee, RegistrationFile
|
||||
|
||||
from Subscriptions.automate import Automate_RF_Register, load_config, getStateMachineObjectState, updateStateMachine
|
||||
|
||||
from Auth.models import Profile
|
||||
|
||||
from N3wtSchool import settings, renderers, bdd
|
||||
|
||||
class RegisterFormListView(APIView):
|
||||
pagination_class = CustomPagination
|
||||
|
||||
def get_register_form(self, _filter, search=None):
|
||||
"""
|
||||
Récupère les fiches d'inscriptions en fonction du filtre passé.
|
||||
_filter: Filtre pour déterminer l'état des fiches ('pending', 'archived', 'subscribed')
|
||||
search: Terme de recherche (optionnel)
|
||||
"""
|
||||
if _filter == 'pending':
|
||||
exclude_states = [RegistrationForm.RegistrationFormStatus.RF_VALIDATED, RegistrationForm.RegistrationFormStatus.RF_ARCHIVED]
|
||||
return bdd.searchObjects(RegistrationForm, search, _excludeStates=exclude_states)
|
||||
elif _filter == 'archived':
|
||||
return bdd.getObjects(RegistrationForm, 'status', RegistrationForm.RegistrationFormStatus.RF_ARCHIVED)
|
||||
elif _filter == 'subscribed':
|
||||
return bdd.getObjects(RegistrationForm, 'status', RegistrationForm.RegistrationFormStatus.RF_VALIDATED)
|
||||
return None
|
||||
|
||||
def get(self, request, _filter):
|
||||
|
||||
# Récupération des paramètres
|
||||
search = request.GET.get('search', '').strip()
|
||||
page_size = request.GET.get('page_size', None)
|
||||
|
||||
# Gestion du page_size
|
||||
if page_size is not None:
|
||||
try:
|
||||
page_size = int(page_size)
|
||||
except ValueError:
|
||||
page_size = settings.NB_RESULT_PER_PAGE
|
||||
|
||||
# Définir le cache_key en fonction du filtre
|
||||
page_number = request.GET.get('page', 1)
|
||||
cache_key = f'N3WT_ficheInscriptions_{_filter}_page_{page_number}_search_{search if _filter == "pending" else ""}'
|
||||
cached_page = cache.get(cache_key)
|
||||
if cached_page:
|
||||
return JsonResponse(cached_page, safe=False)
|
||||
|
||||
# Récupérer les fiches d'inscriptions en fonction du filtre
|
||||
registerForms_List = self.get_register_form(_filter, search)
|
||||
|
||||
if not registerForms_List:
|
||||
return JsonResponse({'error' : 'aucune donnée trouvée', 'count' :0}, safe=False)
|
||||
|
||||
# Pagination
|
||||
paginator = self.pagination_class()
|
||||
page = paginator.paginate_queryset(registerForms_List, request)
|
||||
if page is not None:
|
||||
registerForms_serializer = RegistrationFormSerializer(page, many=True)
|
||||
response_data = paginator.get_paginated_response(registerForms_serializer.data)
|
||||
cache.set(cache_key, response_data, timeout=60*15)
|
||||
return JsonResponse(response_data, safe=False)
|
||||
|
||||
return JsonResponse({'error' : 'aucune donnée trouvée', 'count' :0}, safe=False)
|
||||
|
||||
def post(self, request):
|
||||
studentFormList_serializer=JSONParser().parse(request)
|
||||
for studentForm_data in studentFormList_serializer:
|
||||
# Ajout de la date de mise à jour
|
||||
studentForm_data["last_update"] = util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
|
||||
json.dumps(studentForm_data)
|
||||
# Ajout du code d'inscription
|
||||
code = util.genereRandomCode(12)
|
||||
studentForm_data["codeLienInscription"] = code
|
||||
studentForm_serializer = RegistrationFormSerializer(data=studentForm_data)
|
||||
|
||||
if studentForm_serializer.is_valid():
|
||||
studentForm_serializer.save()
|
||||
|
||||
return JsonResponse(studentForm_serializer.errors, safe=False)
|
||||
|
||||
|
||||
@method_decorator(csrf_protect, name='dispatch')
|
||||
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
||||
class RegisterFormView(APIView):
|
||||
pagination_class = CustomPagination
|
||||
|
||||
def get(self, request, _id):
|
||||
registerForm=bdd.getObject(RegistrationForm, "student__id", _id)
|
||||
registerForm_serializer=RegistrationFormSerializer(registerForm)
|
||||
return JsonResponse(registerForm_serializer.data, safe=False)
|
||||
|
||||
def post(self, request):
|
||||
studentForm_data=JSONParser().parse(request)
|
||||
# Ajout de la date de mise à jour
|
||||
studentForm_data["last_update"] = util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
|
||||
json.dumps(studentForm_data)
|
||||
# Ajout du code d'inscription
|
||||
code = util.genereRandomCode(12)
|
||||
studentForm_data["codeLienInscription"] = code
|
||||
|
||||
guardiansId = studentForm_data.pop('idGuardians', [])
|
||||
studentForm_serializer = RegistrationFormSerializer(data=studentForm_data)
|
||||
|
||||
if studentForm_serializer.is_valid():
|
||||
di = studentForm_serializer.save()
|
||||
|
||||
# Mise à jour de l'automate
|
||||
updateStateMachine(di, 'creationDI')
|
||||
|
||||
# Récupération du reponsable associé
|
||||
for guardianId in guardiansId:
|
||||
guardian = Guardian.objects.get(id=guardianId)
|
||||
di.student.guardians.add(guardian)
|
||||
di.save()
|
||||
|
||||
return JsonResponse(studentForm_serializer.data, safe=False)
|
||||
|
||||
return JsonResponse(studentForm_serializer.errors, safe=False)
|
||||
|
||||
def put(self, request, id):
|
||||
studentForm_data=JSONParser().parse(request)
|
||||
status = studentForm_data.pop('status', 0)
|
||||
studentForm_data["last_update"] = str(util.convertToStr(util._now(), '%d-%m-%Y %H:%M'))
|
||||
registerForm = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=id)
|
||||
|
||||
if status == RegistrationForm.RegistrationFormStatus.RF_UNDER_REVIEW:
|
||||
# Le parent a complété le dossier d'inscription, il est soumis à validation par l'école
|
||||
json.dumps(studentForm_data)
|
||||
util.rfToPDF(registerForm)
|
||||
# Mise à jour de l'automate
|
||||
updateStateMachine(registerForm, 'saisiDI')
|
||||
elif status == RegistrationForm.RegistrationFormStatus.RF_VALIDATED:
|
||||
# L'école a validé le dossier d'inscription
|
||||
# Mise à jour de l'automate
|
||||
updateStateMachine(registerForm, 'valideDI')
|
||||
|
||||
|
||||
studentForm_serializer = RegistrationFormSerializer(registerForm, data=studentForm_data)
|
||||
if studentForm_serializer.is_valid():
|
||||
studentForm_serializer.save()
|
||||
return JsonResponse(studentForm_serializer.data, safe=False)
|
||||
|
||||
return JsonResponse(studentForm_serializer.errors, safe=False)
|
||||
|
||||
def delete(self, request, id):
|
||||
register_form = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=id)
|
||||
if register_form != None:
|
||||
student = register_form.student
|
||||
student.guardians.clear()
|
||||
student.profiles.clear()
|
||||
student.delete()
|
||||
clear_cache()
|
||||
|
||||
return JsonResponse("La suppression du dossier a été effectuée avec succès", safe=False)
|
||||
|
||||
return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False)
|
||||
|
||||
class StudentView(APIView):
|
||||
def get(self, request, _id):
|
||||
student = bdd.getObject(_objectName=Student, _columnName='id', _value=_id)
|
||||
student_serializer = StudentSerializer(student)
|
||||
return JsonResponse(student_serializer.data, safe=False)
|
||||
|
||||
class GuardianView(APIView):
|
||||
def get(self, request):
|
||||
lastGuardian = bdd.getLastId(Guardian)
|
||||
return JsonResponse({"lastid":lastGuardian}, safe=False)
|
||||
|
||||
def send(request, id):
|
||||
register_form = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=id)
|
||||
if register_form != None:
|
||||
student = register_form.student
|
||||
guardian = student.getMainGuardian()
|
||||
email = guardian.email
|
||||
errorMessage = mailer.sendRegisterForm(email)
|
||||
if errorMessage == '':
|
||||
register_form.last_update=util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
|
||||
# Mise à jour de l'automate
|
||||
updateStateMachine(register_form, 'envoiDI')
|
||||
|
||||
return JsonResponse({"errorMessage":errorMessage}, safe=False)
|
||||
|
||||
return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False)
|
||||
|
||||
def archive(request, id):
|
||||
register_form = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=id)
|
||||
if register_form != None:
|
||||
register_form.last_update=util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
|
||||
# Mise à jour de l'automate
|
||||
updateStateMachine(register_form, 'archiveDI')
|
||||
|
||||
return JsonResponse({"errorMessage":''}, safe=False)
|
||||
|
||||
return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False)
|
||||
|
||||
def relance(request, id):
|
||||
register_form = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=id)
|
||||
if register_form != None:
|
||||
student = register_form.student
|
||||
guardian = student.getMainGuardian()
|
||||
email = guardian.email
|
||||
errorMessage = mailer.envoieRelanceDossierInscription(email, register_form.codeLienInscription)
|
||||
if errorMessage == '':
|
||||
register_form.status=RegistrationForm.RegistrationFormStatus.RF_SENT
|
||||
register_form.last_update=util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
|
||||
register_form.save()
|
||||
|
||||
return JsonResponse({"errorMessage":errorMessage}, safe=False)
|
||||
|
||||
return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False)
|
||||
|
||||
# API utilisée pour la vue parent
|
||||
class ChildrenListView(APIView):
|
||||
# Récupération des élèves d'un parent
|
||||
# idProfile : identifiant du profil connecté rattaché aux fiches d'élèves
|
||||
def get(self, request, _idProfile):
|
||||
students = bdd.getObjects(_objectName=RegistrationForm, _columnName='student__guardians__profilAssocie__id', _value=_idProfile)
|
||||
students_serializer = RegistrationFormByParentSerializer(students, many=True)
|
||||
return JsonResponse(students_serializer.data, safe=False)
|
||||
|
||||
# API utilisée pour la vue de création d'un DI
|
||||
class StudentListView(APIView):
|
||||
# Récupération de la liste des élèves inscrits ou en cours d'inscriptions
|
||||
def get(self, request):
|
||||
students = bdd.getAllObjects(_objectName=Student)
|
||||
students_serializer = StudentByRFCreationSerializer(students, many=True)
|
||||
return JsonResponse(students_serializer.data, safe=False)
|
||||
|
||||
# API utilisée pour la vue de personnalisation des frais d'inscription pour la structure
|
||||
class RegisterFeeView(APIView):
|
||||
def get(self, request):
|
||||
tarifs = bdd.getAllObjects(RegistrationFee)
|
||||
tarifs_serializer = RegistrationFeeSerializer(tarifs, many=True)
|
||||
return JsonResponse(tarifs_serializer.data, safe=False)
|
||||
|
||||
class RegisterFileTemplateView(APIView):
|
||||
parser_classes = (MultiPartParser, FormParser)
|
||||
|
||||
def get(self, request):
|
||||
fichiers = RegistrationFile.objects.all()
|
||||
serializer = RegistrationFormSerializer(fichiers, many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
def post(self, request):
|
||||
serializer = RegistrationFormSerializer(data=request.data)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
def delete(self, request, _id):
|
||||
fichierInscription = bdd.getObject(_objectName=RegistrationFile, _columnName='id', _value=_id)
|
||||
if fichierInscription is not None:
|
||||
fichierInscription.file.delete() # Supprimer le fichier uploadé
|
||||
fichierInscription.delete()
|
||||
return JsonResponse({'message': 'La suppression du fichier d\'inscription a été effectuée avec succès'}, safe=False)
|
||||
else:
|
||||
return JsonResponse({'erreur': 'Le fichier d\'inscription n\'a pas été trouvé'}, safe=False)
|
||||
@ -13,11 +13,11 @@ def run_command(command):
|
||||
commands = [
|
||||
["python", "manage.py", "collectstatic", "--noinput"],
|
||||
["python", "manage.py", "flush", "--noinput"],
|
||||
["python", "manage.py", "makemigrations", "GestionInscriptions"],
|
||||
["python", "manage.py", "makemigrations", "Subscriptions"],
|
||||
["python", "manage.py", "makemigrations", "GestionNotification"],
|
||||
["python", "manage.py", "makemigrations", "GestionMessagerie"],
|
||||
["python", "manage.py", "makemigrations", "GestionLogin"],
|
||||
["python", "manage.py", "makemigrations", "GestionEnseignants"],
|
||||
["python", "manage.py", "makemigrations", "Auth"],
|
||||
["python", "manage.py", "makemigrations", "School"],
|
||||
["python", "manage.py", "migrate"]
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user