Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.time.LocalDateTime;
@Repository
public interface MenuRepository extends JpaRepository<Menu, Long> {
// BoundingBox 안에 존재하는 모든 메뉴 반환
@Query(value = """
SELECT m.* FROM menus m
JOIN stores s ON m.store_id = s.store_id
Expand All @@ -28,12 +29,20 @@ List<Menu> findNearbyMenus(
@Param("maxLng") double maxLng
);

// 해당 가게에서 판매 하는 메뉴 반환
@Query("""
SELECT m FROM Menu m
JOIN FETCH m.store s
WHERE s.id = :storeId AND m.quantity > 0 AND m.deadline > :now
""")
List<Menu> findByStoreId(
@Param("storeId") Long storeId,
@Param("now") LocalDateTime now);

/**
* ids에 포함된 Menu와 연관된 Store를 한번에 가져옴
*/
@Query(value = "SELECT m from Menu m join fetch m.store where m.id in :ids")
List<Menu> findAllByIdWithStore(@Param("ids") Collection<Long> ids);



}
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,19 @@

import com.example.Centralthon.domain.menu.entity.Menu;
import com.example.Centralthon.domain.menu.entity.enums.MenuCategory;
import com.fasterxml.jackson.annotation.JsonUnwrapped;

import java.math.BigDecimal;
import java.math.RoundingMode;

public record MenuDetailsRes(
long menuId,
String name,
MenuCategory category,
int costPrice,
int salePrice,
int salePercent,
@JsonUnwrapped MenuItemRes item,
String storeName
) {
public static MenuDetailsRes from(Menu menu) {
return new MenuDetailsRes(
menu.getId(),
menu.getName(),
menu.getCategory(),
menu.getCostPrice(),
menu.getSalePrice(),
calculateDiscount(menu.getCostPrice(), menu.getSalePrice()),
MenuItemRes.from(menu),
menu.getStore().getName()
);
}

private static int calculateDiscount(int cost, int sale) {
return BigDecimal.valueOf(cost - sale)
.multiply(BigDecimal.valueOf(100))
.divide(BigDecimal.valueOf(cost), 0, RoundingMode.HALF_UP)
.intValue();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.example.Centralthon.domain.menu.web.dto;

import com.example.Centralthon.domain.menu.entity.Menu;
import com.example.Centralthon.domain.menu.entity.enums.MenuCategory;

import java.math.BigDecimal;
import java.math.RoundingMode;

// 하위 공통 DTO
public record MenuItemRes(
Long menuId,
String name,
MenuCategory category, // 메뉴 카테고리 (예: 볶음)
int costPrice,
int salePrice,
int salePercent, // (costPrice - salePrice) * 100 / costPrice
int quantity) {

public static MenuItemRes from(Menu menu) {
return new MenuItemRes(
menu.getId(),
menu.getName(),
menu.getCategory(),
menu.getCostPrice(),
menu.getSalePrice(),
calculateDiscount(menu.getCostPrice(), menu.getSalePrice()),
menu.getQuantity()
);
}

private static int calculateDiscount(int cost, int sale) {
return BigDecimal.valueOf(cost - sale)
.multiply(BigDecimal.valueOf(100))
.divide(BigDecimal.valueOf(cost), 0, RoundingMode.HALF_UP)
.intValue();
}
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.example.Centralthon.domain.store.exception;

import com.example.Centralthon.global.response.code.BaseResponseCode;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum StoreErrorCode implements BaseResponseCode {
STORE_NOT_FOUND("STORE_NOT_FOUND_404_1",404,"존재하지 않는 가게 입니다.");

private final String code;
private final int httpStatus;
private final String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.example.Centralthon.domain.store.exception;

import com.example.Centralthon.global.exception.BaseException;

public class StoreNotFoundException extends BaseException {
public StoreNotFoundException( ) {
super(StoreErrorCode.STORE_NOT_FOUND);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.example.Centralthon.domain.store.service;

import com.example.Centralthon.domain.store.web.dto.NearbyStoresRes;
import com.example.Centralthon.domain.store.web.dto.StoreMenusRes;

import java.util.List;

public interface StoreService {
List<NearbyStoresRes> nearbyStores(double lat, double lng);

StoreMenusRes getStoreMenus(Long storeId, double lat, double lng);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package com.example.Centralthon.domain.store.service;

import com.example.Centralthon.domain.menu.entity.Menu;
import com.example.Centralthon.domain.menu.repository.MenuRepository;
import com.example.Centralthon.domain.menu.web.dto.MenuItemRes;
import com.example.Centralthon.domain.store.entity.Store;
import com.example.Centralthon.domain.store.repository.StoreRepository;
import com.example.Centralthon.domain.store.web.dto.NearbyStoresRes;
import com.example.Centralthon.domain.store.web.dto.StoreMenusRes;
import com.example.Centralthon.domain.store.exception.StoreNotFoundException;
import com.example.Centralthon.global.util.geo.BoundingBox;
import com.example.Centralthon.global.util.geo.GeoUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -17,6 +23,7 @@
@RequiredArgsConstructor
public class StoreServiceImpl implements StoreService {
private final StoreRepository storeRepository;
private final MenuRepository menuRepository;

@Override
@Transactional(readOnly = true)
Expand All @@ -33,4 +40,29 @@ public List<NearbyStoresRes> nearbyStores(double lat, double lng) {
.map(store -> NearbyStoresRes.from(store))
.toList();
}

@Override
@Transactional(readOnly = true)
public StoreMenusRes getStoreMenus(Long storeId, double lat, double lng) {
LocalDateTime now = LocalDateTime.now();

// 가게 id가 없을 경우 -> StoreNotFoundException
Store store = storeRepository.findById(storeId)
.orElseThrow(StoreNotFoundException::new);

// 사용자와 가게 간의 거리 구하기
double distance = GeoUtils.calculateDistance(lat, lng, store.getLatitude(), store.getLongitude());

List<Menu> menus = menuRepository.findByStoreId(storeId, now);

List<MenuItemRes> menuItems = menus.stream()
.map(MenuItemRes::from)
.toList();

return StoreMenusRes.from(
store,
distance,
menuItems
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@

import com.example.Centralthon.domain.store.service.StoreService;
import com.example.Centralthon.domain.store.web.dto.NearbyStoresRes;
import com.example.Centralthon.domain.store.web.dto.StoreMenusRes;
import com.example.Centralthon.global.response.SuccessResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
Expand All @@ -28,4 +27,17 @@ public ResponseEntity<SuccessResponse<List<NearbyStoresRes>>> nearbyStores(

return ResponseEntity.status(HttpStatus.OK).body(SuccessResponse.from(stores));
}

// 가게 판매 메뉴 목록 조회
@GetMapping("/{storeId}/menus")
public ResponseEntity<SuccessResponse<StoreMenusRes>> getStoreMenus(
@PathVariable Long storeId,
@RequestParam("lat") Double lat,
@RequestParam("lng") Double lng){

StoreMenusRes menus = storeService.getStoreMenus(storeId, lat, lng);

return ResponseEntity.status(HttpStatus.OK).body(SuccessResponse.from(menus));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.example.Centralthon.domain.store.web.dto;

import com.example.Centralthon.domain.menu.web.dto.MenuItemRes;
import com.example.Centralthon.domain.menu.web.dto.MenuItemRes;
import com.example.Centralthon.domain.store.entity.Store;
import com.example.Centralthon.domain.store.entity.enums.StoreCategory;

import java.util.List;

public record StoreMenusRes(
String name,
StoreCategory category,
double distance,
List<MenuItemRes> menus
) {
public static StoreMenusRes from(Store store, double distance, List<MenuItemRes> menuItems) {
return new StoreMenusRes(
store.getName(),
store.getCategory(),
distance,
menuItems
);
}
}