Restoran İdarəetmə Sistem Dizaynı
Problem Təsviri
Menyu idarəetməsi, sifariş işləmə, masa rezervasyonları və restoran üçün hesab-faktura əməliyyatlarını həll edə bilən restoran idarəetmə sistemi dizayn edin.
Tələblər
-
Funksional Tələblər:
- Restoran menyusunun idarə edilməsi (əlavə etmə, yeniləmə, silmə)
- Müştəri sifarişlərinin işlənməsi
- Masa rezervasyonlarının idarə edilməsi
- Masa təyinatlarının idarə edilməsi
- Ödənişlərin işlənməsi və hesab-fakturaların yaradılması
- İnventarın və inqredientlərin izlənməsi
- Müxtəlif istifadəçi rolları dəstəyi (menecer, garson, aşbaz, kassir)
-
Qeyri-Funksional Tələblər:
- Concurrent sifariş işləmə
- Sifariş statusu yeniləmələri üçün sürətli cavab müddəti
- Ödəniş işləmə üçün etibarlılıq
- Yüksək yüklənmə zamanlarında scalability
Əsas Komponentlər
- Menyu İdarəetməsi: Yemək məhsulları və qiymətlərin saxlanması
- Sifariş Sistemi: Müştəri sifarişlərinin qəbulu və işlənməsi
- Masa İdarəetməsi: Masa rezervasyonları və təyinatlar
- İnventarın İzlənməsi: İnqredient və stok idarəetməsi
- Hesab-faktura Sistemi: Ödəniş hesablaması və işləmə
- İstifadəçi İdarəetməsi: Müxtəlif rol və icazələr
Dizayn Yanaşması
Sifariş işləmə və masa idarəetməsi üçün State Pattern istifadə edəcəyik:
Masa Statusları:
- Available: Masa boş və istifadə üçün hazır
- Reserved: Masa rezerv olunub
- Occupied: Masa müştərilər tərəfindən istifadə olunur
- Cleaning: Masa təmizlənir
Sifariş Statusları:
- Pending: Sifariş gözləyir
- Confirmed: Sifariş təsdiqlənib
- Preparing: Sifariş hazırlanır
- Ready: Sifariş hazırdır
- Served: Sifariş təqdim olunub
- Paid: Sifariş ödənilib
İcra
Koda bax
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.ConcurrentHashMap;
// User roles
enum UserRole {
MANAGER, WAITER, CHEF, CASHIER, CUSTOMER
}
// Table status
enum TableStatus {
AVAILABLE, RESERVED, OCCUPIED, CLEANING, OUT_OF_ORDER
}
// Order status
enum OrderStatus {
PENDING, CONFIRMED, PREPARING, READY, SERVED, PAID, CANCELLED
}
// Menu item categories
enum MenuCategory {
APPETIZER, MAIN_COURSE, DESSERT, BEVERAGE, SALAD, SOUP
}
// User class
class User {
private final String userId;
private final String name;
private final String email;
private final UserRole role;
private final String phoneNumber;
public User(String userId, String name, String email, UserRole role, String phoneNumber) {
this.userId = userId;
this.name = name;
this.email = email;
this.role = role;
this.phoneNumber = phoneNumber;
}
public String getUserId() { return userId; }
public String getName() { return name; }
public String getEmail() { return email; }
public UserRole getRole() { return role; }
public String getPhoneNumber() { return phoneNumber; }
@Override
public String toString() {
return String.format("User{%s: %s (%s)}", userId, name, role);
}
}
// Menu item class
class MenuItem {
private final String itemId;
private String name;
private String description;
private BigDecimal price;
private final MenuCategory category;
private boolean available;
private final Map<String, Integer> ingredients; // ingredient -> quantity needed
private int preparationTime; // in minutes
public MenuItem(String itemId, String name, String description, BigDecimal price,
MenuCategory category, int preparationTime) {
this.itemId = itemId;
this.name = name;
this.description = description;
this.price = price;
this.category = category;
this.available = true;
this.ingredients = new HashMap<>();
this.preparationTime = preparationTime;
}
public String getItemId() { return itemId; }
public String getName() { return name; }
public String getDescription() { return description; }
public BigDecimal getPrice() { return price; }
public MenuCategory getCategory() { return category; }
public boolean isAvailable() { return available; }
public Map<String, Integer> getIngredients() { return new HashMap<>(ingredients); }
public int getPreparationTime() { return preparationTime; }
public void setName(String name) { this.name = name; }
public void setDescription(String description) { this.description = description; }
public void setPrice(BigDecimal price) { this.price = price; }
public void setAvailable(boolean available) { this.available = available; }
public void setPreparationTime(int preparationTime) { this.preparationTime = preparationTime; }
public void addIngredient(String ingredient, int quantity) {
ingredients.put(ingredient, quantity);
}
public void removeIngredient(String ingredient) {
ingredients.remove(ingredient);
}
@Override
public String toString() {
return String.format("MenuItem{%s: %s - $%.2f (%s)}",
itemId, name, price, available ? "Available" : "Unavailable");
}
}
// Ingredient class
class Ingredient {
private final String ingredientId;
private final String name;
private String unit;
private int currentStock;
private int minThreshold;
private final Lock lock;
public Ingredient(String ingredientId, String name, String unit,
int currentStock, int minThreshold) {
this.ingredientId = ingredientId;
this.name = name;
this.unit = unit;
this.currentStock = currentStock;
this.minThreshold = minThreshold;
this.lock = new ReentrantLock();
}
public String getIngredientId() { return ingredientId; }
public String getName() { return name; }
public String getUnit() { return unit; }
public int getCurrentStock() { return currentStock; }
public int getMinThreshold() { return minThreshold; }
public boolean consume(int quantity) {
lock.lock();
try {
if (currentStock >= quantity) {
currentStock -= quantity;
return true;
}
return false;
} finally {
lock.unlock();
}
}
public void restock(int quantity) {
lock.lock();
try {
currentStock += quantity;
} finally {
lock.unlock();
}
}
public boolean isLowStock() {
return currentStock <= minThreshold;
}
public void setUnit(String unit) { this.unit = unit; }
public void setMinThreshold(int minThreshold) { this.minThreshold = minThreshold; }
@Override
public String toString() {
return String.format("Ingredient{%s: %s - %d %s (Min: %d)%s}",
ingredientId, name, currentStock, unit, minThreshold,
isLowStock() ? " [LOW STOCK]" : "");
}
}
// Table class
class RestaurantTable {
private final String tableId;
private final int capacity;
private TableStatus status;
private String assignedWaiterId;
private LocalDateTime reservationTime;
private LocalDateTime occupiedSince;
private final Lock lock;
public RestaurantTable(String tableId, int capacity) {
this.tableId = tableId;
this.capacity = capacity;
this.status = TableStatus.AVAILABLE;
this.lock = new ReentrantLock();
}
public String getTableId() { return tableId; }
public int getCapacity() { return capacity; }
public TableStatus getStatus() { return status; }
public String getAssignedWaiterId() { return assignedWaiterId; }
public LocalDateTime getReservationTime() { return reservationTime; }
public LocalDateTime getOccupiedSince() { return occupiedSince; }
public boolean reserve(LocalDateTime reservationTime) {
lock.lock();
try {
if (status == TableStatus.AVAILABLE) {
this.status = TableStatus.RESERVED;
this.reservationTime = reservationTime;
return true;
}
return false;
} finally {
lock.unlock();
}
}
public boolean occupy(String waiterId) {
lock.lock();
try {
if (status == TableStatus.AVAILABLE || status == TableStatus.RESERVED) {
this.status = TableStatus.OCCUPIED;
this.assignedWaiterId = waiterId;
this.occupiedSince = LocalDateTime.now();
this.reservationTime = null;
return true;
}
return false;
} finally {
lock.unlock();
}
}
public boolean startCleaning() {
lock.lock();
try {
if (status == TableStatus.OCCUPIED) {
this.status = TableStatus.CLEANING;
this.assignedWaiterId = null;
this.occupiedSince = null;
return true;
}
return false;
} finally {
lock.unlock();
}
}
public boolean makeAvailable() {
lock.lock();
try {
if (status == TableStatus.CLEANING || status == TableStatus.RESERVED) {
this.status = TableStatus.AVAILABLE;
this.assignedWaiterId = null;
this.occupiedSince = null;
this.reservationTime = null;
return true;
}
return false;
} finally {
lock.unlock();
}
}
public void setOutOfOrder() {
lock.lock();
try {
if (status == TableStatus.AVAILABLE) {
this.status = TableStatus.OUT_OF_ORDER;
}
} finally {
lock.unlock();
}
}
@Override
public String toString() {
return String.format("Table{%s: Capacity %d, Status: %s, Waiter: %s}",
tableId, capacity, status, assignedWaiterId);
}
}
// Order item class
class OrderItem {
private final String menuItemId;
private final String itemName;
private final int quantity;
private final BigDecimal unitPrice;
private final String specialInstructions;
public OrderItem(String menuItemId, String itemName, int quantity,
BigDecimal unitPrice, String specialInstructions) {
this.menuItemId = menuItemId;
this.itemName = itemName;
this.quantity = quantity;
this.unitPrice = unitPrice;
this.specialInstructions = specialInstructions;
}
public String getMenuItemId() { return menuItemId; }
public String getItemName() { return itemName; }
public int getQuantity() { return quantity; }
public BigDecimal getUnitPrice() { return unitPrice; }
public String getSpecialInstructions() { return specialInstructions; }
public BigDecimal getTotalPrice() {
return unitPrice.multiply(BigDecimal.valueOf(quantity));
}
@Override
public String toString() {
return String.format("OrderItem{%s x%d @ $%.2f = $%.2f%s}",
itemName, quantity, unitPrice, getTotalPrice(),
specialInstructions != null ? " (" + specialInstructions + ")" : "");
}
}
// Order class
class Order {
private final String orderId;
private final String tableId;
private final String waiterId;
private final String customerId;
private final List<OrderItem> items;
private OrderStatus status;
private LocalDateTime orderTime;
private LocalDateTime confirmedTime;
private LocalDateTime readyTime;
private LocalDateTime servedTime;
private LocalDateTime paidTime;
private final Lock lock;
private BigDecimal discount;
private String notes;
public Order(String orderId, String tableId, String waiterId, String customerId) {
this.orderId = orderId;
this.tableId = tableId;
this.waiterId = waiterId;
this.customerId = customerId;
this.items = new ArrayList<>();
this.status = OrderStatus.PENDING;
this.orderTime = LocalDateTime.now();
this.lock = new ReentrantLock();
this.discount = BigDecimal.ZERO;
}
public String getOrderId() { return orderId; }
public String getTableId() { return tableId; }
public String getWaiterId() { return waiterId; }
public String getCustomerId() { return customerId; }
public List<OrderItem> getItems() { return new ArrayList<>(items); }
public OrderStatus getStatus() { return status; }
public LocalDateTime getOrderTime() { return orderTime; }
public LocalDateTime getConfirmedTime() { return confirmedTime; }
public LocalDateTime getReadyTime() { return readyTime; }
public LocalDateTime getServedTime() { return servedTime; }
public LocalDateTime getPaidTime() { return paidTime; }
public BigDecimal getDiscount() { return discount; }
public String getNotes() { return notes; }
public void addItem(OrderItem item) {
lock.lock();
try {
if (status == OrderStatus.PENDING) {
items.add(item);
}
} finally {
lock.unlock();
}
}
public void removeItem(String menuItemId) {
lock.lock();
try {
if (status == OrderStatus.PENDING) {
items.removeIf(item -> item.getMenuItemId().equals(menuItemId));
}
} finally {
lock.unlock();
}
}
public void confirm() {
lock.lock();
try {
if (status == OrderStatus.PENDING) {
status = OrderStatus.CONFIRMED;
confirmedTime = LocalDateTime.now();
}
} finally {
lock.unlock();
}
}
public void startPreparing() {
lock.lock();
try {
if (status == OrderStatus.CONFIRMED) {
status = OrderStatus.PREPARING;
}
} finally {
lock.unlock();
}
}
public void markReady() {
lock.lock();
try {
if (status == OrderStatus.PREPARING) {
status = OrderStatus.READY;
readyTime = LocalDateTime.now();
}
} finally {
lock.unlock();
}
}
public void serve() {
lock.lock();
try {
if (status == OrderStatus.READY) {
status = OrderStatus.SERVED;
servedTime = LocalDateTime.now();
}
} finally {
lock.unlock();
}
}
public void markPaid() {
lock.lock();
try {
if (status == OrderStatus.SERVED) {
status = OrderStatus.PAID;
paidTime = LocalDateTime.now();
}
} finally {
lock.unlock();
}
}
public void cancel() {
lock.lock();
try {
if (status != OrderStatus.PAID) {
status = OrderStatus.CANCELLED;
}
} finally {
lock.unlock();
}
}
public void setDiscount(BigDecimal discount) {
lock.lock();
try {
this.discount = discount != null ? discount : BigDecimal.ZERO;
} finally {
lock.unlock();
}
}
public void setNotes(String notes) {
lock.lock();
try {
this.notes = notes;
} finally {
lock.unlock();
}
}
public BigDecimal getSubtotal() {
return items.stream()
.map(OrderItem::getTotalPrice)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
public BigDecimal getTotalAmount() {
return getSubtotal().subtract(discount);
}
public int getEstimatedPreparationTime() {
// This would be calculated based on menu items' preparation times
return 30; // Default 30 minutes
}
@Override
public String toString() {
return String.format("Order{%s: Table %s, Status: %s, Items: %d, Total: $%.2f}",
orderId, tableId, status, items.size(), getTotalAmount());
}
}
// Bill class
class Bill {
private final String billId;
private final String orderId;
private final BigDecimal subtotal;
private final BigDecimal discount;
private final BigDecimal tax;
private final BigDecimal total;
private final LocalDateTime generatedTime;
private boolean paid;
public Bill(String billId, String orderId, BigDecimal subtotal,
BigDecimal discount, BigDecimal taxRate) {
this.billId = billId;
this.orderId = orderId;
this.subtotal = subtotal;
this.discount = discount;
this.tax = subtotal.subtract(discount).multiply(taxRate);
this.total = subtotal.subtract(discount).add(tax);
this.generatedTime = LocalDateTime.now();
this.paid = false;
}
public String getBillId() { return billId; }
public String getOrderId() { return orderId; }
public BigDecimal getSubtotal() { return subtotal; }
public BigDecimal getDiscount() { return discount; }
public BigDecimal getTax() { return tax; }
public BigDecimal getTotal() { return total; }
public LocalDateTime getGeneratedTime() { return generatedTime; }
public boolean isPaid() { return paid; }
public void markPaid() {
this.paid = true;
}
@Override
public String toString() {
return String.format("Bill{%s: Order %s, Total: $%.2f, Paid: %s}",
billId, orderId, total, paid);
}
}
// Restaurant management service
class RestaurantManagementService {
private final Map<String, User> users;
private final Map<String, MenuItem> menuItems;
private final Map<String, Ingredient> ingredients;
private final Map<String, RestaurantTable> tables;
private final Map<String, Order> orders;
private final Map<String, Bill> bills;
private final BigDecimal taxRate;
public RestaurantManagementService() {
this.users = new ConcurrentHashMap<>();
this.menuItems = new ConcurrentHashMap<>();
this.ingredients = new ConcurrentHashMap<>();
this.tables = new ConcurrentHashMap<>();
this.orders = new ConcurrentHashMap<>();
this.bills = new ConcurrentHashMap<>();
this.taxRate = new BigDecimal("0.08"); // 8% tax rate
initializeDefaultData();
}
private void initializeDefaultData() {
// Create default ingredients
addIngredient(new Ingredient("ING001", "Chicken", "kg", 50, 10));
addIngredient(new Ingredient("ING002", "Rice", "kg", 100, 20));
addIngredient(new Ingredient("ING003", "Tomatoes", "kg", 30, 5));
addIngredient(new Ingredient("ING004", "Cheese", "kg", 25, 5));
// Create default menu items
MenuItem chicken = new MenuItem("MENU001", "Chicken Pilaf", "Delicious chicken with rice",
new BigDecimal("15.99"), MenuCategory.MAIN_COURSE, 25);
chicken.addIngredient("ING001", 200); // 200g chicken
chicken.addIngredient("ING002", 150); // 150g rice
addMenuItem(chicken);
MenuItem salad = new MenuItem("MENU002", "Caesar Salad", "Fresh salad with cheese",
new BigDecimal("8.99"), MenuCategory.SALAD, 10);
salad.addIngredient("ING003", 100); // 100g tomatoes
salad.addIngredient("ING004", 50); // 50g cheese
addMenuItem(salad);
// Create default tables
for (int i = 1; i <= 10; i++) {
int capacity = i <= 4 ? 2 : (i <= 8 ? 4 : 6);
addTable(new RestaurantTable("TABLE" + String.format("%02d", i), capacity));
}
// Create default users
addUser(new User("MGR001", "John Manager", "manager@restaurant.com", UserRole.MANAGER, "+1234567890"));
addUser(new User("WAIT001", "Alice Waiter", "alice@restaurant.com", UserRole.WAITER, "+1234567891"));
addUser(new User("CHEF001", "Bob Chef", "bob@restaurant.com", UserRole.CHEF, "+1234567892"));
addUser(new User("CASH001", "Carol Cashier", "carol@restaurant.com", UserRole.CASHIER, "+1234567893"));
}
public void addUser(User user) {
users.put(user.getUserId(), user);
}
public void addMenuItem(MenuItem item) {
menuItems.put(item.getItemId(), item);
}
public void addIngredient(Ingredient ingredient) {
ingredients.put(ingredient.getIngredientId(), ingredient);
}
public void addTable(RestaurantTable table) {
tables.put(table.getTableId(), table);
}
public List<MenuItem> getMenuByCategory(MenuCategory category) {
return menuItems.values().stream()
.filter(item -> item.getCategory() == category && item.isAvailable())
.toList();
}
public List<MenuItem> getAvailableMenuItems() {
return menuItems.values().stream()
.filter(MenuItem::isAvailable)
.toList();
}
public List<RestaurantTable> getAvailableTables() {
return tables.values().stream()
.filter(table -> table.getStatus() == TableStatus.AVAILABLE)
.toList();
}
public List<RestaurantTable> getAvailableTablesForCapacity(int requiredCapacity) {
return tables.values().stream()
.filter(table -> table.getStatus() == TableStatus.AVAILABLE &&
table.getCapacity() >= requiredCapacity)
.toList();
}
public boolean reserveTable(String tableId, LocalDateTime reservationTime) {
RestaurantTable table = tables.get(tableId);
return table != null && table.reserve(reservationTime);
}
public boolean occupyTable(String tableId, String waiterId) {
RestaurantTable table = tables.get(tableId);
return table != null && table.occupy(waiterId);
}
public String createOrder(String tableId, String waiterId, String customerId) {
String orderId = "ORDER-" + System.currentTimeMillis();
Order order = new Order(orderId, tableId, waiterId, customerId);
orders.put(orderId, order);
return orderId;
}
public boolean addItemToOrder(String orderId, String menuItemId, int quantity,
String specialInstructions) {
Order order = orders.get(orderId);
MenuItem menuItem = menuItems.get(menuItemId);
if (order == null || menuItem == null || !menuItem.isAvailable()) {
return false;
}
// Check ingredient availability
for (Map.Entry<String, Integer> entry : menuItem.getIngredients().entrySet()) {
Ingredient ingredient = ingredients.get(entry.getKey());
if (ingredient == null || ingredient.getCurrentStock() < entry.getValue() * quantity) {
return false;
}
}
OrderItem orderItem = new OrderItem(menuItemId, menuItem.getName(), quantity,
menuItem.getPrice(), specialInstructions);
order.addItem(orderItem);
return true;
}
public boolean confirmOrder(String orderId) {
Order order = orders.get(orderId);
if (order == null || order.getStatus() != OrderStatus.PENDING) {
return false;
}
// Consume ingredients
for (OrderItem orderItem : order.getItems()) {
MenuItem menuItem = menuItems.get(orderItem.getMenuItemId());
if (menuItem != null) {
for (Map.Entry<String, Integer> entry : menuItem.getIngredients().entrySet()) {
Ingredient ingredient = ingredients.get(entry.getKey());
if (ingredient != null) {
ingredient.consume(entry.getValue() * orderItem.getQuantity());
}
}
}
}
order.confirm();
return true;
}
public void updateOrderStatus(String orderId, OrderStatus newStatus) {
Order order = orders.get(orderId);
if (order != null) {
switch (newStatus) {
case PREPARING -> order.startPreparing();
case READY -> order.markReady();
case SERVED -> order.serve();
case PAID -> order.markPaid();
case CANCELLED -> order.cancel();
}
}
}
public String generateBill(String orderId) {
Order order = orders.get(orderId);
if (order == null || order.getStatus() != OrderStatus.SERVED) {
return null;
}
String billId = "BILL-" + System.currentTimeMillis();
Bill bill = new Bill(billId, orderId, order.getSubtotal(),
order.getDiscount(), taxRate);
bills.put(billId, bill);
return billId;
}
public boolean processBillPayment(String billId) {
Bill bill = bills.get(billId);
if (bill == null || bill.isPaid()) {
return false;
}
bill.markPaid();
// Mark order as paid
Order order = orders.get(bill.getOrderId());
if (order != null) {
order.markPaid();
// Free up the table
RestaurantTable table = tables.get(order.getTableId());
if (table != null) {
table.startCleaning();
}
}
return true;
}
public List<Order> getOrdersByStatus(OrderStatus status) {
return orders.values().stream()
.filter(order -> order.getStatus() == status)
.toList();
}
public List<Order> getOrdersByWaiter(String waiterId) {
return orders.values().stream()
.filter(order -> order.getWaiterId().equals(waiterId))
.toList();
}
public List<Ingredient> getLowStockIngredients() {
return ingredients.values().stream()
.filter(Ingredient::isLowStock)
.toList();
}
public void restockIngredient(String ingredientId, int quantity) {
Ingredient ingredient = ingredients.get(ingredientId);
if (ingredient != null) {
ingredient.restock(quantity);
}
}
public void completeTableCleaning(String tableId) {
RestaurantTable table = tables.get(tableId);
if (table != null) {
table.makeAvailable();
}
}
// Getters for accessing data
public Order getOrder(String orderId) { return orders.get(orderId); }
public Bill getBill(String billId) { return bills.get(billId); }
public MenuItem getMenuItem(String itemId) { return menuItems.get(itemId); }
public RestaurantTable getTable(String tableId) { return tables.get(tableId); }
public User getUser(String userId) { return users.get(userId); }
public Ingredient getIngredient(String ingredientId) { return ingredients.get(ingredientId); }
}
// Example usage
public class RestaurantManagementDemo {
public static void main(String[] args) {
RestaurantManagementService restaurant = new RestaurantManagementService();
System.out.println("Restoran İdarəetmə Sistemi Demo");
System.out.println("================================");
// Display available tables
System.out.println("\nMövcud masalar:");
restaurant.getAvailableTables().forEach(System.out::println);
// Display menu
System.out.println("\nMenudakı əsas yeməklər:");
restaurant.getMenuByCategory(MenuCategory.MAIN_COURSE).forEach(System.out::println);
// Occupy a table
String tableId = "TABLE01";
String waiterId = "WAIT001";
String customerId = "CUST001";
boolean tableOccupied = restaurant.occupyTable(tableId, waiterId);
System.out.println("\nMasa " + tableId + " işğal edildi: " + tableOccupied);
// Create an order
String orderId = restaurant.createOrder(tableId, waiterId, customerId);
System.out.println("Sifariş yaradıldı: " + orderId);
// Add items to order
boolean itemAdded1 = restaurant.addItemToOrder(orderId, "MENU001", 2, "Az duzlu");
boolean itemAdded2 = restaurant.addItemToOrder(orderId, "MENU002", 1, null);
System.out.println("Chicken Pilaf əlavə edildi: " + itemAdded1);
System.out.println("Caesar Salad əlavə edildi: " + itemAdded2);
// Display order
Order order = restaurant.getOrder(orderId);
System.out.println("\nSifariş detalları:");
System.out.println(order);
order.getItems().forEach(System.out::println);
System.out.println("Alt cəmi: $" + order.getSubtotal());
System.out.println("Ümumi: $" + order.getTotalAmount());
// Confirm order
boolean orderConfirmed = restaurant.confirmOrder(orderId);
System.out.println("\nSifariş təsdiqləndi: " + orderConfirmed);
// Update order status through kitchen workflow
restaurant.updateOrderStatus(orderId, OrderStatus.PREPARING);
System.out.println("Sifariş hazırlanır: " + restaurant.getOrder(orderId).getStatus());
restaurant.updateOrderStatus(orderId, OrderStatus.READY);
System.out.println("Sifariş hazırdır: " + restaurant.getOrder(orderId).getStatus());
restaurant.updateOrderStatus(orderId, OrderStatus.SERVED);
System.out.println("Sifariş təqdim edildi: " + restaurant.getOrder(orderId).getStatus());
// Generate bill
String billId = restaurant.generateBill(orderId);
System.out.println("\nHesab-faktura yaradıldı: " + billId);
Bill bill = restaurant.getBill(billId);
System.out.println("Hesab-faktura detalları:");
System.out.println("Alt cəmi: $" + bill.getSubtotal());
System.out.println("Endirim: $" + bill.getDiscount());
System.out.println("Vergi: $" + bill.getTax());
System.out.println("Ümumi: $" + bill.getTotal());
// Process payment
boolean paymentProcessed = restaurant.processBillPayment(billId);
System.out.println("Ödəniş işləndi: " + paymentProcessed);
// Check ingredient levels
System.out.println("\nAz inventar məhsulları:");
restaurant.getLowStockIngredients().forEach(System.out::println);
// Complete table cleaning
restaurant.completeTableCleaning(tableId);
RestaurantTable table = restaurant.getTable(tableId);
System.out.println("\nMasa statusu: " + table.getStatus());
// Display final order and bill status
System.out.println("\nYekun sifariş statusu: " + restaurant.getOrder(orderId).getStatus());
System.out.println("Hesab-faktura ödənilib: " + restaurant.getBill(billId).isPaid());
}
}
Thread Safety Considerations
- ReentrantLock: Hər masa, sifariş və inventar üçün ayrı lock-lar
- ConcurrentHashMap: Thread-safe məlumat strukturları
- Atomic Operations: Bütün kritik əməliyyatlar atomik şəkildə həyata keçirilir
- Synchronized State Updates: Sifariş və masa statusu dəyişiklikləri sinxronlaşdırılır
Design Patterns
- State Pattern: Masa və sifariş statuslarının idarə edilməsi
- Observer Pattern: Real-vaxtda status dəyişikliklərinin izlənməsi
- Strategy Pattern: Müxtəlif qiymətləndirmə və endirim strategiyaları
- Command Pattern: Menyu əməliyyatları və sifariş proseslərinin enkapsulasiyası
Business Logic
- Inventory Management: Inventar səviyyələrinin real-vaxtda izlənməsi
- Order Workflow: Sifariş həyat dövrünün tam idarəsi
- Table Management: Masa rezervasyonu və statusu idarəetməsi
- Billing System: Avtomatik hesab-faktura yaratma və ödəniş işləmə
Additional Features
- Multi-role Support: Müxtəlif istifadəçi rolları və icazələr
- Ingredient Tracking: Detallı inventar idarəetməsi
- Order Customization: Xüsusi təlimatlar və modifikasiyalar
- Financial Reporting: Satış və gəlir hesabatları