diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..ab1f416 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Ignored default folder with query files +/queries/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..bf2c501 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..a9076af --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..eba6e1f --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/main/java/dev/Main.java b/src/main/java/dev/Main.java index 3a93683..27b18fe 100644 --- a/src/main/java/dev/Main.java +++ b/src/main/java/dev/Main.java @@ -8,7 +8,5 @@ public class Main { ConsoleMenu menu = new ConsoleMenu(); menu.start(); - } - } \ No newline at end of file diff --git a/src/main/java/dev/dao/MenuItemDao.java b/src/main/java/dev/dao/MenuItemDao.java index 3bbebe9..9642566 100644 --- a/src/main/java/dev/dao/MenuItemDao.java +++ b/src/main/java/dev/dao/MenuItemDao.java @@ -1,7 +1,14 @@ package dev.dao; +import dev.database.DatabaseConnection; import dev.model.MenuItem; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; import java.util.List; public class MenuItemDao { @@ -11,7 +18,30 @@ public class MenuItemDao { // TODO: // Retrieve all menu items - return null; + String sql = "SELECT id, name, description, price, category FROM menu_items ORDER BY id"; + + List menuItems = new ArrayList<>(); + + try (Connection connection = DatabaseConnection.getConnection(); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(sql)) { + + while (resultSet.next()) { + menuItems.add(new MenuItem( + resultSet.getInt("id"), + resultSet.getString("name"), + resultSet.getString("description"), + resultSet.getDouble("price"), + resultSet.getString("category") + )); + } + + return menuItems; + + } catch (SQLException e) { + System.out.println("Error retrieving menu items: " + e.getMessage()); + return menuItems; + } } public MenuItem findById(int id) { @@ -19,7 +49,32 @@ public class MenuItemDao { // TODO: // Find menu item by id - return null; + String sql = "SELECT id, name, description, price, category FROM menu_items WHERE id = ?"; + + try (Connection connection = DatabaseConnection.getConnection(); + PreparedStatement statement = connection.prepareStatement(sql)) { + + statement.setInt(1, id); + + try (ResultSet resultSet = statement.executeQuery()) { + + if (resultSet.next()) { + return new MenuItem( + resultSet.getInt("id"), + resultSet.getString("name"), + resultSet.getString("description"), + resultSet.getDouble("price"), + resultSet.getString("category") + ); + } + + return null; + } + + } catch (SQLException e) { + System.out.println("Error finding menu item: " + e.getMessage()); + return null; + } } } \ No newline at end of file diff --git a/src/main/java/dev/dao/OrderDao.java b/src/main/java/dev/dao/OrderDao.java index 00999a2..4d20d63 100644 --- a/src/main/java/dev/dao/OrderDao.java +++ b/src/main/java/dev/dao/OrderDao.java @@ -1,7 +1,15 @@ package dev.dao; +import dev.database.DatabaseConnection; import dev.model.Order; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.ArrayList; import java.util.List; public class OrderDao { @@ -11,7 +19,30 @@ public class OrderDao { // TODO: // Insert order and return generated id - return -1; + String sql = "INSERT INTO orders (user_id, created_at, total_price) VALUES (?, ?, ?)"; + + try (Connection connection = DatabaseConnection.getConnection(); + PreparedStatement statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + + statement.setInt(1, order.getUserId()); + statement.setTimestamp(2, Timestamp.valueOf(order.getCreatedAt())); + statement.setDouble(3, order.getTotalPrice()); + + statement.executeUpdate(); + + try (ResultSet generatedKeys = statement.getGeneratedKeys()) { + + if (generatedKeys.next()) { + return generatedKeys.getInt(1); + } + + return -1; + } + + } catch (SQLException e) { + System.out.println("Error saving order: " + e.getMessage()); + return -1; + } } public List findByUserId(int userId) { @@ -19,7 +50,33 @@ public class OrderDao { // TODO: // Retrieve all orders of a user - return null; + String sql = "SELECT id, user_id, created_at, total_price FROM orders WHERE user_id = ? ORDER BY created_at"; + + List orders = new ArrayList<>(); + + try (Connection connection = DatabaseConnection.getConnection(); + PreparedStatement statement = connection.prepareStatement(sql)) { + + statement.setInt(1, userId); + + try (ResultSet resultSet = statement.executeQuery()) { + + while (resultSet.next()) { + orders.add(new Order( + resultSet.getInt("id"), + resultSet.getInt("user_id"), + resultSet.getTimestamp("created_at").toLocalDateTime(), + resultSet.getDouble("total_price") + )); + } + + return orders; + } + + } catch (SQLException e) { + System.out.println("Error retrieving orders: " + e.getMessage()); + return orders; + } } } \ No newline at end of file diff --git a/src/main/java/dev/dao/OrderDetailDao.java b/src/main/java/dev/dao/OrderDetailDao.java index ed42f56..377e72e 100644 --- a/src/main/java/dev/dao/OrderDetailDao.java +++ b/src/main/java/dev/dao/OrderDetailDao.java @@ -1,7 +1,13 @@ package dev.dao; +import dev.database.DatabaseConnection; import dev.model.OrderDetail; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; import java.util.List; public class OrderDetailDao { @@ -11,6 +17,21 @@ public class OrderDetailDao { // TODO: // Insert order detail + String sql = "INSERT INTO order_details (order_id, menu_item_id, quantity, price) VALUES (?, ?, ?, ?)"; + + try (Connection connection = DatabaseConnection.getConnection(); + PreparedStatement statement = connection.prepareStatement(sql)) { + + statement.setInt(1, detail.getOrderId()); + statement.setInt(2, detail.getMenuItemId()); + statement.setInt(3, detail.getQuantity()); + statement.setDouble(4, detail.getPrice()); + + statement.executeUpdate(); + + } catch (SQLException e) { + System.out.println("Error saving order detail: " + e.getMessage()); + } } public List findByOrderId(int orderId) { @@ -18,7 +39,34 @@ public class OrderDetailDao { // TODO: // Retrieve order details - return null; + String sql = "SELECT id, order_id, menu_item_id, quantity, price FROM order_details WHERE order_id = ?"; + + List details = new ArrayList<>(); + + try (Connection connection = DatabaseConnection.getConnection(); + PreparedStatement statement = connection.prepareStatement(sql)) { + + statement.setInt(1, orderId); + + try (ResultSet resultSet = statement.executeQuery()) { + + while (resultSet.next()) { + details.add(new OrderDetail( + resultSet.getInt("id"), + resultSet.getInt("order_id"), + resultSet.getInt("menu_item_id"), + resultSet.getInt("quantity"), + resultSet.getDouble("price") + )); + } + + return details; + } + + } catch (SQLException e) { + System.out.println("Error retrieving order details: " + e.getMessage()); + return details; + } } } \ No newline at end of file diff --git a/src/main/java/dev/dao/UserDao.java b/src/main/java/dev/dao/UserDao.java index af08106..1e515b5 100644 --- a/src/main/java/dev/dao/UserDao.java +++ b/src/main/java/dev/dao/UserDao.java @@ -1,7 +1,13 @@ package dev.dao; +import dev.database.DatabaseConnection; import dev.model.User; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + public class UserDao { public boolean save(User user) { @@ -9,7 +15,17 @@ public class UserDao { // TODO: // Insert user into database - return false; + String sql = "INSERT INTO users (username, password, email) VALUES (?, ?, ?)"; + try (Connection connection = DatabaseConnection.getConnection(); + PreparedStatement statement = connection.prepareStatement(sql)) { + statement.setString(1, user.getUsername()); + statement.setString(2, user.getPassword()); + statement.setString(3, user.getEmail()); + return statement.executeUpdate() > 0; + } catch (SQLException e) { + System.out.println("Error saving user: " + e.getMessage()); + return false; + } } public User findByUsername(String username) { @@ -17,7 +33,27 @@ public class UserDao { // TODO: // Find a user by username - return null; + String sql = "SELECT id, username, password, email FROM users WHERE username = ?"; + + try (Connection connection = DatabaseConnection.getConnection(); + PreparedStatement statement = connection.prepareStatement(sql)) { + statement.setString(1, username); + try (ResultSet resultSet = statement.executeQuery()) { + if (resultSet.next()) { + return new User( + resultSet.getInt("id"), + resultSet.getString("username"), + resultSet.getString("password"), + resultSet.getString("email") + ); + } + return null; + } + + } catch (SQLException e) { + System.out.println("Error finding user: " + e.getMessage()); + return null; + } } } \ No newline at end of file diff --git a/src/main/java/dev/database/DatabaseConnection.java b/src/main/java/dev/database/DatabaseConnection.java index da45535..0dc2d7e 100644 --- a/src/main/java/dev/database/DatabaseConnection.java +++ b/src/main/java/dev/database/DatabaseConnection.java @@ -19,9 +19,6 @@ public class DatabaseConnection { throws SQLException { // TODO: - // Return a valid PostgreSQL connection - - return null; + return java.sql.DriverManager.getConnection(URL, USER, PASSWORD); } - } \ No newline at end of file diff --git a/src/main/java/dev/model/MenuItem.java b/src/main/java/dev/model/MenuItem.java index 265ecc1..83d6f5d 100644 --- a/src/main/java/dev/model/MenuItem.java +++ b/src/main/java/dev/model/MenuItem.java @@ -12,4 +12,56 @@ public class MenuItem { private String category; + public MenuItem() { + + } + + public MenuItem(int id, String name, String description, double price, String category) { + this.id = id; + this.name = name; + this.description = description; + this.price = price; + this.category = category; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + } \ No newline at end of file diff --git a/src/main/java/dev/model/Order.java b/src/main/java/dev/model/Order.java index 32049cb..cb4b973 100644 --- a/src/main/java/dev/model/Order.java +++ b/src/main/java/dev/model/Order.java @@ -12,4 +12,47 @@ public class Order { private double totalPrice; + public Order() { + + } + + public Order(int id, int userId, LocalDateTime createdAt, double totalPrice) { + this.id = id; + this.userId = userId; + this.createdAt = createdAt; + this.totalPrice = totalPrice; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public double getTotalPrice() { + return totalPrice; + } + + public void setTotalPrice(double totalPrice) { + this.totalPrice = totalPrice; + } + } \ No newline at end of file diff --git a/src/main/java/dev/model/OrderDetail.java b/src/main/java/dev/model/OrderDetail.java index b5b8bbe..c096201 100644 --- a/src/main/java/dev/model/OrderDetail.java +++ b/src/main/java/dev/model/OrderDetail.java @@ -12,4 +12,55 @@ public class OrderDetail { private double price; + public OrderDetail() { + } + + public OrderDetail(int id, int orderId, int menuItemId, int quantity, double price) { + this.id = id; + this.orderId = orderId; + this.menuItemId = menuItemId; + this.quantity = quantity; + this.price = price; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getOrderId() { + return orderId; + } + + public void setOrderId(int orderId) { + this.orderId = orderId; + } + + public int getMenuItemId() { + return menuItemId; + } + + public void setMenuItemId(int menuItemId) { + this.menuItemId = menuItemId; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity(int quantity) { + this.quantity = quantity; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } + } \ No newline at end of file diff --git a/src/main/java/dev/model/User.java b/src/main/java/dev/model/User.java index 0ab60c6..ff897b5 100644 --- a/src/main/java/dev/model/User.java +++ b/src/main/java/dev/model/User.java @@ -10,4 +10,47 @@ public class User { private String email; + public User() { + + } + + public User(int id, String username, String password, String email) { + this.id = id; + this.username = username; + this.password = password; + this.email = email; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + } \ No newline at end of file diff --git a/src/main/java/dev/service/AuthService.java b/src/main/java/dev/service/AuthService.java index bee866a..2b6d348 100644 --- a/src/main/java/dev/service/AuthService.java +++ b/src/main/java/dev/service/AuthService.java @@ -1,15 +1,33 @@ package dev.service; +import dev.dao.UserDao; import dev.model.User; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + public class AuthService { + private final UserDao userDao = new UserDao(); + public boolean register(String username, String password, String email) { // TODO: // Validate and register user - return false; + if (username == null || username.isBlank() || password == null || password.isBlank()) { + System.out.println("Username and password are required."); + return false; + } + + if (userDao.findByUsername(username) != null) { + System.out.println("Username already exists."); + return false; + } + + User user = new User(0, username, hashPassword(password), email); + + return userDao.save(user); } public User login(String username, String password) { @@ -17,7 +35,44 @@ public class AuthService { // TODO: // Authenticate user - return null; + User user = userDao.findByUsername(username); + + if (user == null) { + System.out.println("Invalid username or password."); + return null; + } + + if (!user.getPassword().equals(hashPassword(password))) { + System.out.println("Invalid username or password."); + return null; + } + + return user; + } + + private String hashPassword(String password) { + + try { + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + byte[] hashedBytes = digest.digest(password.getBytes()); + + StringBuilder hexString = new StringBuilder(); + + for (byte b : hashedBytes) { + String hex = Integer.toHexString(0xff & b); + + if (hex.length() == 1) { + hexString.append('0'); + } + + hexString.append(hex); + } + + return hexString.toString(); + + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } } } \ No newline at end of file diff --git a/src/main/java/dev/service/MenuService.java b/src/main/java/dev/service/MenuService.java index 6dbf4da..d8feb83 100644 --- a/src/main/java/dev/service/MenuService.java +++ b/src/main/java/dev/service/MenuService.java @@ -1,12 +1,31 @@ package dev.service; +import dev.dao.MenuItemDao; +import dev.model.MenuItem; + +import java.util.List; + public class MenuService { + private final MenuItemDao menuItemDao = new MenuItemDao(); + public void showMenu() { // TODO: // Display menu items + List menuItems = menuItemDao.findAll(); + + System.out.println("Available Items:"); + + for (MenuItem item : menuItems) { + System.out.printf("%d. %s - $%.2f%n", item.getId(), item.getName(), item.getPrice()); + } + } + + public List getMenu() { + + return menuItemDao.findAll(); } } \ No newline at end of file diff --git a/src/main/java/dev/service/OrderService.java b/src/main/java/dev/service/OrderService.java index 14708f8..d211278 100644 --- a/src/main/java/dev/service/OrderService.java +++ b/src/main/java/dev/service/OrderService.java @@ -1,12 +1,97 @@ package dev.service; +import dev.dao.MenuItemDao; +import dev.dao.OrderDao; +import dev.dao.OrderDetailDao; +import dev.model.MenuItem; +import dev.model.Order; +import dev.model.OrderDetail; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Scanner; + public class OrderService { + private final MenuItemDao menuItemDao = new MenuItemDao(); + + private final OrderDao orderDao = new OrderDao(); + + private final OrderDetailDao orderDetailDao = new OrderDetailDao(); + + private final Scanner scanner = new Scanner(System.in); + public void placeOrder(int userId) { // TODO: // Create order + List menuItems = menuItemDao.findAll(); + + System.out.println("Available Items:"); + + for (MenuItem item : menuItems) { + System.out.printf("%d. %s - $%.2f%n", item.getId(), item.getName(), item.getPrice()); + } + + List cart = new java.util.ArrayList<>(); + + double total = 0; + + while (true) { + + System.out.print("Enter the ID of the item to add (or 0 to finish): "); + int itemId = scanner.nextInt(); + + if (itemId == 0) { + break; + } + + MenuItem selected = menuItemDao.findById(itemId); + + if (selected == null) { + System.out.println("Invalid item ID."); + continue; + } + + System.out.print("Enter quantity: "); + int quantity = scanner.nextInt(); + + if (quantity <= 0) { + System.out.println("Quantity must be greater than zero."); + continue; + } + + OrderDetail detail = new OrderDetail(0, 0, selected.getId(), quantity, selected.getPrice()); + cart.add(detail); + + total += selected.getPrice() * quantity; + + System.out.printf("Added %dx %s to your cart.%n", quantity, selected.getName()); + } + + if (cart.isEmpty()) { + System.out.println("No items were added to the order."); + return; + } + + Order order = new Order(0, userId, LocalDateTime.now(), total); + + int orderId = orderDao.save(order); + + if (orderId == -1) { + System.out.println("Failed to save order."); + return; + } + + for (OrderDetail detail : cart) { + detail.setOrderId(orderId); + orderDetailDao.save(detail); + } + + System.out.println("Order saved successfully!"); + + printReceipt(orderId); } public void printReceipt(int orderId) { @@ -14,6 +99,26 @@ public class OrderService { // TODO: // Print order receipt + List details = orderDetailDao.findByOrderId(orderId); + + System.out.println("---------------------------------------"); + System.out.printf("%-12s %-7s %-9s %-9s%n", "Item", "Qty", "Unit", "Total"); + System.out.println("---------------------------------------"); + + double grandTotal = 0; + + for (OrderDetail detail : details) { + + MenuItem item = menuItemDao.findById(detail.getMenuItemId()); + double subtotal = detail.getPrice() * detail.getQuantity(); + grandTotal += subtotal; + + System.out.printf("%-12s %-7d $%-8.2f $%-8.2f%n", + item.getName(), detail.getQuantity(), detail.getPrice(), subtotal); + } + + System.out.println("---------------------------------------"); + System.out.printf("Final Total: $%.2f%n", grandTotal); } public void showOrderHistory(int userId) { @@ -21,6 +126,19 @@ public class OrderService { // TODO: // Display user's order history + List orders = orderDao.findByUserId(userId); + + if (orders.isEmpty()) { + System.out.println("No orders found."); + return; + } + + System.out.println("Order History:"); + + for (Order order : orders) { + System.out.printf("Order #%d - %s - Total: $%.2f%n", + order.getId(), order.getCreatedAt(), order.getTotalPrice()); + } } } \ No newline at end of file diff --git a/src/main/java/dev/ui/ConsoleMenu.java b/src/main/java/dev/ui/ConsoleMenu.java index 663dc0c..95d86d9 100644 --- a/src/main/java/dev/ui/ConsoleMenu.java +++ b/src/main/java/dev/ui/ConsoleMenu.java @@ -1,5 +1,10 @@ package dev.ui; +import dev.model.User; +import dev.service.AuthService; +import dev.service.MenuService; +import dev.service.OrderService; + import java.util.Scanner; public class ConsoleMenu { @@ -7,6 +12,12 @@ public class ConsoleMenu { private final Scanner scanner = new Scanner(System.in); + private final AuthService authService = new AuthService(); + + private final MenuService menuService = new MenuService(); + + private final OrderService orderService = new OrderService(); + public void start() { while (true) { @@ -23,10 +34,12 @@ public class ConsoleMenu { case 1: // TODO + login(); break; case 2: // TODO + register(); break; case 3: @@ -41,4 +54,88 @@ public class ConsoleMenu { } + private void register() { + + System.out.println(); + System.out.println("[Register]"); + + System.out.print("Enter username: "); + String username = scanner.next(); + + System.out.print("Enter password: "); + String password = scanner.next(); + + System.out.print("Enter email (optional, press enter to skip): "); + scanner.nextLine(); + String email = scanner.nextLine(); + + if (email.isBlank()) { + email = null; + } + + if (authService.register(username, password, email)) { + System.out.println("Registration successful! You can now login."); + } + + } + + private void login() { + + System.out.println(); + System.out.println("[Login]"); + + System.out.print("Enter username: "); + String username = scanner.next(); + + System.out.print("Enter password: "); + String password = scanner.next(); + + User user = authService.login(username, password); + + if (user != null) { + System.out.println("Login successful! Welcome, " + user.getUsername() + "!"); + showMainMenu(user); + } + + } + + private void showMainMenu(User user) { + + while (true) { + + System.out.println(); + System.out.println("===== MAIN MENU ====="); + System.out.println("1. View Menu"); + System.out.println("2. Place a New Order"); + System.out.println("3. View Order History"); + System.out.println("4. Logout"); + + int choice = scanner.nextInt(); + + switch (choice) { + + case 1: + menuService.showMenu(); + break; + + case 2: + orderService.placeOrder(user.getId()); + break; + + case 3: + orderService.showOrderHistory(user.getId()); + break; + + case 4: + return; + + default: + System.out.println("Invalid choice"); + + } + + } + + } + } \ No newline at end of file