clearance_sys / src /models.py
Testys's picture
Let's just finish this
3358b33
Raw
History Blame Contribute Delete
6.29 kB
from typing import List, Optional
from sqlmodel import Field, Relationship, SQLModel
from enum import Enum
from datetime import datetime
# --- Enums for choices ---
class Role(str, Enum):
ADMIN = "admin"
STAFF = "staff"
STUDENT = "student"
class Department(str, Enum):
COMPUTER_SCIENCE = "Computer Science"
ENGINEERING = "Engineering"
BUSINESS_ADMIN = "Business Administration"
LAW = "Law"
MEDICINE = "Medicine"
class ClearanceDepartment(str, Enum):
LIBRARY = "Library"
STUDENT_AFFAIRS = "Student Affairs"
BURSARY = "Bursary"
ACADEMIC_AFFAIRS = "Academic Affairs"
HEALTH_CENTER = "Health Center"
class ClearanceStatusEnum(str, Enum):
PENDING = "pending"
APPROVED = "approved"
REJECTED = "rejected"
class OverallClearanceStatusEnum(str, Enum):
COMPLETED = "completed"
PENDING = "pending"
# --- Database Table Models ---
class User(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
username: str = Field(index=True, unique=True)
email: str = Field(index=True, unique=True)
full_name: str
hashed_password: str
role: Role
department: Optional[Department] = None # For staff members
rfid_tag: Optional["RFIDTag"] = Relationship(back_populates="user", sa_relationship_kwargs={"cascade": "all, delete-orphan"})
class Student(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
full_name: str
matric_no: str = Field(index=True, unique=True)
email: str = Field(index=True, unique=True)
department: Department
# A student's login is handled by their associated User record, not directly here.
rfid_tag: Optional["RFIDTag"] = Relationship(back_populates="student", sa_relationship_kwargs={"cascade": "all, delete-orphan"})
clearance_statuses: List["ClearanceStatus"] = Relationship(back_populates="student", sa_relationship_kwargs={"cascade": "all, delete-orphan"})
class ClearanceStatus(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
department: ClearanceDepartment
status: ClearanceStatusEnum = Field(default=ClearanceStatusEnum.PENDING)
remarks: Optional[str] = None
student_id: int = Field(foreign_key="student.id")
student: "Student" = Relationship(back_populates="clearance_statuses")
updated_at: Optional[datetime] = Field(default=None)
class RFIDTag(SQLModel, table=True):
tag_id: str = Field(primary_key=True, index=True)
student_id: Optional[int] = Field(default=None, foreign_key="student.id", unique=True)
user_id: Optional[int] = Field(default=None, foreign_key="user.id", unique=True)
student: Optional["Student"] = Relationship(back_populates="rfid_tag")
user: Optional["User"] = Relationship(back_populates="rfid_tag")
class Device(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
device_name: str = Field(unique=True, index=True)
api_key: str = Field(unique=True, index=True)
location: str
department: Department # ADD THIS - referenced in devices.py CRUD
is_active: bool = Field(default=True)
# --- Pydantic Models for API Operations ---
# Token Model
class Token(SQLModel):
access_token: str
token_type: str
# User Models
class UserCreate(SQLModel):
username: str
password: str
email: str
full_name: str
role: Role
department: Optional[Department] = None
class UserUpdate(SQLModel):
username: Optional[str] = None
email: Optional[str] = None
full_name: Optional[str] = None
role: Optional[Role] = None
department: Optional[Department] = None
password: Optional[str] = None
class UserRead(SQLModel):
id: int
username: str
email: str
full_name: str
role: Role
department: Optional[Department] = None
# Student Models
class StudentCreate(SQLModel):
full_name: str
matric_no: str
email: str
department: Department
password: str # This will be used to create the associated User account for the student
class StudentUpdate(SQLModel):
full_name: Optional[str] = None
department: Optional[Department] = None
email: Optional[str] = None
class StudentRead(SQLModel):
id: int
full_name: str
matric_no: str
department: Department
# Clearance Status Models
class ClearanceStatusRead(SQLModel):
department: ClearanceDepartment
status: ClearanceStatusEnum
remarks: Optional[str] = None
class ClearanceUpdate(SQLModel):
matric_no: str
department: ClearanceDepartment
status: ClearanceStatusEnum
remarks: Optional[str] = None
class ClearanceStatusItem(SQLModel):
department: ClearanceDepartment
status: ClearanceStatusEnum
remarks: Optional[str] = None
updated_at: Optional[datetime] = None # Will be added to table model; see below
class ClearanceDetail(SQLModel):
student_id: int
name: str
department: Department
clearance_items: List[ClearanceStatusItem]
overall_status: OverallClearanceStatusEnum
# Combined Read Model
class StudentReadWithClearance(StudentRead):
clearance_statuses: List[ClearanceStatusRead] = []
rfid_tag: Optional["RFIDTagRead"] = None
# RFID Tag Models
class RFIDTagRead(SQLModel):
tag_id: str
student_id: Optional[int] = None
user_id: Optional[int] = None
class TagLink(SQLModel):
tag_id: str
matric_no: Optional[str] = None
username: Optional[str] = None
# RFID Device-Specific Models
class RFIDScanRequest(SQLModel):
tag_id: str
class RFIDStatusResponse(SQLModel):
status: str # "found" or "unregistered" # "found" or "unregistered"
full_name: Optional[str] = None
entity_type: Optional[str] = None # "Student", "Admin", "Staff"None # "Student", "Admin", "Staff"
clearance_status: Optional[str] = None # "Fully Cleared", "Pending Clearance", "N/A" = None # "Fully Cleared", "Pending Clearance", "N/A"
class TagScan(SQLModel):
tag_id: str
api_key: str
# Device Models
class DeviceCreate(SQLModel):
device_name: str
location: str
department: Department # ADD THIS
class DeviceRead(SQLModel):
id: int
device_name: str
api_key: str
location: str
department: Department # ADD THIS
is_active: bool