Fix errors, make menu formatting more readable
This commit is contained in:
parent
c188d692dd
commit
92f3990cc0
|
@ -42,8 +42,7 @@ much money you're due in credits for the purchase when prompted.\n'''
|
||||||
|
|
||||||
if isinstance(thing, Product):
|
if isinstance(thing, Product):
|
||||||
self.printc(f"{amount:d} of {thing.name} registered")
|
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
|
||||||
|
|
||||||
# once we get something in the
|
# 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):
|
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) * '-')
|
width = 6 + Product.name_length
|
||||||
|
print()
|
||||||
|
print(width * '-')
|
||||||
if self.price:
|
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:
|
if self.users:
|
||||||
print("Users to credit:")
|
print("Users to credit:")
|
||||||
for user in self.users:
|
for user in self.users:
|
||||||
print(f" {str(user.name)}")
|
print(f"\t{user.name}")
|
||||||
print("\n{{0:s}}{{1:>{0}s}}".format(Product.name_length-1).format("Product", "Amount"))
|
print()
|
||||||
print((6 + Product.name_length) * '-')
|
print("Products", end="")
|
||||||
|
print("Amount".rjust(width - 8))
|
||||||
|
print(width * '-')
|
||||||
if len(self.products):
|
if len(self.products):
|
||||||
for product in list(self.products.keys()):
|
for product in list(self.products.keys()):
|
||||||
print('{{0:<{0}}}{{1:>6d}}'.format(Product.name_length).format(product.name, self.products[product][0]))
|
print(f"{product.name}", end="")
|
||||||
print((6 + Product.name_length) * '-')
|
print(f"{self.products[product][0]}".rjust(width - len(product.name)))
|
||||||
|
print(width * '-')
|
||||||
|
|
||||||
def add_thing_to_pending(self, thing, amount, price):
|
def add_thing_to_pending(self, thing, amount, price):
|
||||||
if isinstance(thing, User):
|
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):
|
def perform_transaction(self):
|
||||||
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)
|
self.price = self.input_int('How much did you pay?', 0, self.price, 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
|
|
||||||
|
|
||||||
description = self.input_str('Log message', length_range=(0, 50))
|
description = self.input_str('Log message', length_range=(0, 50))
|
||||||
if description == '':
|
if description == '':
|
||||||
|
|
|
@ -77,10 +77,12 @@ When finished, write an empty line to confirm the purchase.\n'''
|
||||||
else:
|
else:
|
||||||
Transaction(thing, purchase=self.purchase)
|
Transaction(thing, purchase=self.purchase)
|
||||||
elif isinstance(thing, Product):
|
elif isinstance(thing, Product):
|
||||||
if len(self.purchase.entries) and self.purchase.entries[-1].product == thing:
|
if self.purchase.entries:
|
||||||
self.purchase.entries[-1].amount += amount
|
for entry in self.purchase.entries:
|
||||||
else:
|
if entry.product == thing:
|
||||||
PurchaseEntry(self.purchase, thing, amount)
|
entry.amount += amount
|
||||||
|
return True
|
||||||
|
PurchaseEntry(self.purchase, thing, amount)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _execute(self, initial_contents=None):
|
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},',
|
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.')
|
'AND SHOULD CONSIDER PUTTING SOME MONEY IN THE BOX.')
|
||||||
|
|
||||||
# Superfast mode skips a linebreak for some reason. This looks ugly.
|
# Superfast mode skips a linebreak for some reason.
|
||||||
# TODO: Figure out why this happens, and fix it in a less hacky way.
|
|
||||||
if self.superfast_mode:
|
if self.superfast_mode:
|
||||||
print("")
|
print("")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def complete_input(self):
|
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'
|
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?
|
total = sum(self.purchase.price_per_transaction() * t.penalty for t in transactions)
|
||||||
string += '\n *total with penalty: %d kr' % sum(
|
string += f'\n *total with penalty: {total} kr'
|
||||||
self.purchase.price_per_transaction() * t.penalty for t in transactions)
|
|
||||||
|
|
||||||
return string
|
return string
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ class AddProductMenu(Menu):
|
||||||
self.print_header()
|
self.print_header()
|
||||||
bar_code = self.input_str('Bar code', regex=Product.bar_code_re, length_range=(8, 13))
|
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))
|
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)
|
product = Product(bar_code, name, price)
|
||||||
self.session.add(product)
|
self.session.add(product)
|
||||||
try:
|
try:
|
||||||
|
@ -97,7 +97,7 @@ class EditProductMenu(Menu):
|
||||||
product.name = self.input_str('Name', default=product.name, regex=Product.name_re,
|
product.name = self.input_str('Name', default=product.name, regex=Product.name_re,
|
||||||
length_range=(1, product.name_length))
|
length_range=(1, product.name_length))
|
||||||
elif what == 'price':
|
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':
|
elif what == 'barcode':
|
||||||
product.bar_code = self.input_str('Bar code', default=product.bar_code, regex=Product.bar_code_re,
|
product.bar_code = self.input_str('Bar code', default=product.bar_code, regex=Product.bar_code_re,
|
||||||
length_range=(8, 13))
|
length_range=(8, 13))
|
||||||
|
@ -129,7 +129,7 @@ class AdjustStockMenu(Menu):
|
||||||
print(f'The stock of this product is: {product.stock:d}')
|
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', allowed_range=(-1000, 1000), zero_allowed=False)
|
add_stock = self.input_int('Added stock', -1000, 1000, zero_allowed=False)
|
||||||
if add_stock > 0:
|
if add_stock > 0:
|
||||||
print(f'You added {add_stock:d} to the stock of {product}')
|
print(f'You added {add_stock:d} to the stock of {product}')
|
||||||
else:
|
else:
|
||||||
|
@ -168,7 +168,7 @@ class CleanupStockMenu(Menu):
|
||||||
|
|
||||||
for product in products:
|
for product in products:
|
||||||
oldstock = product.stock
|
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)
|
self.session.add(product)
|
||||||
if oldstock != product.stock:
|
if oldstock != product.stock:
|
||||||
changed_products.append((product, oldstock))
|
changed_products.append((product, oldstock))
|
||||||
|
|
|
@ -185,26 +185,32 @@ class Menu(object):
|
||||||
def invalid_menu_choice(self, in_str):
|
def invalid_menu_choice(self, in_str):
|
||||||
print('Please enter a valid choice.')
|
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,
|
def input_int(self, prompt=None, minimum=None, maximum=None, null_allowed=False, zero_allowed=True, default=None):
|
||||||
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:
|
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:
|
if result == '' and null_allowed:
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
value = int(result)
|
value = int(result)
|
||||||
# TODO: Should this be turned into greater-than-equals and less-than-equals?
|
if minimum is not None and value < minimum:
|
||||||
if ((allowed_range[0] and value < allowed_range[0]) or (allowed_range[1] and value > allowed_range[1])):
|
print(f'Value must be at least {minimum:d}')
|
||||||
if allowed_range[0] and allowed_range[1]:
|
continue
|
||||||
print(f'Value must be in range [{allowed_range[0]:d}, {allowed_range[1]:d}]')
|
if maximum is not None and value > maximum:
|
||||||
elif allowed_range[0]:
|
print(f'Value must be at most {maximum:d}')
|
||||||
print(f'Value must be at least {allowed_range[0]:d}')
|
continue
|
||||||
else:
|
if not zero_allowed and value == 0:
|
||||||
print(f'Value must be at most {allowed_range[1]:d}')
|
|
||||||
elif not zero_allowed and value == 0:
|
|
||||||
print("Value cannot be zero")
|
print("Value cannot be zero")
|
||||||
else:
|
continue
|
||||||
return value
|
return value
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print("Please enter an integer")
|
print("Please enter an integer")
|
||||||
|
|
||||||
|
@ -412,8 +418,6 @@ 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'
|
|
||||||
while True:
|
while True:
|
||||||
self.print_header()
|
self.print_header()
|
||||||
self.set_context(None)
|
self.set_context(None)
|
||||||
|
@ -422,7 +426,8 @@ class Menu(object):
|
||||||
self.pause()
|
self.pause()
|
||||||
return None
|
return None
|
||||||
for i in range(len(self.items)):
|
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
|
item_i = self.input_choice(len(self.items)) - 1
|
||||||
if self.item_is_submenu(item_i):
|
if self.item_is_submenu(item_i):
|
||||||
self.items[item_i].execute()
|
self.items[item_i].execute()
|
||||||
|
|
|
@ -12,7 +12,7 @@ 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(f'Transferring {amount:d} kr', 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(f' from {user1.name}')
|
self.add_to_context(f' from {user1.name}')
|
||||||
|
@ -62,48 +62,32 @@ class ShowUserMenu(Menu):
|
||||||
elif what == 'products':
|
elif what == 'products':
|
||||||
self.print_purchased_products(user)
|
self.print_purchased_products(user)
|
||||||
elif what == 'transactions-all':
|
elif what == 'transactions-all':
|
||||||
self.print_all_transactions(user)
|
self.print_transactions(user)
|
||||||
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_transactions(user, limit=None):
|
||||||
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):
|
|
||||||
num_trans = len(user.transactions)
|
num_trans = len(user.transactions)
|
||||||
|
if limit is None:
|
||||||
|
limit = num_trans
|
||||||
if num_trans <= limit:
|
if num_trans <= limit:
|
||||||
string = f"{user.name}'s transactions ({num_trans:d}):\n"
|
string = f"{user.name}'s transactions ({num_trans:d}):\n"
|
||||||
else:
|
else:
|
||||||
string = f"{user.name}'s transactions ({num_trans:d}, showing only last {limit:d}):\n"
|
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 += f" * {t.time.isoformat(' ')}: {'in' if t.amount < 0 else 'out'} {abs(t.amount)} kr, "
|
||||||
(t.time.strftime('%Y-%m-%d %H:%M'),
|
|
||||||
'in' if t.amount < 0 else 'out',
|
|
||||||
abs(t.amount))
|
|
||||||
if t.purchase:
|
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 += 'purchase ('
|
||||||
string += ', '.join([e.product.name for e in t.purchase.entries])
|
string += ', '.join(products)
|
||||||
string += ')'
|
string += ')'
|
||||||
if t.penalty > 1:
|
if t.penalty > 1:
|
||||||
string += f' * {t.penalty:d}x penalty applied'
|
string += f' * {t.penalty:d}x penalty applied'
|
||||||
|
@ -151,8 +135,6 @@ class UserListMenu(Menu):
|
||||||
text += line_format % ('total credit', total_credit)
|
text += line_format % ('total credit', total_credit)
|
||||||
less(text)
|
less(text)
|
||||||
|
|
||||||
# reimplements ChargeMenu
|
|
||||||
# TODO: these should be combined to one
|
|
||||||
class AdjustCreditMenu(Menu):
|
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)
|
||||||
|
@ -165,7 +147,7 @@ class AdjustCreditMenu(Menu):
|
||||||
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)')
|
||||||
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('(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('"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)')
|
print('might be useful to help you remember why you adjusted the credit)')
|
||||||
|
|
Loading…
Reference in New Issue