syntax = "proto3"; package next_edu_cloud.core_edu.v1; // CoreEdu service contracts - P3 core teaching domain. // Covers exam management, homework assignment, grade recording, // attendance tracking, and class queries. // // Total: 9 Service / 40 RPC (P3.13 expanded state per downstream 9-module analysis). // - ExamService: 10 RPC (8 original + SaveExamDraft + RecordExamViolation) // - HomeworkService: 5 RPC // - GradeService: 7 RPC (6 original + GetReportCard) // - ClassService: 4 RPC // - AttendanceService: 4 RPC // - ScheduleService: 1 RPC (GetScheduleByStudent) // - LeaveRequestService: 3 RPC // - DashboardService: 2 RPC // - AdminService: 4 RPC (aggregation stubs) // Event contracts live in events.proto under next_edu_cloud.events.v1. // // Status naming (ISSUE-003-ai08 arbitration, scheme A): // ExamStatus: draft / published / in_progress / grading / graded / archived / cancelled // HomeworkStatus: assigned / submitted / graded // SubmissionStatus: not_submitted / submitted / graded // AttendanceStatus: present / absent / late / leave // LeaveRequestStatus: pending / approved / rejected / cancelled service ExamService { rpc CreateExam(CreateExamRequest) returns (CreateExamResponse); rpc GetExam(GetExamRequest) returns (Exam); rpc ListExamsByClass(ListExamsByClassRequest) returns (ListExamsResponse); rpc UpdateExam(UpdateExamRequest) returns (UpdateExamResponse); rpc DeleteExam(DeleteExamRequest) returns (DeleteExamResponse); rpc PublishExam(PublishExamRequest) returns (PublishExamResponse); rpc SubmitExam(SubmitExamRequest) returns (SubmitExamResponse); rpc GradeExam(GradeExamRequest) returns (GradeExamResponse); rpc SaveExamDraft(SaveExamDraftRequest) returns (SaveExamDraftResponse); rpc RecordExamViolation(RecordExamViolationRequest) returns (RecordExamViolationResponse); } service HomeworkService { rpc AssignHomework(AssignHomeworkRequest) returns (AssignHomeworkResponse); rpc GetHomework(GetHomeworkRequest) returns (Homework); rpc ListHomeworkByClass(ListHomeworkByClassRequest) returns (ListHomeworkResponse); rpc SubmitHomework(SubmitHomeworkRequest) returns (SubmitHomeworkResponse); rpc GradeHomework(GradeHomeworkRequest) returns (GradeHomeworkResponse); } service GradeService { rpc RecordGrade(RecordGradeRequest) returns (RecordGradeResponse); rpc GetGrade(GetGradeRequest) returns (Grade); rpc ListGradesByStudent(ListGradesByStudentRequest) returns (ListGradesResponse); rpc ListGradesByExam(ListGradesByExamRequest) returns (ListGradesResponse); rpc ListGradesByHomework(ListGradesByHomeworkRequest) returns (ListGradesResponse); rpc UpdateGrade(UpdateGradeRequest) returns (UpdateGradeResponse); rpc GetReportCard(GetReportCardRequest) returns (ReportCard); } service ClassService { rpc GetClass(GetClassRequest) returns (ClassInfo); rpc GetClassesByTeacher(GetClassesByTeacherRequest) returns (GetClassesByTeacherResponse); rpc BatchGetClasses(BatchGetClassesRequest) returns (BatchGetClassesResponse); rpc ListStudentsByClass(ListStudentsByClassRequest) returns (ListStudentsByClassResponse); } service AttendanceService { rpc RecordAttendance(RecordAttendanceRequest) returns (RecordAttendanceResponse); rpc GetAttendance(GetAttendanceRequest) returns (Attendance); rpc ListAttendanceByStudent(ListAttendanceByStudentRequest) returns (ListAttendanceResponse); rpc ListAttendanceByClass(ListAttendanceByClassRequest) returns (ListAttendanceResponse); } service ScheduleService { rpc GetScheduleByStudent(GetScheduleByStudentRequest) returns (GetScheduleByStudentResponse); } service LeaveRequestService { rpc ListLeaveRequestsByStudent(ListLeaveRequestsByStudentRequest) returns (ListLeaveRequestsResponse); rpc CreateLeaveRequest(CreateLeaveRequestRequest) returns (CreateLeaveRequestResponse); rpc CancelLeaveRequest(CancelLeaveRequestRequest) returns (CancelLeaveRequestResponse); } service DashboardService { rpc GetDashboard(GetDashboardRequest) returns (DashboardData); rpc GetClassPerformance(GetClassPerformanceRequest) returns (ClassPerformance); } service AdminService { rpc ListSchools(ListSchoolsRequest) returns (ListSchoolsResponse); rpc ListGradeLevels(ListGradeLevelsRequest) returns (ListGradeLevelsResponse); rpc ListDepartments(ListDepartmentsRequest) returns (ListDepartmentsResponse); rpc ListAcademicYears(ListAcademicYearsRequest) returns (ListAcademicYearsResponse); } // ---------------------------------------------------------------------------- // Exam domain // ---------------------------------------------------------------------------- message Exam { string id = 1; string class_id = 2; string subject_id = 3; string title = 4; string description = 5; string exam_date = 6; // ISO 8601 int32 duration = 7; // seconds string total_score = 8; // decimal as string string status = 9; string status_changed_at = 10; string status_changed_by = 11; string school_id = 12; string created_by = 13; string archived_at = 14; string created_at = 15; string updated_at = 16; } message ExamQuestion { string id = 1; string exam_id = 2; string question_id = 3; int32 order = 4; string score = 5; string question_type = 6; } message ExamSubmission { string id = 1; string exam_id = 2; string student_id = 3; string status = 4; string submitted_at = 5; string graded_at = 6; string graded_by = 7; string total_score = 8; } message CreateExamRequest { string class_id = 1; string subject_id = 2; string title = 3; string description = 4; string exam_date = 5; int32 duration = 6; string total_score = 7; string school_id = 8; string created_by = 9; } message CreateExamResponse { string id = 1; } message GetExamRequest { string id = 1; } message ListExamsByClassRequest { string class_id = 1; } message ListExamsResponse { repeated Exam exams = 1; } message UpdateExamRequest { string id = 1; string title = 2; string description = 3; string exam_date = 4; int32 duration = 5; string total_score = 6; string status = 7; } message UpdateExamResponse { bool success = 1; } message DeleteExamRequest { string id = 1; } message DeleteExamResponse { bool success = 1; } message PublishExamRequest { string id = 1; string published_by = 2; } message PublishExamResponse { bool success = 1; } message SubmitExamRequest { string exam_id = 1; string student_id = 2; repeated AnswerInput answers = 3; } message AnswerInput { string question_id = 1; string answer = 2; } message SubmitExamResponse { string submission_id = 1; } message GradeExamRequest { string exam_id = 1; string submission_id = 2; repeated ScoreInput scores = 3; string graded_by = 4; } message ScoreInput { string question_id = 1; string score = 2; string teacher_comment = 3; } message GradeExamResponse { bool success = 1; string total_score = 2; } // ---------------------------------------------------------------------------- // Homework domain // ---------------------------------------------------------------------------- message Homework { string id = 1; string class_id = 2; string subject_id = 3; string title = 4; string description = 5; string due_date = 6; int32 grace_period = 7; string status = 8; string school_id = 9; string created_by = 10; string created_at = 11; string updated_at = 12; } message HomeworkSubmission { string id = 1; string homework_id = 2; string student_id = 3; string status = 4; string submitted_at = 5; string graded_at = 6; string graded_by = 7; string total_score = 8; string feedback = 9; } message AssignHomeworkRequest { string class_id = 1; string subject_id = 2; string title = 3; string description = 4; string due_date = 5; int32 grace_period = 6; string school_id = 7; string created_by = 8; } message AssignHomeworkResponse { string id = 1; } message GetHomeworkRequest { string id = 1; } message ListHomeworkByClassRequest { string class_id = 1; } message ListHomeworkResponse { repeated Homework homework = 1; } message SubmitHomeworkRequest { string homework_id = 1; string student_id = 2; repeated AnswerInput answers = 3; } message SubmitHomeworkResponse { string submission_id = 1; } message GradeHomeworkRequest { string homework_id = 1; string submission_id = 2; repeated ScoreInput scores = 3; string feedback = 4; string graded_by = 5; } message GradeHomeworkResponse { bool success = 1; string total_score = 2; } // ---------------------------------------------------------------------------- // Grade domain // ---------------------------------------------------------------------------- message Grade { string id = 1; string student_id = 2; string exam_id = 3; string homework_id = 4; string score = 5; string total_score = 6; string feedback = 7; string graded_by = 8; string school_id = 9; string idempotency_key = 10; string created_at = 11; string updated_at = 12; } message RecordGradeRequest { string student_id = 1; string exam_id = 2; string homework_id = 3; string score = 4; string total_score = 5; string feedback = 6; string graded_by = 7; string school_id = 8; string idempotency_key = 9; } message RecordGradeResponse { string id = 1; } message GetGradeRequest { string id = 1; } message ListGradesByStudentRequest { string student_id = 1; } message ListGradesByExamRequest { string exam_id = 1; } message ListGradesByHomeworkRequest { string homework_id = 1; } message ListGradesResponse { repeated Grade grades = 1; } message UpdateGradeRequest { string id = 1; string score = 2; string feedback = 3; string updated_by = 4; } message UpdateGradeResponse { bool success = 1; } // ---------------------------------------------------------------------------- // Class domain (merged from classes service per ISSUE-006 decision #1) // ---------------------------------------------------------------------------- message ClassInfo { string id = 1; string name = 2; string grade_id = 3; string head_teacher_id = 4; string description = 5; string created_at = 6; string updated_at = 7; } message StudentInfo { string id = 1; string name = 2; string class_id = 3; } message GetClassRequest { string id = 1; } message GetClassesByTeacherRequest { string teacher_id = 1; } message GetClassesByTeacherResponse { repeated ClassInfo classes = 1; } message BatchGetClassesRequest { repeated string ids = 1; } message BatchGetClassesResponse { repeated ClassInfo classes = 1; } message ListStudentsByClassRequest { string class_id = 1; } message ListStudentsByClassResponse { repeated StudentInfo students = 1; } // ---------------------------------------------------------------------------- // Attendance domain // ---------------------------------------------------------------------------- message Attendance { string id = 1; string schedule_id = 2; string student_id = 3; string status = 4; string remark = 5; string recorded_by = 6; string school_id = 7; string created_at = 8; string updated_at = 9; } message RecordAttendanceRequest { string schedule_id = 1; string student_id = 2; string status = 3; string remark = 4; string recorded_by = 5; string school_id = 6; } message RecordAttendanceResponse { string id = 1; } message GetAttendanceRequest { string id = 1; } message ListAttendanceByStudentRequest { string student_id = 1; } message ListAttendanceByClassRequest { string class_id = 1; } message ListAttendanceResponse { repeated Attendance attendance = 1; } // ---------------------------------------------------------------------------- // Exam domain extensions (P3.13) // ---------------------------------------------------------------------------- message SaveExamDraftRequest { string exam_id = 1; string student_id = 2; repeated AnswerInput answers = 3; } message SaveExamDraftResponse { string draft_id = 1; } message RecordExamViolationRequest { string exam_id = 1; string student_id = 2; string violation_type = 3; // tab_switch / window_blur / copy_paste / fullscreen_exit / browser_devtools string detail = 4; int32 severity = 5; // 1=info, 2=warning, 3=critical } message RecordExamViolationResponse { string violation_id = 1; } // ---------------------------------------------------------------------------- // Grade domain extensions (P3.13) // ---------------------------------------------------------------------------- message GetReportCardRequest { string student_id = 1; string term_id = 2; // optional: filter by academic term } message ReportCard { string student_id = 1; string term_id = 2; repeated ReportCardEntry entries = 3; string overall_grade = 4; string class_rank = 5; string created_at = 6; } message ReportCardEntry { string subject_id = 1; string subject_name = 2; string exam_score = 3; string exam_total = 4; string homework_score = 5; string homework_total = 6; string final_score = 7; string grade_level = 8; // A / B / C / D / F string teacher_comment = 9; } // ---------------------------------------------------------------------------- // Schedule domain extensions (P3.13) // ---------------------------------------------------------------------------- message GetScheduleByStudentRequest { string student_id = 1; string week_start = 2; // ISO 8601 date, optional } message GetScheduleByStudentResponse { repeated ScheduleSlotInfo slots = 1; } message ScheduleSlotInfo { string id = 1; string course_id = 2; string course_name = 3; string teacher_id = 4; string class_id = 5; string room_id = 6; string start_time = 7; // ISO 8601 string end_time = 8; // ISO 8601 string subject_id = 9; } // ---------------------------------------------------------------------------- // LeaveRequest domain (P3.13) // ---------------------------------------------------------------------------- message LeaveRequest { string id = 1; string student_id = 2; string class_id = 3; string leave_type = 4; // sick / personal / family / activity / other string start_date = 5; // ISO 8601 string end_date = 6; // ISO 8601 string reason = 7; string status = 8; // pending / approved / rejected / cancelled string submitted_by = 9; string reviewed_by = 10; string review_comment = 11; string school_id = 12; string created_at = 13; string updated_at = 14; } message ListLeaveRequestsByStudentRequest { string student_id = 1; string status = 2; // optional filter } message ListLeaveRequestsResponse { repeated LeaveRequest leave_requests = 1; } message CreateLeaveRequestRequest { string student_id = 1; string class_id = 2; string leave_type = 3; string start_date = 4; string end_date = 5; string reason = 6; string submitted_by = 7; string school_id = 8; } message CreateLeaveRequestResponse { string id = 1; } message CancelLeaveRequestRequest { string id = 1; string cancelled_by = 2; } message CancelLeaveRequestResponse { bool success = 1; } // ---------------------------------------------------------------------------- // Dashboard domain (P3.13) // ---------------------------------------------------------------------------- message GetDashboardRequest { string teacher_id = 1; } message DashboardData { string teacher_id = 1; int32 total_classes = 2; int32 total_students = 3; int32 pending_homework = 4; int32 upcoming_exams = 5; int32 ungraded_submissions = 6; repeated DashboardClassCard classes = 7; repeated DashboardExamCard upcoming_exam_list = 8; string generated_at = 9; } message DashboardClassCard { string class_id = 1; string class_name = 2; int32 student_count = 3; } message DashboardExamCard { string exam_id = 1; string title = 2; string exam_date = 3; string class_id = 4; string class_name = 5; } message GetClassPerformanceRequest { string class_id = 1; string subject_id = 2; // optional } message ClassPerformance { string class_id = 1; string class_name = 2; int32 student_count = 3; string average_score = 4; string highest_score = 5; string lowest_score = 6; string median_score = 7; repeated ClassPerformanceSubject subjects = 8; string generated_at = 9; } message ClassPerformanceSubject { string subject_id = 1; string subject_name = 2; string average_score = 3; int32 student_count = 4; } // ---------------------------------------------------------------------------- // Admin aggregation domain (P3.13 stubs) // ---------------------------------------------------------------------------- message ListSchoolsRequest { // no params - returns all schools (admin scope) } message ListSchoolsResponse { repeated SchoolInfo schools = 1; } message SchoolInfo { string id = 1; string name = 2; string address = 3; string principal_id = 4; string created_at = 5; } message ListGradeLevelsRequest { string school_id = 1; } message ListGradeLevelsResponse { repeated GradeLevelInfo grade_levels = 1; } message GradeLevelInfo { string id = 1; string name = 2; // 如 "7年级" string school_id = 3; int32 order = 4; } message ListDepartmentsRequest { string school_id = 1; } message ListDepartmentsResponse { repeated DepartmentInfo departments = 1; } message DepartmentInfo { string id = 1; string name = 2; string school_id = 3; string head_id = 4; string created_at = 5; } message ListAcademicYearsRequest { string school_id = 1; // optional } message ListAcademicYearsResponse { repeated AcademicYearInfo academic_years = 1; } message AcademicYearInfo { string id = 1; string name = 2; // 如 "2025-2026 第一学期" string school_id = 3; string start_date = 4; string end_date = 5; bool is_current = 6; }