Skip to content

Commit

Permalink
feat: 홀드 테이블, 홀드 생성 및 조회 API 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
wonyangs committed Dec 3, 2024
1 parent cd38ba2 commit ca82cc7
Show file tree
Hide file tree
Showing 11 changed files with 259 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.first.flash.climbing.hold.application;

import com.first.flash.climbing.hold.application.dto.HoldCreateRequestDto;
import com.first.flash.climbing.hold.application.dto.HoldResponseDto;
import com.first.flash.climbing.hold.application.dto.HoldsResponseDto;
import com.first.flash.climbing.hold.domain.Hold;
import com.first.flash.climbing.hold.domain.HoldRepository;
import com.first.flash.climbing.hold.exception.exceptions.HoldNotFoundException;
import com.first.flash.climbing.sector.application.dto.SectorCreateRequestDto;
import com.first.flash.climbing.sector.application.dto.SectorDetailResponseDto;
import com.first.flash.climbing.sector.application.dto.SectorsDetailResponseDto;
import com.first.flash.climbing.sector.domain.Sector;
import com.first.flash.climbing.sector.domain.SectorInfo;
import com.first.flash.climbing.sector.exception.exceptions.SectorNotFoundException;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class HoldService {

private final HoldRepository holdRepository;

public Hold findById(final Long id) {
return holdRepository.findById(id)
.orElseThrow(() -> new HoldNotFoundException(id));
}

public HoldsResponseDto findAllHolds() {
List<HoldResponseDto> holdsResponse = holdRepository.findAll()
.stream()
.map(HoldResponseDto::toDto)
.toList();

return new HoldsResponseDto(holdsResponse);
}

@Transactional
public HoldResponseDto saveHold(final HoldCreateRequestDto createRequestDto) {
Hold hold = createHold(createRequestDto);
return HoldResponseDto.toDto(holdRepository.save(hold));
}

private Hold createHold(final HoldCreateRequestDto createRequestDto) {
return Hold.of(createRequestDto.colorName(), createRequestDto.colorCode());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.first.flash.climbing.hold.application.dto;

import jakarta.validation.constraints.NotNull;
import java.time.LocalDate;

public record HoldCreateRequestDto(
@NotNull(message = "홀드 색상 이름 정보는 비어있을 수 없습니다.") String colorName,
@NotNull(message = "홀드 색상 코드 정보는 비어있을 수 없습니다.") String colorCode) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.first.flash.climbing.hold.application.dto;

import com.first.flash.climbing.hold.domain.Hold;

public record HoldResponseDto(Long id, String colorName, String colorCode) {

public static HoldResponseDto toDto(final Hold hold) {
return new HoldResponseDto(hold.getId(), hold.getColorName(), hold.getColorCode());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.first.flash.climbing.hold.application.dto;

import java.util.List;

public record HoldsResponseDto(List<HoldResponseDto> holdList) {

}
31 changes: 31 additions & 0 deletions src/main/java/com/first/flash/climbing/hold/domain/Hold.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.first.flash.climbing.hold.domain;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Entity
@NoArgsConstructor
@Getter
@ToString
public class Hold {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String colorName;
private String colorCode;

protected Hold(final String colorName, final String colorCode) {
this.colorName = colorName;
this.colorCode = colorCode;
}

public static Hold of(final String colorName, final String colorCode) {
return new Hold(colorName, colorCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.first.flash.climbing.hold.domain;

import com.first.flash.climbing.sector.domain.Sector;
import java.util.List;
import java.util.Optional;

public interface HoldRepository {

Hold save(final Hold hold);

Optional<Hold> findById(final Long id);

List<Hold> findAll();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.first.flash.climbing.hold.exception;

import com.first.flash.climbing.hold.exception.exceptions.HoldNotFoundException;
import com.first.flash.global.dto.ErrorResponseDto;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class HoldExceptionHandler {

@ExceptionHandler(HoldNotFoundException.class)
public ResponseEntity<ErrorResponseDto> handleHoldNotFoundException(
final HoldNotFoundException exception) {
return getResponseWithStatus(HttpStatus.NOT_FOUND, exception);
}

private ResponseEntity<ErrorResponseDto> getResponseWithStatus(final HttpStatus httpStatus,
final RuntimeException exception) {
ErrorResponseDto errorResponse = new ErrorResponseDto(exception.getMessage());
return ResponseEntity.status(httpStatus)
.body(errorResponse);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.first.flash.climbing.hold.exception.exceptions;

import com.first.flash.climbing.sector.exception.exceptions.SectorNotFoundException;
import com.first.flash.global.dto.ErrorResponseDto;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

public class HoldNotFoundException extends RuntimeException {

public HoldNotFoundException(final Long id) {
super(String.format("아이디가 %s인 홀드를 찾을 수 없습니다.", id));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.first.flash.climbing.hold.infrastructure;

import com.first.flash.climbing.hold.domain.Hold;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;

public interface HoldJpaRepository extends JpaRepository<Hold, Long> {

Hold save(final Hold hold);

Optional<Hold> findById(final Long id);

List<Hold> findAll();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.first.flash.climbing.hold.infrastructure;

import com.first.flash.climbing.hold.domain.Hold;
import com.first.flash.climbing.hold.domain.HoldRepository;
import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

@Repository
@RequiredArgsConstructor
public class HoldRepositoryImpl implements HoldRepository {

private final HoldJpaRepository holdJpaRepository;

@Override
public Hold save(Hold hold) {
return holdJpaRepository.save(hold);
}

@Override
public Optional<Hold> findById(Long id) {
return holdJpaRepository.findById(id);
}

@Override
public List<Hold> findAll() {
return holdJpaRepository.findAll();
}
}
52 changes: 52 additions & 0 deletions src/main/java/com/first/flash/climbing/hold/ui/HoldController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.first.flash.climbing.hold.ui;

import com.first.flash.climbing.hold.application.HoldService;
import com.first.flash.climbing.hold.application.dto.HoldCreateRequestDto;
import com.first.flash.climbing.hold.application.dto.HoldResponseDto;
import com.first.flash.climbing.hold.application.dto.HoldsResponseDto;
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 lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Tag(name = "holds", description = "홀드 정보 관리 API")
@RestController
@RequestMapping
@RequiredArgsConstructor
public class HoldController {

private final HoldService holdService;

@Operation(summary = "모든 홀드 정보 조회", description = "모든 홀드 정보를 리스트로 반환")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "성공적으로 홀드를 조회",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = HoldsResponseDto.class))),
})
@GetMapping("holds")
public ResponseEntity<HoldsResponseDto> findAllHolds() {
return ResponseEntity.ok(holdService.findAllHolds());
}

@Operation(summary = "홀드 정보 생성", description = "홀드 정보를 생성")
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "홀드 정보를 생성",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = HoldResponseDto.class))),
})
@PostMapping("holds")
public ResponseEntity<HoldResponseDto> createHold(
@Valid @RequestBody final HoldCreateRequestDto createRequestDto) {
return ResponseEntity.status(HttpStatus.CREATED)
.body(holdService.saveHold(createRequestDto));
}
}

0 comments on commit ca82cc7

Please sign in to comment.