Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Low-Level Design (Object-Oriented Design)  Module 14 – Case studies: money and commerce

Low-level design: shopping cart and discount engine

Design a shopping cart and discount engine: each rule as eligibility plus an action, a stated stacking order, exact paise and a receipt that explains.

  • Intermediate
  • 40 minutes
  • Examples run with Python 3.14.8, Pyodide 314.0.7 and Node.js 24.21.0
  • By MySmartCoPilot
Free intro, Pro: 8 of 40 minutes free
Free: The prompt, the rules and the questions it must answer. With a pass: the other 13 sections and 3 interview answers, about 32 minutes.

What you will learn

  • Model carts, items, prices and checkout
  • Apply stackable and exclusive discounts in a defined order
  • Explain every discount on the receipt
  • Split an order discount over its lines for refunds and tax

Before you start

What you’ll learn · Before you start

What you will learn

  • Model carts, items, prices and checkout
  • Apply stackable and exclusive discounts in a defined order
  • Explain every discount on the receipt
  • Split an order discount over its lines for refunds and tax

Before you start

On this page

Designing a shopping cart with a discount engine in a low-level design (LLD) round means modelling what a customer has picked, pricing it at checkout and taking discounts off in a way anyone can check later. The cart stays small: lines of a product and a quantity, each remembering the price the customer saw. Every discount is a rule with two parts, a specification that says who is eligible and an action that says how much comes off. An engine runs the rules in an order that is written down, item rules before order rules and each by its priority, and rules of an exclusive group compete so that only the best applies. Its receipt names each rule that applied, with its amount, and each rule that did not, with the reason.

The prompt, the rules and the questions it must answer

The prompt is usually one line, “design a shopping cart with discounts”, and the details it leaves out decide the design. So ask first. Are prices fixed when an item goes into the cart or when the customer pays? Can two discounts apply to one order? Is a threshold such as “300 off from 3,000” checked before or after the other discounts? How are fractions of a paisa rounded? Can a customer return part of an order? With the answers, the rules read:

  • R1 A cart belongs to one customer and holds lines of a product and a quantity from 1 to 10; adding a product again raises its quantity.
  • R2 Prices are whole paise. A line remembers the price shown when it was added; checkout prices every line from the current price book and shows what changed.
  • R3 A discount is a rule: a specification of who is eligible plus an action for the amount.
  • R4 Item rules run first and change lines. Order rules run after them, and their conditions see the amount the item rules left. Within a phase, rules run by priority.
  • R5 Rules of one exclusive group never stack: the one that saves the customer most applies, and a tie goes to the earlier rule.
  • R6 No line and no order goes below zero.
  • R7 A percentage is rounded to the paisa once per line, with half a paisa going up.
  • R8 The receipt lists every applied rule with its amount, and every rule that did not apply with its reason.
  • R9 An order carries at most one coupon code.
  • R10 Order discounts are shared over the lines, so that refunds and tax can be worked out per line.

Four responsibilities give four groups of classes: the cart and its lines, the price book, the rules with their specifications and actions, and the engine with the receipt it returns.

Class diagram: a cart of lines, a price book, and an engine that runs rules made of a Spec and an Action, then returns a receipt.Cart+customerstr+codestr | None+add(sku, quantity)+remove(sku)+enter_code(code)CartLine+skustr+quantityint+seen_priceMoneyPriceBook+versionint+price(sku)MoneyDiscountEngine+checkout(cart, prices)ReceiptRule+id, labelstr+phaseitem | order+priorityint+groupstr | None«interface»Spec+is_satisfied_by(x)bool+why_not(x)str | None«interface»Action+on_line(line)Money+on_order(amount)MoneyReceipt+lineslist[PricedLine]+order_adjustmentslist[Adjustment]+skippedlist[(rule, reason)]+total()Money+order_shares()sku → Moneylines0..*1runs, in order1..*when, linesactionprices at checkoutcreatesreads

The cart, the rules and the receipt

Text description of the diagram

