Compare commits

...

15 Commits

Author SHA1 Message Date
545017bf2c Clean little code 2017-03-26 20:53:23 +02:00
e4d36c1b7c Add floating point support in cli.py 2017-03-26 20:44:42 +02:00
2d3bda8328 Break the borders edition. 2017-03-25 21:47:42 +01:00
2ea448d039 Add Macao logo for printer. 2017-03-25 20:22:36 +01:00
1871221f04 Include UID in ticket. 2017-03-25 02:57:22 +01:00
389ad04e19 Implement transaction printing. 2017-03-25 02:38:02 +01:00
67ae28fcac Fix query bug that prevented events with undefined end date being used. 2017-03-24 23:03:13 +01:00
8c4540e82c Fix exception raising on 'event list' command when event has no transactions. 2017-03-24 21:08:32 +01:00
6c5e5568ea Database schema change. Implement ProductCategory.
* The user can now create product categories with the 'category add' command.
* The user can now add products to categories with the
  'product add --category INT' command.
2017-03-24 21:04:10 +01:00
9968cd2b8b Database schema change. Minor database refactoring. 2017-03-24 19:42:21 +01:00
5db877dc4c Minor cli.py refactoring. 2017-03-24 19:39:05 +01:00
c07c19ca32 Database schema change and new UI feature. The user can now rearrange the products.
* Product has a new 'order' column.
* The user can now specify the sort order at product creation time with the
  'product add --sort INT' command.
* The user can now rearrange the products with the 'products set --sort INT'
  comand.
* The user can now show a sorted list of products in cli.py with the
  'product list --sort' command.
2017-03-24 19:23:37 +01:00
10bd8a1660 Fix typos in cli.py. 2017-03-24 18:56:06 +01:00
e2badf6b53 Implement 'user set' command in cli.py. 2017-03-24 15:54:08 +01:00
a29ec236f6 Implement new features for cly.py 'event' command.
* The user can now create a new event with a not defined end date.
* The user can now edit the name and the start and end date of a given event.
* The software can now check if the event the user is creating or editing
  is overlapping another event already present in the database.
* The software will allow the shortcut keywords 'now' and 'none' in the
  'event set --end' command.
2017-03-24 15:08:28 +01:00
11 changed files with 427 additions and 115 deletions

View File

@ -58,12 +58,12 @@ python3 cli.py user add username password
Add some products with: Add some products with:
``` ```
python3 cli.py product add "Birra media" 300 python3 cli.py product add "Birra media" 3
python3 cli.py product add "Birra grande" 400 python3 cli.py product add "Birra grande" 4
python3 cli.py product add "Cocktail" 500 python3 cli.py product add "Cocktail" 5
python3 cli.py product add "Vino" 400 python3 cli.py product add "Vino" 4
python3 cli.py product add "Amaro" 200 python3 cli.py product add "Amaro" 2
python3 cli.py product add "Acqua" 100 python3 cli.py product add "Acqua" 0.5
``` ```
And finally add and event you can play with: And finally add and event you can play with:

255
cli.py
View File

