feat: Gestion des profils des enseignants / Visualisation d'une classe [#4]

This commit is contained in:
N3WT DE COMPET
2024-11-23 20:02:51 +01:00
parent af0cd1c840
commit 81d1dfa9a7
26 changed files with 792 additions and 178 deletions

View File

@ -4,6 +4,27 @@ 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)
@ -59,7 +80,7 @@ class Eleve(models.Model):
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.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)
@ -77,6 +98,9 @@ class Eleve(models.Model):
# 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
@ -98,6 +122,31 @@ class Eleve(models.Model):
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):

View File

@ -1,5 +1,6 @@
from rest_framework import serializers
from GestionInscriptions.models import FicheInscription, Eleve, Responsable, Frere, Langue
from GestionInscriptions.models import 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
@ -7,6 +8,13 @@ from GestionNotification.models import Notification
from N3wtSchool import settings
from django.utils import timezone
import pytz
from datetime import datetime
class FraisInscriptionSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
class Meta:
model = FraisInscription
fields = '__all__'
class LanguesSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
@ -34,7 +42,13 @@ 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)
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__'
@ -89,6 +103,15 @@ class EleveSerializer(serializers.ModelSerializer):
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)

View File

@ -1,7 +1,7 @@
from django.urls import path, re_path
from . import views
from GestionInscriptions.views import ListFichesInscriptionView, FicheInscriptionView, EleveView, ResponsableView, ListeEnfantsView, ListeElevesView
from GestionInscriptions.views import ListFichesInscriptionView, FicheInscriptionView, EleveView, ResponsableView, ListeEnfantsView, ListeElevesView, FraisInscriptionView
urlpatterns = [
re_path(r'^fichesInscription/([a-zA-z]+)$', ListFichesInscriptionView.as_view(), name="listefichesInscriptions"),
@ -26,6 +26,9 @@ urlpatterns = [
# Page PARENT - Liste des enfants
re_path(r'^enfants/([0-9]+)$', ListeEnfantsView.as_view(), name="enfants"),
# Page INSCRIPTION - Liste des élèves
# 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"),
]

View File

@ -179,3 +179,23 @@ def getArgFromRequest(_argument, _request):
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)

View File

@ -17,10 +17,10 @@ from io import BytesIO
import GestionInscriptions.mailManager as mailer
import GestionInscriptions.util as util
from GestionInscriptions.serializers import FicheInscriptionSerializer, EleveSerializer, FicheInscriptionByParentSerializer, EleveByDICreationSerializer
from GestionInscriptions.serializers import FicheInscriptionSerializer, EleveSerializer, FicheInscriptionByParentSerializer, EleveByDICreationSerializer, FraisInscriptionSerializer
from GestionInscriptions.pagination import CustomPagination
from GestionInscriptions.signals import clear_cache
from .models import Eleve, Responsable, FicheInscription
from .models import Eleve, Responsable, FicheInscription, FraisInscription
from GestionInscriptions.automate import Automate_DI_Inscription, load_config, getStateMachineObjectState, updateStateMachine
from GestionLogin.models import Profil
@ -30,85 +30,57 @@ 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):
if _filter == 'all':
# 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
# Récupération des paramètres
search = request.GET.get('search', '').strip()
page_size = request.GET.get('page_size', None)
cached_page_size = cache.get('N3WT_page_size')
if cached_page_size != page_size:
clear_cache()
cache.set('N3WT_page_size', page_size)
# 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)
# Gestion du cache
page_number = request.GET.get('page', 1)
cache_key = f'N3WT_ficheInscriptions_page_{page_number}_search_{search}'
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)
# Filtrage des résultats
if search:
# Utiliser la nouvelle fonction de recherche
ficheInscriptions_List = bdd.searchObjects(
FicheInscription,
search,
_excludeState=6 # Exclure les fiches archivées
)
else:
# Récupère toutes les fiches non archivées
ficheInscriptions_List = bdd.getObjects(FicheInscription, 'etat', 6, _reverseCondition=True)
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)
# 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)
elif _filter == 'archived' :
page_size = request.GET.get('page_size', None)
if page_size is not None:
try:
page_size = int(page_size)
except ValueError:
page_size = settings.NB_RESULT_PER_PAGE
cached_page_size = cache.get('N3WT_archived_page_size')
# Comparer avec le nouveau page_size
if cached_page_size != page_size:
# Appeler cached_page() et mettre à jour le cache
clear_cache()
cache.set('N3WT_archived_page_size',page_size)
page_number = request.GET.get('page', 1)
cache_key_page = f'N3WT_ficheInscriptions_archives_page_{page_number}'
cached_page = cache.get(cache_key_page)
if cached_page:
return JsonResponse(cached_page, safe=False)
ficheInscriptions_List=bdd.getObjects(FicheInscription, 'etat', 6)
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_page, response_data, timeout=60*15)
return JsonResponse(response_data, safe=False)
return JsonResponse(status=status.HTTP_404_NOT_FOUND)
return JsonResponse({'error' : 'aucune donnée trouvée', 'count' :0}, safe=False)
def post(self, request):
fichesEleve_data=JSONParser().parse(request)
@ -168,39 +140,28 @@ class FicheInscriptionView(APIView):
def put(self, request, id):
ficheEleve_data=JSONParser().parse(request)
admin = ficheEleve_data.pop('admin', 1)
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)
currentState = getStateMachineObjectState(ficheEleve.etat)
if admin == 0 and currentState == FicheInscription.EtatDossierInscription.DI_ENVOYE:
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)
# Ajout du fichier d'inscriptions
data = {
'pdf_title': "Dossier d'inscription de %s"%ficheEleve.eleve.prenom,
'dateSignature': util.convertToStr(util._now(), '%d-%m-%Y'),
'heureSignature': util.convertToStr(util._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)
util.diToPDF(ficheEleve)
# Mise à jour de l'automate
updateStateMachine(di, 'saisiDI')
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():
di = ficheEleve_serializer.save()
return JsonResponse("Updated Successfully", safe=False)
ficheEleve_serializer.save()
return JsonResponse(ficheEleve_serializer.data, safe=False)
return JsonResponse(ficheEleve_serializer.errors, safe=False)
@ -287,3 +248,10 @@ class ListeElevesView(APIView):
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)