So far, clients could only read orders. Now they place them: a POST to /orders with a JSON body that names the customer and lists the items, each with a product_id and a quantity.
One order is saved as several rows: first one row in orders, then one row in order_items per item. Every item row needs the order's id, which the database only gives when the order's row is inserted: result.lastInsertRowid holds it. Here is the idea on two other tables, a reading list and its books:
const result = db.prepare("INSERT INTO lists (owner) VALUES (?)").run("Mia");
const listId = result.lastInsertRowid;
for (const title of ["Dune", "Emma"]) {
db.prepare("INSERT INTO list_books (list_id, title) VALUES (?, ?)").run(listId, title);
}
The client only chooses the customer and the items. The shop sets the rest itself: the date (SQLite's date('now')), the status 'new', and each item's unit_price, read from products at the moment of the order. With node:sqlite, every run is saved in shop.db right away, so there is no commit to write. An order without items is refused with 400, before anything is written.
Your route must give these answers, in this order:
POST /orders {"customer_id": 5, "items": [{"product_id": 6, "quantity": 1}, {"product_id": 4, "quantity": 3}]} → 201 {"id": 8}
GET /orders/8/items → 200 {"order_id": 8, "items": [{"name": "Teapot", "quantity": 1, "unit_price": 22}, {"name": "Pen", "quantity": 3, "unit_price": 2}], "total": 28}
GET /orders/8 → 200 {"id": 8, "ordered": (today's date), "status": "new", "customer": "Eva Rossi"}
POST /orders {"customer_id": 1, "items": [{"product_id": 8, "quantity": 2}]} → 201 {"id": 9}
GET /orders/9/items → 200 {"order_id": 9, "items": [{"name": "Gift card", "quantity": 2, "unit_price": 50}], "total": 100}
POST /orders {"customer_id": 2, "items": []} → 400 {"error": "An order needs at least one item"}
The check also reads shop.db: orders 8 and 9 must be saved, dated today, with the status new and their items, and nothing must be saved for the refused order.
Your task: fill in POST /orders (the route and its data are already there). It inserts the order and one row per item, and answers 201 with the new order's id, or 400 when the list of items is empty.
Assignment
Follow the Coding Tutorial to fill in the POST /orders route.
Hint
Keep result.lastInsertRowid right after the order's INSERT: every item row needs it. Check for an empty data.items right after reading the body, before the first INSERT.
Free plan: 30 tutor messages. PRO is unlimited.
