Louis Mazin 5298d69e1f clean
2026-09-21 19:23:30 +02:00

242 lines
6.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from datetime import time as datetime_time
from uuid import uuid4
from django.contrib.auth import get_user_model
from django.db import transaction
from rest_framework import serializers
from users.serializers import UserSerializer
from .models import TimeEntry
User = get_user_model()
class TimeEntrySerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=True)
is_complete = serializers.ReadOnlyField()
is_incomplete = serializers.ReadOnlyField()
class Meta:
model = TimeEntry
fields = [
'id',
'user',
'group_id',
'date',
'start_time',
'end_time',
'created_at',
'updated_at',
'duration',
'day_of_week',
'is_complete',
'is_incomplete',
]
read_only_fields = [
'id',
'user',
'created_at',
'updated_at',
'duration',
'day_of_week',
'is_complete',
'is_incomplete',
]
def create(self, validated_data):
validated_data['user'] = self.context['request'].user
return super().create(validated_data)
def update(self, instance, validated_data):
validated_data.pop('user', None)
return super().update(instance, validated_data)
class TimeEntryCreateSerializer(serializers.ModelSerializer):
user_id = serializers.PrimaryKeyRelatedField(
source='user',
queryset=User.objects.all(),
write_only=True,
required=False,
)
end_date = serializers.DateField(
write_only=True,
required=False,
)
class Meta:
model = TimeEntry
fields = [
'user_id',
'date',
'end_date',
'start_time',
'end_time',
]
def validate(self, attrs):
start_time = attrs.get('start_time')
end_time = attrs.get('end_time')
date = attrs.get('date')
end_date = attrs.get('end_date') or date
if not start_time and not end_time:
raise serializers.ValidationError(
'Une heure d’entrée ou de sortie est requise.'
)
if end_date < date:
raise serializers.ValidationError(
'La date de sortie doit être postérieure ou égale à la date d’entrée.'
)
# Une entrée et une sortie le même jour doivent être cohérentes.
if (
date == end_date
and start_time
and end_time
and end_time <= start_time
):
raise serializers.ValidationError(
'L’heure de sortie doit être après l’entrée.'
)
# Pour un pointage sur plusieurs jours, les deux extrémités
# doivent être connues.
if (
date != end_date
and (
not start_time
or not end_time
)
):
raise serializers.ValidationError(
'Un pointage sur plusieurs jours nécessite une heure d’entrée et une heure de sortie.'
)
attrs['end_date'] = end_date
return attrs
def create(self, validated_data):
user = validated_data.pop('user', None)
end_date = validated_data.pop('end_date')
if user is None:
user = self.context['request'].user
start_date = validated_data['date']
start_time = validated_data.get('start_time')
end_time = validated_data.get('end_time')
# Pointage classique sur une seule journée.
if start_date == end_date:
return TimeEntry.objects.create(
user=user,
date=start_date,
start_time=start_time,
end_time=end_time,
)
# Pointage multi-jours :
#
# Exemple :
# 20/09 14:00 -> 22/09 10:00
#
# 20/09 14:00 -> 23:59:59
# 21/09 00:00 -> 23:59:59
# 22/09 00:00 -> 10:00
group_id = uuid4()
created_entries = []
current_date = start_date
with transaction.atomic():
while current_date <= end_date:
if current_date == start_date:
entry_start = start_time
entry_end = datetime_time(
23,
59,
59,
)
elif current_date == end_date:
entry_start = datetime_time.min
entry_end = end_time
else:
entry_start = datetime_time.min
entry_end = datetime_time(
23,
59,
59,
)
created_entries.append(
TimeEntry.objects.create(
user=user,
group_id=group_id,
date=current_date,
start_time=entry_start,
end_time=entry_end,
)
)
from datetime import timedelta
current_date += timedelta(days=1)
return created_entries[0]
class TimeEntryUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = TimeEntry
fields = [
'start_time',
'end_time',
]
def validate(self, attrs):
start_time = attrs.get(
'start_time',
self.instance.start_time,
)
end_time = attrs.get(
'end_time',
self.instance.end_time,
)
if not start_time and not end_time:
raise serializers.ValidationError(
'Une heure d’entrée ou de sortie est requise.'
)
if (
start_time
and end_time
and end_time <= start_time
):
raise serializers.ValidationError(
'L’heure de sortie doit être après l’entrée.'
)
return attrs
class WeeklySummarySerializer(serializers.Serializer):
user = serializers.CharField()
username = serializers.CharField()
total_hours = serializers.FloatField()
entries = serializers.ListField(
child=serializers.DictField(),
)