add and run black formatter

This commit is contained in:
mcbloch 2019-09-05 03:33:29 +02:00
parent f59ec75bea
commit d591f846d8
No known key found for this signature in database
GPG key ID: CE32A7D95B7D6418
29 changed files with 557 additions and 440 deletions

View file

@ -14,23 +14,23 @@ class ModelBaseView(ModelView):
class UserAdminModel(ModelBaseView): class UserAdminModel(ModelBaseView):
column_searchable_list = ('username', ) column_searchable_list = ("username",)
inline_models = None inline_models = None
class ProductAdminModel(ModelBaseView): class ProductAdminModel(ModelBaseView):
column_searchable_list = ('name', ) column_searchable_list = ("name",)
inline_models = None inline_models = None
class LocationAdminModel(ModelBaseView): class LocationAdminModel(ModelBaseView):
column_searchable_list = ('name', 'address', 'website') column_searchable_list = ("name", "address", "website")
inline_models = None inline_models = None
form_columns = ('name', 'address', 'website', 'telephone') form_columns = ("name", "address", "website", "telephone")
def init_admin(app, db): def init_admin(app, db):
admin = Admin(app, name='Haldis', url='/admin', template_mode='bootstrap3') admin = Admin(app, name="Haldis", url="/admin", template_mode="bootstrap3")
admin.add_view(UserAdminModel(User, db.session)) admin.add_view(UserAdminModel(User, db.session))
admin.add_view(LocationAdminModel(Location, db.session)) admin.add_view(LocationAdminModel(Location, db.session))

View file

@ -23,7 +23,7 @@ def create_app():
app = Flask(__name__) app = Flask(__name__)
# Load the config file # Load the config file
app.config.from_object('config.Configuration') app.config.from_object("config.Configuration")
manager = register_plugins(app, debug=app.debug) manager = register_plugins(app, debug=app.debug)
add_handlers(app) add_handlers(app)
@ -37,24 +37,26 @@ def create_app():
def register_plugins(app, debug: bool): def register_plugins(app, debug: bool):
# Register Airbrake and enable the logrotation # Register Airbrake and enable the logrotation
if not app.debug: if not app.debug:
timedFileHandler = TimedRotatingFileHandler(app.config['LOGFILE'], timedFileHandler = TimedRotatingFileHandler(
when='midnight', app.config["LOGFILE"], when="midnight", backupCount=100
backupCount=100) )
timedFileHandler.setLevel(logging.DEBUG) timedFileHandler.setLevel(logging.DEBUG)
loglogger = logging.getLogger('werkzeug') loglogger = logging.getLogger("werkzeug")
loglogger.setLevel(logging.DEBUG) loglogger.setLevel(logging.DEBUG)
loglogger.addHandler(timedFileHandler) loglogger.addHandler(timedFileHandler)
app.logger.addHandler(timedFileHandler) app.logger.addHandler(timedFileHandler)
airbrakelogger = logging.getLogger('airbrake') airbrakelogger = logging.getLogger("airbrake")
# Airbrake # Airbrake
airbrake = Airbrake(project_id=app.config['AIRBRAKE_ID'], airbrake = Airbrake(
api_key=app.config['AIRBRAKE_KEY']) project_id=app.config["AIRBRAKE_ID"], api_key=app.config["AIRBRAKE_KEY"]
)
# ugly hack to make this work for out errbit # ugly hack to make this work for out errbit
airbrake._api_url = "http://errbit.awesomepeople.tv/api/v3/projects/{}/notices".format( airbrake._api_url = "http://errbit.awesomepeople.tv/api/v3/projects/{}/notices".format(
airbrake.project_id) airbrake.project_id
)
airbrakelogger.addHandler(AirbrakeHandler(airbrake=airbrake)) airbrakelogger.addHandler(AirbrakeHandler(airbrake=airbrake))
app.logger.addHandler(AirbrakeHandler(airbrake=airbrake)) app.logger.addHandler(AirbrakeHandler(airbrake=airbrake))
@ -65,8 +67,8 @@ def register_plugins(app, debug: bool):
# Initialize Flask-Migrate # Initialize Flask-Migrate
migrate = Migrate(app, db) migrate = Migrate(app, db)
manager = Manager(app) manager = Manager(app)
manager.add_command('db', MigrateCommand) manager.add_command("db", MigrateCommand)
manager.add_command('runserver', Server(port=8000)) manager.add_command("runserver", Server(port=8000))
# Add admin interface # Add admin interface
init_admin(app, db) init_admin(app, db)
@ -83,10 +85,10 @@ def register_plugins(app, debug: bool):
# Load the bootstrap local cdn # Load the bootstrap local cdn
Bootstrap(app) Bootstrap(app)
app.config['BOOTSTRAP_SERVE_LOCAL'] = True app.config["BOOTSTRAP_SERVE_LOCAL"] = True
# use our own bootstrap theme # use our own bootstrap theme
app.extensions['bootstrap']['cdns']['bootstrap'] = StaticCDN() app.extensions["bootstrap"]["cdns"]["bootstrap"] = StaticCDN()
# Load the flask debug toolbar # Load the flask debug toolbar
toolbar = DebugToolbarExtension(app) toolbar = DebugToolbarExtension(app)
@ -97,11 +99,11 @@ def register_plugins(app, debug: bool):
def add_handlers(app): def add_handlers(app):
@app.errorhandler(404) @app.errorhandler(404)
def handle404(e): def handle404(e):
return render_template('errors/404.html'), 404 return render_template("errors/404.html"), 404
@app.errorhandler(401) @app.errorhandler(401)
def handle401(e): def handle401(e):
return render_template('errors/401.html'), 401 return render_template("errors/401.html"), 401
def add_routes(application): def add_routes(application):
@ -115,39 +117,39 @@ def add_routes(application):
from login import auth_bp from login import auth_bp
from zeus import oauth_bp from zeus import oauth_bp
application.register_blueprint(general_bp, url_prefix='/') application.register_blueprint(general_bp, url_prefix="/")
application.register_blueprint(order_bp, url_prefix='/order') application.register_blueprint(order_bp, url_prefix="/order")
application.register_blueprint(stats_blueprint, url_prefix='/stats') application.register_blueprint(stats_blueprint, url_prefix="/stats")
application.register_blueprint(auth_bp, url_prefix='/') application.register_blueprint(auth_bp, url_prefix="/")
application.register_blueprint(oauth_bp, url_prefix='/') application.register_blueprint(oauth_bp, url_prefix="/")
if application.debug: if application.debug:
application.register_blueprint(debug_bp, url_prefix='/debug') application.register_blueprint(debug_bp, url_prefix="/debug")
def add_template_filters(app): def add_template_filters(app):
@app.template_filter('countdown') @app.template_filter("countdown")
def countdown(value, only_positive=True, show_text=True): def countdown(value, only_positive=True, show_text=True):
delta = value - datetime.now() delta = value - datetime.now()
if delta.total_seconds() < 0 and only_positive: if delta.total_seconds() < 0 and only_positive:
return "closed" return "closed"
hours, remainder = divmod(delta.seconds, 3600) hours, remainder = divmod(delta.seconds, 3600)
minutes, seconds = divmod(remainder, 60) minutes, seconds = divmod(remainder, 60)
time = '%02d:%02d:%02d' % (hours, minutes, seconds) time = "%02d:%02d:%02d" % (hours, minutes, seconds)
if show_text: if show_text:
return 'closes in ' + time return "closes in " + time
return time return time
@app.template_filter('year') @app.template_filter("year")
def current_year(value): def current_year(value):
return str(datetime.now().year) return str(datetime.now().year)
@app.template_filter('euro') @app.template_filter("euro")
def euro(value): def euro(value):
euro_string(value) euro_string(value)
# For usage when you directly call the script with python # For usage when you directly call the script with python
if __name__ == '__main__': if __name__ == "__main__":
manager = create_app() manager = create_app()
manager.run() manager.run()

View file

