project-init

This commit is contained in:
srikar committed 2026-09-25 08:14:04 -07:00
commit 65691a0aee
7 files changed
+897

No files matched your search

+205
View File
@@ -0,0 +1,205 @@
"""
CRUD operations for GUARDIAN, STUDENT and ATTENDANCE.
Every function takes an open pymysql connection as its first argument and
manages its own commit/rollback. All functions return plain data
(dicts/lists/bool) so this module has no dependency on the UI layer.
"""
import pymysql
class CrudError(Exception):
"""Raised for expected, user-facing data errors (bad FK, duplicate key, etc)."""
pass
def _run(conn, sql, params=None, fetch=None):
"""
Helper: execute a statement, commit, and optionally fetch results.
fetch: None (no fetch), 'one', or 'all'
Translates common MySQL errors into CrudError with a friendly message.
"""
try:
with conn.cursor() as cur:
cur.execute(sql, params or ())
result = None
if fetch == "one":
result = cur.fetchone()
elif fetch == "all":
result = cur.fetchall()
conn.commit()
return result if fetch else cur.rowcount
except pymysql.err.IntegrityError as e:
conn.rollback()
code = e.args[0] if e.args else None
if code == 1062:
raise CrudError("A record with that primary/unique key already exists.")
if code in (1451, 1452):
raise CrudError(
"That operation violates a foreign key constraint "
"(referenced record missing, or still referenced by other rows)."
)
raise CrudError(f"Database integrity error: {e}")
except pymysql.err.DataError as e:
conn.rollback()
raise CrudError(f"Invalid data for one or more fields: {e}")
except pymysql.err.MySQLError as e:
conn.rollback()
raise CrudError(f"Database error: {e}")
# ---------------------------------------------------------------- GUARDIAN --
def create_guardian(conn, guid, gname, gphone, gaddress):
_run(
conn,
"INSERT INTO GUARDIAN (GUID, GName, GPhone, GAddress) VALUES (%s, %s, %s, %s)",
(guid, gname, gphone, gaddress),
)
def get_guardian(conn, guid):
return _run(conn, "SELECT * FROM GUARDIAN WHERE GUID = %s", (guid,), fetch="one")
def list_guardians(conn):
return _run(conn, "SELECT * FROM GUARDIAN ORDER BY GUID", fetch="all")
def update_guardian(conn, guid, gname=None, gphone=None, gaddress=None):
fields, params = [], []
if gname is not None:
fields.append("GName = %s")
params.append(gname)
if gphone is not None:
fields.append("GPhone = %s")
params.append(gphone)
if gaddress is not None:
fields.append("GAddress = %s")
params.append(gaddress)
if not fields:
return 0
params.append(guid)
return _run(conn, f"UPDATE GUARDIAN SET {', '.join(fields)} WHERE GUID = %s", params)
def delete_guardian(conn, guid):
return _run(conn, "DELETE FROM GUARDIAN WHERE GUID = %s", (guid,))
# ----------------------------------------------------------------- STUDENT --
def create_student(conn, roll_number, sname, sdateofbirth, guid):
_run(
conn,
"INSERT INTO STUDENT (RollNumber, SName, SDateofBirth, GUID) VALUES (%s, %s, %s, %s)",
(roll_number, sname, sdateofbirth, guid),
)
def get_student(conn, roll_number):
return _run(conn, "SELECT * FROM STUDENT WHERE RollNumber = %s", (roll_number,), fetch="one")
def list_students(conn):
return _run(
conn,
"""
SELECT s.RollNumber, s.SName, s.SDateofBirth, s.GUID, g.GName AS GuardianName
FROM STUDENT s
LEFT JOIN GUARDIAN g ON s.GUID = g.GUID
ORDER BY s.RollNumber
""",
fetch="all",
)
def update_student(conn, roll_number, sname=None, sdateofbirth=None, guid=None):
fields, params = [], []
if sname is not None:
fields.append("SName = %s")
params.append(sname)
if sdateofbirth is not None:
fields.append("SDateofBirth = %s")
params.append(sdateofbirth)
if guid is not None:
fields.append("GUID = %s")
params.append(guid)
if not fields:
return 0
params.append(roll_number)
return _run(conn, f"UPDATE STUDENT SET {', '.join(fields)} WHERE RollNumber = %s", params)
def delete_student(conn, roll_number):
return _run(conn, "DELETE FROM STUDENT WHERE RollNumber = %s", (roll_number,))
# --------------------------------------------------------------- ATTENDANCE --
def mark_attendance(conn, attendance_date, roll_number, status):
"""Insert attendance; if a record for that date+student exists, update it instead."""
existing = _run(
conn,
"SELECT 1 FROM ATTENDANCE WHERE AttendanceDate = %s AND RollNumber = %s",
(attendance_date, roll_number),
fetch="one",
)
if existing:
_run(
conn,
"UPDATE ATTENDANCE SET AttendanceStatus = %s "
"WHERE AttendanceDate = %s AND RollNumber = %s",
(status, attendance_date, roll_number),
)
return "updated"
else:
_run(
conn,
"INSERT INTO ATTENDANCE (AttendanceDate, RollNumber, AttendanceStatus) "
"VALUES (%s, %s, %s)",
(attendance_date, roll_number, status),
)
return "created"
def get_attendance(conn, attendance_date, roll_number):
return _run(
conn,
"SELECT * FROM ATTENDANCE WHERE AttendanceDate = %s AND RollNumber = %s",
(attendance_date, roll_number),
fetch="one",
)
def list_attendance_by_date(conn, attendance_date):
return _run(
conn,
"""
SELECT a.AttendanceDate, a.RollNumber, s.SName, a.AttendanceStatus
FROM ATTENDANCE a
JOIN STUDENT s ON a.RollNumber = s.RollNumber
WHERE a.AttendanceDate = %s
ORDER BY a.RollNumber
""",
(attendance_date,),
fetch="all",
)
def list_attendance_by_student(conn, roll_number):
return _run(
conn,
"SELECT * FROM ATTENDANCE WHERE RollNumber = %s ORDER BY AttendanceDate",
(roll_number,),
fetch="all",
)
def delete_attendance(conn, attendance_date, roll_number):
return _run(
conn,
"DELETE FROM ATTENDANCE WHERE AttendanceDate = %s AND RollNumber = %s",
(attendance_date, roll_number),
)