@ -5,7 +5,8 @@ from datetime import datetime
from pos.config import Config from pos.config import Config
from pos.logging import init_logging, get_logger from pos.logging import init_logging, get_logger
from pos.database import Database, User, Event, Product, Transaction from pos.database import Database, User, Event, ProductCategory, Product,\
Transaction
config = Config() config = Config()
conf_db = config.core['DATABASE'] conf_db = config.core['DATABASE']
@ -22,7 +23,10 @@ def get_total(transaction):
def get_income(event): def get_income(event):
if event.transactions:
return sum(get_total(t) for t in event.transactions) return sum(get_total(t) for t in event.transactions)
else:
return 0
@click.group() @click.group()
@ -30,6 +34,14 @@ def cli():
pass pass
@cli.command('initdb')
def initdb():
with db.get_session() as session:
categories = session.query(ProductCategory).count()
if not categories:
session.add(ProductCategory(name='Default'))
@cli.group('user') @cli.group('user')
def user(): def user():
pass pass
@ -49,7 +61,7 @@ def user_add(username, password):
user = User(username=username, password=password) user = User(username=username, password=password)
with db.get_session() as session: with db.get_session() as session:
session.add(user) session.add(user)
print("User succesfully added.") print("User successfully added.")
@user.command('list') @user.command('list')
@ -63,6 +75,26 @@ def user_list():
print("No users found.") print("No users found.")
@user.command('set')
@click.option('-p', '--password')
@click.argument('user_uid', type=click.INT)
def user_set(user_uid, password):
with db.get_session() as session:
user = session.query(User).get(user_uid)
if not user:
print("No user found with id #{}.".format(user_uid))
return
if password:
user.password = password
with db.get_session() as session:
session.add(user)
print("User successfully edited.")
@cli.group('event') @cli.group('event')
def event(): def event():
pass pass
@ -78,18 +110,48 @@ def tabulate_events(events):
return tabulate(tab, headers='firstrow') return tabulate(tab, headers='firstrow')
def get_overlapping_events(session, starts_at, ends_at):
events = session.query(Event)
if ends_at is None:
events = events.filter(Event.starts_at <= starts_at)
else:
events = events.filter(Event.ends_at >= starts_at)\
.filter(Event.starts_at <= ends_at)
return events.all()
@event.command('add') @event.command('add')
@click.argument('name') @click.argument('name')
@click.option('--start') @click.argument('starts_at')
@click.option('--end') @click.argument('ends_at', required=False)
def event_add(name, start, end): def event_add(name, starts_at, ends_at):
start = datetime.strptime(start, "%Y-%m-%d %H:%M") starts_at = datetime.strptime(starts_at, "%Y-%m-%d %H:%M")
end = datetime.strptime(end, "%Y-%m-%d %H:%M") ends_at = (datetime.strptime(ends_at, "%Y-%m-%d %H:%M")
event = Event(name=name, starts_at=start, ends_at=end) if ends_at else None)
if ends_at and starts_at >= ends_at:
print("Could now add event: specified start date ({}) "
"is past the end date ({})."
.format(starts_at.strftime("%Y-%m-%d %H:%M"),
ends_at.strftime("%Y-%m-%d %H:%M")))
return
with db.get_session() as session: with db.get_session() as session:
events = get_overlapping_events(session, starts_at, ends_at)
if events:
print("Could not add event: another event is overlapping the date "
"range you have specified.")
print(tabulate_events(events))
return
with db.get_session() as session:
event = Event(name=name, starts_at=starts_at, ends_at=ends_at)
session.add(event) session.add(event)
print("Event succesfully added.") session.flush()
print("Event successfully added.")
print(tabulate_events([event]))
@event.command('list') @event.command('list')
@ -103,32 +165,160 @@ def event_list():
print("No events found.") print("No events found.")
@event.command('set')
@click.option('-n', '--name')
@click.option('-s', '--start')
@click.option('-e', '--end')
@click.argument('event_uid')
def event_set(event_uid, name, start, end):
with db.get_session() as session:
event = session.query(Event).get(event_uid)
if not event:
print("No event found with id #{}.".format(event_uid))
return
if name:
event.name = name
if start:
starts_at = datetime.strptime(start, "%Y-%m-%d %H:%M")
if starts_at >= event.ends_at:
print("Could not edit event #{}: specified start date ({}) "
"is past the end date ({})"
.format(event.uid,
starts_at.strftime("%Y-%m-%d %H:%M"),
event.ends_at.strftime("%Y-%m-%d %H:%M")))
return
event.starts_at = starts_at
if end:
if end == 'none':
event.ends_at = None
elif end == 'now':
event.ends_at = datetime.now()
else:
ends_at = datetime.strptime(end, "%Y-%m-%d %H:%M")
if ends_at <= event.starts_at:
print("Could not edit event #{}: specified end date ({}) "
"is before the start date ({})"
.format(event.uid,
ends_at.strftime("%Y-%m-%d %H:%M"),
event.starts_at.strftime("%Y-%m-%d %H:%M")))
return
event.ends_at = datetime.strptime(end, "%Y-%m-%d %H:%M")
if event.starts_at and event.ends_at:
with db.get_session() as session:
events = get_overlapping_events(session,
event.starts_at, event.ends_at)
if events:
print("Could not edit event: another event is overlapping the "
"date range you have specified.")
print(tabulate_events(events))
return
if any([name, start, end]):
with db.get_session() as session:
session.add(event)
session.flush()
print("Event successfully edited.")
print(tabulate_events([event]))
@cli.group('category')
def category():
pass
@category.command('add')
@click.option('-s', '--sort', type=click.INT)
@click.argument('name')
def category_add(name, sort):
category = ProductCategory(name=name)
if sort:
category.sort = sort
with db.get_session() as session:
session.add(category)
print("Category successfully added.")
def tabulate_categories(categories):
tab = [["UID", "Name", "Sort", "Created at"]]
for c in categories:
tab.append([c.uid, c.name, c.sort, c.created_at])
return tabulate(tab, headers='firstrow')
@category.command('list')
@click.option('-s', '--sort', is_flag=True)
def category_list(sort):
with db.get_session() as session:
categories = session.query(ProductCategory)
if sort:
categories = categories.order_by(ProductCategory.sort.asc())
categories = categories.all()
if categories:
print(tabulate_categories(categories))
else:
print("No categories found.")
@cli.group('product') @cli.group('product')
def product(): def product():
pass pass
def tabulate_products(products): def tabulate_products(products):
tab = [["UID", "Name", "Price", "Enabled", "Created at"]] tab = [["UID", "Name", "Price", "Sort", "Category",
"Enabled", "Created at"]]
for p in products: for p in products:
tab.append([p.uid, p.name, p.price, p.is_active, p.created_at]) tab.append([p.uid, p.name, p.price, p.sort, p.category.name,
p.is_active, p.created_at])
return tabulate(tab, headers='firstrow') return tabulate(tab, headers='firstrow')
@product.command('add') @product.command('add')
@click.argument('name') @click.argument('name')
@click.argument('price') @click.argument('price', type=float)
def product_add(name, price): @click.option('-s', '--sort', type=click.INT)
@click.option('-c', '--category', type=click.INT)
def product_add(name, price, sort, category):
price = int(price * 100)
product = Product(name=name, price=price) product = Product(name=name, price=price)
if sort:
product.sort = sort
if category:
product.category_uid = category
else:
product.category_uid = 1
with db.get_session() as session: with db.get_session() as session:
session.add(product) session.add(product)
print("Product succesfully added.") print("Product successfully added.")
@product.command('list') @product.command('list')
def product_list(): @click.option('-s', '--sort', is_flag=True)
def product_list(sort):
with db.get_session() as session: with db.get_session() as session:
products = session.query(Product).all() products = session.query(Product)
if sort:
products = products.order_by(Product.sort.asc())
products = products.all()
if products: if products:
print(tabulate_products(products)) print(tabulate_products(products))
@ -136,6 +326,39 @@ def product_list():
print("No products found.") print("No products found.")
@product.command('set')
@click.option('-n', '--name')
@click.option('-p', '--price', type=click.INT)
@click.option('-s', '--sort', type=click.INT)
@click.option('-c', '--category', type=click.INT)
@click.argument('product_uid')
def product_set(product_uid, name, price, sort, category):
with db.get_session() as session:
product = session.query(Product).get(product_uid)
if not product:
print("No product found with id #{}.".format(product_uid))
return
if name:
product.name = name
if price:
product.price = price
if sort:
product.sort = sort
if category:
product.category_uid = category
if any([name, price, sort, category]):
with db.get_session() as session:
session.add(product)
print("Event successfully edited.")
print(tabulate_products([product]))
@cli.group('transaction') @cli.group('transaction')
def transaction(): def transaction():
pass pass

