Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • startuplab/courses/tjts5901-continuous-software-engineering/TJTS5901-K23_template
  • planet-of-the-apes/tjts-5901-apeuction
  • uunot-yliopiston-leivissa/tjts-5901-uunot
  • contain-the-cry/tjts-5901-auction-system
  • avengers/avengers
  • cse6/cse-6
  • 13th/13-sins-of-gitlab
  • fast-and-furious/fast-and-furious
  • back-to-the-future/delorean-auction
  • monty-pythons-the-meaning-of-life/the-meaning-of-life
  • team-atlantis/the-empire
  • code-with-the-wind/auction-project
  • the-pirates/the-pirates
  • do-the-right-thing/do-the-right-thing
  • inception/inception
  • the-social-network-syndicate/the-social-auction-network
  • team-the-hunt-for-red-october/tjts-5901-k-23-red-october
  • good-on-paper/good-paper-project
  • desperados/desperados
19 results
Show changes
Commits on Source (18)
......@@ -6,6 +6,7 @@ flask==2.2.2
python-dotenv
flask-login
flask_babel
datetime
flask-mongoengine==1.0
Pillow
......
......@@ -221,6 +221,8 @@ def profile(email):
for item in items:
item.current_price = get_item_price(item)
item.created_at = item.created_at.strftime("%Y-%m-%d %H:%M:%S")
item.closes_at = item.closes_at.strftime("%Y-%m-%d %H:%M:%S")
item.image_base64 = base64.b64encode(item.image.read()).decode('utf-8')
return render_template('auth/profile.html', user=user, items=items)
......
......@@ -58,6 +58,8 @@ class Item(db.Document):
meta = {"indexes": [
{"fields": [
"closes_at",
"closed_processed",
"seller_informed_about_result"
]}
]}
......@@ -73,6 +75,14 @@ class Item(db.Document):
closes_at = DateTimeField()
closed_processed = BooleanField(required=True, default=False)
"Flag indicating if closing of auction was already processed"
seller_informed_about_result = BooleanField(required=True, default=False)
"Flag indicating if seller has already been informed about the result of the auction"
image = FileField()
def save(self, *args, **kwargs):
......@@ -104,6 +114,9 @@ class Bid(db.Document):
"amount",
"item",
"created_at",
"auction_end_processed",
"winning_bid",
"bidder_informed"
]}
]}
......@@ -119,6 +132,15 @@ class Bid(db.Document):
created_at = DateTimeField(required=True, default=datetime.utcnow)
"Date and time that the bid was placed."
auction_end_processed = BooleanField(required=True, default=False)
"Flag indicating, that closed auction has been processes"
winning_bid = BooleanField(required=True, default=False)
"Flag indicating, whether the bid was the winning bid of the auction"
bidder_informed = BooleanField(required=True, default=False)
"Flag indicating, whether the bidder has been informed about the result of the auction"
class AccessToken(db.Document):
......
......@@ -26,6 +26,10 @@
<label for="sPrice" class="form-label">Starting price</label>
<input type="number" class="form-control" id="sPrice" name="sPrice" min="0" max="100000000">
</div>
<div class="mb-3">
<label for="closing" class="form-label">Duration of auction in hours and minutes</label>
<input type="time" id="duration" name="duration" step="60">
</div>
<div class="mb-3">
<label for="image" class="form-label">Image (Please add image in .jpg format)</label>
<input type="file" class="form-control" id="image" name="image">
......
......@@ -41,6 +41,8 @@
<p class="card-text">{{ auction.description }}</p>
<p class="card-text">Starting Bid: {{ auction.starting_bid }} €</p>
<p class="card-text">Current Price: {{ auction.current_price }} €</p>
<p class="card-text">Starting Time: {{ auction.created_at }} </p>
<p class="card-text">Closing Time: {{ auction.closes_at }} </p>
</div>
<div class="card-footer">
</div>
......
......@@ -36,7 +36,7 @@
<ul class="navbar-nav">
{% if current_user.is_authenticated %}
<li class="nav-item"><span>{{current_user['email'] }}</span></li>
<li class="nav-item"><a href="{{ url_for('auth.profile', email='me') }}" class="nav-link">My pro</a></li>
<li class="nav-item"><a href="{{ url_for('auth.profile', email='me') }}" class="nav-link">My Profile</a></li>
<li class="nav-item"><a href="{{ url_for('auth.logout') }}" class="nav-link">Log Out</a></li>
{% else %}
<li class="nav-item"><a href="{{ url_for('auth.register') }}" class="nav-link">Register</a>
......
......@@ -7,8 +7,9 @@ import base64
import logging
from typing import Optional
from datetime import datetime, timedelta
from mongoengine.queryset.visitor import Q
from flask import Blueprint, flash, redirect, render_template, request, url_for, jsonify
from .models import Item, User, Bid
from .models import Item, Bid
from .auth import login_required, current_user
# Main blueprint.
......@@ -62,6 +63,66 @@ def get_item_price(item: Item) -> int:
return winning_bid.amount
else:
return item.starting_bid
def check_auction_ends():
"""
Check if all previously not processed auctions have ended now
Get all closed items, check if they belong to the current user and inform about
the ending of the auction.
Then process all bids on these items and check if they won
"""
items = Item.objects.filter(Q(closes_at=datetime.utcnow()) & Q(closed_processed=False)) \
.order_by('-closes_at')
for item in items:
item.update(closed_processed = True)
message = None
if item.seller == current_user:
message = "The auction of your item \'{}\' has ended. ".format(item.title)
item.update(seller_informed_about_result = True)
# Get (potential) bids for the item and process them
bids = Bid.objects(item=item).order_by('-amount')
if len(bids) >= 1:
# Set winning_bid = True for winning bid
bids[0].update(winning_bid = True)
bids[0].update(auction_end_processed = True)
# Set winning_bid = False for all other bids
for bid in bids[1:]:
bid.update(winning_bid = False)
bid.update(auction_end_processed = True)
# Inform seller if this is current user
if item.seller == current_user:
message += "Congrats! It was sold for {}.".format(bids[0].amount)
# Inform current user if no one bid on the item
else:
if item.seller == current_user:
message += "No one bid on your item. Try again!"
#Display message if not None
if message is not None:
flash((message))
def check_bids_ended():
"""
Method for checking all bids of current user, marked as auction_end_processed
and inform bidder if neccessary
"""
bids = Bid.objects.filter(Q(bidder=current_user) & Q(auction_end_processed=True) & Q(bidder_informed=False))
if len(bids) >= 1:
for bid in bids:
if bid.winning_bid == True:
flash(("Congrats! You won the auction of '{}' with your bid over {}.".format(bid.item.title, bid.amount)))
else:
flash(("Pity! You were not successfull with the auction of '{}' with your bid over {}.".format(bid.item.title, bid.amount)))
bid.update(bidder_informed = True)
@bp.route("/test")
......@@ -81,6 +142,7 @@ def test_item_adding():
item.starting_bid = 100
item.seller = current_user
item.image = image
item.closes_at = datetime.utcnow() + timedelta(days=1)
item.save()
......@@ -98,11 +160,16 @@ def add_item():
description = request.form.get('description')
starting_price = int(request.form.get('sPrice'))
image = request.files['image']
duration = request.form.get('duration')
error = None
if not nItem:
error = 'Item name is required.'
if not starting_price or starting_price < 1:
error = 'Starting price must be greater than 0.'
if not duration:
error = 'Duration is required.'
print(duration, type(duration))
if error is None:
try:
......@@ -111,7 +178,7 @@ def add_item():
description=description,
starting_bid=starting_price,
seller=current_user,
closes_at=datetime.utcnow() + timedelta(days=1),
closes_at=datetime.utcnow() + timedelta(hours=int(duration[:2]), minutes=int(duration[-2:])),
image=image
)
......@@ -134,15 +201,18 @@ def add_item():
@login_required
def list_bid():
"""
page that lists all items currently on auction
page that lists all items currently on auction and checks for notification
"""
check_auction_ends()
check_bids_ended()
# only on sale items are shown
items = Item.objects.filter(closes_at__gt=datetime.utcnow()) \
.order_by('-closes_at')
for item in items:
item.image_base64 = base64.b64encode(item.image.read()).decode('utf-8')
item.created_at = item.created_at.strftime("%Y-%m-%d %H:%M:%S")
item.current_price = get_item_price(item)
html = render_template("listBid.html", items=items)
......@@ -305,10 +375,7 @@ def page_bid(id):
min_bid = current_price + MIN_BID_INCREMENT
item.image_base64 = base64.b64encode(item.image.read()).decode('utf-8')
# Dark pattern to show enticing message to user
#if item.closes_at < datetime.utcnow() + timedelta(hours=1):
# flash("This item is closing soon! Act now! Now! Now!")
item.created_at = item.created_at.strftime("%Y-%m-%d %H:%M:%S")
return render_template('view.html', item=item, current_price=current_price, min_bid=min_bid)