The diagram shows eight classes in UML notation. Each box names a class, then lists its attributes with their types and, below a line, its operations.

  • Cart has a customer and an optional coupon code, and the operations add(sku, quantity), remove(sku) and enter_code(code). It is composed of zero or more CartLines: a filled diamond sits at the Cart end of the line labelled "lines".
  • CartLine has a sku, a quantity and seen_price, the price the customer was shown when the line was added.
  • PriceBook has a version number and the operation price(sku), which returns Money.
  • DiscountEngine has one operation, checkout(cart, prices), which returns a Receipt. Dashed arrows show that it reads the Cart, takes prices from the PriceBook at checkout and creates the Receipt. A solid arrow labelled "runs, in order", with the multiplicity 1..* at the far end, leads to Rule.
  • Rule has an id and a label, a phase (item or order), a priority and an optional exclusive group. Two arrows lead from it: "when, lines" to the Spec interface and "action" to the Action interface.
  • Spec is an interface with is_satisfied_by(x), which returns a boolean, and why_not(x), which returns the reason a candidate fails or nothing.
  • Action is an interface with on_line(line) and on_order(amount), both returning Money.
  • Receipt holds the priced lines, the order adjustments and the rules that were skipped with their reasons, and has the operations total() and order_shares(), which returns an amount of Money for each product.

Asha’s cart holds three blue T-shirts at 499.00, running shoes at 2,499.00 and two packs of socks at 199.00, and she types the code BIG300, which takes 300 off orders of 3,000.00 or more. The rules above give this receipt:

Step Rule Amount
Subtotal 4,394.00
Item rule B2G1-TS: buy two T-shirts, get one free −499.00
Item rule FOOT20: 20 % off footwear −499.80
After item discounts 3,395.20
Order rule BIG300: 300 off from 3,000.00 −300.00
To pay 3,095.20

The order of the rows is part of the design. Had the coupon’s condition been checked against the subtotal of 4,394.00, a coupon for orders of 3,500.00 would have applied as well, although the goods now cost 3,395.20.

The rest of this case study answers the six questions an interviewer is likely to ask next:

  1. What does the model look like in code, and what does it print for four checkouts?
  2. How do specifications and actions combine, and how does a rule explain why it did not apply?
  3. Which mistakes in the order of rules give money away, and which tests catch them?
  4. Does rounding per line or once per order change the total, and by how much?
  5. How much does a customer get back for one returned item from a discounted order?
  6. When is the best combination of offers a search, and where do new rules land?

The model in Python, run on four checkouts Pro: opens with a Pro, Premium or Ultimate pass

In this part:

  • What a rule is made of: specifications and actions
  • Mistakes in the order of rules, each caught by a test
  • Rounding per line or once per order, measured on 9,154 carts
  • Sharing an order discount over the lines: refunds and tax
  • When the best combination of offers is a search
  • Patterns used, and the ones left out
  • Follow-up questions and where each change lands
  • Practise: a cheapest-item-free rule and coupon limits
    • Add a cheapest-item-free rule and coupon limits per customer
  • What each level is expected to cover
  • A 45-minute self-mock
  • Check yourself
  • Interview questions
    • What is the difference between a stackable discount and an exclusive one, and how should an engine choose between two exclusive offers?
    • A coupon takes 350 off orders of 3,500 or more. An order of 4,394 falls to 3,395 after a footwear sale and a buy-two-get-one offer, yet the coupon was applied. What is wrong with the design, how do you fix it, and how do you keep it fixed?
    • An order of three lines used a coupon of 300 off from 3,000. The customer returns the socks, a line that cost 398 after item discounts, and what she keeps now costs 2,997. How much do you refund, and what must the design record at checkout so that the answer is exact to the paisa?
    • Marketing wants every customer to get the best combination of offers automatically. Forty promotions are active: some exclusive, some stackable, some with a minimum amount. How do you design the best deal, and when does it get too slow?
  • Key takeaways

5 runnable examples (Python, cart.py, engine.py, money.py, receipt_demo.py, rules.py, shop.py) · 1 exercise with sample tests · 3 interview answers · about 32 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; nothing renews unless you choose to. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Read a complete sample first: Low-level design: parking lot (the model)

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.