0%

Put a Python Boundary Around the Database · capstone

Capstone project: Project: Complete the Catalog Database Module

One caller can now complete a checkout-and-return journey through a small, honest database :

Available before checkout: ['IT-100', 'IT-200', 'IT-400', 'IT-500']
checkout_item(...) -> 9001
Available after checkout: ['IT-200', 'IT-400', 'IT-500']
return_loan(connection, 9001, '2026-08-27') -> True
Available after return: ['IT-100', 'IT-200', 'IT-400', 'IT-500']

Your final task is to complete return_loan(connection, loan_id, returned_on) in catalog_db.py. It identifies a loan by its own ID, not by item ID, and changes only an active loan:

UPDATE loans
SET returned_on = ?
WHERE id = ? AND returned_on IS NULL;

Run that parameterized update inside with connection:. Bind (returned_on, loan_id) in placeholder order. Before leaving the block, turn the affected-row evidence into a with result.rowcount == 1; return that boolean after the context has committed.

The first call for an active loan returns True. A repeated call returns False and must not overwrite the first return date. A missing loan also returns False. This operation does not catch or translate , and it never closes the supplied connection.

Keep the other three public intact. The completed module’s promises are:

  • open_database(database_path) returns a configured live connection.

  • list_available_items(connection) returns plain in asset-tag order.

  • checkout_item(connection, loan_id, item_id, member_id, checked_out_on) commits one guarded checkout or raises one of the three exact ValueError messages.

  • return_loan(connection, loan_id, returned_on) commits one active-loan update and returns a boolean.

The module should only define these operations when imported. Do not open a fixed database, create tables, print output, or run a demonstration at import time. A calling operation owns the lifetime: it opens once, makes several calls, then closes once in finally.

Press Run. The visible call sequence checks availability, checks out item 1, checks availability again, returns loan 9001, repeats that return to show False, and the restored item. A fresh connection confirms that 2026-08-27 remains stored, then the caller closes its connection.

Submit repeats the whole flow with different records and tests all four public contracts together.

Task

Complete return_loan(connection, loan_id, returned_on) in catalog_db.py.

Inside one connection context, run the exact parameterized update for id = ? AND returned_on IS NULL, bind (returned_on, loan_id), and return whether result.rowcount == 1 after commit. A successful first return is True; a repeated or missing loan is False. Preserve the other three public , leave supplied connections open, and perform no work when the is imported.