#!/usr/bin/env python3 """ Student Management System ========================== Terminal CRUD application for STUDENT / GUARDIAN / ATTENDANCE, backed by MySQL on 10.10.0.160:3306 (student_db). On startup this: 1. Connects to the MySQL server. 2. Verifies (or creates) the student_db database. 3. Verifies (or creates) the STUDENT, GUARDIAN and ATTENDANCE tables. 4. Launches an interactive terminal menu for CRUD operations. Run: python3 main.py """ import sys import mysql.connector import crud import db from ui_helpers import ( clear_hint, pause, print_table, prompt_attendance_status, prompt_date, prompt_guid, prompt_int, prompt_phone, prompt_str, ) # ============================================================ GUARDIAN UI == def menu_guardians(conn): while True: clear_hint() print("GUARDIAN MANAGEMENT") print(" 1. List all guardians") print(" 2. View a guardian") print(" 3. Add a guardian") print(" 4. Update a guardian") print(" 5. Delete a guardian") print(" 0. Back to main menu") choice = input("\nChoice: ").strip() try: if choice == "1": print() print_table(crud.list_guardians(conn)) pause() elif choice == "2": guid = prompt_guid() row = crud.get_guardian(conn, guid) print() print_table([row] if row else []) pause() elif choice == "3": add_guardian(conn) elif choice == "4": update_guardian(conn) elif choice == "5": delete_guardian(conn) elif choice == "0": return else: print(" Invalid choice.") except crud.CrudError as e: print(f"\n [ERROR] {e}") pause() def add_guardian(conn): print("\n-- Add Guardian --") guid = prompt_guid() gname = prompt_str("Guardian name", max_len=20) gphone = prompt_phone() gaddress = prompt_str("Guardian address", max_len=30) crud.create_guardian(conn, guid, gname, gphone, gaddress) print(f" [OK] Guardian {guid} added.") pause() def update_guardian(conn): print("\n-- Update Guardian --") guid = prompt_guid() existing = crud.get_guardian(conn, guid) if not existing: print(" No guardian found with that GUID.") pause() return print(f" Current: {existing}") print(" (Press Enter to leave a field unchanged)") gname = prompt_str("New name", max_len=20, allow_blank_skip=True) gphone_raw = input("New phone (10 digits, blank = unchanged, 'clear' = remove): ").strip() gphone = existing["GPhone"] if gphone_raw.lower() == "clear": gphone = None elif gphone_raw: gphone = prompt_phone_validate(gphone_raw) if gphone is None: print(" Invalid phone — update aborted for that field.") gphone = existing["GPhone"] gaddress = prompt_str("New address", max_len=30, allow_blank_skip=True) crud.update_guardian(conn, guid, gname=gname, gphone=gphone, gaddress=gaddress) print(" [OK] Guardian updated.") pause() def prompt_phone_validate(raw): import re return raw if re.match(r"^\d{10}$", raw) else None def delete_guardian(conn): print("\n-- Delete Guardian --") guid = prompt_guid() confirm = input(f" Type 'yes' to confirm deleting guardian {guid}: ").strip().lower() if confirm != "yes": print(" Cancelled.") pause() return rows = crud.delete_guardian(conn, guid) if rows: print(" [OK] Guardian deleted.") else: print(" No guardian found with that GUID.") pause() # ============================================================= STUDENT UI == def menu_students(conn): while True: clear_hint() print("STUDENT MANAGEMENT") print(" 1. List all students") print(" 2. View a student") print(" 3. Add a student") print(" 4. Update a student") print(" 5. Delete a student") print(" 0. Back to main menu") choice = input("\nChoice: ").strip() try: if choice == "1": print() print_table(crud.list_students(conn)) pause() elif choice == "2": roll = prompt_int("Roll number", max_digits=3) row = crud.get_student(conn, roll) print() print_table([row] if row else []) pause() elif choice == "3": add_student(conn) elif choice == "4": update_student(conn) elif choice == "5": delete_student(conn) elif choice == "0": return else: print(" Invalid choice.") except crud.CrudError as e: print(f"\n [ERROR] {e}") pause() def add_student(conn): print("\n-- Add Student --") roll = prompt_int("Roll number (max 3 digits)", max_digits=3) sname = prompt_str("Student name", max_len=20) dob = prompt_date("Date of birth") print(" (Guardian must already exist — add them first via Guardian Management if needed)") guid = prompt_guid() crud.create_student(conn, roll, sname, dob, guid) print(f" [OK] Student {roll} added.") pause() def update_student(conn): print("\n-- Update Student --") roll = prompt_int("Roll number", max_digits=3) existing = crud.get_student(conn, roll) if not existing: print(" No student found with that roll number.") pause() return print(f" Current: {existing}") print(" (Press Enter to leave a field unchanged)") sname = prompt_str("New name", max_len=20, allow_blank_skip=True) dob = prompt_date("New date of birth", allow_blank_skip=True) guid = prompt_guid("New guardian GUID", allow_blank_skip=True) crud.update_student(conn, roll, sname=sname, sdateofbirth=dob, guid=guid) print(" [OK] Student updated.") pause() def delete_student(conn): print("\n-- Delete Student --") roll = prompt_int("Roll number", max_digits=3) confirm = input(f" Type 'yes' to confirm deleting student {roll} " f"(also deletes their attendance records): ").strip().lower() if confirm != "yes": print(" Cancelled.") pause() return rows = crud.delete_student(conn, roll) if rows: print(" [OK] Student deleted.") else: print(" No student found with that roll number.") pause() # =========================================================== ATTENDANCE UI == def menu_attendance(conn): while True: clear_hint() print("ATTENDANCE MANAGEMENT") print(" 1. Mark / update attendance for a student") print(" 2. View attendance by date") print(" 3. View attendance history for a student") print(" 4. Delete an attendance record") print(" 0. Back to main menu") choice = input("\nChoice: ").strip() try: if choice == "1": mark_attendance(conn) elif choice == "2": d = prompt_date("Date") print() print_table(crud.list_attendance_by_date(conn, d)) pause() elif choice == "3": roll = prompt_int("Roll number", max_digits=3) print() print_table(crud.list_attendance_by_student(conn, roll)) pause() elif choice == "4": delete_attendance(conn) elif choice == "0": return else: print(" Invalid choice.") except crud.CrudError as e: print(f"\n [ERROR] {e}") pause() def mark_attendance(conn): print("\n-- Mark Attendance --") roll = prompt_int("Roll number", max_digits=3) if not crud.get_student(conn, roll): print(" No student found with that roll number.") pause() return d = prompt_date("Date") status = prompt_attendance_status() result = crud.mark_attendance(conn, d, roll, status) print(f" [OK] Attendance {result} for student {roll} on {d}: {status}") pause() def delete_attendance(conn): print("\n-- Delete Attendance Record --") roll = prompt_int("Roll number", max_digits=3) d = prompt_date("Date") confirm = input(" Type 'yes' to confirm: ").strip().lower() if confirm != "yes": print(" Cancelled.") pause() return rows = crud.delete_attendance(conn, d, roll) if rows: print(" [OK] Attendance record deleted.") else: print(" No matching attendance record found.") pause() # ================================================================ MAIN ==== def main_menu(conn): while True: clear_hint() print("STUDENT MANAGEMENT SYSTEM") print(" 1. Guardian management") print(" 2. Student management") print(" 3. Attendance management") print(" 0. Exit") choice = input("\nChoice: ").strip() if choice == "1": menu_guardians(conn) elif choice == "2": menu_students(conn) elif choice == "3": menu_attendance(conn) elif choice == "0": print("\nGoodbye!") return else: print(" Invalid choice.") def main(): print("=" * 60) print(" STUDENT MANAGEMENT SYSTEM - Startup") print("=" * 60) conn = db.get_connection() print("\nAll checks passed. Starting application...\n") try: main_menu(conn) except KeyboardInterrupt: print("\n\nInterrupted. Exiting.") except mysql.connector.Error as e: print(f"\n[ERROR] Lost database connection: {e}") sys.exit(1) finally: conn.close() if __name__ == "__main__": main()