Files
sm-quizzes-plugin/models/review.go
Jakub Zych 2ad4e8b1ec feat: review open answers in the admin and pick a grader per quiz
- Do oceny admin screen (golem15.quizzes.reviews) over the open answers,
  with a read-only context partial, score and comment virtual fields saved
  through SetScore, confirm and regrade record actions, bulk confirm
- open question type, rubric and max_length in the question form; grader
  dropdown on the quiz form from the grader registry
- Review model with quiz, status and student filters
2026-11-09 18:31:19 +01:00

61 lines
2.6 KiB
Go

package models
import "time"
// ReviewMorphName is Review's morph type. Review shares its table with
// AttemptAnswer, so it names itself: two models listed in Models() with the
// same morph type would stop deferred:purge.
const ReviewMorphName = "golem15.quizzes.review"
// Review is an open answer as the admin "Do oceny" screen shows it. It reads
// the same golem15_quizzes_attempt_answers table as AttemptAnswer, which
// keeps its empty Fillable for the API; the admin never writes a column
// through it either. The owner's score and comment are form virtual fields
// that the controller saves through the review service.
type Review struct {
ID uint `gorm:"column:id;primaryKey"`
AttemptID uint `gorm:"column:attempt_id"`
QuestionID uint `gorm:"column:question_id"`
TextAnswer *string `gorm:"column:text_answer"`
GradingStatus *string `gorm:"column:grading_status"`
GradingSeq int `gorm:"column:grading_seq"`
GradingAttempts int `gorm:"column:grading_attempts"`
Grader *string `gorm:"column:grader"`
GraderPoints *float64 `gorm:"column:grader_points"`
GraderFeedback *string `gorm:"column:grader_feedback"`
GradingError *string `gorm:"column:grading_error"`
GradedAt *time.Time `gorm:"column:graded_at"`
Points float64 `gorm:"column:points"`
IsCorrect bool `gorm:"column:is_correct"`
ReviewComment *string `gorm:"column:review_comment"`
ReviewedAt *time.Time `gorm:"column:reviewed_at"`
ReviewedByUserID *uint `gorm:"column:reviewed_by_user_id"`
ReviewedByAdminID *uint `gorm:"column:reviewed_by_admin_id"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
Question *Question `gorm:"foreignKey:QuestionID"`
Attempt *Attempt `gorm:"foreignKey:AttemptID"`
}
// TableName is the attempt answers table.
func (Review) TableName() string { return "golem15_quizzes_attempt_answers" }
// MorphName keeps Review apart from AttemptAnswer, which owns the table.
func (Review) MorphName() string { return ReviewMorphName }
// Fillable is empty: the admin form saves no column of an answer.
func (Review) Fillable() []string { return []string{} }
// Rules are empty: the controller's FormRules check the virtual fields.
func (Review) Rules() map[string]string { return map[string]string{} }
// ReviewStatus reports the grading status, "" when the row is not an open
// answer.
func (r Review) ReviewStatus() string {
if r.GradingStatus == nil {
return ""
}
return *r.GradingStatus
}