From 86ab4e53d47d51cfec59b9e8cea04495d728e72c Mon Sep 17 00:00:00 2001 From: Yared Yemane Date: Wed, 13 May 2026 03:36:39 -0700 Subject: [PATCH] Fix practice completion lookup for progress endpoint. Prioritize resolving lms_practices.id before falling back to question_set.id to avoid false 404 responses caused by cross-table ID collisions. Co-authored-by: Cursor --- internal/web_server/handlers/questions.go | 32 ++++++++++------------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/internal/web_server/handlers/questions.go b/internal/web_server/handlers/questions.go index 876021a..3141599 100644 --- a/internal/web_server/handlers/questions.go +++ b/internal/web_server/handlers/questions.go @@ -1547,29 +1547,25 @@ func (h *Handler) CompletePractice(c *fiber.Ctx) error { }) } - set, err := h.questionsSvc.GetQuestionSetByID(c.Context(), id) - if err != nil { - // Backward/UX compatibility: accept either question_set.id or lms_practices.id. - practice, practiceErr := h.practiceSvc.GetByID(c.Context(), id) - if practiceErr != nil { - return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{ - Message: "Practice not found", - Error: err.Error(), - }) - } - set, err = h.questionsSvc.GetQuestionSetByID(c.Context(), practice.QuestionSetID) - if err != nil { - return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{ - Message: "Practice not found", - Error: err.Error(), - }) - } + // Prefer LMS practice ID resolution to avoid accidental collisions with question_set IDs. + practice, practiceErr := h.practiceSvc.GetByID(c.Context(), id) + var set domain.QuestionSet + var setErr error + if practiceErr == nil { + set, setErr = h.questionsSvc.GetQuestionSetByID(c.Context(), practice.QuestionSetID) + } else { + // Backward compatibility: also accept question_set.id directly. + set, setErr = h.questionsSvc.GetQuestionSetByID(c.Context(), id) } - if !isSequenceGatedPractice(set) || !strings.EqualFold(set.Status, "PUBLISHED") { + if setErr != nil { return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{ Message: "Practice not found", + Error: setErr.Error(), }) } + if !strings.EqualFold(set.SetType, string(domain.QuestionSetTypePractice)) || !strings.EqualFold(set.Status, "PUBLISHED") { + return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{Message: "Practice not found"}) + } if err := h.enforcePracticeSequenceForStudent(c, set); err != nil { return c.Status(fiber.StatusForbidden).JSON(domain.ErrorResponse{