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.contrib.auth.models import Group
from django.core.exceptions import MultipleObjectsReturned from django.core.exceptions import MultipleObjectsReturned
from decorators import * from decorators import *
from collections import Iterable
from decimal import Decimal, InvalidOperation from decimal import Decimal, InvalidOperation
from helper import * from helper import *
import datetime import datetime
@ -20,7 +21,7 @@ class BuyableItemHandler(BaseHandler):
BUY_ITEM, BUY_DEPOSIT, BUY_ITEM_AND_DEPOSIT = range(3) 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. """Get one or multiple items.
- type: Only get items belonging to this type - 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 Note that neither type nor barcode is used if an item id
is specified. 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) barcode = request.GET.get('barcode', None)
if itemId == None: if itemId == None:
obj = Buyable.objects.all() obj = Buyable.objects.all()
@ -54,15 +61,24 @@ class BuyableItemHandler(BaseHandler):
return error return error
@manglePluginPerms @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. """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) - 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) - amount: amount of items to buy (default 1)
""" """
if not request.content_type:
request.data = request.POST
if not itemId: if not itemId:
return rc.BAD_REQUEST return rc.BAD_REQUEST
item = None item = None
@ -92,7 +108,77 @@ class BuyableItemHandler(BaseHandler):
p.save() p.save()
order.updatePrice(commit=True) order.updatePrice(commit=True)
order.save() order.save()
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 return rc.CREATED
class BuyableTypeHandler(BaseHandler): class BuyableTypeHandler(BaseHandler):

View File

@ -38,6 +38,7 @@ configRes = CsrfExemptResource(handler=ConfigHandler, **ad)
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'buyable/item/?$', buyableItemRes), url(r'buyable/item/?$', buyableItemRes),
url(r'buyable/item/(?P<itemId>\d+)/?$', 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/types/?$', buyableTypeRes),
url(r'buyable/history/?$', historyRes), 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 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) 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) 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>` :class:`types/ <api2.handlers.BuyableTypeHandler>`
:func:`GET <api2.handlers.BuyableTypeHandler.read>` :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>` :class:`history/ <api2.handlers.HistoryHandler>`
:func:`GET <api2.handlers.HistoryHandler.read>` :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. 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 .. code-block:: bash
# find item with barcode # 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 curl --basic http://testplugin:maunz@server/api/buyable/account/balance/?user=frundy
# as plugin, buy item with id 3 10 times # 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 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/