diff --git a/VEZA_COMPLETE_MVP_TODOLIST.json b/VEZA_COMPLETE_MVP_TODOLIST.json index 7a37b838a..3c8904780 100644 --- a/VEZA_COMPLETE_MVP_TODOLIST.json +++ b/VEZA_COMPLETE_MVP_TODOLIST.json @@ -2130,7 +2130,17 @@ "description": "Verify GET /api/v1/users/:id/completion returns correct completion percentage", "owner": "backend", "estimated_hours": 2, - "status": "todo", + "status": "completed", + "completion": { + "completed_at": "2025-12-23T10:03:30Z", + "actual_hours": 0.5, + "commits": [], + "files_changed": [ + "veza-backend-api/internal/handlers/profile_handler.go" + ], + "notes": "Standardized GetProfileCompletion handler to use GetUserIDUUID instead of c.Get. Added validation to ensure completion percentage is between 0 and 100. Handler already existed and was working correctly. The CalculateProfileCompletion service method correctly calculates percentage as (completedFields * 100) / totalFields. Endpoint returns correct completion percentage (0-100) and list of missing fields. Handler uses standard API response format (RespondSuccess, RespondWithAppError).", + "issues_encountered": [] + }, "files_involved": [], "implementation_steps": [ { diff --git a/veza-backend-api/internal/handlers/profile_handler.go b/veza-backend-api/internal/handlers/profile_handler.go index f376021d4..65ba999d2 100644 --- a/veza-backend-api/internal/handlers/profile_handler.go +++ b/veza-backend-api/internal/handlers/profile_handler.go @@ -118,6 +118,8 @@ func (h *ProfileHandler) GetProfileByUsername(c *gin.Context) { } // GetProfileCompletion retrieves the profile completion status +// GET /api/v1/users/:id/completion +// BE-API-023: Implement user completion endpoint validation // T0220: Returns percentage and missing fields // @Summary Get Profile Completion // @Description Get profile completion percentage and missing fields @@ -134,22 +136,14 @@ func (h *ProfileHandler) GetProfileCompletion(c *gin.Context) { userIDStr := c.Param("id") userID, err := uuid.Parse(userIDStr) if err != nil { - RespondWithAppError(c, apperrors.New(apperrors.ErrCodeValidation, "invalid user id")) + RespondWithAppError(c, apperrors.NewValidationError("invalid user id")) return } // Get authenticated user ID - var authenticatedUserID uuid.UUID - if reqID, exists := c.Get("user_id"); exists { - if reqUUID, ok := reqID.(uuid.UUID); ok { - authenticatedUserID = reqUUID - } else { - RespondWithAppError(c, apperrors.NewUnauthorizedError("user not authenticated")) - return - } - } else { - RespondWithAppError(c, apperrors.NewUnauthorizedError("user not authenticated")) - return + authenticatedUserID, ok := GetUserIDUUID(c) + if !ok { + return // Erreur déjà envoyée par GetUserIDUUID } // Verify that user_id corresponds to authenticated user @@ -161,10 +155,27 @@ func (h *ProfileHandler) GetProfileCompletion(c *gin.Context) { // Calculate profile completion completion, err := h.userService.CalculateProfileCompletion(userID) if err != nil { - RespondWithAppError(c, apperrors.New(apperrors.ErrCodeInternal, "failed to calculate profile completion")) + if err.Error() == "user not found" { + RespondWithAppError(c, apperrors.NewNotFoundError("user")) + return + } + RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "failed to calculate profile completion", err)) return } + // Verify that percentage is between 0 and 100 + if completion.Percentage < 0 || completion.Percentage > 100 { + h.logger.Warn("Invalid completion percentage calculated", + zap.Int("percentage", completion.Percentage), + zap.String("user_id", userID.String())) + // Clamp to valid range + if completion.Percentage < 0 { + completion.Percentage = 0 + } else if completion.Percentage > 100 { + completion.Percentage = 100 + } + } + RespondSuccess(c, http.StatusOK, completion) }