package models import "time" // Class đại diện cho lớp học từ QLĐT type Class struct { ID uint `gorm:"primaryKey" json:"id"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` RkID int64 `gorm:"column:rk_id;uniqueIndex;not null" json:"rkId"` Name string `gorm:"column:name;size:512" json:"name"` ClassCode string `gorm:"column:class_code;size:128" json:"classCode"` Type string `gorm:"column:type;size:64" json:"type"` StudentCount int `gorm:"column:student_count;default:0" json:"studentCount"` SpecializeRkID *int64 `gorm:"column:specialize_rk_id" json:"specializeRkId"` SpecializeName *string `gorm:"column:specialize_name;size:255" json:"specializeName"` SystemRkID *int64 `gorm:"column:system_rk_id;index" json:"systemRkId"` SystemCode *string `gorm:"column:system_code;size:64" json:"systemCode"` SystemName *string `gorm:"column:system_name;size:512" json:"systemName"` IsStudying bool `gorm:"column:is_studying;default:false;index" json:"isStudying"` } func (Class) TableName() string { return "classes" } // Student đại diện cho sinh viên type Student struct { ID uint `gorm:"primaryKey" json:"id"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` RkID int64 `gorm:"column:rk_id;uniqueIndex;not null" json:"rkId"` StudentCode string `gorm:"column:student_code;size:64;index" json:"studentCode"` FullName string `gorm:"column:full_name;size:255;index" json:"fullName"` Phone *string `gorm:"column:phone;size:32" json:"phone"` Email string `gorm:"column:email;size:255;index" json:"email"` DateOfBirth *time.Time `gorm:"column:date_of_birth" json:"dateOfBirth"` Gender *int `gorm:"column:gender" json:"gender"` Status *string `gorm:"column:status;size:64" json:"status"` Location *string `gorm:"column:location;size:32" json:"location"` SystemID *int64 `gorm:"column:system_id" json:"systemId"` SystemName *string `gorm:"column:system_name;size:255" json:"systemName"` Avatar *string `gorm:"column:avatar;size:512" json:"avatar"` } func (Student) TableName() string { return "students" } // ClassStudent map sinh viên vào lớp tương ứng type ClassStudent struct { ClassRkID int64 `gorm:"column:class_rk_id;primaryKey;not null;index" json:"classRkId"` StudentRkID int64 `gorm:"column:student_rk_id;primaryKey;not null;index" json:"studentRkId"` } func (ClassStudent) TableName() string { return "class_students" } // ClassCourse môn học thuộc lớp (cache từ QLĐT) type ClassCourse struct { ID uint `gorm:"primaryKey" json:"id"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` ClassRkID int64 `gorm:"column:class_rk_id;not null;uniqueIndex:uq_class_course,priority:1" json:"classRkId"` CourseRkID int64 `gorm:"column:course_rk_id;not null;uniqueIndex:uq_class_course,priority:2" json:"courseRkId"` Name string `gorm:"column:name;size:512" json:"name"` CourseCode string `gorm:"column:course_code;size:128" json:"courseCode"` } func (ClassCourse) TableName() string { return "class_courses" } // ClassSchedule lưu cấu hình lịch học theo tuần của lớp (nhiều ca/ngày) type ClassSchedule struct { ID uint `gorm:"primaryKey" json:"id"` ClassRkID int64 `gorm:"column:class_rk_id;index;not null" json:"classRkId"` DayOfWeek int `gorm:"column:day_of_week;not null" json:"dayOfWeek"` // 0=Monday, 6=Sunday Period int `gorm:"column:period;not null;default:1" json:"period"` // Ca 1..4 StartTime string `gorm:"column:start_time;size:8;not null" json:"startTime"` EndTime string `gorm:"column:end_time;size:8;not null" json:"endTime"` CourseID int64 `gorm:"column:course_id;not null" json:"courseId"` CourseName string `gorm:"column:course_name;size:512;not null" json:"courseName"` IsActive bool `gorm:"column:is_active;not null;default:true" json:"isActive"` } func (ClassSchedule) TableName() string { return "class_schedules" } // AttendanceResult điểm danh theo ca — khóa khi giáo viên sửa thủ công type AttendanceResult struct { ID uint `gorm:"primaryKey" json:"id"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` ClassRkID int64 `gorm:"column:class_rk_id;not null;uniqueIndex:idx_att_lookup,priority:1" json:"classRkId"` SessionDate string `gorm:"column:session_date;size:10;not null;uniqueIndex:idx_att_lookup,priority:2" json:"sessionDate"` Period int `gorm:"column:period;not null;uniqueIndex:idx_att_lookup,priority:3" json:"period"` StudentRkID int64 `gorm:"column:student_rk_id;not null;uniqueIndex:idx_att_lookup,priority:4" json:"studentRkId"` Status int `gorm:"column:status;not null;default:0" json:"status"` StatusLabel string `gorm:"column:status_label;size:64;not null" json:"statusLabel"` OnlineMinutes int `gorm:"column:online_minutes;not null;default:0" json:"onlineMinutes"` StatusEditedByTeacher bool `gorm:"column:status_edited_by_teacher;not null;default:false" json:"statusEditedByTeacher"` PushedToQLDTAt *time.Time `gorm:"column:pushed_to_qldt_at" json:"pushedToQldtAt,omitempty"` } func (AttendanceResult) TableName() string { return "attendance_results" } // ClassSeatingLayout lưu sơ đồ chỗ ngồi theo lớp type ClassSeatingLayout struct { ClassRkID int64 `gorm:"column:class_rk_id;primaryKey;not null" json:"classRkId"` LayoutJSON string `gorm:"column:layout_json;type:longtext;not null" json:"layoutJson"` UpdatedAt time.Time `json:"updatedAt"` } func (ClassSeatingLayout) TableName() string { return "class_seating_layouts" } // ExamSeatingLayout lưu sơ đồ chỗ ngồi theo phòng thi type ExamSeatingLayout struct { ExamRoomID uint `gorm:"column:exam_room_id;primaryKey;not null" json:"examRoomId"` LayoutJSON string `gorm:"column:layout_json;type:longtext;not null" json:"layoutJson"` UpdatedAt time.Time `json:"updatedAt"` } func (ExamSeatingLayout) TableName() string { return "exam_seating_layouts" } // ClassAllowedApp lưu từ khóa app được mở của lớp type ClassAllowedApp struct { ClassRkID int64 `gorm:"column:class_rk_id;primaryKey;not null" json:"classRkId"` Keywords string `gorm:"column:keywords;type:text" json:"keywords"` // phân tách bằng dấu phẩy } func (ClassAllowedApp) TableName() string { return "class_allowed_apps" } // AppPoolEntry — kho app bị chặn toàn hệ thống (mọi lớp dùng chung để gợi ý whitelist) type AppPoolEntry struct { ID uint `gorm:"primaryKey" json:"id"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` ProcessName string `gorm:"column:process_name;size:255;not null" json:"processName"` ProcessKey string `gorm:"column:process_key;size:255;not null;uniqueIndex" json:"-"` WindowTitle string `gorm:"column:window_title;type:text" json:"windowTitle"` Keyword string `gorm:"column:keyword;size:100;not null" json:"keyword"` HitCount int `gorm:"column:hit_count;default:1" json:"hitCount"` LastSeenAt time.Time `gorm:"column:last_seen_at" json:"lastSeenAt"` LastStudentRkID int64 `gorm:"column:last_student_rk_id" json:"lastStudentRkId,omitempty"` LastClassRkID int64 `gorm:"column:last_class_rk_id" json:"lastClassRkId,omitempty"` } func (AppPoolEntry) TableName() string { return "app_pool" } // AppTemplate — khung ứng dụng (bộ keyword whitelist) dùng chung cho lớp / phòng thi type AppTemplate struct { ID uint `gorm:"primaryKey" json:"id"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` Name string `gorm:"column:name;size:120;not null" json:"name"` Description string `gorm:"column:description;type:text" json:"description"` Keywords string `gorm:"column:keywords;type:text;not null" json:"keywords"` } func (AppTemplate) TableName() string { return "app_templates" } // WifiPoolEntry — kho WiFi phát hiện từ máy sinh viên (SSID + BSSID điểm phát) type WifiPoolEntry struct { ID uint `gorm:"primaryKey" json:"id"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` SSID string `gorm:"column:ssid;size:255;not null" json:"ssid"` SSIDKey string `gorm:"column:ssid_key;size:255;not null;index" json:"-"` BSSID string `gorm:"column:bssid;size:32;not null" json:"bssid"` BSSIDKey string `gorm:"column:bssid_key;size:32;not null;uniqueIndex" json:"-"` HitCount int `gorm:"column:hit_count;default:1" json:"hitCount"` LastSeenAt time.Time `gorm:"column:last_seen_at" json:"lastSeenAt"` LastStudentRkID int64 `gorm:"column:last_student_rk_id" json:"lastStudentRkId,omitempty"` } func (WifiPoolEntry) TableName() string { return "wifi_pool" } // AcceptedWifi — điểm phát được phép (xác thực theo BSSID, không chỉ tên SSID) type AcceptedWifi struct { ID uint `gorm:"primaryKey" json:"id"` SSID string `gorm:"column:ssid;size:255;not null" json:"ssid"` SSIDKey string `gorm:"column:ssid_key;size:255;not null;index" json:"-"` BSSID string `gorm:"column:bssid;size:32;not null" json:"bssid"` BSSIDKey string `gorm:"column:bssid_key;size:32;not null;uniqueIndex" json:"-"` CreatedAt time.Time `json:"createdAt"` } func (AcceptedWifi) TableName() string { return "accepted_wifis" } // StudentSession lưu log học tập theo ca trong ngày type StudentSession struct { ID uint `gorm:"primaryKey" json:"id"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` StudentRkID int64 `gorm:"column:student_rk_id;not null;uniqueIndex:idx_student_session,priority:1" json:"studentRkId"` ClassRkID int64 `gorm:"column:class_rk_id;not null;uniqueIndex:idx_student_session,priority:2" json:"classRkId"` SessionDate string `gorm:"column:session_date;size:10;not null;uniqueIndex:idx_student_session,priority:3" json:"sessionDate"` // YYYY-MM-DD Period int `gorm:"column:period;not null;default:0;uniqueIndex:idx_student_session,priority:4" json:"period"` // Ca 1..4 (0 = dữ liệu cũ) OnlineSeconds int `gorm:"column:online_seconds;default:0" json:"onlineSeconds"` OfflineSeconds int `gorm:"column:offline_seconds;default:0" json:"offlineSeconds"` WifiSSIDs string `gorm:"column:wifi_ssids;type:text" json:"wifiSsids"` LastActiveAt time.Time `gorm:"column:last_active_at" json:"lastActiveAt"` } func (StudentSession) TableName() string { return "student_sessions" } // StudentViolation — ghi nhận SV tắt app / vi phạm môi trường khi đang giám sát type StudentViolation struct { ID uint `gorm:"primaryKey" json:"id"` CreatedAt time.Time `json:"createdAt"` StudentRkID int64 `gorm:"column:student_rk_id;not null;index" json:"studentRkId"` ClassRkID int64 `gorm:"column:class_rk_id;index" json:"classRkId"` ExamRoomID uint `gorm:"column:exam_room_id;index;default:0" json:"examRoomId"` Kind string `gorm:"column:kind;size:64;not null;index" json:"kind"` // app_closed | unclean_shutdown | multi_monitor | user_switch | session_change | virtual_desktop | wifi | guard Reason string `gorm:"column:reason;type:text" json:"reason"` MonitorMode string `gorm:"column:monitor_mode;size:32" json:"monitorMode"` ClientAt time.Time `gorm:"column:client_at" json:"clientAt"` } func (StudentViolation) TableName() string { return "student_violations" } // SystemSetting lưu các cấu hình hệ thống động type SystemSetting struct { SettingKey string `gorm:"primaryKey;column:setting_key;size:128" json:"settingKey"` SettingValue string `gorm:"column:setting_value;type:text" json:"settingValue"` UpdatedAt time.Time `json:"updatedAt"` } func (SystemSetting) TableName() string { return "system_settings" } // GuideLink đại diện cho tài liệu hướng dẫn Google Docs public type GuideLink struct { ID uint `gorm:"primaryKey" json:"id"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` Title string `gorm:"column:title;size:512;not null" json:"title"` URL string `gorm:"column:url;size:1024;not null" json:"url"` } func (GuideLink) TableName() string { return "guide_links" } // AppDownload đại diện cho ứng dụng và link tải type AppDownload struct { ID uint `gorm:"primaryKey" json:"id"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` Name string `gorm:"column:name;size:255;not null" json:"name"` Description string `gorm:"column:description;size:512" json:"description"` DownloadURL string `gorm:"column:download_url;size:1024;not null" json:"downloadUrl"` Platform string `gorm:"column:platform;size:64" json:"platform"` // "Windows", "macOS", "Linux", "Khác" } func (AppDownload) TableName() string { return "app_downloads" } // AppGuide đại diện cho tài liệu/video hướng dẫn ứng dụng dành cho sinh viên type AppGuide struct { ID uint `gorm:"primaryKey" json:"id"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` Title string `gorm:"column:title;size:512;not null" json:"title"` URL string `gorm:"column:url;size:1024;not null" json:"url"` } func (AppGuide) TableName() string { return "app_guides" } // LocalLeaveRequest lưu trạng thái phê duyệt đơn xin nghỉ phép trên hệ thống nội bộ thay vì call QLĐT type LocalLeaveRequest struct { ID uint `gorm:"primaryKey" json:"id"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` LeaveID int64 `gorm:"column:leave_id;uniqueIndex;not null" json:"leaveId"` Status string `gorm:"column:status;size:32;not null" json:"status"` // "Phê duyệt" hoặc "Từ chối" } func (LocalLeaveRequest) TableName() string { return "local_leave_requests" }