From 0b49709d1b8f42a1fdf53e45b95fd3e05155b65d Mon Sep 17 00:00:00 2001 From: Alexander Kaschta Date: Thu, 29 Feb 2024 01:11:49 +0100 Subject: [PATCH] UPD: Improved purchase verification - Favorites can only be visible items, that are not recharge items --- README.md | 2 + nanposweb/__init__.py | 2 + nanposweb/main.py | 37 +++++++++++--- nanposweb/templates/index.html | 91 +++++++++++++++++++++++++-------- nanposweb/templates/verify.html | 54 +++++++++++++++++++ pyproject.toml | 2 +- 6 files changed, 158 insertions(+), 30 deletions(-) create mode 100644 nanposweb/templates/verify.html diff --git a/README.md b/README.md index eaaf62b..7c10dcb 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,8 @@ SQLALCHEMY_DATABASE_URI='postgresql://nanpos:nanpos@localhost:5432/nanpos', TERMINAL_LOGOUT_TIMEOUT=30, # logout timeout for Terminal mode in seconds, set to none to disable QUICK_CANCEL_SEC=60, # Second-Limit for canceling a revenue PURCHASE_COOLDOWN=0.0, # Cooldown between multiple purchases in seconds. If zero, there's no cooldown. +VERIFY_FREE_PURCHASES=False, # Option, whether purchases with no cost must be verified +VERIFY_FREE_PURCHASES_NOTE=None, # Optional text, that is displayed during confirmation BANK_DATA=None, # Display bank data FAVORITES_DISPLAY=3, # Amount of favorite products which should get highlighted FAVORITES_DAYS=100, # Timespan for calculation of favorite products in Days diff --git a/nanposweb/__init__.py b/nanposweb/__init__.py index 0c52828..22a5b61 100644 --- a/nanposweb/__init__.py +++ b/nanposweb/__init__.py @@ -26,6 +26,8 @@ def create_app(test_config=None): TERMINAL_LOGOUT_TIMEOUT=30, # logout timeout for Terminal mode in seconds, set to none to disable QUICK_CANCEL_SEC=60, # Second-Limit for canceling a revenue PURCHASE_COOLDOWN=0.0, # Cooldown between multiple purchases in seconds. If zero, there's no cooldown. + VERIFY_FREE_PURCHASES=False, # Option, whether purchases with no cost must be verified + VERIFY_FREE_PURCHASES_NOTE=None, # Optional text, that is displayed during confirmation BANK_DATA=None, FAVORITES_DISPLAY=3, # Amount of favorite products which should get highlighted FAVORITES_DAYS=100, # Timespan for calculation of favorite products in Days diff --git a/nanposweb/main.py b/nanposweb/main.py index 91a5977..10e23ac 100644 --- a/nanposweb/main.py +++ b/nanposweb/main.py @@ -40,9 +40,10 @@ def index(): last_revenue = False most_buyed_timestamp = datetime.datetime.now() - datetime.timedelta(days=current_app.config['FAVORITES_DAYS']) - most_buyed_query = db.select(Product, db.func.count(Revenue.product).label('CTR')).join(Product).where( - Revenue.product is not None).where(Revenue.user == user_id).where( - Revenue.date >= most_buyed_timestamp).group_by(Product.id).order_by(db.desc('CTR')) + most_buyed_query = (db.select(Product, db.func.count(Revenue.product).label('CTR')).join(Product) + .where(Revenue.product is not None).where(Revenue.user == user_id) + .where(Revenue.date >= most_buyed_timestamp).where(Product.visible) + .where(Product.price >= 0).group_by(Product.id).order_by(db.desc('CTR'))) most_buyed = db.session.execute(most_buyed_query).all() favorites = [f[0] for f in most_buyed[:current_app.config.get('FAVORITES_DISPLAY')]] @@ -116,10 +117,7 @@ def index_post(): if current_app.config.get("SHOW_BALANCE_AND_PRICE", True): flash(f'Bought {product.name} for {format_currency(product.price)}{user_message}', category='success') else: - if product.price < 0.0: - flash("Please ensure that you have paid for the item on the other device!", category='warning') - else: - flash(f'Bought {product.name}', category='success') + flash(f'Bought {product.name}', category='success') if session.get('terminal', False): return redirect(url_for('auth.logout')) else: @@ -129,6 +127,31 @@ def index_post(): return redirect(url_for('main.index')) +@main_bp.route("/verify-purchase", methods=['GET']) +@login_required +def verify_purchase(): + if not current_app.config.get("VERIFY_FREE_PURCHASES", False): + # Redirect to the verification page + return redirect(url_for("main.index")) + if request.args.get('product') is None: + # Redirect to the verification page + return redirect(url_for("main.index")) + + user_id = get_user_id() + balance = get_balance(user_id) + form = MainForm() + + product_id = request.args.get('product') + if product_id is None: + return redirect(url_for('main.index')) + + product = Product.query.filter_by(id=product_id).first() + if product is None: + return redirect(url_for('main.index')) + + return render_template('verify.html', balance=balance, form=form, product=product) + + @main_bp.route('/quick-cancel', methods=['GET']) @login_required def quick_cancel(): diff --git a/nanposweb/templates/index.html b/nanposweb/templates/index.html index a285d1e..547d843 100644 --- a/nanposweb/templates/index.html +++ b/nanposweb/templates/index.html @@ -23,7 +23,7 @@ {% endif %}
-
+
User: {{ user_name }}
{% if config.SHOW_BALANCE_AND_PRICE %} @@ -53,33 +53,80 @@ {% for product in products %} {% if product.visible or view_all %}
- {% if product in favorites %} - + {% endif %} {% else %} - {% else %} - {{ macro.render_contingent(balance, product.price) }} + {% endif %} - + {% endif %} +
{% endif %} {% endfor %} diff --git a/nanposweb/templates/verify.html b/nanposweb/templates/verify.html new file mode 100644 index 0000000..e12f21c --- /dev/null +++ b/nanposweb/templates/verify.html @@ -0,0 +1,54 @@ +{% extends 'base.html' %} + +{% block pagetitle %}Verify Purchase{% endblock %} + +{% block utilbar %} + +{% endblock %} + +{% block content %} +
+ {{ form.csrf_token }} +

Verify purchase

+

Have you purchased this item, a {{ product.name }}, already at the other device?

+ +
+
+
+ No +
+
+ +
+
+
+
+ {% if config.VERIFY_FREE_PURCHASES_NOTE %} +

{{ config.VERIFY_FREE_PURCHASES_NOTE }}

+ {% endif %} + +
+{% endblock %} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 6e97923..2da57c5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ name = "nanposweb" description = "A simple point of sale system for drinks" requires-python= ">=3.9" license = {text = "MIT"} -version = "1.1.7" +version = "1.2.0" dependencies = [ "Flask==2.2.3", "Flask-SQLAlchemy",