Added bulk buying to api2

This commit is contained in:
seba 2011-10-10 23:59:45 +02:00
parent 828a31ec67
commit f6f0a0f114
3 changed files with 111 additions and 8 deletions

View File

@ -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 <buyable.models.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 <buyable.models.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
@ -95,6 +111,76 @@ class BuyableItemHandler(BaseHandler):
return rc.CREATED
def bulkBuy(self, request):
"""Buy a :class:`Buyable <buyable.models.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):
"""Handler for listing all :class:`BuyableType <buyable.models.BuyableType>`.

View File

@ -38,6 +38,7 @@ configRes = CsrfExemptResource(handler=ConfigHandler, **ad)
urlpatterns = patterns('',
url(r'buyable/item/?$', buyableItemRes),
url(r'buyable/item/(?P<itemId>\d+)/?$', buyableItemRes),
url(r'buyable/item/bulkbuy/$', buyableItemRes, {'bulkBuy': True}),
url(r'buyable/types/?$', buyableTypeRes),
url(r'buyable/history/?$', historyRes),

View File

@ -61,7 +61,7 @@ to the handler or the responsible method for more documentation or code.
barcode item with this barcode
========= =======================
:func:`POST <api2.handlers.BuyableItemHandler.create>`
:func:`POST <api2.handlers.BuyableItemHandler.buyItem>`
Buy a :class:`Buyable <buyable.models.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/ <api2.handlers.BuyableItemHandler>`
:func:`POST <api2.handlers.BuyableItemHandler.bulkBuy>`
Buy multiple :class:`Buyables <buyable.models.Buyable>`.
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 <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/ <api2.handlers.BuyableTypeHandler>`
:func:`GET <api2.handlers.BuyableTypeHandler.read>`
List all types which an item can belong to
List all types which an item can belong to.
:class:`history/ <api2.handlers.HistoryHandler>`
:func:`GET <api2.handlers.HistoryHandler.read>`
@ -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/