Skip to content

Commit

Permalink
점포 조회 3단계 구분 및 세부 구현 (#75)
Browse files Browse the repository at this point in the history
* 점포 조회 3단계 구분 및 세부 구현
- 1. 지도상 자신 주변의 점포 조회 (북마크 된 점포는 별도 아이콘 표시)
- 2. 지도상 점포 마커 클릭 시 간략 정보 조회 (/api/store/{id}/summary)
- 3. 점포 세부 조회

* 간략 정보 조회 수정

* 점포 상세 조회 수정
- 최신 리뷰 3개만 조회하도록 수정
- 리뷰 작성자의 프로필 사진 응답 추가
- 방문 성공, 실패 횟수 응답 추가
- 쿼리 최적화 필요(중요...)
  • Loading branch information
ysw789 authored Oct 6, 2024
1 parent 7381c91 commit cafda8b
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
import com.dongyang.dongpo.apiresponse.ApiResponse;
import com.dongyang.dongpo.domain.member.Member;
import com.dongyang.dongpo.dto.location.LatLong;
import com.dongyang.dongpo.dto.store.StoreDto;
import com.dongyang.dongpo.dto.store.StoreRegisterDto;
import com.dongyang.dongpo.dto.store.StoreUpdateDto;
import com.dongyang.dongpo.dto.store.*;
import com.dongyang.dongpo.service.store.StoreService;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
Expand All @@ -30,14 +28,21 @@ public class StoreController {

@GetMapping("")
@Operation(summary = "현재 위치 기준 주변 점포 조회")
public ResponseEntity<ApiResponse<List<StoreDto>>> getStoresByCurrentLocation(@ModelAttribute LatLong latLong) {
return ResponseEntity.ok(new ApiResponse<>(storeService.findStoresByCurrentLocation(latLong)));
public ResponseEntity<ApiResponse<List<StoreIndexDto>>> getStoresByCurrentLocation(@ModelAttribute LatLong latLong,
@AuthenticationPrincipal Member member) {
return ResponseEntity.ok(new ApiResponse<>(storeService.findStoresByCurrentLocation(latLong, member)));
}

@GetMapping("/{id}/summary")
@Operation(summary = "점포 간략 정보 조회")
public ResponseEntity<ApiResponse<StoreIndexDto>> getStoreSummary(@PathVariable Long id, @AuthenticationPrincipal Member member) {
return ResponseEntity.ok(new ApiResponse<>(storeService.getStoreSummary(id, member)));
}

@GetMapping("/{id}")
@Operation(summary = "점포 상세 조회")
public ResponseEntity<ApiResponse<StoreDto>> detailStore(@PathVariable Long id) throws Exception {
return ResponseEntity.ok(new ApiResponse<>(storeService.detailStore(id)));
public ResponseEntity<ApiResponse<StoreDto>> detailStore(@PathVariable Long id, @AuthenticationPrincipal Member member) {
return ResponseEntity.ok(new ApiResponse<>(storeService.detailStore(id, member)));
}

@PostMapping("")
Expand Down
49 changes: 43 additions & 6 deletions src/main/java/com/dongyang/dongpo/domain/store/Store.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
package com.dongyang.dongpo.domain.store;

import com.dongyang.dongpo.domain.member.Member;
import com.dongyang.dongpo.dto.store.OpenPossibility;
import com.dongyang.dongpo.dto.store.ReviewDto;
import com.dongyang.dongpo.dto.store.StoreDto;
import com.dongyang.dongpo.dto.store.StoreIndexDto;
import com.dongyang.dongpo.dto.store.StoreUpdateDto;
import com.dongyang.dongpo.dto.store.*;
import jakarta.persistence.*;
import lombok.*;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -70,6 +67,9 @@ public class Store {
@Builder.Default
private List<StoreReview> reviews = new ArrayList<>();

@OneToMany(mappedBy = "store", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<StoreVisitCert> storeVisitCerts = new ArrayList<>();

public enum StoreStatus {
ACTIVE, INACTIVE, HIDDEN, CLOSED
}
Expand Down Expand Up @@ -122,8 +122,32 @@ public StoreIndexDto toIndexResponse() {
.registerDate(registerDate)
.build();
}

public StoreIndexDto toIndexResponse(OpenPossibility openPossibility, Boolean isBookmarked, List<String> reviewPics) {
return StoreIndexDto.builder()
.id(id)
.name(name)
.address(address)
.status(status)
.openPossibility(openPossibility)
.isBookmarked(isBookmarked)
.reviewPics(reviewPics)
.build();
}

public StoreIndexDto toIndexResponse(Boolean isBookmarked, OpenPossibility openPossibility) {
return StoreIndexDto.builder()
.id(id)
.name(name)
.latitude(latitude)
.longitude(longitude)
.status(status)
.openPossibility(openPossibility)
.isBookmarked(isBookmarked)
.build();
}

public StoreDto toResponse(OpenPossibility openPossibility) {
public StoreDto toResponse(OpenPossibility openPossibility, boolean isBookmarked) {
List<Store.OperatingDay> operatingDayValues = this.storeOperatingDays.stream()
.map(StoreOperatingDay::getOperatingDay)
.collect(Collectors.toList());
Expand All @@ -133,9 +157,19 @@ public StoreDto toResponse(OpenPossibility openPossibility) {
.collect(Collectors.toList());

List<ReviewDto> reviewDtos = this.reviews.stream()
.sorted(Comparator.comparingLong(StoreReview::getId).reversed())
.map(StoreReview::toResponse)
.limit(3)
.toList();

Long visitSuccessfulCount = storeVisitCerts.stream()
.filter(StoreVisitCert::getIsVisitSuccessful)
.count();

Long visitFailCount = storeVisitCerts.stream()
.filter(cert -> !cert.getIsVisitSuccessful())
.count();

return StoreDto.builder()
.id(id)
.name(name)
Expand All @@ -152,6 +186,9 @@ public StoreDto toResponse(OpenPossibility openPossibility) {
.status(status)
.reviews(reviewDtos)
.openPossibility(openPossibility)
.isBookmarked(isBookmarked)
.visitSuccessfulCount(visitSuccessfulCount)
.visitFailCount(visitFailCount)
.build();
}

Expand Down
14 changes: 10 additions & 4 deletions src/main/java/com/dongyang/dongpo/domain/store/StoreReview.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import lombok.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
Expand All @@ -31,9 +33,6 @@ public class StoreReview {
@Column(columnDefinition = "TEXT")
private String text;

@Column(length = 128)
private String reviewPic;

@Column(columnDefinition = "DATETIME DEFAULT CURRENT_TIMESTAMP")
@Builder.Default
private LocalDateTime registerDate = LocalDateTime.now();
Expand All @@ -49,19 +48,26 @@ public class StoreReview {
@Builder.Default
private Integer reportCount = 0;

@OneToMany(mappedBy = "reviewId", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@Builder.Default
private List<StoreReviewPic> reviewPics = new ArrayList<>();

public enum ReviewStatus {
VISIBLE, HIDDEN, DELETED
}

public ReviewDto toResponse(){
List<String> reviewOnlyPic = reviewPics.stream().map(StoreReviewPic::getPicUrl).toList();

return ReviewDto.builder()
.id(id)
.registerDate(registerDate)
.reviewStar(reviewStar)
.text(text)
.memberId(member.getId())
.memberProfilePic(member.getProfilePic())
.storeId(store.getId())
.reviewPic(reviewPic)
.reviewPics(reviewOnlyPic)
.build();
}

Expand Down
10 changes: 7 additions & 3 deletions src/main/java/com/dongyang/dongpo/dto/store/ReviewDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import com.dongyang.dongpo.domain.member.Member;
import com.dongyang.dongpo.domain.store.Store;
import com.dongyang.dongpo.domain.store.StoreReview;
import com.dongyang.dongpo.domain.store.StoreReviewPic;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;

@Data
@Builder
Expand All @@ -20,9 +22,10 @@ public class ReviewDto {
private Long id;
private Long storeId;
private Long memberId;
private String memberProfilePic;
private Integer reviewStar;
private String text;
private String reviewPic;
private List<String> reviewPics;
private LocalDateTime registerDate;
private StoreReview.ReviewStatus status;
private Integer reportCount;
Expand All @@ -33,19 +36,20 @@ public StoreReview toEntity(Store store, Member member){
.member(member)
.store(store)
.text(text)
.reviewPic(reviewPic)
.reviewStar(reviewStar)
.build();
}

public static ReviewDto toDto(StoreReview storeReview){
List<String> picUrlList = storeReview.getReviewPics().stream().map(StoreReviewPic::getPicUrl).toList();

return ReviewDto.builder()
.id(storeReview.getId())
.storeId(storeReview.getStore().getId())
.memberId(storeReview.getMember().getId())
.reviewStar(storeReview.getReviewStar())
.text(storeReview.getText())
.reviewPic(storeReview.getReviewPic())
.reviewPics(picUrlList)
.registerDate(storeReview.getRegisterDate())
.status(storeReview.getStatus())
.reportCount(storeReview.getReportCount())
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/dongyang/dongpo/dto/store/StoreDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,7 @@ public class StoreDto {
private List<Store.PayMethod> payMethods;
private List<ReviewDto> reviews;
private OpenPossibility openPossibility;
private Boolean isBookmarked;
private Long visitSuccessfulCount;
private Long visitFailCount;
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.dongyang.dongpo.dto.store;

import com.dongyang.dongpo.domain.store.Store;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;

@Data
@Builder
Expand All @@ -16,6 +18,12 @@
public class StoreIndexDto {
private Long id;
private String name;
private Double latitude;
private Double longitude;
private String address;
private LocalDateTime registerDate;
private Store.StoreStatus status;
private OpenPossibility openPossibility;
private Boolean isBookmarked;
private List<String> reviewPics;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


import com.dongyang.dongpo.domain.member.Member;
import com.dongyang.dongpo.domain.store.Store;
import com.dongyang.dongpo.domain.store.StoreBookmark;
import org.springframework.data.jpa.repository.JpaRepository;

Expand All @@ -11,4 +12,6 @@ public interface BookmarkRepository extends JpaRepository<StoreBookmark, Long> {
List<StoreBookmark> findByMemberId(Long id);

List<StoreBookmark> findByMember(Member member);

boolean existsByStoreAndMember(Store store, Member member);
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,8 @@ public void deleteBookmark(Long id, Member member) {
bookmarkRepository.delete(bookmark);
log.info("Member Id : {} is Delete Bookmark Id : {}", member.getId(), id);
}

public boolean isStoreBookmarkedByMember(Store store, Member member) {
return bookmarkRepository.existsByStoreAndMember(store, member);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.dongyang.dongpo.domain.member.Title;
import com.dongyang.dongpo.domain.store.Store;
import com.dongyang.dongpo.domain.store.StoreReview;
import com.dongyang.dongpo.domain.store.StoreReviewPic;
import com.dongyang.dongpo.dto.store.ReviewDto;
import com.dongyang.dongpo.exception.CustomException;
import com.dongyang.dongpo.exception.ErrorCode;
Expand All @@ -17,6 +18,8 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Transactional(readOnly = true)
Expand Down Expand Up @@ -61,4 +64,12 @@ public ReviewDto findOne(Long id){

return review.toResponse();
}

public List<String> getReviewPicsByStoreId(Long id) {
return reviewRepository.findByStoreId(id).stream()
.flatMap(storeReview -> storeReview.getReviewPics().stream())
.map(StoreReviewPic::getPicUrl)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
}
39 changes: 30 additions & 9 deletions src/main/java/com/dongyang/dongpo/service/store/StoreService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.dongyang.dongpo.domain.store.Store;
import com.dongyang.dongpo.domain.store.StoreOperatingDay;
import com.dongyang.dongpo.domain.store.StorePayMethod;
import com.dongyang.dongpo.dto.bookmark.BookmarkDto;
import com.dongyang.dongpo.dto.location.CoordinateRange;
import com.dongyang.dongpo.dto.location.LatLong;
import com.dongyang.dongpo.dto.store.*;
Expand All @@ -13,6 +14,7 @@
import com.dongyang.dongpo.repository.store.StoreOperatingDayRepository;
import com.dongyang.dongpo.repository.store.StorePayMethodRepository;
import com.dongyang.dongpo.repository.store.StoreRepository;
import com.dongyang.dongpo.service.bookmark.BookmarkService;
import com.dongyang.dongpo.service.location.LocationService;
import com.dongyang.dongpo.service.open.OpenPossibilityService;
import com.dongyang.dongpo.service.title.TitleService;
Expand All @@ -24,6 +26,7 @@

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
Expand All @@ -37,6 +40,8 @@ public class StoreService {
private final LocationService locationService;
private final TitleService titleService;
private final OpenPossibilityService openPossibilityService;
private final BookmarkService bookmarkService;
private final StoreReviewService storeReviewService;


@Transactional
Expand Down Expand Up @@ -80,22 +85,38 @@ public List<StoreDto> findAll() {
return storeResponse;
}

public List<StoreDto> findStoresByCurrentLocation(LatLong latLong) {
public List<StoreIndexDto> findStoresByCurrentLocation(LatLong latLong, Member member) {
CoordinateRange coordinateRange = locationService.calcCoordinateRangeByCurrentLocation(latLong);

List<StoreDto> stores = new ArrayList<>();
for (Store store : storeRepository.findStoresWithinRange(coordinateRange.getMinLat(), coordinateRange.getMaxLat(),
coordinateRange.getMinLong(), coordinateRange.getMaxLong())
) stores.add(store.toResponse());
return stores;
List<BookmarkDto> myBookmarks = bookmarkService.getMyBookmarks(member);

return storeRepository.findStoresWithinRange(coordinateRange.getMinLat(), coordinateRange.getMaxLat(),
coordinateRange.getMinLong(), coordinateRange.getMaxLong())
.stream()
.map(store -> {
boolean isBookmarked = myBookmarks.stream()
.anyMatch(bookmark -> store.getId().equals(bookmark.getStoreId()));

return store.toIndexResponse(isBookmarked, openPossibilityService.getOpenPossibility(store));
})
.collect(Collectors.toList());
}

public StoreIndexDto getStoreSummary(Long id, Member member) {
Store store = storeRepository.findById(id)
.orElseThrow(() -> new CustomException(ErrorCode.STORE_NOT_FOUND));

return store.toIndexResponse(openPossibilityService.getOpenPossibility(store),
bookmarkService.isStoreBookmarkedByMember(store, member),
storeReviewService.getReviewPicsByStoreId(id));
}

public StoreDto detailStore(Long id) {
public StoreDto detailStore(Long id, Member member) {
Store store = storeRepository.findById(id)
.orElseThrow(() -> new CustomException(ErrorCode.STORE_NOT_FOUND));
OpenPossibility openPossibility = openPossibilityService.getOpenPossibility(store);

return store.toResponse(openPossibility);
return store.toResponse(openPossibilityService.getOpenPossibility(store),
bookmarkService.isStoreBookmarkedByMember(store, member));
}

@Transactional
Expand Down
Loading

0 comments on commit cafda8b

Please sign in to comment.