From 92662cc514b4fee4be26752cc3e5f6d488e49ca5 Mon Sep 17 00:00:00 2001 From: Jihun Kim Date: Tue, 22 Jul 2025 15:18:56 +0900 Subject: [PATCH 1/7] =?UTF-8?q?chore:=20=EB=9D=84=EC=96=B4=EC=93=B0?= =?UTF-8?q?=EA=B8=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/nowait/applicationuser/config/security/CorsConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/config/security/CorsConfig.java b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/config/security/CorsConfig.java index f437ea21..97b483c9 100644 --- a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/config/security/CorsConfig.java +++ b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/config/security/CorsConfig.java @@ -15,7 +15,7 @@ public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); // 쿠키나 인증헤더 자격증명 허용 - config.setAllowedOrigins(List.of("http://localhost:5173","http://localhost:63342")); // 허용할 출처 설정 + config.setAllowedOrigins(List.of("http://localhost:5173", "http://localhost:63342")); // 허용할 출처 설정 config.setAllowedMethods(List.of("GET", "POST", "PATCH", "PUT", "DELETE", "OPTIONS")); // 메서드 허용 config.setAllowedHeaders(List.of("*")); //클라이언트가 보낼 수 있는 헤더 config.setExposedHeaders(List.of("Authorization")); //클라이언트(브라우저)가 접근할 수 있는 헤더 지정 From ab1b4fa6741ab89af50ad0e3437f7f144c46ca09 Mon Sep 17 00:00:00 2001 From: Jihun Kim Date: Tue, 22 Jul 2025 15:19:18 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat(Department):=20DepartmentRepository=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../department/repository/DepartmentRepository.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/department/repository/DepartmentRepository.java diff --git a/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/department/repository/DepartmentRepository.java b/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/department/repository/DepartmentRepository.java new file mode 100644 index 00000000..023d2409 --- /dev/null +++ b/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/department/repository/DepartmentRepository.java @@ -0,0 +1,10 @@ +package com.nowait.domaincorerdb.department.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.nowait.domaincorerdb.department.entity.Department; + +@Repository +public interface DepartmentRepository extends JpaRepository { +} From ee2d193f95ef7316be90b62d05c3e5c5319d646b Mon Sep 17 00:00:00 2001 From: Jihun Kim Date: Tue, 22 Jul 2025 15:19:38 +0900 Subject: [PATCH 3/7] =?UTF-8?q?feat(Department):=20DepartmentName=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=ED=95=9C=20Dto=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/StoreDepartmentReadResponse.java | 23 ++++++++ .../store/dto/StorePageReadDto.java | 54 +++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/dto/StoreDepartmentReadResponse.java create mode 100644 nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/dto/StorePageReadDto.java diff --git a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/dto/StoreDepartmentReadResponse.java b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/dto/StoreDepartmentReadResponse.java new file mode 100644 index 00000000..fe04584f --- /dev/null +++ b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/dto/StoreDepartmentReadResponse.java @@ -0,0 +1,23 @@ +package com.nowait.applicationuser.store.dto; + +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@AllArgsConstructor +@Builder +public class StoreDepartmentReadResponse { + + private List storePageReadDtos; + private boolean hasNext; + + public static StoreDepartmentReadResponse of(List storePageReadDtos, boolean hasNext) { + return StoreDepartmentReadResponse.builder() + .storePageReadDtos(storePageReadDtos) + .hasNext(hasNext) + .build(); + } +} diff --git a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/dto/StorePageReadDto.java b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/dto/StorePageReadDto.java new file mode 100644 index 00000000..050cc091 --- /dev/null +++ b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/dto/StorePageReadDto.java @@ -0,0 +1,54 @@ +package com.nowait.applicationuser.store.dto; + +import java.time.LocalDateTime; +import java.util.List; + +import com.nowait.domaincorerdb.store.entity.ImageType; +import com.nowait.domaincorerdb.store.entity.Store; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@AllArgsConstructor +@Builder +public class StorePageReadDto { + private Long storeId; + private Long departmentId; + private String departmentName; + private String name; + private String location; + private String description; + private StoreImageUploadResponse profileImage; + private List bannerImages; + private Boolean isActive; + private Boolean deleted; + private LocalDateTime createdAt; + + public static StorePageReadDto fromEntity(Store store, List allImages, String departmentName) { + + StoreImageUploadResponse profile = allImages.stream() + .filter(image -> image.getImageType() == ImageType.PROFILE) + .findFirst() + .orElse(null); + + List banners = allImages.stream() + .filter(image -> image.getImageType() == ImageType.BANNER) + .toList(); + + return StorePageReadDto.builder() + .createdAt(store.getCreatedAt()) + .storeId(store.getStoreId()) + .departmentId(store.getDepartmentId()) + .departmentName(departmentName) + .name(store.getName()) + .location(store.getLocation()) + .description(store.getDescription()) + .isActive(store.getIsActive()) + .deleted(store.getDeleted()) + .profileImage(profile) + .bannerImages(banners) + .build(); + } +} From 4ad97a354e094d1558a61790ac0af17765f2f826 Mon Sep 17 00:00:00 2001 From: Jihun Kim Date: Tue, 22 Jul 2025 15:20:29 +0900 Subject: [PATCH 4/7] =?UTF-8?q?feat(Department):=20=EC=A3=BC=EC=A0=90=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=97=94=EB=93=9C=ED=8F=AC=EC=9D=B8?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/controller/StoreController.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/controller/StoreController.java b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/controller/StoreController.java index f1dbc8d2..b39a53a8 100644 --- a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/controller/StoreController.java +++ b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/controller/StoreController.java @@ -46,6 +46,22 @@ public ResponseEntity getAllStores() { description = "모든 주점을 페이지네이션으로 조회합니다." ) @ApiResponse(responseCode = "200", description = "모든 주점 페이지네이션 조회 성공") + public ResponseEntity getAllStoresByPageAndDeparments(Pageable pageable) { + return ResponseEntity + .ok() + .body( + ApiUtils.success( + storeService.getAllStoresByPageAndDeparments(pageable) + ) + ); + } + + @GetMapping("/low-wait/infinite-scroll") + @Operation( + summary = "모든 주점 페이지네이션 조회", + description = "모든 주점을 페이지네이션으로 조회합니다." + ) + @ApiResponse(responseCode = "200", description = "모든 주점 페이지네이션 조회 성공") public ResponseEntity getAllStores(Pageable pageable) { return ResponseEntity .ok() From a8f91ce77bb4cc960b3c8957d56d014995739f59 Mon Sep 17 00:00:00 2001 From: Jihun Kim Date: Tue, 22 Jul 2025 15:20:46 +0900 Subject: [PATCH 5/7] =?UTF-8?q?feat(Department):=20findByStore=5FStoreIdIn?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domaincorerdb/store/repository/StoreImageRepository.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/repository/StoreImageRepository.java b/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/repository/StoreImageRepository.java index 1ad6929e..45639941 100644 --- a/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/repository/StoreImageRepository.java +++ b/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/repository/StoreImageRepository.java @@ -15,5 +15,7 @@ public interface StoreImageRepository extends JpaRepository { List findByStore(Store store); + List findByStore_StoreIdIn(List storeIds); + Optional findByStoreStoreIdAndImageType(Long storeId, ImageType imageType); } From 72f5aec04b9c8acd039bad97369eb522387b6a3d Mon Sep 17 00:00:00 2001 From: Jihun Kim Date: Tue, 22 Jul 2025 15:21:10 +0900 Subject: [PATCH 6/7] =?UTF-8?q?feat(StoreImage):=20StoreImageUploadRespons?= =?UTF-8?q?e=20storeId=20=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../applicationuser/store/dto/StoreImageUploadResponse.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/dto/StoreImageUploadResponse.java b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/dto/StoreImageUploadResponse.java index 62822b3d..39dbf2a0 100644 --- a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/dto/StoreImageUploadResponse.java +++ b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/dto/StoreImageUploadResponse.java @@ -10,12 +10,14 @@ @Builder public class StoreImageUploadResponse { private final Long id; + private final Long storeId; private final String imageUrl; private final ImageType imageType; public static StoreImageUploadResponse fromEntity(StoreImage storeImage) { return StoreImageUploadResponse.builder() .id(storeImage.getId()) + .storeId(storeImage.getStore().getStoreId()) .imageUrl(storeImage.getImageUrl()) .imageType(storeImage.getImageType()) .build(); From 717cf65e8853ff88016e27e49e72bb1f8ae49e38 Mon Sep 17 00:00:00 2001 From: Jihun Kim Date: Tue, 22 Jul 2025 15:25:33 +0900 Subject: [PATCH 7/7] =?UTF-8?q?feat(Store):=20=EC=A3=BC=EC=A0=90=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=20=EC=A1=B0=ED=9A=8C=20N+1=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/service/StoreService.java | 6 +- .../store/service/StoreServiceImpl.java | 96 +++++++++++++++++-- 2 files changed, 95 insertions(+), 7 deletions(-) diff --git a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/service/StoreService.java b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/service/StoreService.java index f8c854ad..f8bf540a 100644 --- a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/service/StoreService.java +++ b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/service/StoreService.java @@ -4,6 +4,8 @@ import org.springframework.data.domain.Pageable; +import com.nowait.applicationuser.store.dto.StoreDepartmentReadResponse; +import com.nowait.applicationuser.store.dto.StorePageReadDto; import com.nowait.applicationuser.store.dto.StoreReadDto; import com.nowait.applicationuser.store.dto.StoreReadResponse; @@ -13,8 +15,10 @@ public interface StoreService { StoreReadResponse getAllStoresByPage(Pageable pageable); + StoreDepartmentReadResponse getAllStoresByPageAndDeparments(Pageable pageable); + StoreReadDto getStoreByStoreId(Long storeId); - List searchStoresByName(String name); + List searchStoresByName(String name); } diff --git a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/service/StoreServiceImpl.java b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/service/StoreServiceImpl.java index 39e94c03..566e91ea 100644 --- a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/service/StoreServiceImpl.java +++ b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/store/service/StoreServiceImpl.java @@ -1,15 +1,21 @@ package com.nowait.applicationuser.store.service; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.nowait.applicationuser.store.dto.StoreDepartmentReadResponse; import com.nowait.applicationuser.store.dto.StoreImageUploadResponse; +import com.nowait.applicationuser.store.dto.StorePageReadDto; import com.nowait.applicationuser.store.dto.StoreReadDto; import com.nowait.applicationuser.store.dto.StoreReadResponse; +import com.nowait.domaincorerdb.department.entity.Department; +import com.nowait.domaincorerdb.department.repository.DepartmentRepository; import com.nowait.domaincorerdb.store.entity.Store; import com.nowait.domaincorerdb.store.entity.StoreImage; import com.nowait.domaincorerdb.store.exception.StoreNotFoundException; @@ -25,6 +31,7 @@ public class StoreServiceImpl implements StoreService { private final StoreRepository storeRepository; private final StoreImageRepository storeImageRepository; + private final DepartmentRepository departmentRepository; @Override @@ -67,6 +74,55 @@ public StoreReadResponse getAllStoresByPage(Pageable pageable) { return StoreReadResponse.of(storeRead, hasNext); } + @Override + @Transactional(readOnly = true) + public StoreDepartmentReadResponse getAllStoresByPageAndDeparments(Pageable pageable) { + // 1) 페이징된 Store 스냅샷 조회 + Slice slice = storeRepository.findAllByDeletedFalseOrderByStoreIdAsc(pageable); + List stores = slice.getContent(); + + // 2) 각 StoreId / Department ID 추출 + List storeIds = stores.stream() + .map(Store::getStoreId) + .toList(); + List deptIds = stores.stream() + .map(Store::getDepartmentId) + .distinct() + .toList(); + + // 3) 각 StoreId에 해당하는 이미지 조회 + List allImages = storeImageRepository.findByStore_StoreIdIn(storeIds); + Map> imageMap = allImages.stream() + .map(StoreImageUploadResponse::fromEntity) + .collect(Collectors.groupingBy( + StoreImageUploadResponse::getStoreId + )); + + + // 4) 각 DepartmentId에 해당하는 이름 조회 + List allDepts = departmentRepository.findAllById(deptIds); + Map deptNameMap = allDepts.stream() + .collect(Collectors.toMap( + Department::getId, + Department::getName + )); + + // 5) Dto 매핑 + List content = stores.stream() + .map(store -> { + List imgs = imageMap + .getOrDefault(store.getStoreId(), List.of()); + String departmentName = deptNameMap + .getOrDefault(store.getDepartmentId(), "Unknown Department"); + return StorePageReadDto.fromEntity(store, imgs, departmentName); + }) + .toList(); + + boolean hasNext = slice.hasNext(); + + return StoreDepartmentReadResponse.of(content, hasNext); + } + @Override @Transactional(readOnly = true) public StoreReadDto getStoreByStoreId(Long storeId) { @@ -84,19 +140,47 @@ public StoreReadDto getStoreByStoreId(Long storeId) { } @Override - public List searchStoresByName(String name) { + public List searchStoresByName(String name) { if (name == null || name.isBlank()) { throw new StoreParamEmptyException(); } + // 1) 페이징된 Store 스냅샷 조회 List stores = storeRepository.findByNameContainingIgnoreCaseAndDeletedFalse(name); + + // 2) 각 StoreId / Department ID 추출 + List storeIds = stores.stream() + .map(Store::getStoreId) + .toList(); + List deptIds = stores.stream() + .map(Store::getDepartmentId) + .distinct() + .toList(); + + // 3) 각 StoreId에 해당하는 이미지 조회 + List allImages = storeImageRepository.findByStore_StoreIdIn(storeIds); + Map> imageMap = allImages.stream() + .map(StoreImageUploadResponse::fromEntity) + .collect(Collectors.groupingBy( + StoreImageUploadResponse::getStoreId + )); + + // 4) 각 DepartmentId에 해당하는 이름 조회 + List allDepts = departmentRepository.findAllById(deptIds); + Map deptNameMap = allDepts.stream() + .collect(Collectors.toMap( + Department::getId, + Department::getName + )); + + // 5) Dto 매핑 return stores.stream() .map(store -> { - List images = storeImageRepository.findByStore(store); - List imageDto = images.stream() - .map(StoreImageUploadResponse::fromEntity) - .toList(); - return StoreReadDto.fromEntity(store, imageDto); + List imgs = imageMap + .getOrDefault(store.getStoreId(), List.of()); + String departmentName = deptNameMap + .getOrDefault(store.getDepartmentId(), "Unknown Department"); + return StorePageReadDto.fromEntity(store, imgs, departmentName); }) .toList(); }