feat: Harmonisation des fees / ajout de type de réduction / mise à jour

du calcul [#18]
This commit is contained in:
N3WT DE COMPET
2025-01-21 20:39:36 +01:00
parent 8d1a41e269
commit 5462306a60
11 changed files with 169 additions and 194 deletions

View File

@ -73,40 +73,33 @@ class PaymentOptions(models.IntegerChoices):
FOUR_TIME_PAYMENT = 1, _('Paiement en 4 fois')
TEN_TIME_PAYMENT = 2, _('Paiement en 10 fois')
class DiscountType(models.IntegerChoices):
CURRENCY = 0, 'Currency'
PERCENT = 1, 'Percent'
class FeeType(models.IntegerChoices):
REGISTRATION_FEE = 0, 'Registration Fee'
TUITION_FEE = 1, 'Tuition Fee'
class Discount(models.Model):
name = models.CharField(max_length=255, unique=True)
amount = models.DecimalField(max_digits=10, decimal_places=2)
amount = models.DecimalField(max_digits=10, decimal_places=2, default=0)
description = models.TextField(blank=True)
discount_type = models.IntegerField(choices=DiscountType.choices, default=DiscountType.CURRENCY)
def __str__(self):
return self.name
class Fee(models.Model):
name = models.CharField(max_length=255, unique=True)
description = models.TextField(blank=True)
base_amount = models.DecimalField(max_digits=10, decimal_places=2, default=0)
currency = models.CharField(max_length=3, default='EUR')
description = models.TextField(blank=True)
payment_option = models.IntegerField(choices=PaymentOptions.choices, default=PaymentOptions.SINGLE_PAYMENT)
discounts = models.ManyToManyField('Discount', blank=True)
payment_option = models.IntegerField(choices=PaymentOptions, default=PaymentOptions.SINGLE_PAYMENT)
is_active = models.BooleanField(default=True)
updated_at = models.DateTimeField(auto_now=True)
currency = models.CharField(max_length=3, default='EUR')
type = models.IntegerField(choices=FeeType.choices, default=FeeType.REGISTRATION_FEE)
def __str__(self):
return self.name
class TuitionFee(models.Model):
name = models.CharField(max_length=255, unique=True)
description = models.TextField(blank=True)
base_amount = models.DecimalField(max_digits=10, decimal_places=2, default=0)
currency = models.CharField(max_length=3, default='EUR')
discounts = models.ManyToManyField('Discount', blank=True)
payment_option = models.IntegerField(choices=PaymentOptions, default=PaymentOptions.SINGLE_PAYMENT)
is_active = models.BooleanField(default=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
def clean(self):
if self.validity_end_date <= self.validity_start_date:
raise ValidationError(_('La date de fin de validité doit être après la date de début de validité.'))

View File

@ -1,5 +1,5 @@
from rest_framework import serializers
from .models import Teacher, Speciality, SchoolClass, Planning, LEVEL_CHOICES, Discount, TuitionFee, Fee
from .models import Teacher, Speciality, SchoolClass, Planning, LEVEL_CHOICES, Discount, Fee
from Subscriptions.models import RegistrationForm
from Subscriptions.serializers import StudentSerializer
from Auth.serializers import ProfileSerializer
@ -208,42 +208,7 @@ class FeeSerializer(serializers.ModelSerializer):
instance.payment_option = validated_data.get('payment_option', instance.payment_option)
instance.is_active = validated_data.get('is_active', instance.is_active)
instance.updated_at = validated_data.get('updated_at', instance.updated_at)
instance.save()
# Update discounts if provided
instance.discounts.set(discounts_data)
return instance
class TuitionFeeSerializer(serializers.ModelSerializer):
discounts = serializers.PrimaryKeyRelatedField(queryset=Discount.objects.all(), many=True)
class Meta:
model = TuitionFee
fields = '__all__'
def create(self, validated_data):
discounts_data = validated_data.pop('discounts', [])
# Create the TuitionFee instance
tuition_fee = TuitionFee.objects.create(**validated_data)
# Add discounts if provided
tuition_fee.discounts.set(discounts_data)
return tuition_fee
def update(self, instance, validated_data):
discounts_data = validated_data.pop('discounts', [])
# Update the TuitionFee instance
instance.name = validated_data.get('name', instance.name)
instance.description = validated_data.get('description', instance.description)
instance.base_amount = validated_data.get('base_amount', instance.base_amount)
instance.currency = validated_data.get('currency', instance.currency)
instance.payment_option = validated_data.get('payment_option', instance.payment_option)
instance.is_active = validated_data.get('is_active', instance.is_active)
instance.updated_at = validated_data.get('updated_at', instance.updated_at)
instance.type = validated_data.get('type', instance.type)
instance.save()
# Update discounts if provided

View File

@ -11,8 +11,6 @@ from School.views import (
PlanningView,
FeesView,
FeeView,
TuitionFeesView,
TuitionFeeView,
DiscountsView,
DiscountView,
)
@ -33,15 +31,11 @@ urlpatterns = [
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"),
re_path(r'^fees$', FeesView.as_view(), name="fees"),
re_path(r'^fees/(?P<_filter>[a-zA-z]+)$', FeesView.as_view(), name="fees"),
re_path(r'^fee$', FeeView.as_view(), name="fee"),
re_path(r'^fee/([0-9]+)$', FeeView.as_view(), name="fee"),
re_path(r'^tuitionFees$', TuitionFeesView.as_view(), name="tuitionFees"),
re_path(r'^tuitionFee$', TuitionFeeView.as_view(), name="tuitionFee"),
re_path(r'^tuitionFee/([0-9]+)$', TuitionFeeView.as_view(), name="tuitionFee"),
re_path(r'^discounts$', DiscountsView.as_view(), name="discounts"),
re_path(r'^discount$', DiscountView.as_view(), name="discount"),
re_path(r'^discount/([0-9]+)$', DiscountView.as_view(), name="discount"),

View File

@ -5,8 +5,8 @@ from rest_framework.parsers import JSONParser
from rest_framework.views import APIView
from django.core.cache import cache
from django.core.exceptions import ObjectDoesNotExist
from .models import Teacher, Speciality, SchoolClass, Planning, Discount, TuitionFee, Fee
from .serializers import TeacherSerializer, SpecialitySerializer, SchoolClassSerializer, PlanningSerializer, DiscountSerializer, TuitionFeeSerializer, FeeSerializer
from .models import Teacher, Speciality, SchoolClass, Planning, Discount, Fee
from .serializers import TeacherSerializer, SpecialitySerializer, SchoolClassSerializer, PlanningSerializer, DiscountSerializer, FeeSerializer
from N3wtSchool import bdd
from N3wtSchool.bdd import delete_object, getAllObjects, getObject
@ -267,18 +267,16 @@ class PlanningView(APIView):
@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class FeesView(APIView):
def get(self, request):
feesList = Fee.objects.all()
fees_serializer = FeeSerializer(feesList, many=True)
return JsonResponse(fees_serializer.data, safe=False)
def get(self, request, _filter, *args, **kwargs):
def post(self, request):
fee_data = JSONParser().parse(request)
fee_serializer = FeeSerializer(data=fee_data)
if fee_serializer.is_valid():
fee_serializer.save()
return JsonResponse(fee_serializer.data, safe=False, status=201)
return JsonResponse(fee_serializer.errors, safe=False, status=400)
if _filter not in ['registration', 'tuition']:
return JsonResponse({"error": "Invalid type parameter. Must be 'registration' or 'tuition'."}, safe=False, status=400)
fee_type_value = 0 if _filter == 'registration' else 1
fees = Fee.objects.filter(type=fee_type_value)
fee_serializer = FeeSerializer(fees, many=True)
return JsonResponse(fee_serializer.data, safe=False, status=200)
@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
@ -312,47 +310,4 @@ class FeeView(APIView):
return JsonResponse(fee_serializer.errors, safe=False, status=400)
def delete(self, request, _id):
return delete_object(Fee, _id)
# Vues pour les frais de scolarité (TuitionFee)
@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class TuitionFeesView(APIView):
def get(self, request):
tuitionFeesList = TuitionFee.objects.all()
tuitionFees_serializer = TuitionFeeSerializer(tuitionFeesList, many=True)
return JsonResponse(tuitionFees_serializer.data, safe=False)
@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class TuitionFeeView(APIView):
def get(self, request, _id):
try:
tuitionFee = TuitionFee.objects.get(id=_id)
tuitionFee_serializer = TuitionFeeSerializer(tuitionFee)
return JsonResponse(tuitionFee_serializer.data, safe=False)
except TuitionFee.DoesNotExist:
return JsonResponse({'error': 'No object found'}, status=404)
def post(self, request):
tuitionFee_data = JSONParser().parse(request)
tuitionFee_serializer = TuitionFeeSerializer(data=tuitionFee_data)
if tuitionFee_serializer.is_valid():
tuitionFee_serializer.save()
return JsonResponse(tuitionFee_serializer.data, safe=False, status=201)
return JsonResponse(tuitionFee_serializer.errors, safe=False, status=400)
def put(self, request, _id):
tuitionFee_data = JSONParser().parse(request)
try:
tuitionFee = TuitionFee.objects.get(id=_id)
except TuitionFee.DoesNotExist:
return JsonResponse({'error': 'No object found'}, status=404)
tuitionFee_serializer = TuitionFeeSerializer(tuitionFee, data=tuitionFee_data, partial=True) # Utilisation de partial=True
if tuitionFee_serializer.is_valid():
tuitionFee_serializer.save()
return JsonResponse(tuitionFee_serializer.data, safe=False)
return JsonResponse(tuitionFee_serializer.errors, safe=False, status=400)
def delete(self, request, _id):
return delete_object(TuitionFee, _id)
return delete_object(Fee, _id)