from datetime import datetime from time import sleep import escpos.printer from flask import Flask, redirect, request, render_template, flash from flask_login import LoginManager, login_user, logout_user, login_required from pos.config import Config from pos.logging import init_logging, get_logger from pos.database import Database, User, Product, Event, Transaction, Order config = Config() debug = config.core['GENERAL'].getboolean('Debug', False) conf_db = config.core['DATABASE'] conf_printer = config.core['PRINTER'] conf_flask = config.core['FLASK'] init_logging(config.logging) log = get_logger('web') printer = escpos.printer.Network( conf_printer['Host'], port=conf_printer.getint('Port'), timeout=15) db = Database(**conf_db) app = Flask(__name__) app.config.update( debug=debug, SECRET_KEY=conf_flask['SECRET_KEY'] ) login_manager = LoginManager() login_manager.init_app(app) login_manager.login_view = 'login' login_manager.login_message_category = 'error' @login_manager.user_loader def load_user(uid): user = None with db.get_session() as session: user = session.query(User).get(uid) return user @app.route('/') def home(): return redirect('/sell') @app.route('/login', methods=['GET']) def login_page(): return render_template('login.html', title='Login') @app.route('/login', methods=['POST']) def login(): username = request.form['username'] password = request.form['password'] if not all([username, password]): flash("Fill all fields.", 'error') return login_page(), 400 with db.get_session() as session: user = session.query(User)\ .filter(User.username == username)\ .filter(User.is_active == 1)\ .one_or_none() if user is None: flash("User not found.", 'error') return login_page(), 400 if user.password == password: login_user(user) session.add(user) user.is_authenticated = True flash("Succesfully logged in.", 'success') return redirect('/') else: flash("Wrong password.", 'error') return login_page(), 400 @app.route('/logout') def logout(): logout_user() return redirect('/') def get_products(session): return session.query(Product)\ .filter(Product.is_active == 1)\ .order_by(Product.sort.asc())\ .all() def get_event(session): return session.query(Event)\ .filter(Event.starts_at < datetime.now())\ .filter((Event.ends_at.is_(None)) | (Event.ends_at > datetime.now()))\ .one_or_none() @app.route('/sell', methods=['GET']) @login_required def sell_page(): with db.get_session() as session: products = get_products(session) event = get_event(session) return render_template('sell.html', title='Sell', event=event, products=products) def print_orders(transaction, cat, orders): printer.open() printer.set(align='CENTER') printer.image('static/img/macao-logo-printer.png', impl='bitImageColumn') printer.set(align='CENTER', text_type='B') printer.text(transaction.event.name.upper()) printer.text("\n\n") for o in orders: printer.set(align='LEFT', width=2, height=2) printer.text("{} x {}".format(o.quantity, o.product.name.upper())) printer.text("\n") printer.text("\n") printer.set(align='RIGHT') printer.text("{} #{}-{}-{}" .format(datetime.strftime(transaction.created_at, "%Y-%m-%d %H:%M"), transaction.event.uid, transaction.uid, cat)) printer.cut() printer.close() sleep(0.7) def print_transaction(transaction): categorized_orders = {} for o in transaction.orders: uid = o.product.category_uid if not categorized_orders.get(uid, False): categorized_orders[uid] = [] categorized_orders[uid].append(o) for cat, orders in categorized_orders.items(): print_orders(transaction, cat, orders) @app.route('/sell', methods=['POST']) @login_required def sell(): with db.get_session() as session: event = get_event(session) if event is None: flash("Can't perform order without an ongoing event!", 'error') return sell_page() quantities = request.form.values() if not any(int(qty) > 0 for qty in quantities): flash("Can't perform empty order!", 'error') return sell_page() with db.get_session() as session: items = request.form.items() orders = [ Order(product_uid=uid, quantity=qty) for uid, qty in items if int(qty) > 0 ] transaction = Transaction(event_uid=event.uid, orders=orders) session.add(transaction) session.flush() print_transaction(transaction) flash("Success!", 'success') return sell_page() if __name__ == '__main__': app.run(host='0.0.0.0', port=8080, debug=debug)