Fix errors, make menu formatting more readable

This commit is contained in:
Robert Maikher 2019-09-21 16:48:49 +02:00
parent c188d692dd
commit 92f3990cc0
5 changed files with 66 additions and 81 deletions

View File

@ -42,8 +42,7 @@ much money you're due in credits for the purchase when prompted.\n'''
if isinstance(thing, Product):
self.printc(f"{amount:d} of {thing.name} registered")
thing_price = self.input_int('What did you pay a piece? ', (1, 100000),
default=thing.price) * amount
thing_price = self.input_int('What did you pay a piece?', 1, 100000, default=thing.price) * amount
self.price += thing_price
# once we get something in the
@ -65,21 +64,25 @@ much money you're due in credits for the purchase when prompted.\n'''
def complete_input(self):
return bool(self.users) and len(self.products) and self.price
# TODO: Rewrite this madness
def print_info(self):
print((6 + Product.name_length) * '-')
width = 6 + Product.name_length
print()
print(width * '-')
if self.price:
print("Amount to be credited: {{0:>{0}d}}".format(Product.name_length-17).format(self.price))
print(f"Amount to be credited:{self.price:>{width - 22}}")
if self.users:
print("Users to credit:")
for user in self.users:
print(f" {str(user.name)}")
print("\n{{0:s}}{{1:>{0}s}}".format(Product.name_length-1).format("Product", "Amount"))
print((6 + Product.name_length) * '-')
print(f"\t{user.name}")
print()
print("Products", end="")
print("Amount".rjust(width - 8))
print(width * '-')
if len(self.products):
for product in list(self.products.keys()):
print('{{0:<{0}}}{{1:>6d}}'.format(Product.name_length).format(product.name, self.products[product][0]))
print((6 + Product.name_length) * '-')
print(f"{product.name}", end="")
print(f"{self.products[product][0]}".rjust(width - len(product.name)))
print(width * '-')
def add_thing_to_pending(self, thing, amount, price):
if isinstance(thing, User):
@ -94,12 +97,7 @@ much money you're due in credits for the purchase when prompted.\n'''
def perform_transaction(self):
print('Did you pay a different price?')
if self.confirm('>', default=False):
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:
print('Illegal action, total can not be higher than your total.')
else:
self.price = price
self.price = self.input_int('How much did you pay?', 0, self.price, default=self.price)
description = self.input_str('Log message', length_range=(0, 50))
if description == '':

View File

