Total a Shopping Cart
The checkout page needs a cart total with two discount codes. The README has the rules, and cart.py has the shape of the code. Build it with the assistant: accept, edit, or reject each suggestion, and keep the tests green.
cart.py1 of 3
Files
cart.py
Python · Editablefrom decimal import Decimal
CODES = {
"SAVE10": ("percent", Decimal("10")),
"TAKE5": ("flat", Decimal("5.00")),
}
def line_total(unit_price, quantity):
"""unit_price is a string such as "4.99". Returns a Decimal."""
return Decimal(unit_price) * quantity
def subtotal(lines):
"""lines is a list of (sku, unit_price, quantity) tuples."""
raise NotImplementedError
def apply_code(amount, code):
"""Returns the amount after the discount code. Unknown codes change nothing."""
if code not in CODES:
return amount
kind, value = CODES[code]
return amount
def to_cents(amount):
"""Rounds to whole cents, half up, the way the payment provider does."""
return amount
def cart_total(lines, code=None):
return to_cents(apply_code(subtotal(lines), code))
from decimal import Decimal
import pytest
from cart import cart_total, line_total, subtotal
LINES = [("mug", "12.50", 2), ("tea", "4.99", 3)]
def test_subtotal_adds_every_line():
assert subtotal(LINES) == Decimal("39.97")
def test_empty_cart_totals_zero():
assert cart_total([]) == Decimal("0.00")
def test_percent_code():
assert cart_total(LINES, "SAVE10") == Decimal("35.97")
def test_flat_code():
assert cart_total(LINES, "TAKE5") == Decimal("34.97")
def test_flat_code_never_goes_below_zero():
assert cart_total([("sticker", "3.00", 1)], "TAKE5") == Decimal("0.00")
def test_unknown_code_changes_nothing():
assert cart_total(LINES, "FREESHIP") == Decimal("39.97")
def test_total_rounds_half_up_to_cents():
assert cart_total([("pen", "1.25", 1)], "SAVE10") == Decimal("1.13")
def test_rejects_bad_quantities():
for quantity in [0, -1, 1.5]:
with pytest.raises(ValueError):
line_total("1.00", quantity)
# Cart Totals
The checkout page shows a cart total from cart_total (cart.py). Prices arrive as strings, such as "4.99", and all math uses Decimal so no cents are lost to floating point.
## Rules
- A line's total is its unit price times its quantity. Quantity is a whole number of at least 1.
- The subtotal is the sum of every line. An empty cart totals 0.00.
- SAVE10 takes 10% off the subtotal. TAKE5 takes 5.00 off, and a cart never totals less than 0.00.
- Unknown codes change nothing.
- The total is rounded to whole cents, half up, so 1.125 becomes 1.13.
The tests are in test_cart.py.
Test Output
No runs yet.