@ -1,13 +1,14 @@
# config # config
class Configuration(object): class Configuration(object):
SQLALCHEMY_DATABASE_URI = 'sqlite:///haldis.db' SQLALCHEMY_DATABASE_URI = "sqlite:///haldis.db"
SQLALCHEMY_TRACK_MODIFICATIONS = False SQLALCHEMY_TRACK_MODIFICATIONS = False
DEBUG = True DEBUG = True
SECRET_KEY = '<change>' SECRET_KEY = "<change>"
SLACK_WEBHOOK = '<add url>' SLACK_WEBHOOK = "<add url>"
LOGFILE = 'haldis.log' LOGFILE = "haldis.log"
ZEUS_KEY = 'tomtest' ZEUS_KEY = "tomtest"
ZEUS_SECRET = 'blargh' ZEUS_SECRET = "blargh"
AIRBRAKE_ID = '' AIRBRAKE_ID = ""
AIRBRAKE_KEY = '' AIRBRAKE_KEY = ""

View file

@ -8,15 +8,15 @@ def add():
db.session.add(feli) db.session.add(feli)
destro = User() destro = User()
destro.configure('destro', True, 0) destro.configure("destro", True, 0)
db.session.add(destro) db.session.add(destro)
iepoev = User() iepoev = User()
iepoev.configure('iepoev', True, 1) iepoev.configure("iepoev", True, 1)
db.session.add(iepoev) db.session.add(iepoev)
flynn = User() flynn = User()
flynn.configure('flynn', True, 0) flynn.configure("flynn", True, 0)
db.session.add(flynn) db.session.add(flynn)
# To future developers, add yourself here # To future developers, add yourself here

View file

@ -3,24 +3,24 @@ from app import db
menuitems = [ menuitems = [
'Spicy Chicken', "Spicy Chicken",
'Advocado Chick', "Advocado Chick",
'Indian Summer', "Indian Summer",
'Olive Garden', "Olive Garden",
'Advocado Spring', "Advocado Spring",
'Spicy Mexican', "Spicy Mexican",
'Beefcake', "Beefcake",
'Iron Man', "Iron Man",
'Fitalian', "Fitalian",
'Captain', "Captain",
'Sea Breeze', "Sea Breeze",
'Vegan Market', "Vegan Market",
'Sunset Beach', "Sunset Beach",
'Hot Tofu', "Hot Tofu",
'Vegan Advocado Spring' "Vegan Advocado Spring",
] ]
pricedict = {'Small': 799, 'Medium': 999, 'Large': 1199} pricedict = {"Small": 799, "Medium": 999, "Large": 1199}
def add(): def add():
@ -30,8 +30,8 @@ def add():
for menuitem in menuitems: for menuitem in menuitems:
for size, price in pricedict.items(): for size, price in pricedict.items():
for container in ['bowl', 'wrap']: for container in ["bowl", "wrap"]:
name = '%s %s in %s' % (size, menuitem, container) name = "%s %s in %s" % (size, menuitem, container)
entry = Product() entry = Product()
entry.configure(simpizza, name, price) entry.configure(simpizza, name, price)
db.session.add(entry) db.session.add(entry)

View file

@ -5,21 +5,38 @@ from itertools import product
zetmelen = ["Nasi", "Bami"] zetmelen = ["Nasi", "Bami"]
vlezen = ["Rundsvlees", "Varkensvlees", "Kippenstukkjes"] vlezen = ["Rundsvlees", "Varkensvlees", "Kippenstukkjes"]
sauzen = ["Balisaus", "Yu siang saus", "Gon boa saus", "Curry saus", "Oestersaus", "Zwarte pepersaus", sauzen = [
"Champignons", "Chinese champignons", "A la Maleisïe"] "Balisaus",
"Yu siang saus",
"Gon boa saus",
"Curry saus",
"Oestersaus",
"Zwarte pepersaus",
"Champignons",
"Chinese champignons",
"A la Maleisïe",
]
specials = ["Nasi Kippenbolletjes Zoetzuur", "Bami Kippenbolletjes Zoetzuur", specials = [
"Nasi Varkenbolletjes Zoetzuur", "Bami Varkenbolletjes Zoetzuur", "Nasi Kippenbolletjes Zoetzuur",
"Nasi Babi Pangang", "Bami Babi Pangang", "Bami Kippenbolletjes Zoetzuur",
"Nasi Varkenbolletjes Zoetzuur",
"Bami Varkenbolletjes Zoetzuur",
"Nasi Babi Pangang",
"Bami Babi Pangang",
"Diverse Groenten met Bami", "Diverse Groenten met Bami",
"Diverse Groenten met Nasi"] "Diverse Groenten met Nasi",
]
def add(): def add():
chinees = Location() chinees = Location()
chinees.configure("Oceans's Garden", chinees.configure(
"Zwijnaardsesteenweg 399 9000 Gent", "tel: 09/222.72.74", "Oceans's Garden",
"http://oceangarden.byethost3.com/studentenmenus.html") "Zwijnaardsesteenweg 399 9000 Gent",
"tel: 09/222.72.74",
"http://oceangarden.byethost3.com/studentenmenus.html",
)
db.session.add(chinees) db.session.add(chinees)
def chinees_create_entry(name): def chinees_create_entry(name):

View file

