lingo: add API endpoint to cancel a basket item (#9794)

This commit is contained in:
Frédéric Péters 2016-05-26 13:04:47 +02:00
parent f48cd30fe6
commit 8c6b152dfe
4 changed files with 77 additions and 6 deletions

View File

@ -216,8 +216,9 @@ class BasketItem(models.Model):
self.notification_date = timezone.now()
self.save()
def notify_cancellation(self):
self.notify('cancelled')
def notify_cancellation(self, skip_notification=False):
if not skip_notification:
self.notify('cancelled')
self.cancellation_date = timezone.now()
self.save()

View File

@ -19,7 +19,8 @@ from django.conf.urls import patterns, url, include
from combo.urls_utils import decorated_includes, manager_required
from .views import (RegiesApiView, AddBasketItemApiView, PayView, CallbackView,
ReturnView, ItemDownloadView, ItemView, CancelItemView)
ReturnView, ItemDownloadView, ItemView, CancelItemView,
RemoveBasketItemApiView)
from .manager_views import (RegieListView, RegieCreateView, RegieUpdateView,
RegieDeleteView, TransactionListView, ManagerHomeView)
@ -38,6 +39,8 @@ urlpatterns = patterns('',
url('^api/lingo/regies$', RegiesApiView.as_view(), name='api-regies'),
url('^api/lingo/add-basket-item$', AddBasketItemApiView.as_view(),
name='api-add-basket-item'),
url('^api/lingo/remove-basket-item$', RemoveBasketItemApiView.as_view(),
name='api-remove-basket-item'),
url(r'^lingo/pay$', PayView.as_view(), name='lingo-pay'),
url(r'^lingo/cancel/(?P<pk>\w+)/$', CancelItemView.as_view(), name='lingo-cancel-item'),
url(r'^lingo/callback/(?P<regie_pk>\w+)/$', CallbackView.as_view(), name='lingo-callback'),

View File

@ -135,10 +135,52 @@ class AddBasketItemApiView(View):
item.save()
response = HttpResponse(content_type='application/json')
response.write(json.dumps({'result': 'success', 'id': str(item.id)}))
return response
class RemoveBasketItemApiView(View):
http_method_names = ['post', 'options']
@csrf_exempt
def dispatch(self, *args, **kwargs):
return super(RemoveBasketItemApiView, self).dispatch(*args, **kwargs)
def post(self, request, *args, **kwargs):
key = getattr(settings, 'LINGO_API_SIGN_KEY', '12345')
if not check_query(request.META['QUERY_STRING'], key):
return HttpResponseForbidden()
request_body = json.loads(self.request.body)
if not 'basket_item_id' in request_body:
raise Exception('missing basket_item_id parameter')
try:
if request.GET.get('NameId'):
if UserSAMLIdentifier is None:
raise Exception('missing mellon?')
try:
user = UserSAMLIdentifier.objects.get(name_id=request.GET.get('NameId')).user
except UserSAMLIdentifier.DoesNotExist:
raise Exception('unknown name id')
elif request.GET.get('email'):
user = User.objects.get(email=request.GET.get('email'))
else:
raise Exception('no user specified')
except User.DoesNotExist:
raise Exception('unknown user')
item = BasketItem.objects.get(id=request_body.get('basket_item_id'),
user=user, cancellation_date__isnull=True)
item.notify_cancellation(skip_notification=bool(request_body.get('skip_notification')))
response = HttpResponse(content_type='application/json')
response.write(json.dumps({'result': 'success'}))
return response
class PayView(View):
def post(self, request, *args, **kwargs):
regie_id = request.POST.get('regie')

View File

@ -102,14 +102,14 @@ def test_add_amount_to_basket(regie, user):
url = sign_url(url, settings.LINGO_API_SIGN_KEY)
resp = client.post(url, json.dumps(data), content_type='application/json')
assert resp.status_code == 200
assert json.loads(resp.content) == {'result': 'success'}
assert json.loads(resp.content)['result'] == 'success'
assert BasketItem.objects.filter(amount=amount).exists()
data['extra'] = {'amount': '22.22'}
url = sign_url(url, settings.LINGO_API_SIGN_KEY)
resp = client.post(url, json.dumps(data), content_type='application/json')
assert resp.status_code == 200
assert json.loads(resp.content) == {'result': 'success'}
assert json.loads(resp.content)['result'] == 'success'
assert BasketItem.objects.filter(amount=Decimal('64.22')).exists()
data['amount'] = [amount]
@ -117,9 +117,34 @@ def test_add_amount_to_basket(regie, user):
resp = client.post('%s&amount=5' % url, json.dumps(data),
content_type='application/json')
assert resp.status_code == 200
assert json.loads(resp.content) == {'result': 'success'}
assert json.loads(resp.content)['result'] == 'success'
assert BasketItem.objects.filter(amount=Decimal('81.22')).exists()
def test_cancel_basket_item(regie, user):
user_email = 'foo@example.com'
User.objects.get_or_create(email=user_email)
url = '%s?email=%s' % (reverse('api-add-basket-item'), user_email)
url = sign_url(url, settings.LINGO_API_SIGN_KEY)
data = {'amount': 42, 'display_name': 'test amount', 'url': 'http://example.com'}
resp = client.post(url, json.dumps(data), content_type='application/json')
assert resp.status_code == 200
assert json.loads(resp.content)['result'] == 'success'
assert BasketItem.objects.filter(amount=42, cancellation_date__isnull=True).exists()
basket_item_id = json.loads(resp.content)['id']
data = {'amount': 21, 'display_name': 'test amount', 'url': 'http://example.com'}
resp = client.post(url, json.dumps(data), content_type='application/json')
assert resp.status_code == 200
assert json.loads(resp.content)['result'] == 'success'
assert BasketItem.objects.filter(amount=42, cancellation_date__isnull=True).exists()
assert BasketItem.objects.filter(amount=21, cancellation_date__isnull=True).exists()
url = '%s?email=%s' % (reverse('api-remove-basket-item'), user_email)
url = sign_url(url, settings.LINGO_API_SIGN_KEY)
data = {'basket_item_id': basket_item_id, 'skip_notification': True}
resp = client.post(url, json.dumps(data), content_type='application/json')
assert not BasketItem.objects.filter(amount=42, cancellation_date__isnull=True).exists()
assert BasketItem.objects.filter(amount=21, cancellation_date__isnull=True).exists()
def test_payment_callback(regie, user):
item = BasketItem.objects.create(user=user, regie=regie,