chrono/chrono/api/serializers.py

203 lines
7.8 KiB
Python

from django.contrib.auth.models import Group
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from chrono.agendas.models import AbsenceReason, Agenda, Booking, Event
class StringOrListField(serializers.ListField):
def to_internal_value(self, data):
if isinstance(data, str):
data = [s.strip() for s in data.split(',') if s.strip()]
return super().to_internal_value(data)
class CommaSeparatedStringField(serializers.ListField):
def get_value(self, dictionary):
return super(serializers.ListField, self).get_value(dictionary)
def to_internal_value(self, data):
data = [s.strip() for s in data.split(',') if s.strip()]
return super().to_internal_value(data)
class SlotSerializer(serializers.Serializer):
label = serializers.CharField(max_length=250, allow_blank=True)
user_external_id = serializers.CharField(max_length=250, allow_blank=True)
user_name = serializers.CharField(max_length=250, allow_blank=True) # compatibility
user_first_name = serializers.CharField(max_length=250, allow_blank=True)
user_last_name = serializers.CharField(max_length=250, allow_blank=True)
user_display_label = serializers.CharField(max_length=250, allow_blank=True)
user_email = serializers.CharField(max_length=250, allow_blank=True)
user_phone_number = serializers.CharField(max_length=16, allow_blank=True)
exclude_user = serializers.BooleanField(default=False)
events = serializers.CharField(max_length=16, allow_blank=True)
form_url = serializers.CharField(max_length=250, allow_blank=True)
backoffice_url = serializers.URLField(allow_blank=True)
cancel_callback_url = serializers.URLField(allow_blank=True)
count = serializers.IntegerField(min_value=1)
cancel_booking_id = serializers.CharField(max_length=250, allow_blank=True, allow_null=True)
force_waiting_list = serializers.BooleanField(default=False)
use_color_for = serializers.CharField(max_length=250, allow_blank=True)
class SlotsSerializer(SlotSerializer):
slots = StringOrListField(required=True, child=serializers.CharField(max_length=160, allow_blank=False))
def validate(self, attrs):
super().validate(attrs)
if not attrs.get('slots'):
raise serializers.ValidationError({'slots': _('This field is required.')})
return attrs
class EventsSlotsSerializer(SlotSerializer):
slots = StringOrListField(required=True, child=serializers.CharField(max_length=160))
def validate(self, attrs):
super().validate(attrs)
if not 'slots' in attrs:
raise serializers.ValidationError({'slots': _('This field is required.')})
if not attrs.get('user_external_id'):
raise serializers.ValidationError({'user_external_id': _('This field is required.')})
return attrs
class BookingSerializer(serializers.ModelSerializer):
user_absence_reason = serializers.CharField(required=False, allow_blank=True, allow_null=True)
class Meta:
model = Booking
fields = ['id', 'in_waiting_list', 'user_was_present', 'user_absence_reason', 'extra_data']
read_only_fields = ['id', 'in_waiting_list']
def validate_user_absence_reason(self, value):
if not value:
return ''
if not self.instance.event.agenda.absence_reasons_group:
raise serializers.ValidationError(_('unknown absence reason'))
reasons_qs = self.instance.event.agenda.absence_reasons_group.absence_reasons
try:
reason = reasons_qs.get(slug=value)
value = reason.label
except AbsenceReason.DoesNotExist:
if not reasons_qs.filter(label=value).exists():
raise serializers.ValidationError(_('unknown absence reason'))
return value
class ResizeSerializer(serializers.Serializer):
count = serializers.IntegerField(min_value=1)
class StatisticsFiltersSerializer(serializers.Serializer):
time_interval = serializers.ChoiceField(choices=('day', _('Day')), default='day')
start = serializers.DateTimeField(required=False, input_formats=['iso-8601', '%Y-%m-%d'])
end = serializers.DateTimeField(required=False, input_formats=['iso-8601', '%Y-%m-%d'])
category = serializers.SlugField(required=False, allow_blank=False, max_length=256)
agenda = serializers.SlugField(required=False, allow_blank=False, max_length=256)
group_by = serializers.SlugField(required=False, allow_blank=False, max_length=256)
class DateRangeSerializer(serializers.Serializer):
datetime_formats = ['%Y-%m-%d', '%Y-%m-%d %H:%M', 'iso-8601']
date_start = serializers.DateTimeField(required=False, input_formats=datetime_formats)
date_end = serializers.DateTimeField(required=False, input_formats=datetime_formats)
class DatetimesSerializer(DateRangeSerializer):
min_places = serializers.IntegerField(min_value=1, default=1)
user_external_id = serializers.CharField(required=False, max_length=250, allow_blank=True)
exclude_user_external_id = serializers.CharField(required=False, max_length=250, allow_blank=True)
events = serializers.CharField(required=False, max_length=32, allow_blank=True)
hide_disabled = serializers.BooleanField(default=False)
def validate(self, attrs):
super().validate(attrs)
if (
'user_external_id' in attrs
and 'exclude_user_external_id' in attrs
and attrs['user_external_id'] != attrs['exclude_user_external_id']
):
raise ValidationError(
{'user_external_id': _('user_external_id and exclude_user_external_id have different values')}
)
return attrs
class MultipleAgendasDatetimesSerializer(DatetimesSerializer):
agendas = CommaSeparatedStringField(
required=True, child=serializers.SlugField(max_length=160, allow_blank=False)
)
show_past_events = serializers.BooleanField(default=False)
class EventSerializer(serializers.ModelSerializer):
recurrence_days = CommaSeparatedStringField(
required=False, child=serializers.IntegerField(min_value=0, max_value=6)
)
class Meta:
model = Event
fields = [
'start_datetime',
'recurrence_days',
'recurrence_week_interval',
'recurrence_end_date',
'duration',
'publication_date',
'places',
'waiting_list_places',
'label',
'description',
'pricing',
'url',
]
class AgendaSerializer(serializers.ModelSerializer):
edit_role = serializers.CharField(required=False, max_length=150)
view_role = serializers.CharField(required=False, max_length=150)
class Meta:
model = Agenda
fields = [
'slug',
'label',
'kind',
'minimal_booking_delay',
'minimal_booking_delay_in_working_days',
'maximal_booking_delay',
'anonymize_delay',
'edit_role',
'view_role',
]
def get_role(self, value):
try:
return Group.objects.get(name=value)
except Group.DoesNotExist:
raise serializers.ValidationError(_('unknown role: %s' % value))
def validate_edit_role(self, value):
return self.get_role(value)
def validate_view_role(self, value):
return self.get_role(value)
def validate(self, attrs):
super().validate(attrs)
if attrs['minimal_booking_delay_in_working_days'] and attrs.get('kind', 'events') != 'events':
raise ValidationError(
{
'minimal_booking_delay_in_working_days': _('Option not available on %s agenda')
% attrs['kind']
}
)
return attrs