@ -1,10 +1,12 @@
from models import Location, Product from models import Location, Product
from app import db from app import db
def add(): def add():
addTA() addTA()
addAfhalen() addAfhalen()
pizzasTA = { pizzasTA = {
"Peperoni": 750, "Peperoni": 750,
"Basis pizza (extra garneringen zie site)": 600, "Basis pizza (extra garneringen zie site)": 600,
@ -40,12 +42,18 @@ pizzasTA = {
"Milano": 1170, "Milano": 1170,
"Soronto": 1260, "Soronto": 1260,
"Primma Donna": 1260, "Primma Donna": 1260,
"Pasta (zie site voor opties)":900 "Pasta (zie site voor opties)": 900,
} }
def addTA(): def addTA():
primadonna_takeaway = Location() primadonna_takeaway = Location()
primadonna_takeaway.configure("Primadonna (takeaway laten bezorgen)", "Overpoortstraat 46 9000 Gent", "tel: 0475 40 13 00", "https://www.takeaway.com/be-en/prima-donna") primadonna_takeaway.configure(
"Primadonna (takeaway laten bezorgen)",
"Overpoortstraat 46 9000 Gent",
"tel: 0475 40 13 00",
"https://www.takeaway.com/be-en/prima-donna",
)
db.session.add(primadonna_takeaway) db.session.add(primadonna_takeaway)
for pizza, price in pizzasTA.items(): for pizza, price in pizzasTA.items():
@ -53,6 +61,7 @@ def addTA():
entry.configure(primadonna_takeaway, pizza, price) entry.configure(primadonna_takeaway, pizza, price)
db.session.add(entry) db.session.add(entry)
pizzasAfhalen = { pizzasAfhalen = {
"Peperoni": 575, "Peperoni": 575,
"Basis pizza (extra garneringen zie site)": 450, "Basis pizza (extra garneringen zie site)": 450,
@ -88,16 +97,21 @@ pizzasAfhalen = {
"Milano": 900, "Milano": 900,
"Soronto": 970, "Soronto": 970,
"Primma Donna": 970, "Primma Donna": 970,
"Pasta (zie site voor opties)":700 "Pasta (zie site voor opties)": 700,
} }
def addAfhalen(): def addAfhalen():
primadonna_afhalen = Location() primadonna_afhalen = Location()
primadonna_afhalen.configure("Primadonna (bellen en afhalen)", "Overpoortstraat 46 9000 Gent", "tel: 0475 40 13 00", "http://primadonnagent.be/Menu.html") primadonna_afhalen.configure(
"Primadonna (bellen en afhalen)",
"Overpoortstraat 46 9000 Gent",
"tel: 0475 40 13 00",
"http://primadonnagent.be/Menu.html",
)
db.session.add(primadonna_afhalen) db.session.add(primadonna_afhalen)
for pizza, price in pizzasAfhalen.items(): for pizza, price in pizzasAfhalen.items():
entry = Product() entry = Product()
entry.configure(primadonna_afhalen, pizza, price) entry.configure(primadonna_afhalen, pizza, price)
db.session.add(entry) db.session.add(entry)

View file

@ -2,16 +2,45 @@ from models import Location, Product
from app import db from app import db
pizzas = ['Bolognese de luxe', 'Hawaï', 'Popeye', 'Pepperoni', 'Seafood', 'Hot pizzaaah!!!', pizzas = [
'Salmon delight', 'Full option', 'Pitza kebab', 'Multi cheese', '4 Seasons', 'Mega fish', "Bolognese de luxe",
'Creamy multi cheese', 'Green fiësta', 'Chicken bbq', 'Funky chicken', 'Veggie', "Hawaï",
'Meat lovers' 'Scampi mampi', 'Tabasco', 'Chicken time', 'Meatballs', 'Tuna', 'Anchovy', "Popeye",
'Calzone', 'Bbq meatballs', 'Creamy chicken', 'Hot bolognese'] "Pepperoni",
"Seafood",
"Hot pizzaaah!!!",
"Salmon delight",
"Full option",
"Pitza kebab",
"Multi cheese",
"4 Seasons",
"Mega fish",
"Creamy multi cheese",
"Green fiësta",
"Chicken bbq",
"Funky chicken",
"Veggie",
"Meat lovers" "Scampi mampi",
"Tabasco",
"Chicken time",
"Meatballs",
"Tuna",
"Anchovy",
"Calzone",
"Bbq meatballs",
"Creamy chicken",
"Hot bolognese",
]
def add(): def add():
simpizza = Location() simpizza = Location()
simpizza.configure("Sim-pizza", "De Pintelaan 252 9000 Gent", "tel: 09/321.02.00", "http://simpizza.be") simpizza.configure(
"Sim-pizza",
"De Pintelaan 252 9000 Gent",
"tel: 09/321.02.00",
"http://simpizza.be",
)
db.session.add(simpizza) db.session.add(simpizza)
for pizza in pizzas: for pizza in pizzas:

View file

@ -66,7 +66,7 @@ specials = {
"Molleke Dubbel": 1200, "Molleke Dubbel": 1200,
"Stefano": 650, "Stefano": 650,
"Stefano Dubbel": 800, "Stefano Dubbel": 800,
"Picasso": 1350 "Picasso": 1350,
} }
vlezekes = { vlezekes = {
@ -93,20 +93,21 @@ vlezekes = {
"Mini Lucifers": 300, "Mini Lucifers": 300,
"Ragouzi": 250, "Ragouzi": 250,
"stoofvlees": 450, "stoofvlees": 450,
} }
friet = { friet = {"Klein pak": 200, "Midden pak": 250, "Groot pak": 300}
"Klein pak": 200,
"Midden pak": 250,
"Groot pak": 300,
}
data = [special_bickies, specials, vlezekes, friet] data = [special_bickies, specials, vlezekes, friet]
def add(): def add():
stefanos = Location() stefanos = Location()
stefanos.configure("Stefano's Place", "Overpoortstraat 12 9000 Gent", "tel: geen", "https://www.facebook.com/pages/category/Fast-Food-Restaurant/Stefanos-Place-370774480004139/") stefanos.configure(
"Stefano's Place",
"Overpoortstraat 12 9000 Gent",
"tel: geen",
"https://www.facebook.com/pages/category/Fast-Food-Restaurant/Stefanos-Place-370774480004139/",
)
db.session.add(stefanos) db.session.add(stefanos)
# sommige bickies kunde met een schel kaas bestellen # sommige bickies kunde met een schel kaas bestellen

View file

@ -7,7 +7,7 @@ entry_sets = {
"Ocean's Garden": add_oceans_garden.add, "Ocean's Garden": add_oceans_garden.add,
"SimPizza": add_simpizza.add, "SimPizza": add_simpizza.add,
"Primadonna": add_primadonna.add, "Primadonna": add_primadonna.add,
"Fitchen": add_fitchen.add "Fitchen": add_fitchen.add,
} }
yes = ["yes", "y", "Y"] yes = ["yes", "y", "Y"]
@ -45,10 +45,14 @@ def add_to_current():
available = [entry_set for entry_set in entry_sets] available = [entry_set for entry_set in entry_sets]
def add_numbers(): def add_numbers():
return " ".join(["{}({}), ".format(loc, i) for i, loc in enumerate(available)]).rstrip(", ") return " ".join(
["{}({}), ".format(loc, i) for i, loc in enumerate(available)]
).rstrip(", ")
while input("Do you still want to add something? (Y/n) ") not in no: while input("Do you still want to add something? (Y/n) ") not in no:
print("What do you want to add? (Use numbers, or A for all, or C for cancel) ") print(
"What do you want to add? (Use numbers, or A for all, or C for cancel) "
)
answer = input("Available: {} : ".format(add_numbers())) answer = input("Available: {} : ".format(add_numbers()))
if answer == "A": if answer == "A":
add_all() add_all()
@ -66,8 +70,8 @@ def add_to_current():
def init(): def init():
print('Database modification script!') print("Database modification script!")
print('=============================\n\n') print("=============================\n\n")
if check_if_overwrite(): if check_if_overwrite():
recreate_from_scratch() recreate_from_scratch()
else: else:

View file

@ -25,10 +25,11 @@ class FatOrder(Order, FatModel):
# even if they get reduced by the disctinct afterwards. # even if they get reduced by the disctinct afterwards.
@classmethod @classmethod
def items_per_order(cls): def items_per_order(cls):
return Order.query.\ return (
join(OrderItem).\ Order.query.join(OrderItem)
group_by(Order.id).\ .group_by(Order.id)
with_entities(Order.id, func.count(OrderItem.user_id).label('total')) .with_entities(Order.id, func.count(OrderItem.user_id).label("total"))
)
class FatUser(User, FatModel): class FatUser(User, FatModel):
@ -42,15 +43,15 @@ class FatOrderItem(OrderItem, FatModel):
class FatProduct(Product, FatModel): class FatProduct(Product, FatModel):
@classmethod @classmethod
def top4(cls): def top4(cls):
top4 = OrderItem.query\ top4 = (
.join(Product)\ OrderItem.query.join(Product)
.join(Location)\ .join(Location)
.group_by(Product.id)\ .group_by(Product.id)
.with_entities(Product.name, .with_entities(
Location.name, Product.name, Location.name, func.count(Product.id).label("count")
func.count(Product.id).label('count') )
)\ .order_by(desc("count"))
.order_by(desc('count'))\
.limit(4) .limit(4)
)
for top in top4: for top in top4:
print(top) print(top)

View file

@ -3,56 +3,58 @@ from datetime import datetime, timedelta
from flask import session from flask import session
from flask_login import current_user from flask_login import current_user
from flask_wtf import FlaskForm as Form from flask_wtf import FlaskForm as Form
from wtforms import (DateTimeField, SelectField, StringField, SubmitField, from wtforms import DateTimeField, SelectField, StringField, SubmitField, validators
validators)
from models import Location, User from models import Location, User
from utils import euro_string from utils import euro_string
class OrderForm(Form): class OrderForm(Form):
courrier_id = SelectField('Courrier', coerce=int) courrier_id = SelectField("Courrier", coerce=int)
location_id = SelectField('Location', location_id = SelectField(
coerce=int, "Location", coerce=int, validators=[validators.required()]
validators=[validators.required()]) )
starttime = DateTimeField('Starttime', starttime = DateTimeField(
default=datetime.now, "Starttime", default=datetime.now, format="%d-%m-%Y %H:%M"
format='%d-%m-%Y %H:%M') )
stoptime = DateTimeField('Stoptime', format='%d-%m-%Y %H:%M') stoptime = DateTimeField("Stoptime", format="%d-%m-%Y %H:%M")
submit_button = SubmitField('Submit') submit_button = SubmitField("Submit")
def populate(self): def populate(self):
if current_user.is_admin(): if current_user.is_admin():
self.courrier_id.choices = [(0, None)] + \ self.courrier_id.choices = [(0, None)] + [
[(u.id, u.username) for u in User.query.order_by('username')] (u.id, u.username) for u in User.query.order_by("username")
]
else: else:
self.courrier_id.choices = [(0, None), self.courrier_id.choices = [
(current_user.id, (0, None),
current_user.username)] (current_user.id, current_user.username),
self.location_id.choices = [(l.id, l.name) ]
for l in Location.query.order_by('name')] self.location_id.choices = [
(l.id, l.name) for l in Location.query.order_by("name")
]
if self.stoptime.data is None: if self.stoptime.data is None:
self.stoptime.data = datetime.now() + timedelta(hours=1) self.stoptime.data = datetime.now() + timedelta(hours=1)
class OrderItemForm(Form): class OrderItemForm(Form):
product_id = SelectField('Item', coerce=int) product_id = SelectField("Item", coerce=int)
extra = StringField('Extra') extra = StringField("Extra")
submit_button = SubmitField('Submit') submit_button = SubmitField("Submit")
def populate(self, location): def populate(self, location):
self.product_id.choices = [(i.id, self.product_id.choices = [
(i.name + ": " + euro_string(i.price))) (i.id, (i.name + ": " + euro_string(i.price))) for i in location.products
for i in location.products] ]
class AnonOrderItemForm(OrderItemForm): class AnonOrderItemForm(OrderItemForm):
name = StringField('Name', validators=[validators.required()]) name = StringField("Name", validators=[validators.required()])
def populate(self, location): def populate(self, location):
OrderItemForm.populate(self, location) OrderItemForm.populate(self, location)
if self.name.data is None: if self.name.data is None:
self.name.data = session.get('anon_name', None) self.name.data = session.get("anon_name", None)
def validate(self): def validate(self):
rv = OrderForm.validate(self) rv = OrderForm.validate(self)
@ -62,6 +64,6 @@ class AnonOrderItemForm(OrderItemForm):
# check if we have a user with this name # check if we have a user with this name
user = User.query.filter_by(username=self.name.data).first() user = User.query.filter_by(username=self.name.data).first()
if user is not None: if user is not None:
self.name.errors.append('Name already in use') self.name.errors.append("Name already in use")
return False return False
return True return True

View file

@ -5,7 +5,7 @@ from flask_login import current_user, logout_user
from models import User from models import User
from zeus import zeus_login from zeus import zeus_login
auth_bp = Blueprint('auth_bp', __name__) auth_bp = Blueprint("auth_bp", __name__)
def init_login(app): def init_login(app):
@ -14,17 +14,17 @@ def init_login(app):
return User.query.filter_by(id=userid).first() return User.query.filter_by(id=userid).first()
@auth_bp.route('/login') @auth_bp.route("/login")
def login(): def login():
return zeus_login() return zeus_login()
@auth_bp.route('/logout') @auth_bp.route("/logout")
def logout(): def logout():
if 'zeus_token' in session: if "zeus_token" in session:
session.pop('zeus_token', None) session.pop("zeus_token", None)
logout_user() logout_user()
return redirect(url_for('general_bp.home')) return redirect(url_for("general_bp.home"))
def before_request(): def before_request():

View file

@ -16,8 +16,11 @@ fileConfig(config.config_file_name)
# from myapp import mymodel # from myapp import mymodel
# target_metadata = mymodel.Base.metadata # target_metadata = mymodel.Base.metadata
from flask import current_app from flask import current_app
config.set_main_option('sqlalchemy.url', current_app.config.get('SQLALCHEMY_DATABASE_URI'))
target_metadata = current_app.extensions['migrate'].db.metadata config.set_main_option(
"sqlalchemy.url", current_app.config.get("SQLALCHEMY_DATABASE_URI")
)
target_metadata = current_app.extensions["migrate"].db.metadata
# other values from the config, defined by the needs of env.py, # other values from the config, defined by the needs of env.py,
# can be acquired: # can be acquired:
@ -51,14 +54,18 @@ def run_migrations_online():
and associate a connection with the context. and associate a connection with the context.
""" """
engine = engine_from_config(config.get_section(config.config_ini_section), engine = engine_from_config(
prefix='sqlalchemy.', config.get_section(config.config_ini_section),
poolclass=pool.NullPool) prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
connection = engine.connect() connection = engine.connect()
context.configure(connection=connection, context.configure(
connection=connection,
target_metadata=target_metadata, target_metadata=target_metadata,
**current_app.extensions['migrate'].configure_args) **current_app.extensions["migrate"].configure_args
)
try: try:
with context.begin_transaction(): with context.begin_transaction():
@ -66,8 +73,8 @@ def run_migrations_online():
finally: finally:
connection.close() connection.close()
if context.is_offline_mode(): if context.is_offline_mode():
run_migrations_offline() run_migrations_offline()
else: else:
run_migrations_online() run_migrations_online()

View file

@ -7,7 +7,7 @@ Create Date: 2019-04-02 18:00:12.618368
""" """
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '150252c1cdb1' revision = "150252c1cdb1"
down_revision = None down_revision = None
from alembic import op from alembic import op
@ -16,61 +16,66 @@ import sqlalchemy as sa
def upgrade(): def upgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.create_table('location', op.create_table(
sa.Column('id', sa.Integer(), nullable=False), "location",
sa.Column('name', sa.String(length=120), nullable=False), sa.Column("id", sa.Integer(), nullable=False),
sa.Column('address', sa.String(length=254), nullable=True), sa.Column("name", sa.String(length=120), nullable=False),
sa.Column('website', sa.String(length=120), nullable=True), sa.Column("address", sa.String(length=254), nullable=True),
sa.Column('telephone', sa.String(length=20), nullable=True), sa.Column("website", sa.String(length=120), nullable=True),
sa.PrimaryKeyConstraint('id') sa.Column("telephone", sa.String(length=20), nullable=True),
sa.PrimaryKeyConstraint("id"),
) )
op.create_table('user', op.create_table(
sa.Column('id', sa.Integer(), nullable=False), "user",
sa.Column('username', sa.String(length=80), nullable=False), sa.Column("id", sa.Integer(), nullable=False),
sa.Column('admin', sa.Boolean(), nullable=True), sa.Column("username", sa.String(length=80), nullable=False),
sa.Column('bias', sa.Integer(), nullable=True), sa.Column("admin", sa.Boolean(), nullable=True),
sa.PrimaryKeyConstraint('id'), sa.Column("bias", sa.Integer(), nullable=True),
sa.UniqueConstraint('username') sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("username"),
) )
op.create_table('order', op.create_table(
sa.Column('id', sa.Integer(), nullable=False), "order",
sa.Column('courrier_id', sa.Integer(), nullable=True), sa.Column("id", sa.Integer(), nullable=False),
sa.Column('location_id', sa.Integer(), nullable=True), sa.Column("courrier_id", sa.Integer(), nullable=True),
sa.Column('starttime', sa.DateTime(), nullable=True), sa.Column("location_id", sa.Integer(), nullable=True),
sa.Column('stoptime', sa.DateTime(), nullable=True), sa.Column("starttime", sa.DateTime(), nullable=True),
sa.Column('public', sa.Boolean(), nullable=True), sa.Column("stoptime", sa.DateTime(), nullable=True),
sa.ForeignKeyConstraint(['location_id'], ['location.id'], ), sa.Column("public", sa.Boolean(), nullable=True),
sa.PrimaryKeyConstraint('id') sa.ForeignKeyConstraint(["location_id"], ["location.id"]),
sa.PrimaryKeyConstraint("id"),
) )
op.create_table('product', op.create_table(
sa.Column('id', sa.Integer(), nullable=False), "product",
sa.Column('location_id', sa.Integer(), nullable=True), sa.Column("id", sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=120), nullable=False), sa.Column("location_id", sa.Integer(), nullable=True),
sa.Column('price', sa.Integer(), nullable=False), sa.Column("name", sa.String(length=120), nullable=False),
sa.ForeignKeyConstraint(['location_id'], ['location.id'], ), sa.Column("price", sa.Integer(), nullable=False),
sa.PrimaryKeyConstraint('id') sa.ForeignKeyConstraint(["location_id"], ["location.id"]),
sa.PrimaryKeyConstraint("id"),
) )
op.create_table('order_item', op.create_table(
sa.Column('id', sa.Integer(), nullable=False), "order_item",
sa.Column('user_id', sa.Integer(), nullable=True), sa.Column("id", sa.Integer(), nullable=False),
sa.Column('order_id', sa.Integer(), nullable=False), sa.Column("user_id", sa.Integer(), nullable=True),
sa.Column('product_id', sa.Integer(), nullable=True), sa.Column("order_id", sa.Integer(), nullable=False),
sa.Column('paid', sa.Boolean(), nullable=True), sa.Column("product_id", sa.Integer(), nullable=True),
sa.Column('extra', sa.String(length=254), nullable=True), sa.Column("paid", sa.Boolean(), nullable=True),
sa.Column('name', sa.String(length=120), nullable=True), sa.Column("extra", sa.String(length=254), nullable=True),
sa.ForeignKeyConstraint(['order_id'], ['order.id'], ), sa.Column("name", sa.String(length=120), nullable=True),
sa.ForeignKeyConstraint(['product_id'], ['product.id'], ), sa.ForeignKeyConstraint(["order_id"], ["order.id"]),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), sa.ForeignKeyConstraint(["product_id"], ["product.id"]),
sa.PrimaryKeyConstraint('id') sa.ForeignKeyConstraint(["user_id"], ["user.id"]),
sa.PrimaryKeyConstraint("id"),
) )
# ### end Alembic commands ### # ### end Alembic commands ###
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_table('order_item') op.drop_table("order_item")
op.drop_table('product') op.drop_table("product")
op.drop_table('order') op.drop_table("order")
op.drop_table('user') op.drop_table("user")
op.drop_table('location') op.drop_table("location")
# ### end Alembic commands ### # ### end Alembic commands ###

