Convert most strings to fstrings for readability
Some are kept as-is because they wouldn't be more readable, or do insanity that i cannot bother deciphering right now
This commit is contained in:
parent
068015a972
commit
d5475b834f
9
db.py
9
db.py
|
@ -32,7 +32,7 @@ class User(Base):
|
||||||
self.credit = credit
|
self.credit = credit
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<User('%s')>" % self.name
|
return f"<User('{self.name}')>"
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -63,8 +63,7 @@ class Product(Base):
|
||||||
self.hidden = hidden
|
self.hidden = hidden
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Product('%s', '%s', '%s', '%s', '%s')>" %\
|
return f"<Product('{self.name}', '{self.bar_code}', '{self.price}', '{self.stock}', '{self.hidden}')>"
|
||||||
(self.name, self.bar_code, self.price, self.stock, self.hidden)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -97,7 +96,7 @@ class PurchaseEntry(Base):
|
||||||
self.amount = amount
|
self.amount = amount
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<PurchaseEntry('%s', '%s')>" % (self.product.name, self.amount)
|
return f"<PurchaseEntry('{self.product.name}', '{self.amount}')>"
|
||||||
|
|
||||||
|
|
||||||
class Transaction(Base):
|
class Transaction(Base):
|
||||||
|
@ -141,7 +140,7 @@ class Purchase(Base):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Purchase(%d, %d, '%s')>" % (int(self.id), self.price, self.time.strftime('%c'))
|
return f"<Purchase({int(self.id):d}, {self.price:d}, '{self.time.strftime('%c')}')>"
|
||||||
|
|
||||||
def is_complete(self):
|
def is_complete(self):
|
||||||
return len(self.transactions) > 0 and len(self.entries) > 0
|
return len(self.transactions) > 0 and len(self.entries) > 0
|
||||||
|
|
28
helpers.py
28
helpers.py
|
@ -5,30 +5,30 @@ import subprocess
|
||||||
import os
|
import os
|
||||||
import signal
|
import signal
|
||||||
|
|
||||||
def search_user(string, session, ignorethisflag=None):
|
def search_user(str, session, ignorethisflag=None):
|
||||||
string = string.lower()
|
str = str.lower()
|
||||||
exact_match = session.query(User).filter(or_(User.name==string, User.card==string, User.rfid==string)).first()
|
exact_match = session.query(User).filter(or_(User.name == str, User.card == str, User.rfid == str)).first()
|
||||||
if exact_match:
|
if exact_match:
|
||||||
return exact_match
|
return exact_match
|
||||||
user_list = session.query(User).filter(or_(User.name.ilike('%'+string+'%'),
|
user_list = session.query(User).filter(or_(User.name.ilike(f'%{str}%'),
|
||||||
User.card.ilike('%'+string+'%'),
|
User.card.ilike(f'%{str}%'),
|
||||||
User.rfid.ilike('%'+string+'%'))).all()
|
User.rfid.ilike(f'%{str}%'))).all()
|
||||||
return user_list
|
return user_list
|
||||||
|
|
||||||
def search_product(string, session, find_hidden_products=True):
|
def search_product(str, session, find_hidden_products=True):
|
||||||
if find_hidden_products:
|
if find_hidden_products:
|
||||||
exact_match = session.query(Product).filter(or_(Product.bar_code==string, Product.name==string)).first()
|
exact_match = session.query(Product).filter(or_(Product.bar_code == str, Product.name == str)).first()
|
||||||
else:
|
else:
|
||||||
exact_match = session.query(Product).filter(or_(Product.bar_code==string,
|
exact_match = session.query(Product).filter(or_(Product.bar_code == str,
|
||||||
and_(Product.name==string, Product.hidden == False))).first()
|
and_(Product.name == str, Product.hidden == False))).first()
|
||||||
if exact_match:
|
if exact_match:
|
||||||
return exact_match
|
return exact_match
|
||||||
if find_hidden_products:
|
if find_hidden_products:
|
||||||
product_list = session.query(Product).filter(or_(Product.bar_code.ilike('%'+string+'%'),
|
product_list = session.query(Product).filter(or_(Product.bar_code.ilike(f'%{str}%'),
|
||||||
Product.name.ilike('%'+string+'%'))).all()
|
Product.name.ilike(f'%{str}%'))).all()
|
||||||
else:
|
else:
|
||||||
product_list = session.query(Product).filter(or_(Product.bar_code.ilike('%' + string + '%'),
|
product_list = session.query(Product).filter(or_(Product.bar_code.ilike(f'%{str}%'),
|
||||||
and_(Product.name.ilike('%' + string + '%'),
|
and_(Product.name.ilike(f'%{str}%'),
|
||||||
Product.hidden == False))).all()
|
Product.hidden == False))).all()
|
||||||
return product_list
|
return product_list
|
||||||
|
|
||||||
|
|
|
@ -6,4 +6,4 @@ session=Session()
|
||||||
slabbedasker=session.query(User).filter(User.credit<0).all()
|
slabbedasker=session.query(User).filter(User.credit<0).all()
|
||||||
|
|
||||||
for slubbert in slabbedasker:
|
for slubbert in slabbedasker:
|
||||||
print("%s, %s" % (slubbert.name, slubbert.credit))
|
print(f"{slubbert.name}, {slubbert.credit}")
|
||||||
|
|
|
@ -64,7 +64,7 @@ if __name__ == '__main__':
|
||||||
print('Interrupted.')
|
print('Interrupted.')
|
||||||
except:
|
except:
|
||||||
print('Something went wrong.')
|
print('Something went wrong.')
|
||||||
print('%s: %s' % (sys.exc_info()[0], sys.exc_info()[1]))
|
print(f'{sys.exc_info()[0]}: {sys.exc_info()[1]}')
|
||||||
if conf.show_tracebacks:
|
if conf.show_tracebacks:
|
||||||
traceback.print_tb(sys.exc_info()[2])
|
traceback.print_tb(sys.exc_info()[2])
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -41,7 +41,7 @@ much money you're due in credits for the purchase when prompted.\n'''
|
||||||
(thing, amount) = line
|
(thing, amount) = line
|
||||||
|
|
||||||
if isinstance(thing, Product):
|
if isinstance(thing, Product):
|
||||||
self.printc("%d of %s registered" % (amount, thing.name))
|
self.printc(f"{amount:d} of {thing.name} registered")
|
||||||
thing_price = self.input_int('What did you pay a piece? ', (1, 100000),
|
thing_price = self.input_int('What did you pay a piece? ', (1, 100000),
|
||||||
default=thing.price) * amount
|
default=thing.price) * amount
|
||||||
self.price += thing_price
|
self.price += thing_price
|
||||||
|
@ -65,6 +65,7 @@ much money you're due in credits for the purchase when prompted.\n'''
|
||||||
def complete_input(self):
|
def complete_input(self):
|
||||||
return bool(self.users) and len(self.products) and self.price
|
return bool(self.users) and len(self.products) and self.price
|
||||||
|
|
||||||
|
# TODO: Rewrite this madness
|
||||||
def print_info(self):
|
def print_info(self):
|
||||||
print((6 + Product.name_length) * '-')
|
print((6 + Product.name_length) * '-')
|
||||||
if self.price:
|
if self.price:
|
||||||
|
@ -72,7 +73,7 @@ much money you're due in credits for the purchase when prompted.\n'''
|
||||||
if self.users:
|
if self.users:
|
||||||
print("Users to credit:")
|
print("Users to credit:")
|
||||||
for user in self.users:
|
for user in self.users:
|
||||||
print(" %s" % str(user.name))
|
print(f" {str(user.name)}")
|
||||||
print("\n{{0:s}}{{1:>{0}s}}".format(Product.name_length-1).format("Product", "Amount"))
|
print("\n{{0:s}}{{1:>{0}s}}".format(Product.name_length-1).format("Product", "Amount"))
|
||||||
print((6 + Product.name_length) * '-')
|
print((6 + Product.name_length) * '-')
|
||||||
if len(self.products):
|
if len(self.products):
|
||||||
|
@ -94,6 +95,7 @@ much money you're due in credits for the purchase when prompted.\n'''
|
||||||
print('Did you pay a different price?')
|
print('Did you pay a different price?')
|
||||||
if self.confirm('>', default=False):
|
if self.confirm('>', default=False):
|
||||||
price = self.input_int('How much did you pay?', default=self.price)
|
price = self.input_int('How much did you pay?', default=self.price)
|
||||||
|
# TODO: Loop until we get a valid answer instead of assuming default
|
||||||
if price > self.price:
|
if price > self.price:
|
||||||
print('Illegal action, total can not be higher than your total.')
|
print('Illegal action, total can not be higher than your total.')
|
||||||
else:
|
else:
|
||||||
|
@ -109,9 +111,9 @@ much money you're due in credits for the purchase when prompted.\n'''
|
||||||
product.price = int(ceil(float(value) / (max(product.stock, 0) + self.products[product][0])))
|
product.price = int(ceil(float(value) / (max(product.stock, 0) + self.products[product][0])))
|
||||||
product.stock = max(self.products[product][0], product.stock + self.products[product][0])
|
product.stock = max(self.products[product][0], product.stock + self.products[product][0])
|
||||||
product.hidden = False
|
product.hidden = False
|
||||||
print("New stock for %s: %d" % (product.name, product.stock), \
|
print(f"New stock for {product.name}: {product.stock:d}",
|
||||||
("- New price: " + str(product.price) if old_price != product.price else ""), \
|
f"- New price: {product.price}" if old_price != product.price else "",
|
||||||
("- Removed hidden status" if old_hidden != product.hidden else ""))
|
"- Removed hidden status" if old_hidden != product.hidden else "")
|
||||||
|
|
||||||
purchase = Purchase()
|
purchase = Purchase()
|
||||||
for user in self.users:
|
for user in self.users:
|
||||||
|
@ -127,6 +129,6 @@ much money you're due in credits for the purchase when prompted.\n'''
|
||||||
print("Success! Transaction performed:")
|
print("Success! Transaction performed:")
|
||||||
# self.print_info()
|
# self.print_info()
|
||||||
for user in self.users:
|
for user in self.users:
|
||||||
print("User %s's credit is now %i" % (user.name, user.credit))
|
print(f"User {user.name}'s credit is now {user.credit:d}")
|
||||||
except sqlalchemy.exc.SQLAlchemyError as e:
|
except sqlalchemy.exc.SQLAlchemyError as e:
|
||||||
print('Could not perform transaction: %s' % e)
|
print(f'Could not perform transaction: {e}')
|
||||||
|
|
|
@ -49,7 +49,7 @@ When finished, write an empty line to confirm the purchase.\n'''
|
||||||
print("***********************************************************************")
|
print("***********************************************************************")
|
||||||
print("***********************************************************************")
|
print("***********************************************************************")
|
||||||
print("")
|
print("")
|
||||||
print("USER %s HAS LOWER CREDIT THAN %d." % (user.name, conf.low_credit_warning_limit))
|
print(f"USER {user.name} HAS LOWER CREDIT THAN {conf.low_credit_warning_limit:d}.")
|
||||||
print("THIS PURCHASE WILL CHARGE YOUR CREDIT TWICE AS MUCH.")
|
print("THIS PURCHASE WILL CHARGE YOUR CREDIT TWICE AS MUCH.")
|
||||||
print("CONSIDER PUTTING MONEY IN THE BOX TO AVOID THIS.")
|
print("CONSIDER PUTTING MONEY IN THE BOX TO AVOID THIS.")
|
||||||
print("")
|
print("")
|
||||||
|
@ -149,16 +149,16 @@ When finished, write an empty line to confirm the purchase.\n'''
|
||||||
try:
|
try:
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
except sqlalchemy.exc.SQLAlchemyError as e:
|
except sqlalchemy.exc.SQLAlchemyError as e:
|
||||||
print('Could not store purchase: %s' % e)
|
print(f'Could not store purchase: {e}')
|
||||||
else:
|
else:
|
||||||
print('Purchase stored.')
|
print('Purchase stored.')
|
||||||
self.print_purchase()
|
self.print_purchase()
|
||||||
for t in self.purchase.transactions:
|
for t in self.purchase.transactions:
|
||||||
if not t.user.is_anonymous():
|
if not t.user.is_anonymous():
|
||||||
print('User %s\'s credit is now %d kr' % (t.user.name, t.user.credit))
|
print(f"User {t.user.name}'s credit is now {t.user.credit:d} kr")
|
||||||
if t.user.credit < conf.low_credit_warning_limit:
|
if t.user.credit < conf.low_credit_warning_limit:
|
||||||
print('USER %s HAS LOWER CREDIT THAN %d, AND SHOULD CONSIDER PUTTING SOME MONEY IN THE BOX.' \
|
print(f'USER {t.user.name} HAS LOWER CREDIT THAN {conf.low_credit_warning_limit:d},',
|
||||||
% (t.user.name, conf.low_credit_warning_limit))
|
'AND SHOULD CONSIDER PUTTING SOME MONEY IN THE BOX.')
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -183,15 +183,17 @@ When finished, write an empty line to confirm the purchase.\n'''
|
||||||
string += '(empty)'
|
string += '(empty)'
|
||||||
else:
|
else:
|
||||||
string += "\n "
|
string += "\n "
|
||||||
string += '\n '.join(['%dx %s (%d kr)' % (e.amount, e.product.name, e.product.price) for e in entries])
|
string += '\n '.join([f'{e.amount:d}x {e.product.name} ({e.product.price:d} kr)' for e in entries])
|
||||||
if len(transactions) > 1:
|
if len(transactions) > 1:
|
||||||
string += '\n price per person: %d kr' % self.purchase.price_per_transaction()
|
string += f'\n price per person: {self.purchase.price_per_transaction():d} kr'
|
||||||
if any(t.penalty > 1 for t in transactions):
|
if any(t.penalty > 1 for t in transactions):
|
||||||
string += ' *(%d kr)' % (self.purchase.price_per_transaction() * 2)
|
# TODO: Use penalty multiplier instead of 2
|
||||||
|
string += f' *({self.purchase.price_per_transaction() * 2:d} kr)'
|
||||||
|
|
||||||
string += '\n total price: %d kr' % self.purchase.price
|
string += f'\n total price: {self.purchase.price:d} kr'
|
||||||
|
|
||||||
if any(t.penalty > 1 for t in transactions):
|
if any(t.penalty > 1 for t in transactions):
|
||||||
|
# TODO: Rewrite?
|
||||||
string += '\n *total with penalty: %d kr' % sum(
|
string += '\n *total with penalty: %d kr' % sum(
|
||||||
self.purchase.price_per_transaction() * t.penalty for t in transactions)
|
self.purchase.price_per_transaction() * t.penalty for t in transactions)
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,9 @@ class AddUserMenu(Menu):
|
||||||
self.session.add(user)
|
self.session.add(user)
|
||||||
try:
|
try:
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
print('User %s stored' % username)
|
print(f'User {username} stored')
|
||||||
except sqlalchemy.exc.IntegrityError as e:
|
except sqlalchemy.exc.IntegrityError as e:
|
||||||
print('Could not store user %s: %s' % (username, e))
|
print(f'Could not store user {username}: {e}')
|
||||||
self.pause()
|
self.pause()
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,27 +38,29 @@ user, then rfid (write an empty line to remove the card number or rfid).
|
||||||
def _execute(self):
|
def _execute(self):
|
||||||
self.print_header()
|
self.print_header()
|
||||||
user = self.input_user('User> ')
|
user = self.input_user('User> ')
|
||||||
self.printc('Editing user %s' % user.name)
|
self.printc(f'Editing user {user.name}')
|
||||||
card_str = '"%s"' % user.card
|
card_str = f'"{user.card}"'
|
||||||
if user.card is None:
|
if user.card is None:
|
||||||
card_str = 'empty'
|
card_str = 'empty'
|
||||||
|
# TODO: Inconsistent with other defaulted strings. Redo.
|
||||||
user.card = self.input_str('Card number (currently %s)> ' % card_str,
|
user.card = self.input_str('Card number (currently %s)> ' % card_str,
|
||||||
User.card_re, (0, 10),
|
User.card_re, (0, 10),
|
||||||
empty_string_is_none=True)
|
empty_string_is_none=True)
|
||||||
if user.card:
|
if user.card:
|
||||||
user.card = user.card.lower()
|
user.card = user.card.lower()
|
||||||
|
|
||||||
rfid_str = '"%s"' % user.rfid
|
rfid_str = f'"{user.rfid}"'
|
||||||
if user.rfid is None:
|
if user.rfid is None:
|
||||||
rfid_str = 'empty'
|
rfid_str = 'empty'
|
||||||
user.rfid = self.input_str('RFID (currently %s)> ' % rfid_str,
|
# TODO: Inconsistent with other defaulted strings. Redo.
|
||||||
|
user.rfid = self.input_str(f'RFID (currently {rfid_str})> ',
|
||||||
User.rfid_re, (0, 10),
|
User.rfid_re, (0, 10),
|
||||||
empty_string_is_none=True)
|
empty_string_is_none=True)
|
||||||
try:
|
try:
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
print('User %s stored' % user.name)
|
print(f'User {user.name} stored')
|
||||||
except sqlalchemy.exc.SQLAlchemyError as e:
|
except sqlalchemy.exc.SQLAlchemyError as e:
|
||||||
print('Could not store user %s: %s' % (user.name, e))
|
print(f'Could not store user {user.name}: {e}')
|
||||||
self.pause()
|
self.pause()
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,9 +77,9 @@ class AddProductMenu(Menu):
|
||||||
self.session.add(product)
|
self.session.add(product)
|
||||||
try:
|
try:
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
print('Product %s stored' % name)
|
print(f'Product {name} stored')
|
||||||
except sqlalchemy.exc.SQLAlchemyError as e:
|
except sqlalchemy.exc.SQLAlchemyError as e:
|
||||||
print('Could not store product %s: %s' % (name, e))
|
print(f'Could not store product {name}: {e}')
|
||||||
self.pause()
|
self.pause()
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,9 +90,9 @@ class EditProductMenu(Menu):
|
||||||
def _execute(self):
|
def _execute(self):
|
||||||
self.print_header()
|
self.print_header()
|
||||||
product = self.input_product('Product> ')
|
product = self.input_product('Product> ')
|
||||||
self.printc('Editing product %s' % product.name)
|
self.printc(f'Editing product {product.name}')
|
||||||
while True:
|
while True:
|
||||||
selector = Selector('Do what with %s?' % product.name,
|
selector = Selector(f'Do what with {product.name}?',
|
||||||
items=[('name', 'Edit name'),
|
items=[('name', 'Edit name'),
|
||||||
('price', 'Edit price'),
|
('price', 'Edit price'),
|
||||||
('barcode', 'Edit barcode'),
|
('barcode', 'Edit barcode'),
|
||||||
|
@ -98,19 +100,19 @@ class EditProductMenu(Menu):
|
||||||
('store', 'Store')])
|
('store', 'Store')])
|
||||||
what = selector.execute()
|
what = selector.execute()
|
||||||
if what == 'name':
|
if what == 'name':
|
||||||
product.name = self.input_str('Name[%s]> ' % product.name, Product.name_re, (1, product.name_length))
|
product.name = self.input_str(f'Name[{product.name}]> ', Product.name_re, (1, product.name_length))
|
||||||
elif what == 'price':
|
elif what == 'price':
|
||||||
product.price = self.input_int('Price[%s]> ' % product.price, (1, 100000))
|
product.price = self.input_int(f'Price[{product.price}]> ', (1, 100000))
|
||||||
elif what == 'barcode':
|
elif what == 'barcode':
|
||||||
product.bar_code = self.input_str('Bar code[%s]> ' % product.bar_code, Product.bar_code_re, (8, 13))
|
product.bar_code = self.input_str(f'Bar code[{product.bar_code}]> ', Product.bar_code_re, (8, 13))
|
||||||
elif what == 'hidden':
|
elif what == 'hidden':
|
||||||
product.hidden = self.confirm('Hidden[%s]' % ("Y" if product.hidden else "N"), False)
|
product.hidden = self.confirm('Hidden[%s]' % ("Y" if product.hidden else "N"), False)
|
||||||
elif what == 'store':
|
elif what == 'store':
|
||||||
try:
|
try:
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
print('Product %s stored' % product.name)
|
print(f'Product {product.name} stored')
|
||||||
except sqlalchemy.exc.SQLAlchemyError as e:
|
except sqlalchemy.exc.SQLAlchemyError as e:
|
||||||
print('Could not store product %s: %s' % (product.name, e))
|
print(f'Could not store product {product.name}: {e}')
|
||||||
self.pause()
|
self.pause()
|
||||||
return
|
return
|
||||||
elif what is None:
|
elif what is None:
|
||||||
|
@ -128,25 +130,26 @@ class AdjustStockMenu(Menu):
|
||||||
self.print_header()
|
self.print_header()
|
||||||
product = self.input_product('Product> ')
|
product = self.input_product('Product> ')
|
||||||
|
|
||||||
print('The stock of this product is: %d ' % product.stock)
|
print(f'The stock of this product is: {product.stock:d} ')
|
||||||
print('Write the number of products you have added to the stock')
|
print('Write the number of products you have added to the stock')
|
||||||
print('Alternatively, correct the stock for any mistakes')
|
print('Alternatively, correct the stock for any mistakes')
|
||||||
add_stock = self.input_int('Added stock> ', (-1000, 1000))
|
add_stock = self.input_int('Added stock> ', (-1000, 1000))
|
||||||
print('You added %d to the stock of %s' % (add_stock, product))
|
# TODO: Print something else when adding negative stock?
|
||||||
|
print(f'You added {add_stock:d} to the stock of {product}')
|
||||||
|
|
||||||
product.stock += add_stock
|
product.stock += add_stock
|
||||||
|
|
||||||
print('The stock is now %d' % product.stock)
|
print(f'The stock is now {product.stock:d}')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
print('Stock is now stored')
|
print('Stock is now stored')
|
||||||
self.pause()
|
self.pause()
|
||||||
except sqlalchemy.exc.SQLAlchemyError as e:
|
except sqlalchemy.exc.SQLAlchemyError as e:
|
||||||
print('Could not store stock: %s' % e)
|
print(f'Could not store stock: {e}')
|
||||||
self.pause()
|
self.pause()
|
||||||
return
|
return
|
||||||
print('The stock is now %d' % product.stock)
|
print(f'The stock is now {product.stock:d}')
|
||||||
|
|
||||||
|
|
||||||
class CleanupStockMenu(Menu):
|
class CleanupStockMenu(Menu):
|
||||||
|
@ -179,7 +182,7 @@ class CleanupStockMenu(Menu):
|
||||||
print('New stocks are now stored.')
|
print('New stocks are now stored.')
|
||||||
self.pause()
|
self.pause()
|
||||||
except sqlalchemy.exc.SQLAlchemyError as e:
|
except sqlalchemy.exc.SQLAlchemyError as e:
|
||||||
print('Could not store stock: %s' % e)
|
print(f'Could not store stock: {e}')
|
||||||
self.pause()
|
self.pause()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,7 @@ class Menu(object):
|
||||||
return i
|
return i
|
||||||
return self.items[i]
|
return self.items[i]
|
||||||
|
|
||||||
|
# TODO: Allow default
|
||||||
def input_str(self, prompt=None, regex=None, length_range=(None, None),
|
def input_str(self, prompt=None, regex=None, length_range=(None, None),
|
||||||
empty_string_is_none=False, timeout=None):
|
empty_string_is_none=False, timeout=None):
|
||||||
if prompt is None:
|
if prompt is None:
|
||||||
|
@ -98,7 +99,7 @@ class Menu(object):
|
||||||
if result is None or re.match(regex + '$', result):
|
if result is None or re.match(regex + '$', result):
|
||||||
return result
|
return result
|
||||||
else:
|
else:
|
||||||
print('Value must match regular expression "%s"' % regex)
|
print(f'Value must match regular expression "{regex}"')
|
||||||
if length_range != (None, None):
|
if length_range != (None, None):
|
||||||
while True:
|
while True:
|
||||||
result = self.input_str(prompt, empty_string_is_none=empty_string_is_none)
|
result = self.input_str(prompt, empty_string_is_none=empty_string_is_none)
|
||||||
|
@ -109,11 +110,11 @@ class Menu(object):
|
||||||
if ((length_range[0] and length < length_range[0]) or
|
if ((length_range[0] and length < length_range[0]) or
|
||||||
(length_range[1] and length > length_range[1])):
|
(length_range[1] and length > length_range[1])):
|
||||||
if length_range[0] and length_range[1]:
|
if length_range[0] and length_range[1]:
|
||||||
print('Value must have length in range [%d,%d]' % length_range)
|
print(f'Value must have length in range [{length_range[0]:d}, {length_range[1]:d}]')
|
||||||
elif length_range[0]:
|
elif length_range[0]:
|
||||||
print('Value must have length at least %d' % length_range[0])
|
print(f'Value must have length at least {length_range[0]:d}')
|
||||||
else:
|
else:
|
||||||
print('Value must have length at most %d' % length_range[1])
|
print(f'Value must have length at most {length_range[1]:d}')
|
||||||
else:
|
else:
|
||||||
return result
|
return result
|
||||||
while True:
|
while True:
|
||||||
|
@ -129,9 +130,9 @@ class Menu(object):
|
||||||
# timeout occurred, simulate empty line
|
# timeout occurred, simulate empty line
|
||||||
result = ''
|
result = ''
|
||||||
else:
|
else:
|
||||||
result = str(input(), conf.input_encoding).strip()
|
result = input().strip()
|
||||||
else:
|
else:
|
||||||
result = str(input(safe_str(prompt)), conf.input_encoding).strip()
|
result = input(safe_str(prompt)).strip()
|
||||||
except EOFError:
|
except EOFError:
|
||||||
print('quit')
|
print('quit')
|
||||||
self.exit_menu()
|
self.exit_menu()
|
||||||
|
@ -210,7 +211,7 @@ class Menu(object):
|
||||||
if prompt is None:
|
if prompt is None:
|
||||||
prompt = self.prompt
|
prompt = self.prompt
|
||||||
if default is not None:
|
if default is not None:
|
||||||
prompt += ("[%s] " % default)
|
prompt += (f"[{default}] ")
|
||||||
while True:
|
while True:
|
||||||
result = self.input_str(prompt)
|
result = self.input_str(prompt)
|
||||||
if result == '':
|
if result == '':
|
||||||
|
@ -223,11 +224,11 @@ class Menu(object):
|
||||||
if ((allowed_range[0] and value < allowed_range[0]) or
|
if ((allowed_range[0] and value < allowed_range[0]) or
|
||||||
(allowed_range[1] and value > allowed_range[1])):
|
(allowed_range[1] and value > allowed_range[1])):
|
||||||
if allowed_range[0] and allowed_range[1]:
|
if allowed_range[0] and allowed_range[1]:
|
||||||
print('Value must be in range [%d,%d]' % allowed_range)
|
print(f'Value must be in range [{allowed_range[0]:d}, {allowed_range[1]:d}]')
|
||||||
elif allowed_range[0]:
|
elif allowed_range[0]:
|
||||||
print('Value must be at least %d' % allowed_range[0])
|
print(f'Value must be at least {allowed_range[0]:d}')
|
||||||
else:
|
else:
|
||||||
print('Value must be at most %d' % allowed_range[1])
|
print(f'Value must be at most {allowed_range[1]:d}')
|
||||||
else:
|
else:
|
||||||
return value
|
return value
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -302,7 +303,7 @@ class Menu(object):
|
||||||
type_guess = guess_data_type(search_str)
|
type_guess = guess_data_type(search_str)
|
||||||
if type_guess is not None and thing_for_type[type_guess] in add_non_existing:
|
if type_guess is not None and thing_for_type[type_guess] in add_non_existing:
|
||||||
return self.search_add(search_str)
|
return self.search_add(search_str)
|
||||||
# print 'No match found for "%s".' % search_str
|
# print('No match found for "%s".' % search_str)
|
||||||
return None
|
return None
|
||||||
return self.search_ui2(search_str, results[selected_thing], selected_thing)
|
return self.search_ui2(search_str, results[selected_thing], selected_thing)
|
||||||
|
|
||||||
|
@ -321,16 +322,16 @@ class Menu(object):
|
||||||
def search_add(self, string):
|
def search_add(self, string):
|
||||||
type_guess = guess_data_type(string)
|
type_guess = guess_data_type(string)
|
||||||
if type_guess == 'username':
|
if type_guess == 'username':
|
||||||
print('"%s" looks like a username, but no such user exists.' % string)
|
print(f'"{string}" looks like a username, but no such user exists.')
|
||||||
if self.confirm('Create user %s?' % string):
|
if self.confirm(f'Create user {string}?'):
|
||||||
user = User(string, None)
|
user = User(string, None)
|
||||||
self.session.add(user)
|
self.session.add(user)
|
||||||
return user
|
return user
|
||||||
return None
|
return None
|
||||||
if type_guess == 'card':
|
if type_guess == 'card':
|
||||||
selector = Selector('"%s" looks like a card number, but no user with that card number exists.' % string,
|
selector = Selector(f'"{string}" looks like a card number, but no user with that card number exists.',
|
||||||
[('create', 'Create user with card number %s' % string),
|
[('create', f'Create user with card number {string}'),
|
||||||
('set', 'Set card number of an existing user to %s' % string)])
|
('set', f'Set card number of an existing user to {string}')])
|
||||||
selection = selector.execute()
|
selection = selector.execute()
|
||||||
if selection == 'create':
|
if selection == 'create':
|
||||||
username = self.input_str('Username for new user (should be same as PVV username)> ',
|
username = self.input_str('Username for new user (should be same as PVV username)> ',
|
||||||
|
@ -342,7 +343,7 @@ class Menu(object):
|
||||||
user = self.input_user('User to set card number for> ')
|
user = self.input_user('User to set card number for> ')
|
||||||
old_card = user.card
|
old_card = user.card
|
||||||
user.card = string
|
user.card = string
|
||||||
print('Card number of %s set to %s (was %s)' % (user.name, string, old_card))
|
print(f'Card number of {user.name} set to {string} (was {old_card})')
|
||||||
return user
|
return user
|
||||||
return None
|
return None
|
||||||
if type_guess == 'bar_code':
|
if type_guess == 'bar_code':
|
||||||
|
@ -357,22 +358,19 @@ class Menu(object):
|
||||||
if not isinstance(result, list):
|
if not isinstance(result, list):
|
||||||
return result
|
return result
|
||||||
if len(result) == 0:
|
if len(result) == 0:
|
||||||
print('No %ss matching "%s"' % (thing, search_str))
|
print(f'No {thing}s matching "{search_str}"')
|
||||||
return None
|
return None
|
||||||
if len(result) == 1:
|
if len(result) == 1:
|
||||||
msg = 'One %s matching "%s": %s. Use this?' % \
|
msg = f'One {thing} matching "{search_str}": {str(result[0])}. Use this?'
|
||||||
(thing, search_str, str(result[0]))
|
|
||||||
if self.confirm(msg, default=True):
|
if self.confirm(msg, default=True):
|
||||||
return result[0]
|
return result[0]
|
||||||
return None
|
return None
|
||||||
limit = 9
|
limit = 9
|
||||||
if len(result) > limit:
|
if len(result) > limit:
|
||||||
select_header = '%d %ss matching "%s"; showing first %d' % \
|
select_header = f'{len(result):d} {thing}s matching "{search_str}"; showing first {limit:d}'
|
||||||
(len(result), thing, search_str, limit)
|
|
||||||
select_items = result[:limit]
|
select_items = result[:limit]
|
||||||
else:
|
else:
|
||||||
select_header = '%d %ss matching "%s"' % \
|
select_header = f'{len(result):d} {thing}s matching "{search_str}"'
|
||||||
(len(result), thing, search_str)
|
|
||||||
select_items = result
|
select_items = result
|
||||||
selector = Selector(select_header, items=select_items,
|
selector = Selector(select_header, items=select_items,
|
||||||
return_index=False)
|
return_index=False)
|
||||||
|
@ -419,7 +417,8 @@ class Menu(object):
|
||||||
print('no help here')
|
print('no help here')
|
||||||
else:
|
else:
|
||||||
print('')
|
print('')
|
||||||
print('Help for %s:' % (self.header_format % self.name))
|
print('Help for %s:' % (self.header_format
|
||||||
|
% self.name))
|
||||||
print(self.help_text)
|
print(self.help_text)
|
||||||
|
|
||||||
def execute(self, **kwargs):
|
def execute(self, **kwargs):
|
||||||
|
@ -437,6 +436,7 @@ class Menu(object):
|
||||||
self.session = None
|
self.session = None
|
||||||
|
|
||||||
def _execute(self, **kwargs):
|
def _execute(self, **kwargs):
|
||||||
|
# TODO: This is a very awkward line. Is there a better way of doing this?
|
||||||
line_format = '%' + str(len(str(len(self.items)))) + 'd ) %s'
|
line_format = '%' + str(len(str(len(self.items)))) + 'd ) %s'
|
||||||
while True:
|
while True:
|
||||||
self.print_header()
|
self.print_header()
|
||||||
|
@ -478,7 +478,7 @@ class ConfirmMenu(Menu):
|
||||||
def _execute(self):
|
def _execute(self):
|
||||||
options = {True: '[y]/n', False: 'y/[n]', None: 'y/n'}[self.default]
|
options = {True: '[y]/n', False: 'y/[n]', None: 'y/n'}[self.default]
|
||||||
while True:
|
while True:
|
||||||
result = self.input_str('%s (%s) ' % (self.prompt, options), timeout=self.timeout)
|
result = self.input_str(f'{self.prompt} ({options}) ', timeout=self.timeout)
|
||||||
result = result.lower().strip()
|
result = result.lower().strip()
|
||||||
if result in ['y', 'yes']:
|
if result in ['y', 'yes']:
|
||||||
return True
|
return True
|
||||||
|
@ -507,5 +507,5 @@ class Selector(Menu):
|
||||||
print('\'exit\' to go out and do something else.')
|
print('\'exit\' to go out and do something else.')
|
||||||
else:
|
else:
|
||||||
print('')
|
print('')
|
||||||
print('Help for selector (%s):' % self.name)
|
print(f'Help for selector ({self.name}):')
|
||||||
print(self.help_text)
|
print(self.help_text)
|
||||||
|
|
|
@ -13,30 +13,30 @@ class TransferMenu(Menu):
|
||||||
def _execute(self):
|
def _execute(self):
|
||||||
self.print_header()
|
self.print_header()
|
||||||
amount = self.input_int('Transfer amount> ', (1, 100000))
|
amount = self.input_int('Transfer amount> ', (1, 100000))
|
||||||
self.set_context('Transfering %d kr' % amount, display=False)
|
self.set_context(f'Transferring {amount:d} kr', display=False)
|
||||||
user1 = self.input_user('From user> ')
|
user1 = self.input_user('From user> ')
|
||||||
self.add_to_context(' from ' + user1.name)
|
self.add_to_context(f' from {user1.name}')
|
||||||
user2 = self.input_user('To user> ')
|
user2 = self.input_user('To user> ')
|
||||||
self.add_to_context(' to ' + user2.name)
|
self.add_to_context(f' to {user2.name}')
|
||||||
comment = self.input_str('Comment> ')
|
comment = self.input_str('Comment> ')
|
||||||
self.add_to_context(' (comment) ' + user2.name)
|
self.add_to_context(f' (comment) {user2.name}')
|
||||||
|
|
||||||
t1 = Transaction(user1, amount,
|
t1 = Transaction(user1, amount,
|
||||||
'transfer to ' + user2.name + ' "' + comment + '"')
|
f'transfer to {user2.name} "{comment}"')
|
||||||
t2 = Transaction(user2, -amount,
|
t2 = Transaction(user2, -amount,
|
||||||
'transfer from ' + user1.name + ' "' + comment + '"')
|
f'transfer from {user1.name} "{comment}"')
|
||||||
t1.perform_transaction()
|
t1.perform_transaction()
|
||||||
t2.perform_transaction()
|
t2.perform_transaction()
|
||||||
self.session.add(t1)
|
self.session.add(t1)
|
||||||
self.session.add(t2)
|
self.session.add(t2)
|
||||||
try:
|
try:
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
print('Transfered %d kr from %s to %s' % (amount, user1, user2))
|
print(f"Transferred {amount:d} kr from {user1} to {user2}")
|
||||||
print('User %s\'s credit is now %d kr' % (user1, user1.credit))
|
print(f"User {user1}'s credit is now {user1.credit:d} kr")
|
||||||
print('User %s\'s credit is now %d kr' % (user2, user2.credit))
|
print(f"User {user2}'s credit is now {user2.credit:d} kr")
|
||||||
print('Comment: %s' % comment)
|
print(f"Comment: {comment}")
|
||||||
except sqlalchemy.exc.SQLAlchemyError as e:
|
except sqlalchemy.exc.SQLAlchemyError as e:
|
||||||
print('Could not perform transfer: %s' % e)
|
print(f'Could not perform transfer: {e}')
|
||||||
# self.pause()
|
# self.pause()
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,14 +47,14 @@ class ShowUserMenu(Menu):
|
||||||
def _execute(self):
|
def _execute(self):
|
||||||
self.print_header()
|
self.print_header()
|
||||||
user = self.input_user('User name, card number or RFID> ')
|
user = self.input_user('User name, card number or RFID> ')
|
||||||
print('User name: %s' % user.name)
|
print(f'User name: {user.name}')
|
||||||
print('Card number: %s' % user.card)
|
print(f'Card number: {user.card}')
|
||||||
print('RFID: %s' % user.rfid)
|
print(f'RFID: {user.rfid}')
|
||||||
print('Credit: %s kr' % user.credit)
|
print(f'Credit: {user.credit} kr')
|
||||||
selector = Selector('What do you want to know about %s?' % user.name,
|
selector = Selector(f'What do you want to know about {user.name}?',
|
||||||
items=[('transactions', 'Recent transactions (List of last ' + str(
|
items=[('transactions', 'Recent transactions (List of last ' + str(
|
||||||
conf.user_recent_transaction_limit) + ')'),
|
conf.user_recent_transaction_limit) + ')'),
|
||||||
('products', 'Which products %s has bought, and how many' % user.name),
|
('products', f'Which products {user.name} has bought, and how many'),
|
||||||
('transactions-all', 'Everything (List of all transactions)')])
|
('transactions-all', 'Everything (List of all transactions)')])
|
||||||
what = selector.execute()
|
what = selector.execute()
|
||||||
if what == 'transactions':
|
if what == 'transactions':
|
||||||
|
@ -66,21 +66,24 @@ class ShowUserMenu(Menu):
|
||||||
else:
|
else:
|
||||||
print('What what?')
|
print('What what?')
|
||||||
|
|
||||||
|
# TODO: This is almost identical to the print_transactions function. Reimplement using that one?
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def print_all_transactions(user):
|
def print_all_transactions(user):
|
||||||
num_trans = len(user.transactions)
|
num_trans = len(user.transactions)
|
||||||
string = '%s\'s transactions (%d):\n' % (user.name, num_trans)
|
string = f"{user.name}'s transactions ({num_trans:d}):\n"
|
||||||
for t in user.transactions[::-1]:
|
for t in user.transactions[::-1]:
|
||||||
string += ' * %s: %s %d kr, ' % \
|
string += ' * %s: %s %d kr, ' % \
|
||||||
(t.time.strftime('%Y-%m-%d %H:%M'),
|
(t.time.strftime('%Y-%m-%d %H:%M'),
|
||||||
{True: 'in', False: 'out'}[t.amount < 0],
|
'in' if t.amount < 0 else 'out',
|
||||||
abs(t.amount))
|
abs(t.amount))
|
||||||
if t.purchase:
|
if t.purchase:
|
||||||
|
# TODO: Print purchased amount, not just product names
|
||||||
|
# TODO: Print something other than "purchase" when user put products into dibbler?
|
||||||
string += 'purchase ('
|
string += 'purchase ('
|
||||||
string += ', '.join([e.product.name for e in t.purchase.entries])
|
string += ', '.join([e.product.name for e in t.purchase.entries])
|
||||||
string += ')'
|
string += ')'
|
||||||
if t.penalty > 1:
|
if t.penalty > 1:
|
||||||
string += ' * %dx penalty applied' % t.penalty
|
string += f' * {t.penalty:d}x penalty applied'
|
||||||
else:
|
else:
|
||||||
string += t.description
|
string += t.description
|
||||||
string += '\n'
|
string += '\n'
|
||||||
|
@ -90,20 +93,20 @@ class ShowUserMenu(Menu):
|
||||||
def print_transactions(user, limit=10):
|
def print_transactions(user, limit=10):
|
||||||
num_trans = len(user.transactions)
|
num_trans = len(user.transactions)
|
||||||
if num_trans <= limit:
|
if num_trans <= limit:
|
||||||
string = '%s\'s transactions (%d):\n' % (user.name, num_trans)
|
string = f"{user.name}'s transactions ({num_trans:d}):\n"
|
||||||
else:
|
else:
|
||||||
string = '%s\'s transactions (%d, showing only last %d):\n' % (user.name, num_trans, limit)
|
string = f"{user.name}'s transactions ({num_trans:d}, showing only last {limit:d}):\n"
|
||||||
for t in user.transactions[-1:-limit - 1:-1]:
|
for t in user.transactions[-1:-limit - 1:-1]:
|
||||||
string += ' * %s: %s %d kr, ' % \
|
string += ' * %s: %s %d kr, ' % \
|
||||||
(t.time.strftime('%Y-%m-%d %H:%M'),
|
(t.time.strftime('%Y-%m-%d %H:%M'),
|
||||||
{True: 'in', False: 'out'}[t.amount < 0],
|
'in' if t.amount < 0 else 'out',
|
||||||
abs(t.amount))
|
abs(t.amount))
|
||||||
if t.purchase:
|
if t.purchase:
|
||||||
string += 'purchase ('
|
string += 'purchase ('
|
||||||
string += ', '.join([e.product.name for e in t.purchase.entries])
|
string += ', '.join([e.product.name for e in t.purchase.entries])
|
||||||
string += ')'
|
string += ')'
|
||||||
if t.penalty > 1:
|
if t.penalty > 1:
|
||||||
string += ' * %dx penalty applied' % t.penalty
|
string += f' * {t.penalty:d}x penalty applied'
|
||||||
else:
|
else:
|
||||||
string += t.description
|
string += t.description
|
||||||
string += '\n'
|
string += '\n'
|
||||||
|
@ -124,7 +127,7 @@ class ShowUserMenu(Menu):
|
||||||
text = ''
|
text = ''
|
||||||
text += 'Products purchased:\n'
|
text += 'Products purchased:\n'
|
||||||
for product, count in products:
|
for product, count in products:
|
||||||
text += '{0:<47} {1:>3}\n'.format(product.name, count)
|
text += f'{product.name:<47} {count:>3}\n'
|
||||||
less(text)
|
less(text)
|
||||||
|
|
||||||
|
|
||||||
|
@ -148,16 +151,17 @@ class UserListMenu(Menu):
|
||||||
text += line_format % ('total credit', total_credit)
|
text += line_format % ('total credit', total_credit)
|
||||||
less(text)
|
less(text)
|
||||||
|
|
||||||
|
# reimplements ChargeMenu
|
||||||
class AdjustCreditMenu(Menu): # reimplements ChargeMenu; these should be combined to one
|
# TODO: these should be combined to one
|
||||||
|
class AdjustCreditMenu(Menu):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Menu.__init__(self, 'Adjust credit', uses_db=True)
|
Menu.__init__(self, 'Adjust credit', uses_db=True)
|
||||||
|
|
||||||
def _execute(self):
|
def _execute(self):
|
||||||
self.print_header()
|
self.print_header()
|
||||||
user = self.input_user('User> ')
|
user = self.input_user('User> ')
|
||||||
print('User %s\'s credit is %d kr' % (user.name, user.credit))
|
print(f"User {user.name}'s credit is {user.credit:d} kr")
|
||||||
self.set_context('Adjusting credit for user %s' % user.name, display=False)
|
self.set_context(f'Adjusting credit for user {user.name}', display=False)
|
||||||
print('(Note on sign convention: Enter a positive amount here if you have')
|
print('(Note on sign convention: Enter a positive amount here if you have')
|
||||||
print('added money to the PVVVV money box, a negative amount if you have')
|
print('added money to the PVVVV money box, a negative amount if you have')
|
||||||
print('taken money from it)')
|
print('taken money from it)')
|
||||||
|
@ -173,9 +177,9 @@ class AdjustCreditMenu(Menu): # reimplements ChargeMenu; these should be combin
|
||||||
self.session.add(transaction)
|
self.session.add(transaction)
|
||||||
try:
|
try:
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
print('User %s\'s credit is now %d kr' % (user.name, user.credit))
|
print(f"User {user.name}'s credit is now {user.credit:d} kr")
|
||||||
except sqlalchemy.exc.SQLAlchemyError as e:
|
except sqlalchemy.exc.SQLAlchemyError as e:
|
||||||
print('Could not store transaction: %s' % e)
|
print(f'Could not store transaction: {e}')
|
||||||
# self.pause()
|
# self.pause()
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue