diff --git a/README.md b/README.md index c31ca54c..22ef51c3 100644 --- a/README.md +++ b/README.md @@ -1 +1,30 @@ -# java-chicken-2019 \ No newline at end of file +# java-chicken-2019 + +## 기능목록 +Pos 기 기능 출력하기 +원하는 기능 선택하기 +테이블 목록 출력하기 (주어짐) +테이블 선택하기 (주어짐) +메뉴 출력하기 (주어짐) +등록할 메뉴 선택하기 +메뉴의 수량 입력하기 +주문내역 출력하기 +카드결제 할지 현금결제 할지 선택하기 +최종 결제할 금액 출력하기 +주문 정보 등록하기 +결제 금액 계산하기 +할인율 계산하기 +테이블 별로 주문 내역 관리하기 +테이블 당 주문 내역 관리하기 +결제 완료된 테이블 결제 완료 처리하기 + +## 객체 설계 +- Menu + - 아는 것 : 메뉴 자신의 번호, 이름, 종류, 가격 +- PaymentMethod + - 아는 것 : 지불 방식 스스로에 대해 대응되는 번호(code) +- PosFunction + - 아는 것 : pos 기계의 기능 스스로에 대해 대응되는 번호(code), 자신의 한국어 이름 +- Table + - 아는 것 : 주문내역, + - 하는 것 : 자신에 대한 주문내역 등록, 결제하기 \ No newline at end of file diff --git a/src/main/java/Application.java b/src/main/java/Application.java index ea0d34fd..78c78c4d 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,21 +1,8 @@ -import domain.Menu; -import domain.MenuRepository; -import domain.Table; -import domain.TableRepository; -import view.InputView; -import view.OutputView; - -import java.util.List; +import controller.Controller; public class Application { - // TODO 구현 진행 - public static void main(String[] args) { - final List tables = TableRepository.tables(); - OutputView.printTables(tables); - final int tableNumber = InputView.inputTableNumber(); - - final List menus = MenuRepository.menus(); - OutputView.printMenus(menus); + public static void main(String[] args) { + Controller.run(); } } diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java new file mode 100644 index 00000000..8f74db78 --- /dev/null +++ b/src/main/java/controller/Controller.java @@ -0,0 +1,108 @@ +package controller; + +import domain.Menu; +import domain.MenuRepository; +import domain.PaymentMethod; +import domain.PosFunction; +import domain.Table; +import domain.TableRepository; +import java.util.List; +import java.util.stream.Collectors; +import view.IllegalUserInputException; +import view.InputView; +import view.OutputView; + +public class Controller { + + private static final List
tables = TableRepository.tables(); + private static final List menus = MenuRepository.menus(); + + public static void run() { + try { + runWithoutExceptionCatch(); + } catch (Exception e) { + OutputView.printExceptionMessage(e.getMessage()); + } + } + + private static void runWithoutExceptionCatch() { + PosFunction posFunction; + + do { + OutputView.printPosFunctions(PosFunction.getPosFunctionsByCodeKoreanMap()); + posFunction = PosFunction.of(InputView.inputPosFunction()); + + runOnce(posFunction); + } while (posFunction != PosFunction.EXIT); + } + + private static void runOnce(PosFunction posFunction) { + if (posFunction == PosFunction.ORDER_REGISTRATION) { + registerOrder(); + } + if (posFunction == PosFunction.PAYMENT) { + pay(); + } + } + + private static void registerOrder() { + OutputView.printTables(getTableNumbers(), getOrderedTableNumbers()); + final Table table = readTable(); + + OutputView.printMenus(menus); + final Menu menuToRegister = readMenu(); + + table.registerMenu(menuToRegister, InputView.inputMenuCount()); + } + + private static List getTableNumbers() { + return tables.stream() + .mapToInt(Table::getNumber) + .boxed() + .collect(Collectors.toList()); + } + + private static List getOrderedTableNumbers() { + return tables.stream() + .filter(Table::hasOrdered) + .mapToInt(Table::getNumber) + .boxed() + .collect(Collectors.toList()); + } + + private static Table readTable() { + int tableNumber = InputView.inputTableNumber(); + + return tables.stream() + .filter(table -> table.isNumber(tableNumber)) + .findFirst() + .orElseThrow(() -> new IllegalUserInputException("존재하지 않는 테이블입니다.")); + } + + private static Menu readMenu() { + int menuNumber = InputView.inputMenuNumber(); + + return menus.stream() + .filter(targetMenu -> targetMenu.isNumber(menuNumber)) + .findFirst() + .orElseThrow(() -> new IllegalUserInputException("존재하지 않는 메뉴입니다.")); + } + + private static void pay() { + OutputView.printTables(getTableNumbers(), getOrderedTableNumbers()); + final Table table = readTable(); + table.validatePayable(); + + OutputView.printOrderHistory(table.getOrderHistory()); + + final PaymentMethod paymentMethod = readPaymentMethodOf(table); + + OutputView.printFinalPaymentAmount(table.getPaymentAmount()); + table.pay(paymentMethod); + } + + private static PaymentMethod readPaymentMethodOf(Table table) { + OutputView.printMakingPaymentMessage(table.getNumber()); + return PaymentMethod.of(InputView.inputPaymentMethod()); + } +} diff --git a/src/main/java/domain/Menu.java b/src/main/java/domain/Menu.java index 9f5a078e..9dac9b91 100644 --- a/src/main/java/domain/Menu.java +++ b/src/main/java/domain/Menu.java @@ -13,6 +13,18 @@ public Menu(final int number, final String name, final Category category, final this.price = price; } + public boolean isNumber(final int number) { + return this.number == number; + } + + public String getName() { + return this.name; + } + + public int getPrice() { + return this.price; + } + @Override public String toString() { return category + " " + number + " - " + name + " : " + price + "원"; diff --git a/src/main/java/domain/PaymentMethod.java b/src/main/java/domain/PaymentMethod.java new file mode 100644 index 00000000..18d696ca --- /dev/null +++ b/src/main/java/domain/PaymentMethod.java @@ -0,0 +1,22 @@ +package domain; + +import java.util.Arrays; + +public enum PaymentMethod { + CREDIT_CARD(1), + CASH(2); + + private int code; + + PaymentMethod(int code) { + this.code = code; + } + + public static PaymentMethod of(int code) { + return Arrays.stream(values()) + .filter(paymentMethod -> paymentMethod.code == code) + .findFirst() + .orElseThrow(() -> + new IllegalArgumentException("존재하지 않는 결제방식 번호입니다.")); + } +} diff --git a/src/main/java/domain/PosFunction.java b/src/main/java/domain/PosFunction.java new file mode 100644 index 00000000..f21f13ee --- /dev/null +++ b/src/main/java/domain/PosFunction.java @@ -0,0 +1,46 @@ +package domain; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public enum PosFunction { + ORDER_REGISTRATION(1, "주문등록"), + PAYMENT(2, "결제하기"), + EXIT(3, "프로그램 종료"); + + private int code; + private String korean; + + PosFunction(int code, String korean) { + this.code = code; + this.korean = korean; + } + + public static PosFunction of(int code) { + return Arrays.stream(PosFunction.values()) + .filter(posFunction -> posFunction.code == code) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 Pos 기능번호입니다.")); + } + + public int getCode() { + return this.code; + } + + public static Map getPosFunctionsByCodeKoreanMap() { + Map posFunctions = new HashMap<>(); + + Arrays.stream(PosFunction.values()) + .forEach(posFunction -> + posFunctions.put(posFunction.code, posFunction.korean)); + + return Collections.unmodifiableMap(posFunctions); + } + + @Override + public String toString() { + return this.korean; + } +} diff --git a/src/main/java/domain/Table.java b/src/main/java/domain/Table.java index 500c517e..b432dc1d 100644 --- a/src/main/java/domain/Table.java +++ b/src/main/java/domain/Table.java @@ -1,12 +1,59 @@ package domain; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + public class Table { + private final int number; + private final Map orderHistory = new HashMap<>(); public Table(final int number) { this.number = number; } + public void registerMenu(Menu menu, int menuCount) { + if (!orderHistory.containsKey(menu)) { + orderHistory.put(menu, 0); + } + orderHistory.put(menu, orderHistory.get(menu) + menuCount); + } + + public boolean hasOrdered() { + return !orderHistory.isEmpty(); + } + + public Map getOrderHistory() { + return Collections.unmodifiableMap(orderHistory); + } + + public int getPaymentAmount() { + validatePayable(); + return orderHistory.keySet().stream() + .mapToInt(Menu::getPrice) + .sum(); + } + + public void pay(PaymentMethod paymentMethod) { + validatePayable(); + this.orderHistory.clear(); + } + + public void validatePayable() { + if (!hasOrdered()) { + throw new IllegalStateException("결제할 주문내역이 없습니다."); + } + } + + public boolean isNumber(int number) { + return this.number == number; + } + + public int getNumber() { + return this.number; + } + @Override public String toString() { return Integer.toString(number); diff --git a/src/main/java/view/IllegalUserInputException.java b/src/main/java/view/IllegalUserInputException.java new file mode 100644 index 00000000..7a2a6552 --- /dev/null +++ b/src/main/java/view/IllegalUserInputException.java @@ -0,0 +1,11 @@ +package view; + +public class IllegalUserInputException extends RuntimeException { + + public IllegalUserInputException() { + } + + public IllegalUserInputException(String message) { + super(message); + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index d5db24e2..a2684f0c 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -3,10 +3,39 @@ import java.util.Scanner; public class InputView { + private static final Scanner scanner = new Scanner(System.in); + public static int inputPosFunction() { + System.out.println("## 원하는 기능을 선택하세요."); + return readIntegerByOneLine(); + } + public static int inputTableNumber() { - System.out.println("## 주문할 테이블을 선택하세요."); - return scanner.nextInt(); + System.out.println("## 테이블을 선택하세요."); + return readIntegerByOneLine(); + } + + public static int inputMenuNumber() { + System.out.println("## 등록할 메뉴를 선택하세요."); + return readIntegerByOneLine(); + } + + public static int inputMenuCount() { + System.out.println("## 메뉴의 수량을 선택하세요."); + return readIntegerByOneLine(); + } + + public static int inputPaymentMethod() { + System.out.println("## 신용카드는 1번, 현금은 2번"); + return readIntegerByOneLine(); + } + + private static int readIntegerByOneLine() { + try { + return Integer.parseInt(scanner.nextLine()); + } catch (NumberFormatException e) { + throw new IllegalUserInputException("정수만 입력 가능합니다."); + } } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index edb25cc4..59fa9f3b 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,40 +1,91 @@ package view; import domain.Menu; -import domain.Table; - import java.util.List; +import java.util.Map; public class OutputView { + private static final String TOP_LINE = "┌ ─ ┐"; private static final String TABLE_FORMAT = "| %s |"; - private static final String BOTTOM_LINE = "└ ─ ┘"; + private static final String BOTTOM_LINE_WHEN_NOT_ORDERED = "└ ─ ┘"; + private static final String BOTTOM_LINE_WHEN_ORDERED = "└ $ ┘"; + + public static void printPosFunctions(final Map posFunctions) { + System.out.println("## 메인 화면"); + posFunctions.forEach( + (key, value) -> System.out.println(key + " - " + value)); + System.out.println("\n"); + } + + public static void printTables(final List tableNumbers, + final List orderedTableNumbers) { - public static void printTables(final List
tables) { System.out.println("## 테이블 목록"); - final int size = tables.size(); - printLine(TOP_LINE, size); - printTableNumbers(tables); - printLine(BOTTOM_LINE, size); + final int size = tableNumbers.size(); + printTopLine(size); + printTableNumbers(tableNumbers); + printBottomLine(tableNumbers, orderedTableNumbers); + System.out.println(); + } + + private static void printTopLine(final int count) { + for (int index = 0; index < count; index++) { + System.out.print(TOP_LINE); + } + System.out.println(); + } + + private static void printTableNumbers(List tableNumbers) { + for (final int tableNumber : tableNumbers) { + System.out.printf(TABLE_FORMAT, tableNumber + ""); + } + System.out.println(); + } + + private static void printBottomLine(List tableNumbers, + List orderedTableNumbers) { + + for (Integer tableNumber : tableNumbers) { + printOneTableBottomLine(orderedTableNumbers.contains(tableNumber)); + } + System.out.println(); + } + + private static void printOneTableBottomLine(boolean isOrderedTable) { + if (isOrderedTable) { + System.out.print(BOTTOM_LINE_WHEN_ORDERED); + return; + } + System.out.print(BOTTOM_LINE_WHEN_NOT_ORDERED); } public static void printMenus(final List menus) { for (final Menu menu : menus) { System.out.println(menu); } + System.out.println(); } - private static void printLine(final String line, final int count) { - for (int index = 0; index < count; index++) { - System.out.print(line); - } + public static void printOrderHistory(final Map orderHistory) { + System.out.println("메뉴\t수량\t금액"); + orderHistory.forEach((menu, count) -> + System.out.println(menu.getName() + "\t" + count + "\t" + menu.getPrice()) + ); System.out.println(); } - private static void printTableNumbers(final List
tables) { - for (final Table table : tables) { - System.out.printf(TABLE_FORMAT, table); - } + public static void printMakingPaymentMessage(int tableNumber) { + System.out.println(tableNumber + "번 테이블의 결제를 진행합니다."); + } + + public static void printFinalPaymentAmount(int paymentAmount) { + System.out.println("## 최종 결제할 금액"); + System.out.println(paymentAmount + "원"); System.out.println(); } + + public static void printExceptionMessage(String exceptionMessage) { + System.out.println(exceptionMessage); + } } diff --git a/src/test/java/domain/PaymentMethodTest.java b/src/test/java/domain/PaymentMethodTest.java new file mode 100644 index 00000000..dcb96e8f --- /dev/null +++ b/src/test/java/domain/PaymentMethodTest.java @@ -0,0 +1,18 @@ +package domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.jupiter.api.Test; + +class PaymentMethodTest { + + @Test + void of() { + assertThat(PaymentMethod.of(1)).isEqualTo(PaymentMethod.CREDIT_CARD); + assertThat(PaymentMethod.of(2)).isEqualTo(PaymentMethod.CASH); + + assertThatThrownBy(() -> PaymentMethod.of(0)) + .isInstanceOf(IllegalArgumentException.class); + } +} \ No newline at end of file diff --git a/src/test/java/domain/PosFunctionTest.java b/src/test/java/domain/PosFunctionTest.java new file mode 100644 index 00000000..1d3765a5 --- /dev/null +++ b/src/test/java/domain/PosFunctionTest.java @@ -0,0 +1,42 @@ +package domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.Test; + +class PosFunctionTest { + + @Test + void of() { + assertThat(PosFunction.of(1)).isEqualTo(PosFunction.ORDER_REGISTRATION); + assertThat(PosFunction.of(2)).isEqualTo(PosFunction.PAYMENT); + assertThat(PosFunction.of(3)).isEqualTo(PosFunction.EXIT); + } + + @Test + void getCode() { + assertThat(PosFunction.ORDER_REGISTRATION.getCode()).isEqualTo(1); + assertThat(PosFunction.PAYMENT.getCode()).isEqualTo(2); + assertThat(PosFunction.EXIT.getCode()).isEqualTo(3); + } + + @Test + void getPosFunctionsByCodeKoreanMap() { + Map expected = new HashMap<>(); + expected.put(1, "주문등록"); + expected.put(2, "결제하기"); + expected.put(3, "프로그램 종료"); + + assertThat(PosFunction.getPosFunctionsByCodeKoreanMap()) + .isEqualTo(expected); + } + + @Test + void testToString() { + assertThat(PosFunction.ORDER_REGISTRATION.toString()).isEqualTo("주문등록"); + assertThat(PosFunction.PAYMENT.toString()).isEqualTo("결제하기"); + assertThat(PosFunction.EXIT.toString()).isEqualTo("프로그램 종료"); + } +} \ No newline at end of file diff --git a/src/test/java/domain/TableTest.java b/src/test/java/domain/TableTest.java new file mode 100644 index 00000000..115de505 --- /dev/null +++ b/src/test/java/domain/TableTest.java @@ -0,0 +1,54 @@ +package domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class TableTest { + + private Table table; + + @BeforeEach + void setUp() { + table = new Table(1); + } + + @Test + void registerMenu() { + Menu testMenu1 = new Menu(1, "가짜메뉴1", Category.CHICKEN, 1_000); + Menu testMenu2 = new Menu(2, "가짜메뉴2", Category.CHICKEN, 1_3990); + + table.registerMenu(testMenu1, 1); + table.registerMenu(testMenu1, 1); + table.registerMenu(testMenu2, 3); + + Map expected = new HashMap<>(); + expected.put(testMenu1, 2); + expected.put(testMenu2, 3); + + assertThat(table.getOrderHistory()).isEqualTo(expected); + } + + @Test + void isNumber() { + assertThat(table.isNumber(1)).isTrue(); + assertThat(table.isNumber(5)).isFalse(); + } + + @Test + void testToString() { + assertThat(table.toString()).isEqualTo(1 + ""); + } + + @Test + void hasOrdered() { + assertThat(table.hasOrdered()).isFalse(); + + Menu testMenu = new Menu(1, "가짜메뉴", Category.CHICKEN, 1_3990); + table.registerMenu(testMenu, 1); + assertThat(table.hasOrdered()).isTrue(); + } +} \ No newline at end of file diff --git a/src/test/java/empty.txt b/src/test/java/empty.txt deleted file mode 100644 index e69de29b..00000000