View file

@ -7,8 +7,8 @@ class Location(db.Model):
address = db.Column(db.String(254)) address = db.Column(db.String(254))
website = db.Column(db.String(120)) website = db.Column(db.String(120))
telephone = db.Column(db.String(20), nullable=True) telephone = db.Column(db.String(20), nullable=True)
products = db.relationship('Product', backref='location', lazy='dynamic') products = db.relationship("Product", backref="location", lazy="dynamic")
orders = db.relationship('Order', backref='location', lazy='dynamic') orders = db.relationship("Order", backref="location", lazy="dynamic")
def configure(self, name, address, telephone, website): def configure(self, name, address, telephone, website):
self.name = name self.name = name
@ -17,4 +17,4 @@ class Location(db.Model):
self.telephone = telephone self.telephone = telephone
def __repr__(self): def __repr__(self):
return '%s' % (self.name) return "%s" % (self.name)

View file

@ -7,11 +7,11 @@ from .user import User
class Order(db.Model): class Order(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
courrier_id = db.Column(db.Integer, nullable=True) courrier_id = db.Column(db.Integer, nullable=True)
location_id = db.Column(db.Integer, db.ForeignKey('location.id')) location_id = db.Column(db.Integer, db.ForeignKey("location.id"))
starttime = db.Column(db.DateTime) starttime = db.Column(db.DateTime)
stoptime = db.Column(db.DateTime) stoptime = db.Column(db.DateTime)
public = db.Column(db.Boolean, default=True) public = db.Column(db.Boolean, default=True)
items = db.relationship('OrderItem', backref='order', lazy='dynamic') items = db.relationship("OrderItem", backref="order", lazy="dynamic")
def configure(self, courrier, location, starttime, stoptime): def configure(self, courrier, location, starttime, stoptime):
self.courrier = courrier self.courrier = courrier
@ -21,17 +21,18 @@ class Order(db.Model):
def __repr__(self): def __repr__(self):
if self.location: if self.location:
return 'Order %d @ %s' % (self.id, self.location.name or 'None') return "Order %d @ %s" % (self.id, self.location.name or "None")
else: else:
return 'Order %d' % (self.id) return "Order %d" % (self.id)
def group_by_user(self): def group_by_user(self):
group = dict() group = dict()
for item in self.items: for item in self.items:
user = group.get(item.get_name(), dict()) user = group.get(item.get_name(), dict())
user["total"] = user.get("total", 0) + item.product.price user["total"] = user.get("total", 0) + item.product.price
user["to_pay"] = user.get( user["to_pay"] = (
"to_pay", 0) + item.product.price if not item.paid else 0 user.get("to_pay", 0) + item.product.price if not item.paid else 0
)
user["paid"] = user.get("paid", True) and item.paid user["paid"] = user.get("paid", True) and item.paid
user["products"] = user.get("products", []) + [item.product] user["products"] = user.get("products", []) + [item.product]
group[item.get_name()] = user group[item.get_name()] = user
@ -42,7 +43,7 @@ class Order(db.Model):
group = dict() group = dict()
for item in self.items: for item in self.items:
product = group.get(item.product.name, dict()) product = group.get(item.product.name, dict())
product['count'] = product.get("count", 0) + 1 product["count"] = product.get("count", 0) + 1
if item.extra: if item.extra:
product["extras"] = product.get("extras", []) + [item.extra] product["extras"] = product.get("extras", []) + [item.extra]
group[item.product.name] = product group[item.product.name] = product

View file

@ -6,13 +6,14 @@ from .user import User
class OrderItem(db.Model): class OrderItem(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id')) user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
order_id = db.Column(db.Integer, db.ForeignKey('order.id'), nullable=False) order_id = db.Column(db.Integer, db.ForeignKey("order.id"), nullable=False)
product_id = db.Column( product_id = db.Column(
db.Integer, db.ForeignKey('product.id'), db.Integer, db.ForeignKey("product.id"), nullable=True
nullable=True) # TODO make false after init migration ) # TODO make false after init migration
paid = db.Column(db.Boolean, default=False, paid = db.Column(
nullable=True) # TODO make false after init migration db.Boolean, default=False, nullable=True
) # TODO make false after init migration
extra = db.Column(db.String(254), nullable=True) extra = db.Column(db.String(254), nullable=True)
name = db.Column(db.String(120)) name = db.Column(db.String(120))
@ -30,8 +31,11 @@ class OrderItem(db.Model):
product_name = None product_name = None
if self.product: if self.product:
product_name = self.product.name product_name = self.product.name
return 'Order %d: %s wants %s' % (self.order_id or 0, self.get_name(), return "Order %d: %s wants %s" % (
product_name or 'None') self.order_id or 0,
self.get_name(),
product_name or "None",
)
def can_delete(self, order_id, user_id, name): def can_delete(self, order_id, user_id, name):
if int(self.order_id) != int(order_id): if int(self.order_id) != int(order_id):

View file

@ -3,12 +3,10 @@ from models import db
class Product(db.Model): class Product(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
location_id = db.Column(db.Integer, db.ForeignKey('location.id')) location_id = db.Column(db.Integer, db.ForeignKey("location.id"))
name = db.Column(db.String(120), nullable=False) name = db.Column(db.String(120), nullable=False)
price = db.Column(db.Integer, nullable=False) price = db.Column(db.Integer, nullable=False)
orderItems = db.relationship('OrderItem', orderItems = db.relationship("OrderItem", backref="product", lazy="dynamic")
backref='product',
lazy='dynamic')
def configure(self, location, name, price): def configure(self, location, name, price):
self.location = location self.location = location
@ -16,5 +14,8 @@ class Product(db.Model):
self.price = price self.price = price
def __repr__(self): def __repr__(self):
return '%s (€%d)from %s' % (self.name, self.price / 100, self.location return "%s (€%d)from %s" % (
or 'None') self.name,
self.price / 100,
self.location or "None",
)

View file

@ -6,11 +6,13 @@ class User(db.Model):
username = db.Column(db.String(80), unique=True, nullable=False) username = db.Column(db.String(80), unique=True, nullable=False)
admin = db.Column(db.Boolean) admin = db.Column(db.Boolean)
bias = db.Column(db.Integer) bias = db.Column(db.Integer)
runs = db.relation('Order', runs = db.relation(
backref='courrier', "Order",
primaryjoin='Order.courrier_id==User.id', backref="courrier",
foreign_keys='Order.courrier_id') primaryjoin="Order.courrier_id==User.id",
orderItems = db.relationship('OrderItem', backref='user', lazy='dynamic') foreign_keys="Order.courrier_id",
)
orderItems = db.relationship("OrderItem", backref="user", lazy="dynamic")
def configure(self, username, admin, bias): def configure(self, username, admin, bias):
self.username = username self.username = username
@ -33,4 +35,4 @@ class User(db.Model):
return str(self.id) return str(self.id)
def __repr__(self): def __repr__(self):
return '%s' % self.username return "%s" % self.username

View file

@ -8,16 +8,20 @@ from flask import url_for
def post_order_to_webhook(order_item): def post_order_to_webhook(order_item):
message = '' message = ""
if order_item.courrier is not None: if order_item.courrier is not None:
message = '<!channel|@channel> {3} is going to {1}, order <{0}|here>! Deadline in {2} minutes!'.format( message = "<!channel|@channel> {3} is going to {1}, order <{0}|here>! Deadline in {2} minutes!".format(
url_for('order_bp.order', id=order_item.id, _external=True), url_for("order_bp.order", id=order_item.id, _external=True),
order_item.location.name, remaining_minutes(order_item.stoptime), order_item.location.name,
order_item.courrier.username.title()) remaining_minutes(order_item.stoptime),
order_item.courrier.username.title(),
)
else: else:
message = '<!channel|@channel> New order for {}. Deadline in {} minutes. <{}|Open here.>'.format( message = "<!channel|@channel> New order for {}. Deadline in {} minutes. <{}|Open here.>".format(
order_item.location.name, remaining_minutes(order_item.stoptime), order_item.location.name,
url_for('order_bp.order', id=order_item.id, _external=True)) remaining_minutes(order_item.stoptime),
url_for("order_bp.order", id=order_item.id, _external=True),
)
webhookthread = WebhookSenderThread(message) webhookthread = WebhookSenderThread(message)
webhookthread.start() webhookthread.start()
@ -31,8 +35,8 @@ class WebhookSenderThread(Thread):
self.slack_webhook() self.slack_webhook()
def slack_webhook(self): def slack_webhook(self):
js = json.dumps({'text': self.message}) js = json.dumps({"text": self.message})
url = app.config['SLACK_WEBHOOK'] url = app.config["SLACK_WEBHOOK"]
if len(url) > 0: if len(url) > 0:
requests.post(url, data=js) requests.post(url, data=js)
else: else:

View file

@ -2,5 +2,5 @@ def euro_string(value):
""" """
Convert cents to string formatted euro Convert cents to string formatted euro
""" """
result = '{:.2f}'.format(round(value / 100, 2)) result = "{:.2f}".format(round(value / 100, 2))
return result return result

View file

@ -3,26 +3,28 @@ from flask import current_app as app
from flask import url_for from flask import url_for
from flask_login import login_required from flask_login import login_required
debug_bp = Blueprint('debug_bp', __name__) debug_bp = Blueprint("debug_bp", __name__)
@debug_bp.route('/routes') @debug_bp.route("/routes")
@login_required @login_required
def list_routes(): def list_routes():
import urllib import urllib
output = [] output = []
for rule in app.url_map.iter_rules(): for rule in app.url_map.iter_rules():
options = {} options = {}
for arg in rule.arguments: for arg in rule.arguments:
options[arg] = "[{0}]".format(arg) options[arg] = "[{0}]".format(arg)
print(rule.endpoint) print(rule.endpoint)
methods = ','.join(rule.methods) methods = ",".join(rule.methods)
url = url_for(rule.endpoint, **options) url = url_for(rule.endpoint, **options)
line = urllib.parse.unquote("{:50s} {:20s} {}".format( line = urllib.parse.unquote(
rule.endpoint, methods, url)) "{:50s} {:20s} {}".format(rule.endpoint, methods, url)
)
output.append(line) output.append(line)
string = '' string = ""
for line in sorted(output): for line in sorted(output):
string += line + "<br/>" string += line + "<br/>"

View file

@ -7,61 +7,67 @@ from flask import render_template, send_from_directory, url_for
from flask_login import login_required from flask_login import login_required
from models import Location, Order from models import Location, Order
# import views # import views
from views.order import get_orders from views.order import get_orders
general_bp = Blueprint('general_bp', __name__) general_bp = Blueprint("general_bp", __name__)
@general_bp.route('/') @general_bp.route("/")
def home(): def home():
prev_day = datetime.now() - timedelta(days=1) prev_day = datetime.now() - timedelta(days=1)
recently_closed = get_orders( recently_closed = get_orders(
((Order.stoptime > prev_day) & (Order.stoptime < datetime.now()))) ((Order.stoptime > prev_day) & (Order.stoptime < datetime.now()))
return render_template('home.html', )
orders=get_orders(), return render_template(
recently_closed=recently_closed) "home.html", orders=get_orders(), recently_closed=recently_closed
)
@general_bp.route('/map', defaults={'id': None}) @general_bp.route("/map", defaults={"id": None})
@general_bp.route('/map/<int:id>') @general_bp.route("/map/<int:id>")
def map(id): def map(id):
locs = Location.query.order_by('name') locs = Location.query.order_by("name")
return render_template('maps.html', locations=locs) return render_template("maps.html", locations=locs)
@general_bp.route('/location') @general_bp.route("/location")
def locations(): def locations():
locs = Location.query.order_by('name') locs = Location.query.order_by("name")
return render_template('locations.html', locations=locs) return render_template("locations.html", locations=locs)
@general_bp.route('/location/<int:id>') @general_bp.route("/location/<int:id>")
def location(id): def location(id):
loc = Location.query.filter(Location.id == id).first() loc = Location.query.filter(Location.id == id).first()
if loc is None: if loc is None:
abort(404) abort(404)
return render_template('location.html', location=loc, title=loc.name) return render_template("location.html", location=loc, title=loc.name)
@general_bp.route('/about/') @general_bp.route("/about/")
def about(): def about():
return render_template('about.html') return render_template("about.html")
@general_bp.route('/profile/') @general_bp.route("/profile/")
@login_required @login_required
def profile(): def profile():
return render_template('profile.html') return render_template("profile.html")
@general_bp.route('/favicon.ico') @general_bp.route("/favicon.ico")
def favicon(): def favicon():
if len(get_orders((Order.stoptime > datetime.now()))) == 0: if len(get_orders((Order.stoptime > datetime.now()))) == 0:
return send_from_directory(os.path.join(app.root_path, 'static'), return send_from_directory(
'favicon.ico', os.path.join(app.root_path, "static"),
mimetype='image/x-icon') "favicon.ico",
mimetype="image/x-icon",
)
else: else:
return send_from_directory(os.path.join(app.root_path, 'static'), return send_from_directory(
'favicon_orange.ico', os.path.join(app.root_path, "static"),
mimetype='image/x-icon') "favicon_orange.ico",
mimetype="image/x-icon",
)

View file

@ -2,29 +2,37 @@ import random
from datetime import datetime from datetime import datetime
# from flask import current_app as app # from flask import current_app as app
from flask import (Blueprint, abort, flash, redirect, render_template, request, from flask import (
session, url_for) Blueprint,
abort,
flash,
redirect,
render_template,
request,
session,
url_for,
)
from flask_login import current_user, login_required from flask_login import current_user, login_required
from forms import AnonOrderItemForm, OrderForm, OrderItemForm from forms import AnonOrderItemForm, OrderForm, OrderItemForm
from models import Order, OrderItem, User, db from models import Order, OrderItem, User, db
from notification import post_order_to_webhook from notification import post_order_to_webhook
order_bp = Blueprint('order_bp', 'order') order_bp = Blueprint("order_bp", "order")
@order_bp.route('/') @order_bp.route("/")
def orders(form=None): def orders(form=None):
if form is None and not current_user.is_anonymous(): if form is None and not current_user.is_anonymous():
form = OrderForm() form = OrderForm()
location_id = request.args.get('location_id') location_id = request.args.get("location_id")
form.location_id.default = location_id form.location_id.default = location_id
form.process() form.process()
form.populate() form.populate()
return render_template('orders.html', orders=get_orders(), form=form) return render_template("orders.html", orders=get_orders(), form=form)
@order_bp.route('/create', methods=['POST']) @order_bp.route("/create", methods=["POST"])
@login_required @login_required
def order_create(): def order_create():
orderForm = OrderForm() orderForm = OrderForm()
@ -35,50 +43,46 @@ def order_create():
db.session.add(order) db.session.add(order)
db.session.commit() db.session.commit()
post_order_to_webhook(order) post_order_to_webhook(order)
return redirect(url_for('order_bp.order', id=order.id)) return redirect(url_for("order_bp.order", id=order.id))
return orders(form=orderForm) return orders(form=orderForm)
@order_bp.route('/<id>') @order_bp.route("/<id>")
def order(id, form=None): def order(id, form=None):
order = Order.query.filter(Order.id == id).first() order = Order.query.filter(Order.id == id).first()
if order is None: if order is None:
abort(404) abort(404)
if current_user.is_anonymous() and not order.public: if current_user.is_anonymous() and not order.public:
flash('Please login to see this order.', 'info') flash("Please login to see this order.", "info")
abort(401) abort(401)
if form is None: if form is None:
form = AnonOrderItemForm() if current_user.is_anonymous( form = AnonOrderItemForm() if current_user.is_anonymous() else OrderItemForm()
) else OrderItemForm()
form.populate(order.location) form.populate(order.location)
if order.stoptime and order.stoptime < datetime.now(): if order.stoptime and order.stoptime < datetime.now():
form = None form = None
total_price = sum([o.product.price for o in order.items]) total_price = sum([o.product.price for o in order.items])
debts = sum([o.product.price for o in order.items if not o.paid]) debts = sum([o.product.price for o in order.items if not o.paid])
return render_template('order.html', return render_template(
order=order, "order.html", order=order, form=form, total_price=total_price, debts=debts
form=form, )
total_price=total_price,
debts=debts)
@order_bp.route('/<id>/items') @order_bp.route("/<id>/items")
def items_showcase(id, form=None): def items_showcase(id, form=None):
order = Order.query.filter(Order.id == id).first() order = Order.query.filter(Order.id == id).first()
if order is None: if order is None:
abort(404) abort(404)
if current_user.is_anonymous() and not order.public: if current_user.is_anonymous() and not order.public:
flash('Please login to see this order.', 'info') flash("Please login to see this order.", "info")
abort(401) abort(401)
return render_template('order_items.html', order=order) return render_template("order_items.html", order=order)
@order_bp.route('/<id>/edit', methods=['GET', 'POST']) @order_bp.route("/<id>/edit", methods=["GET", "POST"])
@login_required @login_required
def order_edit(id): def order_edit(id):
order = Order.query.filter(Order.id == id).first() order = Order.query.filter(Order.id == id).first()
if current_user.id is not order.courrier_id and not current_user.is_admin( if current_user.id is not order.courrier_id and not current_user.is_admin():
):
abort(401) abort(401)
if order is None: if order is None:
abort(404) abort(404)
@ -87,11 +91,11 @@ def order_edit(id):
if orderForm.validate_on_submit(): if orderForm.validate_on_submit():
orderForm.populate_obj(order) orderForm.populate_obj(order)
db.session.commit() db.session.commit()
return redirect(url_for('order_bp.order', id=order.id)) return redirect(url_for("order_bp.order", id=order.id))
return render_template('order_edit.html', form=orderForm, order_id=id) return render_template("order_edit.html", form=orderForm, order_id=id)
@order_bp.route('/<id>/create', methods=['POST']) @order_bp.route("/<id>/create", methods=["POST"])
def order_item_create(id): def order_item_create(id):
current_order = Order.query.filter(Order.id == id).first() current_order = Order.query.filter(Order.id == id).first()
if current_order is None: if current_order is None:
@ -99,10 +103,9 @@ def order_item_create(id):
if current_order.stoptime and current_order.stoptime < datetime.now(): if current_order.stoptime and current_order.stoptime < datetime.now():
abort(404) abort(404)
if current_user.is_anonymous() and not current_order.public: if current_user.is_anonymous() and not current_order.public:
flash('Please login to see this order.', 'info') flash("Please login to see this order.", "info")
abort(401) abort(401)
form = AnonOrderItemForm() if current_user.is_anonymous( form = AnonOrderItemForm() if current_user.is_anonymous() else OrderItemForm()
) else OrderItemForm()
form.populate(current_order.location) form.populate(current_order.location)
if form.validate_on_submit(): if form.validate_on_submit():
item = OrderItem() item = OrderItem()
@ -111,15 +114,15 @@ def order_item_create(id):
if not current_user.is_anonymous(): if not current_user.is_anonymous():
item.user_id = current_user.id item.user_id = current_user.id
else: else:
session['anon_name'] = item.name session["anon_name"] = item.name
db.session.add(item) db.session.add(item)
db.session.commit() db.session.commit()
flash('Ordered %s' % (item.product.name), 'success') flash("Ordered %s" % (item.product.name), "success")
return redirect(url_for('order_bp.order', id=id)) return redirect(url_for("order_bp.order", id=id))
return order(id, form=form) return order(id, form=form)
@order_bp.route('/<order_id>/<item_id>/paid') @order_bp.route("/<order_id>/<item_id>/paid")
@login_required @login_required
def item_paid(order_id, item_id): def item_paid(order_id, item_id):
item = OrderItem.query.filter(OrderItem.id == item_id).first() item = OrderItem.query.filter(OrderItem.id == item_id).first()
@ -127,23 +130,24 @@ def item_paid(order_id, item_id):
if item.order.courrier_id == id or current_user.admin: if item.order.courrier_id == id or current_user.admin:
item.paid = True item.paid = True
db.session.commit() db.session.commit()
flash('Paid %s by %s' % (item.product.name, item.get_name()), flash("Paid %s by %s" % (item.product.name, item.get_name()), "success")
'success') return redirect(url_for("order_bp.order", id=order_id))
return redirect(url_for('order_bp.order', id=order_id))
abort(404) abort(404)
@order_bp.route('/<order_id>/<user_name>/user_paid') @order_bp.route("/<order_id>/<user_name>/user_paid")
@login_required @login_required
def items_user_paid(order_id, user_name): def items_user_paid(order_id, user_name):
user = User.query.filter(User.username == user_name).first() user = User.query.filter(User.username == user_name).first()
items = [] items = []
if user: if user:
items = OrderItem.query.filter((OrderItem.user_id == user.id) items = OrderItem.query.filter(
& (OrderItem.order_id == order_id)) (OrderItem.user_id == user.id) & (OrderItem.order_id == order_id)
)
else: else:
items = OrderItem.query.filter((OrderItem.name == user_name) items = OrderItem.query.filter(
& (OrderItem.order_id == order_id)) (OrderItem.name == user_name) & (OrderItem.order_id == order_id)
)
current_order = Order.query.filter(Order.id == order_id).first() current_order = Order.query.filter(Order.id == order_id).first()
for item in items: for item in items:
print(item) print(item)
@ -151,29 +155,28 @@ def items_user_paid(order_id, user_name):
for item in items: for item in items:
item.paid = True item.paid = True
db.session.commit() db.session.commit()
flash('Paid %d items for %s' % (items.count(), item.get_name()), flash("Paid %d items for %s" % (items.count(), item.get_name()), "success")
'success') return redirect(url_for("order_bp.order", id=order_id))
return redirect(url_for('order_bp.order', id=order_id))
abort(404) abort(404)
@order_bp.route('/<order_id>/<item_id>/delete') @order_bp.route("/<order_id>/<item_id>/delete")
def delete_item(order_id, item_id): def delete_item(order_id, item_id):
item = OrderItem.query.filter(OrderItem.id == item_id).first() item = OrderItem.query.filter(OrderItem.id == item_id).first()
id = None id = None
if not current_user.is_anonymous(): if not current_user.is_anonymous():
print("%s tries to delete orders" % (current_user.username)) print("%s tries to delete orders" % (current_user.username))
id = current_user.id id = current_user.id
if item.can_delete(order_id, id, session.get('anon_name', '')): if item.can_delete(order_id, id, session.get("anon_name", "")):
product_name = item.product.name product_name = item.product.name
db.session.delete(item) db.session.delete(item)
db.session.commit() db.session.commit()
flash('Deleted %s' % (product_name), 'success') flash("Deleted %s" % (product_name), "success")
return redirect(url_for('order_bp.order', id=order_id)) return redirect(url_for("order_bp.order", id=order_id))
abort(404) abort(404)
@order_bp.route('/<id>/volunteer') @order_bp.route("/<id>/volunteer")
@login_required @login_required
def volunteer(id): def volunteer(id):
order = Order.query.filter(Order.id == id).first() order = Order.query.filter(Order.id == id).first()
@ -185,17 +188,18 @@ def volunteer(id):
flash("Thank you for volunteering!") flash("Thank you for volunteering!")
else: else:
flash("Volunteering not possible!") flash("Volunteering not possible!")
return redirect(url_for('order_bp.order', id=id)) return redirect(url_for("order_bp.order", id=id))
@order_bp.route('/<id>/close') @order_bp.route("/<id>/close")
@login_required @login_required
def close_order(id): def close_order(id):
order = Order.query.filter(Order.id == id).first() order = Order.query.filter(Order.id == id).first()
if order is None: if order is None:
abort(404) abort(404)
if (current_user.id == order.courrier_id or current_user.is_admin()) \ if (current_user.id == order.courrier_id or current_user.is_admin()) and (
and (order.stoptime is None or (order.stoptime > datetime.now())): order.stoptime is None or (order.stoptime > datetime.now())
):
order.stoptime = datetime.now() order.stoptime = datetime.now()
if order.courrier_id == 0 or order.courrier_id is None: if order.courrier_id == 0 or order.courrier_id is None:
courrier = select_user(order.items) courrier = select_user(order.items)
@ -203,7 +207,7 @@ def close_order(id):
if courrier is not None: if courrier is not None:
order.courrier_id = courrier.id order.courrier_id = courrier.id
db.session.commit() db.session.commit()
return redirect(url_for('order_bp.order', id=id)) return redirect(url_for("order_bp.order", id=id))
def select_user(items): def select_user(items):
@ -227,12 +231,11 @@ def select_user(items):
def get_orders(expression=None): def get_orders(expression=None):
orders = [] orders = []
if expression is None: if expression is None:
expression = ((datetime.now() > Order.starttime) & expression = (datetime.now() > Order.starttime) & (
(Order.stoptime > datetime.now()) | Order.stoptime > datetime.now()
(Order.stoptime == None)) ) | (Order.stoptime == None)
if not current_user.is_anonymous(): if not current_user.is_anonymous():
orders = Order.query.filter(expression).all() orders = Order.query.filter(expression).all()
else: else:
orders = Order.query.filter( orders = Order.query.filter((expression & (Order.public == True))).all()
(expression & (Order.public == True))).all()
return orders return orders

View file

@ -4,18 +4,18 @@ from flask import render_template
from fatmodels import FatLocation, FatOrder, FatOrderItem, FatProduct, FatUser from fatmodels import FatLocation, FatOrder, FatOrderItem, FatProduct, FatUser
stats_blueprint = Blueprint('stats_blueprint', __name__) stats_blueprint = Blueprint("stats_blueprint", __name__)
@stats_blueprint.route('/') @stats_blueprint.route("/")
def stats(): def stats():
data = { data = {
'amount': { "amount": {
'orders': FatOrder.amount(), "orders": FatOrder.amount(),
'locations': FatLocation.amount(), "locations": FatLocation.amount(),
'users': FatUser.amount(), "users": FatUser.amount(),
'orderitems': FatOrderItem.amount(), "orderitems": FatOrderItem.amount(),
'products': FatProduct.amount(), "products": FatProduct.amount(),
} }
} }
return render_template('stats.html', data=data) return render_template("stats.html", data=data)

View file

@ -1,5 +1,4 @@
from flask import (current_app, flash, redirect, request, session, from flask import current_app, flash, redirect, request, session, url_for, Blueprint
url_for, Blueprint)
from flask_login import login_user from flask_login import login_user
from flask_oauthlib.client import OAuthException, OAuth from flask_oauthlib.client import OAuthException, OAuth
@ -10,21 +9,24 @@ oauth_bp = Blueprint("oauth_bp", __name__)
def zeus_login(): def zeus_login():
return current_app.zeus.authorize( return current_app.zeus.authorize(
callback=url_for('oauth_bp.authorized', _external=True)) callback=url_for("oauth_bp.authorized", _external=True)
)
@oauth_bp.route('/login/zeus/authorized') @oauth_bp.route("/login/zeus/authorized")
def authorized(): def authorized():
resp = current_app.zeus.authorized_response() resp = current_app.zeus.authorized_response()
if resp is None: if resp is None:
return 'Access denied: reason=%s error=%s' % ( return "Access denied: reason=%s error=%s" % (
request.args['error'], request.args['error_description']) request.args["error"],
request.args["error_description"],
)
if isinstance(resp, OAuthException): if isinstance(resp, OAuthException):
return 'Access denied: %s' % resp.message + '<br>' + str(resp.data) return "Access denied: %s" % resp.message + "<br>" + str(resp.data)
session['zeus_token'] = (resp['access_token'], '') session["zeus_token"] = (resp["access_token"], "")
me = current_app.zeus.get('current_user/') me = current_app.zeus.get("current_user/")
username = me.data.get('username', '').lower() username = me.data.get("username", "").lower()
user = User.query.filter_by(username=username).first() user = User.query.filter_by(username=username).first()
if len(username) > 0 and user: if len(username) > 0 and user:
@ -36,22 +38,24 @@ def authorized():
flash("You're not allowed to enter, please contact a system administrator") flash("You're not allowed to enter, please contact a system administrator")
return redirect(url_for("general_bp.home")) return redirect(url_for("general_bp.home"))
def init_oauth(app): def init_oauth(app):
oauth = OAuth(app) oauth = OAuth(app)
zeus = oauth.remote_app( zeus = oauth.remote_app(
'zeus', "zeus",
consumer_key=app.config['ZEUS_KEY'], consumer_key=app.config["ZEUS_KEY"],
consumer_secret=app.config['ZEUS_SECRET'], consumer_secret=app.config["ZEUS_SECRET"],
request_token_params={}, request_token_params={},
base_url='https://adams.ugent.be/oauth/api/', base_url="https://adams.ugent.be/oauth/api/",
access_token_method='POST', access_token_method="POST",
access_token_url='https://adams.ugent.be/oauth/oauth2/token/', access_token_url="https://adams.ugent.be/oauth/oauth2/token/",
authorize_url='https://adams.ugent.be/oauth/oauth2/authorize/') authorize_url="https://adams.ugent.be/oauth/oauth2/authorize/",
)
@zeus.tokengetter @zeus.tokengetter
def get_zeus_oauth_token(): def get_zeus_oauth_token():
return session.get('zeus_token') return session.get("zeus_token")
return zeus return zeus

View file

@ -9,3 +9,5 @@ Flask-OAuthlib
Flask-Admin Flask-Admin
Flask-Migrate Flask-Migrate
Flask-Script Flask-Script
black
pymysql

View file

@ -6,10 +6,13 @@
# #
airbrake==2.1.2 airbrake==2.1.2
alembic==1.0.8 # via flask-migrate alembic==1.0.8 # via flask-migrate
appdirs==1.4.3 # via black
attrs==19.1.0 # via black
black==19.3b0
blinker==1.4 # via flask-debugtoolbar blinker==1.4 # via flask-debugtoolbar
certifi==2019.3.9 # via requests certifi==2019.3.9 # via requests
chardet==3.0.4 # via requests chardet==3.0.4 # via requests
click==7.0 # via flask click==7.0 # via black, flask
dominate==2.3.5 # via flask-bootstrap dominate==2.3.5 # via flask-bootstrap
flask-admin==1.5.3 flask-admin==1.5.3
flask-bootstrap==3.3.7.1 flask-bootstrap==3.3.7.1
@ -27,12 +30,14 @@ jinja2==2.10.1 # via flask
mako==1.0.8 # via alembic mako==1.0.8 # via alembic
markupsafe==1.1.1 # via jinja2, mako markupsafe==1.1.1 # via jinja2, mako
oauthlib==2.1.0 # via flask-oauthlib, requests-oauthlib oauthlib==2.1.0 # via flask-oauthlib, requests-oauthlib
pymysql==0.9.3
python-dateutil==2.8.0 # via alembic python-dateutil==2.8.0 # via alembic
python-editor==1.0.4 # via alembic python-editor==1.0.4 # via alembic
requests-oauthlib==1.1.0 # via flask-oauthlib requests-oauthlib==1.1.0 # via flask-oauthlib
requests==2.21.0 # via airbrake, requests-oauthlib requests==2.21.0 # via airbrake, requests-oauthlib
six==1.12.0 # via python-dateutil six==1.12.0 # via python-dateutil
sqlalchemy==1.3.2 # via alembic, flask-sqlalchemy sqlalchemy==1.3.2 # via alembic, flask-sqlalchemy
toml==0.10.0 # via black
urllib3==1.24.2 # via requests urllib3==1.24.2 # via requests
visitor==0.1.3 # via flask-bootstrap visitor==0.1.3 # via flask-bootstrap
werkzeug==0.15.2 # via flask, flask-debugtoolbar werkzeug==0.15.2 # via flask, flask-debugtoolbar