2121import org .springframework .web .bind .annotation .*;
2222
2323@ RestController
24- @ RequestMapping ("/api/v1/tasks/{taskId }/questions" )
24+ @ RequestMapping ("/api/v1/task-assignments/{taskAssignmentId }/questions" )
2525@ RequiredArgsConstructor
2626@ PreAuthorize ("isAuthenticated()" )
2727@ Tag (
2828 name = "Participant Forum V1" ,
29- description = "Participant operations for temporary TaskBody -scoped question forums" )
29+ description = "Participant operations for TaskAssignment -scoped question forums" )
3030public class ParticipantForumController {
3131 private final ParticipantForumService participantForumService ;
3232
3333 @ Operation (
34- summary = "Get participant forum questions" ,
34+ summary = "Get task assignment forum questions" ,
3535 description = """
36- Returns a paginated list of questions for the specified task.
36+ Returns a paginated list of questions for the specified task assignment .
3737
38- The response contains public questions and private questions created by
39- the authenticated participant. Questions are ordered by creation time
40- in descending order, with the question ID used as a deterministic
41- tie-breaker .
38+ For an authenticated participant, the response contains public questions
39+ and private questions created by that participant. Participant access
40+ requires the task assignment to be visible and requires a matching
41+ Participation for the assignment's competition and stage .
4242
43- This is a temporary TaskBody-scoped API that will be migrated to
44- TaskAssignment-scoped access.
43+ A global administrator may access an existing task assignment forum
44+ without a participant record.
45+
46+ Questions are ordered by creation time in descending order, with the
47+ question identifier used as a deterministic tie-breaker.
4548 """ )
4649 @ ApiResponses (value = {
4750 @ ApiResponse (
4851 responseCode = "200" ,
49- description = "Forum questions retrieved successfully" ,
52+ description = "Task assignment forum page retrieved successfully" ,
5053 content = @ Content (
5154 mediaType = "application/json" ,
52- schema = @ Schema (implementation = PageResponse .class ))),
55+ schema = @ Schema (
56+ implementation = PageResponse .class ))),
5357 @ ApiResponse (
5458 responseCode = "400" ,
55- description = "Task identifier or pagination parameters are invalid" ,
59+ description = "Task assignment identifier or pagination parameters are invalid" ,
5660 content = @ Content (
5761 mediaType = "application/json" ,
58- schema = @ Schema (implementation = ErrorResponse .class ))),
62+ schema = @ Schema (
63+ implementation = ErrorResponse .class ))),
5964 @ ApiResponse (
6065 responseCode = "401" ,
6166 description = "Authentication is required" ,
6267 content = @ Content (
6368 mediaType = "application/json" ,
64- schema = @ Schema (implementation = ErrorResponse .class ))),
69+ schema = @ Schema (
70+ implementation = ErrorResponse .class ))),
71+ @ ApiResponse (
72+ responseCode = "403" ,
73+ description = "The task assignment is hidden or matching participation is missing" ,
74+ content = @ Content (
75+ mediaType = "application/json" ,
76+ schema = @ Schema (
77+ implementation = ErrorResponse .class ))),
6578 @ ApiResponse (
6679 responseCode = "404" ,
67- description = "Task was not found" ,
80+ description = "The task assignment, related tour, or related stage was not found" ,
6881 content = @ Content (
6982 mediaType = "application/json" ,
70- schema = @ Schema (implementation = ErrorResponse .class )))
83+ schema = @ Schema (
84+ implementation = ErrorResponse .class )))
7185 })
7286 @ GetMapping
7387 public ResponseEntity <PageResponse <QuestionThreadSummaryResponseDTO >> getParticipantForum (
7488 @ Parameter (
75- description = "Positive identifier of the task whose forum is requested" ,
89+ description = "Positive identifier of the task assignment whose forum is requested" ,
7690 example = "42" ,
77- required = true ) @ PathVariable Long taskId ,
78-
91+ required = true ) @ PathVariable Long taskAssignmentId ,
7992 @ Parameter (
8093 description = "Zero-based page number" ,
8194 example = "0" ) @ RequestParam (defaultValue = "0" ) int page ,
82-
8395 @ Parameter (
8496 description = "Number of questions per page. Must be between 1 and 100" ,
8597 example = "20" ) @ RequestParam (defaultValue = "20" ) int size ) {
8698 return ResponseEntity .ok (
87- PageResponse .from (
88- participantForumService .getForumQuestions (
89- taskId ,
90- page ,
91- size )));
99+ PageResponse .from (participantForumService .getForumQuestions (taskAssignmentId , page , size )));
92100 }
93101
94102 @ Operation (
95- summary = "Create a participant question" ,
103+ summary = "Create a question in a task assignment forum " ,
96104 description = """
97- Creates a private question in the forum of the specified task.
105+ Creates a private question in the forum of the specified task assignment.
106+
107+ For a participant, the task assignment must be visible and a matching
108+ Participation must exist for the assignment's competition and stage.
109+ A global administrator may access an existing task assignment forum
110+ without a participant record.
111+
112+ The related tour must have the IN_PROGRESS execution status.
98113
99114 The authenticated user becomes the question author. The backend assigns
100- the initial status NEW, state OPEN, visibility PRIVATE, an empty reviewer,
101- and version zero.
115+ status NEW, state OPEN, visibility PRIVATE, no reviewer, and version zero.
102116
103- The request may provide only the question title and content. This is a
104- temporary TaskBody-scoped API that will be migrated to
105- TaskAssignment-scoped access .
117+ The request may provide only the question title and content. The task
118+ assignment identifier and all workflow fields are controlled by the
119+ backend .
106120 """ )
107- @ ApiResponses (value = {
108- @ ApiResponse (
109- responseCode = "201" ,
110- description = "Question created successfully" ,
111- content = @ Content (
112- mediaType = "application/json" ,
113- schema = @ Schema (implementation = QuestionThreadResponseDTO .class ))),
114- @ ApiResponse (
115- responseCode = "400" ,
116- description = "Task identifier or request body is invalid" ,
117- content = @ Content (
118- mediaType = "application/json" ,
119- schema = @ Schema (implementation = ErrorResponse .class ))),
120- @ ApiResponse (
121- responseCode = "401" ,
122- description = "Authentication is required" ,
123- content = @ Content (
124- mediaType = "application/json" ,
125- schema = @ Schema (implementation = ErrorResponse .class ))),
126- @ ApiResponse (
127- responseCode = "404" ,
128- description = "Task was not found" ,
129- content = @ Content (
130- mediaType = "application/json" ,
131- schema = @ Schema (implementation = ErrorResponse .class )))
132- })
121+ @ ApiResponses (
122+ value = {
123+ @ ApiResponse (
124+ responseCode = "201" ,
125+ description = "Question created successfully" ,
126+ content = @ Content (
127+ mediaType = "application/json" ,
128+ schema = @ Schema (
129+ implementation = QuestionThreadResponseDTO .class ))),
130+ @ ApiResponse (
131+ responseCode = "400" ,
132+ description = "Task assignment identifier or request body is invalid" ,
133+ content = @ Content (
134+ mediaType = "application/json" ,
135+ schema = @ Schema (
136+ implementation = ErrorResponse .class ))),
137+ @ ApiResponse (
138+ responseCode = "401" ,
139+ description = "Authentication is required" ,
140+ content = @ Content (
141+ mediaType = "application/json" ,
142+ schema = @ Schema (
143+ implementation = ErrorResponse .class ))),
144+ @ ApiResponse (
145+ responseCode = "403" ,
146+ description = "The task assignment is hidden or matching participation is missing" ,
147+ content = @ Content (
148+ mediaType = "application/json" ,
149+ schema = @ Schema (
150+ implementation = ErrorResponse .class ))),
151+ @ ApiResponse (
152+ responseCode = "404" ,
153+ description = "The task assignment, related tour, or related stage was not found" ,
154+ content = @ Content (
155+ mediaType = "application/json" ,
156+ schema = @ Schema (
157+ implementation = ErrorResponse .class ))),
158+ @ ApiResponse (
159+ responseCode = "409" ,
160+ description = "Question creation is not allowed because the related tour is not in progress" ,
161+ content = @ Content (
162+ mediaType = "application/json" ,
163+ schema = @ Schema (
164+ implementation = ErrorResponse .class )))
165+ })
133166 @ PostMapping
134167 public ResponseEntity <QuestionThreadResponseDTO > createQuestion (
135168 @ Parameter (
136- description = "Positive identifier of the task in which the question is created" ,
169+ description = "Positive identifier of the task assignment in which the question is created" ,
137170 example = "42" ,
138- required = true ) @ PathVariable Long taskId ,
171+ required = true ) @ PathVariable Long taskAssignmentId ,
139172 @ Valid @ RequestBody CreateQuestionRequestDTO request ) {
140- QuestionThreadResponseDTO response =
141- participantForumService .createQuestion (taskId , request );
173+ QuestionThreadResponseDTO response = participantForumService .createQuestion (taskAssignmentId , request );
142174
143175 return ResponseEntity
144176 .status (HttpStatus .CREATED )
145177 .body (response );
146178 }
147- }
179+ }
0 commit comments