1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| Customer = namedtuple("Customer", 'name fidelity')
class LineItem: def __init__(self, product, quantity, price): self.product = product self.quantity = quantity self.price = price
def total(self): return self.price * self.quantity
class Order:
def __init__(self, customer, cart, promotion=None): self.customer = customer self.cart = list(cart) self.promotion = promotion
def total(self): if not hasattr(self, '__total'): self.__total = sum(item.total() for item in self.cart) return self.__total
def due(self): if self.promotion is None: discount = 0 else: discount = self.promotion.discount(self) return self.total() - discount
def __repr__(self): fmt = '<Order total: {:.2f} due: {:.2f}>' return fmt.format(self.total(), self.due())
class Promotion(ABC):
@abstractclassmethod def discount(self, order): """Return discount as a positive dollar amount"""
class FidelityPromo(Promotion): """%5 discount for customers with 1000 or more fidelity points"""
def discount(self, order): return order.total() * .05 if order.customer.fidelity >= 1000 else 0
class BulkItemPromo(Promotion): """10% discount for each LineItem wit 20 or more units"""
def discount(self, order): discount = 0 for item in order.cart: if item.quantity >= 20: discount += item.total * .1 return discount
class LaregOrderPromo(Promotion): """%7 discount for orders with 10 or more distinct items"""
def discount(self, order): distinct_items = {item.product for item in order.cart} if len(distinct_items) >= 10: return order.total() * .07 return 0
if __name__ == '__main__': joe = Customer('John Doe', 0) ann = Customer('Ann Smith', 1100) cart = [LineItem('banana', 4, .5), LineItem('apple', 10, 1.5), LineItem('watermellon', 5, 5.0)]
print(Order(joe, cart, FidelityPromo()))
|