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: .run gives back a result, and its lastInsertRowid holds the new id. 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. Each .run saves its row the moment it finishes: the order first, then its items one by one. 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: add POST /orders. 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 add the route POST /orders.
Hint
Keep result.lastInsertRowid right after the order's INSERT: every item row needs it. Check for an empty items array right after reading the body, before the first INSERT.
Free plan: 30 tutor messages. PRO is unlimited.
