diff --git a/src/main/java/camp/woowak/lab/menu/domain/Menu.java b/src/main/java/camp/woowak/lab/menu/domain/Menu.java index 1356d366..8caa06fa 100644 --- a/src/main/java/camp/woowak/lab/menu/domain/Menu.java +++ b/src/main/java/camp/woowak/lab/menu/domain/Menu.java @@ -48,4 +48,8 @@ public Menu(Store store, MenuCategory menuCategory, String name, Integer price, this.imageUrl = imageUrl; } + public Long getId() { + return id; + } + } diff --git a/src/main/java/camp/woowak/lab/menu/domain/MenuCategoryValidator.java b/src/main/java/camp/woowak/lab/menu/domain/MenuCategoryValidator.java index 26f9c71b..a8717c16 100644 --- a/src/main/java/camp/woowak/lab/menu/domain/MenuCategoryValidator.java +++ b/src/main/java/camp/woowak/lab/menu/domain/MenuCategoryValidator.java @@ -1,6 +1,9 @@ package camp.woowak.lab.menu.domain; +import static camp.woowak.lab.menu.exception.MenuErrorCode.*; + import camp.woowak.lab.menu.exception.InvalidMenuCategoryCreationException; +import camp.woowak.lab.menu.exception.MenuErrorCode; import camp.woowak.lab.store.domain.Store; public class MenuCategoryValidator { @@ -16,7 +19,7 @@ public static void validate(final Store store, final String name) { private static void validateNotNull(final Object... targets) { for (Object target : targets) { if (target == null) { - throw new InvalidMenuCategoryCreationException(target + "은 Null 이 될 수 없습니다."); + throw new InvalidMenuCategoryCreationException(MenuErrorCode.NULL_EXIST, target + "은 Null 이 될 수 없습니다."); } } } @@ -24,15 +27,16 @@ private static void validateNotNull(final Object... targets) { private static void validateNotBlank(final String... targets) { for (String target : targets) { if (target.isBlank()) { - throw new InvalidMenuCategoryCreationException(target + "은 빈 문자열이거나 공백 문자열이 포함될 수 없습니다."); + throw new InvalidMenuCategoryCreationException(BLANK_EXIST, target + "은 빈 문자열이거나 공백 문자열이 포함될 수 없습니다."); } } } private static void validateNameLength(final String name) { if (name.length() > MAX_NAME_LENGTH) { - throw new InvalidMenuCategoryCreationException("메뉴 카테고리 이름은 " + MAX_NAME_LENGTH + "글자까지 가능합니다."); + throw new InvalidMenuCategoryCreationException(INVALID_NAME_RANGE, + "메뉴 카테고리 이름은 " + MAX_NAME_LENGTH + "글자까지 가능합니다."); } } - + } diff --git a/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java b/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java index db0bc7e9..627895af 100644 --- a/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java +++ b/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java @@ -1,5 +1,7 @@ package camp.woowak.lab.menu.domain; +import static camp.woowak.lab.menu.exception.MenuErrorCode.*; + import camp.woowak.lab.menu.exception.InvalidMenuCreationException; import camp.woowak.lab.store.domain.Store; @@ -18,7 +20,7 @@ public static void validate(final Store store, final MenuCategory menuCategory, private static void validateNotNull(final Object... targets) { for (Object target : targets) { if (target == null) { - throw new InvalidMenuCreationException(target + "은 Null 이 될 수 없습니다."); + throw new InvalidMenuCreationException(NULL_EXIST, target + "은 Null 이 될 수 없습니다."); } } } @@ -26,20 +28,20 @@ private static void validateNotNull(final Object... targets) { private static void validateNotBlank(final String... targets) { for (String target : targets) { if (target.isBlank()) { - throw new InvalidMenuCreationException(target + "은 빈 문자열이거나 공백 문자열이 포함될 수 없습니다."); + throw new InvalidMenuCreationException(BLANK_EXIST, target + "은 빈 문자열이거나 공백 문자열이 포함될 수 없습니다."); } } } private static void validateNameLength(final String name) { if (name.length() > MAX_NAME_LENGTH) { - throw new InvalidMenuCreationException("메뉴 이름은 " + MAX_NAME_LENGTH + "글자까지 가능합니다."); + throw new InvalidMenuCreationException(INVALID_NAME_RANGE, "메뉴 이름은 " + MAX_NAME_LENGTH + "글자까지 가능합니다."); } } private static void validatePriceNegative(final Integer price) { if (price <= 0) { - throw new InvalidMenuCreationException("메뉴의 가격은 양수만 가능합니다"); + throw new InvalidMenuCreationException(INVALID_PRICE, "메뉴의 가격은 양수만 가능합니다"); } } diff --git a/src/main/java/camp/woowak/lab/menu/exception/InvalidMenuCategoryCreationException.java b/src/main/java/camp/woowak/lab/menu/exception/InvalidMenuCategoryCreationException.java index 5b3aeba8..23e4dbcb 100644 --- a/src/main/java/camp/woowak/lab/menu/exception/InvalidMenuCategoryCreationException.java +++ b/src/main/java/camp/woowak/lab/menu/exception/InvalidMenuCategoryCreationException.java @@ -1,10 +1,12 @@ package camp.woowak.lab.menu.exception; -// TODO: extends CustomException -public class InvalidMenuCategoryCreationException extends RuntimeException { +import camp.woowak.lab.common.exception.BadRequestException; +import camp.woowak.lab.common.exception.ErrorCode; - public InvalidMenuCategoryCreationException(String message) { - super(message); +public class InvalidMenuCategoryCreationException extends BadRequestException { + + public InvalidMenuCategoryCreationException(ErrorCode errorCode, String message) { + super(errorCode, message); } } diff --git a/src/main/java/camp/woowak/lab/menu/exception/InvalidMenuCreationException.java b/src/main/java/camp/woowak/lab/menu/exception/InvalidMenuCreationException.java index 3e7ed471..0c824c89 100644 --- a/src/main/java/camp/woowak/lab/menu/exception/InvalidMenuCreationException.java +++ b/src/main/java/camp/woowak/lab/menu/exception/InvalidMenuCreationException.java @@ -1,10 +1,12 @@ package camp.woowak.lab.menu.exception; -// TODO: extends CustomException -public class InvalidMenuCreationException extends RuntimeException { +import camp.woowak.lab.common.exception.BadRequestException; +import camp.woowak.lab.common.exception.ErrorCode; - public InvalidMenuCreationException(String message) { - super(message); +public class InvalidMenuCreationException extends BadRequestException { + + public InvalidMenuCreationException(ErrorCode errorCode, String message) { + super(errorCode, message); } } diff --git a/src/main/java/camp/woowak/lab/menu/exception/MenuErrorCode.java b/src/main/java/camp/woowak/lab/menu/exception/MenuErrorCode.java index ab6bb88d..6e6a16c9 100644 --- a/src/main/java/camp/woowak/lab/menu/exception/MenuErrorCode.java +++ b/src/main/java/camp/woowak/lab/menu/exception/MenuErrorCode.java @@ -5,8 +5,17 @@ import camp.woowak.lab.common.exception.ErrorCode; public enum MenuErrorCode implements ErrorCode { + DUPLICATE_MENU_CATEGORY(HttpStatus.BAD_REQUEST, "m_1", "이미 생성된 카테고리입니다."), - UNAUTHORIZED_MENU_CATEGORY_CREATION(HttpStatus.FORBIDDEN, "m_2", "점주만 카테고리를 생성할 수 있습니다."); + UNAUTHORIZED_MENU_CATEGORY_CREATION(HttpStatus.FORBIDDEN, "m_2", "점주만 카테고리를 생성할 수 있습니다."), + + NULL_EXIST(HttpStatus.BAD_REQUEST, "M0", "값이 존재해야 합니다."), + BLANK_EXIST(HttpStatus.BAD_REQUEST, "M1", "빈 문자열이거나 공백 문자열이 포함되면 안됩니다."), + INVALID_NAME_RANGE(HttpStatus.BAD_REQUEST, "M2", "이름의 길이 범위를 벗어났습니다."), + + INVALID_PRICE(HttpStatus.BAD_REQUEST, "M3", "메뉴의 가격 범위를 벗어났습니다."), + + NOT_FOUND_MENU_CATEGORY(HttpStatus.BAD_REQUEST, "M3", "메뉴 카테고리를 찾을 수 없습니다."); private final int status; private final String errorCode; diff --git a/src/main/java/camp/woowak/lab/menu/exception/NotFoundMenuCategoryException.java b/src/main/java/camp/woowak/lab/menu/exception/NotFoundMenuCategoryException.java index 4e8ef121..44a62528 100644 --- a/src/main/java/camp/woowak/lab/menu/exception/NotFoundMenuCategoryException.java +++ b/src/main/java/camp/woowak/lab/menu/exception/NotFoundMenuCategoryException.java @@ -1,10 +1,12 @@ package camp.woowak.lab.menu.exception; -// TODO: extends CustomException -public class NotFoundMenuCategoryException extends RuntimeException { +import camp.woowak.lab.common.exception.BadRequestException; +import camp.woowak.lab.common.exception.ErrorCode; - public NotFoundMenuCategoryException(String message) { - super(message); +public class NotFoundMenuCategoryException extends BadRequestException { + + public NotFoundMenuCategoryException(ErrorCode errorCode, String message) { + super(errorCode, message); } - + } diff --git a/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java b/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java index b8393cc4..f0b732b6 100644 --- a/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java +++ b/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java @@ -1,10 +1,10 @@ package camp.woowak.lab.store.domain; -import static camp.woowak.lab.store.exception.StoreException.ErrorCode.*; +import static camp.woowak.lab.store.exception.StoreErrorCode.*; import java.time.LocalDateTime; -import camp.woowak.lab.store.exception.StoreException; +import camp.woowak.lab.store.exception.InvalidStoreCreationException; import camp.woowak.lab.vendor.domain.Vendor; public class StoreValidator { @@ -31,7 +31,7 @@ public static void validate(final Vendor owner, StoreCategory storeCategory, fin private static void validateNotNull(Object... targets) { for (Object target : targets) { if (target == null) { - throw new StoreException(NULL_EXIST); + throw new InvalidStoreCreationException(NULL_EXIST, "Null 값은 허용하지 않습니다."); } } } @@ -40,25 +40,28 @@ private static void validateName(final String name) { if (MIN_NAME_LENGTH <= name.length() && name.length() <= MAX_NAME_LENGTH) { return; } - throw new StoreException(INVALID_NAME_RANGE); + throw new InvalidStoreCreationException(INVALID_NAME_RANGE, + "이름의 길이는 " + MIN_NAME_LENGTH + " ~ " + MAX_NAME_LENGTH + " 만 가능합니다. cur: " + name.length()); } private static void validateAddress(final String address) { if (StoreAddress.DEFAULT_DISTRICT.equals(address)) { return; } - throw new StoreException(INVALID_ADDRESS); + throw new InvalidStoreCreationException(INVALID_ADDRESS, "주소는 송파만 가능합니다. cur: " + address); } private static void validateMinOrderPrice(final Integer minOrderPrice) { if (minOrderPrice < MIN_ORDER_PRICE) { - throw new StoreException(INVALID_MIN_ORDER_PRICE); + throw new InvalidStoreCreationException(INVALID_MIN_ORDER_PRICE, + "최소 주문 금액은 " + MIN_ORDER_PRICE + " 보다 이상이어야 합니다. cur: " + minOrderPrice); } } private static void validateUnitOrderPrice(final Integer minOrderPrice) { if (minOrderPrice % UNIT_OF_MIN_ORDER_PRICE != 0) { - throw new StoreException(INVALID_UNIT_OF_MIN_ORDER_PRICE); + throw new InvalidStoreCreationException(INVALID_UNIT_OF_MIN_ORDER_PRICE, + "최소 주문 금액의 단위는 천원이어야 합니다. cur: " + minOrderPrice); } } @@ -66,19 +69,20 @@ private static void validateTime(final LocalDateTime startTime, final LocalDateTime endTime ) { if (isInvalidStoreTimeUnit(startTime)) { - throw new StoreException(INVALID_TIME_UNIT); + throw new InvalidStoreCreationException(INVALID_TIME_UNIT, "가게 시간은 분단위까지 가능합니다. cur: " + startTime); } if (isInvalidStoreTimeUnit(endTime)) { - throw new StoreException(INVALID_TIME_UNIT); + throw new InvalidStoreCreationException(INVALID_TIME_UNIT, "가게 시간은 분단위까지 가능합니다. cur:" + endTime); } if (endTime.isBefore(startTime)) { - throw new StoreException(INVALID_TIME); + throw new InvalidStoreCreationException(INVALID_TIME, + "가게 종료 시간이 시작 시간보다 이전입니다. cur:" + startTime + "," + endTime); } if (startTime.isEqual(endTime)) { - throw new StoreException(INVALID_TIME); + throw new InvalidStoreCreationException(INVALID_TIME, "가게 시작 시간과 종료 시간이 같습니다. cur:" + startTime + endTime); } } diff --git a/src/main/java/camp/woowak/lab/store/exception/InvalidStoreCreationException.java b/src/main/java/camp/woowak/lab/store/exception/InvalidStoreCreationException.java new file mode 100644 index 00000000..18845ea2 --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/exception/InvalidStoreCreationException.java @@ -0,0 +1,12 @@ +package camp.woowak.lab.store.exception; + +import camp.woowak.lab.common.exception.BadRequestException; +import camp.woowak.lab.common.exception.ErrorCode; + +public class InvalidStoreCreationException extends BadRequestException { + + public InvalidStoreCreationException(ErrorCode errorCode, String message) { + super(errorCode, message); + } + +} diff --git a/src/main/java/camp/woowak/lab/store/exception/NotEqualsOwnerException.java b/src/main/java/camp/woowak/lab/store/exception/NotEqualsOwnerException.java index f122216c..ae4807b8 100644 --- a/src/main/java/camp/woowak/lab/store/exception/NotEqualsOwnerException.java +++ b/src/main/java/camp/woowak/lab/store/exception/NotEqualsOwnerException.java @@ -1,9 +1,13 @@ package camp.woowak.lab.store.exception; -public class NotEqualsOwnerException extends RuntimeException { +import static camp.woowak.lab.store.exception.StoreErrorCode.*; + +import camp.woowak.lab.common.exception.BadRequestException; + +public class NotEqualsOwnerException extends BadRequestException { public NotEqualsOwnerException(String message) { - super(message); + super(NOT_EQUALS_VENDOR, message); } } diff --git a/src/main/java/camp/woowak/lab/store/exception/NotFoundStoreCategoryException.java b/src/main/java/camp/woowak/lab/store/exception/NotFoundStoreCategoryException.java new file mode 100644 index 00000000..3f9caa05 --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/exception/NotFoundStoreCategoryException.java @@ -0,0 +1,11 @@ +package camp.woowak.lab.store.exception; + +import camp.woowak.lab.common.exception.NotFoundException; + +public class NotFoundStoreCategoryException extends NotFoundException { + + public NotFoundStoreCategoryException(String message) { + super(StoreErrorCode.INVALID_STORE_CATEGORY, message); + } + +} diff --git a/src/main/java/camp/woowak/lab/store/exception/NotFoundStoreException.java b/src/main/java/camp/woowak/lab/store/exception/NotFoundStoreException.java index 42848feb..bbe04bb3 100644 --- a/src/main/java/camp/woowak/lab/store/exception/NotFoundStoreException.java +++ b/src/main/java/camp/woowak/lab/store/exception/NotFoundStoreException.java @@ -1,10 +1,13 @@ package camp.woowak.lab.store.exception; -// TODO: 404Exception 상속하도록 수정 -public class NotFoundStoreException extends RuntimeException { +import static camp.woowak.lab.store.exception.StoreErrorCode.*; + +import camp.woowak.lab.common.exception.NotFoundException; + +public class NotFoundStoreException extends NotFoundException { public NotFoundStoreException(String message) { - super(message); + super(NOT_FOUND_STORE, message); } } diff --git a/src/main/java/camp/woowak/lab/store/exception/StoreErrorCode.java b/src/main/java/camp/woowak/lab/store/exception/StoreErrorCode.java new file mode 100644 index 00000000..5379fbff --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/exception/StoreErrorCode.java @@ -0,0 +1,49 @@ +package camp.woowak.lab.store.exception; + +import org.springframework.http.HttpStatus; + +import camp.woowak.lab.common.exception.ErrorCode; + +public enum StoreErrorCode implements ErrorCode { + NULL_EXIST(HttpStatus.BAD_REQUEST, "S0", "값이 존재해야 합니다."), + + INVALID_NAME_RANGE(HttpStatus.BAD_REQUEST, "S1", "가게 이름은 2글자 ~ 10글자 이어야합니다."), + + INVALID_ADDRESS(HttpStatus.BAD_REQUEST, "S2", "가게 주소는 송파구만 가능합니다."), + + INVALID_MIN_ORDER_PRICE(HttpStatus.BAD_REQUEST, "S3", "최소 주문 금액은 5,000원 이상이어야 합니다."), + INVALID_UNIT_OF_MIN_ORDER_PRICE(HttpStatus.BAD_REQUEST, "S4", "최소 주문 금액은 1,000원 단위이어야 합니다."), + + INVALID_TIME_UNIT(HttpStatus.BAD_REQUEST, "S5", "가게 시작 시간은 분 단위까지 가능합니다"), + INVALID_TIME(HttpStatus.BAD_REQUEST, "S6", "가게 시작 시간은 종료 시간보다 이전이어야 합니다"), + + INVALID_STORE_CATEGORY(HttpStatus.BAD_REQUEST, "S7", "존재하지 않는 가게 카테고리입니다."), + + NOT_EQUALS_VENDOR(HttpStatus.BAD_REQUEST, "S8", "가게의 점주와 일치하지 않습니다."), + NOT_FOUND_STORE(HttpStatus.BAD_REQUEST, "S9", "가게를 찾을 수 없습니다."); + + private final int status; + private final String errorCode; + private final String message; + + StoreErrorCode(HttpStatus status, String errorCode, String message) { + this.status = status.value(); + this.errorCode = errorCode; + this.message = message; + } + + @Override + public int getStatus() { + return status; + } + + @Override + public String getErrorCode() { + return errorCode; + } + + @Override + public String getMessage() { + return message; + } +} diff --git a/src/main/java/camp/woowak/lab/store/exception/StoreException.java b/src/main/java/camp/woowak/lab/store/exception/StoreException.java deleted file mode 100644 index a108d391..00000000 --- a/src/main/java/camp/woowak/lab/store/exception/StoreException.java +++ /dev/null @@ -1,39 +0,0 @@ -package camp.woowak.lab.store.exception; - -import lombok.Getter; - -@Getter -public class StoreException extends RuntimeException { - - private final ErrorCode errorCode; - - public StoreException(final ErrorCode errorCode) { - super(errorCode.getMessage()); - this.errorCode = errorCode; - } - - @Getter - public enum ErrorCode { - - NULL_EXIST("NULL 값이 존재합니다."), - INVALID_NAME_RANGE("가게 이름은 2글자 ~ 10글자 이어야합니다."), - - INVALID_ADDRESS("가게 주소는 송파구만 가능합니다."), - - INVALID_MIN_ORDER_PRICE("최소 주문 금액은 5,000원 이상이어야 합니다."), - INVALID_UNIT_OF_MIN_ORDER_PRICE("최소 주문 금액은 1,000원 단위이어야 합니다."), - - INVALID_TIME_UNIT("가게 시작 시간은 분 단위까지 가능합니다"), - INVALID_TIME("가게 시작 시간은 종료 시간보다 이전이어야 합니다"), - - INVALID_STORE_CATEGORY("존재하지 않는 가게 카테고리입니다."); - - private final String message; - - ErrorCode(String message) { - this.message = message; - } - - } - -} diff --git a/src/main/java/camp/woowak/lab/store/service/StoreMenuRegistrationService.java b/src/main/java/camp/woowak/lab/store/service/StoreMenuRegistrationService.java index 6b8af6b4..47399f2c 100644 --- a/src/main/java/camp/woowak/lab/store/service/StoreMenuRegistrationService.java +++ b/src/main/java/camp/woowak/lab/store/service/StoreMenuRegistrationService.java @@ -1,19 +1,27 @@ package camp.woowak.lab.store.service; +import static camp.woowak.lab.menu.exception.MenuErrorCode.*; + import java.util.List; +import java.util.UUID; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import camp.woowak.lab.menu.domain.Menu; import camp.woowak.lab.menu.domain.MenuCategory; +import camp.woowak.lab.menu.exception.InvalidMenuCreationException; import camp.woowak.lab.menu.exception.NotFoundMenuCategoryException; import camp.woowak.lab.menu.repository.MenuCategoryRepository; import camp.woowak.lab.menu.repository.MenuRepository; import camp.woowak.lab.store.domain.Store; import camp.woowak.lab.store.exception.NotFoundStoreException; import camp.woowak.lab.store.repository.StoreRepository; -import camp.woowak.lab.store.service.dto.StoreMenuRegistrationRequest; +import camp.woowak.lab.store.service.command.MenuLineItem; +import camp.woowak.lab.store.service.command.StoreMenuRegistrationCommand; import camp.woowak.lab.vendor.domain.Vendor; +import camp.woowak.lab.vendor.exception.NotFoundVendorException; +import camp.woowak.lab.vendor.repository.VendorRepository; import lombok.RequiredArgsConstructor; /** @@ -27,18 +35,37 @@ @RequiredArgsConstructor public class StoreMenuRegistrationService { + private final VendorRepository vendorRepository; private final StoreRepository storeRepository; private final MenuRepository menuRepository; private final MenuCategoryRepository menuCategoryRepository; - public void storeMenuRegistration(final Vendor owner, final StoreMenuRegistrationRequest request) { - Store store = findStoreBy(request.storeId()); + /** + * @throws NotFoundVendorException UUID 기준 가게 점주가 존재하지 않을 때 발생 + * @throws NotFoundStoreException 가게 ID 기준 가게가 존재하지 않을 때 발생 + * @throws NotFoundMenuCategoryException 가게와 메뉴카테고리 이름으로 메뉴카테고리를 찾지 못할 때 발생 + * @throws InvalidMenuCreationException 메뉴 객체 생성 검증 실패 시 발생 + */ + @Transactional + public List storeMenuRegistration(final StoreMenuRegistrationCommand command) { + Vendor owner = findVendor(command.vendorId()); + + Store store = findStoreBy(command.storeId()); store.validateOwner(owner); - - List menuLineItems = request.menuItems(); + + List menuLineItems = command.menuItems(); List menus = createMenus(store, menuLineItems); - menuRepository.saveAll(menus); + List menuIds = menuRepository.saveAll(menus); + + return menuIds.stream() + .map(Menu::getId) + .toList(); + } + + private Vendor findVendor(final UUID vendorId) { + return vendorRepository.findById(vendorId) + .orElseThrow(NotFoundVendorException::new); } private Store findStoreBy(final Long storeId) { @@ -47,21 +74,22 @@ private Store findStoreBy(final Long storeId) { } private List createMenus(final Store store, - final List menuLineItems + final List menuLineItems ) { return menuLineItems.stream() .map(menuLineItem -> createMenu(store, menuLineItem)) .toList(); } - private Menu createMenu(final Store store, final StoreMenuRegistrationRequest.MenuLineItem menuLineItem) { + private Menu createMenu(final Store store, final MenuLineItem menuLineItem) { MenuCategory menuCategory = findMenuCategoryBy(store, menuLineItem.categoryName()); return new Menu(store, menuCategory, menuLineItem.name(), menuLineItem.price(), menuLineItem.imageUrl()); } private MenuCategory findMenuCategoryBy(final Store store, final String manuCategoryName) { return menuCategoryRepository.findByStoreIdAndName(store.getId(), manuCategoryName) - .orElseThrow(() -> new NotFoundMenuCategoryException(store + ", " + manuCategoryName + " 의 메뉴카테고리가 없습니다.")); + .orElseThrow(() -> new NotFoundMenuCategoryException(NOT_FOUND_MENU_CATEGORY, + store + ", " + manuCategoryName + " 의 메뉴카테고리가 없습니다.")); } } diff --git a/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java b/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java index 88f8d533..5731675e 100644 --- a/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java +++ b/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java @@ -1,49 +1,63 @@ package camp.woowak.lab.store.service; -import static camp.woowak.lab.store.exception.StoreException.ErrorCode.*; +import java.util.UUID; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import camp.woowak.lab.store.domain.Store; import camp.woowak.lab.store.domain.StoreCategory; -import camp.woowak.lab.store.exception.StoreException; +import camp.woowak.lab.store.exception.NotFoundStoreCategoryException; import camp.woowak.lab.store.repository.StoreCategoryRepository; import camp.woowak.lab.store.repository.StoreRepository; -import camp.woowak.lab.store.service.dto.StoreRegistrationRequest; +import camp.woowak.lab.store.service.command.StoreRegistrationCommand; import camp.woowak.lab.vendor.domain.Vendor; +import camp.woowak.lab.vendor.exception.NotFoundVendorException; +import camp.woowak.lab.vendor.repository.VendorRepository; import lombok.RequiredArgsConstructor; @Service @RequiredArgsConstructor public class StoreRegistrationService { + private final VendorRepository vendorRepository; private final StoreRepository storeRepository; private final StoreCategoryRepository storeCategoryRepository; /** - * @throws StoreException Store 객체 검증 실패, 존재하지 않는 이름의 가게 카테고리 + * @throws camp.woowak.lab.store.exception.InvalidStoreCreationException Store 객체 생성 검증에 실패시 + * @throws NotFoundStoreCategoryException 가게 카테고리 이름에 대한 가게 카테고리가 존재하지 않을 시 + * @throws NotFoundVendorException UUID 에 대한 가게 점주가 존재하지 않을 시 */ @Transactional - public void storeRegistration(final Vendor vendor, final StoreRegistrationRequest request) { - final StoreCategory storeCategory = findStoreCategoryByName(request.storeCategoryName()); - final Store store = createStore(vendor, storeCategory, request); + public Long storeRegistration(final StoreRegistrationCommand command) { + final Vendor vendor = findVendor(command.vendorId()); + + final StoreCategory storeCategory = findStoreCategoryByName(command.storeCategoryName()); + final Store store = createStore(vendor, storeCategory, command); storeRepository.save(store); + + return store.getId(); + } + + private Vendor findVendor(final UUID vendorId) { + return vendorRepository.findById(vendorId) + .orElseThrow(NotFoundVendorException::new); } - private Store createStore(Vendor vendor, StoreCategory storeCategory, StoreRegistrationRequest request) { - return new Store(vendor, storeCategory, request.storeName(), - request.storeAddress(), - request.storePhoneNumber(), - request.storeMinOrderPrice(), - request.storeStartTime(), - request.storeEndTime()); + private Store createStore(Vendor vendor, StoreCategory storeCategory, StoreRegistrationCommand command) { + return new Store(vendor, storeCategory, command.storeName(), + command.storeAddress(), + command.storePhoneNumber(), + command.storeMinOrderPrice(), + command.storeStartTime(), + command.storeEndTime()); } private StoreCategory findStoreCategoryByName(final String name) { return storeCategoryRepository.findByName(name) - .orElseThrow(() -> new StoreException(INVALID_STORE_CATEGORY)); + .orElseThrow(() -> new NotFoundStoreCategoryException("해당 이름의 가게 카테고리가 없습니다. " + name)); } } diff --git a/src/main/java/camp/woowak/lab/store/service/command/MenuLineItem.java b/src/main/java/camp/woowak/lab/store/service/command/MenuLineItem.java new file mode 100644 index 00000000..4aa7582c --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/service/command/MenuLineItem.java @@ -0,0 +1,19 @@ +package camp.woowak.lab.store.service.command; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +public record MenuLineItem( + @NotBlank(message = "메뉴 이름은 필수값입니다.") + String name, + + @NotBlank(message = "사진은 필수값입니다.") + String imageUrl, + + @NotBlank(message = "메뉴 카테고리 이름은 필수값입니다.") + String categoryName, + + @NotNull(message = "메뉴 가격은 필수값입니다.") + Integer price +) { +} diff --git a/src/main/java/camp/woowak/lab/store/service/command/StoreMenuRegistrationCommand.java b/src/main/java/camp/woowak/lab/store/service/command/StoreMenuRegistrationCommand.java new file mode 100644 index 00000000..75245a39 --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/service/command/StoreMenuRegistrationCommand.java @@ -0,0 +1,11 @@ +package camp.woowak.lab.store.service.command; + +import java.util.List; +import java.util.UUID; + +public record StoreMenuRegistrationCommand( + UUID vendorId, + Long storeId, + List menuItems +) { +} diff --git a/src/main/java/camp/woowak/lab/store/service/command/StoreRegistrationCommand.java b/src/main/java/camp/woowak/lab/store/service/command/StoreRegistrationCommand.java new file mode 100644 index 00000000..35445d0a --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/service/command/StoreRegistrationCommand.java @@ -0,0 +1,18 @@ +package camp.woowak.lab.store.service.command; + +import java.time.LocalDateTime; +import java.util.UUID; + +public record StoreRegistrationCommand( + + UUID vendorId, + + String storeName, + String storeAddress, + String storePhoneNumber, + String storeCategoryName, + Integer storeMinOrderPrice, + LocalDateTime storeStartTime, + LocalDateTime storeEndTime +) { +} diff --git a/src/main/java/camp/woowak/lab/store/service/dto/StoreMenuRegistrationRequest.java b/src/main/java/camp/woowak/lab/store/service/dto/StoreMenuRegistrationRequest.java deleted file mode 100644 index 5a588aaa..00000000 --- a/src/main/java/camp/woowak/lab/store/service/dto/StoreMenuRegistrationRequest.java +++ /dev/null @@ -1,31 +0,0 @@ -package camp.woowak.lab.store.service.dto; - -import java.util.List; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; - -public record StoreMenuRegistrationRequest( - @NotBlank(message = "가게 ID는 필수값입니다.") - Long storeId, - - @NotNull(message = "등록할 메뉴는 필수값입니다.") - List menuItems -) { - - public record MenuLineItem( - @NotBlank(message = "메뉴 이름은 필수값입니다.") - String name, - - @NotBlank(message = "사진은 필수값입니다.") - String imageUrl, - - @NotBlank(message = "메뉴 카테고리 이름은 필수값입니다.") - String categoryName, - - @NotNull(message = "메뉴 가격은 필수값입니다.") - Integer price - ) { - } - -} diff --git a/src/main/java/camp/woowak/lab/web/api/store/StoreApiController.java b/src/main/java/camp/woowak/lab/web/api/store/StoreApiController.java index 7a81f61b..048a25fc 100644 --- a/src/main/java/camp/woowak/lab/web/api/store/StoreApiController.java +++ b/src/main/java/camp/woowak/lab/web/api/store/StoreApiController.java @@ -1,6 +1,7 @@ package camp.woowak.lab.web.api.store; -import org.springframework.http.ResponseEntity; +import java.util.List; + import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -8,14 +9,18 @@ import camp.woowak.lab.menu.service.MenuCategoryRegistrationService; import camp.woowak.lab.menu.service.command.MenuCategoryRegistrationCommand; +import camp.woowak.lab.store.service.StoreMenuRegistrationService; import camp.woowak.lab.store.service.StoreRegistrationService; -import camp.woowak.lab.store.service.dto.StoreRegistrationRequest; -import camp.woowak.lab.vendor.domain.Vendor; -import camp.woowak.lab.vendor.repository.VendorRepository; +import camp.woowak.lab.store.service.command.StoreMenuRegistrationCommand; +import camp.woowak.lab.store.service.command.StoreRegistrationCommand; import camp.woowak.lab.web.authentication.LoginVendor; import camp.woowak.lab.web.authentication.annotation.AuthenticationPrincipal; import camp.woowak.lab.web.dto.request.store.MenuCategoryRegistrationRequest; +import camp.woowak.lab.web.dto.request.store.StoreMenuRegistrationRequest; +import camp.woowak.lab.web.dto.request.store.StoreRegistrationRequest; import camp.woowak.lab.web.dto.response.store.MenuCategoryRegistrationResponse; +import camp.woowak.lab.web.dto.response.store.StoreMenuRegistrationResponse; +import camp.woowak.lab.web.dto.response.store.StoreRegistrationResponse; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; @@ -24,17 +29,41 @@ public class StoreApiController { private final StoreRegistrationService storeRegistrationService; + private final StoreMenuRegistrationService storeMenuRegistrationService; private final MenuCategoryRegistrationService menuCategoryRegistrationService; - private final VendorRepository vendorRepository; - // TODO: 서비스 메서드 코드 스타일 통일하면서 dtoResponse 반환하도록 수정할 예정 @PostMapping("/stores") - public ResponseEntity storeRegistration(@AuthenticationPrincipal final LoginVendor loginVendor, - @Valid @RequestBody final StoreRegistrationRequest request + public StoreRegistrationResponse storeRegistration(@AuthenticationPrincipal final LoginVendor loginVendor, + final @Valid @RequestBody StoreRegistrationRequest request + ) { + StoreRegistrationCommand command = mapBy(loginVendor, request); + + Long storeId = storeRegistrationService.storeRegistration(command); + return new StoreRegistrationResponse(storeId); + } + + private StoreRegistrationCommand mapBy(LoginVendor loginVendor, StoreRegistrationRequest request) { + return new StoreRegistrationCommand( + loginVendor.getId(), + request.storeName(), + request.storeAddress(), + request.storePhoneNumber(), + request.storeCategoryName(), + request.storeMinOrderPrice(), + request.storeStartTime(), + request.storeEndTime()); + } + + @PostMapping("/stores/{storeId}/menus") + public StoreMenuRegistrationResponse storeMenuRegistration(final @AuthenticationPrincipal LoginVendor loginVendor, + final @PathVariable Long storeId, + final @Valid @RequestBody StoreMenuRegistrationRequest request ) { - Vendor vendor = vendorRepository.findById(loginVendor.getId()).orElseThrow(); - storeRegistrationService.storeRegistration(vendor, request); - return ResponseEntity.ok().build(); + StoreMenuRegistrationCommand command = + new StoreMenuRegistrationCommand(loginVendor.getId(), storeId, request.menuItems()); + + List menuIds = storeMenuRegistrationService.storeMenuRegistration(command); + return new StoreMenuRegistrationResponse(menuIds); } @PostMapping("/stores/{storeId}/category") diff --git a/src/main/java/camp/woowak/lab/web/api/store/StoreExceptionHandler.java b/src/main/java/camp/woowak/lab/web/api/store/StoreExceptionHandler.java index e532f5b3..5477bc48 100644 --- a/src/main/java/camp/woowak/lab/web/api/store/StoreExceptionHandler.java +++ b/src/main/java/camp/woowak/lab/web/api/store/StoreExceptionHandler.java @@ -1,20 +1,94 @@ package camp.woowak.lab.web.api.store; import org.springframework.http.HttpStatus; +import org.springframework.http.ProblemDetail; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; -import camp.woowak.lab.store.exception.StoreException; +import camp.woowak.lab.common.advice.DomainExceptionHandler; +import camp.woowak.lab.common.exception.ErrorCode; +import camp.woowak.lab.common.exception.HttpStatusException; +import camp.woowak.lab.menu.exception.InvalidMenuCategoryCreationException; +import camp.woowak.lab.menu.exception.InvalidMenuCreationException; +import camp.woowak.lab.menu.exception.NotFoundMenuCategoryException; +import camp.woowak.lab.store.exception.InvalidStoreCreationException; +import camp.woowak.lab.store.exception.NotEqualsOwnerException; +import camp.woowak.lab.store.exception.NotFoundStoreCategoryException; +import camp.woowak.lab.store.exception.NotFoundStoreException; import lombok.extern.slf4j.Slf4j; @Slf4j -@RestControllerAdvice +@DomainExceptionHandler(basePackageClasses = StoreApiController.class) public class StoreExceptionHandler { - @ExceptionHandler(StoreException.class) - public ResponseEntity handleException(StoreException exception) { - log.warn(exception.getMessage(), exception); - return new ResponseEntity<>("fail", HttpStatus.BAD_REQUEST); + @ExceptionHandler(InvalidStoreCreationException.class) + public ResponseEntity handleException(InvalidStoreCreationException exception) { + log.warn("Bad Request", exception); + HttpStatus badRequest = HttpStatus.BAD_REQUEST; + ProblemDetail problemDetail = getProblemDetail(exception, badRequest); + + return ResponseEntity.status(badRequest).body(problemDetail); + } + + @ExceptionHandler(NotEqualsOwnerException.class) + public ResponseEntity handleException(NotEqualsOwnerException exception) { + log.warn("Bad Request", exception); + HttpStatus badRequest = HttpStatus.BAD_REQUEST; + ProblemDetail problemDetail = getProblemDetail(exception, badRequest); + + return ResponseEntity.status(badRequest).body(problemDetail); + } + + @ExceptionHandler(NotFoundStoreCategoryException.class) + public ResponseEntity handleException(NotFoundStoreCategoryException exception) { + log.warn("Not Found", exception); + HttpStatus badRequest = HttpStatus.BAD_REQUEST; + ProblemDetail problemDetail = getProblemDetail(exception, badRequest); + + return ResponseEntity.status(badRequest).body(problemDetail); + } + + @ExceptionHandler(NotFoundStoreException.class) + public ResponseEntity handleException(NotFoundStoreException exception) { + log.warn("Not Found", exception); + HttpStatus badRequest = HttpStatus.NOT_FOUND; + ProblemDetail problemDetail = getProblemDetail(exception, badRequest); + + return ResponseEntity.status(badRequest).body(problemDetail); + } + + @ExceptionHandler(InvalidMenuCategoryCreationException.class) + public ResponseEntity handleException(InvalidMenuCategoryCreationException exception) { + log.warn("Bad Request", exception); + HttpStatus badRequest = HttpStatus.BAD_REQUEST; + ProblemDetail problemDetail = getProblemDetail(exception, badRequest); + + return ResponseEntity.status(badRequest).body(problemDetail); + } + + @ExceptionHandler(InvalidMenuCreationException.class) + public ResponseEntity handleException(InvalidMenuCreationException exception) { + log.warn("Bad Request", exception); + HttpStatus badRequest = HttpStatus.BAD_REQUEST; + ProblemDetail problemDetail = getProblemDetail(exception, badRequest); + + return ResponseEntity.status(badRequest).body(problemDetail); + } + + @ExceptionHandler(NotFoundMenuCategoryException.class) + public ResponseEntity handleException(NotFoundMenuCategoryException exception) { + log.warn("Not Found", exception); + HttpStatus badRequest = HttpStatus.NOT_FOUND; + ProblemDetail problemDetail = getProblemDetail(exception, badRequest); + + return ResponseEntity.status(badRequest).body(problemDetail); + } + + private ProblemDetail getProblemDetail(HttpStatusException exception, HttpStatus httpStatus) { + ErrorCode errorCode = exception.errorCode(); + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(httpStatus, errorCode.getMessage()); + problemDetail.setProperty("errorCode", errorCode.getErrorCode()); + + return problemDetail; } } diff --git a/src/main/java/camp/woowak/lab/web/dto/request/store/StoreMenuRegistrationRequest.java b/src/main/java/camp/woowak/lab/web/dto/request/store/StoreMenuRegistrationRequest.java new file mode 100644 index 00000000..ccda457b --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/dto/request/store/StoreMenuRegistrationRequest.java @@ -0,0 +1,12 @@ +package camp.woowak.lab.web.dto.request.store; + +import java.util.List; + +import camp.woowak.lab.store.service.command.MenuLineItem; +import jakarta.validation.constraints.NotNull; + +public record StoreMenuRegistrationRequest( + @NotNull(message = "등록할 메뉴는 필수값입니다.") + List menuItems +) { +} diff --git a/src/main/java/camp/woowak/lab/store/service/dto/StoreRegistrationRequest.java b/src/main/java/camp/woowak/lab/web/dto/request/store/StoreRegistrationRequest.java similarity index 94% rename from src/main/java/camp/woowak/lab/store/service/dto/StoreRegistrationRequest.java rename to src/main/java/camp/woowak/lab/web/dto/request/store/StoreRegistrationRequest.java index ebf13716..3f2536b9 100644 --- a/src/main/java/camp/woowak/lab/store/service/dto/StoreRegistrationRequest.java +++ b/src/main/java/camp/woowak/lab/web/dto/request/store/StoreRegistrationRequest.java @@ -1,4 +1,4 @@ -package camp.woowak.lab.store.service.dto; +package camp.woowak.lab.web.dto.request.store; import java.time.LocalDateTime; diff --git a/src/main/java/camp/woowak/lab/web/dto/response/store/StoreMenuRegistrationResponse.java b/src/main/java/camp/woowak/lab/web/dto/response/store/StoreMenuRegistrationResponse.java new file mode 100644 index 00000000..c72c833c --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/dto/response/store/StoreMenuRegistrationResponse.java @@ -0,0 +1,6 @@ +package camp.woowak.lab.web.dto.response.store; + +import java.util.List; + +public record StoreMenuRegistrationResponse(List menuIds) { +} diff --git a/src/main/java/camp/woowak/lab/web/dto/response/store/StoreRegistrationResponse.java b/src/main/java/camp/woowak/lab/web/dto/response/store/StoreRegistrationResponse.java new file mode 100644 index 00000000..d80d6d1a --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/dto/response/store/StoreRegistrationResponse.java @@ -0,0 +1,4 @@ +package camp.woowak.lab.web.dto.response.store; + +public record StoreRegistrationResponse(Long storeId) { +} diff --git a/src/test/java/camp/woowak/lab/store/domain/StoreTest.java b/src/test/java/camp/woowak/lab/store/domain/StoreTest.java index 5d59985c..e006e343 100644 --- a/src/test/java/camp/woowak/lab/store/domain/StoreTest.java +++ b/src/test/java/camp/woowak/lab/store/domain/StoreTest.java @@ -1,6 +1,5 @@ package camp.woowak.lab.store.domain; -import static camp.woowak.lab.store.exception.StoreException.ErrorCode.*; import static org.assertj.core.api.Assertions.*; import java.time.LocalDateTime; @@ -12,7 +11,7 @@ import camp.woowak.lab.infra.date.DateTimeProvider; import camp.woowak.lab.payaccount.domain.PayAccount; import camp.woowak.lab.payaccount.domain.TestPayAccount; -import camp.woowak.lab.store.exception.StoreException; +import camp.woowak.lab.store.exception.InvalidStoreCreationException; import camp.woowak.lab.vendor.domain.Vendor; import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; import camp.woowak.lab.web.authentication.PasswordEncoder; @@ -64,8 +63,7 @@ void lessThanMinOrderPrice() { () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, lessThanMinOrderPrice, validStartTimeFixture, validEndTimeFixture)) - .isInstanceOf(StoreException.class) - .hasMessage(INVALID_MIN_ORDER_PRICE.getMessage()); + .isInstanceOf(InvalidStoreCreationException.class); } @Test @@ -83,7 +81,7 @@ void validUnitOrderPrice() { } @Test - @DisplayName("[Exception] 1,000원 단위가 아니면 StoreException 이 발생한다") + @DisplayName("[Exception] 1,000원 단위가 아니면 InvalidStoreCreationException 이 발생한다") void inValidUnitOrderPrice() { // given int inValidUnitOrderPrice = 5001; @@ -93,8 +91,7 @@ void inValidUnitOrderPrice() { () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, inValidUnitOrderPrice, validStartTimeFixture, validEndTimeFixture)) - .isInstanceOf(StoreException.class) - .hasMessage(INVALID_UNIT_OF_MIN_ORDER_PRICE.getMessage()); + .isInstanceOf(InvalidStoreCreationException.class); } } @@ -128,8 +125,7 @@ void endTimeSameWithStartTime() { () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, validMinOrderPriceFixture, validStartTimeFixture, endTimeSameWithStartTime)) - .isInstanceOf(StoreException.class) - .hasMessage(INVALID_TIME.getMessage()); + .isInstanceOf(InvalidStoreCreationException.class); } @Test @@ -143,8 +139,7 @@ void endTimeBeforeThanStartTime() { () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, validMinOrderPriceFixture, validStartTimeFixture, endTimeBeforeThanStartTime)) - .isInstanceOf(StoreException.class) - .hasMessage(INVALID_TIME.getMessage()); + .isInstanceOf(InvalidStoreCreationException.class); } @Test @@ -174,8 +169,7 @@ void startTimeWithSeconds() { () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, validMinOrderPriceFixture, startTimeWithSeconds, validEndTimeFixture)) - .isInstanceOf(StoreException.class) - .hasMessage(INVALID_TIME_UNIT.getMessage()); + .isInstanceOf(InvalidStoreCreationException.class); } @Test @@ -190,8 +184,7 @@ void startTimeWithNanoSeconds() { () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, 5000, startTimeWithNanoSeconds, validEndTimeFixture)) - .isInstanceOf(StoreException.class) - .hasMessage(INVALID_TIME_UNIT.getMessage()); + .isInstanceOf(InvalidStoreCreationException.class); } @Test @@ -206,8 +199,7 @@ void endTimeWithSeconds() { () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, 5000, validStartTimeFixture, endTimeWithSeconds)) - .isInstanceOf(StoreException.class) - .hasMessage(INVALID_TIME_UNIT.getMessage()); + .isInstanceOf(InvalidStoreCreationException.class); } @Test @@ -222,8 +214,7 @@ void endTimeWithNanoSeconds() { () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, 5000, validStartTimeFixture, endTimeWithNanoSeconds)) - .isInstanceOf(StoreException.class) - .hasMessage(INVALID_TIME_UNIT.getMessage()); + .isInstanceOf(InvalidStoreCreationException.class); } } @@ -259,8 +250,7 @@ void lessThanMinLengthName() { null, validMinOrderPriceFixture, validStartTimeFixture, validEndTimeFixture)) - .isInstanceOf(StoreException.class) - .hasMessage(INVALID_NAME_RANGE.getMessage()); + .isInstanceOf(InvalidStoreCreationException.class); } @Test @@ -275,8 +265,7 @@ void greaterThanMaxLengthName() { validAddressFixture, null, validMinOrderPriceFixture, validStartTimeFixture, validEndTimeFixture)) - .isInstanceOf(StoreException.class) - .hasMessage(INVALID_NAME_RANGE.getMessage()); + .isInstanceOf(InvalidStoreCreationException.class); } } @@ -308,8 +297,7 @@ void notSongPa() { () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddress, null, validMinOrderPriceFixture, validStartTimeFixture, validEndTimeFixture)) - .isInstanceOf(StoreException.class) - .hasMessage(INVALID_ADDRESS.getMessage()); + .isInstanceOf(InvalidStoreCreationException.class); } } diff --git a/src/test/java/camp/woowak/lab/store/service/StoreMenuRegistrationServiceTest.java b/src/test/java/camp/woowak/lab/store/service/StoreMenuRegistrationServiceTest.java index c46fd33b..1032b117 100644 --- a/src/test/java/camp/woowak/lab/store/service/StoreMenuRegistrationServiceTest.java +++ b/src/test/java/camp/woowak/lab/store/service/StoreMenuRegistrationServiceTest.java @@ -6,6 +6,7 @@ import java.time.LocalDateTime; import java.util.List; import java.util.Optional; +import java.util.UUID; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -24,14 +25,19 @@ import camp.woowak.lab.store.domain.StoreCategory; import camp.woowak.lab.store.exception.NotFoundStoreException; import camp.woowak.lab.store.repository.StoreRepository; -import camp.woowak.lab.store.service.dto.StoreMenuRegistrationRequest; +import camp.woowak.lab.store.service.command.MenuLineItem; +import camp.woowak.lab.store.service.command.StoreMenuRegistrationCommand; import camp.woowak.lab.vendor.domain.Vendor; +import camp.woowak.lab.vendor.repository.VendorRepository; import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; import camp.woowak.lab.web.authentication.PasswordEncoder; @ExtendWith(MockitoExtension.class) class StoreMenuRegistrationServiceTest { + @Mock + VendorRepository vendorRepository; + @Mock StoreRepository storeRepository; @@ -54,18 +60,20 @@ class StoreMenuRegistrationServiceTest { void storeMenuRegistrationSuccess() { // given Long storeId = 1L; - - List menuItems = List.of( - new StoreMenuRegistrationRequest.MenuLineItem("메뉴1", "image1.jpg", "카테고리1", 10000) + UUID vendorId = UUID.randomUUID(); + List menuItems = List.of( + new MenuLineItem("메뉴1", "image1.jpg", "카테고리1", 10000) ); - StoreMenuRegistrationRequest request = new StoreMenuRegistrationRequest(storeId, menuItems); + StoreMenuRegistrationCommand request = new StoreMenuRegistrationCommand(vendorId, storeId, menuItems); + + when(vendorRepository.findById(vendorId)).thenReturn(Optional.of(owner)); when(storeRepository.findById(storeId)).thenReturn(Optional.of(storeFixture)); when(menuCategoryRepository.findByStoreIdAndName(storeFixture.getId(), "카테고리1")).thenReturn( Optional.of(menuCategoryFixture)); // when - storeMenuRegistrationService.storeMenuRegistration(owner, request); + storeMenuRegistrationService.storeMenuRegistration(request); // then verify(storeRepository).findById(storeId); @@ -78,16 +86,17 @@ void storeMenuRegistrationSuccess() { void storeMenuRegistrationStoreNotFound() { // given Long storeId = 1L; - - List menuItems = List.of( - new StoreMenuRegistrationRequest.MenuLineItem("메뉴1", "image1.jpg", "카테고리1", 10000) + UUID vendorId = UUID.randomUUID(); + List menuItems = List.of( + new MenuLineItem("메뉴1", "image1.jpg", "카테고리1", 10000) ); - StoreMenuRegistrationRequest request = new StoreMenuRegistrationRequest(storeId, menuItems); + StoreMenuRegistrationCommand command = new StoreMenuRegistrationCommand(vendorId, storeId, menuItems); + when(vendorRepository.findById(vendorId)).thenReturn(Optional.of(owner)); when(storeRepository.findById(storeId)).thenReturn(Optional.empty()); // when & then - assertThatThrownBy(() -> storeMenuRegistrationService.storeMenuRegistration(owner, request)) + assertThatThrownBy(() -> storeMenuRegistrationService.storeMenuRegistration(command)) .isInstanceOf(NotFoundStoreException.class); } diff --git a/src/test/java/camp/woowak/lab/store/service/StoreRegistrationServiceTest.java b/src/test/java/camp/woowak/lab/store/service/StoreRegistrationServiceTest.java index aa483061..d516f876 100644 --- a/src/test/java/camp/woowak/lab/store/service/StoreRegistrationServiceTest.java +++ b/src/test/java/camp/woowak/lab/store/service/StoreRegistrationServiceTest.java @@ -1,10 +1,10 @@ package camp.woowak.lab.store.service; -import static camp.woowak.lab.store.exception.StoreException.ErrorCode.*; import static org.mockito.BDDMockito.*; import java.time.LocalDateTime; import java.util.Optional; +import java.util.UUID; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; @@ -19,17 +19,21 @@ import camp.woowak.lab.payaccount.domain.TestPayAccount; import camp.woowak.lab.store.domain.Store; import camp.woowak.lab.store.domain.StoreCategory; -import camp.woowak.lab.store.exception.StoreException; +import camp.woowak.lab.store.exception.NotFoundStoreCategoryException; import camp.woowak.lab.store.repository.StoreCategoryRepository; import camp.woowak.lab.store.repository.StoreRepository; -import camp.woowak.lab.store.service.dto.StoreRegistrationRequest; +import camp.woowak.lab.store.service.command.StoreRegistrationCommand; import camp.woowak.lab.vendor.domain.Vendor; +import camp.woowak.lab.vendor.repository.VendorRepository; import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; import camp.woowak.lab.web.authentication.PasswordEncoder; @ExtendWith(MockitoExtension.class) class StoreRegistrationServiceTest { + @Mock + private VendorRepository vendorRepository; + @Mock private StoreRepository storeRepository; @@ -50,16 +54,19 @@ class StoreRegistrationServiceTest { void successfulRegistration() { // given Vendor vendor = createVendor(); + UUID id = UUID.randomUUID(); + String storeCategoryName = "한식"; - StoreRegistrationRequest request = createStoreRegistrationRequest(storeCategoryName); + StoreRegistrationCommand request = createStoreRegistrationRequest(id, storeCategoryName); StoreCategory mockStoreCategory = new StoreCategory(storeCategoryName); + when(vendorRepository.findById(id)).thenReturn(Optional.of(vendor)); when(storeCategoryRepository.findByName(storeCategoryName)).thenReturn(Optional.of(mockStoreCategory)); when(storeRepository.save(any(Store.class))) .thenAnswer(invocation -> invocation.getArgument(0)); // when - storeRegistrationService.storeRegistration(vendor, request); + storeRegistrationService.storeRegistration(request); // then then(storeRepository).should().save(any(Store.class)); @@ -70,22 +77,24 @@ void successfulRegistration() { void notExistStoreCategoryName() { // given Vendor vendor = createVendor(); + UUID id = UUID.randomUUID(); + String invalidCategoryName = "존재하지 않는 카테고리"; - StoreRegistrationRequest request = createStoreRegistrationRequest(invalidCategoryName); + StoreRegistrationCommand request = createStoreRegistrationRequest(id, invalidCategoryName); + when(vendorRepository.findById(id)).thenReturn(Optional.of(vendor)); given(storeCategoryRepository.findByName(invalidCategoryName)) .willReturn(Optional.empty()); // when & then - Assertions.assertThatThrownBy(() -> storeRegistrationService.storeRegistration(vendor, request)) - .isInstanceOf(StoreException.class) - .hasMessage(INVALID_STORE_CATEGORY.getMessage()); + Assertions.assertThatThrownBy(() -> storeRegistrationService.storeRegistration(request)) + .isInstanceOf(NotFoundStoreCategoryException.class); then(storeRepository).shouldHaveNoInteractions(); } - private StoreRegistrationRequest createStoreRegistrationRequest(String storeCategory) { - return new StoreRegistrationRequest("3K1K가게", "송파", "02-0000-0000", + private StoreRegistrationCommand createStoreRegistrationRequest(UUID id, String storeCategory) { + return new StoreRegistrationCommand(id, "3K1K가게", "송파", "02-0000-0000", storeCategory, 5000, validStartTimeFixture, validEndTimeFixture); } diff --git a/src/test/java/camp/woowak/lab/web/api/store/StoreApiControllerTest.java b/src/test/java/camp/woowak/lab/web/api/store/StoreApiControllerTest.java index 06f9a451..cf3dec6c 100644 --- a/src/test/java/camp/woowak/lab/web/api/store/StoreApiControllerTest.java +++ b/src/test/java/camp/woowak/lab/web/api/store/StoreApiControllerTest.java @@ -1,6 +1,5 @@ package camp.woowak.lab.web.api.store; -import static camp.woowak.lab.store.exception.StoreException.ErrorCode.*; import static org.mockito.BDDMockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @@ -32,9 +31,10 @@ import camp.woowak.lab.menu.service.command.MenuCategoryRegistrationCommand; import camp.woowak.lab.payaccount.domain.PayAccount; import camp.woowak.lab.payaccount.domain.TestPayAccount; -import camp.woowak.lab.store.exception.StoreException; +import camp.woowak.lab.store.exception.NotFoundStoreCategoryException; +import camp.woowak.lab.store.service.StoreMenuRegistrationService; import camp.woowak.lab.store.service.StoreRegistrationService; -import camp.woowak.lab.store.service.dto.StoreRegistrationRequest; +import camp.woowak.lab.store.service.command.StoreRegistrationCommand; import camp.woowak.lab.vendor.domain.Vendor; import camp.woowak.lab.vendor.repository.VendorRepository; import camp.woowak.lab.web.authentication.AuthenticationErrorCode; @@ -42,6 +42,7 @@ import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; import camp.woowak.lab.web.authentication.PasswordEncoder; import camp.woowak.lab.web.dto.request.store.MenuCategoryRegistrationRequest; +import camp.woowak.lab.web.dto.request.store.StoreRegistrationRequest; import camp.woowak.lab.web.resolver.session.SessionConst; import camp.woowak.lab.web.resolver.session.SessionVendorArgumentResolver; @@ -55,6 +56,9 @@ class StoreApiControllerTest { @MockBean private StoreRegistrationService storeRegistrationService; + @MockBean + private StoreMenuRegistrationService storeMenuRegistrationService; + @MockBean private MenuCategoryRegistrationService menuCategoryRegistrationService; @@ -115,7 +119,7 @@ void storeRegistrationSuccess() throws Exception { .sessionAttr(SessionConst.SESSION_VENDOR_KEY, loginVendor)) .andExpect(status().isOk()); - verify(storeRegistrationService).storeRegistration(any(Vendor.class), any(StoreRegistrationRequest.class)); + verify(storeRegistrationService).storeRegistration(any(StoreRegistrationCommand.class)); } @Disabled @@ -135,9 +139,8 @@ void storeRegistrationFailure() throws Exception { validEndTimeFixture ); - doThrow(new StoreException(INVALID_STORE_CATEGORY)) - .when(storeRegistrationService) - .storeRegistration(any(Vendor.class), any(StoreRegistrationRequest.class)); + doThrow(new NotFoundStoreCategoryException("invalid category")) + .when(storeRegistrationService).storeRegistration(any(StoreRegistrationCommand.class)); // when & then mockMvc.perform(post("/stores") @@ -147,7 +150,7 @@ void storeRegistrationFailure() throws Exception { .andExpect(status().isBadRequest()) .andExpect(content().string("fail")); - verify(storeRegistrationService).storeRegistration(any(Vendor.class), any(StoreRegistrationRequest.class)); + verify(storeRegistrationService).storeRegistration(any(StoreRegistrationCommand.class)); } }