diff --git a/k4ever/api2/handlers.py b/k4ever/api2/handlers.py index d878973..9da7625 100644 --- a/k4ever/api2/handlers.py +++ b/k4ever/api2/handlers.py @@ -6,6 +6,7 @@ from django.contrib.auth.decorators import user_passes_test from django.contrib.auth.models import Group from django.core.exceptions import MultipleObjectsReturned from decorators import * +from collections import Iterable from decimal import Decimal, InvalidOperation from helper import * import datetime @@ -20,7 +21,7 @@ class BuyableItemHandler(BaseHandler): BUY_ITEM, BUY_DEPOSIT, BUY_ITEM_AND_DEPOSIT = range(3) - def read(self, request, itemId=None): + def read(self, request, itemId=None, bulkBuy=False): """Get one or multiple items. - type: Only get items belonging to this type @@ -29,6 +30,12 @@ class BuyableItemHandler(BaseHandler): Note that neither type nor barcode is used if an item id is specified. """ + + if bulkBuy: + ret = rc.NOT_IMPLEMENTED + ret.write("\nBulk buying does not support GET\n") + return ret + barcode = request.GET.get('barcode', None) if itemId == None: obj = Buyable.objects.all() @@ -54,15 +61,24 @@ class BuyableItemHandler(BaseHandler): return error @manglePluginPerms - def create(self, request, itemId=None): + def create(self, request, itemId=None, bulkBuy=False): + """Buy one or multiple :class:`Buyable ` items. + """ + + if not request.content_type: + request.data = request.POST + + if bulkBuy: + return self.bulkBuy(request) + else: + return self.buyItem(request, itemId) + + def buyItem(self, request, itemId): """Buy a :class:`Buyable ` item. - deposit: Set to 0 for no deposit, 1 for item+deposit and 2 for deposit only (default 0) - amount: amount of items to buy (default 1) """ - - if not request.content_type: - request.data = request.POST if not itemId: return rc.BAD_REQUEST item = None @@ -92,7 +108,77 @@ class BuyableItemHandler(BaseHandler): p.save() order.updatePrice(commit=True) order.save() - + + return rc.CREATED + + def bulkBuy(self, request): + """Buy a :class:`Buyable ` item. + + To buy multiple items, the body of the POST-request has to + be either JSON or YAML. + - items: List of items to buy. + - deposits: List of items to buy deposit for. + """ + if not request.content_type: + ret = rc.BAD_REQUEST + ret.write("\nThe content-type of the request must not be empty/urlencoded\n") + return ret + + if not request.data.has_key("items") and not request.data.has_key("deposits"): + ret = rc.BAD_REQUEST + ret.write("\nYou need to specify either items or deposits (or both).\n") + return ret + + itemList = [] + try: + if request.data.has_key('items'): + if not isinstance(request.data['items'], Iterable): + raise TypeError() + itemList += request.data['items'] + if request.data.has_key('deposits'): + if request.data.has_key('items'): + if not isinstance(request.data['deposits'], Iterable): + raise TypeError() + itemList += request.data['deposits'] + except TypeError: + ret = rc.BAD_REQUEST + ret.write("\nThe items/deposists parameter have to be a list.\n") + return ret + + ids = {} + for item in itemList: + if not ids.has_key(item): + try: + ids[item] = Buyable.objects.get(id=item) + except Buyable.DoesNotExist: + ret = rc.NOT_FOUND + ret.write("\nThe item with the id '%s' could not be found\n" % (item,)) + return ret + except ValueError: + ret = rc.NOT_FOUND + ret.write("\nItem ids should be numeric (and preferably integers)\n") + return ret + if item in request.data['deposits'] and not ids[item].hasDeposit(): + ret = rc.BAD_REQUEST + ret.write("\nItem '%s' cant be bought with deposit\n" % (item,)) + return ret + + order = Order() + order.create(request.user) + order.save() + purchases = [] + if request.data.has_key('items'): + for item in request.data['items']: + p = Purchase.create(order, ids[item], isDeposit=False) + p.save() + if request.data.has_key('deposits'): + for item in request.data['deposits']: + p = Purchase.create(order, ids[item], isDeposit=True) + p.save() + + order.updatePrice(commit=True) + order.save() + return rc.CREATED class BuyableTypeHandler(BaseHandler): diff --git a/k4ever/api2/urls.py b/k4ever/api2/urls.py index 552a004..600d69e 100644 --- a/k4ever/api2/urls.py +++ b/k4ever/api2/urls.py @@ -38,6 +38,7 @@ configRes = CsrfExemptResource(handler=ConfigHandler, **ad) urlpatterns = patterns('', url(r'buyable/item/?$', buyableItemRes), url(r'buyable/item/(?P\d+)/?$', buyableItemRes), + url(r'buyable/item/bulkbuy/$', buyableItemRes, {'bulkBuy': True}), url(r'buyable/types/?$', buyableTypeRes), url(r'buyable/history/?$', historyRes), diff --git a/k4ever/docs/django/api.rst b/k4ever/docs/django/api.rst index d4d0a71..6bda061 100644 --- a/k4ever/docs/django/api.rst +++ b/k4ever/docs/django/api.rst @@ -61,7 +61,7 @@ to the handler or the responsible method for more documentation or code. barcode item with this barcode ========= ======================= - :func:`POST ` + :func:`POST ` Buy a :class:`Buyable ` (requires an ItemId) ========= ======================================================= @@ -71,9 +71,22 @@ to the handler or the responsible method for more documentation or code. amount amount of items to buy (default 1) ========= ======================================================= + :class:`item/bulkbuy/ ` + :func:`POST ` + Buy multiple :class:`Buyables `. + To buy multiple items, the body of this ``POST``-request has to + be either JSON or YAML. In case of doubt, see the :ref:`curl examples ` below. + + ========= ======================================================= + Parameter Description + ========= ======================================================= + items A list of ids for items to buy. + deposits A list of ids for items to buy as deposit. + ========= ======================================================= + :class:`types/ ` :func:`GET ` - List all types which an item can belong to + List all types which an item can belong to. :class:`history/ ` :func:`GET ` @@ -185,6 +198,7 @@ CURL """" As one might see, ``curl`` is quite nice for accessing the API. ``curl`` also supports the ``HTTP``, ``PUT`` and ``DELETE`` methods. +.. _curl-examples: .. code-block:: bash # find item with barcode @@ -195,4 +209,6 @@ As one might see, ``curl`` is quite nice for accessing the API. ``curl`` also su curl --basic http://testplugin:maunz@server/api/buyable/account/balance/?user=frundy # as plugin, buy item with id 3 10 times curl --basic -X POST --data "amount=10" http://testplugin:maunz@server/api/buyable/item/3/?user=frundy + # buy multiple items by sending JSON-data + curl --basic -X POST -H "Content-Type: application/json" --data '{"items": [1,2,4], "deposits": [1, 3]}' http://frundy:foobar@server/api/buyable/item/bulkbuy/