From fa492708ceaa2fd7a9f0143dba0ffd1f82a9526f Mon Sep 17 00:00:00 2001 From: eedo_y Date: Sun, 25 May 2025 00:33:05 +0900 Subject: [PATCH 01/10] =?UTF-8?q?=E2=9C=A8=EF=B8=8F=20feat/ZIP-29=20:=20?= =?UTF-8?q?=EB=8C=80=EC=8B=9C=EB=B3=B4=EB=93=9C=EB=A5=BC=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84=20-=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EB=B0=8F=20=EC=9C=A0=EC=A6=88=EC=BC=80=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/out/EstateOwnerShipAdapter.java | 10 ++ .../out/FavoritePersistenceAdapter.java | 7 + .../EstateOwnershipJpaRepository.java | 6 + .../jpa/favorite/FavoriteJpaRepository.java | 2 + .../in/dashboard/DashBoardUseCase.java | 39 +++++ .../estateOwnership/EstateOwnerShipPort.java | 5 + .../out/favorite/FavoritePort.java | 2 + .../application/service/DashBoardService.java | 165 ++++++++++++++++++ 8 files changed, 236 insertions(+) create mode 100644 src/main/java/com/zipte/platform/server/application/service/DashBoardService.java diff --git a/src/main/java/com/zipte/platform/server/adapter/out/EstateOwnerShipAdapter.java b/src/main/java/com/zipte/platform/server/adapter/out/EstateOwnerShipAdapter.java index 465454b..0ee01b7 100644 --- a/src/main/java/com/zipte/platform/server/adapter/out/EstateOwnerShipAdapter.java +++ b/src/main/java/com/zipte/platform/server/adapter/out/EstateOwnerShipAdapter.java @@ -7,6 +7,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; +import java.util.List; + @Component @RequiredArgsConstructor public class EstateOwnerShipAdapter implements EstateOwnerShipPort { @@ -33,4 +35,12 @@ public void deleteOwnership(Long userId, String kaptCode) { repository.deleteByKaptCodeAndUserId(kaptCode, userId); } + @Override + public List loadMyOwnerships(Long userId) { + + return repository.findByUserId(userId).stream() + .map(EstateOwnershipJpaEntity::toDomain) + .toList(); + } + } diff --git a/src/main/java/com/zipte/platform/server/adapter/out/FavoritePersistenceAdapter.java b/src/main/java/com/zipte/platform/server/adapter/out/FavoritePersistenceAdapter.java index a4bb554..0de9f3e 100644 --- a/src/main/java/com/zipte/platform/server/adapter/out/FavoritePersistenceAdapter.java +++ b/src/main/java/com/zipte/platform/server/adapter/out/FavoritePersistenceAdapter.java @@ -55,6 +55,13 @@ public Page loadUserFavoriteByType(Long userId, FavoriteType type, Pag .map(FavoriteJpaEntity::toDomain); } + @Override + public List loadUserFavoriteByType(Long userId, FavoriteType type) { + return repository.findByUserIdAndType(userId, type).stream() + .map(FavoriteJpaEntity::toDomain) + .toList(); + } + @Override public boolean checkFavoriteByUserIdAndTypeAndCode(Long userId, FavoriteType type, String code) { if (type.equals(FavoriteType.REGION)) { diff --git a/src/main/java/com/zipte/platform/server/adapter/out/jpa/estateOwnership/EstateOwnershipJpaRepository.java b/src/main/java/com/zipte/platform/server/adapter/out/jpa/estateOwnership/EstateOwnershipJpaRepository.java index 9306221..dc5d059 100644 --- a/src/main/java/com/zipte/platform/server/adapter/out/jpa/estateOwnership/EstateOwnershipJpaRepository.java +++ b/src/main/java/com/zipte/platform/server/adapter/out/jpa/estateOwnership/EstateOwnershipJpaRepository.java @@ -2,9 +2,15 @@ import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + public interface EstateOwnershipJpaRepository extends JpaRepository { boolean existsByKaptCodeAndUserId(String kaptCode, Long userId); void deleteByKaptCodeAndUserId(String kaptCode, Long userId); + + List findByUserId(Long userId); + + } diff --git a/src/main/java/com/zipte/platform/server/adapter/out/jpa/favorite/FavoriteJpaRepository.java b/src/main/java/com/zipte/platform/server/adapter/out/jpa/favorite/FavoriteJpaRepository.java index 66e26b0..8bd562f 100644 --- a/src/main/java/com/zipte/platform/server/adapter/out/jpa/favorite/FavoriteJpaRepository.java +++ b/src/main/java/com/zipte/platform/server/adapter/out/jpa/favorite/FavoriteJpaRepository.java @@ -15,6 +15,8 @@ public interface FavoriteJpaRepository extends JpaRepository findByUserIdAndType(Long userId, FavoriteType type, Pageable pageable); + List findByUserIdAndType(Long userId, FavoriteType type); + Optional findByIdAndUserId(Long id, Long userId); boolean existsByUserIdAndKaptCode(Long userId, String kaptCode); diff --git a/src/main/java/com/zipte/platform/server/application/in/dashboard/DashBoardUseCase.java b/src/main/java/com/zipte/platform/server/application/in/dashboard/DashBoardUseCase.java index 515123f..01cc731 100644 --- a/src/main/java/com/zipte/platform/server/application/in/dashboard/DashBoardUseCase.java +++ b/src/main/java/com/zipte/platform/server/application/in/dashboard/DashBoardUseCase.java @@ -1,4 +1,43 @@ package com.zipte.platform.server.application.in.dashboard; +import com.zipte.platform.server.domain.estate.Estate; +import com.zipte.platform.server.domain.estate.EstatePrice; +import com.zipte.platform.server.domain.region.Region; +import com.zipte.platform.server.domain.region.RegionPrice; + +import java.util.List; + public interface DashBoardUseCase { + + /* + 매매 / 관심 지역 관심 지역 - 실거래가 동향 관심 지역으로 설정한 지역의 가격 변화에 대한 알림을 받는다. + 매매 / 관심 아파트 관심 아파트 - 시세 변화 관심 아파트의 가격 변화에 대한 알림을 받는다. + 전체 / 맞춤형 아파트 제공 맞춤형 추천 매물 현황 추천시스템을 통해 관심 아파트로 설정한 유사 아파트를 제공한다. + 나의 아파트 가격 변화 / 나의 아파트 가격 변화 조회 / 개인정보에 등록한 나의 아파트의 가격 변화를 그래프로 확인한다. + */ + + + /// 관심 지역 조회하기 + List getFavoriteRegion(Long userId); + + /// 관심 지역 가격 조회하기 + List getFavoriteRegionPrices(Long userId); + + + /// 관심 아파트 목록 조회하기 + List getFavoriteEstates(Long userId); + + + /// 관심 아파트 가격 목록 조회하기 + List getFavoriteEstatePrice(Long userId); + + + /// AI 추천 목록 조회하기 + + + /// 주거지 인증을 한 나의 아파트 조회하기 + List getMyEstatePrices(Long userId); + + + } diff --git a/src/main/java/com/zipte/platform/server/application/out/estateOwnership/EstateOwnerShipPort.java b/src/main/java/com/zipte/platform/server/application/out/estateOwnership/EstateOwnerShipPort.java index 0c4e71d..233e3d8 100644 --- a/src/main/java/com/zipte/platform/server/application/out/estateOwnership/EstateOwnerShipPort.java +++ b/src/main/java/com/zipte/platform/server/application/out/estateOwnership/EstateOwnerShipPort.java @@ -2,6 +2,8 @@ import com.zipte.platform.server.domain.estateOwnership.EstateOwnership; +import java.util.*; + public interface EstateOwnerShipPort { /// 저장하기 @@ -15,4 +17,7 @@ public interface EstateOwnerShipPort { void deleteOwnership(Long userId, String kaptCode); + /// 대시보드용 + List loadMyOwnerships(Long userId); + } diff --git a/src/main/java/com/zipte/platform/server/application/out/favorite/FavoritePort.java b/src/main/java/com/zipte/platform/server/application/out/favorite/FavoritePort.java index 9f239cf..68aba88 100644 --- a/src/main/java/com/zipte/platform/server/application/out/favorite/FavoritePort.java +++ b/src/main/java/com/zipte/platform/server/application/out/favorite/FavoritePort.java @@ -27,6 +27,8 @@ public interface FavoritePort { // 관심 목록 조회하기 Page loadUserFavoriteByType(Long userId, FavoriteType type, Pageable pageable); + List loadUserFavoriteByType(Long userId, FavoriteType type); + // 중복 여부 판단 조회 boolean checkFavoriteByUserIdAndTypeAndCode(Long userId, FavoriteType type, String code); diff --git a/src/main/java/com/zipte/platform/server/application/service/DashBoardService.java b/src/main/java/com/zipte/platform/server/application/service/DashBoardService.java new file mode 100644 index 0000000..eb67ed1 --- /dev/null +++ b/src/main/java/com/zipte/platform/server/application/service/DashBoardService.java @@ -0,0 +1,165 @@ +package com.zipte.platform.server.application.service; + +import com.zipte.platform.core.response.ErrorCode; +import com.zipte.platform.server.application.in.dashboard.DashBoardUseCase; +import com.zipte.platform.server.application.out.estate.EstatePricePort; +import com.zipte.platform.server.application.out.estate.LoadEstatePort; +import com.zipte.platform.server.application.out.estateOwnership.EstateOwnerShipPort; +import com.zipte.platform.server.application.out.favorite.FavoritePort; +import com.zipte.platform.server.application.out.region.RegionPort; +import com.zipte.platform.server.application.out.region.RegionPricePort; +import com.zipte.platform.server.application.out.user.UserPort; +import com.zipte.platform.server.domain.estate.Estate; +import com.zipte.platform.server.domain.estate.EstatePrice; +import com.zipte.platform.server.domain.estateOwnership.EstateOwnership; +import com.zipte.platform.server.domain.favorite.Favorite; +import com.zipte.platform.server.domain.favorite.FavoriteType; +import com.zipte.platform.server.domain.region.Region; +import com.zipte.platform.server.domain.region.RegionPrice; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; + +@Service +@Transactional +@RequiredArgsConstructor +public class DashBoardService implements DashBoardUseCase { + + + private final UserPort userPort; + + private final FavoritePort favoritePort; + + private final RegionPort regionPort; + + private final RegionPricePort regionPricePort; + + private final LoadEstatePort loadEstatePort; + + private final EstatePricePort estatePricePort; + + private final EstateOwnerShipPort estateOwnerShipPort; + + /// 나의 관심 지역 조회 + @Override + public List getFavoriteRegion(Long userId) { + /// 유저 예외 처리 + if (userPort.checkExistingById(userId)) { + throw new NoSuchElementException(ErrorCode.NOT_USER.getMessage()); + } + + /// 유저의 관심 지역 목록 조회하기 + List regionList = favoritePort.loadUserFavoriteByType(userId, FavoriteType.REGION); + + + /// 관심 지역 목록을 바탕으로 조회하기 + List response = new ArrayList<>(); + + + regionList.forEach(favorite -> { + String regionCode = favorite.getRegionCode(); + Region region = regionPort.loadRegion(regionCode) + .orElseThrow(() -> new NoSuchElementException(ErrorCode.NOT_REGION.getMessage())); + + response.add(region); + }); + + return response; + } + + @Override + public List getFavoriteRegionPrices(Long userId) { + + /// 유저 예외 처리 + if (userPort.checkExistingById(userId)) { + throw new NoSuchElementException(ErrorCode.NOT_USER.getMessage()); + } + + /// 유저의 관심 지역 목록 조회하기 + List regionList = favoritePort.loadUserFavoriteByType(userId, FavoriteType.REGION); + + /// 관심 지역 목록을 바탕으로 가격 조회하기 + List response = new ArrayList<>(); + + regionList.forEach(region -> { + String regionCode = region.getRegionCode(); + RegionPrice regionPrice = regionPricePort.loadRegionPriceByCode(regionCode) + .orElseThrow(() -> new NoSuchElementException(ErrorCode.NOT_REGION_PRICE.getMessage())); + + response.add(regionPrice); + }); + + return response; + } + + + /// 나의 관심 아파트 조회 + @Override + public List getFavoriteEstates(Long userId) { + /// 유저 예외 처리 + if (userPort.checkExistingById(userId)) { + throw new NoSuchElementException(ErrorCode.NOT_USER.getMessage()); + } + + /// 유저의 관심 목록 조회하기 + List estateList = favoritePort.loadUserFavoriteByType(userId, FavoriteType.APARTMENT); + + /// 유저 관련 아파트 조회 + List response = new ArrayList<>(); + + + estateList.forEach(favorite -> { + String kaptCode = favorite.getKaptCode(); + Estate estate = loadEstatePort.loadEstateByCode(kaptCode) + .orElseThrow(() -> new NoSuchElementException(ErrorCode.NOT_ESTATE.getMessage())); + response.add(estate); + }); + + return response; + } + + + @Override + public List getFavoriteEstatePrice(Long userId) { + + /// 유저 예외 처리 + if (userPort.checkExistingById(userId)) { + throw new NoSuchElementException(ErrorCode.NOT_USER.getMessage()); + } + + /// 유저의 관심 목록 조회하기 + List regionList = favoritePort.loadUserFavoriteByType(userId, FavoriteType.APARTMENT); + + /// 관심 아파트 목록을 바탕으로 가격 조회하기 + // flatMap을 통해 새롭게 정의 해봄 + return regionList.stream() + .map(Favorite::getKaptCode) + .map(estatePricePort::loadAllEstatePrices) + .flatMap(List::stream) + .toList(); + } + + + /// 나의 소유 아파트 조회 + @Override + public List getMyEstatePrices(Long userId) { + + /// 유저 예외 처리 + if (userPort.checkExistingById(userId)) { + throw new NoSuchElementException(ErrorCode.NOT_USER.getMessage()); + } + + /// 나의 주거지 인증 아파트 목록 조회 + List ownerships = estateOwnerShipPort.loadMyOwnerships(userId); + + return ownerships.stream() + .map(EstateOwnership::getKaptCode) + .map(estatePricePort::loadAllEstatePrices) + .flatMap(List::stream) + .toList(); + } +} From 3b8e24473bce68fef91fd998719d73428c820674 Mon Sep 17 00:00:00 2001 From: eedo_y Date: Tue, 27 May 2025 01:36:12 +0900 Subject: [PATCH 02/10] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor/ZIP-29=20:?= =?UTF-8?q?=20N+1=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0=20-=20?= =?UTF-8?q?=ED=95=9C=EB=B2=88=EC=97=90=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../out/jpa/region/RegionJpaRepository.java | 2 + .../jpa/region/RegionPriceJpaRepository.java | 4 +- .../mongo/estate/EstateMongoRepository.java | 3 + .../estate/EstatePriceMongoRepository.java | 1 + .../out/estate/EstatePricePort.java | 3 +- .../out/estate/LoadEstatePort.java | 1 + .../application/out/region/RegionPort.java | 3 + .../out/region/RegionPricePort.java | 4 +- .../application/service/DashBoardService.java | 103 ++++++++---------- 9 files changed, 64 insertions(+), 60 deletions(-) diff --git a/src/main/java/com/zipte/platform/server/adapter/out/jpa/region/RegionJpaRepository.java b/src/main/java/com/zipte/platform/server/adapter/out/jpa/region/RegionJpaRepository.java index 1be1356..38d762d 100644 --- a/src/main/java/com/zipte/platform/server/adapter/out/jpa/region/RegionJpaRepository.java +++ b/src/main/java/com/zipte/platform/server/adapter/out/jpa/region/RegionJpaRepository.java @@ -16,4 +16,6 @@ public interface RegionJpaRepository extends JpaRepository findByCodeIn(List codes); + } diff --git a/src/main/java/com/zipte/platform/server/adapter/out/jpa/region/RegionPriceJpaRepository.java b/src/main/java/com/zipte/platform/server/adapter/out/jpa/region/RegionPriceJpaRepository.java index babbd31..2303377 100644 --- a/src/main/java/com/zipte/platform/server/adapter/out/jpa/region/RegionPriceJpaRepository.java +++ b/src/main/java/com/zipte/platform/server/adapter/out/jpa/region/RegionPriceJpaRepository.java @@ -2,11 +2,13 @@ import org.springframework.data.jpa.repository.JpaRepository; -import java.util.Optional; +import java.util.*; public interface RegionPriceJpaRepository extends JpaRepository { Optional findByRegionCode(String regionCode); + List findByRegionCodeIn(List regionCodes); + boolean existsByRegionCode(String regionCode); } diff --git a/src/main/java/com/zipte/platform/server/adapter/out/mongo/estate/EstateMongoRepository.java b/src/main/java/com/zipte/platform/server/adapter/out/mongo/estate/EstateMongoRepository.java index 001b5b4..b7a992a 100644 --- a/src/main/java/com/zipte/platform/server/adapter/out/mongo/estate/EstateMongoRepository.java +++ b/src/main/java/com/zipte/platform/server/adapter/out/mongo/estate/EstateMongoRepository.java @@ -28,4 +28,7 @@ public interface EstateMongoRepository extends MongoRepository findByLocation(double longitude, double latitude, double radiusInRadians); boolean existsByKaptCode(String kaptCode); + + /// 코드를 바탕으로 여러개를 한번에 가져오기 + List findByKaptCodeIn(List kaptCodes); } diff --git a/src/main/java/com/zipte/platform/server/adapter/out/mongo/estate/EstatePriceMongoRepository.java b/src/main/java/com/zipte/platform/server/adapter/out/mongo/estate/EstatePriceMongoRepository.java index 890da34..c5e2f89 100644 --- a/src/main/java/com/zipte/platform/server/adapter/out/mongo/estate/EstatePriceMongoRepository.java +++ b/src/main/java/com/zipte/platform/server/adapter/out/mongo/estate/EstatePriceMongoRepository.java @@ -10,4 +10,5 @@ public interface EstatePriceMongoRepository extends MongoRepository findALlByKaptCodeAndExclusiveArea(String kaptCode, double exclusiveArea); + List findByKaptCodeIn(List kaptCodes); } diff --git a/src/main/java/com/zipte/platform/server/application/out/estate/EstatePricePort.java b/src/main/java/com/zipte/platform/server/application/out/estate/EstatePricePort.java index 10da6d7..19f7934 100644 --- a/src/main/java/com/zipte/platform/server/application/out/estate/EstatePricePort.java +++ b/src/main/java/com/zipte/platform/server/application/out/estate/EstatePricePort.java @@ -15,5 +15,6 @@ public interface EstatePricePort { /// 기간별 조회하기 List loadAllEstatePricesBetween(String kaptCode, String from, String to); - + /// 외부 의존성 + List loadEstatePricesByCodes(List kaptCodes); } diff --git a/src/main/java/com/zipte/platform/server/application/out/estate/LoadEstatePort.java b/src/main/java/com/zipte/platform/server/application/out/estate/LoadEstatePort.java index 484b979..c55063a 100644 --- a/src/main/java/com/zipte/platform/server/application/out/estate/LoadEstatePort.java +++ b/src/main/java/com/zipte/platform/server/application/out/estate/LoadEstatePort.java @@ -23,4 +23,5 @@ public interface LoadEstatePort { /// 외부에서 활용하는 포트 List loadEstatesByRegion(String region); + List loadEstatesByCodes(List kaptCodes); } diff --git a/src/main/java/com/zipte/platform/server/application/out/region/RegionPort.java b/src/main/java/com/zipte/platform/server/application/out/region/RegionPort.java index 2173ae2..a415461 100644 --- a/src/main/java/com/zipte/platform/server/application/out/region/RegionPort.java +++ b/src/main/java/com/zipte/platform/server/application/out/region/RegionPort.java @@ -16,6 +16,9 @@ public interface RegionPort { /// 존재 여부를 체크하는 boolean boolean checkExistCode(String regionCode); + /// 코드를 바탕으로 한번에 조회하기 + List loadRegionsByCodes(List codes); + /// 배치 처리 List loadAllRegions(); diff --git a/src/main/java/com/zipte/platform/server/application/out/region/RegionPricePort.java b/src/main/java/com/zipte/platform/server/application/out/region/RegionPricePort.java index 3d98f55..db76474 100644 --- a/src/main/java/com/zipte/platform/server/application/out/region/RegionPricePort.java +++ b/src/main/java/com/zipte/platform/server/application/out/region/RegionPricePort.java @@ -2,7 +2,7 @@ import com.zipte.platform.server.domain.region.RegionPrice; -import java.util.Optional; +import java.util.*; public interface RegionPricePort { @@ -17,6 +17,8 @@ public interface RegionPricePort { boolean checkRegionPriceExist(String regionCode); + List loadRegionPriceByCodes(List regionCodes); + /// 삭제 void deleteRegionPriceByCode(String regionCode); diff --git a/src/main/java/com/zipte/platform/server/application/service/DashBoardService.java b/src/main/java/com/zipte/platform/server/application/service/DashBoardService.java index eb67ed1..dca14bc 100644 --- a/src/main/java/com/zipte/platform/server/application/service/DashBoardService.java +++ b/src/main/java/com/zipte/platform/server/application/service/DashBoardService.java @@ -17,15 +17,16 @@ import com.zipte.platform.server.domain.region.Region; import com.zipte.platform.server.domain.region.RegionPrice; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; +@Slf4j @Service -@Transactional +@Transactional(readOnly = true) @RequiredArgsConstructor public class DashBoardService implements DashBoardUseCase { @@ -38,7 +39,7 @@ public class DashBoardService implements DashBoardUseCase { private final RegionPricePort regionPricePort; - private final LoadEstatePort loadEstatePort; + private final LoadEstatePort estatePort; private final EstatePricePort estatePricePort; @@ -47,79 +48,57 @@ public class DashBoardService implements DashBoardUseCase { /// 나의 관심 지역 조회 @Override public List getFavoriteRegion(Long userId) { + /// 유저 예외 처리 - if (userPort.checkExistingById(userId)) { - throw new NoSuchElementException(ErrorCode.NOT_USER.getMessage()); - } + checkUser(userId); /// 유저의 관심 지역 목록 조회하기 List regionList = favoritePort.loadUserFavoriteByType(userId, FavoriteType.REGION); - /// 관심 지역 목록을 바탕으로 조회하기 - List response = new ArrayList<>(); - - - regionList.forEach(favorite -> { - String regionCode = favorite.getRegionCode(); - Region region = regionPort.loadRegion(regionCode) - .orElseThrow(() -> new NoSuchElementException(ErrorCode.NOT_REGION.getMessage())); - - response.add(region); - }); + List regionCodes = regionList.stream() + .map(Favorite::getRegionCode) + .toList(); - return response; + return regionPort.loadRegionsByCodes(regionCodes); } @Override public List getFavoriteRegionPrices(Long userId) { /// 유저 예외 처리 - if (userPort.checkExistingById(userId)) { - throw new NoSuchElementException(ErrorCode.NOT_USER.getMessage()); - } + checkUser(userId); /// 유저의 관심 지역 목록 조회하기 List regionList = favoritePort.loadUserFavoriteByType(userId, FavoriteType.REGION); /// 관심 지역 목록을 바탕으로 가격 조회하기 - List response = new ArrayList<>(); - - regionList.forEach(region -> { - String regionCode = region.getRegionCode(); - RegionPrice regionPrice = regionPricePort.loadRegionPriceByCode(regionCode) - .orElseThrow(() -> new NoSuchElementException(ErrorCode.NOT_REGION_PRICE.getMessage())); - - response.add(regionPrice); - }); + List regionCodes = regionList.stream() + .map(Favorite::getRegionCode) + .toList(); - return response; + /// 코드들을 바탕으로 조회하기 + return regionPricePort.loadRegionPriceByCodes(regionCodes); } /// 나의 관심 아파트 조회 @Override public List getFavoriteEstates(Long userId) { + /// 유저 예외 처리 - if (userPort.checkExistingById(userId)) { - throw new NoSuchElementException(ErrorCode.NOT_USER.getMessage()); - } + checkUser(userId); /// 유저의 관심 목록 조회하기 List estateList = favoritePort.loadUserFavoriteByType(userId, FavoriteType.APARTMENT); /// 유저 관련 아파트 조회 - List response = new ArrayList<>(); - - - estateList.forEach(favorite -> { - String kaptCode = favorite.getKaptCode(); - Estate estate = loadEstatePort.loadEstateByCode(kaptCode) - .orElseThrow(() -> new NoSuchElementException(ErrorCode.NOT_ESTATE.getMessage())); - response.add(estate); - }); + List codes = estateList.stream() + .map(Favorite::getKaptCode) + .toList(); - return response; + /// 코드들을 바탕으로 조회하기 + return estatePort.loadEstatesByCodes(codes); } @@ -127,20 +106,22 @@ public List getFavoriteEstates(Long userId) { public List getFavoriteEstatePrice(Long userId) { /// 유저 예외 처리 - if (userPort.checkExistingById(userId)) { - throw new NoSuchElementException(ErrorCode.NOT_USER.getMessage()); - } + checkUser(userId); /// 유저의 관심 목록 조회하기 List regionList = favoritePort.loadUserFavoriteByType(userId, FavoriteType.APARTMENT); /// 관심 아파트 목록을 바탕으로 가격 조회하기 - // flatMap을 통해 새롭게 정의 해봄 - return regionList.stream() + List codes = regionList.stream() .map(Favorite::getKaptCode) - .map(estatePricePort::loadAllEstatePrices) - .flatMap(List::stream) .toList(); + + log.info("codes: {}", codes); + + List list = estatePricePort.loadEstatePricesByCodes(codes); + + log.info("list: {}", list); + return list; } @@ -149,17 +130,25 @@ public List getFavoriteEstatePrice(Long userId) { public List getMyEstatePrices(Long userId) { /// 유저 예외 처리 - if (userPort.checkExistingById(userId)) { - throw new NoSuchElementException(ErrorCode.NOT_USER.getMessage()); - } + checkUser(userId); /// 나의 주거지 인증 아파트 목록 조회 List ownerships = estateOwnerShipPort.loadMyOwnerships(userId); - return ownerships.stream() + List codes = ownerships.stream() .map(EstateOwnership::getKaptCode) - .map(estatePricePort::loadAllEstatePrices) - .flatMap(List::stream) .toList(); + + return estatePricePort.loadEstatePricesByCodes(codes); + } + + + /// 내부 함수 + private void checkUser(Long userId) { + if (!userPort.checkExistingById(userId)) { + throw new NoSuchElementException(ErrorCode.NOT_USER.getMessage()); + } } + + } From 421c9d2f9dec8d0e252cd6e3222124be5c83d1e2 Mon Sep 17 00:00:00 2001 From: eedo_y Date: Tue, 27 May 2025 01:36:45 +0900 Subject: [PATCH 03/10] =?UTF-8?q?=E2=9C=A8=EF=B8=8F=20feat/ZIP-29=20:=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=EC=B2=B4=20=EC=A0=95=EC=9D=98=20-=20API=20?= =?UTF-8?q?=EB=B0=8F=20=EC=96=B4=EB=8C=91=ED=84=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/adapter/in/web/DashBoardApi.java | 97 +++++++++++++++++++ .../dto/response/EstateDetailResponse.java | 9 ++ .../web/dto/response/RegionPriceResponse.java | 25 ++++- .../adapter/out/EstatePersistenceAdapter.java | 7 ++ .../out/EstatePricePersistenceAdapter.java | 7 ++ .../adapter/out/RegionPersistenceAdapter.java | 8 ++ .../out/RegionPricePersistenceAdapter.java | 8 ++ 7 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/zipte/platform/server/adapter/in/web/DashBoardApi.java diff --git a/src/main/java/com/zipte/platform/server/adapter/in/web/DashBoardApi.java b/src/main/java/com/zipte/platform/server/adapter/in/web/DashBoardApi.java new file mode 100644 index 0000000..e88f053 --- /dev/null +++ b/src/main/java/com/zipte/platform/server/adapter/in/web/DashBoardApi.java @@ -0,0 +1,97 @@ +package com.zipte.platform.server.adapter.in.web; + +import com.zipte.platform.core.response.ApiResponse; +import com.zipte.platform.security.oauth2.domain.PrincipalDetails; +import com.zipte.platform.server.adapter.in.web.dto.response.*; +import com.zipte.platform.server.application.in.dashboard.DashBoardUseCase; +import com.zipte.platform.server.domain.estate.Estate; +import com.zipte.platform.server.domain.estate.EstatePrice; +import com.zipte.platform.server.domain.region.Region; +import com.zipte.platform.server.domain.region.RegionPrice; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequestMapping("/api/v1/dashboard") +@RequiredArgsConstructor +public class DashBoardApi { + + private final DashBoardUseCase dashboardService; + + @GetMapping("/region") + public ApiResponse> getMyRegion(@AuthenticationPrincipal PrincipalDetails principalDetails) { + + /// 유저 아이디 추출하기 -> AOP로 한번에 처리하기? + Long userId = principalDetails.getId(); + + List region = dashboardService.getFavoriteRegion(userId); + + List responses = RegionResponse.from(region); + return ApiResponse.ok(responses); + } + + + @GetMapping("/region/price") + public ApiResponse> getMyRegionPrice(@AuthenticationPrincipal PrincipalDetails principalDetails) { + + /// 유저 아이디 추출하기 + Long userId = principalDetails.getId(); + + List regionPrices = dashboardService.getFavoriteRegionPrices(userId); + + List responses = RegionPriceResponse.from(regionPrices); + + return ApiResponse.ok(responses); + } + + + @GetMapping("/estate") + public ApiResponse> getMyEstate(@AuthenticationPrincipal PrincipalDetails principalDetails) { + + /// 유저 아이디 추출하기 + Long userId = principalDetails.getId(); + + List estates = dashboardService.getFavoriteEstates(userId); + + List responses = EstateDetailResponse.from(estates); + + return ApiResponse.ok(responses); + } + + @GetMapping("/estate/price") + public ApiResponse> getMyEstatePrice(@AuthenticationPrincipal PrincipalDetails principalDetails) { + + /// 유저 아이디 추출하기 + Long userId = principalDetails.getId(); + + /// 서비스 계층 추출 + List estatePrices = dashboardService.getFavoriteEstatePrice(userId); + + List responses = EstatePriceListResponse.from(estatePrices); + + return ApiResponse.ok(responses); + } + + @GetMapping("/estate/myhome") + public ApiResponse> getMyHomeEstate(@AuthenticationPrincipal PrincipalDetails principalDetails) { + + /// 유저 아이디 추출하기 + Long userId = principalDetails.getId(); + + /// 서비스 계층 추출 + List myEstatePrices = dashboardService.getMyEstatePrices(userId); + + /// + List responses = EstatePriceListResponse.from(myEstatePrices); + + return ApiResponse.ok(responses); + } + + + +} diff --git a/src/main/java/com/zipte/platform/server/adapter/in/web/dto/response/EstateDetailResponse.java b/src/main/java/com/zipte/platform/server/adapter/in/web/dto/response/EstateDetailResponse.java index 017153c..c2e6701 100644 --- a/src/main/java/com/zipte/platform/server/adapter/in/web/dto/response/EstateDetailResponse.java +++ b/src/main/java/com/zipte/platform/server/adapter/in/web/dto/response/EstateDetailResponse.java @@ -4,6 +4,8 @@ import lombok.Builder; import lombok.Data; +import java.util.*; + @Data @Builder public class EstateDetailResponse { @@ -34,4 +36,11 @@ public static EstateDetailResponse from(Estate estate) { .facility(EstateFacilityResponse.from(estate)) .build(); } + + public static List from(List estates) { + return estates.stream() + .map(EstateDetailResponse::from) + .toList(); + + } } diff --git a/src/main/java/com/zipte/platform/server/adapter/in/web/dto/response/RegionPriceResponse.java b/src/main/java/com/zipte/platform/server/adapter/in/web/dto/response/RegionPriceResponse.java index 7ad1960..72e89f0 100644 --- a/src/main/java/com/zipte/platform/server/adapter/in/web/dto/response/RegionPriceResponse.java +++ b/src/main/java/com/zipte/platform/server/adapter/in/web/dto/response/RegionPriceResponse.java @@ -3,6 +3,8 @@ import com.zipte.platform.server.domain.region.RegionPrice; import lombok.Builder; +import java.util.*; + @Builder public record RegionPriceResponse( @JsonProperty("지역코드") @@ -20,7 +22,6 @@ public record RegionPriceResponse( @JsonProperty("25~30평") String between25and30, - @JsonProperty("30평 이상") String upper30 ) { @@ -35,8 +36,28 @@ public static RegionPriceResponse from(RegionPrice regionPrice) { .build(); } + + public static List from(List regionPrices) { + return regionPrices.stream() + .map(RegionPriceResponse::from) + .toList(); + } + + /// 내부 함수 private static String format(Double price) { if (price == null) return "-"; - return String.format("%.0f만원", price); + + long value = price.longValue(); // 만원 단위 정수화 + long billion = value / 10000; // 억 단위 + long rest = value % 10000; // 천만원 이하 + + if (billion > 0 && rest > 0) { + return String.format("%d억 %,d만원", billion, rest); + } else if (billion > 0) { + return String.format("%d억", billion); + } else { + return String.format("%,d만원", rest); + } } + } diff --git a/src/main/java/com/zipte/platform/server/adapter/out/EstatePersistenceAdapter.java b/src/main/java/com/zipte/platform/server/adapter/out/EstatePersistenceAdapter.java index a0f05b6..c48a963 100644 --- a/src/main/java/com/zipte/platform/server/adapter/out/EstatePersistenceAdapter.java +++ b/src/main/java/com/zipte/platform/server/adapter/out/EstatePersistenceAdapter.java @@ -53,4 +53,11 @@ public List loadEstatesByRegion(String region) { .map(EstateDocument::toDomain) .toList(); } + + @Override + public List loadEstatesByCodes(List kaptCodes) { + return repository.findByKaptCodeIn(kaptCodes).stream() + .map(EstateDocument::toDomain) + .toList(); + } } diff --git a/src/main/java/com/zipte/platform/server/adapter/out/EstatePricePersistenceAdapter.java b/src/main/java/com/zipte/platform/server/adapter/out/EstatePricePersistenceAdapter.java index 4c5cb72..c451105 100644 --- a/src/main/java/com/zipte/platform/server/adapter/out/EstatePricePersistenceAdapter.java +++ b/src/main/java/com/zipte/platform/server/adapter/out/EstatePricePersistenceAdapter.java @@ -33,4 +33,11 @@ public List loadEstatePriceByCodeAndArea(String kaptCode, double ex public List loadAllEstatePricesBetween(String kaptCode, String from, String to) { return List.of(); } + + @Override + public List loadEstatePricesByCodes(List kaptCodes) { + return repository.findByKaptCodeIn(kaptCodes).stream() + .map(EstatePriceDocument::toDomain) + .toList(); + } } diff --git a/src/main/java/com/zipte/platform/server/adapter/out/RegionPersistenceAdapter.java b/src/main/java/com/zipte/platform/server/adapter/out/RegionPersistenceAdapter.java index a9ac634..6f3f66f 100644 --- a/src/main/java/com/zipte/platform/server/adapter/out/RegionPersistenceAdapter.java +++ b/src/main/java/com/zipte/platform/server/adapter/out/RegionPersistenceAdapter.java @@ -41,6 +41,14 @@ public List loadChildRegionsByPrefix(String prefix, String suffix) { .toList(); } + + @Override + public List loadRegionsByCodes(List codes) { + return repository.findByCodeIn(codes).stream() + .map(RegionJpaEntity::toDomain) + .toList(); + } + @Override public boolean checkExistCode(String regionCode) { return repository.existsByCode(regionCode); diff --git a/src/main/java/com/zipte/platform/server/adapter/out/RegionPricePersistenceAdapter.java b/src/main/java/com/zipte/platform/server/adapter/out/RegionPricePersistenceAdapter.java index d54f100..5d8b03e 100644 --- a/src/main/java/com/zipte/platform/server/adapter/out/RegionPricePersistenceAdapter.java +++ b/src/main/java/com/zipte/platform/server/adapter/out/RegionPricePersistenceAdapter.java @@ -7,6 +7,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; +import java.util.List; import java.util.NoSuchElementException; import java.util.Optional; @@ -50,6 +51,13 @@ public boolean checkRegionPriceExist(String regionCode) { return repository.existsByRegionCode(regionCode); } + @Override + public List loadRegionPriceByCodes(List regionCodes) { + return repository.findByRegionCodeIn(regionCodes).stream() + .map(RegionPriceJpaEntity::toDomain) + .toList(); + } + @Override public void deleteRegionPriceByCode(String regionCode) { From a3747eb00280757cba4884ec9080aa55f9a7ea40 Mon Sep 17 00:00:00 2001 From: eedo_y Date: Tue, 27 May 2025 01:39:22 +0900 Subject: [PATCH 04/10] =?UTF-8?q?=F0=9F=92=A1=EF=B8=8Fstyle/ZIP-29=20:=20?= =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4=20=EB=82=B4=20=EB=A1=9C=EA=B7=B8=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/application/service/DashBoardService.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/java/com/zipte/platform/server/application/service/DashBoardService.java b/src/main/java/com/zipte/platform/server/application/service/DashBoardService.java index dca14bc..d3198e8 100644 --- a/src/main/java/com/zipte/platform/server/application/service/DashBoardService.java +++ b/src/main/java/com/zipte/platform/server/application/service/DashBoardService.java @@ -116,12 +116,7 @@ public List getFavoriteEstatePrice(Long userId) { .map(Favorite::getKaptCode) .toList(); - log.info("codes: {}", codes); - - List list = estatePricePort.loadEstatePricesByCodes(codes); - - log.info("list: {}", list); - return list; + return estatePricePort.loadEstatePricesByCodes(codes); } From 36962be5ed7e4a205bdb06da5443fcd89a7eb6eb Mon Sep 17 00:00:00 2001 From: eedo_y Date: Wed, 28 May 2025 02:20:27 +0900 Subject: [PATCH 05/10] =?UTF-8?q?=E2=9C=85test/ZIP-29=20:=20=EC=84=9C?= =?UTF-8?q?=EB=B9=84=EC=8A=A4=20=EB=B0=8F=20API=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80=20-=20happy=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9C=84=EC=A3=BC=EB=A1=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/in/web/DashBoardApiTest.java | 223 +++++++++++++++ .../service/DashBoardServiceTest.java | 264 ++++++++++++++++++ .../service/EstateOwnershipServiceTest.java | 2 +- .../server/domain/estate/EstateFixtures.java | 41 +++ .../domain/estate/EstatePriceFixtures.java | 18 ++ .../domain/region/RegionPriceFixtures.java | 20 ++ .../server/domain/review/EstateFixtures.java | 26 -- 7 files changed, 567 insertions(+), 27 deletions(-) create mode 100644 src/test/java/com/zipte/platform/server/adapter/in/web/DashBoardApiTest.java create mode 100644 src/test/java/com/zipte/platform/server/application/service/DashBoardServiceTest.java create mode 100644 src/test/java/com/zipte/platform/server/domain/estate/EstateFixtures.java create mode 100644 src/test/java/com/zipte/platform/server/domain/estate/EstatePriceFixtures.java create mode 100644 src/test/java/com/zipte/platform/server/domain/region/RegionPriceFixtures.java delete mode 100644 src/test/java/com/zipte/platform/server/domain/review/EstateFixtures.java diff --git a/src/test/java/com/zipte/platform/server/adapter/in/web/DashBoardApiTest.java b/src/test/java/com/zipte/platform/server/adapter/in/web/DashBoardApiTest.java new file mode 100644 index 0000000..839f6d1 --- /dev/null +++ b/src/test/java/com/zipte/platform/server/adapter/in/web/DashBoardApiTest.java @@ -0,0 +1,223 @@ +package com.zipte.platform.server.adapter.in.web; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.zipte.platform.core.response.ApiResponse; +import com.zipte.platform.security.annotation.WithMockCustomUser; +import com.zipte.platform.server.adapter.in.web.dto.response.EstateDetailResponse; +import com.zipte.platform.server.adapter.in.web.dto.response.EstatePriceListResponse; +import com.zipte.platform.server.adapter.in.web.dto.response.RegionPriceResponse; +import com.zipte.platform.server.adapter.in.web.dto.response.RegionResponse; +import com.zipte.platform.server.application.service.DashBoardService; +import com.zipte.platform.server.domain.estate.Estate; +import com.zipte.platform.server.domain.estate.EstateFixtures; +import com.zipte.platform.server.domain.estate.EstatePrice; +import com.zipte.platform.server.domain.estate.EstatePriceFixtures; +import com.zipte.platform.server.domain.region.Region; +import com.zipte.platform.server.domain.region.RegionFixtures; +import com.zipte.platform.server.domain.region.RegionPrice; +import com.zipte.platform.server.domain.region.RegionPriceFixtures; +import org.junit.jupiter.api.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.*; + +@SpringBootTest +@AutoConfigureMockMvc(addFilters = false) +class DashBoardApiTest { + + @Autowired + private MockMvc mockMvc; + + @MockitoBean + private DashBoardService dashBoardService; + + private ObjectMapper objectMapper; + + @BeforeEach + void setUp() { + this.objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + } + + @Nested + @DisplayName("지역 관련") + class RegionLoad { + + + @Test + @WithMockCustomUser + @DisplayName("[happy] 지역관련") + void happy_region() throws Exception { + + // Given + Long userId = 1L; + + Region region1 = RegionFixtures.분당구(); + Region region2 = RegionFixtures.종로구(); + List responses = List.of(region1, region2); + given(dashBoardService.getFavoriteRegion(userId)) + .willReturn(responses); + List responseList = RegionResponse.from(responses); + + ApiResponse> apiResponse = ApiResponse.ok(responseList); + + // When + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders + .get("/api/v1/dashboard/region") + .contentType(MediaType.APPLICATION_JSON)); + + // Then + MvcResult mvcResult = resultActions + .andExpect(status().isOk()) + .andDo(print()) + .andReturn(); + + String responseBody = mvcResult.getResponse().getContentAsString(); + + assertEquals(responseBody, objectMapper.writeValueAsString(apiResponse)); + } + } + + + @Nested + @DisplayName("지역 가격 관련") + class RegionPriceLoad { + + @Test + @WithMockCustomUser + @DisplayName("[happy] 관심 지역 가격 조회") + void getFavoriteRegionPrices_success() throws Exception { + // Given + Long userId = 1L; + + String regionCode1 = "region1"; + String regionCode2 = "region2"; + RegionPrice stub1 = RegionPriceFixtures.stub(regionCode1); + RegionPrice stub2 = RegionPriceFixtures.stub(regionCode2); + var prices = List.of(stub1, stub2); + + given(dashBoardService.getFavoriteRegionPrices(userId)) + .willReturn(prices); + ApiResponse> expectedResponse = ApiResponse.ok(RegionPriceResponse.from(prices)); + + // When + ResultActions result = mockMvc.perform(MockMvcRequestBuilders + .get("/api/v1/dashboard/region/price") + .contentType(MediaType.APPLICATION_JSON)); + + // Then + String responseBody = result.andExpect(status().isOk()) + .andDo(print()) + .andReturn().getResponse().getContentAsString(); + + assertEquals(objectMapper.writeValueAsString(expectedResponse), responseBody); + } + } + + @Nested + @DisplayName("관심 아파트 관련") + class EstateLoad { + + @Test + @WithMockCustomUser + @DisplayName("[happy] 관심 아파트 조회") + void getFavoriteEstates_success() throws Exception { + // Given + Long userId = 1L; + Estate 테스트1 = EstateFixtures.stub("테스트1"); + Estate 테스트2 = EstateFixtures.stub("테스트2"); + + + List estates = List.of(테스트1, 테스트2); + given(dashBoardService.getFavoriteEstates(userId)) + .willReturn(estates); + + ApiResponse> expectedResponse = ApiResponse.ok(EstateDetailResponse.from(estates)); + + // When + ResultActions result = mockMvc.perform(MockMvcRequestBuilders + .get("/api/v1/dashboard/estate") + .contentType(MediaType.APPLICATION_JSON)); + + // Then + String responseBody = result.andExpect(status().isOk()) + .andDo(print()) + .andReturn().getResponse().getContentAsString(); + + assertEquals(objectMapper.writeValueAsString(expectedResponse), responseBody); + } + + @Test + @WithMockCustomUser + @DisplayName("[happy] 관심 아파트 가격 조회") + void getFavoriteEstatePrices_success() throws Exception { + // Given + Long userId = 1L; + EstatePrice stub1 = EstatePriceFixtures.stub("테스트1"); + EstatePrice stub2 = EstatePriceFixtures.stub("테스트2"); + List prices = List.of(stub1, stub2); + + given(dashBoardService.getFavoriteEstatePrice(userId)) + .willReturn(prices); + + ApiResponse> expectedResponse = ApiResponse.ok(EstatePriceListResponse.from(prices)); + + // When + ResultActions result = mockMvc.perform(MockMvcRequestBuilders + .get("/api/v1/dashboard/estate/price") + .contentType(MediaType.APPLICATION_JSON)); + + // Then + String responseBody = result.andExpect(status().isOk()) + .andDo(print()) + .andReturn().getResponse().getContentAsString(); + + assertEquals(objectMapper.writeValueAsString(expectedResponse), responseBody); + } + } + + @Nested + @DisplayName("내 아파트 관련") + class MyHome { + + @Test + @WithMockCustomUser + @DisplayName("[happy] 내 보유 아파트 가격 조회") + void getMyEstatePrices_success() throws Exception { + // Given + Long userId = 1L; + EstatePrice stub1 = EstatePriceFixtures.stub("테스트1"); + + List prices = List.of(stub1); + given(dashBoardService.getMyEstatePrices(userId)) + .willReturn(prices); + ApiResponse> expectedResponse = ApiResponse.ok(EstatePriceListResponse.from(prices)); + + // When + ResultActions result = mockMvc.perform(MockMvcRequestBuilders + .get("/api/v1/dashboard/estate/myhome") + .contentType(MediaType.APPLICATION_JSON)); + + // Then + String responseBody = result.andExpect(status().isOk()) + .andDo(print()) + .andReturn().getResponse().getContentAsString(); + + assertEquals(objectMapper.writeValueAsString(expectedResponse), responseBody); + } + } +} diff --git a/src/test/java/com/zipte/platform/server/application/service/DashBoardServiceTest.java b/src/test/java/com/zipte/platform/server/application/service/DashBoardServiceTest.java new file mode 100644 index 0000000..1d23451 --- /dev/null +++ b/src/test/java/com/zipte/platform/server/application/service/DashBoardServiceTest.java @@ -0,0 +1,264 @@ +package com.zipte.platform.server.application.service; + +import com.zipte.platform.server.application.out.estate.EstatePricePort; +import com.zipte.platform.server.application.out.estate.LoadEstatePort; +import com.zipte.platform.server.application.out.estateOwnership.EstateOwnerShipPort; +import com.zipte.platform.server.application.out.favorite.FavoritePort; +import com.zipte.platform.server.application.out.region.RegionPort; +import com.zipte.platform.server.application.out.region.RegionPricePort; +import com.zipte.platform.server.application.out.user.UserPort; +import com.zipte.platform.server.domain.FavoriteFixtures; +import com.zipte.platform.server.domain.estate.Estate; +import com.zipte.platform.server.domain.estate.EstatePrice; +import com.zipte.platform.server.domain.estateOwnership.EstateOwnership; +import com.zipte.platform.server.domain.favorite.Favorite; +import com.zipte.platform.server.domain.favorite.FavoriteType; +import com.zipte.platform.server.domain.region.Region; +import com.zipte.platform.server.domain.region.RegionFixtures; +import com.zipte.platform.server.domain.estate.EstateFixtures; +import com.zipte.platform.server.domain.review.EstateOwnerShipFixtures; +import com.zipte.platform.server.domain.estate.EstatePriceFixtures; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +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.time.LocalDateTime; +import java.util.List; +import java.util.NoSuchElementException; + +import static org.assertj.core.api.BDDAssertions.then; +import static org.mockito.BDDMockito.given; + +@ExtendWith(MockitoExtension.class) +class DashBoardServiceTest { + + @Mock + private UserPort userPort; + + @Mock + private FavoritePort favoritePort; + + @Mock + private RegionPort regionPort; + + @Mock + private RegionPricePort regionPricePort; + + @Mock + private LoadEstatePort loadEstatePort; + + @Mock + private EstatePricePort estatePricePort; + + @Mock + private EstateOwnerShipPort estateOwnerShipPort; + + @InjectMocks + private DashBoardService sut; + + + @Nested + @DisplayName("지역 관련 조회") + class GetRegion { + + @Test + @DisplayName("[happy] 나의 관심 지역 목록을 조회합니다.") + void getRegionList_happy() { + + // Given + Long userId = 1L; + + given(userPort.checkExistingById(userId)) + .willReturn(true); + + Favorite 테스트_지역1 = FavoriteFixtures.regionFavorite(userId, "분당구"); + Favorite 테스트_지역2 = FavoriteFixtures.regionFavorite(userId, "종로구"); + List favoriteList = List.of(테스트_지역1, 테스트_지역2); + + given(favoritePort.loadUserFavoriteByType(userId, FavoriteType.REGION)) + .willReturn(favoriteList); + + List codes = List.of(테스트_지역1.getRegionCode(), 테스트_지역2.getRegionCode()); + + Region 분당구 = RegionFixtures.분당구(); + Region 종로구 = RegionFixtures.종로구(); + List regionList = List.of(분당구, 종로구); + + given(regionPort.loadRegionsByCodes(codes)) + .willReturn(regionList); + + // When + List response = sut.getFavoriteRegion(userId); + + // Then + then(response) + .isNotNull() + .hasSize(2) + .containsExactlyInAnyOrder(분당구, 종로구); + } + + + @Test + @DisplayName("[happy] 나의 관심 지역 가격을 조회합니다.") + void getRegionPrice_happy() { + + // Given + Long userId = 1L; + + given(userPort.checkExistingById(userId)) + .willReturn(true); + + Favorite 테스트_지역1 = FavoriteFixtures.regionFavorite(userId, "분당구"); + Favorite 테스트_지역2 = FavoriteFixtures.regionFavorite(userId, "종로구"); + List favoriteList = List.of(테스트_지역1, 테스트_지역2); + + given(favoritePort.loadUserFavoriteByType(userId, FavoriteType.REGION)) + .willReturn(favoriteList); + + List codes = List.of(테스트_지역1.getRegionCode(), 테스트_지역2.getRegionCode()); + + Region 분당구 = RegionFixtures.분당구(); + Region 종로구 = RegionFixtures.종로구(); + List regionList = List.of(분당구, 종로구); + + given(regionPort.loadRegionsByCodes(codes)) + .willReturn(regionList); + + // When + List response = sut.getFavoriteRegion(userId); + + // Then + then(response) + .isNotNull() + .hasSize(2) + .containsExactlyInAnyOrder(분당구, 종로구); + } + + } + + @Nested + @DisplayName("아파트 관련 조회") + class EstateTest { + + @Test + @DisplayName("[happy] 나의 관심 아파트 목록을 조회합니다.") + void getFavoriteEstates_success() { + // Given + Long userId = 1L; + String kaptCode1 = "KaptCode1"; + String kaptCode2 = "KaptCode2"; + given(userPort.checkExistingById(userId)) + .willReturn(true); + + Favorite apt1 = FavoriteFixtures.apartmentFavorite(userId, kaptCode1); + Favorite apt2 = FavoriteFixtures.apartmentFavorite(userId, kaptCode2); + + given(favoritePort.loadUserFavoriteByType(userId, FavoriteType.APARTMENT)) + .willReturn(List.of(apt1, apt2)); + + Estate stub1 = EstateFixtures.stub(kaptCode1); + Estate stub2 = EstateFixtures.stub(kaptCode2); + + given(loadEstatePort.loadEstatesByCodes(List.of(kaptCode1, kaptCode2))) + .willReturn(List.of(stub1, stub2)); + + // When + var result = sut.getFavoriteEstates(userId); + + // Then + then(result) + .hasSize(2) + .containsExactlyInAnyOrder(stub1, stub2); + } + + @Test + @DisplayName("[happy] 나의 관심 아파트 가격을 조회합니다.") + void getFavoriteEstatePrices_success() { + // Given + Long userId = 1L; + given(userPort.checkExistingById(userId)) + .willReturn(true); + + String kaptCode1 = "KaptCode1"; + String kaptCode2 = "KaptCode2"; + Favorite apt1 = FavoriteFixtures.apartmentFavorite(userId, "AAPT1"); + Favorite apt2 = FavoriteFixtures.apartmentFavorite(userId, "AAPT2"); + + given(favoritePort.loadUserFavoriteByType(userId, FavoriteType.APARTMENT)) + .willReturn(List.of(apt1, apt2)); + + EstatePrice stub = EstatePriceFixtures.stub(kaptCode1); + EstatePrice stub2 = EstatePriceFixtures.stub(kaptCode2); + + given(estatePricePort.loadEstatePricesByCodes(List.of("AAPT1", "AAPT2"))) + .willReturn(List.of(stub, stub2)); + + // When + List result = sut.getFavoriteEstatePrice(userId); + + // Then + then(result).hasSize(2) + .containsExactlyInAnyOrder(stub, stub2); + } + } + + @Nested + @DisplayName("소유 아파트 조회") + class OwnershipTest { + + @Test + @DisplayName("[happy] 나의 소유 아파트 가격을 조회합니다.") + void getMyEstatePrices_success() { + // Given + Long userId = 1L; + String kaptCode1 = "KaptCode1"; + String kaptCode2 = "KaptCode2"; + + given(userPort.checkExistingById(userId)).willReturn(true); + + EstateOwnership 소유1 = EstateOwnerShipFixtures.stub(userId, kaptCode1, LocalDateTime.now()); + EstateOwnership 소유2 = EstateOwnerShipFixtures.stub(userId, kaptCode2, LocalDateTime.now()); + + given(estateOwnerShipPort.loadMyOwnerships(userId)) + .willReturn(List.of(소유1, 소유2)); + + EstatePrice stub = EstatePriceFixtures.stub(kaptCode1); + EstatePrice stub2 = EstatePriceFixtures.stub(kaptCode2); + + given(estatePricePort.loadEstatePricesByCodes(List.of(kaptCode1, kaptCode2))) + .willReturn(List.of(stub, stub2)); + + // When + List result = sut.getMyEstatePrices(userId); + + // Then + then(result).hasSize(2) + .containsExactlyInAnyOrder(stub, stub2); + } + } + + @Nested + @DisplayName("예외 처리") + class ExceptionTest { + + @Test + @DisplayName("[error] 존재하지 않는 유저일 경우 예외를 던집니다.") + void throwException_whenUserNotFound() { + // Given + Long userId = 1L; + given(userPort.checkExistingById(userId)) + .willReturn(false); + + // When / Then + org.junit.jupiter.api.Assertions.assertThrows( + NoSuchElementException.class, + () -> sut.getFavoriteRegion(userId) + ); + } + } + +} diff --git a/src/test/java/com/zipte/platform/server/application/service/EstateOwnershipServiceTest.java b/src/test/java/com/zipte/platform/server/application/service/EstateOwnershipServiceTest.java index 08d3a43..8029617 100644 --- a/src/test/java/com/zipte/platform/server/application/service/EstateOwnershipServiceTest.java +++ b/src/test/java/com/zipte/platform/server/application/service/EstateOwnershipServiceTest.java @@ -8,7 +8,7 @@ import com.zipte.platform.server.application.service.exception.NotExistingEstateInYourAreaException; import com.zipte.platform.server.domain.estate.Estate; import com.zipte.platform.server.domain.estateOwnership.EstateOwnership; -import com.zipte.platform.server.domain.review.EstateFixtures; +import com.zipte.platform.server.domain.estate.EstateFixtures; import com.zipte.platform.server.domain.review.EstateOwnerShipFixtures; import org.junit.Assert; import org.junit.jupiter.api.DisplayName; diff --git a/src/test/java/com/zipte/platform/server/domain/estate/EstateFixtures.java b/src/test/java/com/zipte/platform/server/domain/estate/EstateFixtures.java new file mode 100644 index 0000000..a997638 --- /dev/null +++ b/src/test/java/com/zipte/platform/server/domain/estate/EstateFixtures.java @@ -0,0 +1,41 @@ +package com.zipte.platform.server.domain.estate; + +import java.util.Arrays; + +public class EstateFixtures { + + public static Estate stub() { + + Location location = Location.builder() + .type("Point") + .coordinates(Arrays.asList( + 127.1280, // 경도 + 37.4116) // 위도 + ) + .build(); + + return Estate.builder() + .kaptCode("kaptCode") + .location(location) + .build(); + } + + public static Estate stub(String kaptCode) { + + Location location = Location.builder() + .type("Point") + .coordinates(Arrays.asList( + 127.1280, // 경도 + 37.4116) // 위도 + ) + .build(); + + return Estate.builder() + .kaptCode(kaptCode) + .location(location) + .build(); + } + + + +} diff --git a/src/test/java/com/zipte/platform/server/domain/estate/EstatePriceFixtures.java b/src/test/java/com/zipte/platform/server/domain/estate/EstatePriceFixtures.java new file mode 100644 index 0000000..68ca46e --- /dev/null +++ b/src/test/java/com/zipte/platform/server/domain/estate/EstatePriceFixtures.java @@ -0,0 +1,18 @@ +package com.zipte.platform.server.domain.estate; + +public class EstatePriceFixtures { + + + public static EstatePrice stub(String kaptCode) { + + return EstatePrice.builder() + .id("id") + .kaptCode(kaptCode) + .kaptName("kaptName") + .exclusiveArea(0.0) + .floor(1) + .price("1000000") + .build(); + } + +} diff --git a/src/test/java/com/zipte/platform/server/domain/region/RegionPriceFixtures.java b/src/test/java/com/zipte/platform/server/domain/region/RegionPriceFixtures.java new file mode 100644 index 0000000..10fc588 --- /dev/null +++ b/src/test/java/com/zipte/platform/server/domain/region/RegionPriceFixtures.java @@ -0,0 +1,20 @@ +package com.zipte.platform.server.domain.region; + +import java.util.HashMap; +import java.util.Map; + +public class RegionPriceFixtures { + + public static RegionPrice stub(String region) { + Map averagePrices = new HashMap<>(); + averagePrices.put("15평 이하", 80000.0); + averagePrices.put("15~20평", 100000.0); + averagePrices.put("20~25평", 120000.0); + averagePrices.put("25~30평", 140000.0); + averagePrices.put("30평 이상", 160000.0); + + return RegionPrice.of(region, averagePrices); // 예: 분당구 코드 + } + +} + diff --git a/src/test/java/com/zipte/platform/server/domain/review/EstateFixtures.java b/src/test/java/com/zipte/platform/server/domain/review/EstateFixtures.java deleted file mode 100644 index f96afad..0000000 --- a/src/test/java/com/zipte/platform/server/domain/review/EstateFixtures.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.zipte.platform.server.domain.review; - -import com.zipte.platform.server.domain.estate.Estate; -import com.zipte.platform.server.domain.estate.Location; - -import java.util.Arrays; - -public class EstateFixtures { - - public static Estate stub() { - - Location location = Location.builder() - .type("Point") - .coordinates(Arrays.asList( - 127.1280, // 경도 - 37.4116) // 위도 - ) - .build(); - - return Estate.builder() - .kaptCode("kaptCode") - .location(location) - .build(); - } - -} From 08dfb81f1ae31b9953155084acf1eb42c6341122 Mon Sep 17 00:00:00 2001 From: eedo_y Date: Wed, 28 May 2025 02:27:22 +0900 Subject: [PATCH 06/10] =?UTF-8?q?=E2=9C=85test/ZIP-29=20:=20=EC=84=9C?= =?UTF-8?q?=EB=B9=84=EC=8A=A4=20=EC=BD=94=EB=93=9C=20=EC=A4=91=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/application/service/DashBoardServiceTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/zipte/platform/server/application/service/DashBoardServiceTest.java b/src/test/java/com/zipte/platform/server/application/service/DashBoardServiceTest.java index 1d23451..4a45ae0 100644 --- a/src/test/java/com/zipte/platform/server/application/service/DashBoardServiceTest.java +++ b/src/test/java/com/zipte/platform/server/application/service/DashBoardServiceTest.java @@ -185,8 +185,8 @@ void getFavoriteEstatePrices_success() { String kaptCode1 = "KaptCode1"; String kaptCode2 = "KaptCode2"; - Favorite apt1 = FavoriteFixtures.apartmentFavorite(userId, "AAPT1"); - Favorite apt2 = FavoriteFixtures.apartmentFavorite(userId, "AAPT2"); + Favorite apt1 = FavoriteFixtures.apartmentFavorite(userId, kaptCode1); + Favorite apt2 = FavoriteFixtures.apartmentFavorite(userId, kaptCode2); given(favoritePort.loadUserFavoriteByType(userId, FavoriteType.APARTMENT)) .willReturn(List.of(apt1, apt2)); @@ -194,7 +194,7 @@ void getFavoriteEstatePrices_success() { EstatePrice stub = EstatePriceFixtures.stub(kaptCode1); EstatePrice stub2 = EstatePriceFixtures.stub(kaptCode2); - given(estatePricePort.loadEstatePricesByCodes(List.of("AAPT1", "AAPT2"))) + given(estatePricePort.loadEstatePricesByCodes(List.of(kaptCode1, kaptCode2))) .willReturn(List.of(stub, stub2)); // When From a93fb89c99dc8a09a53c50364ff10f054ea9b138 Mon Sep 17 00:00:00 2001 From: eedo_y Date: Thu, 29 May 2025 19:01:46 +0900 Subject: [PATCH 07/10] =?UTF-8?q?=E2=9C=85=20test/ZIP-29=20:=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=ED=99=98=EA=B2=BD=20=EC=A3=BC=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zipte/platform/server/adapter/in/web/DashBoardApiTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/com/zipte/platform/server/adapter/in/web/DashBoardApiTest.java b/src/test/java/com/zipte/platform/server/adapter/in/web/DashBoardApiTest.java index 839f6d1..e77828a 100644 --- a/src/test/java/com/zipte/platform/server/adapter/in/web/DashBoardApiTest.java +++ b/src/test/java/com/zipte/platform/server/adapter/in/web/DashBoardApiTest.java @@ -22,6 +22,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; @@ -36,6 +37,7 @@ import java.util.*; @SpringBootTest +@ActiveProfiles("test") @AutoConfigureMockMvc(addFilters = false) class DashBoardApiTest { From 45e1040c0f9c1214a6a0729a32edca865eda95e8 Mon Sep 17 00:00:00 2001 From: eedo_y Date: Thu, 29 May 2025 21:01:54 +0900 Subject: [PATCH 08/10] =?UTF-8?q?=E2=9C=85=20test/ZIP-29=20:=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=9D=98=20=EB=B3=80=EC=88=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/EstateOwnershipServiceTest.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/zipte/platform/server/application/service/EstateOwnershipServiceTest.java b/src/test/java/com/zipte/platform/server/application/service/EstateOwnershipServiceTest.java index 8029617..b762c39 100644 --- a/src/test/java/com/zipte/platform/server/application/service/EstateOwnershipServiceTest.java +++ b/src/test/java/com/zipte/platform/server/application/service/EstateOwnershipServiceTest.java @@ -85,13 +85,19 @@ public void badRequest_code() { public void createOwnerShipBy1KM() { // Given - var request = createRequest(00.00, 00.00); + var request = createRequest(37.12345, 127.123456); - given(loadUserPort.checkExistingById(anyLong())).willReturn(true); + given(loadUserPort.checkExistingById(anyLong())) + .willReturn(true); - given(loadEstatePort.checkExistingByCode(any())).willReturn(true); + given(loadEstatePort.checkExistingByCode(any())) + .willReturn(true); + + given(port.loadOwnershipByUser(request.getUserId(), request.getKaptCode())) + .willReturn(false); + + Estate stub = EstateFixtures.stub(request.getKaptCode()); - Estate stub = EstateFixtures.stub(); given(loadEstatePort.loadEstatesNearBy(request.getLongitude(), request.getLatitude(), ONE_KM_IN_RADIANS)) .willReturn(List.of(stub)); From 01dab617439bfaca6a74d23654517ec7f90e0b24 Mon Sep 17 00:00:00 2001 From: eedo_y Date: Fri, 30 May 2025 16:21:42 +0900 Subject: [PATCH 09/10] =?UTF-8?q?=E2=9C=A8=20feat/ZIP-29=20:=20=EC=8A=A4?= =?UTF-8?q?=EC=9B=A8=EA=B1=B0=20=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/adapter/in/web/DashBoardApi.java | 3 +- .../in/web/swagger/DashBoardApiSpec.java | 59 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/zipte/platform/server/adapter/in/web/swagger/DashBoardApiSpec.java diff --git a/src/main/java/com/zipte/platform/server/adapter/in/web/DashBoardApi.java b/src/main/java/com/zipte/platform/server/adapter/in/web/DashBoardApi.java index e88f053..cdae0b8 100644 --- a/src/main/java/com/zipte/platform/server/adapter/in/web/DashBoardApi.java +++ b/src/main/java/com/zipte/platform/server/adapter/in/web/DashBoardApi.java @@ -3,6 +3,7 @@ import com.zipte.platform.core.response.ApiResponse; import com.zipte.platform.security.oauth2.domain.PrincipalDetails; import com.zipte.platform.server.adapter.in.web.dto.response.*; +import com.zipte.platform.server.adapter.in.web.swagger.DashBoardApiSpec; import com.zipte.platform.server.application.in.dashboard.DashBoardUseCase; import com.zipte.platform.server.domain.estate.Estate; import com.zipte.platform.server.domain.estate.EstatePrice; @@ -19,7 +20,7 @@ @RestController @RequestMapping("/api/v1/dashboard") @RequiredArgsConstructor -public class DashBoardApi { +public class DashBoardApi implements DashBoardApiSpec { private final DashBoardUseCase dashboardService; diff --git a/src/main/java/com/zipte/platform/server/adapter/in/web/swagger/DashBoardApiSpec.java b/src/main/java/com/zipte/platform/server/adapter/in/web/swagger/DashBoardApiSpec.java new file mode 100644 index 0000000..212088a --- /dev/null +++ b/src/main/java/com/zipte/platform/server/adapter/in/web/swagger/DashBoardApiSpec.java @@ -0,0 +1,59 @@ +package com.zipte.platform.server.adapter.in.web.swagger; + +import com.zipte.platform.core.response.ApiResponse; +import com.zipte.platform.security.oauth2.domain.PrincipalDetails; +import com.zipte.platform.server.adapter.in.web.dto.response.EstateDetailResponse; +import com.zipte.platform.server.adapter.in.web.dto.response.EstatePriceListResponse; +import com.zipte.platform.server.adapter.in.web.dto.response.RegionPriceResponse; +import com.zipte.platform.server.adapter.in.web.dto.response.RegionResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.core.annotation.AuthenticationPrincipal; + +import java.util.List; + +@Tag(name = "대시보드 API", description = "대시보드 관련 API") +public interface DashBoardApiSpec { + + @Operation( + summary = "나의 관심 지역 목록 조회", + description = "JWT 를 통해서 나의 관심 지역 목록을 조회합니다." + ) + ApiResponse> getMyRegion( + @AuthenticationPrincipal PrincipalDetails principalDetails); + + + @Operation( + summary = "나의 관심 지역 가격 조회", + description = "JWT 를 통해서 나의 관심 지역 가격을 조회합니다. (그래프 생성 데이터 전달)" + ) + ApiResponse> getMyRegionPrice( + @AuthenticationPrincipal PrincipalDetails principalDetails); + + + @Operation( + summary = "나의 관심 아파트 목록 조회", + description = "JWT 를 통해서 나의 관심 아파트 목록을 조회합니다." + ) + ApiResponse> getMyEstate( + @AuthenticationPrincipal PrincipalDetails principalDetails); + + + @Operation( + summary = "나의 관심 아파트 가격 조회", + description = "JWT 를 통해서 나의 관심 아파트 가격을 조회합니다. (그래프 생성 데이터 전달)" + ) + ApiResponse> getMyEstatePrice( + @AuthenticationPrincipal PrincipalDetails principalDetails); + + + + @Operation( + summary = "나의 아파트 조회", + description = "JWT 를 통해서 나의 거주 인증 아파트를 조회합니다. (그래프 생성 데이터 전달)" + ) + ApiResponse> getMyHomeEstate( + @AuthenticationPrincipal PrincipalDetails principalDetails); + + +} From 5a7bb8cb51d1e7cb20c3c5509c25b4b01bb1ed64 Mon Sep 17 00:00:00 2001 From: eedo_y Date: Fri, 30 May 2025 16:25:49 +0900 Subject: [PATCH 10/10] =?UTF-8?q?=E2=9C=A8=20feat/ZIP-8=20:=20=EC=84=B1?= =?UTF-8?q?=EB=8A=A5=20=ED=96=A5=EC=83=81=EC=9D=84=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=ED=8C=8C=EC=9D=B4=ED=94=84?= =?UTF-8?q?=EB=9D=BC=EC=9D=B8=20=EC=88=98=EC=A0=95=20-=20Gradle=20?= =?UTF-8?q?=EC=BA=90=EC=8B=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci-test.yml | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index d06da19..44f1691 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -74,10 +74,18 @@ jobs: echo "${{ secrets.APPLICATION_TEST_YML }}" > ./src/test/resources/application-test.yml - # 1-4. gradle 환경 설치 - - name: Setup Gradle - uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 - + # 1-4. 성능 향상을 위한 Gradle 캐싱 + - name: Gradle Caching + uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + gradle-${{ runner.os }} + + # 1-5. 테스트 컨테이너들 작동여부 체크 - name: MySQL 체크 run: | until nc -z localhost 3306; do @@ -100,11 +108,11 @@ jobs: sleep 3 done - # 1-5. 빌드 + # 2. 빌드 - name: Build with Gradle Wrapper run: ./gradlew clean build - ## 테스트 커버리지 + # 3. 테스트 커버리지 - name: Test Coverage Report id: jacoco uses: madrapps/jacoco-report@v1.2 @@ -116,7 +124,7 @@ jobs: min-coverage-overall: 0 debug-mode: true - # 7. JUnit 테스트 결과 게시 + # 4. JUnit 테스트 결과 게시 - name: Test 결과 출력 uses: EnricoMi/publish-unit-test-result-action@v2 if: always()