From dceeb56b2224504a2522f8fa5a151ab43815e9e8 Mon Sep 17 00:00:00 2001 From: Amir Ali Amiri Date: Wed, 1 Jul 2026 16:45:18 +0330 Subject: [PATCH] implement database persistence layer and core restaurant backend logic --- .idea/.gitignore | 10 ++ .idea/compiler.xml | 13 ++ .idea/encodings.xml | 7 + .idea/jarRepositories.xml | 20 +++ .idea/misc.xml | 12 ++ .idea/vcs.xml | 6 + database.sql | 161 +++++------------- src/main/java/dev/dao/MenuItemDao.java | 51 +++++- src/main/java/dev/dao/OrderDao.java | 48 +++++- src/main/java/dev/dao/OrderDetailDao.java | 48 +++++- src/main/java/dev/dao/UserDao.java | 43 ++++- .../java/dev/database/DatabaseConnection.java | 17 +- src/main/java/dev/model/MenuItem.java | 30 +++- src/main/java/dev/model/Order.java | 25 ++- src/main/java/dev/model/OrderDetail.java | 30 +++- src/main/java/dev/model/User.java | 27 ++- src/main/java/dev/service/AuthService.java | 66 ++++++- src/main/java/dev/service/MenuService.java | 28 ++- src/main/java/dev/service/OrderService.java | 121 ++++++++++++- src/main/java/dev/ui/ConsoleMenu.java | 124 +++++++++++--- 20 files changed, 676 insertions(+), 211 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/compiler.xml create mode 100644 .idea/encodings.xml create mode 100644 .idea/jarRepositories.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/vcs.xml 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..abb532a --- /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..0d77bc8 --- /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/database.sql b/database.sql index 2169346..25b11bc 100644 --- a/database.sql +++ b/database.sql @@ -1,141 +1,68 @@ -- Restaurant Database Management System --- --- Instructions: --- 1. Create all required tables. --- 2. Design appropriate PRIMARY KEY and FOREIGN KEY relationships. --- 3. Add suitable constraints based on the requirements. --- 4. Insert initial mock data. --- 5. Insert at least 3 menu items. --- 6. The script should be executable from start to finish without errors. - +-- Workshop 10 - Database Schema & Initial Data +-- پاک کردن جدول‌های قدیمی در صورت وجود (به ترتیب برعکس وابستگی برای جلوگیری از ارور Foreign Key) +DROP TABLE IF EXISTS order_details CASCADE; +DROP TABLE IF EXISTS orders CASCADE; +DROP TABLE IF EXISTS menu_items CASCADE; +DROP TABLE IF EXISTS users CASCADE; -- ======================================================= -- USER TABLE -- ======================================================= --- --- Represents customers using the system. --- --- Required information: --- - Unique identifier --- - Username --- - Password --- - Email (optional) --- --- Requirements: --- - Each user must have a unique identifier. --- - Usernames must be unique. --- - Username and password are required. --- - Passwords should not be stored in plain text. --- --- CREATE TABLE ... - - +CREATE TABLE users ( + id SERIAL PRIMARY KEY, + username VARCHAR(50) NOT NULL UNIQUE, + password_hash VARCHAR(255) NOT NULL, -- ذخیره به صورت هش شده مطابق نیازمندی + email VARCHAR(100) +); -- ======================================================= -- MENU ITEM TABLE -- ======================================================= --- --- Represents available food and drink items. --- --- Required information: --- - Unique identifier --- - Name --- - Description (optional) --- - Price --- - Category (optional) --- --- Requirements: --- - Each menu item must have a unique identifier. --- - Name is required. --- - Price must always be positive. --- --- CREATE TABLE ... - - +CREATE TABLE menu_items ( + id SERIAL PRIMARY KEY, + name VARCHAR(100) NOT NULL, + description TEXT, + price DECIMAL(10, 2) NOT NULL CHECK (price > 0), -- قید مثبت بودن قیمت + category VARCHAR(50) +); -- ======================================================= -- ORDER TABLE -- ======================================================= --- --- Represents orders placed by customers. --- --- Required information: --- - Unique identifier --- - Reference to customer --- - Creation date and time --- - Total price --- --- Requirements: --- - Each order must belong to exactly one user. --- - A user can have multiple orders. --- - The relationship between User and Order must be implemented. --- --- Note: --- Avoid using reserved SQL keywords as table names. --- Consider using a name such as "orders" or "customer_orders". --- --- CREATE TABLE ... - - +-- از نام جایگزین orders استفاده شده چون order کلمه کلیدی رزرو شده SQL است. +CREATE TABLE orders ( + id SERIAL PRIMARY KEY, + user_id INT NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + total_price DECIMAL(10, 2) NOT NULL DEFAULT 0.00, + CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE +); -- ======================================================= -- ORDER DETAIL TABLE -- ======================================================= --- --- Represents items inside an order. --- --- Required information: --- - Unique identifier --- - Reference to an order --- - Reference to a menu item --- - Quantity --- - Item price at purchase time --- --- Requirements: --- - Each detail record must belong to one order. --- - Each detail record must reference one menu item. --- - Quantity must always be greater than zero. --- - Store the item's price at the moment of purchase. --- --- CREATE TABLE ... - - +CREATE TABLE order_details ( + id SERIAL PRIMARY KEY, + order_id INT NOT NULL, + menu_item_id INT NOT NULL, + quantity INT NOT NULL CHECK (quantity > 0), -- قید بزرگتر از صفر بودن تعداد + unit_price DECIMAL(10, 2) NOT NULL, -- ذخیره قیمت زمان خرید (اگر بعداً قیمت منو عوض شد، فاکتورهای قبلی خراب نشوند) + CONSTRAINT fk_order FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE, + CONSTRAINT fk_menu_item FOREIGN KEY (menu_item_id) REFERENCES menu_items(id) ON DELETE RESTRICT +); -- ======================================================= --- INITIAL MENU DATA +-- INITIAL MENU DATA (حداقل ۳ آیتم) -- ======================================================= --- --- Insert at least 3 food or drink items. --- --- Example categories: --- - Pizza --- - Burger --- - Pasta --- - Drink --- --- INSERT INTO ... - - +INSERT INTO menu_items (name, description, price, category) VALUES +('Pizza', 'Delicious Pepperoni Pizza with mozzarella cheese', 10.00, 'Food'), +('Burger', 'Juicy Beef Burger with cheddar cheese and fries', 8.00, 'Food'), +('Pasta', 'Creamy Alfredo Pasta with grilled chicken', 12.00, 'Food'), +('Soda', 'Cold refreshing soft drink', 2.00, 'Drink'); -- ======================================================= --- OPTIONAL TEST DATA +-- VERIFICATION QUERIES (کدهای تایید صحت ساختار) -- ======================================================= --- --- You may insert sample users and orders for testing. --- This section is optional. --- --- INSERT INTO ... - - - --- ======================================================= --- VERIFICATION QUERIES --- ======================================================= --- --- Uncomment these queries to verify your database. --- --- SELECT * FROM ...; --- SELECT * FROM ...; --- SELECT * FROM ...; --- SELECT * FROM ...; \ No newline at end of file +SELECT * FROM menu_items; \ 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..a072e4d 100644 --- a/src/main/java/dev/dao/MenuItemDao.java +++ b/src/main/java/dev/dao/MenuItemDao.java @@ -1,25 +1,62 @@ 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.util.ArrayList; import java.util.List; public class MenuItemDao { public List findAll() { + List items = new ArrayList<>(); + String query = "SELECT * FROM menu_items"; - // TODO: - // Retrieve all menu items + try (Connection conn = DatabaseConnection.getConnection(); + PreparedStatement stmt = conn.prepareStatement(query); + ResultSet rs = stmt.executeQuery()) { - return null; + while (rs.next()) { + MenuItem item = new MenuItem( + rs.getInt("id"), + rs.getString("name"), + rs.getString("description"), + rs.getDouble("price"), + rs.getString("category") + ); + items.add(item); + } + } catch (SQLException e) { + System.err.println("Error retrieving menu items: " + e.getMessage()); + } + return items; } public MenuItem findById(int id) { + String query = "SELECT * FROM menu_items WHERE id = ?"; - // TODO: - // Find menu item by id + try (Connection conn = DatabaseConnection.getConnection(); + PreparedStatement stmt = conn.prepareStatement(query)) { + stmt.setInt(1, id); + + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + return new MenuItem( + rs.getInt("id"), + rs.getString("name"), + rs.getString("description"), + rs.getDouble("price"), + rs.getString("category") + ); + } + } + } catch (SQLException e) { + System.err.println("Error finding menu item by id: " + 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..0e3d76d 100644 --- a/src/main/java/dev/dao/OrderDao.java +++ b/src/main/java/dev/dao/OrderDao.java @@ -1,25 +1,59 @@ package dev.dao; +import dev.database.DatabaseConnection; import dev.model.Order; - +import java.sql.*; +import java.util.ArrayList; import java.util.List; public class OrderDao { public int save(Order order) { + String query = "INSERT INTO orders (user_id, total_price) VALUES (?, ?)"; - // TODO: - // Insert order and return generated id + try (Connection conn = DatabaseConnection.getConnection(); + PreparedStatement stmt = conn.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)) { + stmt.setInt(1, order.getUserId()); + stmt.setDouble(2, order.getTotalPrice()); + + int affectedRows = stmt.executeUpdate(); + if (affectedRows > 0) { + try (ResultSet generatedKeys = stmt.getGeneratedKeys()) { + if (generatedKeys.next()) { + return generatedKeys.getInt(1); // برگرداندن آیدی خودکار تولید شده فاکتور + } + } + } + } catch (SQLException e) { + System.err.println("Error saving order: " + e.getMessage()); + } return -1; } public List findByUserId(int userId) { + List orders = new ArrayList<>(); + String query = "SELECT * FROM orders WHERE user_id = ? ORDER BY created_at DESC"; - // TODO: - // Retrieve all orders of a user + try (Connection conn = DatabaseConnection.getConnection(); + PreparedStatement stmt = conn.prepareStatement(query)) { - return null; + stmt.setInt(1, userId); + + try (ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + Order order = new Order( + rs.getInt("id"), + rs.getInt("user_id"), + rs.getTimestamp("created_at").toLocalDateTime(), + rs.getDouble("total_price") + ); + orders.add(order); + } + } + } catch (SQLException e) { + System.err.println("Error retrieving user 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..f2e779b 100644 --- a/src/main/java/dev/dao/OrderDetailDao.java +++ b/src/main/java/dev/dao/OrderDetailDao.java @@ -1,24 +1,58 @@ 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 { public void save(OrderDetail detail) { + String query = "INSERT INTO order_details (order_id, menu_item_id, quantity, unit_price) VALUES (?, ?, ?, ?)"; - // TODO: - // Insert order detail + try (Connection conn = DatabaseConnection.getConnection(); + PreparedStatement stmt = conn.prepareStatement(query)) { + stmt.setInt(1, detail.getOrderId()); + stmt.setInt(2, detail.getMenuItemId()); + stmt.setInt(3, detail.getQuantity()); + stmt.setDouble(4, detail.getPrice()); + + stmt.executeUpdate(); + + } catch (SQLException e) { + System.err.println("Error saving order detail: " + e.getMessage()); + } } public List findByOrderId(int orderId) { + List details = new ArrayList<>(); + String query = "SELECT * FROM order_details WHERE order_id = ?"; - // TODO: - // Retrieve order details + try (Connection conn = DatabaseConnection.getConnection(); + PreparedStatement stmt = conn.prepareStatement(query)) { - return null; + stmt.setInt(1, orderId); + + try (ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + OrderDetail detail = new OrderDetail( + rs.getInt("id"), + rs.getInt("order_id"), + rs.getInt("menu_item_id"), + rs.getInt("quantity"), + rs.getDouble("unit_price") + ); + details.add(detail); + } + } + } catch (SQLException e) { + System.err.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..9bc8fe2 100644 --- a/src/main/java/dev/dao/UserDao.java +++ b/src/main/java/dev/dao/UserDao.java @@ -1,23 +1,54 @@ 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) { + String query = "INSERT INTO users (username, password_hash, email) VALUES (?, ?, ?)"; - // TODO: - // Insert user into database + try (Connection conn = DatabaseConnection.getConnection(); + PreparedStatement stmt = conn.prepareStatement(query)) { - return false; + stmt.setString(1, user.getUsername()); + stmt.setString(2, user.getPassword()); // مقدار پاس داده شده (که در سرویس لایه باید هش شده باشد) + stmt.setString(3, user.getEmail()); + + int affectedRows = stmt.executeUpdate(); + return affectedRows > 0; + + } catch (SQLException e) { + System.err.println("Error saving user: " + e.getMessage()); + return false; + } } public User findByUsername(String username) { + String query = "SELECT * FROM users WHERE username = ?"; - // TODO: - // Find a user by username + try (Connection conn = DatabaseConnection.getConnection(); + PreparedStatement stmt = conn.prepareStatement(query)) { + stmt.setString(1, username); + + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + return new User( + rs.getInt("id"), + rs.getString("username"), + rs.getString("password_hash"), + rs.getString("email") + ); + } + } + } catch (SQLException e) { + System.err.println("Error finding user by username: " + 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..f87cb86 100644 --- a/src/main/java/dev/database/DatabaseConnection.java +++ b/src/main/java/dev/database/DatabaseConnection.java @@ -1,27 +1,20 @@ package dev.database; import java.sql.Connection; +import java.sql.DriverManager; import java.sql.SQLException; public class DatabaseConnection { private static final String URL = "jdbc:postgresql://localhost:5432/restaurant_db"; // DB Server - private static final String USER = "postgres"; // Your Username - - private static final String PASSWORD = "password"; // Your Password + private static final String PASSWORD = "password"; // Your Password (اینجا پسورد دیتابیس خودت رو بذار) private DatabaseConnection() { - } - public static Connection getConnection() - throws SQLException { - - // TODO: - // Return a valid PostgreSQL connection - - return null; + public static Connection getConnection() throws SQLException { + // بازگرداندن یک کانکشن معتبر به PostgreSQL دیتابیس + return 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..368f57a 100644 --- a/src/main/java/dev/model/MenuItem.java +++ b/src/main/java/dev/model/MenuItem.java @@ -3,13 +3,35 @@ package dev.model; public class MenuItem { private int id; - private String name; - private String description; - private double price; - 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..59cb6ce 100644 --- a/src/main/java/dev/model/Order.java +++ b/src/main/java/dev/model/Order.java @@ -5,11 +5,30 @@ import java.time.LocalDateTime; public class Order { private int id; - private int userId; - private LocalDateTime createdAt; - 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..15740bf 100644 --- a/src/main/java/dev/model/OrderDetail.java +++ b/src/main/java/dev/model/OrderDetail.java @@ -3,13 +3,35 @@ package dev.model; public class OrderDetail { private int id; - private int orderId; - private int menuItemId; - private int quantity; - 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..0f26b13 100644 --- a/src/main/java/dev/model/User.java +++ b/src/main/java/dev/model/User.java @@ -3,11 +3,32 @@ package dev.model; public class User { private int id; - private String username; - private String password; - 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..936bf9f 100644 --- a/src/main/java/dev/service/AuthService.java +++ b/src/main/java/dev/service/AuthService.java @@ -1,23 +1,79 @@ 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) { + // چک کردن تهی نبودن ورودی‌های اجباری + if (username == null || username.trim().isEmpty() || password == null || password.trim().isEmpty()) { + System.out.println("Username and password cannot be empty!"); + return false; + } - // TODO: - // Validate and register user + // بررسی یکتا بودن نام کاربری در دیتابیس + if (userDao.findByUsername(username) != null) { + System.out.println("Username already exists!"); + return false; + } - return false; + // هش کردن پسورد برای امنیت دیتابیس طبق داک پروژه + String hashedPassword = hashPassword(password); + if (hashedPassword == null) { + return false; + } + + // ساخت آبجکت کاربر جدید و ذخیره در دیتابیس + User newUser = new User(); + newUser.setUsername(username); + newUser.setPassword(hashedPassword); + newUser.setEmail(email); + + return userDao.save(newUser); } public User login(String username, String password) { + if (username == null || password == null) { + return null; + } - // TODO: - // Authenticate user + // پیدا کردن کاربر از روی نام کاربری + User user = userDao.findByUsername(username); + if (user == null) { + System.out.println("User not found!"); + return null; + } + // هش کردن پسورد ورودی برای مقایسه با هش داخل دیتابیس + String hashedInput = hashPassword(password); + if (hashedInput != null && hashedInput.equals(user.getPassword())) { + return user; // ورود موفق + } + + System.out.println("Incorrect password!"); return null; } + // متد کمکی برای هش کردن کلمه عبور به روش SHA-256 + private String hashPassword(String password) { + try { + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + byte[] encodedhash = digest.digest(password.getBytes()); + StringBuilder hexString = new StringBuilder(); + for (byte b : encodedhash) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) hexString.append('0'); + hexString.append(hex); + } + return hexString.toString(); + } catch (NoSuchAlgorithmException e) { + System.err.println("Error hashing password: " + e.getMessage()); + return null; + } + } } \ 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..973a327 100644 --- a/src/main/java/dev/service/MenuService.java +++ b/src/main/java/dev/service/MenuService.java @@ -1,12 +1,34 @@ 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() { + List items = menuItemDao.findAll(); - // TODO: - // Display menu items + if (items == null || items.isEmpty()) { + System.out.println("The menu is currently empty."); + return; + } + System.out.println("\n======================================="); + System.out.println(" 🍽️ OUR MENU 🍽️ "); + System.out.println("======================================="); + System.out.printf("%-4s | %-12s | %-7s | %-20s\n", "ID", "Name", "Price", "Description"); + System.out.println("---------------------------------------"); + + for (MenuItem item : items) { + System.out.printf("%-4d | %-12s | $%-6.2f | %-20s\n", + item.getId(), + item.getName(), + item.getPrice(), + item.getDescription() != null ? item.getDescription() : ""); + } + System.out.println("======================================="); } - } \ 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..3d15b25 100644 --- a/src/main/java/dev/service/OrderService.java +++ b/src/main/java/dev/service/OrderService.java @@ -1,26 +1,133 @@ 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.util.ArrayList; +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) { + List cart = new ArrayList<>(); + double totalPrice = 0.0; - // TODO: - // Create order + System.out.println("\n[Placing Order]"); + 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 item = menuItemDao.findById(itemId); + if (item == null) { + System.out.println("Invalid Item ID! Please try again."); + 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(); + detail.setMenuItemId(item.getId()); + detail.setQuantity(quantity); + detail.setPrice(item.getPrice()); + + cart.add(detail); + totalPrice += item.getPrice() * quantity; + + System.out.printf("Added %dx %s to your cart.\n", quantity, item.getName()); + } + + if (cart.isEmpty()) { + System.out.println("Order cancelled. Cart is empty."); + return; + } + + // ۱. ذخیره سفارش اصلی در دیتابیس و گرفتن آیدی تولید شده + Order order = new Order(); + order.setUserId(userId); + order.setTotalPrice(totalPrice); + + int orderId = orderDao.save(order); + + if (orderId != -1) { + // ۲. ذخیره تک‌تک جزئیات سبد خرید متصل به این اوردر آیدی + for (OrderDetail detail : cart) { + detail.setOrderId(orderId); + orderDetailDao.save(detail); + } + System.out.println("\nOrder saved successfully!"); + // ۳. چاپ خودکار رسید بلافاصله پس از ثبت سفارش طبق نیازمندی داک + printReceipt(orderId); + } else { + System.out.println("Failed to save order due to a database error."); + } } public void printReceipt(int orderId) { + List details = orderDetailDao.findByOrderId(orderId); + if (details == null || details.isEmpty()) { + System.out.println("No receipt details found for Order ID: " + orderId); + return; + } - // TODO: - // Print order receipt + System.out.println("\n[Order Summary / Receipt]"); + System.out.println("---------------------------------------"); + System.out.printf("%-12s %-5s %-9s %-6s\n", "Item", "Qty", "Unit", "Total"); + System.out.println("---------------------------------------"); + double grandTotal = 0.0; + for (OrderDetail detail : details) { + MenuItem item = menuItemDao.findById(detail.getMenuItemId()); + String itemName = (item != null) ? item.getName() : "Unknown"; + double itemTotal = detail.getPrice() * detail.getQuantity(); + grandTotal += itemTotal; + + System.out.printf("%-12s %-5d $%-8.2f $%-6.2f\n", itemName, detail.getQuantity(), detail.getPrice(), itemTotal); + } + + System.out.println("---------------------------------------"); + System.out.printf("Final Total: $%-6.2f\n", grandTotal); } public void showOrderHistory(int userId) { + List orders = orderDao.findByUserId(userId); - // TODO: - // Display user's order history + if (orders == null || orders.isEmpty()) { + System.out.println("\nYou have no past orders."); + return; + } + System.out.println("\n======================================="); + System.out.println(" 📜 ORDER HISTORY 📜 "); + System.out.println("======================================="); + System.out.printf("%-10s | %-20s | %-12s\n", "Order ID", "Date & Time", "Total Price"); + System.out.println("---------------------------------------"); + + for (Order o : orders) { + System.out.printf("%-10d | %-20s | $%-12.2f\n", + o.getId(), + o.getCreatedAt().toString().replace("T", " ").substring(0, 19), + o.getTotalPrice()); + } + System.out.println("======================================="); } - } \ 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..de2b575 100644 --- a/src/main/java/dev/ui/ConsoleMenu.java +++ b/src/main/java/dev/ui/ConsoleMenu.java @@ -1,44 +1,116 @@ 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 { - private final Scanner scanner = - new Scanner(System.in); + 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(); + + private User currentUser = null; // برای مانیتور کردن وضعیت سشن کاربر جاری public void start() { - while (true) { + if (currentUser == null) { + // منوی اولیه قبل از لاگین + System.out.println(); + System.out.println("===== 🍕 WELCOME TO JAVA PIZZERIA 🍕 ====="); + System.out.println("1. Login"); + System.out.println("2. Register New Account"); + System.out.println("3. Exit"); + System.out.println("======================================="); + System.out.print("Choose an option: "); - System.out.println(); - System.out.println("===== JAVA PIZZERIA ====="); - System.out.println("1. Login"); - System.out.println("2. Register"); - System.out.println("3. Exit"); + int choice = scanner.nextInt(); + scanner.nextLine(); // مصرف کردن کلید اینتر مابقی هدر کلاینت - int choice = scanner.nextInt(); + switch (choice) { + case 1: + handleLogin(); + break; + case 2: + handleRegister(); + break; + case 3: + System.out.println("Goodbye!"); + return; + default: + System.out.println("Invalid choice! Please select a valid number."); + } + } else { + // منوی اصلی سیستم بعد از لاگین موفق کاربر طبق ساختار تمپلت داک + System.out.println(); + System.out.println("======================================="); + System.out.println(" 🍽️ MAIN MENU 🍽️ "); + System.out.println("======================================="); + 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"); + System.out.println("======================================="); + System.out.print("Choose an option: "); - switch (choice) { - - case 1: - // TODO - break; - - case 2: - // TODO - break; - - case 3: - return; - - default: - System.out.println("Invalid choice"); + int choice = scanner.nextInt(); + scanner.nextLine(); + switch (choice) { + case 1: + menuService.showMenu(); + break; + case 2: + orderService.placeOrder(currentUser.getId()); + break; + case 3: + orderService.showOrderHistory(currentUser.getId()); + break; + case 4: + System.out.println("Logged out successfully."); + currentUser = null; // ریست کردن سشن کابر جاری + break; + default: + System.out.println("Invalid choice! Please select a valid number."); + } } - } - } + private void handleLogin() { + System.out.println("\n[Login]"); + System.out.print("Enter username: "); + String username = scanner.nextLine(); + System.out.print("Enter password: "); + String password = scanner.nextLine(); + + User user = authService.login(username, password); + if (user != null) { + currentUser = user; + System.out.println("Welcome back, " + currentUser.getUsername() + "!"); + } + } + + private void handleRegister() { + System.out.println("\n[Register New Account]"); + System.out.print("Enter username: "); + String username = scanner.nextLine(); + System.out.print("Enter password: "); + String password = scanner.nextLine(); + System.out.print("Enter email (optional, press Enter to skip): "); + String email = scanner.nextLine(); + if (email.trim().isEmpty()) { + email = null; + } + + boolean success = authService.register(username, password, email); + if (success) { + System.out.println("Account created successfully! You can now log in."); + } else { + System.out.println("Registration failed."); + } + } } \ No newline at end of file