Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
package com.devaulty.backend.adapter.in.web.problem;

import com.devaulty.backend.adapter.in.web.exception.ApiErrorResponse;
import com.devaulty.backend.adapter.in.web.problem.dto.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.UUID;

@Tag(name = "Problems", description = "Endpoints for managing problems/errors encountered within a project")
public interface ProblemApi {

@Operation(
summary = "Create a new problem log",
description = "Logs a new problem associated with the specified project ID."
)
@ApiResponses(value = {
@ApiResponse(
responseCode = "201",
description = "Problem logged successfully",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ProblemViewResponse.class)
)
),
@ApiResponse(
responseCode = "400",
description = "Invalid request body or validation constraints failed",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiErrorResponse.class)
)
),
@ApiResponse(
responseCode = "404",
description = "Project not found",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiErrorResponse.class)
)
),
@ApiResponse(
responseCode = "500",
description = "Internal server error occurred",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiErrorResponse.class)
)
)
})
@PostMapping
ResponseEntity<ProblemViewResponse> create(
@PathVariable UUID projectId,
@RequestBody @Valid CreateProblemRequest request
);

@Operation(
summary = "Get all problems by project",
description = "Retrieves a paginated list of all problem summaries belonging to the specified project ID."
)
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "Successfully retrieved list of problem summaries"
),
@ApiResponse(
responseCode = "404",
description = "Project not found",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiErrorResponse.class)
)
),
@ApiResponse(
responseCode = "500",
description = "Internal server error occurred",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiErrorResponse.class)
)
)
})
@GetMapping
ResponseEntity<Page<ProblemSummaryResponse>> getAllByProject(
@PathVariable UUID projectId,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size
);
Comment thread
MathCunha16 marked this conversation as resolved.

@Operation(
summary = "Get problem details by ID",
description = "Retrieves details of a single problem by its unique identifier and its project ID."
)
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "Successfully retrieved the problem details",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ProblemViewResponse.class)
)
),
@ApiResponse(
responseCode = "404",
description = "Project or Problem not found",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiErrorResponse.class)
)
),
@ApiResponse(
responseCode = "500",
description = "Internal server error occurred",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiErrorResponse.class)
)
)
})
@GetMapping("/{problemId}")
ResponseEntity<ProblemViewResponse> getById(
@PathVariable UUID projectId,
@PathVariable UUID problemId
);

@Operation(
summary = "Update a problem",
description = "Updates details of an existing problem by its unique identifier and its project ID."
)
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "Problem updated successfully",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ProblemViewResponse.class)
)
),
@ApiResponse(
responseCode = "400",
description = "Invalid request body or validation constraints failed",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiErrorResponse.class)
)
),
@ApiResponse(
responseCode = "404",
description = "Project or Problem not found",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiErrorResponse.class)
)
),
@ApiResponse(
responseCode = "500",
description = "Internal server error occurred",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiErrorResponse.class)
)
)
})
@PatchMapping("/{problemId}")
ResponseEntity<ProblemViewResponse> update(
@PathVariable UUID projectId,
@PathVariable UUID problemId,
@RequestBody @Valid UpdateProblemRequest request
);

@Operation(
summary = "Update problem status",
description = "Updates status of an existing problem by its unique identifier and its project ID."
)
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "Problem status updated successfully",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ProblemViewResponse.class)
)
),
@ApiResponse(
responseCode = "400",
description = "Invalid request body or validation constraints failed",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiErrorResponse.class)
)
),
@ApiResponse(
responseCode = "404",
description = "Project or Problem not found",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiErrorResponse.class)
)
),
@ApiResponse(
responseCode = "500",
description = "Internal server error occurred",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiErrorResponse.class)
)
)
})
@PatchMapping("/{problemId}/status")
ResponseEntity<ProblemViewResponse> updateStatus(
@PathVariable UUID projectId,
@PathVariable UUID problemId,
@RequestBody @Valid UpdateProblemStatusRequest request
);

