Several Changes, One Outcome · practice
Refuse a Second Active Checkout
The schema permits several loan rows for one item because returned rows are valuable history. That also means the schema alone permits two active rows. The checkout operation must refuse the second one.
Open transactions.py. The new checkout_loan(connection, loan) receives one four-(item_id,) and fetch one optional row.
If a row is present, raise this exact error:
raise ValueError("That item is already checked out.")
Keep the check inside with connection: beside the insert so a refusal exits through the same failure path as an insert error. Returned history does not match because its returned_on value is present.
This program handles one checkout at a time. With the connection settings used here, entering with connection: does not itself start a transaction; the first insert starts it. The earlier read does not reserve the item. Two programs writing at once would need additional protection against both seeing the item as available.
The loan_id from the tuple.
Press Run. The first fixed call uses item 1, which already has active loan 501, and should show:
ValueError: That item is already checked out.
On a separate database, Sam checks out available items 4 and 5. Both currently succeed because the function protects the item, not the member’s limit. The reopened active count for Sam becomes 3. That visible over-limit result shows the second rule the operation still needs.
Submit tests an active item, an item with only returned history, and a never-loaned item. It passes SQL-looking date text as ordinary data and uses IDs absent from the prompt. It also checks that missing items and members still raise sqlite3.IntegrityError, successful work is visible after reopening, and the supplied connection remains open.
Task
Complete the active-item guard in checkout_loan(connection, loan). Query for the proposed item_id with returned_on IS NULL inside the same connection context.
If a row exists, raise ValueError("That item is already checked out."). Otherwise insert the bound