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/dataSources.xml b/.idea/dataSources.xml
new file mode 100644
index 0000000..84a2485
--- /dev/null
+++ b/.idea/dataSources.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ postgresql
+ true
+ org.postgresql.Driver
+ jdbc:postgresql://localhost:5432/restaurant_db
+ $ProjectFileDir$
+
+
+
\ 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..4158879
--- /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..f6a588b
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml
new file mode 100644
index 0000000..c3c8b8e
--- /dev/null
+++ b/.idea/sqldialects.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ 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..d777d05 100644
--- a/database.sql
+++ b/database.sql
@@ -138,4 +138,138 @@
-- SELECT * FROM ...;
-- SELECT * FROM ...;
-- SELECT * FROM ...;
--- SELECT * FROM ...;
\ No newline at end of file
+-- SELECT * FROM ...;
+
+
+-- =======================================================
+-- Restaurant Database Management System
+-- PostgreSQL Schema
+-- =======================================================
+
+-- -------------------------------------------------------
+-- OPTIONAL CLEANUP
+-- Uncomment if you want to reset the database completely
+-- -------------------------------------------------------
+-- 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.
+-- Requirements:
+-- - Unique identifier
+-- - Unique username
+-- - Required username and password
+-- - Passwords should not be stored in plain text
+CREATE TABLE users (
+ id SERIAL PRIMARY KEY,
+ username VARCHAR(100) NOT NULL UNIQUE,
+ password_hash VARCHAR(255) NOT NULL,
+ email VARCHAR(255)
+);
+
+-- =======================================================
+-- MENU ITEM TABLE
+-- =======================================================
+-- Represents available food and drink items.
+-- Requirements:
+-- - Unique identifier
+-- - Name required
+-- - Price positive
+CREATE TABLE menu_items (
+ id SERIAL PRIMARY KEY,
+ name VARCHAR(150) NOT NULL,
+ description TEXT,
+ price DOUBLE PRECISION NOT NULL CHECK (price > 0),
+ category VARCHAR(100)
+);
+
+-- =======================================================
+-- ORDER TABLE
+-- =======================================================
+-- Represents orders placed by customers.
+-- Requirements:
+-- - Each order belongs to exactly one user
+-- - A user can have multiple orders
+-- - Use non-reserved table name: orders
+CREATE TABLE orders (
+ id SERIAL PRIMARY KEY,
+ user_id INT NOT NULL,
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ total_price DOUBLE PRECISION NOT NULL DEFAULT 0 CHECK (total_price >= 0),
+ CONSTRAINT fk_orders_user
+ FOREIGN KEY (user_id)
+ REFERENCES users(id)
+ ON DELETE CASCADE
+);
+
+-- =======================================================
+-- ORDER DETAIL TABLE
+-- =======================================================
+-- Represents items inside an order.
+-- Requirements:
+-- - Each detail belongs to one order
+-- - Each detail references one menu item
+-- - Quantity > 0
+-- - Store item price at purchase time
+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),
+ price DOUBLE PRECISION NOT NULL CHECK (price > 0),
+ CONSTRAINT fk_order_details_order
+ FOREIGN KEY (order_id)
+ REFERENCES orders(id)
+ ON DELETE CASCADE,
+ CONSTRAINT fk_order_details_menu_item
+ FOREIGN KEY (menu_item_id)
+ REFERENCES menu_items(id)
+);
+
+-- =======================================================
+-- INITIAL MENU DATA
+-- =======================================================
+-- Insert at least 3 food/drink items
+INSERT INTO menu_items (name, description, price, category) VALUES
+ ('Margherita Pizza', 'Classic pizza with tomato sauce, mozzarella, and basil', 8.99, 'Pizza'),
+ ('Pepperoni Pizza', 'Pizza topped with pepperoni and cheese', 10.99, 'Pizza'),
+ ('Cheeseburger', 'Beef burger with cheddar cheese and lettuce', 7.50, 'Burger'),
+ ('Pasta Carbonara', 'Creamy pasta with bacon and parmesan', 11.50, 'Pasta'),
+ ('Coca Cola', 'Chilled soft drink', 1.50, 'Drink');
+
+-- =======================================================
+-- OPTIONAL TEST DATA
+-- =======================================================
+-- Sample user for testing (password is hashed placeholder)
+INSERT INTO users (username, password_hash, email) VALUES
+ ('testuser', '$2a$10$dummyhashforTestingOnly12345678901234567890', 'testuser@example.com');
+
+-- Sample order for testing
+INSERT INTO orders (user_id, created_at, total_price)
+VALUES (1, CURRENT_TIMESTAMP, 0);
+
+-- Sample order details for testing
+INSERT INTO order_details (order_id, menu_item_id, quantity, price) VALUES
+ (1, 1, 2, 8.99),
+ (1, 5, 2, 1.50);
+
+-- Update total price for the sample order
+UPDATE orders
+SET total_price = (
+ SELECT SUM(quantity * price)
+ FROM order_details
+ WHERE order_id = 1
+)
+WHERE id = 1;
+
+-- =======================================================
+-- VERIFICATION QUERIES
+-- =======================================================
+SELECT * FROM users;
+SELECT * FROM menu_items;
+SELECT * FROM orders;
+SELECT * FROM order_details;
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 028ca50..1b26cb2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,6 +21,12 @@
+
+ org.mindrot
+ jbcrypt
+ 0.4
+
+
org.postgresql
postgresql
diff --git a/restaurant_db.sql b/restaurant_db.sql
new file mode 100644
index 0000000..2ce88b9
--- /dev/null
+++ b/restaurant_db.sql
@@ -0,0 +1,110 @@
+CREATE TABLE users (
+ id SERIAL PRIMARY KEY,
+ username VARCHAR(100) NOT NULL UNIQUE,
+ password_hash VARCHAR(255) NOT NULL,
+ email VARCHAR(255)
+);
+
+-- =======================================================
+-- MENU ITEM TABLE
+-- =======================================================
+-- Represents available food and drink items.
+-- Requirements:
+-- - Unique identifier
+-- - Name required
+-- - Price positive
+CREATE TABLE menu_items (
+ id SERIAL PRIMARY KEY,
+ name VARCHAR(150) NOT NULL,
+ description TEXT,
+ price DOUBLE PRECISION NOT NULL CHECK (price > 0),
+ category VARCHAR(100)
+);
+
+-- =======================================================
+-- ORDER TABLE
+-- =======================================================
+-- Represents orders placed by customers.
+-- Requirements:
+-- - Each order belongs to exactly one user
+-- - A user can have multiple orders
+-- - Use non-reserved table name: orders
+CREATE TABLE orders (
+ id SERIAL PRIMARY KEY,
+ user_id INT NOT NULL,
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ total_price DOUBLE PRECISION NOT NULL DEFAULT 0 CHECK (total_price >= 0),
+ CONSTRAINT fk_orders_user
+ FOREIGN KEY (user_id)
+ REFERENCES users(id)
+ ON DELETE CASCADE
+);
+
+-- =======================================================
+-- ORDER DETAIL TABLE
+-- =======================================================
+-- Represents items inside an order.
+-- Requirements:
+-- - Each detail belongs to one order
+-- - Each detail references one menu item
+-- - Quantity > 0
+-- - Store item price at purchase time
+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),
+ price DOUBLE PRECISION NOT NULL CHECK (price > 0),
+ CONSTRAINT fk_order_details_order
+ FOREIGN KEY (order_id)
+ REFERENCES orders(id)
+ ON DELETE CASCADE,
+ CONSTRAINT fk_order_details_menu_item
+ FOREIGN KEY (menu_item_id)
+ REFERENCES menu_items(id)
+ ON DELETE RESTRICT
+);
+
+-- =======================================================
+-- INITIAL MENU DATA
+-- =======================================================
+-- Insert at least 3 food/drink items
+INSERT INTO menu_items (name, description, price, category) VALUES
+ ('Margherita Pizza', 'Classic pizza with tomato sauce, mozzarella, and basil', 8.99, 'Pizza'),
+ ('Pepperoni Pizza', 'Pizza topped with pepperoni and cheese', 10.99, 'Pizza'),
+ ('Cheeseburger', 'Beef burger with cheddar cheese and lettuce', 7.50, 'Burger'),
+ ('Pasta Carbonara', 'Creamy pasta with bacon and parmesan', 11.50, 'Pasta'),
+ ('Coca Cola', 'Chilled soft drink', 1.50, 'Drink');
+
+-- =======================================================
+-- OPTIONAL TEST DATA
+-- =======================================================
+-- Sample user for testing (password is hashed placeholder)
+INSERT INTO users (username, password_hash, email) VALUES
+ ('testuser', '$2a$10$dummyhashforTestingOnly12345678901234567890', 'testuser@example.com');
+
+-- Sample order for testing
+INSERT INTO orders (user_id, created_at, total_price)
+VALUES (1, CURRENT_TIMESTAMP, 0);
+
+-- Sample order details for testing
+INSERT INTO order_details (order_id, menu_item_id, quantity, price) VALUES
+ (1, 1, 2, 8.99),
+ (1, 5, 2, 1.50);
+
+-- Update total price for the sample order
+UPDATE orders
+SET total_price = (
+ SELECT SUM(quantity * price)
+ FROM order_details
+ WHERE order_id = 1
+)
+WHERE id = 1;
+
+-- =======================================================
+-- VERIFICATION QUERIES
+-- =======================================================
+SELECT * FROM users;
+SELECT * FROM menu_items;
+SELECT * FROM orders;
+SELECT * FROM order_details;
diff --git a/src/main/java/dev/Main.java b/src/main/java/dev/Main.java
index 3a93683..24432cd 100644
--- a/src/main/java/dev/Main.java
+++ b/src/main/java/dev/Main.java
@@ -1,12 +1,21 @@
package dev;
import dev.ui.ConsoleMenu;
+import dev.service.AuthService;
+import dev.service.MenuService;
+import dev.service.OrderService;
-public class Main {
+public class Main
+{
- public static void main(String[] args) {
+ public static void main(String[] args)
+ {
+
+ AuthService authService = new AuthService();
+ MenuService menuService = new MenuService();
+ OrderService orderService = new OrderService();
- ConsoleMenu menu = new ConsoleMenu();
+ ConsoleMenu menu = new ConsoleMenu(authService, menuService, orderService);
menu.start();
}
diff --git a/src/main/java/dev/dao/MenuItemDao.java b/src/main/java/dev/dao/MenuItemDao.java
index 3bbebe9..021da09 100644
--- a/src/main/java/dev/dao/MenuItemDao.java
+++ b/src/main/java/dev/dao/MenuItemDao.java
@@ -1,24 +1,73 @@
package dev.dao;
+import dev.database.DatabaseConnection;
import dev.model.MenuItem;
-
+import java.sql.*;
+import java.util.ArrayList;
import java.util.List;
-public class MenuItemDao {
+public class MenuItemDao
+{
- public List