fix: end grading when a question stops being open
WR-06: a Question save hook clears grading_status on the answers of a question that changed type away from open, in the save's transaction, so they leave the review queue and needs_review. GradeAnswer ignores a question that is no longer open, and a choice or self-check re-answer clears the text, grade and review columns of its row.
This commit is contained in:
45
models/question_hooks.go
Normal file
45
models/question_hooks.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// wasOpenKey is the statement setting by which BeforeSave tells AfterSave
|
||||
// that the saved question was open before.
|
||||
const wasOpenKey = "golem15.quizzes:question_was_open"
|
||||
|
||||
// BeforeSave notes whether a stored question that is saved as another
|
||||
// type was open, for AfterSave. Every write path (the admin form and
|
||||
// relation manager, the manage API and MCP, the importer) saves through
|
||||
// GORM, so the hooks cover them all.
|
||||
func (q *Question) BeforeSave(tx *gorm.DB) error {
|
||||
if q.ID == 0 || q.Type == TypeOpen {
|
||||
return nil
|
||||
}
|
||||
var stored string
|
||||
err := tx.Session(&gorm.Session{NewDB: true}).Model(&Question{}).
|
||||
Where("id = ?", q.ID).Limit(1).Pluck("type", &stored).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if stored == TypeOpen {
|
||||
tx.InstanceSet(wasOpenKey, true)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AfterSave ends the grading of the answers to a question that stopped
|
||||
// being open, in the same transaction as the save: their grading_status
|
||||
// becomes NULL, so they leave the review queue and needs_review, and a
|
||||
// grading job still queued for them does nothing. Their text, grades and
|
||||
// points stay for the record (stored scores are never touched).
|
||||
func (q *Question) AfterSave(tx *gorm.DB) error {
|
||||
if was, ok := tx.InstanceGet(wasOpenKey); !ok || was != true {
|
||||
return nil
|
||||
}
|
||||
return tx.Session(&gorm.Session{NewDB: true}).Model(&AttemptAnswer{}).
|
||||
Where("question_id = ? AND grading_status IS NOT NULL", q.ID).
|
||||
Updates(map[string]any{"grading_status": nil, "updated_at": time.Now().UTC()}).Error
|
||||
}
|
||||
Reference in New Issue
Block a user