Skip to content
Snippets Groups Projects
Commit 661c4b5d authored by Arno Wunderlich's avatar Arno Wunderlich
Browse files

added api bidding

parent eddea8e4
No related branches found
No related tags found
1 merge request!38Create rest api
Pipeline #15172 passed
......@@ -62,6 +62,7 @@ def create_app(config: Optional[Dict] = None) -> Flask:
# Register blueprints
from . import views
flask_app.register_blueprint(views.bp, url_prefix='')
flask_app.register_blueprint(views.api)
# a simple page that says hello
@flask_app.route('/hello')
......
......@@ -5,17 +5,66 @@ Basic views for Application
import base64
import random
import logging
from typing import Optional
from datetime import datetime, timedelta
from flask import Blueprint, flash, redirect, render_template, request, url_for
from .models import Item, User
from flask import Blueprint, flash, redirect, render_template, request, url_for, jsonify
from .models import Item, User, Bid
from .auth import login_required, current_user
# Main blueprint.
bp = Blueprint('views', __name__)
api = Blueprint('api', __name__, url_prefix='/api')
logger = logging.getLogger(__name__)
# Blueprint for documentation.
docs_bp = Blueprint('docs', __name__)
MIN_BID_INCREMENT = 1
def get_winning_bid(item: Item) -> Optional[Bid]:
"""
Return the (currently) winning bid for the given item.
If there are no bids, or the item is not yet closed, return None.
:param item: The item to get the winning bid for.
:return: The winning bid, or None.
"""
winning_bid = None
try:
winning_bid = Bid.objects(item=item) \
.filter(created_at__lt=item.closes_at) \
.order_by('-amount') \
.first()
except Exception as exc:
logger.warning("Error getting winning bid: %s", exc, exc_info=True, extra={
'item_id': item.id,
})
return winning_bid
def get_item_price(item: Item) -> int:
"""
Return the current price of the given item.
If there are no bids, return the starting bid.
:param item: The item to get the price for.
:return: The current price.
"""
winning_bid = get_winning_bid(item)
if winning_bid:
return winning_bid.amount + MIN_BID_INCREMENT
else:
return item.starting_bid
@bp.route("/")
def index() -> str:
"""
......@@ -137,7 +186,7 @@ def bid(id):
amount = request.form['amount']
if amount < min_amount:
flash(_("Bid must be at least %(min_amount)s", min_amount))
flash(("Bid must be at least %(min_amount)s", min_amount))
return redirect(url_for('views.list_bid'))
if item.closes_at < datetime.utcnow():
......@@ -163,3 +212,96 @@ def bid(id):
return "ok"
@api.route('<id>/bids', methods=('GET',))
@login_required
def api_item_bids(id):
"""
Get the bids for an item.
:param id: The id of the item to get bids for.
:return: A JSON response containing the bids.
"""
item = Item.objects.get_or_404(id=id)
bids = []
for bid in Bid.objects(item=item).order_by('-amount'):
bids.append(bid.to_json())
return jsonify({
'success': True,
'bids': bids
})
@api.route('<id>/bids', methods=('POST',))
@login_required
def api_item_place_bid(id):
"""
Place a bid on an item.
If the bid is valid, create a new bid and return the bid.
Otherwise, return an error message.
Only accepts `REF_CURRENCY` bids.
:param id: The id of the item to bid on.
:return: A JSON response containing the bid.
"""
item = Item.objects.get_or_404(id=id)
min_amount = get_item_price(item)
try:
amount = int(request.form['amount'])
except KeyError:
return jsonify({
'success': False,
'error': ("Missing required argument %(argname)s", argname:='amount')
})
except ValueError:
return jsonify({
'success': False,
'error': ("Invalid value for argument %(argname)s", argname:='amount')
})
except Exception as exc:
return jsonify({
'success': False,
'error': ("Error parsing argument %(argname)s: %(exc)s", argname:='amount', exc:=exc)
})
if amount < min_amount:
return jsonify({
'success': False,
'error': ("Bid must be at least %(min_amount)s", min_amount:=min_amount)
})
if item.closes_at < datetime.utcnow():
return jsonify({
'success': False,
'error': ("This item is no longer on sale.")
})
try:
bid = Bid(
item=item,
bidder=current_user,
amount=amount,
)
bid.save()
except Exception as exc:
logger.error("Error placing bid: %s", exc, exc_info=True, extra={
'item_id': item.id,
'bidder_id': current_user.id,
'amount': amount,
})
return jsonify({
'success': False,
'error': ("Error placing bid: %(exc)s", exc:=exc)
})
print(type(bid))
return jsonify({
'success': True,
'bid': bid.to_json()
})
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment