iT邦幫忙

2023 iThome 鐵人賽

DAY 28
0
Mobile Development

Spring Boot+Android 30天 實戰開發 系列 第 28

【Day - 28】建立餐廳後台點餐應用04:實作新增&管理訂單功能

  • 分享至 

  • xImage
  •  

今天我們將實作新增訂單訂單管理功能。這兩個功能對於餐廳後台管理系統來說非常重要,它們使得餐廳能夠輕鬆處理顧客的訂單,並保持訂單歷史記錄。接下來,我們將深入了解這些功能的實作。

功能概述

我們要實作的新增訂單和訂單管理功能包括以下幾點:

  1. 新增訂單
    • 提供員工手動輸入餐點的頁面。
    • 記錄顧客選擇的餐點、數量和總金額等訂單細節。
  2. 訂單管理
    • 提供查看歷史訂單資料的功能。
    • 根據訂單編號查看該訂單的詳細內容和明細。

Controller層

首先,我們來看Controller層的實作。這個層次負責處理Web頁面(Thymeleaf)的請求和處理API請求。以下是相關的程式碼:

@Controller
@RequestMapping("/orders")
@RequiredArgsConstructor
@Slf4j
public class DishOrderController {
    private final DishService dishService;
    private final OrderService orderService;

    // 顯示新增訂單頁面
    @GetMapping("/create")
    public String createOrder(Model model) {
        List<DishEntity> dishes = dishService.getAllDishes();
        model.addAttribute("dishes", dishes);
        return "create-order";
    }

    // 處理新增訂單的API請求
    @PostMapping("/place")
    public ResponseEntity<OrderResponse> placeOrder(@RequestBody List<OrderDetailsRequest> orderItems) {
        return ResponseEntity.ok(orderService.placeOrder(orderItems));
    }

    // 刪除訂單
    @GetMapping("/delete/{orderId}")
    public String deleteOrder(@PathVariable Long orderId) {
        orderService.deleteOrder(orderId);
        return "redirect:/orders";
    }

    // 顯示所有訂單
    @GetMapping()
    public String getAllOrders(Model model) {
        List<OrderEntity> orders = orderService.getAllOrders();
        model.addAttribute("orders", orders);
        return "orders";
    }

    // 顯示訂單詳細內容
    @GetMapping("/{orderId}")
    public String getOrderDetails(@PathVariable("orderId") Long orderId, Model model) {
        OrderEntity order = orderService.getOrderById(orderId);
        List<OrderDetailEntity> orderDetails = order.getOrderDetails();
        model.addAttribute("order", order);
        model.addAttribute("orderDetails", orderDetails);
        return "orders";
    }
}

Service層

接下來,我們將看一下Service層的實作,特別是OrderService。這個層次負責處理業務邏輯。以下是相關的程式碼:

  • OrderService
@Service
@RequiredArgsConstructor
public class OrderService {
    private final DishRepository dishRepository;
    private final OrderRepository orderRepository;

    // 新增訂單並返回訂單號碼
    public OrderResponse placeOrder(List<OrderDetailsRequest> orderItems) {
        // 創建訂單實體
        OrderEntity order = new OrderEntity();
        order.setDateTime(LocalDateTime.now());

        OrderEntity orderDB = orderRepository.save(order);

        int totalPrice = 0;
        int index = 0;
        for (OrderDetailsRequest item : orderItems) {
            var dish = dishRepository.findById(item.getDishId()).orElse(null);
            var subTotal = item.getPrice() * item.getCount();
            if (dish == null) continue;

            OrderDetailEntity orderDetail = new OrderDetailEntity();
            orderDetail.getId().setOrderId(orderDB.getId());
            orderDetail.getId().setDno(index);
            index += 1;
            orderDetail.setDish(dish);
            orderDetail.setCount(item.getCount());
            orderDetail.setTotal(subTotal);

            // 設定訂單項目關聯至訂單
            orderDB.addOrderDetail(orderDetail);

            totalPrice += subTotal;
        }

        orderDB.setTotalPrice(totalPrice);

        // 儲存訂單至資料庫
        orderRepository.save(orderDB);

        return OrderResponse.builder()
                    .orderId(orderDB.getId())
                    .build();
    }

    // 獲取所有訂單
    public List<OrderEntity> getAllOrders() {
        return orderRepository.findAll();
    }

    // 根據訂單ID獲取訂單
    public OrderEntity getOrderById(Long orderId) {
        return orderRepository.findById(orderId).orElse(null);
    }

    // 刪除訂單
    public void deleteOrder(Long orderId) {
        orderRepository.deleteById(orderId);
    }
}

Repository層

資料表(實體類)在第26天文章有詳細介紹和創建。
在Repository層,我們只需要簡單地繼承JpaRepository接口即可,這樣我們就可以擁有基本的資料庫操作。以下是相關的程式碼:

  • 訂單明細表的Repository
public interface OrderDetailRepository extends JpaRepository<OrderDetailEntity, Long> {
    // 只需繼承JpaRepository即可擁有基本操作
}
  • 訂單表的Repository
@Repository
public interface OrderRepository extends JpaRepository<OrderEntity, Long> {
    // 只需繼承JpaRepository即可擁有基本操作
}

View層

最後,我們來看一下View層,這裡包括了新增訂單頁面和訂單管理頁面的HTML Thymeleaf模板。

(1) 創建訂單之頁面

這是新增訂單的HTML模板,它包含了一個表單,員工可以在這個表單中選擇餐點並輸入訂購數量:
圖片無法顯示
訂單建立成功之提示
圖片無法顯示

  • 程式碼
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <title>Order</title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
  <script src="/order.js"></script>
</head>
<body>
<div class="container">

  <div th:insert="~{navbar}"></div>
  <div th:insert="~{create-order-dialog}"></div>
<!--  <div class="modal"></div>-->

  <div class="row">
    <div class="col-md-6">
      <h2>Menu</h2>
      <ul class="list-group">
        <li class="list-group-item" th:each="dish : ${dishes}">
          <div th:data-dish-id="${dish.id}">
            <span th:text="${dish.name}"></span> - $<span th:text="${dish.price}"></span>
          </div>
        </li>
      </ul>
    </div>

    <div class="col-md-6">
      <div class="row">
        <div class="col"><h2>Order Summary</h2></div>
        <div class="col">
          <button id="placeOrderBtn"
                  class="btn btn-primary" disabled="true">
            送出訂單
          </button>
        </div>
      </div>

      <ul class="list-group" id="orderSummary">
      </ul>

      <div class="row mt-3">
        <div class="col-md-6">
          <h4>Total:</h4>
        </div>
        <div class="col-md-6">
          <h4 id="totalAmount">$0.00</h4>
        </div>
      </div>
    </div>
  </div>
</div>
</body>
</html>

訂單管理之頁面

這是訂單管理的HTML模板,用於顯示所有訂單的列表,以及訂單的詳細內容:
圖片無法顯示

  • 程式碼
<!DOCTYPE html>
<html lang="zh-tw" xmlns:th="http://www.thymeleaf.org">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
  <title>Orders</title>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">

  <div th:insert="~{navbar}"></div>

  <h1>Orders</h1>
  <table class="table">
    <thead>
    <tr>
      <th>ID</th>
      <th>Order Date</th>
      <th>Total Amount</th>
      <th>Details</th>
    </tr>
    </thead>
    <tbody>
      <!-- Iterate over the list of orders -->
      <th:block th:each="order : ${orders}" class="card">
        <tr class="card-header">
          <td th:text="${order.id}"></td>
          <td th:text="${#temporals.format(order.dateTime, 'yyyy-MM-dd HH:mm:ss')}"></td>
          <td>$<span th:text="${order.totalPrice}"></span></td>
          <td>
            <button class="btn btn-primary" data-toggle="collapse"
                    th:data-target="'#order-details-' + ${order.id}">Details</button>
            <a class="btn btn-danger" th:href="@{/orders/delete/{orderId}(orderId=${order.id})}"><i class="bi bi-trash3"></i></a>
          </td>
        </tr>

        <!-- Add a hidden row for order details -->
        <tr class="collapse card-body" th:id="'order-details-' + ${order.id}">
          <td colspan="4">
            <!-- Render order details here -->
            <ul>
              <!-- Iterate over the order details -->
              <li th:each="detail : ${order.orderDetails}"
                  th:text="${detail.id.dno+1} + ' '+ ${detail.dish.name} + ' $' + ${detail.total/detail.count}  + 'x' + ${detail.count} + ' ...... $' + ${detail.total}"></li>
            </ul>
          </td>
        </tr>
      </th:block>
    </tbody>
  </table>
</div>
</body>
</html>

小結

在這篇文章中,我們成功實作了新增訂單和訂單管理功能。這些功能使得餐廳能夠有效地管理顧客的訂單並保持訂單歷史記錄。在明天的文章中,我們將繼續擴展我們的餐廳後台點餐應用,實作營業分析功能。敬請期待!
/images/emoticon/emoticon12.gif


上一篇
【Day - 27】建立餐廳後台點餐應用03:實作餐點管理功能
下一篇
【Day - 29】建立餐廳後台點餐應用05:結合Google Charts實作營業分析功能
系列文
Spring Boot+Android 30天 實戰開發 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言