api: add post method on agenda endpoint (#57103)

This commit is contained in:
Nicolas Roche 2021-09-27 17:26:40 +02:00
parent b9e6c9c55c
commit 25b5222dd4
3 changed files with 172 additions and 2 deletions

View File

@ -1,8 +1,9 @@
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, Booking, Event
from chrono.agendas.models import AbsenceReason, Agenda, Booking, Event
class StringOrListField(serializers.ListField):
@ -157,3 +158,45 @@ class EventSerializer(serializers.ModelSerializer):
'pricing',
'url',
]
class AgendaSerializer(serializers.ModelSerializer):
edit_role = serializers.CharField(required=False)
view_role = serializers.CharField(required=False)
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

View File

@ -690,7 +690,12 @@ def make_booking(event, payload, extra_data, primary_booking=None, in_waiting_li
class Agendas(APIView):
permission_classes = ()
serializer_class = serializers.AgendaSerializer
def get_permissions(self):
if self.request.method == 'GET':
return []
return [permissions.IsAuthenticated()]
def get(self, request, format=None):
agendas_queryset = (
@ -728,6 +733,18 @@ class Agendas(APIView):
return Response({'err': 0, 'data': agendas})
def post(self, request, format=None):
serializer = self.serializer_class(data=request.data)
if not serializer.is_valid():
raise APIError(
_('invalid payload'),
err_class='invalid payload',
errors=serializer.errors,
http_status=status.HTTP_400_BAD_REQUEST,
)
agenda = serializer.save()
return Response({'err': 0, 'data': [get_agenda_detail(request, agenda)]})
agendas = Agendas.as_view()

View File

@ -592,3 +592,113 @@ def test_virtual_agendas_meetingtypes_api(app):
},
]
}
@pytest.mark.freeze_time('2021-07-09')
def test_add_agenda(app, user, settings):
api_url = '/api/agenda/'
# no authentication
resp = app.post(api_url, status=401)
assert resp.json['detail'] == 'Authentication credentials were not provided.'
# wrong password
app.authorization = ('Basic', ('john.doe', 'wrong'))
resp = app.post(api_url, status=401)
assert resp.json['detail'] == 'Invalid username/password.'
app.authorization = ('Basic', ('john.doe', 'password'))
# missing fields
resp = app.post(api_url, status=400)
assert resp.json['err']
assert resp.json['errors'] == {'label': ['This field is required.'], 'slug': ['This field is required.']}
# wrong contents
params = {
'label': 'foo',
'slug': 'foo',
'kind': 'oups',
'minimal_booking_delay': 'oups',
'minimal_booking_delay_in_working_days': 'oups',
'anonymize_delay': 'oups',
'edit_role': 'oups',
'view_role': 'plop',
}
resp = app.post(api_url, params=params, status=400)
assert resp.json['err']
assert resp.json['errors'] == {
'kind': ['"oups" is not a valid choice.'],
'minimal_booking_delay': ['A valid integer is required.'],
'minimal_booking_delay_in_working_days': ['Must be a valid boolean.'],
'anonymize_delay': ['A valid integer is required.'],
'edit_role': ['unknown role: oups'],
'view_role': ['unknown role: plop'],
}
# slug already used
meeting_agenda = Agenda(label='Foo bar Meeting', kind='meetings')
meeting_agenda.save()
params = {
'label': 'foo',
'slug': meeting_agenda.slug,
}
resp = app.post(api_url, params=params, status=400)
assert resp.json['err']
assert resp.json['errors'] == {'slug': ['agenda with this Identifier already exists.']}
# option only available on events agenda
params = {
'label': 'foo',
'slug': 'foo',
'kind': 'meetings',
'minimal_booking_delay_in_working_days': True,
}
resp = app.post(api_url, params=params, status=400)
assert resp.json['err']
assert resp.json['errors'] == {
'minimal_booking_delay_in_working_days': ['Option not available on meetings agenda']
}
settings.WORKING_DAY_CALENDAR = 'workalendar.europe.France'
edit_group = Group.objects.create(name='Edit')
view_group = Group.objects.create(name='View')
# add a meetings agenda
params = {
'label': 'foo Meetings',
'slug': 'foo-meetings',
'kind': 'meetings',
'minimal_booking_delay': 1,
'maximal_booking_delay': 3,
'anonymize_delay': 30,
'edit_role': 'Edit',
'view_role': 'View',
}
resp = app.post(api_url, params=params)
assert not resp.json['err']
assert len(resp.json['data']) == 1
agenda = Agenda.objects.get(slug='foo-meetings')
assert agenda.min_booking_datetime.date() == datetime.date(2021, 7, 10)
assert agenda.edit_role == edit_group
assert agenda.view_role == view_group
# add an events agenda
params = {
'label': 'foo Events',
'slug': 'foo-events',
'kind': 'events',
'minimal_booking_delay': 1,
'minimal_booking_delay_in_working_days': True,
'maximal_booking_delay': 3,
'anonymize_delay': 30,
'edit_role': 'Edit',
'view_role': 'View',
}
resp = app.post(api_url, params=params)
assert not resp.json['err']
assert len(resp.json['data']) == 1
agenda = Agenda.objects.get(slug='foo-events')
assert agenda.edit_role == edit_group
assert agenda.view_role == view_group
assert agenda.min_booking_datetime.date() == datetime.date(2021, 7, 12)