general: make it possible to cancel bookings (#9999)

This commit is contained in:
Frédéric Péters 2016-03-30 00:51:34 +02:00
parent f80afdd268
commit 6bc22b0dfe
8 changed files with 69 additions and 5 deletions

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('agendas', '0003_booking'),
]
operations = [
migrations.AddField(
model_name='booking',
name='cancellation_datetime',
field=models.DateTimeField(null=True),
preserve_default=True,
),
]

View File

@ -16,7 +16,7 @@
from django.core.urlresolvers import reverse
from django.db import models
from django.db.models import Count
from django.db.models.expressions import RawSQL
from django.utils.text import slugify
from django.utils.translation import ugettext_lazy as _
@ -52,7 +52,10 @@ class Agenda(models.Model):
class EventManager(models.Manager):
def get_queryset(self):
return super(EventManager, self).get_queryset().annotate(
booked_places=Count('booking'))
booked_places=RawSQL('''SELECT count(*)
FROM agendas_booking
WHERE agendas_booking.event_id = agendas_event.id
AND cancellation_datetime IS NULL''', ()))
class Event(models.Model):
@ -69,3 +72,4 @@ class Event(models.Model):
class Booking(models.Model):
event = models.ForeignKey(Event)
extra_data = JSONField(null=True)
cancellation_datetime = models.DateTimeField(null=True)

View File

@ -21,4 +21,5 @@ from . import views
urlpatterns = patterns('',
url(r'agenda/(?P<pk>\w+)/datetimes/', views.datetimes),
url(r'agenda/(?P<agenda_pk>\w+)/fillslot/(?P<event_pk>\w+)/', views.fillslot),
url(r'booking/(?P<booking_pk>\w+)/', views.booking),
)

View File

@ -21,6 +21,7 @@ from django.utils.timezone import localtime, now
from rest_framework import serializers, status
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework.views import APIView
from ..agendas.models import Event, Booking
@ -57,3 +58,18 @@ class Fillslot(GenericAPIView):
return Response(response)
fillslot = Fillslot.as_view()
class BookingAPI(APIView):
def initial(self, request, *args, **kwargs):
super(BookingAPI, self).initial(request, *args, **kwargs)
self.booking = Booking.objects.get(id=kwargs.get('booking_pk'),
cancellation_datetime__isnull=True)
def delete(self, request, *args, **kwargs):
self.booking.cancellation_datetime = now()
self.booking.save()
response = {'err': 0, 'booking_id': self.booking.id}
return Response(response)
booking = BookingAPI.as_view()

View File

@ -1,4 +1,4 @@
django>=1.7, <1.8
django>=1.8, <1.9
gadjo
djangorestframework>=3.1
django-jsonfield >= 0.9.3

View File

@ -102,7 +102,7 @@ setup(
'Programming Language :: Python',
'Programming Language :: Python :: 2',
],
install_requires=['django>=1.7, <1.8',
install_requires=['django>=1.8, <1.9',
'gadjo',
'djangorestframework>=3.1',
'django-jsonfield >= 0.9.3',

View File

@ -1,6 +1,8 @@
import pytest
from chrono.agendas.models import Agenda
from django.utils.timezone import now
from chrono.agendas.models import Agenda, Event, Booking
pytestmark = pytest.mark.django_db
@ -25,3 +27,15 @@ def test_duplicate_slugs():
agenda = Agenda(label=u'Foo baz')
agenda.save()
assert agenda.slug == 'foo-baz-2'
def test_event_manager():
agenda = Agenda(label=u'Foo baz')
agenda.save()
event = Event(start_datetime=now(), places=10, agenda=agenda)
event.save()
booking = Booking(event=event)
booking.save()
assert Event.objects.all()[0].booked_places == 1
booking.cancellation_datetime = now()
booking.save()
assert Event.objects.all()[0].booked_places == 0

View File

@ -66,6 +66,15 @@ def test_booking_api_with_data(app, some_data):
assert Booking.objects.count() == 1
assert Booking.objects.all()[0].extra_data == {'hello': 'world'}
def test_booking_cancellation_api(app, some_data):
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
event = Event.objects.filter(agenda_id=agenda_id)[0]
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event.id))
booking_id = resp.json['booking_id']
assert Booking.objects.count() == 1
resp = app.delete('/api/booking/%s/' % booking_id)
assert Booking.objects.filter(cancellation_datetime__isnull=False).count() == 1
def test_soldout(app, some_data):
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
event = Event.objects.filter(agenda_id=agenda_id).exclude(start_datetime__lt=now())[0]