Skip to content

Commit

Permalink
Add basic discount codes test
Browse files Browse the repository at this point in the history
  • Loading branch information
iamareebjamal committed May 13, 2020
1 parent 230df98 commit 85c5e57
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 27 deletions.
2 changes: 1 addition & 1 deletion app/api/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ def after_create_object(self, event, data, view_kwargs):
role_name=role.title_name,
event=event,
role=role,
status='accepted'
status='accepted',
)
save_to_db(role_invite, 'Owner Role Invite Added')

Expand Down
21 changes: 14 additions & 7 deletions app/api/helpers/order.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ def calculate_order_amount(tickets, discount_code=None):
ticket_list = []
for ticket_info in tickets:
discount_amount = 0.0
discount_data = {}
discount_data = None
ticket_fee = 0.0

ticket_identifier = ticket_info['id']
Expand All @@ -209,11 +209,15 @@ def calculate_order_amount(tickets, discount_code=None):
event = ticket.event

if event.deleted_at:
raise ObjectNotFound({'pointer': 'tickets/event'}, f'Event: {event.id} not found')
raise ObjectNotFound(
{'pointer': 'tickets/event'}, f'Event: {event.id} not found'
)

fees = TicketFees.query.filter_by(currency=event.payment_currency).first()
elif ticket.event.id != event.id:
raise UnprocessableEntity({'pointer': 'tickets'}, "All tickets must belong to same event")
raise UnprocessableEntity(
{'pointer': 'tickets'}, "All tickets must belong to same event"
)

if not tax and event.tax:
tax = event.tax
Expand All @@ -223,8 +227,9 @@ def calculate_order_amount(tickets, discount_code=None):
price = ticket_info.get('price')
if not price or price > ticket.max_price or price < ticket.min_price:
raise UnprocessableEntity(
{'pointer': 'tickets/price'}, f"Price for donation ticket should be present and within range "
f"{ticket.min_price} to {ticket.max_price}"
{'pointer': 'tickets/price'},
f"Price for donation ticket should be present and within range "
f"{ticket.min_price} to {ticket.max_price}",
)
else:
price = ticket.price
Expand All @@ -242,9 +247,11 @@ def calculate_order_amount(tickets, discount_code=None):
'code': discount_code.code,
'percent': round(discount_percent, 2),
'amount': round(discount_amount, 2),
'total': round(discount_amount * quantity, 2),
}
break

total_discount = total_discount + discount_amount * quantity
total_discount += round(discount_amount * quantity, 2)
if fees and not ticket.is_fee_absorbed:
ticket_fee = fees.service_fee * (price * quantity) / 100
if ticket_fee > fees.maximum_fee:
Expand All @@ -265,7 +272,7 @@ def calculate_order_amount(tickets, discount_code=None):

sub_total = total_amount
if tax:
total_tax = total_amount * tax.rate/100
total_tax = total_amount * tax.rate / 100
if not tax_included:
total_amount += total_tax

Expand Down
13 changes: 4 additions & 9 deletions app/api/helpers/ticketing.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@
class TicketingManager:
"""All ticketing and orders related helper functions"""

@staticmethod
def get_order_expiry():
return 10

@staticmethod
def match_discount_quantity(discount_code, tickets=None, ticket_holders=None):
qty = 0
Expand All @@ -44,14 +40,13 @@ def match_discount_quantity(discount_code, tickets=None, ticket_holders=None):
elif tickets:
for ticket in tickets:
if int(ticket['id']) in ticket_ids:
qty += ticket['quantity']
if (
qty += ticket.get('quantity', 1)
return (
(qty + old_holders) <= discount_code.tickets_number
and discount_code.min_quantity <= qty <= discount_code.max_quantity
):
return True
return False
)

# TODO(Areeb): Remove after validating logic
@staticmethod
def calculate_update_amount(order):
discount = None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from app.api.helpers.exceptions import UnprocessableEntity
from app.api.helpers.order import calculate_order_amount
from tests.factories.discount_code import DiscountCodeTicketSubFactory
from tests.factories.event import EventFactoryBasic
from tests.factories.tax import TaxSubFactory
from tests.factories.ticket import TicketSubFactory
Expand Down Expand Up @@ -40,7 +41,10 @@ def test_single_ticket(db):


def _create_ticket_dict(tickets, quantities):
return [dict(id=ticket.id, quantity=quantity) for ticket, quantity in zip(tickets, quantities)]
return [
dict(id=ticket.id, quantity=quantity)
for ticket, quantity in zip(tickets, quantities)
]


def test_multiple_tickets_different_event(db):
Expand All @@ -51,7 +55,9 @@ def test_multiple_tickets_different_event(db):

ticket_dict = _create_ticket_dict([ticket1, ticket2], [1, 2])

with pytest.raises(UnprocessableEntity, match='All tickets must belong to same event'):
with pytest.raises(
UnprocessableEntity, match='All tickets must belong to same event'
):
calculate_order_amount(ticket_dict)


Expand Down Expand Up @@ -89,15 +95,20 @@ def _create_tickets(prices, **kwargs):
def _create_donation_tickets(db):
event = EventFactoryBasic()
tickets = _create_tickets([10, 20], event=event)
tickets.append(TicketSubFactory(type='donation', max_price=20, min_price=10, event=event))
tickets.append(
TicketSubFactory(type='donation', max_price=20, min_price=10, event=event)
)
db.session.commit()

