Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create exercise-2.py #28

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 73 additions & 36 deletions exercise-2.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,29 @@

import datetime
import unittest
from collections import OrderedDict


class Customer:
class Date(object):
@classmethod
def now(cls):
return datetime.datetime.now()

@classmethod
def year(cls):
return datetime.timedelta(days=365)


def get_years_delta(years=1):
return Date.now() - years * Date.year()


class Customer(object):
loyalty_discount_map = OrderedDict(((10, 20), (5, 12), (1, 10)))
senior_discount_percentage = 5
new_customer_discount_percentage = 15
veteran_discount_percentage = 10

def __init__(self, first_purchase_date, birth_date, is_veteran):
assert isinstance(first_purchase_date, (type(None), datetime.datetime))
assert isinstance(birth_date, datetime.datetime)
Expand All @@ -50,101 +70,118 @@ def __init__(self, first_purchase_date, birth_date, is_veteran):
self.birth_date = birth_date
self.is_veteran = is_veteran

@property
def loyalty_discount(self):
if not self.first_purchase:
for years, discount in self.loyalty_discount_map.items():
if self.first_purchase_date <= get_years_delta(years):
return discount
return 0

@property
def new_customer_discount(self):
if self.first_purchase:
return self.new_customer_discount_percentage
else:
return 0

@property
def first_purchase(self):
return self.first_purchase_date is None

@property
def veteran_discount(self):
if self.is_veteran:
return self.veteran_discount_percentage
else:
return 0

@property
def senior_discount(self):
if self.have_senior_discount():
return self.senior_discount_percentage
else:
return 0

def have_senior_discount(self):
return self.birth_date <= get_years_delta(65)


def calculate_discount_percentage(customer):
discount = 0
now = datetime.datetime.now()
year = datetime.timedelta(days=365)
if customer.birth_date <= now - 65*year:
# senior discount
discount = 5
if customer.first_purchase_date is not None:
if customer.first_purchase_date <= now - year:
# after one year, loyal customers get 10%
discount = 10
if customer.first_purchase_date <= now - 5*year:
# after five years, 12%
discount = 12
if customer.first_purchase_date <= now - 10*year:
# after ten years, 20%
discount = 20
else:
# first time purchase ==> 15% discount
discount = 15
if customer.is_veteran:
discount = max(discount, 10)
return discount
return max(customer.loyalty_discount, customer.veteran_discount, customer.senior_discount,
customer.new_customer_discount)


class CalculateDiscountPercentageTests(unittest.TestCase):
def setUp(self):
self.now = datetime.datetime.now()
self.year = datetime.timedelta(days=365)
self.now = Date.now()
self.year = Date.year()

def test_should_return_zero_for_casual_customer(self):
customer = Customer(first_purchase_date=self.now,
birth_date=self.now-20*self.year,
birth_date=self.now - 20 * self.year,
is_veteran=False)
got = calculate_discount_percentage(customer)
expected = 0
self.assertEqual(got, expected)

def test_should_return_15_for_new_client(self):
customer = Customer(first_purchase_date=None,
birth_date=self.now-20*self.year,
birth_date=self.now - 20 * self.year,
is_veteran=False)
got = calculate_discount_percentage(customer)
expected = 15
self.assertEqual(got, expected)

def test_should_return_10_for_veteran(self):
customer = Customer(first_purchase_date=self.now,
birth_date=self.now-20*self.year,
birth_date=self.now - 20 * self.year,
is_veteran=True)
got = calculate_discount_percentage(customer)
expected = 10
self.assertEqual(got, expected)

def test_should_return_5_for_a_senior(self):
customer = Customer(first_purchase_date=self.now,
birth_date=self.now-65*self.year,
birth_date=self.now - 65 * self.year,
is_veteran=False)
got = calculate_discount_percentage(customer)
expected = 5
self.assertEqual(got, expected)

def test_should_return_10_for_a_loyal_customer(self):
customer = Customer(first_purchase_date=self.now-1*self.year,
birth_date=self.now-20*self.year,
customer = Customer(first_purchase_date=self.now - 1 * self.year,
birth_date=self.now - 20 * self.year,
is_veteran=False)
got = calculate_discount_percentage(customer)
expected = 10
self.assertEqual(got, expected)

def test_should_return_12_for_a_more_loyal_customer(self):
customer = Customer(first_purchase_date=self.now-5*self.year,
birth_date=self.now-20*self.year,
customer = Customer(first_purchase_date=self.now - 5 * self.year,
birth_date=self.now - 20 * self.year,
is_veteran=False)
got = calculate_discount_percentage(customer)
expected = 12
self.assertEqual(got, expected)

def test_should_return_20_for_a_most_loyal_customer(self):
customer = Customer(first_purchase_date=self.now-10*self.year,
birth_date=self.now-20*self.year,
customer = Customer(first_purchase_date=self.now - 10 * self.year,
birth_date=self.now - 20 * self.year,
is_veteran=False)
got = calculate_discount_percentage(customer)
expected = 20
self.assertEqual(got, expected)

def test_should_return_maximum_discount(self):
customer = Customer(first_purchase_date=None,
birth_date=self.now-20*self.year,
birth_date=self.now - 20 * self.year,
is_veteran=True)
# eligible for 15% discount as a new client and 10% as a veteran
got = calculate_discount_percentage(customer)
expected = 15
self.assertEqual(got, expected)


if __name__ == "__main__":
unittest.main()