project-init
This commit is contained in:
commit
65691a0aee
7 files changed
+897
No files matched your search
@@ -0,0 +1,337 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Student Management System
|
||||
==========================
|
||||
Terminal CRUD application for STUDENT / GUARDIAN / ATTENDANCE, backed by
|
||||
MySQL on 10.0.1.40: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 pymysql
|
||||
|
||||
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 pymysql.err.MySQLError as e:
|
||||
print(f"\n[ERROR] Lost database connection: {e}")
|
||||
sys.exit(1)
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user