return _create_ticket_dict(tickets, [3, 1, 2])


def _expect_donation_error(ticket_dict):
with pytest.raises(UnprocessableEntity, match='Price for donation ticket should be present and within range '
'10.0 to 20.0'):
with pytest.raises(
UnprocessableEntity,
match='Price for donation ticket should be present and within range '
'10.0 to 20.0',
):
calculate_order_amount(ticket_dict)


Expand Down Expand Up @@ -142,7 +153,11 @@ def test_donation_ticket(db):
def _create_taxed_tickets(db, tax_included=True):
tax = TaxSubFactory(rate=18.0, is_tax_included_in_price=tax_included)
tickets = _create_tickets([123.5, 456.3], event=tax.event)
tickets.append(TicketSubFactory(type='donation', event=tax.event, min_price=500.0, max_price=1000.0))
tickets.append(
TicketSubFactory(
type='donation', event=tax.event, min_price=500.0, max_price=1000.0
)
)
db.session.commit()

tickets_dict = _create_ticket_dict(tickets, [2, 4, 3])
Expand Down Expand Up @@ -177,6 +192,68 @@ def test_tax_excluded(db):
assert amount_data['discount'] == 0.0


def test_discount_code(db):
ticket = TicketSubFactory(price=100.0)
discount_code = DiscountCodeTicketSubFactory(
type='percent', value=10.0, tickets=[ticket]
)
db.session.commit()

amount_data = calculate_order_amount([{'id': ticket.id}], discount_code)

assert amount_data['total'] == 90.0
assert amount_data['tax_included'] is None
assert amount_data['tax'] == 0.0
assert amount_data['discount'] == 10.0
ticket_dict = amount_data['tickets'][0]
assert ticket_dict['id'] == ticket.id
assert ticket_dict['name'] == ticket.name
assert ticket_dict['price'] == ticket.price
assert ticket_dict['quantity'] == 1
assert ticket_dict['ticket_fee'] == 0.0
assert ticket_dict['sub_total'] == 90.0
assert ticket_dict['discount']['total'] == 10.0
assert ticket_dict['discount']['amount'] == 10.0
assert ticket_dict['discount']['percent'] == 10.0
assert ticket_dict['discount']['code'] == discount_code.code


def test_multiple_tickets_discount(db):
ticket_a = TicketSubFactory(price=50.0)
ticket_b = TicketSubFactory(price=495.8, event=ticket_a.event)
ticket_c = TicketSubFactory(price=321.3, event=ticket_a.event)

discount = DiscountCodeTicketSubFactory(
type='percent', value=50.0, tickets=[ticket_a, ticket_b]
)
DiscountCodeTicketSubFactory(type='amount', value=100.0, tickets=[ticket_c])

db.session.commit()

tickets_dict = _create_ticket_dict([ticket_a, ticket_b, ticket_c], [2, 3, 1])

amount_data = calculate_order_amount(tickets_dict, discount)

assert amount_data['total'] == 1115.0
assert amount_data['discount'] == 793.7
assert amount_data['tickets'][0]['quantity'] == 2
assert amount_data['tickets'][0]['price'] == 50.0
assert amount_data['tickets'][0]['sub_total'] == 50.0
assert amount_data['tickets'][0]['discount']['total'] == 50.0
assert amount_data['tickets'][0]['discount']['amount'] == 25.0
assert amount_data['tickets'][0]['discount']['percent'] == 50.0
assert amount_data['tickets'][1]['quantity'] == 3
assert amount_data['tickets'][1]['price'] == 495.8
assert amount_data['tickets'][1]['sub_total'] == 743.7
assert amount_data['tickets'][1]['discount']['total'] == 743.7
assert amount_data['tickets'][1]['discount']['amount'] == 247.9
assert amount_data['tickets'][1]['discount']['percent'] == 50.0
assert amount_data['tickets'][2]['quantity'] == 1
assert amount_data['tickets'][2]['price'] == 321.3
assert amount_data['tickets'][2]['sub_total'] == 321.3
assert amount_data['tickets'][2]['discount'] is None


def test_deleted_ticket(db):
ticket = TicketSubFactory(deleted_at=datetime.now())
db.session.commit()
Expand Down
15 changes: 11 additions & 4 deletions tests/factories/discount_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Meta:
type = "amount"
is_active = True
tickets_number = 30
min_quantity = 10
min_quantity = 1
max_quantity = 20
valid_from = common.date_
valid_till = common.dateEnd_
Expand All @@ -28,12 +28,10 @@ class Meta:
event_id = None


class DiscountCodeTicketFactory(BaseFactory):
class DiscountCodeTicketFactoryBase(BaseFactory):
class Meta:
model = DiscountCode

marketer = factory.RelatedFactory(UserFactory)
tickets = factory.RelatedFactory(TicketFactory)
code = common.string_
discount_url = common.url_
value = common.float_
Expand All @@ -45,5 +43,14 @@ class Meta:
valid_from = common.date_
valid_till = common.dateEnd_
used_for = "ticket"


class DiscountCodeTicketSubFactory(DiscountCodeTicketFactoryBase):
tickets = factory.SubFactory(TicketFactory)


class DiscountCodeTicketFactory(DiscountCodeTicketFactoryBase):
marketer = factory.RelatedFactory(UserFactory)
tickets = factory.RelatedFactory(TicketFactory)
marketer_id = 1
event_id = None

0 comments on commit 85c5e57

Please sign in to comment.