diff --git a/src/main/java/com/first/flash/climbing/problem/application/ProblemsHoldService.java b/src/main/java/com/first/flash/climbing/problem/application/ProblemsHoldService.java new file mode 100644 index 00000000..9abb42d3 --- /dev/null +++ b/src/main/java/com/first/flash/climbing/problem/application/ProblemsHoldService.java @@ -0,0 +1,35 @@ +package com.first.flash.climbing.problem.application; + +import com.first.flash.climbing.hold.application.HoldService; +import com.first.flash.climbing.hold.domain.Hold; +import com.first.flash.climbing.problem.application.dto.ProblemDetailResponseDto; +import com.first.flash.climbing.problem.domain.Problem; +import com.first.flash.climbing.problem.domain.QueryProblem; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class ProblemsHoldService { + + private final ProblemReadService problemReadService; + private final HoldService holdService; + + @Transactional + public ProblemDetailResponseDto updateHold(final UUID problemId, + final Long holdId) { + Hold hold = holdService.findById(holdId); + + Problem problem = problemReadService.findProblemById(problemId); + QueryProblem queryProblem = problemReadService.findQueryProblemById(problemId); + + problem.updateHoldInfo(hold.getId()); + queryProblem.updateHoldInfo(hold.getId(), hold.getColorName(), hold.getColorCode()); + + return ProblemDetailResponseDto.of(queryProblem); + } + +} diff --git a/src/main/java/com/first/flash/climbing/problem/application/dto/ProblemHoldRequestDto.java b/src/main/java/com/first/flash/climbing/problem/application/dto/ProblemHoldRequestDto.java new file mode 100644 index 00000000..82407017 --- /dev/null +++ b/src/main/java/com/first/flash/climbing/problem/application/dto/ProblemHoldRequestDto.java @@ -0,0 +1,8 @@ +package com.first.flash.climbing.problem.application.dto; + +import jakarta.validation.constraints.NotNull; + +public record ProblemHoldRequestDto( + @NotNull(message = "변경할 홀드 id는 필수입니다.") Long holdId) { + +} diff --git a/src/main/java/com/first/flash/climbing/problem/domain/Problem.java b/src/main/java/com/first/flash/climbing/problem/domain/Problem.java index fdd54423..b5d24701 100644 --- a/src/main/java/com/first/flash/climbing/problem/domain/Problem.java +++ b/src/main/java/com/first/flash/climbing/problem/domain/Problem.java @@ -10,6 +10,7 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import lombok.ToString; @Entity @@ -70,4 +71,9 @@ public void setThumbnailInfo(final Long thumbnailSolutionId, final String imageU this.imageUrl = imageUrl; this.imageSource = imageSource; } + + public void updateHoldInfo(final Long holdId) { + this.holdId = holdId; + } + } diff --git a/src/main/java/com/first/flash/climbing/problem/domain/QueryProblem.java b/src/main/java/com/first/flash/climbing/problem/domain/QueryProblem.java index 177515f0..51b39fb7 100644 --- a/src/main/java/com/first/flash/climbing/problem/domain/QueryProblem.java +++ b/src/main/java/com/first/flash/climbing/problem/domain/QueryProblem.java @@ -105,6 +105,12 @@ public void setThumbnailInfo(final Long thumbnailSolutionId, final String imageU this.imageSource = imageSource; } + public void updateHoldInfo(final Long holdId, final String holdColorName, final String holdColorCode) { + this.holdId = holdId; + this.holdColorName = holdColorName; + this.holdColorCode = holdColorCode; + } + private void enableSolution() { if (!hasSolution) { hasSolution = true; diff --git a/src/main/java/com/first/flash/climbing/problem/infrastructure/QueryProblemQueryDslRepository.java b/src/main/java/com/first/flash/climbing/problem/infrastructure/QueryProblemQueryDslRepository.java index 351650ef..e40ec488 100644 --- a/src/main/java/com/first/flash/climbing/problem/infrastructure/QueryProblemQueryDslRepository.java +++ b/src/main/java/com/first/flash/climbing/problem/infrastructure/QueryProblemQueryDslRepository.java @@ -1,9 +1,11 @@ package com.first.flash.climbing.problem.infrastructure; +import static com.first.flash.climbing.hold.domain.QHold.hold; import static com.first.flash.climbing.problem.domain.QQueryProblem.queryProblem; import static com.first.flash.climbing.problem.infrastructure.paging.ProblemSortBy.DIFFICULTY; import static com.first.flash.climbing.problem.infrastructure.paging.ProblemSortBy.VIEWS; +import com.first.flash.climbing.hold.domain.Hold; import com.first.flash.climbing.problem.domain.QueryProblem; import com.first.flash.climbing.problem.infrastructure.paging.ProblemCursor; import com.first.flash.climbing.problem.infrastructure.paging.ProblemSortBy; diff --git a/src/main/java/com/first/flash/climbing/problem/ui/ProblemController.java b/src/main/java/com/first/flash/climbing/problem/ui/ProblemController.java index 90c76305..0e63598c 100644 --- a/src/main/java/com/first/flash/climbing/problem/ui/ProblemController.java +++ b/src/main/java/com/first/flash/climbing/problem/ui/ProblemController.java @@ -1,11 +1,13 @@ package com.first.flash.climbing.problem.ui; import com.first.flash.climbing.problem.application.ProblemReadService; +import com.first.flash.climbing.problem.application.ProblemsHoldService; import com.first.flash.climbing.problem.application.ProblemsSaveService; import com.first.flash.climbing.problem.application.ProblemsService; import com.first.flash.climbing.problem.application.dto.DuplicateProblemsResponseDto; import com.first.flash.climbing.problem.application.dto.ProblemCreateResponseDto; import com.first.flash.climbing.problem.application.dto.ProblemDetailResponseDto; +import com.first.flash.climbing.problem.application.dto.ProblemHoldRequestDto; import com.first.flash.climbing.problem.application.dto.ProblemPerceivedDifficultyRequestDto; import com.first.flash.climbing.problem.application.dto.ProblemsResponseDto; import com.first.flash.climbing.problem.domain.dto.ProblemCreateRequestDto; @@ -41,6 +43,7 @@ public class ProblemController { private final ProblemsSaveService problemsSaveService; private final ProblemReadService problemReadService; private final ProblemsService problemsService; + private final ProblemsHoldService problemsHoldService; @Operation(summary = "문제 생성", description = "특정 섹터에 문제 생성") @ApiResponses(value = { @@ -125,6 +128,26 @@ public ResponseEntity changePerceivedDifficulty( return ResponseEntity.ok(problemsService.setPerceivedDifficulty(problemId, requestDto.perceivedDifficulty())); } + @Operation(summary = "문제 홀드색 수정", description = "특정 문제의 홀드색 수정") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "성공적으로 문제 정보 수정함", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ProblemDetailResponseDto.class))), + @ApiResponse(responseCode = "400", description = "유효하지 않은 요청 형식", + content = @Content(mediaType = "application/json", examples = { + @ExampleObject(name = "요청값 누락", value = "{\"perceivedDifficulty\": \"변경할 홀드 id는 필수입니다.\"}") + })), + @ApiResponse(responseCode = "404", description = "리소스를 찾을 수 없음", + content = @Content(mediaType = "application/json", examples = { + @ExampleObject(name = "문제 없음", value = "{\"error\": \"아이디가 0190c558-9063-7050-b4fc-eb421e3236b3인 문제를 찾을 수 없습니다.\"}") + })) + }) + @PatchMapping("/admin/problems/{problemId}/holds") + public ResponseEntity changeHold( + @PathVariable final UUID problemId, + @Valid @RequestBody final ProblemHoldRequestDto requestDto) { + return ResponseEntity.ok(problemsHoldService.updateHold(problemId, requestDto.holdId())); + } + @Operation(summary = "중복된 문제 조회", description = "sectorId, holdColorId, difficulty로 중복된 문제를 조회") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "성공적으로 중복된 문제 조회",