refactor(customer-vue, store-service): 즐겨찾기 매장 조회

- 즐겨찾기 매장 조회
- 즐겨찾기 테스트 데이터
- 페이지 라우팅 체크 로직
This commit is contained in:
hoon7566
2022-03-07 13:45:51 +09:00
parent 624c02905d
commit d2b32078d3
14 changed files with 266 additions and 43 deletions

View File

@@ -1,5 +1,7 @@
package com.justpickup.storeservice;
import com.justpickup.storeservice.domain.favoritestore.entity.FavoriteStore;
import com.justpickup.storeservice.domain.favoritestore.repository.FavoriteStoreRepository;
import com.justpickup.storeservice.domain.map.entity.Map;
import com.justpickup.storeservice.domain.store.entity.Store;
import com.justpickup.storeservice.domain.store.repository.StoreRepository;
@@ -22,7 +24,7 @@ public class StoreServiceApplication {
}
@Bean
CommandLineRunner run(StoreRepository storeRepository) {
CommandLineRunner run(StoreRepository storeRepository, FavoriteStoreRepository favoriteStoreRepository) {
return args -> {
List<Store> stores = new ArrayList<>();
@@ -63,6 +65,14 @@ public class StoreServiceApplication {
);
storeRepository.saveAll(stores);
List<Long> userList = List.of(1L,2L,3L,4L,5L,6L,7L);
userList.forEach(userId -> {
stores.forEach(store -> {
favoriteStoreRepository.save(FavoriteStore.of(userId, store));
});
});
};
}
}

View File

@@ -2,9 +2,7 @@ package com.justpickup.storeservice.domain.favoritestore.entity;
import com.justpickup.storeservice.domain.store.entity.Store;
import com.justpickup.storeservice.global.entity.BaseEntity;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.*;
import javax.persistence.*;
@@ -25,4 +23,11 @@ public class FavoriteStore extends BaseEntity {
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "store_id")
private Store store;
public static FavoriteStore of(Long userId , Store store){
FavoriteStore favoriteStore = new FavoriteStore();
favoriteStore.userId = userId;
favoriteStore.store = store;
return favoriteStore;
}
}

View File

@@ -0,0 +1,7 @@
package com.justpickup.storeservice.domain.favoritestore.repository;
import com.justpickup.storeservice.domain.favoritestore.entity.FavoriteStore;
import org.springframework.data.jpa.repository.JpaRepository;
public interface FavoriteStoreRepository extends JpaRepository<FavoriteStore,Long> {
}

View File