View File

@ -7,3 +7,7 @@ Path = pos.db
[FLASK] [FLASK]
SECRET_KEY = CHANGE_ME_NOW! SECRET_KEY = CHANGE_ME_NOW!
[PRINTER]
Host = 192.168.1.100
Post = 9100

View File

@ -11,3 +11,7 @@ Password = secret
[FLASK] [FLASK]
SECRET_KEY = CHANGE_ME_NOW! SECRET_KEY = CHANGE_ME_NOW!
[PRINTER]
Host = 192.168.1.100
Post = 9100

View File

@ -94,9 +94,9 @@ class User(Base):
uid = Column(Integer, primary_key=True) uid = Column(Integer, primary_key=True)
username = Column(String, nullable=False, unique=True) username = Column(String, nullable=False, unique=True)
password = Column(PasswordType(schemes=PASSWORD_SCHEMES), nullable=False) password = Column(PasswordType(schemes=PASSWORD_SCHEMES), nullable=False)
created_at = Column(DateTime, nullable=False, default=datetime.now)
is_active = Column(Boolean, nullable=False, server_default='1') is_active = Column(Boolean, nullable=False, server_default='1')
is_authenticated = Column(Boolean, nullable=False, server_default='0') is_authenticated = Column(Boolean, nullable=False, server_default='0')
created_at = Column(DateTime, nullable=False, default=datetime.now)
def get_id(self): def get_id(self):
return u'{}'.format(self.uid) return u'{}'.format(self.uid)
@ -106,20 +106,35 @@ class Event(Base):
__tablename__ = 'events' __tablename__ = 'events'
uid = Column(Integer, primary_key=True) uid = Column(Integer, primary_key=True)
name = Column(String, nullable=False) name = Column(String, nullable=False)
created_at = Column(DateTime, nullable=False, default=datetime.now)
starts_at = Column(DateTime, nullable=False, default=datetime.now) starts_at = Column(DateTime, nullable=False, default=datetime.now)
ends_at = Column(DateTime) ends_at = Column(DateTime)
created_at = Column(DateTime, nullable=False, default=datetime.now)
transactions = relationship('Transaction', lazy='joined') transactions = relationship('Transaction', lazy='joined')
class ProductCategory(Base):
__tablename__ = 'product_categories'
uid = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
sort = Column(Integer, nullable=False, server_default='0')
created_at = Column(DateTime, nullable=False, default=datetime.now)
products = relationship('Product', lazy='joined')
class Product(Base): class Product(Base):
__tablename__ = 'products' __tablename__ = 'products'
uid = Column(Integer, primary_key=True) uid = Column(Integer, primary_key=True)
name = Column(String, nullable=False) name = Column(String, nullable=False)
price = Column(Integer, nullable=False) price = Column(Integer, nullable=False)
created_at = Column(DateTime, nullable=False, default=datetime.now) sort = Column(Integer, nullable=False, server_default='0')
category_uid = Column(Integer, ForeignKey('product_categories.uid'),
nullable=False)
is_active = Column(Boolean, nullable=False, server_default='1') is_active = Column(Boolean, nullable=False, server_default='1')
created_at = Column(DateTime, nullable=False, default=datetime.now)
category = relationship('ProductCategory', lazy='joined')
order_entry_association = Table( order_entry_association = Table(
@ -132,8 +147,8 @@ order_entry_association = Table(
class Transaction(Base): class Transaction(Base):
__tablename__ = 'transactions' __tablename__ = 'transactions'
uid = Column(Integer, primary_key=True) uid = Column(Integer, primary_key=True)
created_at = Column(DateTime, nullable=False, default=datetime.now)
event_uid = Column(Integer, ForeignKey('events.uid'), nullable=False) event_uid = Column(Integer, ForeignKey('events.uid'), nullable=False)
created_at = Column(DateTime, nullable=False, default=datetime.now)
event = relationship('Event') event = relationship('Event')
orders = relationship('Order', lazy='joined', orders = relationship('Order', lazy='joined',

View File

@ -8,3 +8,4 @@ tabulate
PyYAML PyYAML
flask>=0.12.0 flask>=0.12.0
flask_login>=0.4.0 flask_login>=0.4.0
python-escpos

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

54
static/js/sell.js Normal file
View File

@ -0,0 +1,54 @@
function updateTotal(amount) {
total_el = document.getElementById('total')
total = parseFloat(total_el.innerText)
total += amount
total_el.innerText = total.toFixed(2)
}
function renderBasketItem(uid, name) {
return '<button id="basketitem_' + uid + '"' +
'onclick="delProduct(' + uid + ')">' +
'1 x ' + name +
'</button>'
}
function addProduct(uid) {
// This is the hidden input element inside the form. We'll use this DOM
// element to keep informations about the product, such as the name,
// the price and the value inside the 'data-' tag.
form_el = document.getElementById('prod_' + uid)
basket = document.getElementById('basket')
basket_el = document.getElementById('basketitem_' + uid)
form_el.value = parseInt(form_el.value) + 1
// If there is not a button for the given product inside the basket
// div we'll create it.
if (basket_el === null) {
basket.innerHTML += renderBasketItem(uid, form_el.dataset.name)
} else {
// Otherwise we'll just update it.
console.log(form_el.value)
new_text = form_el.value + ' x ' + form_el.dataset.name
basket_el.innerText = new_text
}
updateTotal(parseFloat(form_el.dataset.price))
}
function delProduct(uid) {
form_el = document.getElementById('prod_' + uid)
basket = document.getElementById('basket')
basket_el = document.getElementById('basketitem_' + uid)
form_el.value = parseInt(form_el.value) - 1
if (form_el.value == 0) {
basket.removeChild(basket_el)
} else {
new_text = form_el.value + ' x ' + form_el.dataset.name
basket_el.innerText = new_text
}
updateTotal(parseFloat(-form_el.dataset.price))
}

View File

@ -1,7 +1,5 @@
html { html {
width: 100%; font-size: 14px;
height: 100%;
font-size: 16px;
} }
body { body {
@ -11,7 +9,7 @@ body {
main { main {
margin: 2rem; margin: 1rem 2rem;
} }
.alert { .alert {
@ -41,12 +39,6 @@ h1 {
h2 { h2 {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
font-size: 2rem;
text-align: center;
}
h3 {
margin-bottom: 0.2rem;
font-size: 1.5rem; font-size: 1.5rem;
text-align: center; text-align: center;
} }
@ -120,8 +112,8 @@ form#login > button:hover {
#products { #products {
display: inline-block; display: inline-block;
margin: 4rem auto; margin: 0.5rem auto;
max-width: 50%; width: 60%;
} }
#products > button { #products > button {
@ -138,33 +130,38 @@ form#login > button:hover {
display: block; display: block;
} }
#basket { #summary {
display: inline-block; display: inline-block;
float: right; float: right;
margin: 4rem auto; margin: 0.5rem auto;
min-width: 30%; }
#basket {
margin: 2rem auto;
} }
#basket > button { #basket > button {
display: block; display: block;
width: 15rem; width: 20rem;
height: 3rem; height: 4rem;
margin-bottom: 0.3rem; margin-bottom: 0.3rem;
padding: 0.2rem 0.5rem; padding: 0.2rem 0.5rem;
font-size: 1.3rem; font-size: 1.5rem;
} }
#sell { #sell {
display: inline-block; margin: 1rem auto;
float: right;
margin: auto;
min-width: 30%;
} }
#sell > button { #sell > button {
display: block; display: block;
width: 15rem; width: 20rem;
height: 3rem; height: 5rem;
padding: 0.2rem 0.5rem; padding: 0.2rem 0.5rem;
font-size: 1.3rem; font-size: 2rem;
}
#sell > p {
font-size: 2rem;
margin-bottom: 0.5rem;
} }

