Skip to content

Commit

Permalink
[feat] 식당 Id로 메뉴 목록 불러오기 (#218)
Browse files Browse the repository at this point in the history
* [feat] get menu list of store

* [refactor] change to primitive type

* [refactor] add '/'

* [refactor] transfer logic to dto

* [refactor] add path variable validation

* [refactor] add exception

* [refactor] change store delete query

* [refactor] divide method

* [refactor] change method name

* [refactor] put data in deletedMenu Repository

* [refactor] delete unused method

* [refactor] change variable name

* [fix] save deleted menu when menu deleted
  • Loading branch information
kgy1008 authored Nov 13, 2024
1 parent 68baf50 commit 963655d
Show file tree
Hide file tree
Showing 12 changed files with 170 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package org.hankki.hankkiserver.api.advice;

import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.hankki.hankkiserver.api.dto.HankkiResponse;
import org.hankki.hankkiserver.common.code.BusinessErrorCode;
import org.hankki.hankkiserver.common.code.StoreErrorCode;
import org.hankki.hankkiserver.common.code.StoreImageErrorCode;
import org.hankki.hankkiserver.common.exception.*;
import org.hankki.hankkiserver.common.exception.BadRequestException;
import org.hankki.hankkiserver.common.exception.ConflictException;
import org.hankki.hankkiserver.common.exception.NotFoundException;
import org.hankki.hankkiserver.common.exception.UnauthorizedException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
Expand Down Expand Up @@ -98,4 +102,10 @@ public HankkiResponse<Void> handleException(Exception e) {
log.error("[500] INTERNAL SERVER ERROR({}) : {}",e.getClass() , e.getMessage());
return HankkiResponse.fail(BusinessErrorCode.INTERNAL_SERVER_ERROR);
}

@ExceptionHandler(ConstraintViolationException.class)
public HankkiResponse<Void> handleConstraintViolationException(ConstraintViolationException e) {
log.warn("handleConstraintViolationException() in GlobalExceptionHandler throw ConstraintViolationException : {}", e.getMessage());
return HankkiResponse.fail(BusinessErrorCode.BAD_REQUEST);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@
import org.hankki.hankkiserver.api.menu.service.command.MenuPatchCommand;
import org.hankki.hankkiserver.api.menu.service.command.MenuPostCommand;
import org.hankki.hankkiserver.api.menu.service.command.MenusPostCommand;
import org.hankki.hankkiserver.api.menu.service.response.MenusGetResponse;
import org.hankki.hankkiserver.api.menu.service.response.MenusPostResponse;
import org.hankki.hankkiserver.api.store.controller.request.MenuPostRequest;
import org.hankki.hankkiserver.auth.UserId;
import org.hankki.hankkiserver.common.code.CommonSuccessCode;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -32,8 +35,9 @@ public class MenuController {

@DeleteMapping("/{storeId}/menus/{id}")
public HankkiResponse<Void> deleteMenu(@PathVariable("storeId") @Min(value = 1L) final long storeId,
@PathVariable("id") @Min(value = 1L) final long id) {
menuCommandService.deleteMenu(MenuDeleteCommand.of(storeId, id));
@PathVariable("id") @Min(value = 1L) final long id,
@UserId final Long userId) {
menuCommandService.deleteMenu(MenuDeleteCommand.of(storeId, id, userId));
return HankkiResponse.success(CommonSuccessCode.NO_CONTENT);
}

Expand All @@ -45,12 +49,18 @@ public HankkiResponse<Void> updateMenu(@PathVariable("storeId") @Min(value = 1L)
return HankkiResponse.success(CommonSuccessCode.OK);
}

@PostMapping("{storeId}/menus/bulk")
public HankkiResponse<MenusPostResponse> createMenus(@PathVariable @Min(value = 1L) final long storeId,
@Valid @RequestBody final List<MenuPostRequest> request) {
@PostMapping("/{storeId}/menus/bulk")
public HankkiResponse<MenusPostResponse> createMenu(@PathVariable @Min(value = 1L) final long storeId,
@Valid @RequestBody final List<MenuPostRequest> request) {
List<MenuPostCommand> command = request.stream()
.map(r -> MenuPostCommand.of(r.name(), r.price()))
.toList();
return HankkiResponse.success(CommonSuccessCode.CREATED, menuCommandService.createMenus(MenusPostCommand.of(storeId, command)));
return HankkiResponse.success(CommonSuccessCode.CREATED,
menuCommandService.createMenus(MenusPostCommand.of(storeId, command)));
}

@GetMapping("/{storeId}/menus")
public HankkiResponse<MenusGetResponse> getMenus(@PathVariable @Min(value = 1L) final long storeId) {
return HankkiResponse.success(CommonSuccessCode.OK, menuCommandService.getMenus(storeId));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.hankki.hankkiserver.api.menu.service;

import lombok.RequiredArgsConstructor;
import org.hankki.hankkiserver.domain.menu.model.DeletedMenu;
import org.hankki.hankkiserver.domain.menu.repository.DeletedMenuRepository;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class DeletedMenuUpdater {

private final DeletedMenuRepository deletedMenuRepository;

public void save(final DeletedMenu deletedMenu) {
deletedMenuRepository.save(deletedMenu);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@
import org.hankki.hankkiserver.api.menu.service.command.MenuDeleteCommand;
import org.hankki.hankkiserver.api.menu.service.command.MenuPatchCommand;
import org.hankki.hankkiserver.api.menu.service.command.MenusPostCommand;
import org.hankki.hankkiserver.api.menu.service.response.MenusGetResponse;
import org.hankki.hankkiserver.api.menu.service.response.MenusPostResponse;
import org.hankki.hankkiserver.api.store.service.StoreFinder;
import org.hankki.hankkiserver.api.store.service.StoreUpdater;
import org.hankki.hankkiserver.domain.menu.model.DeletedMenu;
import org.hankki.hankkiserver.domain.menu.model.Menu;
import org.hankki.hankkiserver.domain.store.model.Store;
import org.hankki.hankkiserver.event.EventPublisher;
import org.hankki.hankkiserver.event.store.DeleteStoreEvent;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -20,16 +25,18 @@ public class MenuCommandService {
private final MenuFinder menuFinder;
private final MenuUpdater menuUpdater;
private final StoreFinder storeFinder;
private final StoreUpdater storeUpdater;
private final DeletedMenuUpdater deletedMenuUpdater;
private final EventPublisher publisher;

@Transactional
public void deleteMenu(final MenuDeleteCommand command) {
Menu menu = menuFinder.findByStoreIdAndId(command.storeId(), command.id());
Store findStore = storeFinder.findByIdWhereDeletedIsFalse(command.storeId());
Menu menu = menuFinder.findByStoreIdAndId(findStore.getId(), command.id());
menuDeleter.deleteMenu(menu);
if (emptyMenuInStore(command.storeId())) {
deleteStore(command.storeId());
return;
}
saveToDeletedMenu(menu, findStore.getId());
updateLowestPriceInStore(storeFinder.findByIdWhereDeletedIsFalse(command.storeId()));
checkNoMenuInStore(findStore, command.userId());
}

@Transactional
Expand All @@ -51,10 +58,11 @@ public MenusPostResponse createMenus(final MenusPostCommand command) {
return MenusPostResponse.of(menus);
}

private void deleteStore(final long id) {
Store store = storeFinder.findByIdWhereDeletedIsFalse(id);
store.updateLowestPrice(0);
store.softDelete();
@Transactional(readOnly = true)
public MenusGetResponse getMenus(final long storeId) {
Store findStore = storeFinder.findByIdWhereDeletedIsFalse(storeId);
List<Menu> findMenus = menuFinder.findAllByStore(findStore);
return MenusGetResponse.of(findMenus);
}

private void updateLowestPriceInStore(final Store findStore) {
Expand All @@ -65,7 +73,15 @@ private boolean validateMenuConflict(final Store store, final String menuName) {
return menuFinder.existsByStoreAndName(store, menuName);
}

private boolean emptyMenuInStore(final long storeId) {
return !menuFinder.existsByStoreId(storeId);
private void checkNoMenuInStore(final Store store, final long userId) {
if (!menuFinder.existsByStoreId(store.getId())) {
storeUpdater.deleteStore(store.getId());
publisher.publish(DeleteStoreEvent.of(store.getName(), userId));
}
}

private void saveToDeletedMenu(final Menu menu, final long storedId) {
DeletedMenu deletedMenu = DeletedMenu.create(menu.getName(), menu.getPrice(), storedId);
deletedMenuUpdater.save(deletedMenu);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ public List<Menu> findAllByStore(final Store store) {
}

protected Menu findByStoreIdAndId(final long storeId, final long id) {
return menuRepository.findByStoreIdAndId(storeId,id).orElseThrow(() -> new NotFoundException(MenuErrorCode.MENU_NOT_FOUND));
return menuRepository.findByStoreIdAndId(storeId,id)
.orElseThrow(() -> new NotFoundException(MenuErrorCode.MENU_NOT_FOUND));
}

protected boolean existsByStoreAndName(final Store store, final String name) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

public record MenuDeleteCommand(
long storeId,
long id
long id,
long userId
) {
public static MenuDeleteCommand of(long storeId, long id) {
return new MenuDeleteCommand(storeId, id);
public static MenuDeleteCommand of(long storeId, long id, long userId) {
return new MenuDeleteCommand(storeId, id, userId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.hankki.hankkiserver.api.menu.service.response;

import org.hankki.hankkiserver.domain.menu.model.Menu;

public record MenuGetResponse (
long id,
int price,
String name
){
public static MenuGetResponse of(final Menu menu) {
return new MenuGetResponse(menu.getId(), menu.getPrice(), menu.getName());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.hankki.hankkiserver.api.menu.service.response;

import java.util.List;
import org.hankki.hankkiserver.domain.menu.model.Menu;

public record MenusGetResponse(
List<MenuGetResponse> menus
) {
public static MenusGetResponse of(final List<Menu> menus) {
List<MenuGetResponse> findmenus = menus.stream()
.map(MenuGetResponse::of)
.toList();
return new MenusGetResponse(findmenus);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.hankki.hankkiserver.api.store.service;

import lombok.RequiredArgsConstructor;
import org.hankki.hankkiserver.common.code.StoreErrorCode;
import org.hankki.hankkiserver.common.exception.NotFoundException;
import org.hankki.hankkiserver.domain.store.model.Store;
import org.hankki.hankkiserver.domain.store.repository.StoreRepository;
import org.springframework.stereotype.Component;
Expand All @@ -14,4 +16,10 @@ public class StoreUpdater {
public Store save(final Store store) {
return storeRepository.save(store);
}

public void deleteStore(final Long id) {
Store store = storeRepository.findByIdAndIsDeletedIsFalse(id)
.orElseThrow(() -> new NotFoundException(StoreErrorCode.STORE_NOT_FOUND));
store.softDelete();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.hankki.hankkiserver.domain.menu.model;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hankki.hankkiserver.domain.common.BaseCreatedAtEntity;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "deleted_menu")
public class DeletedMenu extends BaseCreatedAtEntity {

@Id
@Column(name = "deleted_menu_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "name", nullable = false)
private String name;

@Column(name = "price", nullable = false)
private int price;

@Column(name = "store_id", nullable = false)
private Long storeId;

@Builder
private DeletedMenu(final String name, final int price, final Long storeId) {
this.name = name;
this.price = price;
this.storeId = storeId;
}

public static DeletedMenu create(final String name, final int price, final Long storeId) {
return DeletedMenu.builder()
.name(name)
.price(price)
.storeId(storeId)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.hankki.hankkiserver.domain.menu.repository;

import org.hankki.hankkiserver.domain.menu.model.DeletedMenu;
import org.springframework.data.jpa.repository.JpaRepository;

public interface DeletedMenuRepository extends JpaRepository<DeletedMenu, Long> {
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public interface MenuRepository extends JpaRepository<Menu, Long> {
Optional<Menu> findByStoreIdAndId(long storeId, long id);
boolean existsByStoreAndName(Store store, String name);

@Query("SELECT MIN(m.price) FROM Menu m WHERE m.store = :store")
@Query("SELECT COALESCE(MIN(m.price), 0) FROM Menu m WHERE m.store = :store")
int findLowestPriceByStore(Store store);

boolean existsByStoreId(long storeId);
Expand Down

0 comments on commit 963655d

Please sign in to comment.