Capstone: A Persistent Lending Tool · practice
Register a Member
A member row now has five values that must survive the command boundary together. The
The demo makes this exact call after initializing the database and importing the three items:
main([
"register-member", str(database_path), "17", "MB-017",
"Riley", "riley@example.test", "--loan-limit", "2.5",
])
Argparse passes six namespace fields to register_member_command: args.database, args.member_id, args.member_code, args.name, args.email, and args.loan_limit. The ID is already a positive int. The explicit limit is already a positive finite float; without the option, its 3.
Add this small text register_member_command(args):
def trimmed(value, label):
text = value.strip()
if not text:
raise ValueError(f"{label} must not be blank.")
return text
First require the database path to exist. Then trim the member code, name, and email with trimmed(value, label). Use the labels MEMBER_CODE, NAME, and EMAIL, so whitespace-only input becomes one exact message such as Error: EMAIL must not be blank.. Do this before schema preparation or connection opening because invalid input should not change database state.
Call prepare_database(args.database) to validate or migrate the existing file. Open the application connection with open_database, and close that connection in finally, whether registration succeeds or raises a documented conflict. Call the function that inserts a member once:
register_member(
connection, args.member_id, member_code, name, email, args.loan_limit
)
That function uses placeholders, commits the five explicit values, leaves its caller’s connection open, and translates only its insert’s integrity conflict to ValueError("The member ID or code is already in use."). Catch documented lending.py or catch unrelated database failures.
Only after the connection has closed successfully, print the trimmed code and return 0. Add the exact branch if args.command == "register-member": return register_member_command(args) in main.
Press Run to see durable state after reopening:
== register-member ==
Status: 0
stdout: Member registered: MB-017
stderr: <empty>
Stored member after reopening: 17 | MB-017 | Riley | 2.5 | riley@example.test
A thorough check uses default and fractional limits, Unicode and SQL-looking text, duplicate IDs and codes, blank fields, and a missing path. Literal text must remain data throughout.
Task
Add the exact trimmed(value, label) register_member_command(args), and add this branch in main:
if args.command == "register-member":
return register_member_command(args)
Refuse a missing database, trim and validate MEMBER_CODE, NAME, and EMAIL, prepare the database, and call the supplied register_member boundary with all five member values. Close the application connection in finally. On success print Member registered: CODE and return 0; map only documented report_error.