runtime
46 / 250
lesson 46 Fundamentals Integration · beginner

Price an order from its lines

An order total is a chain of small rules: line amounts, discounts, a coupon, shipping. One function per rule keeps each rule readable and testable on its own.

You'll be able to
  • Split a pricing job into one function per rule, each returning a number
  • Apply rules in the right order: line discounts, then the coupon, then shipping
  • Reuse the pricing functions to compare several orders
The idea

A checkout page answers one question, *what does this order cost?*, but the answer depends on several rules applied in order. Written as one long block, those rules tangle together; written as small functions, each one can be read, tested and changed alone.

This lesson adds nothing new to the language. It uses lists of dictionaries (see Dictionaries & Sets), functions with defaults and return values (see Functions) and f-strings (see Strings & Text) together, in the order a real checkout applies them.

Run each example to see what it prints. Running examples doesn't count toward progress.

example-1.py · One order, three small functions
def line_amount(line):
    """Return quantity times price for one order line."""
    return line["quantity"] * line["price"]

def shipping(subtotal, free_from=50):
    """Return the shipping fee for a subtotal."""
    if subtotal >= free_from:
        return 0
    return 5.99

def order_total(lines):
    """Return the subtotal of all lines plus shipping."""
    subtotal = 0
    for line in lines:
        subtotal = subtotal + line_amount(line)
    return subtotal + shipping(subtotal)

lines = [
    {"sku": "HOM-22847", "quantity": 2, "price": 15.5},
    {"sku": "SPO-11681", "quantity": 1, "price": 7.49},
]
for line in lines:
    print(f"{line['sku']}  {line_amount(line):>6.2f}")
print(f"total     {order_total(lines):>6.2f}")

Once orders are priced by a function, questions about many orders are just loops that call it. Here the same order_total ranks a day's orders and flags the ones that will need a signature on delivery. The order ID and the lines live together in a dictionary, the shape an online shop's API would send.

example-2.py · A day's orders, priced and ranked
def line_amount(line):
    return line["quantity"] * line["price"]

def order_total(lines, free_from=50):
    subtotal = 0
    for line in lines:
        subtotal = subtotal + line_amount(line)
    if subtotal >= free_from:
        return subtotal
    return subtotal + 5.99

orders = [
    {"order_id": "O100043", "lines": [{"quantity": 1, "price": 6.49}]},
    {"order_id": "O104839", "lines": [{"quantity": 1, "price": 51.49}, {"quantity": 2, "price": 15.99}]},
    {"order_id": "O101217", "lines": [{"quantity": 3, "price": 12.0}]},
]
biggest = None
for order in orders:
    total = order_total(order["lines"])
    flag = "  signature" if total >= 80 else ""
    print(f"{order['order_id']} {total:>7.2f}{flag}")
    if biggest is None or total > biggest[1]:
        biggest = (order["order_id"], total)
print("largest:", biggest[0])

When to use it: any calculation with several rules. Give each rule a function with a name that says what it decides, pass in what it needs, and return a number. Mistakes to avoid:

  • Applying rules in the wrong order: a coupon usually comes off before the free-shipping check, not after.
  • Printing inside the pricing functions, which makes them useless for comparisons and totals.
  • Repeating a rule's arithmetic in two places instead of calling its function.
Review
  • Price an order with one function per rule: line amount, discounts, coupon, shipping.
  • Apply the rules in the order the business applies them, and return numbers rather than printing them.
  • Questions about many orders are loops that call the same functions.
  • Next: summarise a list of records, the films in Runtime Films' catalogue.
Practise this

Loading your progress…

To master this lesson, solve both challenges without hints or the answer, and pass the concept check.

Price an order from its lines — Fundamentals Integration · Runtime