Enforce strict initial assessment set validation.
Require INITIAL_ASSESSMENT titles to follow the Level Test A1/A2/B1/B2 format and ensure passing_score is always present on create and update. Made-with: Cursor
This commit is contained in:
parent
9027b65011
commit
cdb0fa1bb3
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
|
@ -550,6 +551,15 @@ type listQuestionSetsRes struct {
|
||||||
TotalCount int64 `json:"total_count"`
|
TotalCount int64 `json:"total_count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var initialAssessmentTitlePattern = regexp.MustCompile(`^Level Test (A1|A2|B1|B2) \([^)]+\)$`)
|
||||||
|
|
||||||
|
func validateInitialAssessmentTitle(title string) error {
|
||||||
|
if !initialAssessmentTitlePattern.MatchString(strings.TrimSpace(title)) {
|
||||||
|
return fmt.Errorf("title must match format: Level Test <A1|A2|B1|B2> (<description>)")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func isSequenceGatedPractice(set domain.QuestionSet) bool {
|
func isSequenceGatedPractice(set domain.QuestionSet) bool {
|
||||||
if !strings.EqualFold(set.SetType, string(domain.QuestionSetTypePractice)) || set.OwnerType == nil {
|
if !strings.EqualFold(set.SetType, string(domain.QuestionSetTypePractice)) || set.OwnerType == nil {
|
||||||
return false
|
return false
|
||||||
|
|
@ -605,6 +615,20 @@ func (h *Handler) CreateQuestionSet(c *fiber.Ctx) error {
|
||||||
Error: err.Error(),
|
Error: err.Error(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
if strings.EqualFold(req.SetType, string(domain.QuestionSetTypeInitialAssessment)) {
|
||||||
|
if err := validateInitialAssessmentTitle(req.Title); err != nil {
|
||||||
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
||||||
|
Message: "Invalid initial assessment title",
|
||||||
|
Error: err.Error(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if req.PassingScore == nil {
|
||||||
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
||||||
|
Message: "Invalid initial assessment set",
|
||||||
|
Error: "passing_score is required for INITIAL_ASSESSMENT question sets",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
input := domain.CreateQuestionSetInput{
|
input := domain.CreateQuestionSetInput{
|
||||||
Title: req.Title,
|
Title: req.Title,
|
||||||
|
|
@ -883,6 +907,14 @@ func (h *Handler) UpdateQuestionSet(c *fiber.Ctx) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
existingSet, err := h.questionsSvc.GetQuestionSetByID(c.Context(), id)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{
|
||||||
|
Message: "Question set not found",
|
||||||
|
Error: err.Error(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
var req updateQuestionSetReq
|
var req updateQuestionSetReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
||||||
|
|
@ -896,6 +928,30 @@ func (h *Handler) UpdateQuestionSet(c *fiber.Ctx) error {
|
||||||
title = *req.Title
|
title = *req.Title
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if strings.EqualFold(existingSet.SetType, string(domain.QuestionSetTypeInitialAssessment)) {
|
||||||
|
effectiveTitle := existingSet.Title
|
||||||
|
if req.Title != nil {
|
||||||
|
effectiveTitle = *req.Title
|
||||||
|
}
|
||||||
|
if err := validateInitialAssessmentTitle(effectiveTitle); err != nil {
|
||||||
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
||||||
|
Message: "Invalid initial assessment title",
|
||||||
|
Error: err.Error(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
effectivePassingScore := existingSet.PassingScore
|
||||||
|
if req.PassingScore != nil {
|
||||||
|
effectivePassingScore = req.PassingScore
|
||||||
|
}
|
||||||
|
if effectivePassingScore == nil {
|
||||||
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
||||||
|
Message: "Invalid initial assessment set",
|
||||||
|
Error: "passing_score is required for INITIAL_ASSESSMENT question sets",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
input := domain.CreateQuestionSetInput{
|
input := domain.CreateQuestionSetInput{
|
||||||
Title: title,
|
Title: title,
|
||||||
Description: req.Description,
|
Description: req.Description,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user