Bluepine Supply — product requirements
This product is a B2B office-supply store. A buyer signs in, browses an eight-product catalog by category and price, builds a cart with an optional promo code, checks out with a name, email and delivery address, reviews paginated order history and manages account settings. The same pricing and order rules are exposed through a REST API.
Problem. Procurement buyers need to order everyday supplies quickly and trust that every price, discount, tax amount and order number on screen is exact.
Users
- Office buyer — Find items, see an exact total with tax and discount, and place an order with clear confirmation.
- Accounts payable contact — Keep a billing email on file and look back at past orders.
- Integrator — Price carts and place orders through an API that agrees with the website to the cent.
Goals
- Line totals, sub-total, discount, tax and total always reconcile to the cent, in the UI and the API.
- Invalid input is rejected with a specific, correct message before an order is created.
- Browsing (filter, sort, pages) always shows exactly the items the control promises.
Out of scope
- Payment: orders are placed without one
- Email delivery
Contents
Sign-in
Buyer login and logout.
- The sign-in page shows the store name as its heading and a hint about the demo account
- After sign-in: heading "Catalog", header "Hi, Buyer", navigation Catalog / Cart (0) / Orders / Settings
- 8 product cards, each with name, "<Category> · <SKU>", price and "Add to cart"
- Alert reads exactly "Incorrect username or password."
- Usernames are case-sensitive
Catalog
Eight products with category filter, price sort and a support link.
- Paper (3): A4 copy paper, Sticky notes, Spiral notebook
- Pens (2): Gel pens 10 pack, Highlighters 6 colours
- Desk (3): Desk stapler, Monitor stand, Desk organiser
- All: 8 products
- Low to high: Sticky notes $4.25, Highlighters $5.75, Gel pens $6.99, A4 copy paper $9.49, Spiral notebook $12.50, Desk stapler $14.99, Desk organiser $21.50, Monitor stand $32.00
- Desk with high to low: Monitor stand, Desk organiser, Desk stapler
Cart, promo code and tax
Quantities, line totals, SAVE10 promo code and 8% tax.
- Adding "Gel pens, 10 pack" shows status "Gel pens, 10 pack added to cart." and "Cart (1)"
- Adding it again and then "Desk stapler" shows "Cart (3)" while still on Catalog
- 2 × A4 copy paper $9.49 + 1 × Monitor stand $32.00: lines $18.98 and $32.00, Sub-total $50.98, Tax (8%) $4.08, Total $55.06
- Tax on a $45.88 amount is $3.67 (not rounded up)
- Entering "save10" in the promo-code field on the $50.98 basket: Discount (SAVE10) -$5.10, Tax (8%) $3.67, Total $49.55
- "SAVE50" shows an alert of the form "That <promo> code is not valid."; the Discount row disappears and Total returns to $55.06
- A4 copy paper quantity 1: line $9.49, Sub-total $41.49, Tax $3.32, Total $44.81, "Cart (2)"
- Quantity 0 snaps back to 1
- Removing every line shows "Your cart is empty." and "Cart (0)"
Checkout and confirmation
Validate delivery details, place the order, confirm.
- Checkout shows "3 item(s) · $55.06 including tax"
- Empty form: "Enter your full name.", "Enter a valid email address.", "Enter a delivery address."; fields are aria-invalid="true"
- Email "ada@example" (no domain dot) leaves only "Enter a valid email address."
- Confirmation reads "Order BP-1241 was placed: 3 item(s), $49.55." for the promo-code basket
- Navigation reads "Cart (0)"
- Orders first row: BP-1241 · 2026-10-02 · 3 · $49.55, "Page 1 of 3"
- #/confirmation: "There is no recent order to show." with "Continue shopping"
- #/checkout with an empty cart: "Your cart is empty."
- Unknown routes show the Catalog
Order history
Twelve seeded orders, newest first, five per page.
- Page 1: BP-1240 2026-09-28 1 $19.99; BP-1239 2026-09-26 2 $27.34; BP-1238 3 $34.69; BP-1237 4 $42.04; BP-1236 1 $49.39; "Page 1 of 3"; "Previous" disabled
- Page 2: BP-1235 … BP-1231, button 2 has aria-current="page"
- Page 3: BP-1230 and BP-1229 only; "Next" disabled
Settings
Display name and billing email.
- Defaults: Display name "Buyer" and a seeded billing email
- Saving "Ada" shows "Settings saved." and header "Hi, Ada"; after reload both values are kept
- A 31-character address is saved in full
- The field keeps at most 40 characters (maxlength 40)
- API: 40 characters returns 200; 41 returns 422 "Billing email must be at most 40 characters."
REST API
Bearer-token API mirroring the website.
- GET /orders without a token returns 401
- POST /auth/login with a wrong password returns 401 "Invalid credentials"; a valid login returns 200 with token and user
- GET /products?category=Desk&sort=price-desc returns BP-302, BP-303, BP-301 and supportEmail
- POST /cart/quote with BP-101 ×2, BP-302 ×1 and promo code "save10": items 3, sub-total 5098, discount 510, tax 367, total 4955
- Promo code "SAVE50" returns 422 with the same "... code is not valid." message as the website
- Validating " save10 " (padded, lower-case) returns valid true, code "SAVE10", percent 10
- GET /orders: total 12, pages 3, pageSize 5, first BP-1240 placed 2026-09-28, items 1, total 1999; page=3 gives BP-1230, BP-1229
- POST /orders with empty fields returns 422 with errors for name, email, address and lines ("Your cart is empty.")
- A valid order returns 201 id BP-1241, placed 2026-10-02, items 3, total 4955
- GET /orders/BP-1241 returns 200; /orders/BP-9999 returns 404 not_found
Non-functional requirements
Glossary and rules
| SAVE10 | The only valid promo code; 10% off the sub-total, applied before tax. |
|---|---|
| Units | Sum of quantities across cart lines; this is what the Cart badge shows. |