View File

@ -1,76 +1,36 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block main %} {% block main %}
<h1>{{ title }}</h1>
{% if event %}
<h2>{{ event.name }}</h2>
<h3>{{ event.starts_at }} → {{ event.ends_at }}</h3>
{% else %}
<h2>No ongoing event!</h2>
{% endif %}
<div id="products"> <div id="products">
{% for product in products %} {% for product in products %}
<button type="button" <button type="button"
onclick="addProduct({{ product.uid }})"> onclick="addProduct({{ product.uid }})">
<span class="name">{{ product.name }}</span> <span class="name">{{ product.name }}</span>
<span class="price">{{ product.price }}</span> <span class="price">
€ {{ '{0:.02f}'.format(product.price / 100.0) }}
</span>
</button> </button>
{% endfor %} {% endfor %}
</div> </div>
<div id="basket"> <div id="summary">
</div> <div id="basket"></div>
<form id="sell" action="/sell" method="POST"> <form id="sell" action="/sell" method="POST">
{% for product in products %} {% for product in products %}
<input type="hidden" <input type="hidden"
id="prod_{{ product.uid }}" id="prod_{{ product.uid }}"
name="{{ product.uid }}" name="{{ product.uid }}"
data-name="{{ product.name }}" data-name="{{ product.name }}"
data-price="{{ product.price }}" data-price="{{ '{0:.02f}'.format(product.price / 100.0) }}"
value="0"> value="0">
{% endfor %} {% endfor %}
<p>Total: € <span id="total">0.00</span></p>
<button type="submit">Print</input> <button type="submit">Print</input>
</form> </form>
</div>
<script type="text/javascript" src="{{ url_for('static', filename='js/sell.js') }}">
<script type="text/javascript"> <script type="text/javascript">
function addProduct(uid) { {%- for product in products %}
// This is the hidden input element inside the form. We'll use this DOM document.getElementById('prod_{{ product.uid }}').value = 0
// element to keep informations about the product, such as the name, {%- endfor %}
// the price and the value inside the 'data-' tag.
form_el = document.getElementById('prod_' + uid)
basket = document.getElementById('basket')
basket_el = document.getElementById('basketitem_' + uid)
form_el.value = parseInt(form_el.value) + 1
// If there is not a button for the given product inside the basket
// div we'll create it.
if (basket_el === null) {
new_basket_el =
'<button id="basketitem_' + uid + '"' +
'onclick="delProduct(' + uid + ')">' +
'1 x ' + form_el.dataset.name +
'</button>'
basket.innerHTML += new_basket_el
} else {
// Otherwise we'll just update it.
console.log(form_el.value)
new_text = form_el.value + ' x ' + form_el.dataset.name
basket_el.innerText = new_text
}
}
function delProduct(uid) {
form_el = document.getElementById('prod_' + uid)
basket = document.getElementById('basket')
basket_el = document.getElementById('basketitem_' + uid)
form_el.value = parseInt(form_el.value) - 1
if (form_el.value == 0) {
basket.removeChild(basket_el)
} else {
new_text = form_el.value + ' x ' + form_el.dataset.name
basket_el.innerText = new_text
}
}
</script> </script>
{% endblock %} {% endblock %}

