The checkout that never oversells
Dishes now have stock. Checkout must reserve stock for every line and create the order — or do nothing at all. Then report the best sellers.
Reserve stock safely
This capstone ties the whole course together in one realistic feature.
The heart of checkout is "take qty from stock only if at least qty is left." Putting the condition in the update's where makes the database check and change in one atomic step. updateMany returns how many rows it changed: 0 means not enough stock, so throw — and the transaction rolls back every reservation made for earlier lines.
for (const line of lines) {
const { count } = await tx.dish.updateMany({
where: { name: line.dish, stock: { gte: line.qty } },
data: { stock: { decrement: line.qty } },
});
if (count === 0) throw new Error(`Not enough ${line.dish}`);
}Two customers buying the last momo at the same moment: one update matches, the other gets count 0. No overselling.