@@ -1,6 +1,7 @@
package com.justpickup.storeservice.domain.store.entity;
import com.justpickup.storeservice.domain.category.entity.Category;
import com.justpickup.storeservice.domain.favoritestore.entity.FavoriteStore;
import com.justpickup.storeservice.domain.item.entity.Item;
import com.justpickup.storeservice.domain.map.entity.Map;
import com.justpickup.storeservice.global.entity.Address;
@@ -52,6 +53,8 @@ public class Store extends BaseEntity {
@OneToMany(mappedBy = "store")
private List<Item> items;
@OneToMany(mappedBy = "store")
private List<FavoriteStore> favoriteStores;
// == 연관관계 편의 메소드 == //
public void addCategory(Category category) {
categories.add(category);

View File

@@ -1,5 +1,7 @@
package com.justpickup.storeservice.domain.store.repository;
import com.justpickup.storeservice.domain.favoritestore.entity.FavoriteStore;
import com.justpickup.storeservice.domain.favoritestore.entity.QFavoriteStore;
import com.justpickup.storeservice.domain.store.dto.SearchStoreCondition;
import com.justpickup.storeservice.domain.store.dto.SearchStoreResult;
import com.querydsl.core.types.Expression;
@@ -28,25 +30,8 @@ public class StoreRepositoryCustom {
private final JPAQueryFactory queryFactory;
public SliceImpl<SearchStoreResult> findSearchStoreScroll(SearchStoreCondition condition, Pageable pageable) {
Expression<Double> latitude = Expressions.constant(condition.getLatitude());
Expression<Double> longitude = Expressions.constant(condition.getLongitude());
NumberExpression<Double> haversineDistance = getHaversineDistance(condition.getLatitude(),condition.getLongitude());
NumberPath<Double> distanceAlias = Expressions.numberPath(Double.class, "distance");
int earthRadius = 6371;
NumberExpression<Double> haversineDistance = acos(
cos(radians(latitude))
.multiply(cos(radians(store.map.latitude)))
.multiply(
cos(radians(store.map.longitude)
.subtract(radians(longitude)))
)
.add(
sin(radians(latitude))
.multiply(sin(radians(store.map.latitude)))
)
)
.multiply(Expressions.constant(earthRadius * 1000));
List<SearchStoreResult> content = queryFactory.select(
Projections.constructor(SearchStoreResult.class,
@@ -77,4 +62,47 @@ public class StoreRepositoryCustom {
return storeName == null ? null : store.name.contains(storeName);
}
public List<SearchStoreResult> findFavoriteStore(SearchStoreCondition condition,Long userId){
NumberExpression<Double> haversineDistance = getHaversineDistance(condition.getLatitude(),condition.getLongitude());
NumberPath<Double> distanceAlias = Expressions.numberPath(Double.class, "distance");
List<SearchStoreResult> content = queryFactory.select(
Projections.constructor(SearchStoreResult.class,
store.id,
store.name,
haversineDistance.as(distanceAlias))
)
.from(store)
.join(store.map)
.join(store.favoriteStores, QFavoriteStore.favoriteStore)
.on(QFavoriteStore.favoriteStore.userId.eq(userId))
.orderBy(distanceAlias.asc())
.fetch();
return content;
}
private NumberExpression<Double> getHaversineDistance (double SearchLatitude, double SearchLongitude){
Expression<Double> latitude = Expressions.constant(SearchLatitude);
Expression<Double> longitude = Expressions.constant(SearchLongitude);
int earthRadius = 6371;
NumberExpression<Double> haversineDistance = acos(
cos(radians(latitude))
.multiply(cos(radians(store.map.latitude)))
.multiply(
cos(radians(store.map.longitude)
.subtract(radians(longitude)))
)
.add(
sin(radians(latitude))
.multiply(sin(radians(store.map.latitude)))
)
)
.multiply(Expressions.constant(earthRadius * 1000));
return haversineDistance;
}
}

View File

@@ -5,6 +5,9 @@ import com.justpickup.storeservice.domain.store.dto.SearchStoreResult;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.SliceImpl;
import java.util.List;
public interface StoreService {
SliceImpl<SearchStoreResult> findSearchStoreScroll(SearchStoreCondition condition, Pageable pageable);
List<SearchStoreResult> findFavoriteStore(SearchStoreCondition condition, Long userId);
}

View File

@@ -8,6 +8,8 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.SliceImpl;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@RequiredArgsConstructor
public class StoreServiceImpl implements StoreService {
@@ -18,4 +20,9 @@ public class StoreServiceImpl implements StoreService {
public SliceImpl<SearchStoreResult> findSearchStoreScroll(SearchStoreCondition condition, Pageable pageable) {
return storeRepositoryCustom.findSearchStoreScroll(condition, pageable);
}
@Override
public List<SearchStoreResult> findFavoriteStore(SearchStoreCondition condition, Long userId) {
return storeRepositoryCustom.findFavoriteStore(condition,userId);
}
}

View File

@@ -0,0 +1,63 @@
package com.justpickup.storeservice.domain.store.web;
import com.justpickup.storeservice.domain.store.dto.SearchStoreCondition;
import com.justpickup.storeservice.domain.store.dto.SearchStoreResult;
import com.justpickup.storeservice.domain.store.service.StoreService;
import com.justpickup.storeservice.global.dto.Result;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.SliceImpl;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@Slf4j
@RequestMapping("api/customer/store")
@RequiredArgsConstructor
public class StoreCustomerApiController {
private final StoreService storeService;
@GetMapping("/favorite")
public ResponseEntity getFavoriteStore(@Valid SearchStoreCondition condition,
@RequestHeader(value = "user-id") String userId){
List<SearchStoreResult> favoriteStore = storeService.findFavoriteStore(condition,Long.parseLong(userId));
List<StoreCustomerApiController.SearchStoreResponse> searchStoreResponse
= favoriteStore.stream().map(SearchStoreResponse::new).collect(Collectors.toList());
return ResponseEntity.status(HttpStatus.OK).body(Result.createSuccessResult(searchStoreResponse));
}
@Data @NoArgsConstructor
static class SearchStoreResponse {
private Long id;
private String name;
private String distance;
public SearchStoreResponse(SearchStoreResult storeResult) {
this.id = storeResult.getStoreId();
this.name = storeResult.getStoreName();
this.distance = storeResult.convertDistanceToString();
}
}
}