Lesson Complete!

Rewrite Every Endpoint

What you rewrote

Every CRUD endpoint now uses the database session instead of the in-memory dict:

EndpointBeforeAfter
POST /expensescounter += 1, dict insert, file writesession.add, session.commit, session.refresh
GET /expensesPython loop with optional filterselect(Expense) with optional .where()
GET /expenses/{id}if expense_id not in expenses dict checksession.get(Expense, expense_id)
DELETE /expenses/{id}expenses.pop(expense_id), file writesession.delete, session.commit
PATCH /expenses/{id}dict.update(), file writesqlmodel_update, session.commit, session.refresh

The error handling, middleware, and validation are unchanged — those were already correct. Only the storage layer changed.

What comes next

The GET /summary endpoint has a temporary implementation that loops through all expenses in Python. Lesson 3 replaces it with a proper SQL aggregation query — and adds date range filtering and description search to GET /expenses while it's at it.