62
web.py
View File

@ -1,4 +1,6 @@
from datetime import datetime from datetime import datetime
from time import sleep
import escpos.printer
from flask import Flask, redirect, request, render_template, flash from flask import Flask, redirect, request, render_template, flash
from flask_login import LoginManager, login_user, logout_user, login_required from flask_login import LoginManager, login_user, logout_user, login_required
@ -11,11 +13,20 @@ from pos.database import Database, User, Product, Event, Transaction, Order
config = Config() config = Config()
debug = config.core['GENERAL'].getboolean('Debug', False) debug = config.core['GENERAL'].getboolean('Debug', False)
conf_db = config.core['DATABASE'] conf_db = config.core['DATABASE']
conf_printer = config.core['PRINTER']
conf_flask = config.core['FLASK'] conf_flask = config.core['FLASK']
init_logging(config.logging) init_logging(config.logging)
log = get_logger('web') 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 = Flask(__name__)
app.config.update( app.config.update(
debug=debug, debug=debug,
@ -27,8 +38,6 @@ login_manager.init_app(app)
login_manager.login_view = 'login' login_manager.login_view = 'login'
login_manager.login_message_category = 'error' login_manager.login_message_category = 'error'
db = Database(**conf_db)
@login_manager.user_loader @login_manager.user_loader
def load_user(uid): def load_user(uid):
@ -87,14 +96,15 @@ def logout():
def get_products(session): def get_products(session):
return session.query(Product)\ return session.query(Product)\
.filter(Product.is_active == 1)\ .filter(Product.is_active == 1)\
.order_by(Product.sort.asc())\
.all() .all()
def get_event(session): def get_event(session):
return session.query(Event)\ return session.query(Event)\
.filter(Event.starts_at < datetime.now())\ .filter(Event.starts_at < datetime.now())\
.filter((Event.ends_at > datetime.now()) | .filter((Event.ends_at.is_(None))
(Event.ends_at is None))\ | (Event.ends_at > datetime.now()))\
.one_or_none() .one_or_none()
@ -109,6 +119,48 @@ def sell_page():
title='Sell', event=event, products=products) 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']) @app.route('/sell', methods=['POST'])
@login_required @login_required
def sell(): def sell():
@ -134,6 +186,8 @@ def sell():
transaction = Transaction(event_uid=event.uid, orders=orders) transaction = Transaction(event_uid=event.uid, orders=orders)
session.add(transaction) session.add(transaction)
session.flush()
print_transaction(transaction)
flash("Success!", 'success') flash("Success!", 'success')
return sell_page() return sell_page()