From 6c708a37695b0e3c56ed7553b9e9f203d394f2ac Mon Sep 17 00:00:00 2001 From: seojin Yoon <90759319+7zrv@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:10:37 +0900 Subject: [PATCH 01/15] =?UTF-8?q?feat:=20=EC=98=88=EC=99=B8=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=EC=83=81=EC=88=98=EB=A5=BC=20enum?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EA=B4=80=EB=A6=AC=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 예외 메시지를 ExceptionMessage enum으로 분리하여 중앙 관리 - 상수로 관리하여 메시지의 일관성 유지 및 중복 제거 - 향후 메시지 변경 시 한 곳에서 관리 가능하도록 개선 --- .../com/somemore/center/domain/Center.java | 66 +++++++++++++++++++ .../java/com/somemore/domains/Center.java | 42 ------------ .../global/exception/BadRequestException.java | 6 +- .../global/exception/ExceptionMessage.java | 15 +++++ 4 files changed, 82 insertions(+), 47 deletions(-) create mode 100644 src/main/java/com/somemore/center/domain/Center.java delete mode 100644 src/main/java/com/somemore/domains/Center.java create mode 100644 src/main/java/com/somemore/global/exception/ExceptionMessage.java diff --git a/src/main/java/com/somemore/center/domain/Center.java b/src/main/java/com/somemore/center/domain/Center.java new file mode 100644 index 000000000..6eb0d56cd --- /dev/null +++ b/src/main/java/com/somemore/center/domain/Center.java @@ -0,0 +1,66 @@ +package com.somemore.center.domain; + +import com.somemore.global.common.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.UUID; + + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Entity +public class Center extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + @Column(nullable = false, length = 16) + private UUID id; + + @Column(name = "name", nullable = false) + private String name; + + @Column(name = "contact_number", nullable = false) + private String contactNumber; + + @Column(name = "img_url", nullable = false) + private String imgUrl; + + @Column(name = "introduce", columnDefinition = "TEXT", nullable = false) + private String introduce; + + @Column(name = "homepage_link", nullable = false) + private String homepageLink; + + @Column(name = "account_id", nullable = false) + private String accountId; + + @Column(name = "account_pw", nullable = false) + private String accountPw; + + + @Builder + private Center(String name, String contactNumber, String imgUrl, String introduce, String homepageLink, String accountId, String accountPw) { + + this.name = name; + this.contactNumber = contactNumber; + this.imgUrl = imgUrl; + this.introduce = introduce; + this.homepageLink = homepageLink; + this.accountId = accountId; + this.accountPw = accountPw; + } + + public static Center create(String name, String contactNumber, String imgUrl, String introduce, String homepageLink, String accountId, String accountPw) { + return Center.builder() + .name(name) + .contactNumber(contactNumber) + .imgUrl(imgUrl) + .introduce(introduce) + .homepageLink(homepageLink) + .accountId(accountId) + .accountPw(accountPw) + .build(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/somemore/domains/Center.java b/src/main/java/com/somemore/domains/Center.java deleted file mode 100644 index 0fd91979d..000000000 --- a/src/main/java/com/somemore/domains/Center.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.somemore.domains; - -import jakarta.persistence.*; -import lombok.Getter; -import lombok.Setter; - -import java.util.UUID; - -@Getter -@Setter -@Entity -public class Center { - @Id - @GeneratedValue(strategy = GenerationType.UUID) - private UUID id; - - @Column(name = "name", nullable = false) - private String name; - - @Column(name = "contact_number", nullable = false) - private String contactNumber; - - @Column(name = "img_url", nullable = false) - private String imgUrl; - - @Lob - @Column(name = "introduce", nullable = false) - private String introduce; - - @Column(name = "requirement") - private String requirement; - - @Column(name = "homepage_link") - private String homepageLink; - - @Column(name = "account_id", nullable = false) - private String accountId; - - @Column(name = "account_pw", nullable = false) - private String accountPw; - -} \ No newline at end of file diff --git a/src/main/java/com/somemore/global/exception/BadRequestException.java b/src/main/java/com/somemore/global/exception/BadRequestException.java index 3066752fe..488546df3 100644 --- a/src/main/java/com/somemore/global/exception/BadRequestException.java +++ b/src/main/java/com/somemore/global/exception/BadRequestException.java @@ -4,11 +4,7 @@ public class BadRequestException extends RuntimeException{ - public BadRequestException() { - super(); - } - - public BadRequestException(String message) { + public BadRequestException(final String message) { super(message); } } diff --git a/src/main/java/com/somemore/global/exception/ExceptionMessage.java b/src/main/java/com/somemore/global/exception/ExceptionMessage.java new file mode 100644 index 000000000..615f84ac0 --- /dev/null +++ b/src/main/java/com/somemore/global/exception/ExceptionMessage.java @@ -0,0 +1,15 @@ +package com.somemore.global.exception; + + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public enum ExceptionMessage { + + NOT_EXISTS_CENTER("존재하지 않는 기관 ID 입니다.") + ; + + private final String message; +} From e708f74822e0102936ce70f952ff96806fbac9e4 Mon Sep 17 00:00:00 2001 From: seojin Yoon <90759319+7zrv@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:18:06 +0900 Subject: [PATCH 02/15] =?UTF-8?q?feat:=20=EC=84=A0=ED=98=B8=EB=AC=BC?= =?UTF-8?q?=ED=92=88=20=EB=93=B1=EB=A1=9D=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기관이 선호하는 물품을 등록할 수 있는 API 추가 - 선호물품 테이블 추가 - 선호물품 등록 요청 DTO 구현 - 선호물품 등록 서비스 레이어 구현 - 테스트 코드 작성 및 검증 완료 --- .../somemore/center/domain/PreferItem.java | 38 +++++++++++ .../request/PreferItemCreateRequestDto.java | 19 ++++++ .../repository/PreferItemRepository.java | 18 ++++++ .../command/CreatePreferItemService.java | 24 +++++++ .../command/CreatePreferItemUseCase.java | 8 +++ .../repository/PreferItemRepositoryTest.java | 42 ++++++++++++ .../command/CreatePreferItemServiceTest.java | 64 +++++++++++++++++++ 7 files changed, 213 insertions(+) create mode 100644 src/main/java/com/somemore/center/domain/PreferItem.java create mode 100644 src/main/java/com/somemore/center/dto/request/PreferItemCreateRequestDto.java create mode 100644 src/main/java/com/somemore/center/repository/PreferItemRepository.java create mode 100644 src/main/java/com/somemore/center/service/command/CreatePreferItemService.java create mode 100644 src/main/java/com/somemore/center/usecase/command/CreatePreferItemUseCase.java create mode 100644 src/test/java/com/somemore/center/repository/PreferItemRepositoryTest.java create mode 100644 src/test/java/com/somemore/center/service/command/CreatePreferItemServiceTest.java diff --git a/src/main/java/com/somemore/center/domain/PreferItem.java b/src/main/java/com/somemore/center/domain/PreferItem.java new file mode 100644 index 000000000..16ec8266d --- /dev/null +++ b/src/main/java/com/somemore/center/domain/PreferItem.java @@ -0,0 +1,38 @@ +package com.somemore.center.domain; + +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.UUID; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Entity +public class PreferItem { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "center_id", nullable = false) + private UUID centerId; + + @Column(name = "item_name", nullable = false) + private String itemName; + + @Builder + private PreferItem(UUID centerId, String itemName) { + this.centerId = centerId; + this.itemName = itemName; + } + + public static PreferItem create(UUID centerId, String itemName) { + return PreferItem.builder() + .centerId(centerId) + .itemName(itemName) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/somemore/center/dto/request/PreferItemCreateRequestDto.java b/src/main/java/com/somemore/center/dto/request/PreferItemCreateRequestDto.java new file mode 100644 index 000000000..bda87dae5 --- /dev/null +++ b/src/main/java/com/somemore/center/dto/request/PreferItemCreateRequestDto.java @@ -0,0 +1,19 @@ +package com.somemore.center.dto.request; + + +import com.somemore.center.domain.PreferItem; + +import java.util.UUID; + + +public record PreferItemCreateRequestDto( + + UUID centerId, + String itemName + +) { + public PreferItem createPreferItem() { + return PreferItem.create(centerId, itemName); + } + +} diff --git a/src/main/java/com/somemore/center/repository/PreferItemRepository.java b/src/main/java/com/somemore/center/repository/PreferItemRepository.java new file mode 100644 index 000000000..8603cd310 --- /dev/null +++ b/src/main/java/com/somemore/center/repository/PreferItemRepository.java @@ -0,0 +1,18 @@ +package com.somemore.center.repository; + +import com.somemore.center.domain.PreferItem; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.UUID; + +@Repository +public interface PreferItemRepository extends JpaRepository { + + @Query("SELECT p FROM PreferItem p WHERE p.centerId = :centerId") + List findByCenterId(@Param("centerId") UUID centerId); + +} \ No newline at end of file diff --git a/src/main/java/com/somemore/center/service/command/CreatePreferItemService.java b/src/main/java/com/somemore/center/service/command/CreatePreferItemService.java new file mode 100644 index 000000000..bee07f924 --- /dev/null +++ b/src/main/java/com/somemore/center/service/command/CreatePreferItemService.java @@ -0,0 +1,24 @@ +package com.somemore.center.service.command; + +import com.somemore.center.dto.request.PreferItemCreateRequestDto; +import com.somemore.center.repository.PreferItemRepository; +import com.somemore.center.usecase.command.CreatePreferItemUseCase; +import com.somemore.center.usecase.query.CenterQueryUseCase; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class CreatePreferItemService implements CreatePreferItemUseCase { + + private final CenterQueryUseCase centerQueryUseCase; + private final PreferItemRepository preferItemRepository; + + @Override + public void createPreferItem(PreferItemCreateRequestDto requestDto) { + + centerQueryUseCase.validateCenterExists(requestDto.centerId()); + + preferItemRepository.save(requestDto.createPreferItem()); + } +} diff --git a/src/main/java/com/somemore/center/usecase/command/CreatePreferItemUseCase.java b/src/main/java/com/somemore/center/usecase/command/CreatePreferItemUseCase.java new file mode 100644 index 000000000..78c793edc --- /dev/null +++ b/src/main/java/com/somemore/center/usecase/command/CreatePreferItemUseCase.java @@ -0,0 +1,8 @@ +package com.somemore.center.usecase.command; + +import com.somemore.center.dto.request.PreferItemCreateRequestDto; + +public interface CreatePreferItemUseCase { + + void createPreferItem(PreferItemCreateRequestDto requestDto); +} diff --git a/src/test/java/com/somemore/center/repository/PreferItemRepositoryTest.java b/src/test/java/com/somemore/center/repository/PreferItemRepositoryTest.java new file mode 100644 index 000000000..0a05b8a11 --- /dev/null +++ b/src/test/java/com/somemore/center/repository/PreferItemRepositoryTest.java @@ -0,0 +1,42 @@ +package com.somemore.center.repository; + +import com.somemore.IntegrationTestSupport; +import com.somemore.center.domain.PreferItem; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.tuple; + +class PreferItemRepositoryTest extends IntegrationTestSupport { + + @Autowired + private PreferItemRepository preferItemRepository; + + @DisplayName("기관의 id로 선호물품을 검색할 수 있다.") + @Test + void findByCenterId() { + + //given + PreferItem preferItem = PreferItem.create(UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a1"), "어린이 동화책"); + PreferItem preferItem1 = PreferItem.create(UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a1"), "간식"); + PreferItem preferItem2 = PreferItem.create(UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a2"), "수건"); + PreferItem preferItem3 = PreferItem.create(UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a3"), "식재료"); + preferItemRepository.saveAll(List.of(preferItem, preferItem1, preferItem2, preferItem3)); + + //when + List preferItems = preferItemRepository.findByCenterId(UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a2")); + + //then + assertThat(preferItems).hasSize(1) + .extracting("centerId", "itemName") + .containsExactlyInAnyOrder( + tuple(UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a2"), "수건") + ); + } + +} diff --git a/src/test/java/com/somemore/center/service/command/CreatePreferItemServiceTest.java b/src/test/java/com/somemore/center/service/command/CreatePreferItemServiceTest.java new file mode 100644 index 000000000..a7db8c925 --- /dev/null +++ b/src/test/java/com/somemore/center/service/command/CreatePreferItemServiceTest.java @@ -0,0 +1,64 @@ +package com.somemore.center.service.command; + +import com.somemore.IntegrationTestSupport; +import com.somemore.center.domain.Center; +import com.somemore.center.domain.PreferItem; +import com.somemore.center.dto.request.PreferItemCreateRequestDto; +import com.somemore.center.repository.CenterRepository; +import com.somemore.center.repository.PreferItemRepository; +import jakarta.transaction.Transactional; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import static org.assertj.core.api.Assertions.assertThat; + +@Transactional +class CreatePreferItemServiceTest extends IntegrationTestSupport { + + @Autowired + private CreatePreferItemService createPreferItemService; + + @Autowired + private PreferItemRepository preferItemRepository; + + @Autowired + private CenterRepository centerRepository; + + @DisplayName("기관 아이디와 선호물품 이름을 받아 선호물품을 생성한다.") + @Test + void createPreferItem() { + //given + Center center = Center.create( + "기본 기관 이름", + "010-1234-5678", + "http://example.com/image.jpg", + "기관 소개 내용", + "http://example.com", + "account123", + "password123" + ); + centerRepository.save(center); + String itemName = "어린이 도서"; + + + PreferItemCreateRequestDto requestDto = new PreferItemCreateRequestDto( + center.getId(), + itemName + ); + + //when + createPreferItemService.createPreferItem(requestDto); + + //then + PreferItem savedItem = preferItemRepository.findAll().stream() + .filter(item -> item.getCenterId().equals(center.getId()) + && item.getItemName().equals(itemName)) + .findFirst() + .orElseThrow(() -> new AssertionError("저장된 선호물품을 찾을 수 없습니다.")); + + assertThat(savedItem.getCenterId()).isEqualTo(center.getId()); + assertThat(savedItem.getItemName()).isEqualTo(itemName); + } + +} From 70066052f80cebd6e5703bb45531b12f73d9e08d Mon Sep 17 00:00:00 2001 From: seojin Yoon <90759319+7zrv@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:22:56 +0900 Subject: [PATCH 03/15] =?UTF-8?q?feat:=20=EA=B8=B0=EA=B4=80=20=EC=A1=B4?= =?UTF-8?q?=EC=9E=AC=20=EC=97=AC=EB=B6=80=20=EA=B2=80=EC=A6=9D=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기관 존재 여부를 확인하는 validateCenterExists 메서드 구현 - 존재하지 않는 센터에 대해 BadRequestException 처리 추가 - 테스트 코드 작성및 검증 완 --- .../center/repository/CenterRepository.java | 17 ++++ .../service/query/CenterQueryService.java | 27 ++++++ .../usecase/query/CenterQueryUseCase.java | 8 ++ .../repository/CenterRepositoryTest.java | 84 +++++++++++++++++++ .../service/query/CenterQueryServiceTest.java | 64 ++++++++++++++ 5 files changed, 200 insertions(+) create mode 100644 src/main/java/com/somemore/center/repository/CenterRepository.java create mode 100644 src/main/java/com/somemore/center/service/query/CenterQueryService.java create mode 100644 src/main/java/com/somemore/center/usecase/query/CenterQueryUseCase.java create mode 100644 src/test/java/com/somemore/center/repository/CenterRepositoryTest.java create mode 100644 src/test/java/com/somemore/center/service/query/CenterQueryServiceTest.java diff --git a/src/main/java/com/somemore/center/repository/CenterRepository.java b/src/main/java/com/somemore/center/repository/CenterRepository.java new file mode 100644 index 000000000..6f0aa035b --- /dev/null +++ b/src/main/java/com/somemore/center/repository/CenterRepository.java @@ -0,0 +1,17 @@ +package com.somemore.center.repository; + +import com.somemore.center.domain.Center; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.UUID; + +@Repository +public interface CenterRepository extends JpaRepository { + + boolean existsById(UUID id); + + default boolean doesNotExistById(UUID id) { + return !existsById(id); + } +} diff --git a/src/main/java/com/somemore/center/service/query/CenterQueryService.java b/src/main/java/com/somemore/center/service/query/CenterQueryService.java new file mode 100644 index 000000000..1fd0d4f4e --- /dev/null +++ b/src/main/java/com/somemore/center/service/query/CenterQueryService.java @@ -0,0 +1,27 @@ +package com.somemore.center.service.query; + +import com.somemore.center.repository.CenterRepository; +import com.somemore.center.usecase.query.CenterQueryUseCase; +import com.somemore.global.exception.BadRequestException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.UUID; + +import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_CENTER; + +@RequiredArgsConstructor +@Service +public class CenterQueryService implements CenterQueryUseCase { + + private final CenterRepository centerRepository; + + @Override + public void validateCenterExists(UUID id) { + + if (centerRepository.doesNotExistById(id)) { + throw new BadRequestException(NOT_EXISTS_CENTER.getMessage()); + } + } + +} diff --git a/src/main/java/com/somemore/center/usecase/query/CenterQueryUseCase.java b/src/main/java/com/somemore/center/usecase/query/CenterQueryUseCase.java new file mode 100644 index 000000000..12bab3812 --- /dev/null +++ b/src/main/java/com/somemore/center/usecase/query/CenterQueryUseCase.java @@ -0,0 +1,8 @@ +package com.somemore.center.usecase.query; + +import java.util.UUID; + +public interface CenterQueryUseCase { + + void validateCenterExists(UUID id); +} diff --git a/src/test/java/com/somemore/center/repository/CenterRepositoryTest.java b/src/test/java/com/somemore/center/repository/CenterRepositoryTest.java new file mode 100644 index 000000000..ed345d58c --- /dev/null +++ b/src/test/java/com/somemore/center/repository/CenterRepositoryTest.java @@ -0,0 +1,84 @@ +package com.somemore.center.repository; + +import com.somemore.IntegrationTestSupport; +import com.somemore.center.domain.Center; +import jakarta.transaction.Transactional; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.UUID; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +@Transactional +class CenterRepositoryTest extends IntegrationTestSupport { + + @Autowired + private CenterRepository centerRepository; + + @DisplayName("기관 id로 기관 프로필을 조회할 수 있다.") + @Test + void findById() { + //given + Center center = Center.create( + "기본 기관 이름", + "010-1234-5678", + "http://example.com/image.jpg", + "기관 소개 내용", + "http://example.com", + "account123", + "password123" + ); + centerRepository.save(center); + + //when + Center foundCenter = centerRepository.findById(center.getId()).orElse(null); + + //then + assertThat(foundCenter).isNotNull(); + assertThat(foundCenter.getName()).isEqualTo("기본 기관 이름"); + assertThat(foundCenter.getContactNumber()).isEqualTo("010-1234-5678"); + assertThat(foundCenter.getImgUrl()).isEqualTo("http://example.com/image.jpg"); + assertThat(foundCenter.getIntroduce()).isEqualTo("기관 소개 내용"); + assertThat(foundCenter.getHomepageLink()).isEqualTo("http://example.com"); + assertThat(foundCenter.getAccountId()).isEqualTo("account123"); + assertThat(foundCenter.getAccountPw()).isEqualTo("password123"); + } + + @DisplayName("기관 id로 기관이 존재하는지 확인할 수 있다.") + @Test + void existsById() { + //given + Center center = Center.create( + "기본 기관 이름", + "010-1234-5678", + "http://example.com/image.jpg", + "기관 소개 내용", + "http://example.com", + "account123", + "password123" + ); + centerRepository.save(center); + + //when + Boolean isExist = centerRepository.existsById(center.getId()); + + //then + assertThat(isExist).isTrue(); + } + + @DisplayName("존재하지 않는 기관 ID로 조회 시 false를 반환한다") + @Test + void notExistsById() { + //given + UUID nonExistentId = UUID.randomUUID(); + + //when + Boolean isExist = centerRepository.existsById(nonExistentId); + + //then + assertThat(isExist).isFalse(); + } + +} diff --git a/src/test/java/com/somemore/center/service/query/CenterQueryServiceTest.java b/src/test/java/com/somemore/center/service/query/CenterQueryServiceTest.java new file mode 100644 index 000000000..351e08f4f --- /dev/null +++ b/src/test/java/com/somemore/center/service/query/CenterQueryServiceTest.java @@ -0,0 +1,64 @@ +package com.somemore.center.service.query; + +import com.somemore.IntegrationTestSupport; +import com.somemore.center.domain.Center; +import com.somemore.center.repository.CenterRepository; +import com.somemore.global.exception.BadRequestException; +import com.somemore.global.exception.ExceptionMessage; +import org.assertj.core.api.ThrowableAssert; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +class CenterQueryServiceTest extends IntegrationTestSupport { + + @Autowired + private CenterQueryService centerQueryService; + + @Autowired + private CenterRepository centerRepository; + + @DisplayName("존재하지 않는 기관 ID로 조회 시 예외가 발생한다") + @Test + void validateNonExistentCenter() { + // given + UUID nonExistentId = UUID.randomUUID(); + + // when + ThrowableAssert.ThrowingCallable throwingCallable = () -> + centerQueryService.validateCenterExists(nonExistentId); + + // then + assertThatExceptionOfType(BadRequestException.class) + .isThrownBy(throwingCallable) + .withMessage(ExceptionMessage.NOT_EXISTS_CENTER.getMessage()); + } + + @DisplayName("존재하는 기관 ID로 조회 시 예외가 발생하지 않는다") + @Test + void validateExistingCenter() { + // given + Center center = Center.create( + "기본 기관 이름", + "010-1234-5678", + "http://example.com/image.jpg", + "기관 소개 내용", + "http://example.com", + "account123", + "password123" + ); + Center savedCenter = centerRepository.save(center); + + // when + ThrowableAssert.ThrowingCallable callable = () -> centerQueryService.validateCenterExists(savedCenter.getId()); + + // then + assertThatCode(callable).doesNotThrowAnyException(); + } + +} From c9dbfb61fe90af6d8852c8c35329cb50b33d9841 Mon Sep 17 00:00:00 2001 From: seojin Yoon <90759319+7zrv@users.noreply.github.com> Date: Sun, 24 Nov 2024 01:23:49 +0900 Subject: [PATCH 04/15] =?UTF-8?q?feat:=20=EA=B8=B0=EA=B4=80=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=95=84=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기관 id로 기관 정보와 기관이 등록한 선호 물품을 조회하는 메서드 구현 - 레포지토리에 기관 id를 통한 단건 조회 메서드 추가 - 기관과 선호물품을 함께 반환하기 위한 응답Dto 구현 - 테스트 코드 작성및 검증 완료 --- .../response/CenterProfileResponseDto.java | 34 +++++++++++ .../center/repository/CenterRepository.java | 3 + .../service/query/CenterQueryService.java | 24 +++++++- .../service/query/PreferItemQueryService.java | 22 +++++++ .../usecase/query/CenterQueryUseCase.java | 5 +- .../usecase/query/PreferItemQueryUseCase.java | 10 ++++ .../repository/CenterRepositoryTest.java | 19 +++--- .../service/query/CenterQueryServiceTest.java | 60 ++++++++++++++++++- 8 files changed, 164 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/somemore/center/dto/response/CenterProfileResponseDto.java create mode 100644 src/main/java/com/somemore/center/service/query/PreferItemQueryService.java create mode 100644 src/main/java/com/somemore/center/usecase/query/PreferItemQueryUseCase.java diff --git a/src/main/java/com/somemore/center/dto/response/CenterProfileResponseDto.java b/src/main/java/com/somemore/center/dto/response/CenterProfileResponseDto.java new file mode 100644 index 000000000..d3042ab81 --- /dev/null +++ b/src/main/java/com/somemore/center/dto/response/CenterProfileResponseDto.java @@ -0,0 +1,34 @@ +package com.somemore.center.dto.response; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.somemore.center.domain.Center; +import com.somemore.center.domain.PreferItem; +import lombok.Builder; + +import java.util.List; +import java.util.UUID; + +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +@Builder +public record CenterProfileResponseDto( + UUID centerId, + String name, + String contactNumber, + String imgUrl, + String introduce, + String homepageLink, + List preferItems +) { + public static CenterProfileResponseDto of(Center center, List preferItems) { + return CenterProfileResponseDto.builder() + .centerId(center.getId()) + .name(center.getName()) + .contactNumber(center.getContactNumber()) + .imgUrl(center.getImgUrl()) + .introduce(center.getIntroduce()) + .homepageLink(center.getHomepageLink()) + .preferItems(preferItems) + .build(); + } +} diff --git a/src/main/java/com/somemore/center/repository/CenterRepository.java b/src/main/java/com/somemore/center/repository/CenterRepository.java index 6f0aa035b..b72572f5a 100644 --- a/src/main/java/com/somemore/center/repository/CenterRepository.java +++ b/src/main/java/com/somemore/center/repository/CenterRepository.java @@ -4,6 +4,7 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; import java.util.UUID; @Repository @@ -14,4 +15,6 @@ public interface CenterRepository extends JpaRepository { default boolean doesNotExistById(UUID id) { return !existsById(id); } + + Optional
findCenterById(UUID id); } diff --git a/src/main/java/com/somemore/center/service/query/CenterQueryService.java b/src/main/java/com/somemore/center/service/query/CenterQueryService.java index 1fd0d4f4e..76f63f4f8 100644 --- a/src/main/java/com/somemore/center/service/query/CenterQueryService.java +++ b/src/main/java/com/somemore/center/service/query/CenterQueryService.java @@ -1,24 +1,44 @@ package com.somemore.center.service.query; - +import com.somemore.center.domain.Center; +import com.somemore.center.domain.PreferItem; +import com.somemore.center.dto.response.CenterProfileResponseDto; import com.somemore.center.repository.CenterRepository; import com.somemore.center.usecase.query.CenterQueryUseCase; +import com.somemore.center.usecase.query.PreferItemQueryUseCase; import com.somemore.global.exception.BadRequestException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import java.util.List; import java.util.UUID; import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_CENTER; @RequiredArgsConstructor +@Transactional(readOnly = true) @Service public class CenterQueryService implements CenterQueryUseCase { + private final PreferItemQueryUseCase preferItemQueryUseCase; private final CenterRepository centerRepository; @Override - public void validateCenterExists(UUID id) { + public CenterProfileResponseDto getCenterProfileByCenterId(UUID centerId) { + + Center center = getCenterById(centerId); + List preferItems = preferItemQueryUseCase.getPreferItemsByCenterId(centerId); + + return CenterProfileResponseDto.of(center, preferItems); + } + private Center getCenterById(UUID centerId) { + return centerRepository.findCenterById(centerId) + .orElseThrow(() -> new BadRequestException(NOT_EXISTS_CENTER.getMessage())); + } + + @Override + public void validateCenterExists(UUID id) { if (centerRepository.doesNotExistById(id)) { throw new BadRequestException(NOT_EXISTS_CENTER.getMessage()); } diff --git a/src/main/java/com/somemore/center/service/query/PreferItemQueryService.java b/src/main/java/com/somemore/center/service/query/PreferItemQueryService.java new file mode 100644 index 000000000..17e881f15 --- /dev/null +++ b/src/main/java/com/somemore/center/service/query/PreferItemQueryService.java @@ -0,0 +1,22 @@ +package com.somemore.center.service.query; + +import com.somemore.center.domain.PreferItem; +import com.somemore.center.repository.PreferItemRepository; +import com.somemore.center.usecase.query.PreferItemQueryUseCase; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.UUID; + +@RequiredArgsConstructor +@Service +public class PreferItemQueryService implements PreferItemQueryUseCase { + + private final PreferItemRepository preferItemRepository; + + @Override + public List getPreferItemsByCenterId(UUID centerId) { + return preferItemRepository.findByCenterId(centerId); + } +} diff --git a/src/main/java/com/somemore/center/usecase/query/CenterQueryUseCase.java b/src/main/java/com/somemore/center/usecase/query/CenterQueryUseCase.java index 12bab3812..7c12cb28c 100644 --- a/src/main/java/com/somemore/center/usecase/query/CenterQueryUseCase.java +++ b/src/main/java/com/somemore/center/usecase/query/CenterQueryUseCase.java @@ -1,8 +1,11 @@ package com.somemore.center.usecase.query; +import com.somemore.center.dto.response.CenterProfileResponseDto; + import java.util.UUID; public interface CenterQueryUseCase { - void validateCenterExists(UUID id); + CenterProfileResponseDto getCenterProfileByCenterId(UUID centerId); + void validateCenterExists(UUID centerId); } diff --git a/src/main/java/com/somemore/center/usecase/query/PreferItemQueryUseCase.java b/src/main/java/com/somemore/center/usecase/query/PreferItemQueryUseCase.java new file mode 100644 index 000000000..a93c675b0 --- /dev/null +++ b/src/main/java/com/somemore/center/usecase/query/PreferItemQueryUseCase.java @@ -0,0 +1,10 @@ +package com.somemore.center.usecase.query; + +import com.somemore.center.domain.PreferItem; + +import java.util.List; +import java.util.UUID; + +public interface PreferItemQueryUseCase { + List getPreferItemsByCenterId(UUID centerId); +} diff --git a/src/test/java/com/somemore/center/repository/CenterRepositoryTest.java b/src/test/java/com/somemore/center/repository/CenterRepositoryTest.java index ed345d58c..cb663d659 100644 --- a/src/test/java/com/somemore/center/repository/CenterRepositoryTest.java +++ b/src/test/java/com/somemore/center/repository/CenterRepositoryTest.java @@ -7,6 +7,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import java.util.Optional; import java.util.UUID; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -17,7 +18,7 @@ class CenterRepositoryTest extends IntegrationTestSupport { @Autowired private CenterRepository centerRepository; - @DisplayName("기관 id로 기관 프로필을 조회할 수 있다.") + @DisplayName("기관 id로 기관 정보를 조회할 수 있다. (Repository)") @Test void findById() { //given @@ -33,17 +34,17 @@ void findById() { centerRepository.save(center); //when - Center foundCenter = centerRepository.findById(center.getId()).orElse(null); + Optional
foundCenter = centerRepository.findCenterById(center.getId()); //then assertThat(foundCenter).isNotNull(); - assertThat(foundCenter.getName()).isEqualTo("기본 기관 이름"); - assertThat(foundCenter.getContactNumber()).isEqualTo("010-1234-5678"); - assertThat(foundCenter.getImgUrl()).isEqualTo("http://example.com/image.jpg"); - assertThat(foundCenter.getIntroduce()).isEqualTo("기관 소개 내용"); - assertThat(foundCenter.getHomepageLink()).isEqualTo("http://example.com"); - assertThat(foundCenter.getAccountId()).isEqualTo("account123"); - assertThat(foundCenter.getAccountPw()).isEqualTo("password123"); + assertThat(foundCenter.get().getName()).isEqualTo("기본 기관 이름"); + assertThat(foundCenter.get().getContactNumber()).isEqualTo("010-1234-5678"); + assertThat(foundCenter.get().getImgUrl()).isEqualTo("http://example.com/image.jpg"); + assertThat(foundCenter.get().getIntroduce()).isEqualTo("기관 소개 내용"); + assertThat(foundCenter.get().getHomepageLink()).isEqualTo("http://example.com"); + assertThat(foundCenter.get().getAccountId()).isEqualTo("account123"); + assertThat(foundCenter.get().getAccountPw()).isEqualTo("password123"); } @DisplayName("기관 id로 기관이 존재하는지 확인할 수 있다.") diff --git a/src/test/java/com/somemore/center/service/query/CenterQueryServiceTest.java b/src/test/java/com/somemore/center/service/query/CenterQueryServiceTest.java index 351e08f4f..457b0a175 100644 --- a/src/test/java/com/somemore/center/service/query/CenterQueryServiceTest.java +++ b/src/test/java/com/somemore/center/service/query/CenterQueryServiceTest.java @@ -2,19 +2,26 @@ import com.somemore.IntegrationTestSupport; import com.somemore.center.domain.Center; +import com.somemore.center.domain.PreferItem; +import com.somemore.center.dto.response.CenterProfileResponseDto; import com.somemore.center.repository.CenterRepository; +import com.somemore.center.repository.PreferItemRepository; import com.somemore.global.exception.BadRequestException; import com.somemore.global.exception.ExceptionMessage; +import jakarta.transaction.Transactional; import org.assertj.core.api.ThrowableAssert; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import java.util.List; import java.util.UUID; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +@Transactional class CenterQueryServiceTest extends IntegrationTestSupport { @Autowired @@ -22,8 +29,59 @@ class CenterQueryServiceTest extends IntegrationTestSupport { @Autowired private CenterRepository centerRepository; + + @Autowired + private PreferItemRepository preferItemRepository; + + @DisplayName("기관 Id로 기관 프로필을 조회할 수 있다. (service)") + @Test + void getCenterProfileById() { + // given + Center center = Center.create( + "기본 기관 이름", + "010-1234-5678", + "http://example.com/image.jpg", + "기관 소개 내용", + "http://example.com", + "account123", + "password123" + ); + Center foundCenter = centerRepository.save(center); + + PreferItem preferItem = PreferItem.create(foundCenter.getId(), "어린이 동화책"); + PreferItem preferItem1 = PreferItem.create(foundCenter.getId(), "간식"); + preferItemRepository.saveAll(List.of(preferItem, preferItem1)); + + // when + CenterProfileResponseDto responseDto = centerQueryService.getCenterProfileByCenterId(foundCenter.getId()); + + // then + assertThat(responseDto) + .extracting( + "centerId", + "name", + "contactNumber", + "imgUrl", + "introduce", + "homepageLink" + ) + .containsExactly( + foundCenter.getId(), + "기본 기관 이름", + "010-1234-5678", + "http://example.com/image.jpg", + "기관 소개 내용", + "http://example.com" + ); + + assertThat(responseDto.preferItems()) + .hasSize(2) + .extracting("itemName") + .containsExactly("어린이 동화책", "간식"); + } + - @DisplayName("존재하지 않는 기관 ID로 조회 시 예외가 발생한다") + @DisplayName("존재하지 않는 기관 ID를 검증할 수 있다.") @Test void validateNonExistentCenter() { // given From 32d7f188c037539ea311f0bd7bfd01e8782fc391 Mon Sep 17 00:00:00 2001 From: seojin Yoon <90759319+7zrv@users.noreply.github.com> Date: Sun, 24 Nov 2024 01:58:07 +0900 Subject: [PATCH 05/15] =?UTF-8?q?chore:=20sonar=20=EC=BB=A4=EB=B2=84?= =?UTF-8?q?=EB=A6=AC=EC=A7=80=20=EC=84=A4=EC=A0=95=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 누락된 exclude 설정을 추가 --- build.gradle | 3 +- .../somemore/center/domain/CenterTest.java | 46 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/somemore/center/domain/CenterTest.java diff --git a/build.gradle b/build.gradle index 23fc66b45..5e9aeb52d 100644 --- a/build.gradle +++ b/build.gradle @@ -57,7 +57,6 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.6.0' - //test testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' @@ -105,6 +104,7 @@ def jacocoExcludePatterns = [ '**/*Response*', '**/*Entity*', '**/*Dto*', + '**/*Dto.*', '**/*Jwt*', '**/auth/*', '**/domain/*', @@ -179,6 +179,7 @@ sonar { property 'sonar.language', 'java' property 'sonar.sourceEncoding', 'UTF-8' property 'sonar.test.exclusions', jacocoExcludePatterns.join(',') + property 'sonar.coverage.exclusions', jacocoExcludePatterns.join(',') property 'sonar.test.inclusions', '**/*Test.java' property 'sonar.java.coveragePlugin', 'jacoco' property 'sonar.coverage.jacoco.xmlReportPaths', jacocoDir.get().file("jacoco/index.xml").asFile diff --git a/src/test/java/com/somemore/center/domain/CenterTest.java b/src/test/java/com/somemore/center/domain/CenterTest.java new file mode 100644 index 000000000..bed4b8583 --- /dev/null +++ b/src/test/java/com/somemore/center/domain/CenterTest.java @@ -0,0 +1,46 @@ +package com.somemore.center.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +class CenterTest { + + private static final String NAME = "서울 도서관"; + private static final String CONTACT_NUMBER = "02-1234-5678"; + private static final String IMG_URL = "http://example.com/image.jpg"; + private static final String INTRODUCE = "우리는 서울 도서관입니다."; + private static final String HOMEPAGE_LINK = "http://testcenter.com"; + private static final String ACCOUNT_ID = "testId"; + private static final String ACCOUNT_PW = "testPw"; + + @DisplayName("Center 엔티티를 생성할 수 있다.") + @Test + void create() { + //when + Center center = Center.create( + NAME, + CONTACT_NUMBER, + IMG_URL, + INTRODUCE, + HOMEPAGE_LINK, + ACCOUNT_ID, + ACCOUNT_PW + ); + + //then + assertAll( + () -> assertThat(center.getName()).isEqualTo(NAME), + () -> assertThat(center.getContactNumber()).isEqualTo(CONTACT_NUMBER), + () -> assertThat(center.getImgUrl()).isEqualTo(IMG_URL), + () -> assertThat(center.getIntroduce()).isEqualTo(INTRODUCE), + () -> assertThat(center.getHomepageLink()).isEqualTo(HOMEPAGE_LINK), + () -> assertThat(center.getAccountId()).isEqualTo(ACCOUNT_ID), + () -> assertThat(center.getAccountPw()).isEqualTo(ACCOUNT_PW) + ); + } + + +} \ No newline at end of file From 20854da928f701c521986dc94cf5e3b944e2be10 Mon Sep 17 00:00:00 2001 From: seojin Yoon <90759319+7zrv@users.noreply.github.com> Date: Sun, 24 Nov 2024 12:15:13 +0900 Subject: [PATCH 06/15] =?UTF-8?q?chore:=20=ED=8C=8C=EC=9D=BC=20=EB=A7=88?= =?UTF-8?q?=EC=A7=80=EB=A7=89=20=EB=9D=BC=EC=9D=B8=EC=97=90=20=EA=B0=9C?= =?UTF-8?q?=ED=96=89=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 코딩 표준을 준수하기 위해 "no newline at end of file" 경고를 수정했습니다. --- src/main/java/com/somemore/center/domain/Center.java | 2 +- src/main/java/com/somemore/center/domain/PreferItem.java | 2 +- .../com/somemore/center/repository/PreferItemRepository.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/somemore/center/domain/Center.java b/src/main/java/com/somemore/center/domain/Center.java index 6eb0d56cd..a13f964f2 100644 --- a/src/main/java/com/somemore/center/domain/Center.java +++ b/src/main/java/com/somemore/center/domain/Center.java @@ -63,4 +63,4 @@ public static Center create(String name, String contactNumber, String imgUrl, St .build(); } -} \ No newline at end of file +} diff --git a/src/main/java/com/somemore/center/domain/PreferItem.java b/src/main/java/com/somemore/center/domain/PreferItem.java index 16ec8266d..9cc935974 100644 --- a/src/main/java/com/somemore/center/domain/PreferItem.java +++ b/src/main/java/com/somemore/center/domain/PreferItem.java @@ -35,4 +35,4 @@ public static PreferItem create(UUID centerId, String itemName) { .itemName(itemName) .build(); } -} \ No newline at end of file +} diff --git a/src/main/java/com/somemore/center/repository/PreferItemRepository.java b/src/main/java/com/somemore/center/repository/PreferItemRepository.java index 8603cd310..00e7c0df7 100644 --- a/src/main/java/com/somemore/center/repository/PreferItemRepository.java +++ b/src/main/java/com/somemore/center/repository/PreferItemRepository.java @@ -15,4 +15,4 @@ public interface PreferItemRepository extends JpaRepository { @Query("SELECT p FROM PreferItem p WHERE p.centerId = :centerId") List findByCenterId(@Param("centerId") UUID centerId); -} \ No newline at end of file +} From e8db6e037715f8510b4e46eaf0133dc66912e1f7 Mon Sep 17 00:00:00 2001 From: seojin Yoon <90759319+7zrv@users.noreply.github.com> Date: Sun, 24 Nov 2024 17:47:59 +0900 Subject: [PATCH 07/15] =?UTF-8?q?Fix:=20=EC=BD=94=EB=93=9C=20=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 서비스 레이어의 public 메서드를 상단에 배치하여 가독성 향상 - CQRS 적용을 위한 Query, Command 서비스 클래스에 @Transactinal(readOnly = true), @Transactinal 어노테이션을 각각 추가 - 레포지토리의 불필요한 @Query 어노테이션 삭제 --- .../center/repository/PreferItemRepository.java | 2 -- .../service/command/CreatePreferItemService.java | 3 +++ .../center/service/query/CenterQueryService.java | 10 +++++----- .../center/service/query/PreferItemQueryService.java | 2 ++ 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/somemore/center/repository/PreferItemRepository.java b/src/main/java/com/somemore/center/repository/PreferItemRepository.java index 00e7c0df7..9437e2941 100644 --- a/src/main/java/com/somemore/center/repository/PreferItemRepository.java +++ b/src/main/java/com/somemore/center/repository/PreferItemRepository.java @@ -2,7 +2,6 @@ import com.somemore.center.domain.PreferItem; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; @@ -12,7 +11,6 @@ @Repository public interface PreferItemRepository extends JpaRepository { - @Query("SELECT p FROM PreferItem p WHERE p.centerId = :centerId") List findByCenterId(@Param("centerId") UUID centerId); } diff --git a/src/main/java/com/somemore/center/service/command/CreatePreferItemService.java b/src/main/java/com/somemore/center/service/command/CreatePreferItemService.java index bee07f924..5a22f8679 100644 --- a/src/main/java/com/somemore/center/service/command/CreatePreferItemService.java +++ b/src/main/java/com/somemore/center/service/command/CreatePreferItemService.java @@ -6,8 +6,10 @@ import com.somemore.center.usecase.query.CenterQueryUseCase; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @RequiredArgsConstructor +@Transactional @Service public class CreatePreferItemService implements CreatePreferItemUseCase { @@ -21,4 +23,5 @@ public void createPreferItem(PreferItemCreateRequestDto requestDto) { preferItemRepository.save(requestDto.createPreferItem()); } + } diff --git a/src/main/java/com/somemore/center/service/query/CenterQueryService.java b/src/main/java/com/somemore/center/service/query/CenterQueryService.java index 76f63f4f8..975bbec26 100644 --- a/src/main/java/com/somemore/center/service/query/CenterQueryService.java +++ b/src/main/java/com/somemore/center/service/query/CenterQueryService.java @@ -32,11 +32,6 @@ public CenterProfileResponseDto getCenterProfileByCenterId(UUID centerId) { return CenterProfileResponseDto.of(center, preferItems); } - private Center getCenterById(UUID centerId) { - return centerRepository.findCenterById(centerId) - .orElseThrow(() -> new BadRequestException(NOT_EXISTS_CENTER.getMessage())); - } - @Override public void validateCenterExists(UUID id) { if (centerRepository.doesNotExistById(id)) { @@ -44,4 +39,9 @@ public void validateCenterExists(UUID id) { } } + private Center getCenterById(UUID centerId) { + return centerRepository.findCenterById(centerId) + .orElseThrow(() -> new BadRequestException(NOT_EXISTS_CENTER.getMessage())); + } + } diff --git a/src/main/java/com/somemore/center/service/query/PreferItemQueryService.java b/src/main/java/com/somemore/center/service/query/PreferItemQueryService.java index 17e881f15..6fe7dad1e 100644 --- a/src/main/java/com/somemore/center/service/query/PreferItemQueryService.java +++ b/src/main/java/com/somemore/center/service/query/PreferItemQueryService.java @@ -5,11 +5,13 @@ import com.somemore.center.usecase.query.PreferItemQueryUseCase; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.UUID; @RequiredArgsConstructor +@Transactional(readOnly = true) @Service public class PreferItemQueryService implements PreferItemQueryUseCase { From 6bf6af5bfc9e657724dde974897a8be0176a6dc2 Mon Sep 17 00:00:00 2001 From: seojin Yoon <90759319+7zrv@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:10:37 +0900 Subject: [PATCH 08/15] =?UTF-8?q?feat:=20=EC=98=88=EC=99=B8=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=EC=83=81=EC=88=98=EB=A5=BC=20enum?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EA=B4=80=EB=A6=AC=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 예외 메시지를 ExceptionMessage enum으로 분리하여 중앙 관리 - 상수로 관리하여 메시지의 일관성 유지 및 중복 제거 - 향후 메시지 변경 시 한 곳에서 관리 가능하도록 개선 --- .../com/somemore/center/domain/Center.java | 66 +++++++++++++++++++ .../java/com/somemore/domains/Center.java | 42 ------------ .../global/exception/BadRequestException.java | 6 +- .../global/exception/ExceptionMessage.java | 15 +++++ 4 files changed, 82 insertions(+), 47 deletions(-) create mode 100644 src/main/java/com/somemore/center/domain/Center.java delete mode 100644 src/main/java/com/somemore/domains/Center.java create mode 100644 src/main/java/com/somemore/global/exception/ExceptionMessage.java diff --git a/src/main/java/com/somemore/center/domain/Center.java b/src/main/java/com/somemore/center/domain/Center.java new file mode 100644 index 000000000..6eb0d56cd --- /dev/null +++ b/src/main/java/com/somemore/center/domain/Center.java @@ -0,0 +1,66 @@ +package com.somemore.center.domain; + +import com.somemore.global.common.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.UUID; + + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Entity +public class Center extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + @Column(nullable = false, length = 16) + private UUID id; + + @Column(name = "name", nullable = false) + private String name; + + @Column(name = "contact_number", nullable = false) + private String contactNumber; + + @Column(name = "img_url", nullable = false) + private String imgUrl; + + @Column(name = "introduce", columnDefinition = "TEXT", nullable = false) + private String introduce; + + @Column(name = "homepage_link", nullable = false) + private String homepageLink; + + @Column(name = "account_id", nullable = false) + private String accountId; + + @Column(name = "account_pw", nullable = false) + private String accountPw; + + + @Builder + private Center(String name, String contactNumber, String imgUrl, String introduce, String homepageLink, String accountId, String accountPw) { + + this.name = name; + this.contactNumber = contactNumber; + this.imgUrl = imgUrl; + this.introduce = introduce; + this.homepageLink = homepageLink; + this.accountId = accountId; + this.accountPw = accountPw; + } + + public static Center create(String name, String contactNumber, String imgUrl, String introduce, String homepageLink, String accountId, String accountPw) { + return Center.builder() + .name(name) + .contactNumber(contactNumber) + .imgUrl(imgUrl) + .introduce(introduce) + .homepageLink(homepageLink) + .accountId(accountId) + .accountPw(accountPw) + .build(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/somemore/domains/Center.java b/src/main/java/com/somemore/domains/Center.java deleted file mode 100644 index 0fd91979d..000000000 --- a/src/main/java/com/somemore/domains/Center.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.somemore.domains; - -import jakarta.persistence.*; -import lombok.Getter; -import lombok.Setter; - -import java.util.UUID; - -@Getter -@Setter -@Entity -public class Center { - @Id - @GeneratedValue(strategy = GenerationType.UUID) - private UUID id; - - @Column(name = "name", nullable = false) - private String name; - - @Column(name = "contact_number", nullable = false) - private String contactNumber; - - @Column(name = "img_url", nullable = false) - private String imgUrl; - - @Lob - @Column(name = "introduce", nullable = false) - private String introduce; - - @Column(name = "requirement") - private String requirement; - - @Column(name = "homepage_link") - private String homepageLink; - - @Column(name = "account_id", nullable = false) - private String accountId; - - @Column(name = "account_pw", nullable = false) - private String accountPw; - -} \ No newline at end of file diff --git a/src/main/java/com/somemore/global/exception/BadRequestException.java b/src/main/java/com/somemore/global/exception/BadRequestException.java index 3066752fe..488546df3 100644 --- a/src/main/java/com/somemore/global/exception/BadRequestException.java +++ b/src/main/java/com/somemore/global/exception/BadRequestException.java @@ -4,11 +4,7 @@ public class BadRequestException extends RuntimeException{ - public BadRequestException() { - super(); - } - - public BadRequestException(String message) { + public BadRequestException(final String message) { super(message); } } diff --git a/src/main/java/com/somemore/global/exception/ExceptionMessage.java b/src/main/java/com/somemore/global/exception/ExceptionMessage.java new file mode 100644 index 000000000..615f84ac0 --- /dev/null +++ b/src/main/java/com/somemore/global/exception/ExceptionMessage.java @@ -0,0 +1,15 @@ +package com.somemore.global.exception; + + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public enum ExceptionMessage { + + NOT_EXISTS_CENTER("존재하지 않는 기관 ID 입니다.") + ; + + private final String message; +} From e0327603c305a5f7ebee88fc5695e3844845c495 Mon Sep 17 00:00:00 2001 From: seojin Yoon <90759319+7zrv@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:18:06 +0900 Subject: [PATCH 09/15] =?UTF-8?q?feat:=20=EC=84=A0=ED=98=B8=EB=AC=BC?= =?UTF-8?q?=ED=92=88=20=EB=93=B1=EB=A1=9D=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기관이 선호하는 물품을 등록할 수 있는 API 추가 - 선호물품 테이블 추가 - 선호물품 등록 요청 DTO 구현 - 선호물품 등록 서비스 레이어 구현 - 테스트 코드 작성 및 검증 완료 --- .../somemore/center/domain/PreferItem.java | 38 +++++++++++ .../request/PreferItemCreateRequestDto.java | 19 ++++++ .../repository/PreferItemRepository.java | 18 ++++++ .../command/CreatePreferItemService.java | 24 +++++++ .../command/CreatePreferItemUseCase.java | 8 +++ .../repository/PreferItemRepositoryTest.java | 42 ++++++++++++ .../command/CreatePreferItemServiceTest.java | 64 +++++++++++++++++++ 7 files changed, 213 insertions(+) create mode 100644 src/main/java/com/somemore/center/domain/PreferItem.java create mode 100644 src/main/java/com/somemore/center/dto/request/PreferItemCreateRequestDto.java create mode 100644 src/main/java/com/somemore/center/repository/PreferItemRepository.java create mode 100644 src/main/java/com/somemore/center/service/command/CreatePreferItemService.java create mode 100644 src/main/java/com/somemore/center/usecase/command/CreatePreferItemUseCase.java create mode 100644 src/test/java/com/somemore/center/repository/PreferItemRepositoryTest.java create mode 100644 src/test/java/com/somemore/center/service/command/CreatePreferItemServiceTest.java diff --git a/src/main/java/com/somemore/center/domain/PreferItem.java b/src/main/java/com/somemore/center/domain/PreferItem.java new file mode 100644 index 000000000..16ec8266d --- /dev/null +++ b/src/main/java/com/somemore/center/domain/PreferItem.java @@ -0,0 +1,38 @@ +package com.somemore.center.domain; + +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.UUID; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Entity +public class PreferItem { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "center_id", nullable = false) + private UUID centerId; + + @Column(name = "item_name", nullable = false) + private String itemName; + + @Builder + private PreferItem(UUID centerId, String itemName) { + this.centerId = centerId; + this.itemName = itemName; + } + + public static PreferItem create(UUID centerId, String itemName) { + return PreferItem.builder() + .centerId(centerId) + .itemName(itemName) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/somemore/center/dto/request/PreferItemCreateRequestDto.java b/src/main/java/com/somemore/center/dto/request/PreferItemCreateRequestDto.java new file mode 100644 index 000000000..bda87dae5 --- /dev/null +++ b/src/main/java/com/somemore/center/dto/request/PreferItemCreateRequestDto.java @@ -0,0 +1,19 @@ +package com.somemore.center.dto.request; + + +import com.somemore.center.domain.PreferItem; + +import java.util.UUID; + + +public record PreferItemCreateRequestDto( + + UUID centerId, + String itemName + +) { + public PreferItem createPreferItem() { + return PreferItem.create(centerId, itemName); + } + +} diff --git a/src/main/java/com/somemore/center/repository/PreferItemRepository.java b/src/main/java/com/somemore/center/repository/PreferItemRepository.java new file mode 100644 index 000000000..8603cd310 --- /dev/null +++ b/src/main/java/com/somemore/center/repository/PreferItemRepository.java @@ -0,0 +1,18 @@ +package com.somemore.center.repository; + +import com.somemore.center.domain.PreferItem; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.UUID; + +@Repository +public interface PreferItemRepository extends JpaRepository { + + @Query("SELECT p FROM PreferItem p WHERE p.centerId = :centerId") + List findByCenterId(@Param("centerId") UUID centerId); + +} \ No newline at end of file diff --git a/src/main/java/com/somemore/center/service/command/CreatePreferItemService.java b/src/main/java/com/somemore/center/service/command/CreatePreferItemService.java new file mode 100644 index 000000000..bee07f924 --- /dev/null +++ b/src/main/java/com/somemore/center/service/command/CreatePreferItemService.java @@ -0,0 +1,24 @@ +package com.somemore.center.service.command; + +import com.somemore.center.dto.request.PreferItemCreateRequestDto; +import com.somemore.center.repository.PreferItemRepository; +import com.somemore.center.usecase.command.CreatePreferItemUseCase; +import com.somemore.center.usecase.query.CenterQueryUseCase; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class CreatePreferItemService implements CreatePreferItemUseCase { + + private final CenterQueryUseCase centerQueryUseCase; + private final PreferItemRepository preferItemRepository; + + @Override + public void createPreferItem(PreferItemCreateRequestDto requestDto) { + + centerQueryUseCase.validateCenterExists(requestDto.centerId()); + + preferItemRepository.save(requestDto.createPreferItem()); + } +} diff --git a/src/main/java/com/somemore/center/usecase/command/CreatePreferItemUseCase.java b/src/main/java/com/somemore/center/usecase/command/CreatePreferItemUseCase.java new file mode 100644 index 000000000..78c793edc --- /dev/null +++ b/src/main/java/com/somemore/center/usecase/command/CreatePreferItemUseCase.java @@ -0,0 +1,8 @@ +package com.somemore.center.usecase.command; + +import com.somemore.center.dto.request.PreferItemCreateRequestDto; + +public interface CreatePreferItemUseCase { + + void createPreferItem(PreferItemCreateRequestDto requestDto); +} diff --git a/src/test/java/com/somemore/center/repository/PreferItemRepositoryTest.java b/src/test/java/com/somemore/center/repository/PreferItemRepositoryTest.java new file mode 100644 index 000000000..0a05b8a11 --- /dev/null +++ b/src/test/java/com/somemore/center/repository/PreferItemRepositoryTest.java @@ -0,0 +1,42 @@ +package com.somemore.center.repository; + +import com.somemore.IntegrationTestSupport; +import com.somemore.center.domain.PreferItem; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.tuple; + +class PreferItemRepositoryTest extends IntegrationTestSupport { + + @Autowired + private PreferItemRepository preferItemRepository; + + @DisplayName("기관의 id로 선호물품을 검색할 수 있다.") + @Test + void findByCenterId() { + + //given + PreferItem preferItem = PreferItem.create(UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a1"), "어린이 동화책"); + PreferItem preferItem1 = PreferItem.create(UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a1"), "간식"); + PreferItem preferItem2 = PreferItem.create(UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a2"), "수건"); + PreferItem preferItem3 = PreferItem.create(UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a3"), "식재료"); + preferItemRepository.saveAll(List.of(preferItem, preferItem1, preferItem2, preferItem3)); + + //when + List preferItems = preferItemRepository.findByCenterId(UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a2")); + + //then + assertThat(preferItems).hasSize(1) + .extracting("centerId", "itemName") + .containsExactlyInAnyOrder( + tuple(UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a2"), "수건") + ); + } + +} diff --git a/src/test/java/com/somemore/center/service/command/CreatePreferItemServiceTest.java b/src/test/java/com/somemore/center/service/command/CreatePreferItemServiceTest.java new file mode 100644 index 000000000..a7db8c925 --- /dev/null +++ b/src/test/java/com/somemore/center/service/command/CreatePreferItemServiceTest.java @@ -0,0 +1,64 @@ +package com.somemore.center.service.command; + +import com.somemore.IntegrationTestSupport; +import com.somemore.center.domain.Center; +import com.somemore.center.domain.PreferItem; +import com.somemore.center.dto.request.PreferItemCreateRequestDto; +import com.somemore.center.repository.CenterRepository; +import com.somemore.center.repository.PreferItemRepository; +import jakarta.transaction.Transactional; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import static org.assertj.core.api.Assertions.assertThat; + +@Transactional +class CreatePreferItemServiceTest extends IntegrationTestSupport { + + @Autowired + private CreatePreferItemService createPreferItemService; + + @Autowired + private PreferItemRepository preferItemRepository; + + @Autowired + private CenterRepository centerRepository; + + @DisplayName("기관 아이디와 선호물품 이름을 받아 선호물품을 생성한다.") + @Test + void createPreferItem() { + //given + Center center = Center.create( + "기본 기관 이름", + "010-1234-5678", + "http://example.com/image.jpg", + "기관 소개 내용", + "http://example.com", + "account123", + "password123" + ); + centerRepository.save(center); + String itemName = "어린이 도서"; + + + PreferItemCreateRequestDto requestDto = new PreferItemCreateRequestDto( + center.getId(), + itemName + ); + + //when + createPreferItemService.createPreferItem(requestDto); + + //then + PreferItem savedItem = preferItemRepository.findAll().stream() + .filter(item -> item.getCenterId().equals(center.getId()) + && item.getItemName().equals(itemName)) + .findFirst() + .orElseThrow(() -> new AssertionError("저장된 선호물품을 찾을 수 없습니다.")); + + assertThat(savedItem.getCenterId()).isEqualTo(center.getId()); + assertThat(savedItem.getItemName()).isEqualTo(itemName); + } + +} From dbcea2d8672b6ab29889864ff497562afb3868d4 Mon Sep 17 00:00:00 2001 From: seojin Yoon <90759319+7zrv@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:22:56 +0900 Subject: [PATCH 10/15] =?UTF-8?q?feat:=20=EA=B8=B0=EA=B4=80=20=EC=A1=B4?= =?UTF-8?q?=EC=9E=AC=20=EC=97=AC=EB=B6=80=20=EA=B2=80=EC=A6=9D=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기관 존재 여부를 확인하는 validateCenterExists 메서드 구현 - 존재하지 않는 센터에 대해 BadRequestException 처리 추가 - 테스트 코드 작성및 검증 완 --- .../center/repository/CenterRepository.java | 17 ++++ .../service/query/CenterQueryService.java | 27 ++++++ .../usecase/query/CenterQueryUseCase.java | 8 ++ .../repository/CenterRepositoryTest.java | 84 +++++++++++++++++++ .../service/query/CenterQueryServiceTest.java | 64 ++++++++++++++ 5 files changed, 200 insertions(+) create mode 100644 src/main/java/com/somemore/center/repository/CenterRepository.java create mode 100644 src/main/java/com/somemore/center/service/query/CenterQueryService.java create mode 100644 src/main/java/com/somemore/center/usecase/query/CenterQueryUseCase.java create mode 100644 src/test/java/com/somemore/center/repository/CenterRepositoryTest.java create mode 100644 src/test/java/com/somemore/center/service/query/CenterQueryServiceTest.java diff --git a/src/main/java/com/somemore/center/repository/CenterRepository.java b/src/main/java/com/somemore/center/repository/CenterRepository.java new file mode 100644 index 000000000..6f0aa035b --- /dev/null +++ b/src/main/java/com/somemore/center/repository/CenterRepository.java @@ -0,0 +1,17 @@ +package com.somemore.center.repository; + +import com.somemore.center.domain.Center; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.UUID; + +@Repository +public interface CenterRepository extends JpaRepository { + + boolean existsById(UUID id); + + default boolean doesNotExistById(UUID id) { + return !existsById(id); + } +} diff --git a/src/main/java/com/somemore/center/service/query/CenterQueryService.java b/src/main/java/com/somemore/center/service/query/CenterQueryService.java new file mode 100644 index 000000000..1fd0d4f4e --- /dev/null +++ b/src/main/java/com/somemore/center/service/query/CenterQueryService.java @@ -0,0 +1,27 @@ +package com.somemore.center.service.query; + +import com.somemore.center.repository.CenterRepository; +import com.somemore.center.usecase.query.CenterQueryUseCase; +import com.somemore.global.exception.BadRequestException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.UUID; + +import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_CENTER; + +@RequiredArgsConstructor +@Service +public class CenterQueryService implements CenterQueryUseCase { + + private final CenterRepository centerRepository; + + @Override + public void validateCenterExists(UUID id) { + + if (centerRepository.doesNotExistById(id)) { + throw new BadRequestException(NOT_EXISTS_CENTER.getMessage()); + } + } + +} diff --git a/src/main/java/com/somemore/center/usecase/query/CenterQueryUseCase.java b/src/main/java/com/somemore/center/usecase/query/CenterQueryUseCase.java new file mode 100644 index 000000000..12bab3812 --- /dev/null +++ b/src/main/java/com/somemore/center/usecase/query/CenterQueryUseCase.java @@ -0,0 +1,8 @@ +package com.somemore.center.usecase.query; + +import java.util.UUID; + +public interface CenterQueryUseCase { + + void validateCenterExists(UUID id); +} diff --git a/src/test/java/com/somemore/center/repository/CenterRepositoryTest.java b/src/test/java/com/somemore/center/repository/CenterRepositoryTest.java new file mode 100644 index 000000000..ed345d58c --- /dev/null +++ b/src/test/java/com/somemore/center/repository/CenterRepositoryTest.java @@ -0,0 +1,84 @@ +package com.somemore.center.repository; + +import com.somemore.IntegrationTestSupport; +import com.somemore.center.domain.Center; +import jakarta.transaction.Transactional; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.UUID; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +@Transactional +class CenterRepositoryTest extends IntegrationTestSupport { + + @Autowired + private CenterRepository centerRepository; + + @DisplayName("기관 id로 기관 프로필을 조회할 수 있다.") + @Test + void findById() { + //given + Center center = Center.create( + "기본 기관 이름", + "010-1234-5678", + "http://example.com/image.jpg", + "기관 소개 내용", + "http://example.com", + "account123", + "password123" + ); + centerRepository.save(center); + + //when + Center foundCenter = centerRepository.findById(center.getId()).orElse(null); + + //then + assertThat(foundCenter).isNotNull(); + assertThat(foundCenter.getName()).isEqualTo("기본 기관 이름"); + assertThat(foundCenter.getContactNumber()).isEqualTo("010-1234-5678"); + assertThat(foundCenter.getImgUrl()).isEqualTo("http://example.com/image.jpg"); + assertThat(foundCenter.getIntroduce()).isEqualTo("기관 소개 내용"); + assertThat(foundCenter.getHomepageLink()).isEqualTo("http://example.com"); + assertThat(foundCenter.getAccountId()).isEqualTo("account123"); + assertThat(foundCenter.getAccountPw()).isEqualTo("password123"); + } + + @DisplayName("기관 id로 기관이 존재하는지 확인할 수 있다.") + @Test + void existsById() { + //given + Center center = Center.create( + "기본 기관 이름", + "010-1234-5678", + "http://example.com/image.jpg", + "기관 소개 내용", + "http://example.com", + "account123", + "password123" + ); + centerRepository.save(center); + + //when + Boolean isExist = centerRepository.existsById(center.getId()); + + //then + assertThat(isExist).isTrue(); + } + + @DisplayName("존재하지 않는 기관 ID로 조회 시 false를 반환한다") + @Test + void notExistsById() { + //given + UUID nonExistentId = UUID.randomUUID(); + + //when + Boolean isExist = centerRepository.existsById(nonExistentId); + + //then + assertThat(isExist).isFalse(); + } + +} diff --git a/src/test/java/com/somemore/center/service/query/CenterQueryServiceTest.java b/src/test/java/com/somemore/center/service/query/CenterQueryServiceTest.java new file mode 100644 index 000000000..351e08f4f --- /dev/null +++ b/src/test/java/com/somemore/center/service/query/CenterQueryServiceTest.java @@ -0,0 +1,64 @@ +package com.somemore.center.service.query; + +import com.somemore.IntegrationTestSupport; +import com.somemore.center.domain.Center; +import com.somemore.center.repository.CenterRepository; +import com.somemore.global.exception.BadRequestException; +import com.somemore.global.exception.ExceptionMessage; +import org.assertj.core.api.ThrowableAssert; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +class CenterQueryServiceTest extends IntegrationTestSupport { + + @Autowired + private CenterQueryService centerQueryService; + + @Autowired + private CenterRepository centerRepository; + + @DisplayName("존재하지 않는 기관 ID로 조회 시 예외가 발생한다") + @Test + void validateNonExistentCenter() { + // given + UUID nonExistentId = UUID.randomUUID(); + + // when + ThrowableAssert.ThrowingCallable throwingCallable = () -> + centerQueryService.validateCenterExists(nonExistentId); + + // then + assertThatExceptionOfType(BadRequestException.class) + .isThrownBy(throwingCallable) + .withMessage(ExceptionMessage.NOT_EXISTS_CENTER.getMessage()); + } + + @DisplayName("존재하는 기관 ID로 조회 시 예외가 발생하지 않는다") + @Test + void validateExistingCenter() { + // given + Center center = Center.create( + "기본 기관 이름", + "010-1234-5678", + "http://example.com/image.jpg", + "기관 소개 내용", + "http://example.com", + "account123", + "password123" + ); + Center savedCenter = centerRepository.save(center); + + // when + ThrowableAssert.ThrowingCallable callable = () -> centerQueryService.validateCenterExists(savedCenter.getId()); + + // then + assertThatCode(callable).doesNotThrowAnyException(); + } + +} From 84a0473b7123db5ca52bf35d58565220fc40c414 Mon Sep 17 00:00:00 2001 From: seojin Yoon <90759319+7zrv@users.noreply.github.com> Date: Sun, 24 Nov 2024 01:23:49 +0900 Subject: [PATCH 11/15] =?UTF-8?q?feat:=20=EA=B8=B0=EA=B4=80=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=95=84=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기관 id로 기관 정보와 기관이 등록한 선호 물품을 조회하는 메서드 구현 - 레포지토리에 기관 id를 통한 단건 조회 메서드 추가 - 기관과 선호물품을 함께 반환하기 위한 응답Dto 구현 - 테스트 코드 작성및 검증 완료 --- .../response/CenterProfileResponseDto.java | 34 +++++++++++ .../center/repository/CenterRepository.java | 3 + .../service/query/CenterQueryService.java | 24 +++++++- .../service/query/PreferItemQueryService.java | 22 +++++++ .../usecase/query/CenterQueryUseCase.java | 5 +- .../usecase/query/PreferItemQueryUseCase.java | 10 ++++ .../repository/CenterRepositoryTest.java | 19 +++--- .../service/query/CenterQueryServiceTest.java | 60 ++++++++++++++++++- 8 files changed, 164 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/somemore/center/dto/response/CenterProfileResponseDto.java create mode 100644 src/main/java/com/somemore/center/service/query/PreferItemQueryService.java create mode 100644 src/main/java/com/somemore/center/usecase/query/PreferItemQueryUseCase.java diff --git a/src/main/java/com/somemore/center/dto/response/CenterProfileResponseDto.java b/src/main/java/com/somemore/center/dto/response/CenterProfileResponseDto.java new file mode 100644 index 000000000..d3042ab81 --- /dev/null +++ b/src/main/java/com/somemore/center/dto/response/CenterProfileResponseDto.java @@ -0,0 +1,34 @@ +package com.somemore.center.dto.response; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.somemore.center.domain.Center; +import com.somemore.center.domain.PreferItem; +import lombok.Builder; + +import java.util.List; +import java.util.UUID; + +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +@Builder +public record CenterProfileResponseDto( + UUID centerId, + String name, + String contactNumber, + String imgUrl, + String introduce, + String homepageLink, + List preferItems +) { + public static CenterProfileResponseDto of(Center center, List preferItems) { + return CenterProfileResponseDto.builder() + .centerId(center.getId()) + .name(center.getName()) + .contactNumber(center.getContactNumber()) + .imgUrl(center.getImgUrl()) + .introduce(center.getIntroduce()) + .homepageLink(center.getHomepageLink()) + .preferItems(preferItems) + .build(); + } +} diff --git a/src/main/java/com/somemore/center/repository/CenterRepository.java b/src/main/java/com/somemore/center/repository/CenterRepository.java index 6f0aa035b..b72572f5a 100644 --- a/src/main/java/com/somemore/center/repository/CenterRepository.java +++ b/src/main/java/com/somemore/center/repository/CenterRepository.java @@ -4,6 +4,7 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; import java.util.UUID; @Repository @@ -14,4 +15,6 @@ public interface CenterRepository extends JpaRepository { default boolean doesNotExistById(UUID id) { return !existsById(id); } + + Optional
findCenterById(UUID id); } diff --git a/src/main/java/com/somemore/center/service/query/CenterQueryService.java b/src/main/java/com/somemore/center/service/query/CenterQueryService.java index 1fd0d4f4e..76f63f4f8 100644 --- a/src/main/java/com/somemore/center/service/query/CenterQueryService.java +++ b/src/main/java/com/somemore/center/service/query/CenterQueryService.java @@ -1,24 +1,44 @@ package com.somemore.center.service.query; - +import com.somemore.center.domain.Center; +import com.somemore.center.domain.PreferItem; +import com.somemore.center.dto.response.CenterProfileResponseDto; import com.somemore.center.repository.CenterRepository; import com.somemore.center.usecase.query.CenterQueryUseCase; +import com.somemore.center.usecase.query.PreferItemQueryUseCase; import com.somemore.global.exception.BadRequestException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import java.util.List; import java.util.UUID; import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_CENTER; @RequiredArgsConstructor +@Transactional(readOnly = true) @Service public class CenterQueryService implements CenterQueryUseCase { + private final PreferItemQueryUseCase preferItemQueryUseCase; private final CenterRepository centerRepository; @Override - public void validateCenterExists(UUID id) { + public CenterProfileResponseDto getCenterProfileByCenterId(UUID centerId) { + + Center center = getCenterById(centerId); + List preferItems = preferItemQueryUseCase.getPreferItemsByCenterId(centerId); + + return CenterProfileResponseDto.of(center, preferItems); + } + private Center getCenterById(UUID centerId) { + return centerRepository.findCenterById(centerId) + .orElseThrow(() -> new BadRequestException(NOT_EXISTS_CENTER.getMessage())); + } + + @Override + public void validateCenterExists(UUID id) { if (centerRepository.doesNotExistById(id)) { throw new BadRequestException(NOT_EXISTS_CENTER.getMessage()); } diff --git a/src/main/java/com/somemore/center/service/query/PreferItemQueryService.java b/src/main/java/com/somemore/center/service/query/PreferItemQueryService.java new file mode 100644 index 000000000..17e881f15 --- /dev/null +++ b/src/main/java/com/somemore/center/service/query/PreferItemQueryService.java @@ -0,0 +1,22 @@ +package com.somemore.center.service.query; + +import com.somemore.center.domain.PreferItem; +import com.somemore.center.repository.PreferItemRepository; +import com.somemore.center.usecase.query.PreferItemQueryUseCase; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.UUID; + +@RequiredArgsConstructor +@Service +public class PreferItemQueryService implements PreferItemQueryUseCase { + + private final PreferItemRepository preferItemRepository; + + @Override + public List getPreferItemsByCenterId(UUID centerId) { + return preferItemRepository.findByCenterId(centerId); + } +} diff --git a/src/main/java/com/somemore/center/usecase/query/CenterQueryUseCase.java b/src/main/java/com/somemore/center/usecase/query/CenterQueryUseCase.java index 12bab3812..7c12cb28c 100644 --- a/src/main/java/com/somemore/center/usecase/query/CenterQueryUseCase.java +++ b/src/main/java/com/somemore/center/usecase/query/CenterQueryUseCase.java @@ -1,8 +1,11 @@ package com.somemore.center.usecase.query; +import com.somemore.center.dto.response.CenterProfileResponseDto; + import java.util.UUID; public interface CenterQueryUseCase { - void validateCenterExists(UUID id); + CenterProfileResponseDto getCenterProfileByCenterId(UUID centerId); + void validateCenterExists(UUID centerId); } diff --git a/src/main/java/com/somemore/center/usecase/query/PreferItemQueryUseCase.java b/src/main/java/com/somemore/center/usecase/query/PreferItemQueryUseCase.java new file mode 100644 index 000000000..a93c675b0 --- /dev/null +++ b/src/main/java/com/somemore/center/usecase/query/PreferItemQueryUseCase.java @@ -0,0 +1,10 @@ +package com.somemore.center.usecase.query; + +import com.somemore.center.domain.PreferItem; + +import java.util.List; +import java.util.UUID; + +public interface PreferItemQueryUseCase { + List getPreferItemsByCenterId(UUID centerId); +} diff --git a/src/test/java/com/somemore/center/repository/CenterRepositoryTest.java b/src/test/java/com/somemore/center/repository/CenterRepositoryTest.java index ed345d58c..cb663d659 100644 --- a/src/test/java/com/somemore/center/repository/CenterRepositoryTest.java +++ b/src/test/java/com/somemore/center/repository/CenterRepositoryTest.java @@ -7,6 +7,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import java.util.Optional; import java.util.UUID; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -17,7 +18,7 @@ class CenterRepositoryTest extends IntegrationTestSupport { @Autowired private CenterRepository centerRepository; - @DisplayName("기관 id로 기관 프로필을 조회할 수 있다.") + @DisplayName("기관 id로 기관 정보를 조회할 수 있다. (Repository)") @Test void findById() { //given @@ -33,17 +34,17 @@ void findById() { centerRepository.save(center); //when - Center foundCenter = centerRepository.findById(center.getId()).orElse(null); + Optional
foundCenter = centerRepository.findCenterById(center.getId()); //then assertThat(foundCenter).isNotNull(); - assertThat(foundCenter.getName()).isEqualTo("기본 기관 이름"); - assertThat(foundCenter.getContactNumber()).isEqualTo("010-1234-5678"); - assertThat(foundCenter.getImgUrl()).isEqualTo("http://example.com/image.jpg"); - assertThat(foundCenter.getIntroduce()).isEqualTo("기관 소개 내용"); - assertThat(foundCenter.getHomepageLink()).isEqualTo("http://example.com"); - assertThat(foundCenter.getAccountId()).isEqualTo("account123"); - assertThat(foundCenter.getAccountPw()).isEqualTo("password123"); + assertThat(foundCenter.get().getName()).isEqualTo("기본 기관 이름"); + assertThat(foundCenter.get().getContactNumber()).isEqualTo("010-1234-5678"); + assertThat(foundCenter.get().getImgUrl()).isEqualTo("http://example.com/image.jpg"); + assertThat(foundCenter.get().getIntroduce()).isEqualTo("기관 소개 내용"); + assertThat(foundCenter.get().getHomepageLink()).isEqualTo("http://example.com"); + assertThat(foundCenter.get().getAccountId()).isEqualTo("account123"); + assertThat(foundCenter.get().getAccountPw()).isEqualTo("password123"); } @DisplayName("기관 id로 기관이 존재하는지 확인할 수 있다.") diff --git a/src/test/java/com/somemore/center/service/query/CenterQueryServiceTest.java b/src/test/java/com/somemore/center/service/query/CenterQueryServiceTest.java index 351e08f4f..457b0a175 100644 --- a/src/test/java/com/somemore/center/service/query/CenterQueryServiceTest.java +++ b/src/test/java/com/somemore/center/service/query/CenterQueryServiceTest.java @@ -2,19 +2,26 @@ import com.somemore.IntegrationTestSupport; import com.somemore.center.domain.Center; +import com.somemore.center.domain.PreferItem; +import com.somemore.center.dto.response.CenterProfileResponseDto; import com.somemore.center.repository.CenterRepository; +import com.somemore.center.repository.PreferItemRepository; import com.somemore.global.exception.BadRequestException; import com.somemore.global.exception.ExceptionMessage; +import jakarta.transaction.Transactional; import org.assertj.core.api.ThrowableAssert; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import java.util.List; import java.util.UUID; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +@Transactional class CenterQueryServiceTest extends IntegrationTestSupport { @Autowired @@ -22,8 +29,59 @@ class CenterQueryServiceTest extends IntegrationTestSupport { @Autowired private CenterRepository centerRepository; + + @Autowired + private PreferItemRepository preferItemRepository; + + @DisplayName("기관 Id로 기관 프로필을 조회할 수 있다. (service)") + @Test + void getCenterProfileById() { + // given + Center center = Center.create( + "기본 기관 이름", + "010-1234-5678", + "http://example.com/image.jpg", + "기관 소개 내용", + "http://example.com", + "account123", + "password123" + ); + Center foundCenter = centerRepository.save(center); + + PreferItem preferItem = PreferItem.create(foundCenter.getId(), "어린이 동화책"); + PreferItem preferItem1 = PreferItem.create(foundCenter.getId(), "간식"); + preferItemRepository.saveAll(List.of(preferItem, preferItem1)); + + // when + CenterProfileResponseDto responseDto = centerQueryService.getCenterProfileByCenterId(foundCenter.getId()); + + // then + assertThat(responseDto) + .extracting( + "centerId", + "name", + "contactNumber", + "imgUrl", + "introduce", + "homepageLink" + ) + .containsExactly( + foundCenter.getId(), + "기본 기관 이름", + "010-1234-5678", + "http://example.com/image.jpg", + "기관 소개 내용", + "http://example.com" + ); + + assertThat(responseDto.preferItems()) + .hasSize(2) + .extracting("itemName") + .containsExactly("어린이 동화책", "간식"); + } + - @DisplayName("존재하지 않는 기관 ID로 조회 시 예외가 발생한다") + @DisplayName("존재하지 않는 기관 ID를 검증할 수 있다.") @Test void validateNonExistentCenter() { // given From ccceed4f77cc0702beeb707efaf7889a2a1a2776 Mon Sep 17 00:00:00 2001 From: seojin Yoon <90759319+7zrv@users.noreply.github.com> Date: Sun, 24 Nov 2024 01:58:07 +0900 Subject: [PATCH 12/15] =?UTF-8?q?chore:=20sonar=20=EC=BB=A4=EB=B2=84?= =?UTF-8?q?=EB=A6=AC=EC=A7=80=20=EC=84=A4=EC=A0=95=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 누락된 exclude 설정을 추가 --- .../somemore/center/domain/CenterTest.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/test/java/com/somemore/center/domain/CenterTest.java diff --git a/src/test/java/com/somemore/center/domain/CenterTest.java b/src/test/java/com/somemore/center/domain/CenterTest.java new file mode 100644 index 000000000..bed4b8583 --- /dev/null +++ b/src/test/java/com/somemore/center/domain/CenterTest.java @@ -0,0 +1,46 @@ +package com.somemore.center.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +class CenterTest { + + private static final String NAME = "서울 도서관"; + private static final String CONTACT_NUMBER = "02-1234-5678"; + private static final String IMG_URL = "http://example.com/image.jpg"; + private static final String INTRODUCE = "우리는 서울 도서관입니다."; + private static final String HOMEPAGE_LINK = "http://testcenter.com"; + private static final String ACCOUNT_ID = "testId"; + private static final String ACCOUNT_PW = "testPw"; + + @DisplayName("Center 엔티티를 생성할 수 있다.") + @Test + void create() { + //when + Center center = Center.create( + NAME, + CONTACT_NUMBER, + IMG_URL, + INTRODUCE, + HOMEPAGE_LINK, + ACCOUNT_ID, + ACCOUNT_PW + ); + + //then + assertAll( + () -> assertThat(center.getName()).isEqualTo(NAME), + () -> assertThat(center.getContactNumber()).isEqualTo(CONTACT_NUMBER), + () -> assertThat(center.getImgUrl()).isEqualTo(IMG_URL), + () -> assertThat(center.getIntroduce()).isEqualTo(INTRODUCE), + () -> assertThat(center.getHomepageLink()).isEqualTo(HOMEPAGE_LINK), + () -> assertThat(center.getAccountId()).isEqualTo(ACCOUNT_ID), + () -> assertThat(center.getAccountPw()).isEqualTo(ACCOUNT_PW) + ); + } + + +} \ No newline at end of file From ddaa78dbd30715b1d3c2809b47ec44fe976f127d Mon Sep 17 00:00:00 2001 From: seojin Yoon <90759319+7zrv@users.noreply.github.com> Date: Sun, 24 Nov 2024 12:15:13 +0900 Subject: [PATCH 13/15] =?UTF-8?q?chore:=20=ED=8C=8C=EC=9D=BC=20=EB=A7=88?= =?UTF-8?q?=EC=A7=80=EB=A7=89=20=EB=9D=BC=EC=9D=B8=EC=97=90=20=EA=B0=9C?= =?UTF-8?q?=ED=96=89=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 코딩 표준을 준수하기 위해 "no newline at end of file" 경고를 수정했습니다. --- src/main/java/com/somemore/center/domain/Center.java | 2 +- src/main/java/com/somemore/center/domain/PreferItem.java | 2 +- .../com/somemore/center/repository/PreferItemRepository.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/somemore/center/domain/Center.java b/src/main/java/com/somemore/center/domain/Center.java index 6eb0d56cd..a13f964f2 100644 --- a/src/main/java/com/somemore/center/domain/Center.java +++ b/src/main/java/com/somemore/center/domain/Center.java @@ -63,4 +63,4 @@ public static Center create(String name, String contactNumber, String imgUrl, St .build(); } -} \ No newline at end of file +} diff --git a/src/main/java/com/somemore/center/domain/PreferItem.java b/src/main/java/com/somemore/center/domain/PreferItem.java index 16ec8266d..9cc935974 100644 --- a/src/main/java/com/somemore/center/domain/PreferItem.java +++ b/src/main/java/com/somemore/center/domain/PreferItem.java @@ -35,4 +35,4 @@ public static PreferItem create(UUID centerId, String itemName) { .itemName(itemName) .build(); } -} \ No newline at end of file +} diff --git a/src/main/java/com/somemore/center/repository/PreferItemRepository.java b/src/main/java/com/somemore/center/repository/PreferItemRepository.java index 8603cd310..00e7c0df7 100644 --- a/src/main/java/com/somemore/center/repository/PreferItemRepository.java +++ b/src/main/java/com/somemore/center/repository/PreferItemRepository.java @@ -15,4 +15,4 @@ public interface PreferItemRepository extends JpaRepository { @Query("SELECT p FROM PreferItem p WHERE p.centerId = :centerId") List findByCenterId(@Param("centerId") UUID centerId); -} \ No newline at end of file +} From 00030896492e84858b056d559efb279f9527d106 Mon Sep 17 00:00:00 2001 From: seojin Yoon <90759319+7zrv@users.noreply.github.com> Date: Sun, 24 Nov 2024 17:47:59 +0900 Subject: [PATCH 14/15] =?UTF-8?q?Fix:=20=EC=BD=94=EB=93=9C=20=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 서비스 레이어의 public 메서드를 상단에 배치하여 가독성 향상 - CQRS 적용을 위한 Query, Command 서비스 클래스에 @Transactinal(readOnly = true), @Transactinal 어노테이션을 각각 추가 - 레포지토리의 불필요한 @Query 어노테이션 삭제 --- .../center/repository/PreferItemRepository.java | 2 -- .../service/command/CreatePreferItemService.java | 3 +++ .../center/service/query/CenterQueryService.java | 10 +++++----- .../center/service/query/PreferItemQueryService.java | 2 ++ 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/somemore/center/repository/PreferItemRepository.java b/src/main/java/com/somemore/center/repository/PreferItemRepository.java index 00e7c0df7..9437e2941 100644 --- a/src/main/java/com/somemore/center/repository/PreferItemRepository.java +++ b/src/main/java/com/somemore/center/repository/PreferItemRepository.java @@ -2,7 +2,6 @@ import com.somemore.center.domain.PreferItem; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; @@ -12,7 +11,6 @@ @Repository public interface PreferItemRepository extends JpaRepository { - @Query("SELECT p FROM PreferItem p WHERE p.centerId = :centerId") List findByCenterId(@Param("centerId") UUID centerId); } diff --git a/src/main/java/com/somemore/center/service/command/CreatePreferItemService.java b/src/main/java/com/somemore/center/service/command/CreatePreferItemService.java index bee07f924..5a22f8679 100644 --- a/src/main/java/com/somemore/center/service/command/CreatePreferItemService.java +++ b/src/main/java/com/somemore/center/service/command/CreatePreferItemService.java @@ -6,8 +6,10 @@ import com.somemore.center.usecase.query.CenterQueryUseCase; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @RequiredArgsConstructor +@Transactional @Service public class CreatePreferItemService implements CreatePreferItemUseCase { @@ -21,4 +23,5 @@ public void createPreferItem(PreferItemCreateRequestDto requestDto) { preferItemRepository.save(requestDto.createPreferItem()); } + } diff --git a/src/main/java/com/somemore/center/service/query/CenterQueryService.java b/src/main/java/com/somemore/center/service/query/CenterQueryService.java index 76f63f4f8..975bbec26 100644 --- a/src/main/java/com/somemore/center/service/query/CenterQueryService.java +++ b/src/main/java/com/somemore/center/service/query/CenterQueryService.java @@ -32,11 +32,6 @@ public CenterProfileResponseDto getCenterProfileByCenterId(UUID centerId) { return CenterProfileResponseDto.of(center, preferItems); } - private Center getCenterById(UUID centerId) { - return centerRepository.findCenterById(centerId) - .orElseThrow(() -> new BadRequestException(NOT_EXISTS_CENTER.getMessage())); - } - @Override public void validateCenterExists(UUID id) { if (centerRepository.doesNotExistById(id)) { @@ -44,4 +39,9 @@ public void validateCenterExists(UUID id) { } } + private Center getCenterById(UUID centerId) { + return centerRepository.findCenterById(centerId) + .orElseThrow(() -> new BadRequestException(NOT_EXISTS_CENTER.getMessage())); + } + } diff --git a/src/main/java/com/somemore/center/service/query/PreferItemQueryService.java b/src/main/java/com/somemore/center/service/query/PreferItemQueryService.java index 17e881f15..6fe7dad1e 100644 --- a/src/main/java/com/somemore/center/service/query/PreferItemQueryService.java +++ b/src/main/java/com/somemore/center/service/query/PreferItemQueryService.java @@ -5,11 +5,13 @@ import com.somemore.center.usecase.query.PreferItemQueryUseCase; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.UUID; @RequiredArgsConstructor +@Transactional(readOnly = true) @Service public class PreferItemQueryService implements PreferItemQueryUseCase { From 038d45344629e02a91bea7bea4d03aab8e9f35b1 Mon Sep 17 00:00:00 2001 From: seojin Yoon <90759319+7zrv@users.noreply.github.com> Date: Mon, 25 Nov 2024 11:19:54 +0900 Subject: [PATCH 15/15] =?UTF-8?q?Refactor:=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기관 프로필 조회 응답값중 선호 물품 엔티티를 직접 응답하는것이 아닌 Dto로 전환하여 응답하도록 수정과 그에 따른 usecase, service 수정, 선호물품 응답 Dto 생성 - 단위 테스트 코드 작성과 검증 완료 --- .../response/CenterProfileResponseDto.java | 6 +- .../dto/response/PreferItemResponseDto.java | 21 ++++++ .../repository/PreferItemRepository.java | 3 +- .../service/query/CenterQueryService.java | 7 +- .../service/query/PreferItemQueryService.java | 14 ++++ .../usecase/query/PreferItemQueryUseCase.java | 2 + .../repository/PreferItemRepositoryTest.java | 14 +++- .../query/PreferItemQueryServiceTest.java | 75 +++++++++++++++++++ src/test/resources/application-test.yml | 4 +- 9 files changed, 133 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/somemore/center/dto/response/PreferItemResponseDto.java create mode 100644 src/test/java/com/somemore/center/service/query/PreferItemQueryServiceTest.java diff --git a/src/main/java/com/somemore/center/dto/response/CenterProfileResponseDto.java b/src/main/java/com/somemore/center/dto/response/CenterProfileResponseDto.java index d3042ab81..7ccf73d63 100644 --- a/src/main/java/com/somemore/center/dto/response/CenterProfileResponseDto.java +++ b/src/main/java/com/somemore/center/dto/response/CenterProfileResponseDto.java @@ -18,9 +18,9 @@ public record CenterProfileResponseDto( String imgUrl, String introduce, String homepageLink, - List preferItems + List preferItems ) { - public static CenterProfileResponseDto of(Center center, List preferItems) { + public static CenterProfileResponseDto of(Center center, List preferItemDtos) { return CenterProfileResponseDto.builder() .centerId(center.getId()) .name(center.getName()) @@ -28,7 +28,7 @@ public static CenterProfileResponseDto of(Center center, List prefer .imgUrl(center.getImgUrl()) .introduce(center.getIntroduce()) .homepageLink(center.getHomepageLink()) - .preferItems(preferItems) + .preferItems(preferItemDtos) .build(); } } diff --git a/src/main/java/com/somemore/center/dto/response/PreferItemResponseDto.java b/src/main/java/com/somemore/center/dto/response/PreferItemResponseDto.java new file mode 100644 index 000000000..85fa74744 --- /dev/null +++ b/src/main/java/com/somemore/center/dto/response/PreferItemResponseDto.java @@ -0,0 +1,21 @@ +package com.somemore.center.dto.response; + +import com.somemore.center.domain.PreferItem; +import lombok.Builder; + +import java.util.UUID; + +@Builder +public record PreferItemResponseDto ( + Long id, + UUID centerId, + String itemName +){ + public static PreferItemResponseDto from(PreferItem preferItem) { + return PreferItemResponseDto.builder() + .id(preferItem.getId()) + .centerId(preferItem.getCenterId()) + .itemName(preferItem.getItemName()) + .build(); + } +} diff --git a/src/main/java/com/somemore/center/repository/PreferItemRepository.java b/src/main/java/com/somemore/center/repository/PreferItemRepository.java index 9437e2941..8f3f4eecb 100644 --- a/src/main/java/com/somemore/center/repository/PreferItemRepository.java +++ b/src/main/java/com/somemore/center/repository/PreferItemRepository.java @@ -2,7 +2,6 @@ import com.somemore.center.domain.PreferItem; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import java.util.List; @@ -11,6 +10,6 @@ @Repository public interface PreferItemRepository extends JpaRepository { - List findByCenterId(@Param("centerId") UUID centerId); + List findByCenterId(UUID centerId); } diff --git a/src/main/java/com/somemore/center/service/query/CenterQueryService.java b/src/main/java/com/somemore/center/service/query/CenterQueryService.java index 975bbec26..838eba6ea 100644 --- a/src/main/java/com/somemore/center/service/query/CenterQueryService.java +++ b/src/main/java/com/somemore/center/service/query/CenterQueryService.java @@ -1,7 +1,8 @@ package com.somemore.center.service.query; + import com.somemore.center.domain.Center; -import com.somemore.center.domain.PreferItem; import com.somemore.center.dto.response.CenterProfileResponseDto; +import com.somemore.center.dto.response.PreferItemResponseDto; import com.somemore.center.repository.CenterRepository; import com.somemore.center.usecase.query.CenterQueryUseCase; import com.somemore.center.usecase.query.PreferItemQueryUseCase; @@ -27,9 +28,9 @@ public class CenterQueryService implements CenterQueryUseCase { public CenterProfileResponseDto getCenterProfileByCenterId(UUID centerId) { Center center = getCenterById(centerId); - List preferItems = preferItemQueryUseCase.getPreferItemsByCenterId(centerId); + List preferItemDtos = preferItemQueryUseCase.getPreferItemDtosByCenterId(centerId); - return CenterProfileResponseDto.of(center, preferItems); + return CenterProfileResponseDto.of(center, preferItemDtos); } @Override diff --git a/src/main/java/com/somemore/center/service/query/PreferItemQueryService.java b/src/main/java/com/somemore/center/service/query/PreferItemQueryService.java index 6fe7dad1e..46074e0a5 100644 --- a/src/main/java/com/somemore/center/service/query/PreferItemQueryService.java +++ b/src/main/java/com/somemore/center/service/query/PreferItemQueryService.java @@ -1,6 +1,7 @@ package com.somemore.center.service.query; import com.somemore.center.domain.PreferItem; +import com.somemore.center.dto.response.PreferItemResponseDto; import com.somemore.center.repository.PreferItemRepository; import com.somemore.center.usecase.query.PreferItemQueryUseCase; import lombok.RequiredArgsConstructor; @@ -17,8 +18,21 @@ public class PreferItemQueryService implements PreferItemQueryUseCase { private final PreferItemRepository preferItemRepository; + @Override + public List getPreferItemDtosByCenterId(UUID centerId) { + List preferItems = getPreferItemsByCenterId(centerId); + return preferItemConvertToDtos(preferItems); + } + + //프론트와 의논후 private으로 전환 예정 @Override public List getPreferItemsByCenterId(UUID centerId) { return preferItemRepository.findByCenterId(centerId); } + + private static List preferItemConvertToDtos(List preferItems) { + return preferItems.stream() + .map(PreferItemResponseDto::from) + .toList(); + } } diff --git a/src/main/java/com/somemore/center/usecase/query/PreferItemQueryUseCase.java b/src/main/java/com/somemore/center/usecase/query/PreferItemQueryUseCase.java index a93c675b0..46230cfc9 100644 --- a/src/main/java/com/somemore/center/usecase/query/PreferItemQueryUseCase.java +++ b/src/main/java/com/somemore/center/usecase/query/PreferItemQueryUseCase.java @@ -1,10 +1,12 @@ package com.somemore.center.usecase.query; import com.somemore.center.domain.PreferItem; +import com.somemore.center.dto.response.PreferItemResponseDto; import java.util.List; import java.util.UUID; public interface PreferItemQueryUseCase { + List getPreferItemDtosByCenterId(UUID centerId); List getPreferItemsByCenterId(UUID centerId); } diff --git a/src/test/java/com/somemore/center/repository/PreferItemRepositoryTest.java b/src/test/java/com/somemore/center/repository/PreferItemRepositoryTest.java index 0a05b8a11..cf7fcc9d5 100644 --- a/src/test/java/com/somemore/center/repository/PreferItemRepositoryTest.java +++ b/src/test/java/com/somemore/center/repository/PreferItemRepositoryTest.java @@ -17,15 +17,21 @@ class PreferItemRepositoryTest extends IntegrationTestSupport { @Autowired private PreferItemRepository preferItemRepository; + + private UUID centerId = UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a1"); + private UUID centerId1 = UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a1"); + private UUID centerId2 = UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a2"); + private UUID centerId3 = UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a3"); + @DisplayName("기관의 id로 선호물품을 검색할 수 있다.") @Test void findByCenterId() { //given - PreferItem preferItem = PreferItem.create(UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a1"), "어린이 동화책"); - PreferItem preferItem1 = PreferItem.create(UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a1"), "간식"); - PreferItem preferItem2 = PreferItem.create(UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a2"), "수건"); - PreferItem preferItem3 = PreferItem.create(UUID.fromString("1a1a1a1a-1a1a-1a1a-1a1a-1a1a1a1a1a3"), "식재료"); + PreferItem preferItem = PreferItem.create(centerId, "어린이 동화책"); + PreferItem preferItem1 = PreferItem.create(centerId1, "간식"); + PreferItem preferItem2 = PreferItem.create(centerId2, "수건"); + PreferItem preferItem3 = PreferItem.create(centerId3, "식재료"); preferItemRepository.saveAll(List.of(preferItem, preferItem1, preferItem2, preferItem3)); //when diff --git a/src/test/java/com/somemore/center/service/query/PreferItemQueryServiceTest.java b/src/test/java/com/somemore/center/service/query/PreferItemQueryServiceTest.java new file mode 100644 index 000000000..4f7475f93 --- /dev/null +++ b/src/test/java/com/somemore/center/service/query/PreferItemQueryServiceTest.java @@ -0,0 +1,75 @@ +package com.somemore.center.service.query; + +import com.somemore.center.domain.PreferItem; +import com.somemore.center.dto.response.PreferItemResponseDto; +import com.somemore.center.repository.PreferItemRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class PreferItemQueryServiceTest { + + @Mock + private PreferItemRepository preferItemRepository; + + @InjectMocks + private PreferItemQueryService preferItemQueryService; + + @Test + void getPreferItemDtosByCenterId() { + // Given + UUID centerId = UUID.randomUUID(); + PreferItem preferItem1 = createPreferItem(centerId, "item1"); + PreferItem preferItem2 = createPreferItem(centerId, "item2"); + List preferItems = List.of(preferItem1, preferItem2); + + when(preferItemRepository.findByCenterId(centerId)).thenReturn(preferItems); + + // When + List result = preferItemQueryService.getPreferItemDtosByCenterId(centerId); + + // Then + assertThat(result).hasSize(2); + assertThat(result.get(0).centerId()).isEqualTo(centerId); + assertThat(result.get(0).itemName()).isEqualTo("item1"); + + assertThat(result.get(1).centerId()).isEqualTo(centerId); + assertThat(result.get(1).itemName()).isEqualTo("item2"); + + verify(preferItemRepository, times(1)).findByCenterId(centerId); + } + + @Test + void getPreferItemsByCenterId() { + // Given + UUID centerId = UUID.randomUUID(); + PreferItem preferItem1 = createPreferItem(centerId, "item1"); + PreferItem preferItem2 = createPreferItem(centerId, "item2"); + List expectedItems = List.of(preferItem1, preferItem2); + + when(preferItemRepository.findByCenterId(centerId)).thenReturn(expectedItems); + + // When + List result = preferItemQueryService.getPreferItemsByCenterId(centerId); + + // Then + assertThat(result).hasSize(2).isEqualTo(expectedItems); + verify(preferItemRepository, times(1)).findByCenterId(centerId); + } + + private PreferItem createPreferItem(UUID centerId, String itemName) { + return PreferItem.builder() + .centerId(centerId) + .itemName(itemName) + .build(); + } +} \ No newline at end of file diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml index 5e687f767..4b984f3e6 100644 --- a/src/test/resources/application-test.yml +++ b/src/test/resources/application-test.yml @@ -19,4 +19,6 @@ spring: sql: init: - mode: never \ No newline at end of file + mode: never + +JWT_SECRET: 965b005bea929b5da041a3c8cf24ce0130880eb438942c159039f210aac07cc6857394c1253db2f4673f81e9485415764a086971620149072329179b800ea8e7 \ No newline at end of file