diff --git a/docs/README.md b/docs/README.md index e69de29..32fcf39 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,84 @@ +# Christmas + +### 프로그램 구성 + +#### 메뉴 + +``` +<애피타이저> +양송이수프(6,000), 타파스(5,500), 시저샐러드(8,000) + +<메인> +티본스테이크(55,000), 바비큐립(54,000), 해산물파스타(35,000), 크리스마스파스타(25,000) + +<디저트> +초코케이크(15,000), 아이스크림(5,000) + +<음료> +제로콜라(3,000), 레드와인(60,000), 샴페인(25,000) +``` + +#### 달력 + +![](../image.png) + +#### 12월 이벤트 계획 + +- 크리스마스 디데이 할인 + - [x] 이벤트 기간: 2023.12.1 ~ 2023.12.25 + - [x] 1,000원으로 시작하여 크리스마스가 다가올수록 날마다 할인 금액이 100원씩 증가 + - [x] 총주문 금액에서 해당 금액만큼 할인 + (e.g. 시작일인 12월 1일에 1,000원, 2일에 1,100원, ..., 25일엔 3,400원 할인) +- [x] 평일 할인(일요일~목요일): 평일에는 디저트 메뉴를 메뉴 1개당 2,023원 할인 +- [x] 주말 할인(금요일, 토요일): 주말에는 메인 메뉴를 메뉴 1개당 2,023원 할인 +- [x] 특별 할인: 이벤트 달력에 별이 있으면 총주문 금액에서 1,000원 할인 +- [ ] 증정 이벤트: 할인 전 총주문 금액이 12만 원 이상일 때, 샴페인 1개 증정 +- [x] 이벤트 기간: '크리스마스 디데이 할인'을 제외한 다른 이벤트는 2023.12.1 ~ 2023.12.31 동안 적용 + +#### 혜택 금액에 따른 12월 이벤트 배지 부여 + +- [x] 총혜택 금액에 따라 다른 이벤트 배지를 부여 + - 5천 원 이상: 별 + - 1만 원 이상: 트리 + - 2만 원 이상: 산타 + +#### 고객에게 안내할 이벤트 주의 사항 + +- [] 총주문 금액 10,000원 이상부터 이벤트가 적용 +- [x] 음료만 주문 시, 주문 불가 +- [x] 메뉴는 한 번에 최대 20개까지만 주문 가능 + (e.g. 시저샐러드-1, 티본스테이크-1, 크리스마스파스타-1, 제로콜라-3, 아이스크림-1의 총개수는 7개) + + +### 프로그램 Work Flow + +- [x] 이벤트 플래너 안내 문구 출력 +- [x] 예상 방문 날짜 입력 안내 문구 출력 +- [ ] 올바르지 않은 값 입력 시 에러 메세지 출력 후 재입력 받음 + - [x] 방문할 날짜는 1 이상 31 이하의 숫자로만 입력받 + - [x] 1 이상 31 이하의 숫자가 아닌 경우, "[ERROR] 유효하지 않은 날짜입니다. 다시 입력해 주세요."라는 에러 메시지 출력 + - [x] 모든 에러 메시지는 "[ERROR]"로 시작하도록 작성 + +- [x] 입력값에 따른 ```EventReservation``` 객체 생성 + +- [x] 주문할 메뉴와 개수 입력 안내 문구 출력 +- [ ] 올바르지 않은 값 입력 시 에러 메세지 출력 후 재입력 받음 + - [x] 고객이 메뉴판에 없는 메뉴를 입력하는 경우, "[ERROR] 유효하지 않은 주문입니다. 다시 입력해 주세요."라는 에러 메시지 출력 + - [x] 메뉴의 개수는 1 이상의 숫자만 입력. 이외의 입력값은 "[ERROR] 유효하지 않은 주문입니다. 다시 입력해 주세요."라는 에러 메시지 출력 + - [x] 메뉴 형식이 예시와 다른 경우, "[ERROR] 유효하지 않은 주문입니다. 다시 입력해 주세요."라는 에러 메시지 출력 + - [x] 중복 메뉴를 입력한 경우(e.g. 시저샐러드-1,시저샐러드-1), "[ERROR] 유효하지 않은 주문입니다. 다시 입력해 주세요."라는 에러 메시지 출력 + - [x] 모든 에러 메시지는 "[ERROR]"로 시작하도록 작성 + + +- [x] 주문 결과 출력 + - [x] 미리보기 안내문 출력 + - [x] 주문 메뉴 종류 및 갯수 출력 + - [x] 할인 전 총 주문금액 출력 + - [x] 증정 메뉴 출력 + - [x] 없을 시 "없음" 출력 + - [x] 혜택 내역 출력 + - [x] 없을 시 "없음" 출력 + - [x] 총혜택 금액 출력 + - [x] 할인 후 예상 결제 금액 출력 + - [x] 12월 이벤트 배지 출력 + \ No newline at end of file diff --git a/src/main/java/christmas/Application.java b/src/main/java/christmas/Application.java index b9ba6a2..50ca474 100644 --- a/src/main/java/christmas/Application.java +++ b/src/main/java/christmas/Application.java @@ -1,7 +1,12 @@ package christmas; +import christmas.config.AppConfig; +import christmas.controller.EventController; + public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + EventController eventController = AppConfig.getEventController(); + eventController.run(); + } } diff --git a/src/main/java/christmas/config/AppConfig.java b/src/main/java/christmas/config/AppConfig.java new file mode 100644 index 0000000..a830d44 --- /dev/null +++ b/src/main/java/christmas/config/AppConfig.java @@ -0,0 +1,76 @@ +package christmas.config; + +import christmas.controller.EventController; +import christmas.domain.event.DiscountProcessor; +import christmas.domain.event.EventProcessor; +import christmas.domain.event.Gift; +import christmas.domain.event.impl.BadgeGift; +import christmas.domain.event.impl.ChampagneGift; +import christmas.domain.event.impl.DDayDiscount; +import christmas.domain.event.impl.SpecialDiscount; +import christmas.domain.event.impl.TotalEventProcessor; +import christmas.domain.event.impl.WeekdaysDiscount; +import christmas.domain.event.impl.WeekendDiscount; +import christmas.domain.reservation.Order; +import christmas.domain.reservation.Reservation; +import christmas.repository.ReservationRepository; +import christmas.repository.SingleRepository; +import christmas.service.AcceptReservationService; +import christmas.service.AcceptReservationServiceImpl; +import christmas.service.ProcessEventService; +import christmas.service.ProcessEventServiceImpl; +import christmas.utils.InputParser; +import christmas.utils.InputValidator; +import christmas.utils.impl.DateToVisitParser; +import christmas.utils.impl.DateToVisitValidator; +import christmas.utils.impl.OrdersParser; +import christmas.utils.impl.OrdersValidator; +import christmas.view.InputView; +import christmas.view.OutputView; +import christmas.view.impl.ConsoleInputView; +import christmas.view.impl.ConsoleOutputView; +import java.time.LocalDate; +import java.util.List; + +public class AppConfig { + + private final static OutputView consoleOutputView = new ConsoleOutputView(); + private final static InputView consoleInputView = new ConsoleInputView(); + + private final static SingleRepository reservationRepository = new ReservationRepository(); + + private final static InputValidator dateToVisitValidator = new DateToVisitValidator(); + private final static InputValidator ordersValidator = new OrdersValidator(); + + private final static InputParser dateToVisitParser = new DateToVisitParser(dateToVisitValidator); + private final static InputParser> ordersParser = new OrdersParser(ordersValidator); + + private final static DiscountProcessor dDayDiscount = new DDayDiscount(); + private final static DiscountProcessor specialDiscount = new SpecialDiscount(); + private final static DiscountProcessor> weekdaysDiscount = new WeekdaysDiscount(); + private final static DiscountProcessor> weekendDiscount = new WeekendDiscount(); + + private final static Gift badgeGift = new BadgeGift(); + private final static Gift champagneGift = new ChampagneGift(); + + private final static EventProcessor totalEventProcessor = new TotalEventProcessor(dDayDiscount, + specialDiscount, + weekdaysDiscount, + weekendDiscount, + champagneGift + ,badgeGift); + + private final static AcceptReservationService acceptReservationServiceImpl = new AcceptReservationServiceImpl(reservationRepository, + ordersParser, + dateToVisitParser); + private final static ProcessEventService processEventService = new ProcessEventServiceImpl(reservationRepository, totalEventProcessor); + + private final static EventController eventController = new EventController(consoleInputView, + consoleOutputView, + acceptReservationServiceImpl, + processEventService); + + public static EventController getEventController() { + return eventController; + } +} diff --git a/src/main/java/christmas/controller/EventController.java b/src/main/java/christmas/controller/EventController.java new file mode 100644 index 0000000..f53a5a4 --- /dev/null +++ b/src/main/java/christmas/controller/EventController.java @@ -0,0 +1,36 @@ +package christmas.controller; + +import christmas.dto.ReceiptDTO; +import christmas.service.AcceptReservationService; +import christmas.service.ProcessEventService; +import christmas.view.InputView; +import christmas.view.OutputView; + +public class EventController { + private final InputView inputView; + private final OutputView outputView; + private final AcceptReservationService acceptReservationService; + private final ProcessEventService processEventService; + + public EventController(InputView inputView, + OutputView outputView, + AcceptReservationService acceptReservationService, + ProcessEventService processEventService) { + + this.inputView = inputView; + this.outputView = outputView; + this.acceptReservationService = acceptReservationService; + this.processEventService = processEventService; + } + + public void run(){ + outputView.printWelcomeMessage(); + + acceptReservationService.buildDateToVisit(inputView.readDate()); + acceptReservationService.buildOrders(inputView.readOrders()); + acceptReservationService.buildReservations(); + + ReceiptDTO receiptDTO = processEventService.sendReceipt(); + outputView.printReceipt(receiptDTO); + } +} diff --git a/src/main/java/christmas/domain/event/DiscountProcessor.java b/src/main/java/christmas/domain/event/DiscountProcessor.java new file mode 100644 index 0000000..94e7abc --- /dev/null +++ b/src/main/java/christmas/domain/event/DiscountProcessor.java @@ -0,0 +1,5 @@ +package christmas.domain.event; + +public interface DiscountProcessor { + int processDiscount(Type input); +} diff --git a/src/main/java/christmas/domain/event/EventProcessor.java b/src/main/java/christmas/domain/event/EventProcessor.java new file mode 100644 index 0000000..4beb2bb --- /dev/null +++ b/src/main/java/christmas/domain/event/EventProcessor.java @@ -0,0 +1,9 @@ +package christmas.domain.event; + +import christmas.domain.reservation.Order; +import java.time.LocalDate; +import java.util.List; + +public interface EventProcessor { + String getEventResult(List orders, LocalDate date, int totalPrice); +} diff --git a/src/main/java/christmas/domain/event/Gift.java b/src/main/java/christmas/domain/event/Gift.java new file mode 100644 index 0000000..109a8ca --- /dev/null +++ b/src/main/java/christmas/domain/event/Gift.java @@ -0,0 +1,5 @@ +package christmas.domain.event; + +public interface Gift { + Type getGiftOrNot(int amount); +} diff --git a/src/main/java/christmas/domain/event/impl/BadgeGift.java b/src/main/java/christmas/domain/event/impl/BadgeGift.java new file mode 100644 index 0000000..b0f9ae2 --- /dev/null +++ b/src/main/java/christmas/domain/event/impl/BadgeGift.java @@ -0,0 +1,19 @@ +package christmas.domain.event.impl; + +import christmas.domain.event.Gift; + +public class BadgeGift implements Gift { + @Override + public String getGiftOrNot(int discountAmount) { + if (discountAmount >= 20000) { + return "산타"; + } + if (discountAmount >= 10000) { + return "트리"; + } + if (discountAmount >= 5000) { + return "별"; + } + return "없음"; + } +} diff --git a/src/main/java/christmas/domain/event/impl/ChampagneGift.java b/src/main/java/christmas/domain/event/impl/ChampagneGift.java new file mode 100644 index 0000000..6f82c28 --- /dev/null +++ b/src/main/java/christmas/domain/event/impl/ChampagneGift.java @@ -0,0 +1,14 @@ +package christmas.domain.event.impl; + +import christmas.domain.event.Gift; + +public class ChampagneGift implements Gift { + @Override + public Boolean getGiftOrNot(int totalAmount) { + if (totalAmount >= 120000) { + return true; + } + return false; + + } +} diff --git a/src/main/java/christmas/domain/event/impl/DDayDiscount.java b/src/main/java/christmas/domain/event/impl/DDayDiscount.java new file mode 100644 index 0000000..714edb1 --- /dev/null +++ b/src/main/java/christmas/domain/event/impl/DDayDiscount.java @@ -0,0 +1,18 @@ +package christmas.domain.event.impl; + +import christmas.domain.event.DiscountProcessor; +import java.time.LocalDate; + +public class DDayDiscount implements DiscountProcessor { + private static final LocalDate CHRISTMAS =LocalDate.of(2023,12,25); + @Override + public int processDiscount(LocalDate reservationDate) { + if (reservationDate.isAfter(CHRISTMAS)) { + return 0; + } + int discount = 1000; + discount += 100 * (reservationDate.getDayOfMonth() - 1); + + return discount; + } +} diff --git a/src/main/java/christmas/domain/event/impl/SpecialDiscount.java b/src/main/java/christmas/domain/event/impl/SpecialDiscount.java new file mode 100644 index 0000000..d6ea8f2 --- /dev/null +++ b/src/main/java/christmas/domain/event/impl/SpecialDiscount.java @@ -0,0 +1,18 @@ +package christmas.domain.event.impl; + +import christmas.domain.event.DiscountProcessor; +import java.time.LocalDate; +import java.util.List; + +public class SpecialDiscount implements DiscountProcessor { + private static final List specialDays = List.of(3,10,17,24,25,31); + + @Override + public int processDiscount(LocalDate reservationDate) { + int discount = 0; + if (specialDays.contains(reservationDate.getDayOfWeek())) { + discount +=1000; + } + return discount; + } +} diff --git a/src/main/java/christmas/domain/event/impl/TotalEventProcessor.java b/src/main/java/christmas/domain/event/impl/TotalEventProcessor.java new file mode 100644 index 0000000..705ac8e --- /dev/null +++ b/src/main/java/christmas/domain/event/impl/TotalEventProcessor.java @@ -0,0 +1,124 @@ +package christmas.domain.event.impl; +import christmas.domain.event.DiscountProcessor; +import christmas.domain.event.EventProcessor; +import christmas.domain.event.Gift; +import christmas.domain.menu.impl.Menu; +import christmas.domain.reservation.Order; +import java.time.LocalDate; +import java.util.List; + +public class TotalEventProcessor implements EventProcessor { + private static final List weekends = List.of(1,2,8,9,15,16,22,33,29,30); + + private final DiscountProcessor dDayDiscount; + private final DiscountProcessor specialDiscount; + private final DiscountProcessor> weekdaysDiscount; + private final DiscountProcessor> weekendDiscount; + private final Gift champagneGift; + private final Gift badgeGift; + + public TotalEventProcessor(DiscountProcessor dDayDiscount, + DiscountProcessor specialDiscount, + DiscountProcessor> weekdaysDiscount, + DiscountProcessor> weekendDiscount, + Gift champagneGift, + Gift badgeGift + ) { + this.dDayDiscount = dDayDiscount; + this.specialDiscount = specialDiscount; + this.weekdaysDiscount = weekdaysDiscount; + this.weekendDiscount = weekendDiscount; + this.champagneGift = champagneGift; + this.badgeGift = badgeGift; + } + + + @Override + public String getEventResult(List orders, LocalDate date, int totalPrice) { + StringBuilder builder = new StringBuilder(); + + if (totalPrice > 10000){ + getLessMoneyResult(totalPrice,builder); + return builder.toString(); + } + + builder.append("\n<증정메뉴>\n"); + + int champagneDiscount = getChampagneDiscount(totalPrice, builder); + int totalDiscountAmount = champagneDiscount; + + builder.append("\n<혜택 내역>\n"); + totalDiscountAmount += getDDayDiscount(date,builder); + if(weekends.contains(date.getDayOfWeek()) ) { + totalDiscountAmount += getWeekendDiscount(orders,builder); + } + if (!weekends.contains(date.getDayOfWeek())){ + totalDiscountAmount += getWeekdaysDiscount(orders,builder); + } + totalDiscountAmount += getSpecialDiscount(date,builder); + if(champagneDiscount != 0) { + builder.append("증정 이벤트: -").append(champagneDiscount).append("원").append("\n"); + } + + builder.append("\n<총혜택 금액>\n").append( (-1)*totalDiscountAmount).append("원").append("\n"); + builder.append("\n<할인 후 예상 결제 금액>\n").append(totalPrice - totalDiscountAmount).append("원").append("\n"); + builder.append("\n<12월 이벤트 배지>\n").append(badgeGift.getGiftOrNot(totalDiscountAmount)); + + return builder.toString(); + } + + private int getChampagneDiscount(int totalPrice, StringBuilder result) { + int champagneDiscountAmount = 0; + if(champagneGift.getGiftOrNot(totalPrice)){ + champagneDiscountAmount += Menu.valueOf("샴페인").getPrice(); + result.append("샴페인 1개\n"); + return champagneDiscountAmount; + } + result.append("없음\n"); + return champagneDiscountAmount; + } + + private int getDDayDiscount(LocalDate date, StringBuilder result) { + int dDayDiscountAmount = dDayDiscount.processDiscount(date); + if (dDayDiscountAmount != 0) { + result.append("크리스마스 디데이 할인: -").append(dDayDiscountAmount).append("원").append("\n"); + } + + return dDayDiscountAmount; + } + + private int getWeekendDiscount(List orders, StringBuilder result) { + int weekendDiscountAmount = weekendDiscount.processDiscount(orders); + if (weekendDiscountAmount != 0) { + result.append("주말 할인: -").append(weekendDiscountAmount).append("원").append("\n"); + } + return weekendDiscountAmount; + } + + private int getWeekdaysDiscount(List orders, StringBuilder result) { + int weekdaysDiscountAmount = weekdaysDiscount.processDiscount(orders); + if (weekdaysDiscountAmount != 0) { + result.append("평일 할인: -").append(weekdaysDiscountAmount).append("원").append("\n"); + } + return weekdaysDiscountAmount; + } + + private int getSpecialDiscount(LocalDate date, StringBuilder result) { + int specialDiscountAmount = specialDiscount.processDiscount(date); + if (specialDiscountAmount != 0) { + result.append("특별 할인: -").append(specialDiscountAmount).append("원").append("\n"); + } + return specialDiscountAmount; + + } + + private void getLessMoneyResult(int totalPrice, StringBuilder builder) { + builder.append("\n<증정 메뉴>\n없음\n").append("\n<혜택 내역>\n없음\n").append("\n<총혜택 금액>\n0원\n") + .append("\n<할인 후 예상 결재 금액>\n").append(totalPrice).append("원\n") + .append("\n<12월 이벤트 배지>\n없음"); + + } + + + +} diff --git a/src/main/java/christmas/domain/event/impl/WeekdaysDiscount.java b/src/main/java/christmas/domain/event/impl/WeekdaysDiscount.java new file mode 100644 index 0000000..e47c11a --- /dev/null +++ b/src/main/java/christmas/domain/event/impl/WeekdaysDiscount.java @@ -0,0 +1,23 @@ +package christmas.domain.event.impl; + +import christmas.domain.event.DiscountProcessor; +import christmas.domain.menu.impl.Menu; +import christmas.domain.reservation.Order; +import java.util.List; + +public class WeekdaysDiscount implements DiscountProcessor> { + @Override + public int processDiscount(List orders) { + int discount = 0; + + for (Order order : orders) { + String dishName = order.getDishName(); + + if (Menu.valueOf(dishName).getCategory().equals("Dessert")){ + discount += 2023; + } + } + + return discount; + } +} diff --git a/src/main/java/christmas/domain/event/impl/WeekendDiscount.java b/src/main/java/christmas/domain/event/impl/WeekendDiscount.java new file mode 100644 index 0000000..efb6dcf --- /dev/null +++ b/src/main/java/christmas/domain/event/impl/WeekendDiscount.java @@ -0,0 +1,23 @@ +package christmas.domain.event.impl; + +import christmas.domain.event.DiscountProcessor; +import christmas.domain.menu.impl.Menu; +import christmas.domain.reservation.Order; +import java.util.List; + +public class WeekendDiscount implements DiscountProcessor> { + @Override + public int processDiscount(List orders) { + int discount = 0; + + for (Order order : orders) { + String dishName = order.getDishName(); + + if (Menu.valueOf(dishName).getCategory().equals("MainDish")){ + discount += 2023; + } + } + + return discount; + } +} diff --git a/src/main/java/christmas/domain/menu/Dishes.java b/src/main/java/christmas/domain/menu/Dishes.java new file mode 100644 index 0000000..b25d862 --- /dev/null +++ b/src/main/java/christmas/domain/menu/Dishes.java @@ -0,0 +1,4 @@ +package christmas.domain.menu; + +public interface Dishes { +} diff --git a/src/main/java/christmas/domain/menu/impl/Menu.java b/src/main/java/christmas/domain/menu/impl/Menu.java new file mode 100644 index 0000000..14203ff --- /dev/null +++ b/src/main/java/christmas/domain/menu/impl/Menu.java @@ -0,0 +1,39 @@ +package christmas.domain.menu.impl; + +import christmas.domain.menu.Dishes; + +public enum Menu implements Dishes { + + 양송이스프(6_000, "Appetizer"), + 타파스(5_500, "Appetizer"), + 시저샐러드(8_000, "Appetizer"), + + 티본스테이크(55_000, "MainDish"), + 바비큐립(54_000,"MainDish"), + 해산물파스타(35_000, "MainDish"), + 크리스마스파스타(25_000, "MainDish"), + + 초코케이크(15_000, "Dessert"), + 아이스크림(5_000, "Dessert"), + + 제로콜라(3_000, "Beverage"), + 레드와인(60_000, "Beverage"), + 샴페인(25_000,"Beverage"); + + + private final int price; + public final String category; + + Menu(int price, String category) { + this.price = price; + this.category = category; + } + + public int getPrice() { + return price; + } + + public String getCategory() { + return category; + } +} diff --git a/src/main/java/christmas/domain/reservation/EventOrder.java b/src/main/java/christmas/domain/reservation/EventOrder.java new file mode 100644 index 0000000..b425301 --- /dev/null +++ b/src/main/java/christmas/domain/reservation/EventOrder.java @@ -0,0 +1,18 @@ +package christmas.domain.reservation; + +public class EventOrder implements Order { + private final String dishName; + private final int quantity; + + public EventOrder(String dishName, int quantity) { + this.dishName = dishName; + this.quantity = quantity; + } + + public int getQuantity(){ + return quantity; + } + public String getDishName() { + return dishName; + } +} diff --git a/src/main/java/christmas/domain/reservation/EventReservation.java b/src/main/java/christmas/domain/reservation/EventReservation.java new file mode 100644 index 0000000..edf311b --- /dev/null +++ b/src/main/java/christmas/domain/reservation/EventReservation.java @@ -0,0 +1,53 @@ +package christmas.domain.reservation; + +import christmas.domain.event.EventProcessor; +import christmas.domain.menu.impl.Menu; +import java.time.LocalDate; +import java.util.List; + +public class EventReservation implements Reservation { + private final List orders; + private final LocalDate eventDate; + private final int totalPrice; + + private EventReservation(List orders,LocalDate eventDate) { + this.orders = orders; + this.eventDate = eventDate; + this.totalPrice = getTotalPrice(); + + } + + public static EventReservation create(List orders,LocalDate eventDate){ + return new EventReservation(orders,eventDate); + } + + public String makeReceipt(EventProcessor totalEventProcessor){ + StringBuilder builder = new StringBuilder(); + builder.append("12월 ").append(eventDate.getDayOfWeek()).append("일에 우테코 식당에서 받을 혜택 미리 보기!\n"); + + builder.append("\n<주문 메뉴>\n"); + for(Order order : orders){ + builder.append(order.getDishName()).append(" ").append(order.getQuantity()).append("개\n"); + } + builder.append("\n<할인 전 총주문 금액>\n").append(totalPrice).append("원\n"); + + builder.append(totalEventProcessor.getEventResult(orders,eventDate,totalPrice)); + + return builder.toString(); + } + + + private int getTotalPrice(){ + int priceSum = 0; + + for (Order order : orders) { + String dishName = order.getDishName(); + int quantity = order.getQuantity(); + + priceSum += quantity * Menu.valueOf(dishName).getPrice(); + } + return priceSum; + } + + +} diff --git a/src/main/java/christmas/domain/reservation/Order.java b/src/main/java/christmas/domain/reservation/Order.java new file mode 100644 index 0000000..f508ca9 --- /dev/null +++ b/src/main/java/christmas/domain/reservation/Order.java @@ -0,0 +1,6 @@ +package christmas.domain.reservation; + +public interface Order { + int getQuantity(); + String getDishName(); +} diff --git a/src/main/java/christmas/domain/reservation/Reservation.java b/src/main/java/christmas/domain/reservation/Reservation.java new file mode 100644 index 0000000..c9323b0 --- /dev/null +++ b/src/main/java/christmas/domain/reservation/Reservation.java @@ -0,0 +1,7 @@ +package christmas.domain.reservation; + +import christmas.domain.event.EventProcessor; + +public interface Reservation { + String makeReceipt(EventProcessor eventProcessor); +} diff --git a/src/main/java/christmas/dto/ReceiptDTO.java b/src/main/java/christmas/dto/ReceiptDTO.java new file mode 100644 index 0000000..5f555aa --- /dev/null +++ b/src/main/java/christmas/dto/ReceiptDTO.java @@ -0,0 +1,4 @@ +package christmas.dto; + +public record ReceiptDTO(String receipt) { +} diff --git a/src/main/java/christmas/exception/ErrorMessage.java b/src/main/java/christmas/exception/ErrorMessage.java new file mode 100644 index 0000000..a75b1a0 --- /dev/null +++ b/src/main/java/christmas/exception/ErrorMessage.java @@ -0,0 +1,21 @@ +package christmas.exception; + +public enum ErrorMessage { + ERROR_HEADER("[ERROR] "), + NOT_VALID_ORDER_FORMAT("유효하지 않은 주문입니다. 다시 입력해 주세요."), + NOT_INTEGER("입력값이 숫자가 아닙니다. 다시 입력해주세요"), + NOT_VALID_DATE("유효하지 않은 날짜입니다. 다시 입력해주세요."); + private final String message; + + ErrorMessage(String message) { + this.message = message; + } + + private String getMessage() { + return message; + } + + public String getErrorMessage() { + return ERROR_HEADER.getMessage() + message; + } +} diff --git a/src/main/java/christmas/repository/ReservationRepository.java b/src/main/java/christmas/repository/ReservationRepository.java new file mode 100644 index 0000000..1dc37dc --- /dev/null +++ b/src/main/java/christmas/repository/ReservationRepository.java @@ -0,0 +1,19 @@ +package christmas.repository; + +import christmas.domain.reservation.Reservation; +import java.util.Optional; + +public class ReservationRepository implements SingleRepository { + private Reservation reservation; + + @Override + public Optional get() { + return Optional.ofNullable(this.reservation); + } + + @Override + public void save(Reservation reservation) { + this.reservation = reservation; + } +} + diff --git a/src/main/java/christmas/repository/SingleRepository.java b/src/main/java/christmas/repository/SingleRepository.java new file mode 100644 index 0000000..ecc83bb --- /dev/null +++ b/src/main/java/christmas/repository/SingleRepository.java @@ -0,0 +1,8 @@ +package christmas.repository; + +import java.util.Optional; + +public interface SingleRepository { + void save(Type entity); + Optional get(); +} diff --git a/src/main/java/christmas/service/AcceptReservationService.java b/src/main/java/christmas/service/AcceptReservationService.java new file mode 100644 index 0000000..345a591 --- /dev/null +++ b/src/main/java/christmas/service/AcceptReservationService.java @@ -0,0 +1,7 @@ +package christmas.service; + +public interface AcceptReservationService { + void buildDateToVisit(String rawDateToVisit); + void buildOrders(String rawOrders); + void buildReservations(); +} diff --git a/src/main/java/christmas/service/AcceptReservationServiceImpl.java b/src/main/java/christmas/service/AcceptReservationServiceImpl.java new file mode 100644 index 0000000..dd2e72f --- /dev/null +++ b/src/main/java/christmas/service/AcceptReservationServiceImpl.java @@ -0,0 +1,41 @@ +package christmas.service; + +import christmas.domain.reservation.EventReservation; +import christmas.domain.reservation.Order; +import christmas.domain.reservation.Reservation; +import christmas.repository.SingleRepository; +import christmas.utils.InputParser; +import java.time.LocalDate; +import java.util.List; + +public class AcceptReservationServiceImpl implements AcceptReservationService { + private final SingleRepository reservationRepository; + private final InputParser> ordersParser; + private final InputParser dateToVisitParser; + private LocalDate dateToVisit; + private List orders; + + public AcceptReservationServiceImpl(SingleRepository reservationRepository, + InputParser> ordersParser, + InputParser dateToVisitParser) { + this.reservationRepository = reservationRepository; + this.ordersParser = ordersParser; + this.dateToVisitParser = dateToVisitParser; + } + + @Override + public void buildDateToVisit(String rawDateToVisit) { + dateToVisit = dateToVisitParser.parse(rawDateToVisit); + } + + @Override + public void buildOrders(String rawOrders) { + orders = ordersParser.parse(rawOrders); + } + + @Override + public void buildReservations() { + Reservation reservation = EventReservation.create(orders,dateToVisit); + reservationRepository.save(reservation); + } +} diff --git a/src/main/java/christmas/service/ProcessEventService.java b/src/main/java/christmas/service/ProcessEventService.java new file mode 100644 index 0000000..b242dcc --- /dev/null +++ b/src/main/java/christmas/service/ProcessEventService.java @@ -0,0 +1,7 @@ +package christmas.service; + +import christmas.dto.ReceiptDTO; + +public interface ProcessEventService { + ReceiptDTO sendReceipt(); +} diff --git a/src/main/java/christmas/service/ProcessEventServiceImpl.java b/src/main/java/christmas/service/ProcessEventServiceImpl.java new file mode 100644 index 0000000..8f99307 --- /dev/null +++ b/src/main/java/christmas/service/ProcessEventServiceImpl.java @@ -0,0 +1,25 @@ +package christmas.service; + +import christmas.domain.event.EventProcessor; +import christmas.domain.reservation.Reservation; +import christmas.dto.ReceiptDTO; +import christmas.repository.SingleRepository; + +public class ProcessEventServiceImpl implements ProcessEventService{ + private final SingleRepository reservationRepositoryImpl; + private final EventProcessor totalEventProcessor; + + public ProcessEventServiceImpl(SingleRepository reservationRepositoryImpl, + EventProcessor totalEventProcessor) { + this.reservationRepositoryImpl = reservationRepositoryImpl; + this.totalEventProcessor = totalEventProcessor; + } + + + public ReceiptDTO sendReceipt(){ + Reservation eventReservation = reservationRepositoryImpl.get() + .orElseThrow(() -> new RuntimeException("There is no event reservation")); + + return new ReceiptDTO(eventReservation.makeReceipt(totalEventProcessor)); + } +} diff --git a/src/main/java/christmas/utils/InputParser.java b/src/main/java/christmas/utils/InputParser.java new file mode 100644 index 0000000..5e1fbb9 --- /dev/null +++ b/src/main/java/christmas/utils/InputParser.java @@ -0,0 +1,5 @@ +package christmas.utils; + +public interface InputParser { + Type parse(String input); +} diff --git a/src/main/java/christmas/utils/InputValidator.java b/src/main/java/christmas/utils/InputValidator.java new file mode 100644 index 0000000..d69cc65 --- /dev/null +++ b/src/main/java/christmas/utils/InputValidator.java @@ -0,0 +1,5 @@ +package christmas.utils; + +public interface InputValidator { + void validate(String input); +} diff --git a/src/main/java/christmas/utils/impl/DateToVisitParser.java b/src/main/java/christmas/utils/impl/DateToVisitParser.java new file mode 100644 index 0000000..e7cae96 --- /dev/null +++ b/src/main/java/christmas/utils/impl/DateToVisitParser.java @@ -0,0 +1,20 @@ +package christmas.utils.impl; + +import christmas.utils.InputParser; +import christmas.utils.InputValidator; +import java.time.LocalDate; + +public class DateToVisitParser implements InputParser { + private final InputValidator dateToVisitValidator; + + public DateToVisitParser(InputValidator dateToVisitValidator) { + this.dateToVisitValidator = dateToVisitValidator; + } + + @Override + public LocalDate parse(String rawDate) { + dateToVisitValidator.validate(rawDate); + int day = Integer.parseInt(rawDate); + return LocalDate.of(2023, 12, day); + } +} diff --git a/src/main/java/christmas/utils/impl/DateToVisitValidator.java b/src/main/java/christmas/utils/impl/DateToVisitValidator.java new file mode 100644 index 0000000..e5e1a0a --- /dev/null +++ b/src/main/java/christmas/utils/impl/DateToVisitValidator.java @@ -0,0 +1,32 @@ +package christmas.utils.impl; + +import static christmas.exception.ErrorMessage.NOT_INTEGER; +import static christmas.exception.ErrorMessage.NOT_VALID_DATE; + +import christmas.utils.InputValidator; + +public class DateToVisitValidator implements InputValidator { + private final int FIRST_DATE = 1; + private final int LAST_DATE = 31; + + @Override + public void validate(String input) { + validateInteger(input); + validateInRange(input); + } + + private void validateInteger(String date) { + try{ + Integer.parseInt(date); + } catch(NumberFormatException e) { + throw new IllegalArgumentException(NOT_INTEGER.getErrorMessage()); + } + } + + private void validateInRange(String date) { + int parsedDate = Integer.parseInt(date); + if (parsedDate < FIRST_DATE || parsedDate > LAST_DATE) { + throw new IllegalArgumentException(NOT_VALID_DATE.getErrorMessage()); + } + } +} diff --git a/src/main/java/christmas/utils/impl/OrdersParser.java b/src/main/java/christmas/utils/impl/OrdersParser.java new file mode 100644 index 0000000..f2856b2 --- /dev/null +++ b/src/main/java/christmas/utils/impl/OrdersParser.java @@ -0,0 +1,32 @@ +package christmas.utils.impl; + +import christmas.domain.reservation.EventOrder; +import christmas.domain.reservation.Order; +import christmas.utils.InputParser; +import christmas.utils.InputValidator; +import java.util.ArrayList; +import java.util.List; + +public class OrdersParser implements InputParser> { + private final InputValidator ordersValidator; + + public OrdersParser(InputValidator ordersValidator) { + this.ordersValidator = ordersValidator; + } + + @Override + public List parse(String rawOrders) { + ordersValidator.validate(rawOrders); + + List orders = new ArrayList<>(); + for (String rawOrder : rawOrders.split(",")) { + String[] parts = rawOrder.split("-"); + + String dishName = parts[0]; + int quantity = Integer.parseInt(parts[1]); + Order order = new EventOrder(dishName, quantity); + orders.add(order); + } + return orders; + } +} diff --git a/src/main/java/christmas/utils/impl/OrdersValidator.java b/src/main/java/christmas/utils/impl/OrdersValidator.java new file mode 100644 index 0000000..330525a --- /dev/null +++ b/src/main/java/christmas/utils/impl/OrdersValidator.java @@ -0,0 +1,79 @@ +package christmas.utils.impl; + +import static christmas.exception.ErrorMessage.NOT_VALID_ORDER_FORMAT; + +import christmas.domain.menu.impl.Menu; +import christmas.utils.InputValidator; +import java.util.HashSet; +import java.util.Set; + +public class OrdersValidator implements InputValidator { + @Override + public void validate(String rawOrders) { + validateNotEmpty(rawOrders); + validateFormat(rawOrders); + + } + + private void validateNotEmpty(String rawOrders) { + if (rawOrders == null || rawOrders.isEmpty()) { + throw new IllegalArgumentException(NOT_VALID_ORDER_FORMAT.getErrorMessage()); + } + } + + private void validateFormat(String rawOrders) { + Set dishes = new HashSet<>(); + + for (String rawOrder : rawOrders.split(",")) { + String[] parts = rawOrder.split("-"); + + if (parts.length > 40 || parts.length %2 == 1) { + throw new IllegalArgumentException(NOT_VALID_ORDER_FORMAT.getErrorMessage()); + } + + validateDishName(parts[0]); + validateQuantity(parts[1]); + + String dishName = parts[0]; + int quantity = Integer.parseInt(parts[1]); + + + if (dishes.contains(dishName)) { + throw new IllegalArgumentException(NOT_VALID_ORDER_FORMAT.getErrorMessage()); + } + dishes.add(dishName); + } + + for (String dishName : dishes) { + if( !Menu.valueOf(dishName).getCategory().equals("BEVERAGE")){ + return; + } + } + + throw new IllegalArgumentException(NOT_VALID_ORDER_FORMAT.getErrorMessage()); + } + + private void validateDishName(String dishName) { + if (dishName == null || dishName.isEmpty()) { + throw new IllegalArgumentException(NOT_VALID_ORDER_FORMAT.getErrorMessage()); + } + try {Menu.valueOf(dishName); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException(NOT_VALID_ORDER_FORMAT.getErrorMessage()); + } + } + + private void validateQuantity(String rawQuantity) { + if (rawQuantity == null || rawQuantity.isEmpty()) { + throw new IllegalArgumentException(NOT_VALID_ORDER_FORMAT.getErrorMessage()); + } + try{ + int quantity = Integer.parseInt(rawQuantity); + if(quantity < 1){ + throw new IllegalArgumentException(NOT_VALID_ORDER_FORMAT.getErrorMessage()); + } + } catch (NumberFormatException e) { + throw new IllegalArgumentException(NOT_VALID_ORDER_FORMAT.getErrorMessage()); + } + } +} diff --git a/src/main/java/christmas/view/InputView.java b/src/main/java/christmas/view/InputView.java new file mode 100644 index 0000000..4fb71f1 --- /dev/null +++ b/src/main/java/christmas/view/InputView.java @@ -0,0 +1,6 @@ +package christmas.view; + +public interface InputView { + String readDate(); + String readOrders(); +} diff --git a/src/main/java/christmas/view/OutputView.java b/src/main/java/christmas/view/OutputView.java new file mode 100644 index 0000000..4a33a8a --- /dev/null +++ b/src/main/java/christmas/view/OutputView.java @@ -0,0 +1,8 @@ +package christmas.view; + +import christmas.dto.ReceiptDTO; + +public interface OutputView { + void printWelcomeMessage(); + void printReceipt(ReceiptDTO receiptDTO); +} diff --git a/src/main/java/christmas/view/impl/ConsoleInputView.java b/src/main/java/christmas/view/impl/ConsoleInputView.java new file mode 100644 index 0000000..3b7a571 --- /dev/null +++ b/src/main/java/christmas/view/impl/ConsoleInputView.java @@ -0,0 +1,17 @@ +package christmas.view.impl; + +import camp.nextstep.edu.missionutils.Console; +import christmas.view.InputView; + +public class ConsoleInputView implements InputView { + + public String readDate(){ + System.out.println("12월 중 식당 예상 방문 날짜는 언제인가요? (숫자만 입력해 주세요!)"); + return Console.readLine(); + } + + public String readOrders(){ + System.out.println("주문하실 메뉴와 개수를 알려 주세요. (e.g. 해물파스타-2,레드와인-1,초코케이크-1"); + return Console.readLine(); + } +} diff --git a/src/main/java/christmas/view/impl/ConsoleOutputView.java b/src/main/java/christmas/view/impl/ConsoleOutputView.java new file mode 100644 index 0000000..afc55f7 --- /dev/null +++ b/src/main/java/christmas/view/impl/ConsoleOutputView.java @@ -0,0 +1,15 @@ +package christmas.view.impl; + +import christmas.dto.ReceiptDTO; +import christmas.view.OutputView; + +public class ConsoleOutputView implements OutputView { + + public void printWelcomeMessage(){ + System.out.println("안녕하세요! 우테코 식당 12월 이벤트 플래너입니다."); + } + + public void printReceipt(ReceiptDTO receiptDTO) { + System.out.println(receiptDTO.receipt()); + } +}