Course content

Module 1

Module 2

Module 3

Module 4

Module 5

Module 6

Module 7

Module 8

Module 9

Module 10

Module 11

Module 12

Module 13

Module 14

Module 15

Module 16

Module 17

Module 18

4 to 6 hours

Final Project: Mini Order Management System

Translate a small business brief into a tested modular program

By the end of this lesson

  • Translate a small business brief into a tested modular program
  • Explain validation, rounding and reporting policies

Your mission

Build an in-memory order program that validates records, calculates quotes, searches and filters orders, and produces a summary. It is a small program with realistic decisions, not a SaaS application. No DOM, database, payment system or real API is required.

Work independently first. A complete reference implementation and test suite is available for comparison after your attempt. It contains .mjs modules and runs with Node without external packages.

Start with a precise brief

An order has a nonempty string id, a customer record and at least one item. The customer has a nonempty name, a type of standard or premium, and a Boolean active field. An inactive customer cannot receive a quote under this exercise's policy.

Each item has a nonempty name, a nonnegative integer unitPriceCents and a positive integer quantity. Amounts and products must stay within JavaScript's safe integer range. A missing array, missing property, numeric string or fractional quantity is invalid. Do not silently convert or drop it.

Represent money in integer cents to make units explicit. We assume a currency with 100 cents per unit. Real systems may need other monetary conventions; those are outside this exercise.

Confirm the pricing policy

  1. Sum unitPriceCents multiplied by quantity for every item.
  2. An active premium customer receives a 10% discount when the subtotal is strictly greater than 10,000 cents.
  3. Round the discount to the nearest whole cent using Math.round; for nonnegative half-cent values this rounds upward.
  4. Apply 20% exercise tax to the discounted subtotal and round that tax to the nearest cent using the same rule.
  5. Add discounted subtotal and tax. There is no delivery charge or promotion stacking in this project.

These fictional policies are fully specified so you can test them. They do not describe actual tax obligations.

Predict before implementing

Case Subtotal Discount Tax Total
Standard customer, one 10,000-cent item 10000 0 2000 12000
Premium customer, exactly 10,000 cents 10000 0 2000 12000
Premium customer, 15,000 cents 15000 1500 2700 16200
Standard customer, a 103-cent item 103 0 21 124
Inactive customer ? ? ? Reject

Compute the table by hand. A successful normal quote is insufficient: the exact threshold and a fractional tax case reveal different decisions.

Design the data and responsibilities

validation.mjs: validate the order, customer, items and collection ids
pricing.mjs: calculate subtotal, eligibility, discount, tax and total
orders.mjs: search, filter and summarize valid and invalid orders
main.mjs: prepare sample input and display results
tests.mjs: execute behavioral checks

The reference keeps calculation helpers together rather than creating one file per formula. A quote returns its component amounts so the result can be explained. Query functions return matching source records without modifying them.

Define reporting rules too

Order ids must be unique within a collection. Reject a duplicate-id collection because a search would otherwise be ambiguous. Structural errors in a record should be identified, not omitted from a report silently.

A summary contains accepted quotes and invalid records with reasons. Its total counts only valid quotes and must be labeled as such. For an empty collection, accepted and invalid lists are empty, total is zero and average is null. A non-array input is invalid.

Searching a valid unique collection by id returns the matching record or null. Filtering by customer type returns an array. These operations do not themselves approve an order: quote validation makes that decision.

Implement in deliberate stages

  1. Write requirements and open questions in your own words.
  2. Create your expected-result table, including missing data and boundaries.
  3. Write validation before arithmetic can consume invalid inputs.
  4. Implement one quote and test its component amounts.
  5. Add collection queries and the summary.
  6. Separate modules once responsibilities are clear.
  7. Run the complete suite after each refactor.

Do not add an interface to conceal an uncertain rule. A console report is enough to demonstrate correctness at this stage.

Required tests

Cover standard and premium customers, the exact threshold, above-threshold eligibility, inactive customers, missing names, unsupported customer types, no items, zero quantity, fractional quantity, text prices, nonfinite amounts, unsafe totals, rounding, duplicate ids, empty collections, absent searches and input immutability.

Include a mixed collection with one valid and one invalid order. Verify that the invalid record is reported and excluded from the financial total. Test the returned details, not only whether the function completed.

Run the reference after your attempt

Extract the download. In its folder run node tests.mjs, then node main.mjs. Read README.md for module responsibilities and expected output. The reference's error strings are implementation choices; your solution can use other clear wording if its failure behavior remains explicit and tested.

Change request: demonstrate your mindset

The owner changes eligibility to "10,000 cents or more." Before changing code, identify the expected row that changes. Then add a second request: "special discounts for some customers." Explain why the second request cannot yet be implemented faithfully.

Review and correction

At exactly 10,000 cents, a premium quote now has discount 1000, discounted subtotal 9000, tax 1800 and total 10800. The standard quote remains 12000. The 15,000-cent premium case stays 16200. Special discounts still require eligibility, rate, priority and combination rules. List those questions rather than inventing answers.

Submission rubric

Area Weight Evidence
Understanding and policy 25% Clear rules, units, assumptions and examples
Correct behavior 25% Valid quotes, explicit rejection and honest reports
Tests 20% Boundaries, failure cases and unchanged input
Organization 15% Responsibilities and readable function contracts
Reasoning and revision 15% Counterexample, alternatives and change analysis

Submit your source, test command, brief and decision journal. Explain what remains outside scope, such as persistence and concurrency. A maintainable program makes both its behavior and its limits understandable.

Lesson complete?

Your progress is saved on this device.