@ -77,10 +77,12 @@ When finished, write an empty line to confirm the purchase.\n'''
else:
Transaction(thing, purchase=self.purchase)
elif isinstance(thing, Product):
if len(self.purchase.entries) and self.purchase.entries[-1].product == thing:
self.purchase.entries[-1].amount += amount
else:
PurchaseEntry(self.purchase, thing, amount)
if self.purchase.entries:
for entry in self.purchase.entries:
if entry.product == thing:
entry.amount += amount
return True
PurchaseEntry(self.purchase, thing, amount)
return True
def _execute(self, initial_contents=None):
@ -160,10 +162,9 @@ When finished, write an empty line to confirm the purchase.\n'''
print(f'USER {t.user.name} HAS LOWER CREDIT THAN {conf.low_credit_warning_limit:d},',
'AND SHOULD CONSIDER PUTTING SOME MONEY IN THE BOX.')
# Superfast mode skips a linebreak for some reason. This looks ugly.
# TODO: Figure out why this happens, and fix it in a less hacky way.
# Superfast mode skips a linebreak for some reason.
if self.superfast_mode:
print("")
print("")
return True
def complete_input(self):
@ -197,9 +198,8 @@ When finished, write an empty line to confirm the purchase.\n'''
string += f'\n total price: {self.purchase.price:d} kr'
if any(t.penalty > 1 for t in transactions):
# TODO: Rewrite?
string += '\n *total with penalty: %d kr' % sum(
self.purchase.price_per_transaction() * t.penalty for t in transactions)
total = sum(self.purchase.price_per_transaction() * t.penalty for t in transactions)
string += f'\n *total with penalty: {total} kr'
return string

View File

@ -66,7 +66,7 @@ class AddProductMenu(Menu):
self.print_header()
bar_code = self.input_str('Bar code', regex=Product.bar_code_re, length_range=(8, 13))
name = self.input_str('Name', regex=Product.name_re, length_range=(1, Product.name_length))
price = self.input_int('Price', allowed_range=(1, 100000))
price = self.input_int('Price', 1, 100000)
product = Product(bar_code, name, price)
self.session.add(product)
try:
@ -97,7 +97,7 @@ class EditProductMenu(Menu):
product.name = self.input_str('Name', default=product.name, regex=Product.name_re,
length_range=(1, product.name_length))
elif what == 'price':
product.price = self.input_int('Price', default=product.price, allowed_range=(1, 100000))
product.price = self.input_int('Price', 1, 100000, default=product.price)
elif what == 'barcode':
product.bar_code = self.input_str('Bar code', default=product.bar_code, regex=Product.bar_code_re,
length_range=(8, 13))
@ -129,7 +129,7 @@ class AdjustStockMenu(Menu):
print(f'The stock of this product is: {product.stock:d}')
print('Write the number of products you have added to the stock')
print('Alternatively, correct the stock for any mistakes')
add_stock = self.input_int('Added stock', allowed_range=(-1000, 1000), zero_allowed=False)
add_stock = self.input_int('Added stock', -1000, 1000, zero_allowed=False)
if add_stock > 0:
print(f'You added {add_stock:d} to the stock of {product}')
else:
@ -168,7 +168,7 @@ class CleanupStockMenu(Menu):
for product in products:
oldstock = product.stock
product.stock = self.input_int(product.name, allowed_range=(0, 10000), default=max(0, oldstock))
product.stock = self.input_int(product.name, 0, 10000, default=max(0, oldstock))
self.session.add(product)
if oldstock != product.stock:
changed_products.append((product, oldstock))

View File

@ -185,26 +185,32 @@ class Menu(object):
def invalid_menu_choice(self, in_str):
print('Please enter a valid choice.')
def input_int(self, prompt=None, end_prompt=None, allowed_range=(None, None), null_allowed=False, zero_allowed=True,
default=None):
def input_int(self, prompt=None, minimum=None, maximum=None, null_allowed=False, zero_allowed=True, default=None):
if minimum is not None and maximum is not None:
end_prompt = f"({minimum}-{maximum})>"
elif minimum is not None:
end_prompt = f"(>{minimum})>"
elif maximum is not None:
end_prompt = f"(<{maximum})>"
else:
end_prompt = ""
while True:
result = self.input_str(prompt, end_prompt, default=default)
result = self.input_str(prompt + end_prompt, default=default)
if result == '' and null_allowed:
return False
try:
value = int(result)
# TODO: Should this be turned into greater-than-equals and less-than-equals?
if ((allowed_range[0] and value < allowed_range[0]) or (allowed_range[1] and value > allowed_range[1])):
if allowed_range[0] and allowed_range[1]:
print(f'Value must be in range [{allowed_range[0]:d}, {allowed_range[1]:d}]')
elif allowed_range[0]:
print(f'Value must be at least {allowed_range[0]:d}')
else:
print(f'Value must be at most {allowed_range[1]:d}')
elif not zero_allowed and value == 0:
if minimum is not None and value < minimum:
print(f'Value must be at least {minimum:d}')
continue
if maximum is not None and value > maximum:
print(f'Value must be at most {maximum:d}')
continue
if not zero_allowed and value == 0:
print("Value cannot be zero")
else:
return value
continue
return value
except ValueError:
print("Please enter an integer")
@ -412,8 +418,6 @@ class Menu(object):
self.session = None
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'
while True:
self.print_header()
self.set_context(None)
@ -422,7 +426,8 @@ class Menu(object):
self.pause()
return None
for i in range(len(self.items)):
self.printc(line_format % (i + 1, self.item_name(i)))
length = len(str(len(self.items)))
self.printc(f"{i + 1:>{length}} ) {self.item_name(i)}")
item_i = self.input_choice(len(self.items)) - 1
if self.item_is_submenu(item_i):
self.items[item_i].execute()

View File

@ -12,7 +12,7 @@ class TransferMenu(Menu):
def _execute(self):
self.print_header()
amount = self.input_int('Transfer amount', (1, 100000))
amount = self.input_int('Transfer amount', 1, 100000)
self.set_context(f'Transferring {amount:d} kr', display=False)
user1 = self.input_user('From user')
self.add_to_context(f' from {user1.name}')
@ -62,48 +62,32 @@ class ShowUserMenu(Menu):
elif what == 'products':
self.print_purchased_products(user)
elif what == 'transactions-all':
self.print_all_transactions(user)
self.print_transactions(user)
else:
print('What what?')
# TODO: This is almost identical to the print_transactions function. Reimplement using that one?
@staticmethod
def print_all_transactions(user):
num_trans = len(user.transactions)
string = f"{user.name}'s transactions ({num_trans:d}):\n"
for t in user.transactions[::-1]:
string += ' * %s: %s %d kr, ' % \
(t.time.strftime('%Y-%m-%d %H:%M'),
'in' if t.amount < 0 else 'out',
abs(t.amount))
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 += ', '.join([e.product.name for e in t.purchase.entries])
string += ')'
if t.penalty > 1:
string += f' * {t.penalty:d}x penalty applied'
else:
string += t.description
string += '\n'
less(string)
@staticmethod
def print_transactions(user, limit=10):
def print_transactions(user, limit=None):
num_trans = len(user.transactions)
if limit is None:
limit = num_trans
if num_trans <= limit:
string = f"{user.name}'s transactions ({num_trans:d}):\n"
else:
string = f"{user.name}'s transactions ({num_trans:d}, showing only last {limit:d}):\n"
for t in user.transactions[-1:-limit - 1:-1]:
string += ' * %s: %s %d kr, ' % \
(t.time.strftime('%Y-%m-%d %H:%M'),
'in' if t.amount < 0 else 'out',
abs(t.amount))
string += f" * {t.time.isoformat(' ')}: {'in' if t.amount < 0 else 'out'} {abs(t.amount)} kr, "
if t.purchase:
products = []
for entry in t.purchase.entries:
if abs(entry.amount) != 1:
amount = f"{abs(entry.amount)}x "
else:
amount = ""
product = f"{amount}{entry.product.name}"
products.append(product)
string += 'purchase ('
string += ', '.join([e.product.name for e in t.purchase.entries])
string += ', '.join(products)
string += ')'
if t.penalty > 1:
string += f' * {t.penalty:d}x penalty applied'
@ -151,8 +135,6 @@ class UserListMenu(Menu):
text += line_format % ('total credit', total_credit)
less(text)
# reimplements ChargeMenu
# TODO: these should be combined to one
class AdjustCreditMenu(Menu):
def __init__(self):
Menu.__init__(self, 'Adjust credit', uses_db=True)
@ -165,7 +147,7 @@ class AdjustCreditMenu(Menu):
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('taken money from it)')
amount = self.input_int('Add amount', allowed_range=(-100000, 100000))
amount = self.input_int('Add amount', -100000, 100000)
print('(The "log message" will show up in the transaction history in the')
print('"Show user" menu. It is not necessary to enter a message, but it')
print('might be useful to help you remember why you adjusted the credit)')