commit
9459eb0f1e
29 changed files with 557 additions and 440 deletions
10
app/admin.py
10
app/admin.py
|
@ -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))
|
||||||
|
|
56
app/app.py
56
app/app.py
|
@ -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()
|
||||||
|
|
|
@ -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 = ""
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -1,51 +1,59 @@
|
||||||
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,
|
||||||
"Parma":750,
|
"Parma": 750,
|
||||||
"Margharita":600,
|
"Margharita": 600,
|
||||||
"Funghi":715,
|
"Funghi": 715,
|
||||||
"Mamma mia":715,
|
"Mamma mia": 715,
|
||||||
"Napoletana":750,
|
"Napoletana": 750,
|
||||||
"Exotic":750,
|
"Exotic": 750,
|
||||||
"Siciliana":750,
|
"Siciliana": 750,
|
||||||
"Michelangelo":750,
|
"Michelangelo": 750,
|
||||||
"Roma":750,
|
"Roma": 750,
|
||||||
"Torno":750,
|
"Torno": 750,
|
||||||
"Bolognese":780,
|
"Bolognese": 780,
|
||||||
"Hawai":910,
|
"Hawai": 910,
|
||||||
"Cipolla":910,
|
"Cipolla": 910,
|
||||||
"Dolce vita":910,
|
"Dolce vita": 910,
|
||||||
"Valentino":910,
|
"Valentino": 910,
|
||||||
"Vegateriana":1000,
|
"Vegateriana": 1000,
|
||||||
"La donna":1000,
|
"La donna": 1000,
|
||||||
"Tropical":1000,
|
"Tropical": 1000,
|
||||||
"Quattro Stagioni":1000,
|
"Quattro Stagioni": 1000,
|
||||||
"Romana":1000,
|
"Romana": 1000,
|
||||||
"Diabolo":1000,
|
"Diabolo": 1000,
|
||||||
"Turkish":1000,
|
"Turkish": 1000,
|
||||||
"Cesar":1000,
|
"Cesar": 1000,
|
||||||
"Calzone":1040,
|
"Calzone": 1040,
|
||||||
"Calzone Vegetariana":1040,
|
"Calzone Vegetariana": 1040,
|
||||||
"Quattro Formaggi":1040,
|
"Quattro Formaggi": 1040,
|
||||||
"Frutti di mare":1040,
|
"Frutti di mare": 1040,
|
||||||
"Gerookte ham en rucola":1040,
|
"Gerookte ham en rucola": 1040,
|
||||||
"Van de chef":1170,
|
"Van de chef": 1170,
|
||||||
"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,51 +61,57 @@ 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,
|
||||||
"Parma":575,
|
"Parma": 575,
|
||||||
"Margharita":450,
|
"Margharita": 450,
|
||||||
"Funghi":550,
|
"Funghi": 550,
|
||||||
"Mamma mia":550,
|
"Mamma mia": 550,
|
||||||
"Napoletana":575,
|
"Napoletana": 575,
|
||||||
"Exotic":575,
|
"Exotic": 575,
|
||||||
"Siciliana":575,
|
"Siciliana": 575,
|
||||||
"Michelangelo":575,
|
"Michelangelo": 575,
|
||||||
"Roma":575,
|
"Roma": 575,
|
||||||
"Torno":575,
|
"Torno": 575,
|
||||||
"Bolognese":600,
|
"Bolognese": 600,
|
||||||
"Hawai":700,
|
"Hawai": 700,
|
||||||
"Cipolla":700,
|
"Cipolla": 700,
|
||||||
"Dolce vita":700,
|
"Dolce vita": 700,
|
||||||
"Valentino":700,
|
"Valentino": 700,
|
||||||
"Vegateriana":770,
|
"Vegateriana": 770,
|
||||||
"La donna":770,
|
"La donna": 770,
|
||||||
"Tropical":770,
|
"Tropical": 770,
|
||||||
"Quattro Stagioni":770,
|
"Quattro Stagioni": 770,
|
||||||
"Romana":770,
|
"Romana": 770,
|
||||||
"Diabolo":770,
|
"Diabolo": 770,
|
||||||
"Turkish":770,
|
"Turkish": 770,
|
||||||
"Cesar":770,
|
"Cesar": 770,
|
||||||
"Calzone":800,
|
"Calzone": 800,
|
||||||
"Calzone Vegetariana":800,
|
"Calzone Vegetariana": 800,
|
||||||
"Quattro Formaggi":800,
|
"Quattro Formaggi": 800,
|
||||||
"Frutti di mare":800,
|
"Frutti di mare": 800,
|
||||||
"Gerookte ham en rucola":800,
|
"Gerookte ham en rucola": 800,
|
||||||
"Van de chef":900,
|
"Van de chef": 900,
|
||||||
"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)
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -2,13 +2,13 @@ from models import Location, Product
|
||||||
from app import db
|
from app import db
|
||||||
|
|
||||||
bickies = {
|
bickies = {
|
||||||
"Bicky Burger Original":330,
|
"Bicky Burger Original": 330,
|
||||||
"Bicky Burger":300,
|
"Bicky Burger": 300,
|
||||||
"Bicky Glenniei":330,
|
"Bicky Glenniei": 330,
|
||||||
"Bicky Capoentje":330,
|
"Bicky Capoentje": 330,
|
||||||
"Bicky Chicken":350,
|
"Bicky Chicken": 350,
|
||||||
"Bicky Fish":350,
|
"Bicky Fish": 350,
|
||||||
"Bicky Veggie":350,
|
"Bicky Veggie": 350,
|
||||||
}
|
}
|
||||||
|
|
||||||
saus = {
|
saus = {
|
||||||
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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)
|
||||||
|
|
56
app/forms.py
56
app/forms.py
|
@ -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
|
||||||
|
|
12
app/login.py
12
app/login.py
|
@ -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():
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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 ###
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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",
|
||||||
|
)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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/>"
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
|
)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
40
app/zeus.py
40
app/zeus.py
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -9,3 +9,5 @@ Flask-OAuthlib
|
||||||
Flask-Admin
|
Flask-Admin
|
||||||
Flask-Migrate
|
Flask-Migrate
|
||||||
Flask-Script
|
Flask-Script
|
||||||
|
black
|
||||||
|
pymysql
|
||||||
|
|
|
@ -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.3 # via flask, flask-debugtoolbar
|
werkzeug==0.15.3 # via flask, flask-debugtoolbar
|
||||||
|
|
Loading…
Reference in a new issue