diff --git a/client-barcode/freitagskasse.py b/client-barcode/freitagskasse.py index 1f4a5c5..edc2045 100644 --- a/client-barcode/freitagskasse.py +++ b/client-barcode/freitagskasse.py @@ -6,7 +6,7 @@ from __future__ import print_function import freitagslib.network as net -from freitagslib.commands import BuyCommand, DepositCommand, ToGoCommand +from freitagslib.commands import BuyCommand, DepositCommand import colorama from colorama import Fore, Style @@ -98,22 +98,14 @@ class Status: def color(amount): return COLOR_WITHDRAW if amount < 0 else COLOR_DEPOSIT - def color_command(command): - diff = command.difference() - if diff >= 0: - return COLOR_DEPOSIT - return COLOR_TO_GO if isinstance(command, ToGoCommand) else COLOR_WITHDRAW - def show_total(balance, plus=' '): print('%3s %-40s %s%c %6.2f Euro%s' \ % ('', '', color(balance), sign(balance, plus), abs(balance), COLOR_RESET)) - def show_item(position, command): - diff = command.difference() - label = command.label() + def show_item(position, diff, label, color): print('%2d) %-40s %s%c %6.2f Euro%s' \ - % (position, label, color_command(command), sign(diff), + % (position, label, color, sign(diff), abs(diff), COLOR_RESET)) def show_bar(): @@ -127,8 +119,18 @@ class Status: print('Geplante Änderungen:') show_total(initial_balance) - for i, (command, balance_backup) in enumerate(self.transfers): - show_item(i + 1, command) + i = 1 + for command, dummy in self.transfers: + if isinstance(command, BuyCommand): + if (command.includes_commodity()): + show_item(i, -command.commodity_value(), command.commodity_label(), COLOR_WITHDRAW) + i += 1 + if (command.includes_deposit()): + show_item(i, -command.deposit_value(), command.deposit_label(), COLOR_TO_GO) + i += 1 + else: + show_item(i, command.difference(), command.label(), COLOR_DEPOSIT) + i += 1 show_bar() if len(self.transfers) > 1: show_total(self.balance - initial_balance, plus='+') @@ -215,109 +217,78 @@ class Status: if scope == TO_GO_ALL: """ - Adds a ToGoCommands for each BuyCommands with deposit > 0 lacking a pair + Makes all BuyCommands with deposit > 0 include deposit + ...and updates future balance accordingly. """ - after = list() dummy, initial_balance = self.transfers[0] balance_before = initial_balance - def body(prev, command, balance_before): - if isinstance(prev, BuyCommand) \ - and prev.deposit() > 0 \ - and (not isinstance(command, ToGoCommand) \ - or (isinstance(command, ToGoCommand) \ - and prev.item() != command.item())): - to_go = ToGoCommand(prev.item()) - prev.set_to_go(True) - after.append((to_go, balance_before)) - balance_before += to_go.difference() - if command is not None: - after.append((command, balance_before)) - balance_before += command.difference() - return balance_before - - prev = None - for command, dummy in list(self.transfers): - balance_before = body(prev, command, balance_before) - prev = command - balance_before = body(prev, None, balance_before) + for command, dummy in self.transfers: + if isinstance(command, BuyCommand) \ + and not command.includes_deposit() \ + and command.deposit_value() > 0: + command.include_deposit(True) + balance_before += command.difference() self.balance = balance_before - self.transfers = after elif scope == TO_GO_NONE: """ - Deletes all ToGoCommands + Makes all BuyCommands that include commodity + not include deposit any more + ...and updates future balance accordingly. """ - after = list() first_command, initial_balance = self.transfers[0] balance_before = initial_balance - for command, dummy in list(self.transfers): + for command, dummy in self.transfers: if isinstance(command, BuyCommand) \ - and command.is_to_go(): - command.set_to_go(False) - elif isinstance(command, ToGoCommand): - continue - after.append((command, balance_before)) + and command.includes_commodity(): + command.include_deposit(False) balance_before += command.difference() self.balance = balance_before - self.transfers = after elif scope == TO_GO_PREV: """ - Adds a ToGoCommand after previous BuyCommand + Makes the last BuyCommand include deposit + ...and updates future balance accordingly. """ prev, balance_backup = self.transfers[-1] if not isinstance(prev, BuyCommand): error_page(_PRODUCT_FIRST) return - to_go = ToGoCommand(prev.item()) - prev.set_to_go(True) - self.transfers.append((to_go, self.balance)) - self.balance += to_go.difference() + if prev.includes_deposit(): + error_page('FEHLER: Pfand für Produkt "%s" bereits aktiviert' % prev.item_name()) + return + if prev.deposit_value() <= 0: + error_page('FEHLER: Produkt "%s" hat kein Pfand' % prev.item_name()) + return + before = prev.difference() + prev.include_deposit(True) + after = prev.difference() + self.balance += (after - before) elif scope == TO_GO_ONLY: """ - Replace all BuyCommands with deposit > 0 by - a ToGoCommand. Resolve ToGoCommand duplicates. + Makes all BuyCommand that include commodity + be deposit only + ...and updates future balance accordingly. """ - after = list() - first_command, initial_balance = self.transfers[0] + dummy, initial_balance = self.transfers[0] balance_before = initial_balance - for command, dummy in list(self.transfers): - if isinstance(command, ToGoCommand) \ - and prev_item is not None \ - and command.item() == prev_item: - """ - Skip this very duplicate - """ - prev_item = None - continue - elif isinstance(command, BuyCommand) \ - and command.deposit() > 0: - """ - Replace by ToGoCommand - """ - item = command.item() - command = ToGoCommand(item) - prev_item = item - else: - prev_item = None - after.append((command, balance_before)) + for command, dummy in self.transfers: + if isinstance(command, BuyCommand) \ + and command.deposit_value() > 0 \ + and command.includes_commodity(): + command.include_commodity(False) + command.include_deposit(True) balance_before += command.difference() self.balance = balance_before - self.transfers = after def undo(self): assert(self.logged_in()) if self.transfers: - (last_command, balance_backup) = self.transfers[-1] - if isinstance(last_command, ToGoCommand) \ - and self.transfers: - second_last_command = self.transfers[-2] - if isinstance(second_last_command, BuyCommand): - second_last_command.set_to_go(False) + dummy, balance_backup = self.transfers[-1] self.transfers.pop() self.balance = balance_backup else: diff --git a/client-barcode/freitagslib/commands.py b/client-barcode/freitagslib/commands.py index 48f0934..333ead8 100644 --- a/client-barcode/freitagslib/commands.py +++ b/client-barcode/freitagslib/commands.py @@ -5,18 +5,16 @@ # Licensed under GPL v3 or later import freitagslib.network as net -from freitagslib.network import ITEM_ONLY, DEPOSIT_ONLY +from freitagslib.network import ITEM_ONLY, DEPOSIT_ONLY, ITEM_AND_DEPOSIT -class Command(object): - def difference(self): - return self._difference - - -class DepositCommand(Command): +class DepositCommand(object): def __init__(self, amount): self._difference = amount + def difference(self): + self._difference + def run(self, user_name): net.deposit(self._difference, net.DEPOSIT_CASH, user_name) @@ -24,43 +22,61 @@ class DepositCommand(Command): return '%.2f Euro einzahlen' % self._difference -class _ItemBasedCommand(Command): +class BuyCommand(object): def __init__(self, item): self._item = item + self._commodity = True + self._deposit = False + + def _what_to_buy(self): + if self._deposit and self._commodity: + return ITEM_AND_DEPOSIT + elif self._deposit: + return DEPOSIT_ONLY + elif self._commodity: + return ITEM_ONLY + else: + raise ValueError("BuyCommand in illegal state") - def item(self): - return self._item - - -class BuyCommand(_ItemBasedCommand): - def __init__(self, item): - super(BuyCommand, self).__init__(item) - self._difference = -item.price - self._to_go = False ## TODO session state, instead? + def difference(self): + if self._deposit and self._commodity: + return -(self._item.price + self._item.deposit) + elif self._deposit: + return -(self._item.deposit) + elif self._commodity: + return -(self._item.price) + else: + raise ValueError("BuyCommand in illegal state") def run(self, user_name): - net.buy_item(self._item.id, what_about_it=ITEM_ONLY, user_name=user_name) + net.buy_item(self._item.id, what_about_it=self._what_to_buy(), user_name=user_name) - def label(self): + def item_name(self): return self._item.name - def is_to_go(self): - return self._to_go + def commodity_label(self): + if self._deposit: + return self._item.name + else: + return "%s (exkl. Pfand)" % self._item.name - def set_to_go(self, to_go): - self._to_go = to_go + def deposit_label(self): + return '%s Pfand' % self._item.name - def deposit(self): - return self._item.deposit + def includes_commodity(self): + return self._commodity + def includes_deposit(self): + return self._deposit -class ToGoCommand(_ItemBasedCommand): - def __init__(self, item): - super(ToGoCommand, self).__init__(item) - self._difference = -item.deposit + def include_commodity(self, commodity): + self._commodity = commodity - def run(self, user_name): - net.buy_item(self._item.id, what_about_it=DEPOSIT_ONLY, user_name=user_name) + def include_deposit(self, deposit): + self._deposit = deposit - def label(self): - return '%s Pfand' % self._item.name + def commodity_value(self): + return self._item.price + + def deposit_value(self): + return self._item.deposit