From d55ac0778ee6331b91df09b79b7f4095306033e5 Mon Sep 17 00:00:00 2001 From: kjh0718 Date: Wed, 14 Jan 2026 01:19:57 +0900 Subject: [PATCH 01/12] =?UTF-8?q?rank=5F=EA=B8=B0=EB=8A=A5=5F=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20:=20feat=20:=20{=EB=9E=AD=ED=81=AC=20=EB=8B=A8?= =?UTF-8?q?=EC=88=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84}=20https://?= =?UTF-8?q?github.com/CampusTable/campus-table-be/issues/66?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../menu/controller/MenuController.java | 116 ++++++++++-------- .../be/domain/menu/dto/TopMenuResponse.java | 21 ++++ .../be/domain/menu/service/MenuService.java | 43 +++++++ .../be/domain/order/service/OrderService.java | 10 ++ 4 files changed, 137 insertions(+), 53 deletions(-) create mode 100644 src/main/java/com/campustable/be/domain/menu/dto/TopMenuResponse.java diff --git a/src/main/java/com/campustable/be/domain/menu/controller/MenuController.java b/src/main/java/com/campustable/be/domain/menu/controller/MenuController.java index 291ec2c..3536ea3 100644 --- a/src/main/java/com/campustable/be/domain/menu/controller/MenuController.java +++ b/src/main/java/com/campustable/be/domain/menu/controller/MenuController.java @@ -3,6 +3,7 @@ import com.campustable.be.domain.menu.dto.MenuRequest; import com.campustable.be.domain.menu.dto.MenuResponse; import com.campustable.be.domain.menu.dto.MenuUpdateRequest; +import com.campustable.be.domain.menu.dto.TopMenuResponse; import com.campustable.be.domain.menu.service.MenuService; import com.campustable.be.global.aop.LogMonitoringInvocation; import jakarta.validation.Valid; @@ -19,78 +20,87 @@ public class MenuController implements MenuControllerDocs { - private final MenuService menuService; + private final MenuService menuService; - @Override - @GetMapping - @LogMonitoringInvocation - public ResponseEntity> getAllMenus(){ + @Override + @GetMapping + @LogMonitoringInvocation + public ResponseEntity> getAllMenus() { - List menus = menuService.getAllMenus(); + List menus = menuService.getAllMenus(); - return ResponseEntity.ok(menus); + return ResponseEntity.ok(menus); - } + } - @Override - @LogMonitoringInvocation - @GetMapping("/category/{category_id}") - public ResponseEntity> getAllMenusByCategoryId( - @PathVariable(name = "category_id") Long categoryId){ + @Override + @LogMonitoringInvocation + @GetMapping("/category/{category_id}") + public ResponseEntity> getAllMenusByCategoryId( + @PathVariable(name = "category_id") Long categoryId) { - List menus = menuService.getAllMenusByCategory(categoryId); + List menus = menuService.getAllMenusByCategory(categoryId); - return ResponseEntity.ok(menus); + return ResponseEntity.ok(menus); - } + } - @Override - @LogMonitoringInvocation - @GetMapping("/{menuId}") - public ResponseEntity getMenuById(@PathVariable Long menuId){ - return ResponseEntity.ok(menuService.getMenuById(menuId)); - } + @Override + @LogMonitoringInvocation + @GetMapping("/{menuId}") + public ResponseEntity getMenuById(@PathVariable Long menuId) { + return ResponseEntity.ok(menuService.getMenuById(menuId)); + } - @Override - @LogMonitoringInvocation - @GetMapping("/cafeteria/{cafeteria-id}") - public ResponseEntity> getAllMenusByCafeteriaId( + @Override + @LogMonitoringInvocation + @GetMapping("/cafeteria/{cafeteria-id}") + public ResponseEntity> getAllMenusByCafeteriaId( @PathVariable(name = "cafeteria-id") Long cafeteriaId - ) { - return ResponseEntity.ok(menuService.getAllMenusByCafeteriaId(cafeteriaId)); - } + ) { + return ResponseEntity.ok(menuService.getAllMenusByCafeteriaId(cafeteriaId)); + } - @Override - @PostMapping - @LogMonitoringInvocation - public ResponseEntity createMenu(@Valid @RequestBody MenuRequest createRequest){ - MenuResponse createMenu = menuService.createMenu(createRequest); + @Override + @PostMapping + @LogMonitoringInvocation + public ResponseEntity createMenu(@Valid @RequestBody MenuRequest createRequest) { + MenuResponse createMenu = menuService.createMenu(createRequest); - return ResponseEntity.status(HttpStatus.CREATED).body(createMenu); - } + return ResponseEntity.status(HttpStatus.CREATED).body(createMenu); + } - @Override - @PatchMapping("/{menu_id}") - @LogMonitoringInvocation - public ResponseEntity updateMenu( - @PathVariable(name = "menu_id") Long menuId, - @RequestBody MenuUpdateRequest updateRequest){ + @Override + @PatchMapping("/{menu_id}") + @LogMonitoringInvocation + public ResponseEntity updateMenu( + @PathVariable(name = "menu_id") Long menuId, + @RequestBody MenuUpdateRequest updateRequest) { - MenuResponse updateMenu = menuService.updateMenu(menuId, updateRequest); + MenuResponse updateMenu = menuService.updateMenu(menuId, updateRequest); - return ResponseEntity.ok(updateMenu); - } + return ResponseEntity.ok(updateMenu); + } - @Override - @LogMonitoringInvocation - @DeleteMapping("/{menu_id}") - public ResponseEntity deleteMenu( - @PathVariable(name = "menu_id") Long menuId) { + @Override + @LogMonitoringInvocation + @DeleteMapping("/{menu_id}") + public ResponseEntity deleteMenu( + @PathVariable(name = "menu_id") Long menuId) { - menuService.deleteMenu(menuId); + menuService.deleteMenu(menuId); - return ResponseEntity.noContent().build(); - } + return ResponseEntity.noContent().build(); + } + + @GetMapping("/top") + @LogMonitoringInvocation + public ResponseEntity> getTopMenus() { + + List topMenus = menuService.getTopMenus(); + + return ResponseEntity.ok(topMenus); + } } diff --git a/src/main/java/com/campustable/be/domain/menu/dto/TopMenuResponse.java b/src/main/java/com/campustable/be/domain/menu/dto/TopMenuResponse.java new file mode 100644 index 0000000..a8799cb --- /dev/null +++ b/src/main/java/com/campustable/be/domain/menu/dto/TopMenuResponse.java @@ -0,0 +1,21 @@ +package com.campustable.be.domain.menu.dto; + +import com.campustable.be.domain.menu.entity.Menu; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class TopMenuResponse { + + private Long rank; + private MenuResponse menu; + + public static TopMenuResponse of(Long rank, Menu menu) { + return TopMenuResponse.builder() + .rank(rank) + .menu(MenuResponse.from(menu)) + .build(); + } + +} diff --git a/src/main/java/com/campustable/be/domain/menu/service/MenuService.java b/src/main/java/com/campustable/be/domain/menu/service/MenuService.java index 146c24e..41b2409 100644 --- a/src/main/java/com/campustable/be/domain/menu/service/MenuService.java +++ b/src/main/java/com/campustable/be/domain/menu/service/MenuService.java @@ -8,12 +8,20 @@ import com.campustable.be.domain.menu.dto.MenuRequest; import com.campustable.be.domain.menu.dto.MenuResponse; import com.campustable.be.domain.menu.dto.MenuUpdateRequest; +import com.campustable.be.domain.menu.dto.TopMenuResponse; import com.campustable.be.domain.menu.entity.Menu; import com.campustable.be.domain.menu.repository.MenuRepository; import com.campustable.be.global.exception.CustomException; import com.campustable.be.global.exception.ErrorCode; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.transaction.annotation.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -29,6 +37,7 @@ public class MenuService { private final MenuRepository menuRepository; private final CategoryRepository categoryRepository; private final CafeteriaService cafeteriaService; + private final StringRedisTemplate stringRedisTemplate; @Transactional @@ -142,5 +151,39 @@ public void deleteMenu(Long menuId) { } } + + @Transactional + public List getTopMenus(){ + + Set topMenus = stringRedisTemplate.opsForZSet().reverseRange("menu:rank",0,2); + + if(topMenus == null || topMenus.isEmpty()){ + return List.of(); + } + + List topMenuIds = topMenus.stream() + .map(Long::parseLong) + .toList(); + + List menus = menuRepository.findAllById(topMenuIds); + + Map topMenusMap = menus.stream() + .collect(Collectors.toMap(Menu::getId, Function.identity())); + + List topMenusResponse = new ArrayList<>(); + + for(int i=0;i<3;i++){ + Long topMenuId = topMenuIds.get(i); + Menu menu = topMenusMap.get(topMenuId); + + if(menu != null){ + topMenusResponse.add(TopMenuResponse.of((long)(i+1),menu)); + } + } + + return topMenusResponse; + + } + } diff --git a/src/main/java/com/campustable/be/domain/order/service/OrderService.java b/src/main/java/com/campustable/be/domain/order/service/OrderService.java index fa4135a..b29e0cf 100644 --- a/src/main/java/com/campustable/be/domain/order/service/OrderService.java +++ b/src/main/java/com/campustable/be/domain/order/service/OrderService.java @@ -3,6 +3,7 @@ import com.campustable.be.domain.cart.entity.Cart; import com.campustable.be.domain.cart.repository.CartRepository; import com.campustable.be.domain.menu.entity.Menu; +import com.campustable.be.domain.menu.repository.MenuRepository; import com.campustable.be.domain.order.dto.OrderResponse; import com.campustable.be.domain.order.entity.Order; import com.campustable.be.domain.order.entity.OrderItem; @@ -16,6 +17,8 @@ import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -29,6 +32,7 @@ public class OrderService { private final CartRepository cartRepository; private final UserRepository userRepository; private final OrderItemRepository orderItemRepository; + private final StringRedisTemplate stringRedisTemplate; public OrderResponse createOrder() { Long userId = SecurityUtil.getCurrentUserId(); @@ -63,6 +67,12 @@ public OrderResponse createOrder() { user.setCart(null); cartRepository.delete(cart); + // 주문된 메뉴 랭킹 점수 증가 + for(OrderItem orderItem : orderItems) { + stringRedisTemplate.opsForZSet() + .incrementScore("menu:rank",String.valueOf(orderItem.getMenu().getId()),orderItem.getQuantity()); + } + return OrderResponse.from(order); } From 9699b0aa40ade115513216fd996f4b7659523c33 Mon Sep 17 00:00:00 2001 From: kjh0718 Date: Wed, 14 Jan 2026 13:28:06 +0900 Subject: [PATCH 02/12] =?UTF-8?q?rank=5F=EA=B8=B0=EB=8A=A5=5F=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20:=20feat=20:=20{=EC=8B=9D=EB=8B=B9=EB=B3=84=20top3?= =?UTF-8?q?=20=EB=82=98=EC=98=A4=EA=B2=8C=20=EA=B5=AC=ED=98=84}=20https://?= =?UTF-8?q?github.com/CampusTable/campus-table-be/issues/66?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../be/domain/menu/controller/MenuController.java | 6 +++--- .../campustable/be/domain/menu/dto/MenuRequest.java | 1 + .../campustable/be/domain/menu/dto/MenuResponse.java | 4 +++- .../be/domain/menu/service/MenuService.java | 8 +++++--- .../be/domain/order/service/OrderService.java | 12 +++++++++++- 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/campustable/be/domain/menu/controller/MenuController.java b/src/main/java/com/campustable/be/domain/menu/controller/MenuController.java index 3536ea3..21ac8ee 100644 --- a/src/main/java/com/campustable/be/domain/menu/controller/MenuController.java +++ b/src/main/java/com/campustable/be/domain/menu/controller/MenuController.java @@ -94,11 +94,11 @@ public ResponseEntity deleteMenu( return ResponseEntity.noContent().build(); } - @GetMapping("/top") + @GetMapping("/cafeteria/{cafeteria-id}/top-menus") @LogMonitoringInvocation - public ResponseEntity> getTopMenus() { + public ResponseEntity> getTopMenus(@PathVariable(name = "cafeteria-id") Long cafeteriaId) { - List topMenus = menuService.getTopMenus(); + List topMenus = menuService.getTopMenusByCafeteriaId(cafeteriaId); return ResponseEntity.ok(topMenus); } diff --git a/src/main/java/com/campustable/be/domain/menu/dto/MenuRequest.java b/src/main/java/com/campustable/be/domain/menu/dto/MenuRequest.java index 5f42a07..8b6968b 100644 --- a/src/main/java/com/campustable/be/domain/menu/dto/MenuRequest.java +++ b/src/main/java/com/campustable/be/domain/menu/dto/MenuRequest.java @@ -43,6 +43,7 @@ public Menu toEntity(Category category) { .menuUrl(this.getMenuUrl()) .available(this.getAvailable()) .stockQuantity(this.getStockQuantity()) + .build(); } diff --git a/src/main/java/com/campustable/be/domain/menu/dto/MenuResponse.java b/src/main/java/com/campustable/be/domain/menu/dto/MenuResponse.java index af03eaa..17a52c4 100644 --- a/src/main/java/com/campustable/be/domain/menu/dto/MenuResponse.java +++ b/src/main/java/com/campustable/be/domain/menu/dto/MenuResponse.java @@ -24,6 +24,7 @@ public class MenuResponse { private Boolean available; private Integer stockQuantity; private LocalDateTime createdDate; + private Long cafeteriaId; public static MenuResponse from(Menu menu) { return new MenuResponse( @@ -34,7 +35,8 @@ public static MenuResponse from(Menu menu) { menu.getMenuUrl(), menu.getAvailable(), menu.getStockQuantity(), - menu.getCreatedAt() + menu.getCreatedAt(), + menu.getCategory().getCafeteria().getCafeteriaId() ); } diff --git a/src/main/java/com/campustable/be/domain/menu/service/MenuService.java b/src/main/java/com/campustable/be/domain/menu/service/MenuService.java index 41b2409..40e6db3 100644 --- a/src/main/java/com/campustable/be/domain/menu/service/MenuService.java +++ b/src/main/java/com/campustable/be/domain/menu/service/MenuService.java @@ -153,9 +153,11 @@ public void deleteMenu(Long menuId) { @Transactional - public List getTopMenus(){ + public List getTopMenusByCafeteriaId(Long cafeteriaId) { - Set topMenus = stringRedisTemplate.opsForZSet().reverseRange("menu:rank",0,2); + String key = "cafeteria:"+cafeteriaId+"menu:rank"; + + Set topMenus = stringRedisTemplate.opsForZSet().reverseRange(key,0,2); if(topMenus == null || topMenus.isEmpty()){ return List.of(); @@ -172,7 +174,7 @@ public List getTopMenus(){ List topMenusResponse = new ArrayList<>(); - for(int i=0;i<3;i++){ + for(int i=0;i Date: Wed, 14 Jan 2026 13:39:36 +0900 Subject: [PATCH 03/12] =?UTF-8?q?rank=5F=EA=B8=B0=EB=8A=A5=5F=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20:=20feat=20:=20{key=20=EA=B0=92=EC=97=90=20?= =?UTF-8?q?=EC=BD=9C=EB=A1=A0=20=EC=B6=94=EA=B0=80}=20https://github.com/C?= =?UTF-8?q?ampusTable/campus-table-be/issues/66?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/campustable/be/domain/menu/service/MenuService.java | 2 +- .../com/campustable/be/domain/order/service/OrderService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/campustable/be/domain/menu/service/MenuService.java b/src/main/java/com/campustable/be/domain/menu/service/MenuService.java index 40e6db3..fcb6f50 100644 --- a/src/main/java/com/campustable/be/domain/menu/service/MenuService.java +++ b/src/main/java/com/campustable/be/domain/menu/service/MenuService.java @@ -155,7 +155,7 @@ public void deleteMenu(Long menuId) { @Transactional public List getTopMenusByCafeteriaId(Long cafeteriaId) { - String key = "cafeteria:"+cafeteriaId+"menu:rank"; + String key = "cafeteria:"+cafeteriaId+":menu:rank"; Set topMenus = stringRedisTemplate.opsForZSet().reverseRange(key,0,2); diff --git a/src/main/java/com/campustable/be/domain/order/service/OrderService.java b/src/main/java/com/campustable/be/domain/order/service/OrderService.java index 8530951..2a44556 100644 --- a/src/main/java/com/campustable/be/domain/order/service/OrderService.java +++ b/src/main/java/com/campustable/be/domain/order/service/OrderService.java @@ -77,7 +77,7 @@ public OrderResponse createOrder() { Cafeteria cafeteria = category.getCafeteria(); Long cafeteriaId = cafeteria.getCafeteriaId(); - String key = "cafeteria:" + cafeteriaId + "menu:rank"; + String key = "cafeteria:" + cafeteriaId + ":menu:rank"; stringRedisTemplate.opsForZSet() .incrementScore(key,String.valueOf(menu.getId()),orderItem.getQuantity()); From 2660e5075091c381673ac4a0652b240b31afafae Mon Sep 17 00:00:00 2001 From: kjh0718 Date: Wed, 14 Jan 2026 15:16:34 +0900 Subject: [PATCH 04/12] =?UTF-8?q?rank=5F=EA=B8=B0=EB=8A=A5=5F=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20:=20feat=20:=20{=EC=8B=9D=EB=8B=B9=20=EC=97=86?= =?UTF-8?q?=EC=9D=84=EB=95=8C=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?+=20docs}=20https://github.com/CampusTable/campus-table-be/issu?= =?UTF-8?q?es/66?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../menu/controller/MenuController.java | 5 +++-- .../menu/controller/MenuControllerDocs.java | 19 +++++++++++++++++++ .../be/domain/menu/service/MenuService.java | 4 +++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/campustable/be/domain/menu/controller/MenuController.java b/src/main/java/com/campustable/be/domain/menu/controller/MenuController.java index 21ac8ee..99b5761 100644 --- a/src/main/java/com/campustable/be/domain/menu/controller/MenuController.java +++ b/src/main/java/com/campustable/be/domain/menu/controller/MenuController.java @@ -94,11 +94,12 @@ public ResponseEntity deleteMenu( return ResponseEntity.noContent().build(); } + @Override @GetMapping("/cafeteria/{cafeteria-id}/top-menus") @LogMonitoringInvocation - public ResponseEntity> getTopMenus(@PathVariable(name = "cafeteria-id") Long cafeteriaId) { + public ResponseEntity> getTop3MenusByCafeteriaId(@PathVariable(name = "cafeteria-id") Long cafeteriaId) { - List topMenus = menuService.getTopMenusByCafeteriaId(cafeteriaId); + List topMenus = menuService.getTop3MenusByCafeteriaId(cafeteriaId); return ResponseEntity.ok(topMenus); } diff --git a/src/main/java/com/campustable/be/domain/menu/controller/MenuControllerDocs.java b/src/main/java/com/campustable/be/domain/menu/controller/MenuControllerDocs.java index a1d3479..2320817 100644 --- a/src/main/java/com/campustable/be/domain/menu/controller/MenuControllerDocs.java +++ b/src/main/java/com/campustable/be/domain/menu/controller/MenuControllerDocs.java @@ -3,6 +3,7 @@ import com.campustable.be.domain.menu.dto.MenuRequest; import com.campustable.be.domain.menu.dto.MenuResponse; import com.campustable.be.domain.menu.dto.MenuUpdateRequest; +import com.campustable.be.domain.menu.dto.TopMenuResponse; import com.campustable.be.global.exception.ErrorResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -123,4 +124,22 @@ ResponseEntity updateMenu( ResponseEntity deleteMenu( @Parameter(description = "삭제할 메뉴 ID", example = "1") Long menuId ); + + /** + * 특정 식당의 인기 메뉴(Top 3)를 조회합니다. + * Redis ZSet을 기반으로 식당별 주문량이 가장 많은 Top3 메뉴 정보와 랭킹을 반환 + * @param cafeteriaId 식당 고유 식별자 + * @return 랭킹과 메뉴 상세 정보 리스트를 담은 ResponseEntity + */ + @Operation(summary = "식당별 인기 메뉴 조회(Top 3)", description = "특정 식당 ID의 Top 3 인기 메뉴를 조회합니다.") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "조회 성공"), + @ApiResponse(responseCode = "404", description = "해당 식당을 찾을 수 없습니다.", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))) + }) + ResponseEntity> getTop3MenusByCafeteriaId( + @Parameter(description = "조회할 식당 ID",example = "1") Long cafeteriaId + ); + + } \ No newline at end of file diff --git a/src/main/java/com/campustable/be/domain/menu/service/MenuService.java b/src/main/java/com/campustable/be/domain/menu/service/MenuService.java index fcb6f50..f29d971 100644 --- a/src/main/java/com/campustable/be/domain/menu/service/MenuService.java +++ b/src/main/java/com/campustable/be/domain/menu/service/MenuService.java @@ -153,7 +153,9 @@ public void deleteMenu(Long menuId) { @Transactional - public List getTopMenusByCafeteriaId(Long cafeteriaId) { + public List getTop3MenusByCafeteriaId(Long cafeteriaId) { + + cafeteriaService.findCafeteriaById(cafeteriaId); String key = "cafeteria:"+cafeteriaId+":menu:rank"; From f153f03aaf4182573e8a27c82e8608235e4591bf Mon Sep 17 00:00:00 2001 From: kjh0718 Date: Thu, 15 Jan 2026 16:55:31 +0900 Subject: [PATCH 05/12] =?UTF-8?q?rank=5F=EA=B8=B0=EB=8A=A5=5F=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20:=20feat=20:=20{=EB=A9=94=EB=89=B4=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EC=8B=9C=20redis=20=EB=9E=AD=ED=82=B9=200=EC=A0=90=20?= =?UTF-8?q?=EC=B4=88=EA=B8=B0=ED=99=94}=20https://github.com/CampusTable/c?= =?UTF-8?q?ampus-table-be/issues/66?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../be/domain/menu/service/MenuService.java | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/campustable/be/domain/menu/service/MenuService.java b/src/main/java/com/campustable/be/domain/menu/service/MenuService.java index f29d971..03a64c3 100644 --- a/src/main/java/com/campustable/be/domain/menu/service/MenuService.java +++ b/src/main/java/com/campustable/be/domain/menu/service/MenuService.java @@ -60,7 +60,15 @@ public MenuResponse createMenu(MenuRequest request) { } Menu menu = request.toEntity(category); - return MenuResponse.from(menuRepository.save(menu)); + + Menu savedMenu = menuRepository.save(menu); + + Long cafeteriaId = savedMenu.getCategory().getCafeteria().getCafeteriaId(); + String key = "cafeteria:" + cafeteriaId + ":menu:rank"; + + stringRedisTemplate.opsForZSet().add(key, String.valueOf(savedMenu.getId()), 0.0); + + return MenuResponse.from(savedMenu); } @@ -68,7 +76,7 @@ public MenuResponse createMenu(MenuRequest request) { public MenuResponse getMenuById(Long menuId) { Menu menu = menuRepository.findById(menuId) - .orElseThrow(()->{ + .orElseThrow(() -> { log.error("getMenuById : 유효하지않은 menuId"); return new CustomException(ErrorCode.MENU_NOT_FOUND); }); @@ -155,13 +163,13 @@ public void deleteMenu(Long menuId) { @Transactional public List getTop3MenusByCafeteriaId(Long cafeteriaId) { - cafeteriaService.findCafeteriaById(cafeteriaId); + cafeteriaService.findCafeteriaById(cafeteriaId); - String key = "cafeteria:"+cafeteriaId+":menu:rank"; + String key = "cafeteria:" + cafeteriaId + ":menu:rank"; - Set topMenus = stringRedisTemplate.opsForZSet().reverseRange(key,0,2); + Set topMenus = stringRedisTemplate.opsForZSet().reverseRange(key, 0, 2); - if(topMenus == null || topMenus.isEmpty()){ + if (topMenus == null || topMenus.isEmpty()) { return List.of(); } @@ -171,17 +179,17 @@ public List getTop3MenusByCafeteriaId(Long cafeteriaId) { List menus = menuRepository.findAllById(topMenuIds); - Map topMenusMap = menus.stream() + Map topMenusMap = menus.stream() .collect(Collectors.toMap(Menu::getId, Function.identity())); List topMenusResponse = new ArrayList<>(); - for(int i=0;i Date: Sun, 25 Jan 2026 21:01:22 +0900 Subject: [PATCH 06/12] =?UTF-8?q?rank=5F=EA=B8=B0=EB=8A=A5=5F=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20:=20feat=20:=20{coderabbit=20=EC=88=98=EC=A0=95}=20?= =?UTF-8?q?https://github.com/CampusTable/campus-table-be/issues/66?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../be/domain/menu/service/MenuService.java | 13 +++++-- .../be/domain/order/service/OrderService.java | 38 +++++++++++++------ 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/campustable/be/domain/menu/service/MenuService.java b/src/main/java/com/campustable/be/domain/menu/service/MenuService.java index 03a64c3..b9fb2a7 100644 --- a/src/main/java/com/campustable/be/domain/menu/service/MenuService.java +++ b/src/main/java/com/campustable/be/domain/menu/service/MenuService.java @@ -63,10 +63,17 @@ public MenuResponse createMenu(MenuRequest request) { Menu savedMenu = menuRepository.save(menu); - Long cafeteriaId = savedMenu.getCategory().getCafeteria().getCafeteriaId(); - String key = "cafeteria:" + cafeteriaId + ":menu:rank"; + try{ + Long cafeteriaId = savedMenu.getCategory().getCafeteria().getCafeteriaId(); + String key = "cafeteria:" + cafeteriaId + ":menu:rank"; + + stringRedisTemplate.opsForZSet().add(key, String.valueOf(savedMenu.getId()), 0.0); + } + catch (Exception e){ - stringRedisTemplate.opsForZSet().add(key, String.valueOf(savedMenu.getId()), 0.0); + log.error("메뉴 생성 후 Redis 랭킹 등록 실패. (Menu Id: {}), 원인 :{}",savedMenu.getId(),e.getMessage()); + + } return MenuResponse.from(savedMenu); diff --git a/src/main/java/com/campustable/be/domain/order/service/OrderService.java b/src/main/java/com/campustable/be/domain/order/service/OrderService.java index 2a44556..f558638 100644 --- a/src/main/java/com/campustable/be/domain/order/service/OrderService.java +++ b/src/main/java/com/campustable/be/domain/order/service/OrderService.java @@ -23,6 +23,8 @@ import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionSynchronization; +import org.springframework.transaction.support.TransactionSynchronizationManager; @Service @RequiredArgsConstructor @@ -69,21 +71,33 @@ public OrderResponse createOrder() { user.setCart(null); cartRepository.delete(cart); - // 주문된 메뉴 랭킹 점수 증가 - for(OrderItem orderItem : orderItems) { - - Menu menu = orderItem.getMenu(); - Category category = menu.getCategory(); - Cafeteria cafeteria = category.getCafeteria(); - Long cafeteriaId = cafeteria.getCafeteriaId(); + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { + @Override + public void afterCommit() { + updateMenuRanking(orderItems); + } + }); - String key = "cafeteria:" + cafeteriaId + ":menu:rank"; + return OrderResponse.from(order); + } - stringRedisTemplate.opsForZSet() - .incrementScore(key,String.valueOf(menu.getId()),orderItem.getQuantity()); + private void updateMenuRanking(List orderItems) { + for(OrderItem orderItem : orderItems) { + try { + Menu menu = orderItem.getMenu(); + Category category = menu.getCategory(); + Cafeteria cafeteria = category.getCafeteria(); + Long cafeteriaId = cafeteria.getCafeteriaId(); + + String key = "cafeteria:" + cafeteriaId + ":menu:rank"; + + stringRedisTemplate.opsForZSet() + .incrementScore(key, String.valueOf(menu.getId()), orderItem.getQuantity()); + } + catch (Exception e) { + log.error("랭킹 점수 반영 실패: {}",e.getMessage()); + } } - - return OrderResponse.from(order); } public void updateCategoryToReady(Long orderId,Long categoryId) { From f8698abe31b2726aa2abcd98b922e054a8b207d9 Mon Sep 17 00:00:00 2001 From: kjh0718 Date: Sun, 25 Jan 2026 21:16:13 +0900 Subject: [PATCH 07/12] =?UTF-8?q?rank=5F=EA=B8=B0=EB=8A=A5=5F=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20:=20feat=20:=20{coderabbit=20=EC=88=98=EC=A0=95=20-?= =?UTF-8?q?=20redis=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=B3=80=ED=99=98=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC}=20https://github.com/C?= =?UTF-8?q?ampusTable/campus-table-be/issues/66?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../be/domain/menu/service/MenuService.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/campustable/be/domain/menu/service/MenuService.java b/src/main/java/com/campustable/be/domain/menu/service/MenuService.java index b9fb2a7..acc78bb 100644 --- a/src/main/java/com/campustable/be/domain/menu/service/MenuService.java +++ b/src/main/java/com/campustable/be/domain/menu/service/MenuService.java @@ -63,15 +63,14 @@ public MenuResponse createMenu(MenuRequest request) { Menu savedMenu = menuRepository.save(menu); - try{ + try { Long cafeteriaId = savedMenu.getCategory().getCafeteria().getCafeteriaId(); String key = "cafeteria:" + cafeteriaId + ":menu:rank"; stringRedisTemplate.opsForZSet().add(key, String.valueOf(savedMenu.getId()), 0.0); - } - catch (Exception e){ + } catch (Exception e) { - log.error("메뉴 생성 후 Redis 랭킹 등록 실패. (Menu Id: {}), 원인 :{}",savedMenu.getId(),e.getMessage()); + log.error("메뉴 생성 후 Redis 랭킹 등록 실패. (Menu Id: {}), 원인 :{}", savedMenu.getId(), e.getMessage()); } @@ -181,7 +180,15 @@ public List getTop3MenusByCafeteriaId(Long cafeteriaId) { } List topMenuIds = topMenus.stream() - .map(Long::parseLong) + .map(id -> { + try { + return Long.parseLong(id); + } catch (NumberFormatException e) { + log.warn("Redis에 잘못된 메뉴 ID 형식: {}", id); + return null; + } + }) + .filter(Objects::nonNull) .toList(); List menus = menuRepository.findAllById(topMenuIds); From f580fa8c917941a5a5ada271f558a1ee81015676 Mon Sep 17 00:00:00 2001 From: kjh0718 Date: Wed, 4 Feb 2026 01:53:10 +0900 Subject: [PATCH 08/12] =?UTF-8?q?rank=5F=EA=B8=B0=EB=8A=A5=5F=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20:=20feat=20:=20{=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=EC=97=85=EB=A1=9C=EB=93=9C=20+=20rank}=20https://github.com/Ca?= =?UTF-8?q?mpusTable/campus-table-be/issues/66?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../be/domain/menu/controller/MenuController.java | 11 +++++++++-- .../be/domain/menu/service/MenuService.java | 5 ----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/campustable/be/domain/menu/controller/MenuController.java b/src/main/java/com/campustable/be/domain/menu/controller/MenuController.java index 9de1222..61c5263 100644 --- a/src/main/java/com/campustable/be/domain/menu/controller/MenuController.java +++ b/src/main/java/com/campustable/be/domain/menu/controller/MenuController.java @@ -36,7 +36,15 @@ public ResponseEntity> getAllMenus(){ } - @Override + @Override + @LogMonitoringInvocation + @GetMapping("/menus/{menuId}") + public ResponseEntity getMenuById(@PathVariable Long menuId){ + return ResponseEntity.ok(menuService.getMenuById(menuId)); + } + + + @Override @LogMonitoringInvocation @GetMapping("/category/{category_id}/menus") public ResponseEntity> getAllMenusByCategoryId( @@ -49,7 +57,6 @@ public ResponseEntity> getAllMenusByCategoryId( } - @Override @LogMonitoringInvocation @GetMapping("/cafeteria/{cafeteria-id}") diff --git a/src/main/java/com/campustable/be/domain/menu/service/MenuService.java b/src/main/java/com/campustable/be/domain/menu/service/MenuService.java index 03d5892..0515b18 100644 --- a/src/main/java/com/campustable/be/domain/menu/service/MenuService.java +++ b/src/main/java/com/campustable/be/domain/menu/service/MenuService.java @@ -61,11 +61,6 @@ public MenuResponse createMenu(MenuRequest request, MultipartFile image) { Menu menu = request.toEntity(category); Menu savedMenu = menuRepository.save(menu); - - Menu menu = request.toEntity(category); - - Menu savedMenu = menuRepository.save(menu); - try { Long cafeteriaId = savedMenu.getCategory().getCafeteria().getCafeteriaId(); String key = "cafeteria:" + cafeteriaId + ":menu:rank"; From f38e1705a375bbd15d32e9549055831b77cb8997 Mon Sep 17 00:00:00 2001 From: kjh0718 Date: Fri, 6 Feb 2026 17:06:06 +0900 Subject: [PATCH 09/12] =?UTF-8?q?=EB=A0=88=EB=94=94=EC=8A=A4=20=EB=9E=AD?= =?UTF-8?q?=ED=82=B9=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EC=8B=9C=20?= =?UTF-8?q?LazyInitializationException=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../be/domain/order/service/OrderService.java | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/campustable/be/domain/order/service/OrderService.java b/src/main/java/com/campustable/be/domain/order/service/OrderService.java index f558638..92fe50b 100644 --- a/src/main/java/com/campustable/be/domain/order/service/OrderService.java +++ b/src/main/java/com/campustable/be/domain/order/service/OrderService.java @@ -17,6 +17,7 @@ import com.campustable.be.global.exception.CustomException; import com.campustable.be.global.exception.ErrorCode; import java.util.List; +import java.util.Map; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.RedisTemplate; @@ -66,41 +67,43 @@ public OrderResponse createOrder() { .toList(); Order order = Order.createOrder(user, orderItems); - orderRepository.save(order); + + List rankingData = orderItems.stream() + .map(item -> new RankingDto( + item.getMenu().getCategory().getCafeteria().getCafeteriaId(), + item.getMenu().getId(), + item.getQuantity())) + .toList(); + user.setCart(null); cartRepository.delete(cart); TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCommit() { - updateMenuRanking(orderItems); + updateMenuRanking(rankingData); } }); return OrderResponse.from(order); } - private void updateMenuRanking(List orderItems) { - for(OrderItem orderItem : orderItems) { + private void updateMenuRanking(List rankingData) { + for (RankingDto data : rankingData) { try { - Menu menu = orderItem.getMenu(); - Category category = menu.getCategory(); - Cafeteria cafeteria = category.getCafeteria(); - Long cafeteriaId = cafeteria.getCafeteriaId(); - - String key = "cafeteria:" + cafeteriaId + ":menu:rank"; + String key = "cafeteria:"+data.cafeteriaId+":menu:rank"; stringRedisTemplate.opsForZSet() - .incrementScore(key, String.valueOf(menu.getId()), orderItem.getQuantity()); - } - catch (Exception e) { - log.error("랭킹 점수 반영 실패: {}",e.getMessage()); + .incrementScore(key,String.valueOf(data.menuId),data.quantity); + + } catch (Exception e) { + log.error("랭킹 점수 반영 실패: {}", e.getMessage()); } } } - public void updateCategoryToReady(Long orderId,Long categoryId) { + public void updateCategoryToReady(Long orderId, Long categoryId) { List items = orderItemRepository.findByOrderOrderIdAndCategoryId(orderId, categoryId); if (items.isEmpty()) { @@ -110,7 +113,7 @@ public void updateCategoryToReady(Long orderId,Long categoryId) { items.forEach(OrderItem::markAsReady); //PREPARING -> READY } - public void updateCategoryToComplete(Long orderId,Long categoryId) { + public void updateCategoryToComplete(Long orderId, Long categoryId) { List items = orderItemRepository.findByOrderOrderIdAndCategoryId(orderId, categoryId); if (items.isEmpty()) { @@ -136,7 +139,7 @@ public List getMyOrders() { public List getOrdersByUserId(Long userId) { - User user = userRepository.findById(userId) + User user = userRepository.findById(userId) .orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND)); return orderRepository.findByUserUserIdOrderByCreatedAtDesc(userId).stream() @@ -145,4 +148,8 @@ public List getOrdersByUserId(Long userId) { } + private record RankingDto(Long cafeteriaId, Long menuId, Integer quantity) { + + } + } From 467329e3a7d057d13f0d0cfe6775cfd788f306c9 Mon Sep 17 00:00:00 2001 From: kjh0718 Date: Fri, 6 Feb 2026 17:25:13 +0900 Subject: [PATCH 10/12] =?UTF-8?q?=EB=A0=88=EB=94=94=EC=8A=A4=20=EB=9E=AD?= =?UTF-8?q?=ED=82=B9=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EC=8B=9C=20?= =?UTF-8?q?LazyInitializationException=20=ED=95=B4=EA=B2=B0(=EC=88=98?= =?UTF-8?q?=EC=A0=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../campustable/be/domain/order/service/OrderService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/campustable/be/domain/order/service/OrderService.java b/src/main/java/com/campustable/be/domain/order/service/OrderService.java index 92fe50b..01c1bfd 100644 --- a/src/main/java/com/campustable/be/domain/order/service/OrderService.java +++ b/src/main/java/com/campustable/be/domain/order/service/OrderService.java @@ -93,9 +93,9 @@ private void updateMenuRanking(List rankingData) { for (RankingDto data : rankingData) { try { - String key = "cafeteria:"+data.cafeteriaId+":menu:rank"; + String key = "cafeteria:"+data.cafeteriaId()+":menu:rank"; stringRedisTemplate.opsForZSet() - .incrementScore(key,String.valueOf(data.menuId),data.quantity); + .incrementScore(key,String.valueOf(data.menuId()),data.quantity()); } catch (Exception e) { log.error("랭킹 점수 반영 실패: {}", e.getMessage()); @@ -148,7 +148,7 @@ public List getOrdersByUserId(Long userId) { } - private record RankingDto(Long cafeteriaId, Long menuId, Integer quantity) { + private record RankingDto(Long cafeteriaId, Long menuId, int quantity) { } From adacb093f54b41566fd6e6db8bac6c0141ad943b Mon Sep 17 00:00:00 2001 From: kjh0718 Date: Fri, 6 Feb 2026 17:37:27 +0900 Subject: [PATCH 11/12] TEST --- .../be/domain/order/service/OrderService.java | 132 +++++++++--------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/src/main/java/com/campustable/be/domain/order/service/OrderService.java b/src/main/java/com/campustable/be/domain/order/service/OrderService.java index 01c1bfd..c52cb13 100644 --- a/src/main/java/com/campustable/be/domain/order/service/OrderService.java +++ b/src/main/java/com/campustable/be/domain/order/service/OrderService.java @@ -39,69 +39,69 @@ public class OrderService { private final OrderItemRepository orderItemRepository; private final StringRedisTemplate stringRedisTemplate; - public OrderResponse createOrder() { - Long userId = SecurityUtil.getCurrentUserId(); - - User user = userRepository.findById(userId) - .orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND)); - - Cart cart = cartRepository.findByUser(user) - .orElseThrow(() -> new CustomException(ErrorCode.CART_NOT_FOUND)); - - if (cart.getCartItems().isEmpty()) { - throw new CustomException(ErrorCode.CART_NOT_FOUND); - } - - List orderItems = cart.getCartItems().stream() - .map(cartItem -> { - - Menu menu = cartItem.getMenu(); - menu.decreaseStockQuantity(cartItem.getQuantity()); - - return OrderItem.createOrderItem( - menu, - menu.getPrice(), - cartItem.getQuantity() - ); - }) - .toList(); - - Order order = Order.createOrder(user, orderItems); - orderRepository.save(order); - - List rankingData = orderItems.stream() - .map(item -> new RankingDto( - item.getMenu().getCategory().getCafeteria().getCafeteriaId(), - item.getMenu().getId(), - item.getQuantity())) - .toList(); - - user.setCart(null); - cartRepository.delete(cart); - - TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { - @Override - public void afterCommit() { - updateMenuRanking(rankingData); - } - }); - - return OrderResponse.from(order); - } - - private void updateMenuRanking(List rankingData) { - for (RankingDto data : rankingData) { - try { - - String key = "cafeteria:"+data.cafeteriaId()+":menu:rank"; - stringRedisTemplate.opsForZSet() - .incrementScore(key,String.valueOf(data.menuId()),data.quantity()); - - } catch (Exception e) { - log.error("랭킹 점수 반영 실패: {}", e.getMessage()); - } - } - } +// public OrderResponse createOrder() { +// Long userId = SecurityUtil.getCurrentUserId(); +// +// User user = userRepository.findById(userId) +// .orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND)); +// +// Cart cart = cartRepository.findByUser(user) +// .orElseThrow(() -> new CustomException(ErrorCode.CART_NOT_FOUND)); +// +// if (cart.getCartItems().isEmpty()) { +// throw new CustomException(ErrorCode.CART_NOT_FOUND); +// } +// +// List orderItems = cart.getCartItems().stream() +// .map(cartItem -> { +// +// Menu menu = cartItem.getMenu(); +// menu.decreaseStockQuantity(cartItem.getQuantity()); +// +// return OrderItem.createOrderItem( +// menu, +// menu.getPrice(), +// cartItem.getQuantity() +// ); +// }) +// .toList(); +// +// Order order = Order.createOrder(user, orderItems); +// orderRepository.save(order); +// +// List rankingData = orderItems.stream() +// .map(item -> new RankingDto( +// item.getMenu().getCategory().getCafeteria().getCafeteriaId(), +// item.getMenu().getId(), +// item.getQuantity())) +// .toList(); +// +// user.setCart(null); +// cartRepository.delete(cart); +// +// TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { +// @Override +// public void afterCommit() { +// updateMenuRanking(rankingData); +// } +// }); +// +// return OrderResponse.from(order); +// } + +// private void updateMenuRanking(List rankingData) { +// for (RankingDto data : rankingData) { +// try { +// +// String key = "cafeteria:"+data.cafeteriaId()+":menu:rank"; +// stringRedisTemplate.opsForZSet() +// .incrementScore(key,String.valueOf(data.menuId()),data.quantity()); +// +// } catch (Exception e) { +// log.error("랭킹 점수 반영 실패: {}", e.getMessage()); +// } +// } +// } public void updateCategoryToReady(Long orderId, Long categoryId) { @@ -148,8 +148,8 @@ public List getOrdersByUserId(Long userId) { } - private record RankingDto(Long cafeteriaId, Long menuId, int quantity) { - - } +// private record RankingDto(Long cafeteriaId, Long menuId, int quantity) { +// +// } } From 409b592fe33cc0a47d61a91b64a3f1f862af65bc Mon Sep 17 00:00:00 2001 From: kjh0718 Date: Fri, 6 Feb 2026 17:43:52 +0900 Subject: [PATCH 12/12] TEST --- .../be/domain/order/service/OrderService.java | 131 +++++++++--------- 1 file changed, 64 insertions(+), 67 deletions(-) diff --git a/src/main/java/com/campustable/be/domain/order/service/OrderService.java b/src/main/java/com/campustable/be/domain/order/service/OrderService.java index c52cb13..ab852ae 100644 --- a/src/main/java/com/campustable/be/domain/order/service/OrderService.java +++ b/src/main/java/com/campustable/be/domain/order/service/OrderService.java @@ -39,69 +39,70 @@ public class OrderService { private final OrderItemRepository orderItemRepository; private final StringRedisTemplate stringRedisTemplate; -// public OrderResponse createOrder() { -// Long userId = SecurityUtil.getCurrentUserId(); -// -// User user = userRepository.findById(userId) -// .orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND)); -// -// Cart cart = cartRepository.findByUser(user) -// .orElseThrow(() -> new CustomException(ErrorCode.CART_NOT_FOUND)); -// -// if (cart.getCartItems().isEmpty()) { -// throw new CustomException(ErrorCode.CART_NOT_FOUND); -// } -// -// List orderItems = cart.getCartItems().stream() -// .map(cartItem -> { -// -// Menu menu = cartItem.getMenu(); -// menu.decreaseStockQuantity(cartItem.getQuantity()); -// -// return OrderItem.createOrderItem( -// menu, -// menu.getPrice(), -// cartItem.getQuantity() -// ); -// }) -// .toList(); -// -// Order order = Order.createOrder(user, orderItems); -// orderRepository.save(order); -// -// List rankingData = orderItems.stream() -// .map(item -> new RankingDto( -// item.getMenu().getCategory().getCafeteria().getCafeteriaId(), -// item.getMenu().getId(), -// item.getQuantity())) -// .toList(); -// -// user.setCart(null); -// cartRepository.delete(cart); -// -// TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { -// @Override -// public void afterCommit() { -// updateMenuRanking(rankingData); -// } -// }); -// -// return OrderResponse.from(order); -// } - -// private void updateMenuRanking(List rankingData) { -// for (RankingDto data : rankingData) { -// try { -// -// String key = "cafeteria:"+data.cafeteriaId()+":menu:rank"; -// stringRedisTemplate.opsForZSet() -// .incrementScore(key,String.valueOf(data.menuId()),data.quantity()); -// -// } catch (Exception e) { -// log.error("랭킹 점수 반영 실패: {}", e.getMessage()); -// } -// } -// } + public OrderResponse createOrder() { + + Long userId = SecurityUtil.getCurrentUserId(); + + User user = userRepository.findById(userId) + .orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND)); + + Cart cart = cartRepository.findByUser(user) + .orElseThrow(() -> new CustomException(ErrorCode.CART_NOT_FOUND)); + + if (cart.getCartItems().isEmpty()) { + throw new CustomException(ErrorCode.CART_NOT_FOUND); + } + + List orderItems = cart.getCartItems().stream() + .map(cartItem -> { + Menu menu = cartItem.getMenu(); + menu.decreaseStockQuantity(cartItem.getQuantity()); + + return OrderItem.createOrderItem( + menu, + menu.getPrice(), + cartItem.getQuantity() + ); + }) + .toList(); + + Order order = Order.createOrder(user, orderItems); + + orderRepository.save(order); + + user.setCart(null); + + cartRepository.delete(cart); + + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { + @Override + public void afterCommit() { + updateMenuRanking(orderItems); + } + }); + return OrderResponse.from(order); + } + + + private void updateMenuRanking(List orderItems) { + + for (OrderItem orderItem : orderItems) { + try { + Menu menu = orderItem.getMenu(); + Category category = menu.getCategory(); + Cafeteria cafeteria = category.getCafeteria(); + Long cafeteriaId = cafeteria.getCafeteriaId(); + + String key = "cafeteria:" + cafeteriaId + ":menu:rank"; + + stringRedisTemplate.opsForZSet() + .incrementScore(key, String.valueOf(menu.getId()), orderItem.getQuantity()); + + } catch (Exception e) { + log.error("랭킹 점수 반영 실패: {}", e.getMessage()); + } + } + } public void updateCategoryToReady(Long orderId, Long categoryId) { @@ -148,8 +149,4 @@ public List getOrdersByUserId(Long userId) { } -// private record RankingDto(Long cafeteriaId, Long menuId, int quantity) { -// -// } - }