client-barcode: Resolve class ToGoCommand, make UNDO delete commodity/deposity combined

This commit is contained in:
Sebastian Pipping 2011-10-12 05:51:04 +02:00
parent 8d6ff280e3
commit 356c2584db
2 changed files with 112 additions and 125 deletions

View File

@ -6,7 +6,7 @@
from __future__ import print_function from __future__ import print_function
import freitagslib.network as net import freitagslib.network as net
from freitagslib.commands import BuyCommand, DepositCommand, ToGoCommand from freitagslib.commands import BuyCommand, DepositCommand
import colorama import colorama
from colorama import Fore, Style from colorama import Fore, Style
@ -98,22 +98,14 @@ class Status:
def color(amount): def color(amount):
return COLOR_WITHDRAW if amount < 0 else COLOR_DEPOSIT 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=' '): def show_total(balance, plus=' '):
print('%3s %-40s %s%c %6.2f Euro%s' \ print('%3s %-40s %s%c %6.2f Euro%s' \
% ('', '', color(balance), sign(balance, plus), % ('', '', color(balance), sign(balance, plus),
abs(balance), COLOR_RESET)) abs(balance), COLOR_RESET))
def show_item(position, command): def show_item(position, diff, label, color):
diff = command.difference()
label = command.label()
print('%2d) %-40s %s%c %6.2f Euro%s' \ 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)) abs(diff), COLOR_RESET))
def show_bar(): def show_bar():
@ -127,8 +119,18 @@ class Status:
print('Geplante Änderungen:') print('Geplante Änderungen:')
show_total(initial_balance) show_total(initial_balance)
for i, (command, balance_backup) in enumerate(self.transfers): i = 1
show_item(i + 1, command) 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() show_bar()
if len(self.transfers) > 1: if len(self.transfers) > 1:
show_total(self.balance - initial_balance, plus='+') show_total(self.balance - initial_balance, plus='+')
@ -215,109 +217,78 @@ class Status:
if scope == TO_GO_ALL: 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] dummy, initial_balance = self.transfers[0]
balance_before = initial_balance balance_before = initial_balance
def body(prev, command, balance_before): for command, dummy in self.transfers:
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)
self.balance = balance_before
self.transfers = after
elif scope == TO_GO_NONE:
"""
Deletes all ToGoCommands
"""
after = list()
first_command, initial_balance = self.transfers[0]
balance_before = initial_balance
for command, dummy in list(self.transfers):
if isinstance(command, BuyCommand) \ if isinstance(command, BuyCommand) \
and command.is_to_go(): and not command.includes_deposit() \
command.set_to_go(False) and command.deposit_value() > 0:
elif isinstance(command, ToGoCommand): command.include_deposit(True)
continue balance_before += command.difference()
after.append((command, balance_before))
self.balance = balance_before
elif scope == TO_GO_NONE:
"""
Makes all BuyCommands that include commodity
not include deposit any more
...and updates future balance accordingly.
"""
first_command, initial_balance = self.transfers[0]
balance_before = initial_balance
for command, dummy in self.transfers:
if isinstance(command, BuyCommand) \
and command.includes_commodity():
command.include_deposit(False)
balance_before += command.difference() balance_before += command.difference()
self.balance = balance_before self.balance = balance_before
self.transfers = after
elif scope == TO_GO_PREV: 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] prev, balance_backup = self.transfers[-1]
if not isinstance(prev, BuyCommand): if not isinstance(prev, BuyCommand):
error_page(_PRODUCT_FIRST) error_page(_PRODUCT_FIRST)
return return
to_go = ToGoCommand(prev.item()) if prev.includes_deposit():
prev.set_to_go(True) error_page('FEHLER: Pfand für Produkt "%s" bereits aktiviert' % prev.item_name())
self.transfers.append((to_go, self.balance)) return
self.balance += to_go.difference() 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: elif scope == TO_GO_ONLY:
""" """
Replace all BuyCommands with deposit > 0 by Makes all BuyCommand that include commodity
a ToGoCommand. Resolve ToGoCommand duplicates. be deposit only
...and updates future balance accordingly.
""" """
after = list() dummy, initial_balance = self.transfers[0]
first_command, initial_balance = self.transfers[0]
balance_before = initial_balance balance_before = initial_balance
for command, dummy in list(self.transfers): for command, dummy in self.transfers:
if isinstance(command, ToGoCommand) \ if isinstance(command, BuyCommand) \
and prev_item is not None \ and command.deposit_value() > 0 \
and command.item() == prev_item: and command.includes_commodity():
""" command.include_commodity(False)
Skip this very duplicate command.include_deposit(True)
"""
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))
balance_before += command.difference() balance_before += command.difference()
self.balance = balance_before self.balance = balance_before
self.transfers = after
def undo(self): def undo(self):
assert(self.logged_in()) assert(self.logged_in())
if self.transfers: if self.transfers:
(last_command, balance_backup) = self.transfers[-1] dummy, 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)
self.transfers.pop() self.transfers.pop()
self.balance = balance_backup self.balance = balance_backup
else: else:

View File

@ -5,18 +5,16 @@
# Licensed under GPL v3 or later # Licensed under GPL v3 or later
import freitagslib.network as net 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): class DepositCommand(object):
def difference(self):
return self._difference
class DepositCommand(Command):
def __init__(self, amount): def __init__(self, amount):
self._difference = amount self._difference = amount
def difference(self):
self._difference
def run(self, user_name): def run(self, user_name):
net.deposit(self._difference, net.DEPOSIT_CASH, user_name) net.deposit(self._difference, net.DEPOSIT_CASH, user_name)
@ -24,43 +22,61 @@ class DepositCommand(Command):
return '%.2f Euro einzahlen' % self._difference return '%.2f Euro einzahlen' % self._difference
class _ItemBasedCommand(Command): class BuyCommand(object):
def __init__(self, item): def __init__(self, item):
self._item = item self._item = item
self._commodity = True
self._deposit = False
def item(self): def _what_to_buy(self):
return self._item 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 difference(self):
class BuyCommand(_ItemBasedCommand): if self._deposit and self._commodity:
def __init__(self, item): return -(self._item.price + self._item.deposit)
super(BuyCommand, self).__init__(item) elif self._deposit:
self._difference = -item.price return -(self._item.deposit)
self._to_go = False ## TODO session state, instead? elif self._commodity:
return -(self._item.price)
else:
raise ValueError("BuyCommand in illegal state")
def run(self, user_name): 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 return self._item.name
def is_to_go(self): def commodity_label(self):
return self._to_go if self._deposit:
return self._item.name
else:
return "%s (exkl. Pfand)" % self._item.name
def set_to_go(self, to_go): def deposit_label(self):
self._to_go = to_go
def deposit(self):
return self._item.deposit
class ToGoCommand(_ItemBasedCommand):
def __init__(self, item):
super(ToGoCommand, self).__init__(item)
self._difference = -item.deposit
def run(self, user_name):
net.buy_item(self._item.id, what_about_it=DEPOSIT_ONLY, user_name=user_name)
def label(self):
return '%s Pfand' % self._item.name return '%s Pfand' % self._item.name
def includes_commodity(self):
return self._commodity
def includes_deposit(self):
return self._deposit
def include_commodity(self, commodity):
self._commodity = commodity
def include_deposit(self, deposit):
self._deposit = deposit
def commodity_value(self):
return self._item.price
def deposit_value(self):
return self._item.deposit