-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: 구역 생성 컨트롤러 * feat: 요청에 중복 이름, 별칭이 있는지 확인 * feat: custom exception 추가 * fix: alias null 체크 추가 * fix: 오타 수정 * test: 테스트 코드 추가
- Loading branch information
Showing
12 changed files
with
317 additions
and
3 deletions.
There are no files selected for viewing
19 changes: 18 additions & 1 deletion
19
application/src/main/java/org/depromeet/spot/application/common/dto/RgbCodeRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
...ication/src/main/java/org/depromeet/spot/application/section/CreateSectionController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package org.depromeet.spot.application.section; | ||
|
||
import java.util.List; | ||
|
||
import jakarta.validation.Valid; | ||
import jakarta.validation.constraints.NotEmpty; | ||
import jakarta.validation.constraints.NotNull; | ||
import jakarta.validation.constraints.Positive; | ||
|
||
import org.depromeet.spot.application.section.dto.request.CreateSectionRequest; | ||
import org.depromeet.spot.usecase.port.in.section.CreateSectionUsecase; | ||
import org.depromeet.spot.usecase.port.in.section.CreateSectionUsecase.CreateSectionCommand; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
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.ResponseStatus; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import io.swagger.v3.oas.annotations.Operation; | ||
import io.swagger.v3.oas.annotations.tags.Tag; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@RestController | ||
@Tag(name = "구역") | ||
@RequiredArgsConstructor | ||
@RequestMapping("/api/v1") | ||
public class CreateSectionController { | ||
|
||
private final CreateSectionUsecase createSectionUsecase; | ||
|
||
@ResponseStatus(HttpStatus.CREATED) | ||
@PostMapping("/stadiums/{stadiumId}/sections") | ||
@Operation(summary = "특정 경기장의 구역 정보들을 생성한다.") | ||
public void createAll( | ||
@PathVariable @Positive @NotNull final Long stadiumId, | ||
@RequestBody @Valid @NotEmpty List<CreateSectionRequest> requests) { | ||
List<CreateSectionCommand> commands = | ||
requests.stream().map(CreateSectionRequest::toCommand).toList(); | ||
createSectionUsecase.createAll(stadiumId, commands); | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
...rc/main/java/org/depromeet/spot/application/section/dto/request/CreateSectionRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package org.depromeet.spot.application.section.dto.request; | ||
|
||
import jakarta.validation.constraints.NotBlank; | ||
import jakarta.validation.constraints.NotNull; | ||
|
||
import org.depromeet.spot.application.common.dto.RgbCodeRequest; | ||
import org.depromeet.spot.usecase.port.in.section.CreateSectionUsecase.CreateSectionCommand; | ||
import org.hibernate.validator.constraints.Length; | ||
|
||
import io.swagger.v3.oas.annotations.Parameter; | ||
|
||
public record CreateSectionRequest( | ||
@NotBlank | ||
@Parameter(description = "구역 이름", example = "오렌지석") | ||
@Length(max = 20, message = "구역 이름은 최대 20글자 까지만 입력할 수 있습니다.") | ||
String name, | ||
@Parameter(description = "구역 별칭", example = "응원석") | ||
@Length(max = 20, message = "별칭은 최대 20글자 까지만 입력할 수 있습니다.") | ||
String alias, | ||
@NotNull RgbCodeRequest rgbCodeRequest) { | ||
|
||
public CreateSectionCommand toCommand() { | ||
return CreateSectionCommand.builder() | ||
.name(name) | ||
.alias(alias) | ||
.labelRgbCode(rgbCodeRequest.toDomain()) | ||
.build(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
...re/jpa/src/main/java/org/depromeet/spot/jpa/section/repository/SectionJdbcRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package org.depromeet.spot.jpa.section.repository; | ||
|
||
import java.sql.PreparedStatement; | ||
import java.sql.SQLException; | ||
import java.util.List; | ||
|
||
import org.depromeet.spot.domain.section.Section; | ||
import org.springframework.jdbc.core.BatchPreparedStatementSetter; | ||
import org.springframework.jdbc.core.JdbcTemplate; | ||
import org.springframework.stereotype.Repository; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
|
||
@Repository | ||
@RequiredArgsConstructor | ||
public class SectionJdbcRepository { | ||
|
||
private final JdbcTemplate jdbcTemplate; | ||
|
||
public void createSections(List<Section> sections) { | ||
jdbcTemplate.batchUpdate( | ||
"insert into sections" | ||
+ "(stadium_id, name, alias, red, green, blue) values (?, ?, ?, ?, ?, ?)", | ||
new BatchPreparedStatementSetter() { | ||
@Override | ||
public void setValues(PreparedStatement ps, int i) throws SQLException { | ||
ps.setLong(1, sections.get(i).getStadiumId()); | ||
ps.setString(2, sections.get(i).getName()); | ||
ps.setString(3, sections.get(i).getAlias()); | ||
ps.setInt(4, sections.get(i).getLabelRgbCode().getRed()); | ||
ps.setInt(5, sections.get(i).getLabelRgbCode().getGreen()); | ||
ps.setInt(6, sections.get(i).getLabelRgbCode().getBlue()); | ||
} | ||
|
||
@Override | ||
public int getBatchSize() { | ||
return sections.size(); | ||
} | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
usecase/src/main/java/org/depromeet/spot/usecase/port/in/section/CreateSectionUsecase.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package org.depromeet.spot.usecase.port.in.section; | ||
|
||
import java.util.List; | ||
|
||
import org.depromeet.spot.domain.common.RgbCode; | ||
import org.depromeet.spot.domain.section.Section; | ||
|
||
import lombok.Builder; | ||
|
||
public interface CreateSectionUsecase { | ||
|
||
void createAll(Long stadiumId, List<CreateSectionCommand> commands); | ||
|
||
@Builder | ||
record CreateSectionCommand(String name, String alias, RgbCode labelRgbCode) { | ||
|
||
public Section toDomain(final Long stadiumId) { | ||
return Section.builder() | ||
.stadiumId(stadiumId) | ||
.name(name) | ||
.alias(alias) | ||
.labelRgbCode(labelRgbCode) | ||
.build(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
65 changes: 65 additions & 0 deletions
65
usecase/src/main/java/org/depromeet/spot/usecase/service/section/CreateSectionService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package org.depromeet.spot.usecase.service.section; | ||
|
||
import java.util.ArrayList; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
import org.depromeet.spot.common.exception.section.SectionException.SectionAliasDuplicateException; | ||
import org.depromeet.spot.common.exception.section.SectionException.SectionNameDuplicateException; | ||
import org.depromeet.spot.domain.section.Section; | ||
import org.depromeet.spot.usecase.port.in.section.CreateSectionUsecase; | ||
import org.depromeet.spot.usecase.port.in.stadium.StadiumReadUsecase; | ||
import org.depromeet.spot.usecase.port.out.section.SectionRepository; | ||
import org.springframework.stereotype.Service; | ||
|
||
import lombok.Builder; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@Service | ||
@Builder | ||
@RequiredArgsConstructor | ||
public class CreateSectionService implements CreateSectionUsecase { | ||
|
||
private final SectionRepository sectionRepository; | ||
private final StadiumReadUsecase stadiumReadUsecase; | ||
|
||
@Override | ||
public void createAll(final Long stadiumId, List<CreateSectionCommand> commands) { | ||
validate(commands); | ||
stadiumReadUsecase.checkIsExistsBy(stadiumId); | ||
|
||
List<Section> sections = commands.stream().map(c -> c.toDomain(stadiumId)).toList(); | ||
sectionRepository.saveAll(sections); | ||
} | ||
|
||
private void validate(List<CreateSectionCommand> commands) { | ||
List<String> names = new ArrayList<>(); | ||
List<String> aliases = new ArrayList<>(); | ||
commands.forEach( | ||
command -> { | ||
names.add(command.name()); | ||
// alias는 nullable하기 때문에 체크 필요 -> name은 request에서 NN validation 완료 | ||
if (command.alias() != null) { | ||
aliases.add(command.alias()); | ||
} | ||
}); | ||
|
||
checkIsDuplicateName(names); | ||
checkIsDuplicateAlias(aliases); | ||
} | ||
|
||
public void checkIsDuplicateName(List<String> names) { | ||
Set<String> namesSet = new HashSet<>(names); | ||
if (namesSet.size() < names.size()) { | ||
throw new SectionNameDuplicateException(); | ||
} | ||
} | ||
|
||
public void checkIsDuplicateAlias(List<String> aliases) { | ||
Set<String> aliasSet = new HashSet<>(aliases); | ||
if (aliasSet.size() < aliases.size()) { | ||
throw new SectionAliasDuplicateException(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
...se/src/test/java/org/depromeet/spot/usecase/service/section/CreateSectionServiceTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package org.depromeet.spot.usecase.service.section; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
import org.depromeet.spot.common.exception.section.SectionException.SectionAliasDuplicateException; | ||
import org.depromeet.spot.common.exception.section.SectionException.SectionNameDuplicateException; | ||
import org.depromeet.spot.usecase.port.in.stadium.StadiumReadUsecase; | ||
import org.depromeet.spot.usecase.service.fake.FakeSectionRepository; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
|
||
class CreateSectionServiceTest { | ||
|
||
private CreateSectionService createSectionService; | ||
private StadiumReadUsecase stadiumReadUsecase; | ||
|
||
@BeforeEach | ||
void init() { | ||
FakeSectionRepository fakeSectionRepository = new FakeSectionRepository(); | ||
this.createSectionService = | ||
CreateSectionService.builder() | ||
.sectionRepository(fakeSectionRepository) | ||
.stadiumReadUsecase(stadiumReadUsecase) | ||
.build(); | ||
} | ||
|
||
@Test | ||
public void 요청에_이름과_별칭에_중복이_없다면_유효성_검증을_통과한다() { | ||
// given | ||
List<String> names = List.of("Section1", "Section2", "Section3"); | ||
List<String> aliases = Arrays.asList("Alias1", "Alias2", null); | ||
|
||
// when | ||
// then | ||
assertDoesNotThrow(() -> createSectionService.checkIsDuplicateName(names)); | ||
assertDoesNotThrow(() -> createSectionService.checkIsDuplicateAlias(aliases)); | ||
} | ||
|
||
@Test | ||
void 요청에_중복된_이름이_있다면_에러를_반환한다() { | ||
// given | ||
List<String> names = List.of("Section1", "Section1", "Section2"); | ||
|
||
// when | ||
// then | ||
assertThrows( | ||
SectionNameDuplicateException.class, | ||
() -> createSectionService.checkIsDuplicateName(names)); | ||
} | ||
|
||
@Test | ||
void 요청에_중복된_별칭이_있다면_에러를_반환한다() { | ||
// given | ||
List<String> aliases = Arrays.asList(null, "Alias1", "Alias1"); | ||
|
||
// when | ||
// then | ||
assertThrows( | ||
SectionAliasDuplicateException.class, | ||
() -> createSectionService.checkIsDuplicateAlias(aliases)); | ||
} | ||
} |