general: make it possible to cancel bookings (#9999)
This commit is contained in:
parent
f80afdd268
commit
6bc22b0dfe
|
@ -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,
|
||||
),
|
||||
]
|
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
django>=1.7, <1.8
|
||||
django>=1.8, <1.9
|
||||
gadjo
|
||||
djangorestframework>=3.1
|
||||
django-jsonfield >= 0.9.3
|
||||
|
|
2
setup.py
2
setup.py
|
@ -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',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Reference in New Issue