@Operation(
summary = "Delete a problem log",
description = "Deletes an existing problem log by its unique identifier and its project ID."
)
@ApiResponses(value = {
@ApiResponse(
responseCode = "204",
description = "Problem deleted successfully"
),
@ApiResponse(
responseCode = "404",
description = "Project or Problem not found",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiErrorResponse.class)
)
),
@ApiResponse(
responseCode = "500",
description = "Internal server error occurred",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiErrorResponse.class)
)
)
})
@DeleteMapping("/{problemId}")
ResponseEntity<Void> delete(
@PathVariable UUID projectId,
@PathVariable UUID problemId
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package com.devaulty.backend.adapter.in.web.problem;

import com.devaulty.backend.adapter.in.web.problem.dto.*;
import com.devaulty.backend.adapter.in.web.util.UriLocationBuilderHelper;
import com.devaulty.backend.application.port.in.problem.*;
import com.devaulty.backend.domain.model.Problem;
import jakarta.validation.Valid;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.net.URI;
import java.util.UUID;

@RestController
@RequestMapping("/api/v1/projects/{projectId}/problems")
public class ProblemController implements ProblemApi{

private final CreateProblemUseCase createProblemUseCase;
private final GetAllProblemsByProjectUseCase getAllProblemsByProjectUseCase;
private final GetProblemByIdUseCase getProblemByIdUseCase;
private final UpdateProblemUseCase updateProblemUseCase;
private final UpdateProblemStatusUseCase updateProblemStatusUseCase;
private final DeleteProblemUseCase deleteProblemUseCase;
private final ProblemWebMapper mapper;
private final UriLocationBuilderHelper uriLocationBuilderHelper;

public ProblemController(CreateProblemUseCase createProblemUseCase, GetAllProblemsByProjectUseCase getAllProblemsByProjectUseCase, GetProblemByIdUseCase getProblemByIdUseCase, UpdateProblemUseCase updateProblemUseCase, UpdateProblemStatusUseCase updateProblemStatusUseCase, DeleteProblemUseCase deleteProblemUseCase, ProblemWebMapper mapper, UriLocationBuilderHelper uriLocationBuilderHelper) {
this.createProblemUseCase = createProblemUseCase;
this.getAllProblemsByProjectUseCase = getAllProblemsByProjectUseCase;
this.getProblemByIdUseCase = getProblemByIdUseCase;
this.updateProblemUseCase = updateProblemUseCase;
this.updateProblemStatusUseCase = updateProblemStatusUseCase;
this.deleteProblemUseCase = deleteProblemUseCase;
this.mapper = mapper;
this.uriLocationBuilderHelper = uriLocationBuilderHelper;
}

@Override
@PostMapping
public ResponseEntity<ProblemViewResponse> create(
@PathVariable UUID projectId,
@RequestBody @Valid CreateProblemRequest request)
{
CreateProblemCommand command = mapper.toCreateProblemCommand(request, projectId);
Problem problem = createProblemUseCase.execute(command);
URI location = uriLocationBuilderHelper.buildLocationUri(problem.getId());
return ResponseEntity.created(location).body(mapper.toViewResponse(problem));
}

@Override
@GetMapping
public ResponseEntity<Page<ProblemSummaryResponse>> getAllByProject(
@PathVariable UUID projectId,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size
){
Page<Problem> problems = getAllProblemsByProjectUseCase.execute(projectId, page, size);
return ResponseEntity.ok(problems.map(mapper::toSummaryResponse));
}

@Override
@GetMapping("/{problemId}")
public ResponseEntity<ProblemViewResponse> getById(
@PathVariable UUID projectId,
@PathVariable UUID problemId
){
Problem problem = getProblemByIdUseCase.execute(projectId, problemId);
return ResponseEntity.ok(mapper.toViewResponse(problem));
}

@Override
@PatchMapping("/{problemId}")
public ResponseEntity<ProblemViewResponse> update(
@PathVariable UUID projectId,
@PathVariable UUID problemId,
@RequestBody @Valid UpdateProblemRequest request
){
UpdateProblemCommand command = mapper.toUpdateProblemCommand(request, projectId, problemId);
Problem problem = updateProblemUseCase.execute(command);
return ResponseEntity.ok(mapper.toViewResponse(problem));
}

@Override
@PatchMapping("/{problemId}/status")
public ResponseEntity<ProblemViewResponse> updateStatus(
@PathVariable UUID projectId,
@PathVariable UUID problemId,
@RequestBody @Valid UpdateProblemStatusRequest request
){
UpdateProblemStatusCommand command = mapper.toUpdateProblemStatusCommand(request, projectId, problemId);
Problem problem = updateProblemStatusUseCase.execute(command);
return ResponseEntity.ok(mapper.toViewResponse(problem));
}

@Override
@DeleteMapping("/{problemId}")
public ResponseEntity<Void> delete(
@PathVariable UUID projectId,
@PathVariable UUID problemId
){
deleteProblemUseCase.execute(projectId, problemId);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.devaulty.backend.adapter.in.web.problem;

import com.devaulty.backend.adapter.in.web.problem.dto.*;
import com.devaulty.backend.application.port.in.problem.CreateProblemCommand;
import com.devaulty.backend.application.port.in.problem.UpdateProblemCommand;
import com.devaulty.backend.application.port.in.problem.UpdateProblemStatusCommand;
import com.devaulty.backend.domain.model.Problem;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

import java.util.UUID;

@Mapper(componentModel = "spring")
public interface ProblemWebMapper {

ProblemViewResponse toViewResponse(Problem problem);

ProblemSummaryResponse toSummaryResponse(Problem problem);

@Mapping(target = "projectId", source = "projectId")
CreateProblemCommand toCreateProblemCommand(CreateProblemRequest request, UUID projectId);

@Mapping(target = "projectId", source = "projectId")
@Mapping(target = "id", source = "problemId")
UpdateProblemCommand toUpdateProblemCommand(UpdateProblemRequest request, UUID projectId, UUID problemId);

@Mapping(target = "projectId", source = "projectId")
@Mapping(target = "id", source = "problemId")
UpdateProblemStatusCommand toUpdateProblemStatusCommand(UpdateProblemStatusRequest request, UUID projectId, UUID problemId);
}
Loading