iT邦幫忙

2024 iThome 鐵人賽

DAY 30
0

https://ithelp.ithome.com.tw/upload/images/20241002/20147438cM8d9nAyZQ.jpg

  • Utility/SD新增
  • 等待店家確認訂單 -> 店家確認後改為訂單準備中 -> 店家準備完成後改為訂單完成、可取貨-> 使用者取貨後改為訂單完成
public const string StatusPending = "Pending"; // 等待店家確認訂單
public const string StatusInProcess = "Processing"; // 店家確認後改為訂單準備中
public const string StatusCancelled = "Cancelled"; // 店家或顧客取消訂單
public const string StatusReady = "Ready"; // 店家準備完成,顧客可以取貨
public const string StatusCompleted = "Completed"; // 顧客取貨及付款後,店家結束訂單
  • 訂單過程寫進資料庫
[HttpPost]
[ActionName("Summary")]
public IActionResult SummaryPOST(ShoppingCartVM shoppingCartVM)
{
    var claimsIdentity = (ClaimsIdentity)User.Identity;
    var userId = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier).Value;
    ShoppingCartVM.ShoppingCartList = _unitOfWork.ShoppingCart.GetAll(u => u.ApplicationUserId == userId, includeProperties: "Product");
    ShoppingCartVM.OrderHeader.OrderDate = System.DateTime.Now;
    ShoppingCartVM.OrderHeader.ApplicationUserId = userId;
    ShoppingCartVM.OrderHeader.ApplicationUser = _unitOfWork.ApplicationUser.Get(u => u.Id == userId);
    foreach (var cart in ShoppingCartVM.ShoppingCartList)
    {
        ShoppingCartVM.OrderHeader.OrderTotal += (cart.Product.Price * cart.Count);
    }
    _unitOfWork.OrderHeader.Add(ShoppingCartVM.OrderHeader);
    _unitOfWork.Save();

    foreach (var cart in ShoppingCartVM.ShoppingCartList)
    {
        OrderDetail orderDetail = new()
        {
            ProductId = cart.ProductId,
            OrderHeaderId = ShoppingCartVM.OrderHeader.Id,
            Color = cart.Color,
            Size = cart.Size,
            Price = cart.Product.Price,
            Count = cart.Count
        };
        _unitOfWork.OrderDetail.Add(orderDetail);
        _unitOfWork.Save();
    }
    return RedirectToAction(nameof(OrderConfirmation), new { id = ShoppingCartVM.OrderHeader.Id }); 
}

public IActionResult OrderConfirmation(int id)
{
OrderHeader orderHeader = _unitOfWork.OrderHeader.Get(u => u.Id == id, includeProperties: "ApplicationUser");
_unitOfWork.OrderHeader.UpdateStatus(id, SD.StatusPending);

List<ShoppingCart> shoppingCarts = _unitOfWork.ShoppingCart.GetAll(u => u.ApplicationUserId == orderHeader.ApplicationUserId).ToList();
_unitOfWork.ShoppingCart.RemoveRange(shoppingCarts);
_unitOfWork.Save();

return View(id);
}

  • 新增Order確認View
    • 對OrderConfirmation右鍵新增View
@model int

<div class="container row pt-4">
    <div class="col-12 text-center">
        <h1 class="text-primary text-center">訂單送出成功</h1>
        您的訂單編號為 : @Model <br /><br />
    </div>
    <div class="col-12 text-center" style="color:maroon">
        <br />
        您的訂單已成功下達! <br />
        
    </div>
</div> 

https://ithelp.ithome.com.tw/upload/images/20241002/20147438rLw8k74oqG.png

  • 修改訂單狀態
    • IOrderHeaderRepository新增:
 void UpdateStatus(int id, string orderStatus, string? paymentStatus = null);

https://ithelp.ithome.com.tw/upload/images/20241002/20147438lWxXXzOgE6.png

  • OrderHeaderRepository的Update下方新增:
public void UpdateStatus(int id, string orderStatus, string? paymentStatus = null)
 {
     var orderFromDb = _db.OrderHeaders.FirstOrDefault(u => u.Id == id);
     if (orderFromDb != null)
     {
         orderFromDb.OrderStatus = orderStatus;
         if (!string.IsNullOrEmpty(paymentStatus))
         {
             orderFromDb.PaymentStatus = paymentStatus;
         }
     }
 }
  • 訂單管理
    • Admin新增OrderController
    • 設定管理者與員工可以看到所有訂單,其餘人只能看到自己的訂單
 [Area("Admin")]
    [Authorize]
    public class OrderController : Controller
    {
        private readonly IUnitOfWork _unitOfWork;
        [BindProperty]
        public OrderVM OrderVM { get; set; }
        public OrderController(IUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }
        public IActionResult Index(string status)
        {
            IEnumerable<OrderHeader> objOrderHeaders;

            if (User.IsInRole(SD.Role_Admin) || User.IsInRole(SD.Role_Employee) || User.IsInRole(SD.Role_Manager))
            {
                objOrderHeaders = _unitOfWork.OrderHeader.GetAll(includeProperties: "ApplicationUser").ToList();
            }
            else
            {
                var claimsIdentity = (ClaimsIdentity)User.Identity;
                var userId = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier).Value;
                objOrderHeaders = _unitOfWork.OrderHeader
                    .GetAll(u => u.ApplicationUserId == userId, includeProperties: "ApplicationUser");
            }
            switch (status)
            {
                case "Pending":
                    objOrderHeaders = objOrderHeaders.Where(u => u.OrderStatus == SD.StatusPending);
                    break;
                case "Processing":
                    objOrderHeaders = objOrderHeaders.Where(u => u.OrderStatus == SD.StatusInProcess);
                    break;
                case "Ready":
                    objOrderHeaders = objOrderHeaders.Where(u => u.OrderStatus == SD.StatusReady);
                    break;
                case "Completed":
                    objOrderHeaders = objOrderHeaders.Where(u => u.OrderStatus == SD.StatusCompleted);
                    break;
                default:
                    break;
            }
            return View(objOrderHeaders);
        }
    }

https://ithelp.ithome.com.tw/upload/images/20241002/201474386iW77qoygG.jpg

  • 製作Order的ViewModel
 public class OrderVM
    {
        public OrderHeader OrderHeader { get; set; }
        public IEnumerable<OrderDetail> OrderDetail { get; set; }
    }

https://ithelp.ithome.com.tw/upload/images/20241002/201474383Ehd6dVL2u.png


  • 新增Order Index View
@model IEnumerable<ClothShop.Models.OrderHeader>
@{
    var status = Context.Request.Query["status"];
    var pending = "text-primary";
    var processing = "text-primary";
    var ready = "text-primary";
    var completed = "text-primary";
    var all = "text-primary";

    switch (status)
    {
        case "Pending":
            pending = "active text-white";
            break;
        case "Processing":
            processing = "active text-white";
            break;
        case "Ready":
            ready = "active text-white";
            break;
        case "Completed":
            completed = "active text-white";
            break;
        default:
            all = "active text-white";
            break;
    }
}

<div class="p-3">
    <div class="d-flex justify-content-between pt-4">
        <div class="pt-2">
            <h2 class="text-primary">訂單清單 Order List</h2>
        </div>
        <div class="p-2">
            <ul class="list-group list-group-horizontal-sm">
                <a style="text-decoration:none;" asp-controller="Order"
                   asp-action="Index" asp-route-status="Pending">
                <li class="list-group-item" @pending>等待確認訂單</li>
                </a>
                <a style="text-decoration:none;" asp-controller="Order"
                   asp-action="Index" asp-route-status="Processing">
                <li class="list-group-item" @processing>訂單準備中</li>
                </a>
                <a style="text-decoration:none;" asp-controller="Order"
                   asp-action="Index" asp-route-status="Ready">
                <li class="list-group-item" @ready>可取貨</li>
                </a>
                <a style="text-decoration:none;" asp-controller="Order"
                   asp-action="Index" asp-route-status="Completed">
                <li class="list-group-item" @completed>已完成</li>
                </a>
                <a style="text-decoration:none;" asp-controller="Order"
                   asp-action="Index" asp-route-status="all">
                <li class="list-group-item" @all>全部訂單</li>
                </a>
            </ul>
        </div>
    </div>
    <table id="tblData" class="table table-bordered table-striped" style="width:100%">
        <thead>
            <tr class="align-middle">
                <th>訂單編號</th>
                <th>姓名</th>
                <th>電話號碼</th>
                <th>信箱</th>
                <th>訂單狀態</th>
                <th>總計金額</th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model)
            {
                <tr>
                    <td>@Html.DisplayFor(modelItem => item.Id)</td>
                    <td>@Html.DisplayFor(modelItem => item.Name)</td>
                    <td>@Html.DisplayFor(modelItem => item.PhoneNumber)</td>
                    <td>@Html.DisplayFor(modelItem => item.ApplicationUser.Email)</td>
                    <td>@Html.DisplayFor(modelItem => item.OrderStatus)</td>
                    <td>@Html.DisplayFor(modelItem => item.OrderTotal)</td>
                    <td>
                        <div class="w-75 btn-group" role="group">
                            <a href="/admin/order/details?orderId=${data}" class="btn btn-primary mx-2"> Edit</a>
                        </div>
                    </td>
                </tr>
            }
        </tbody>
    </table>
</div>
@section Scripts {

}

https://ithelp.ithome.com.tw/upload/images/20241002/20147438pdQR7yGcrJ.jpg

  • 修改_Layout
 <li class="nav-item">
<a class="nav-link text-dark" asp-area="Admin" asp-controller="Order" asp-action="Index">訂單</a>
</li>
  • 訂單詳細資訊
public IActionResult Details(int orderId)
        {
            OrderVM = new OrderVM
            {
         OrderHeader = _unitOfWork.OrderHeader.Get(u => u.Id == orderId, includeProperties: "ApplicationUser"),
         OrderDetail = _unitOfWork.OrderDetail.GetAll(u => u.OrderHeaderId == orderId, includeProperties: "Product")
            };
            return View(OrderVM);
        }
 [HttpPost]
        [Authorize(Roles = SD.Role_Admin + "," + SD.Role_Employee + "," + SD.Role_Manager)]
        public IActionResult UpdateOrderDetail()
        {
            var orderHeaderFromDb = _unitOfWork.OrderHeader.Get(u => u.Id == OrderVM.OrderHeader.Id);
            orderHeaderFromDb.Name = OrderVM.OrderHeader.Name;
            orderHeaderFromDb.PhoneNumber = OrderVM.OrderHeader.PhoneNumber;
            orderHeaderFromDb.Address = OrderVM.OrderHeader.Address;

            _unitOfWork.OrderHeader.Update(orderHeaderFromDb);
            _unitOfWork.Save();
            return RedirectToAction(nameof(Details), new { orderId = orderHeaderFromDb.Id });
        }
  • 新增Details View
@model OrderVM
@using ClothShop.Utility

<form method="post">
    <input asp-for="OrderHeader.Id" hidden />
    <br />
    <div class="container">
        <div class="card">
            <div class="card-header bg-dark text-light ml-0">
                <div class="container row">
                    <div class="col-12 d-none d-md-block col-md-6 p-2">
                        <i class="fas fa-shopping-cart"></i> &nbsp; 訂單總計 Order Summary
                    </div>
                    <div class="col-12 col-md-4 offset-md-2 text-right p-2">
                        <a asp-action="Index" class="btn btn-outline-info form-control btn-sm">回訂單列 Back to Orders</a>
                    </div>
                </div>
            </div>
            <div class="card-body">
                <div class="container rounded p-2">
                    <div class="row">
                        <div class="col-12 col-lg-6 pb-4">
                            <div class="row">
                                <h4 class="d-flex justify-content-between align-items-center mb-3">
                                    <span class="text-primary">訂購人資訊 PickUp Details:</span>
                                </h4>
                            </div>
                            <div class="row my-1">
                                <div class="col-4">姓名 Name</div>
                                <div class="col-8">
                                    @if (User.IsInRole(SD.Role_Admin) || User.IsInRole(SD.Role_Employee) || User.IsInRole(SD.Role_Manager))
                                    {
                                        <input asp-for="OrderHeader.Name" type="text" class="form-control" />
                                        <span asp-validation-for="OrderHeader.Name" class="text-danger"></span>
                                    }
                                    else
                                    {
                                        <input asp-for="OrderHeader.Name" readonly type="text" class="form-control" />
                                    }
                                </div>
                            </div>
                            <div class="row my-1">
                                <div class="col-4">手機 Phone</div>
                                <div class="col-8">
                                    @if (User.IsInRole(SD.Role_Admin) || User.IsInRole(SD.Role_Employee) || User.IsInRole(SD.Role_Manager))
                                    {
                                        <input asp-for="OrderHeader.PhoneNumber" type="text" class="form-control" />
                                        <span asp-validation-for="OrderHeader.PhoneNumber" class="text-danger"></span>
                                    }
                                    else
                                    {
                                        <input asp-for="OrderHeader.PhoneNumber" readonly type="text" class="form-control" />
                                    }
                                </div>
                            </div>
                            <div class="row my-1">
                                <div class="col-4">地址 Address</div>
                                <div class="col-8">
                                    @if (User.IsInRole(SD.Role_Admin) || User.IsInRole(SD.Role_Employee) || User.IsInRole(SD.Role_Manager))
                                    {
                                        <input asp-for="OrderHeader.Address" type="text" class="form-control" />
                                        <span asp-validation-for="OrderHeader.Address" class="text-danger"></span>
                                    }
                                    else
                                    {
                                        <input asp-for="OrderHeader.Address" readonly type="text" class="form-control" />
                                    }
                                </div>
                            </div>

                            <div class="row my-1">
                                <div class="col-4">信箱 Email</div>
                                <div class="col-8">
                                    <input asp-for="OrderHeader.ApplicationUser.Email" readonly type="text" class="form-control" />
                                </div>
                            </div>
                            <div class="row my-1">
                                <div class="col-4">訂購日期 Order Date</div>
                                <div class="col-8">
                                    <input value="@Model.OrderHeader.OrderDate.ToShortDateString()" type="text" class="form-control" readonly />
                                </div>
                            </div>
                            @if (User.IsInRole(SD.Role_Admin) || User.IsInRole(SD.Role_Employee) || User.IsInRole(SD.Role_Manager))
                            {
                                <button type="submit" asp-action="UpdateOrderDetail" class="btn btn-warning form-control my-1">修改訂單資訊 Update Order Details</button>
                            }
                        </div>
                        <div class="col-12 col-lg-5 offset-lg-1">
                            <h4 class="d-flex justify-content-between align-items-center mb-3">
                                <span class="text-primary">訂購內容 Order Summary</span>
                            </h4>
                            <label class="btn btn-outline-primary form-control my-2">訂單狀態 Order Status - @Model.OrderHeader.OrderStatus</label>

                            <ul class="list-group mb-3">
                                @foreach (var detail in Model.OrderDetail)
                                {
                                    <li class="list-group-item d-flex justify-content-between p-2">
                                        <div class="row container">
                                            <div class="col-8">

                                                <h6 class="my-0 text-primary">@detail.Product.Name</h6>
                                                <small class="text-muted">價格:@detail.Price.ToString("c")</small><br />
                                                <small class="text-muted">數量:@detail.Count</small><br />
                                                <small class="text-muted">顏色:@detail.Color</small><br />
                                                <small class="text-muted">尺寸:@detail.Size</small>
                                            </div>
                                            <div class="col-4">
                                                <p class="text-success"> @((detail.Count * detail.Price).ToString("c"))</p>
                                            </div>
                                        </div>
                                    </li>
                                }
                                <li class="list-group-item bg-info">
                                    <div class="row container">
                                        <div class="col-6 text-center">
                                            <h5 class="text-white">總計 TOTAL </h5>
                                        </div>
                                        <div class="col-6 text-center">
                                            <h5 class="text-white">@Model.OrderHeader.OrderTotal.ToString("c")</h5>
                                        </div>
                                    </div>
                                </li>
                            </ul>
                            @if (User.IsInRole(SD.Role_Admin) || User.IsInRole(SD.Role_Employee) || User.IsInRole(SD.Role_Manager))
                            {
                                @if (Model.OrderHeader.OrderStatus == SD.StatusPending)
                                {
                                    <button type="submit" asp-action="StartProcessing" class="btn btn-primary form-control my-1">接受訂單</button>
                                }
                                @if (Model.OrderHeader.OrderStatus == SD.StatusInProcess)
                                {
                                    <button type="submit" asp-action="OrderReady" class="btn btn-primary form-control my-1">製作完成(通知顧客取貨)</button>
                                }
                                @if (Model.OrderHeader.OrderStatus == SD.StatusReady)
                                {
                                    <button type="submit" asp-action="OrderCompleted" class="btn btn-success form-control my-1">確認付款(訂單完成)</button>
                                }
                                @if (Model.OrderHeader.OrderStatus != SD.StatusCompleted && Model.OrderHeader.OrderStatus != SD.StatusCancelled)
                                {
                                    <button type="submit" asp-action="CancelOrder" class="btn btn-danger form-control my-1">取消訂單</button>
                                }
                            }
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</form>
@section Scripts {
    <partial name="_ValidationScriptsPartial" />
}

https://ithelp.ithome.com.tw/upload/images/20241002/20147438tzk0XfQwy1.jpg


  • OrderController 新增接收訂單 / 準備完成 / 訂單完成 / 訂單取消 (四個)Action
 [HttpPost]
        [Authorize(Roles = SD.Role_Admin + "," + SD.Role_Employee + "," + SD.Role_Manager)]
        public IActionResult StartProcessing()
        {
            _unitOfWork.OrderHeader.UpdateStatus(OrderVM.OrderHeader.Id, SD.StatusInProcess);
            _unitOfWork.Save();
             return RedirectToAction(nameof(Details), new { orderId = OrderVM.OrderHeader.Id });
        }
 [HttpPost]
        [Authorize(Roles = SD.Role_Admin + "," + SD.Role_Employee + "," + SD.Role_Manager)]
        public IActionResult OrderReady()
        {
            _unitOfWork.OrderHeader.UpdateStatus(OrderVM.OrderHeader.Id, SD.StatusReady);
            _unitOfWork.Save();
            return RedirectToAction(nameof(Details), new { orderId = OrderVM.OrderHeader.Id });
        }
 [HttpPost]
        [Authorize(Roles = SD.Role_Admin + "," + SD.Role_Employee + "," + SD.Role_Manager)]
        public IActionResult OrderCompleted()
        {
            _unitOfWork.OrderHeader.UpdateStatus(OrderVM.OrderHeader.Id, SD.StatusCompleted);
            _unitOfWork.Save();
            return RedirectToAction(nameof(Details), new { orderId = OrderVM.OrderHeader.Id });
        }
 [HttpPost]
        [Authorize(Roles = SD.Role_Admin + "," + SD.Role_Employee + "," + SD.Role_Manager)]
        public IActionResult CancelOrder()
        {
            _unitOfWork.OrderHeader.UpdateStatus(OrderVM.OrderHeader.Id, SD.StatusCancelled);
            _unitOfWork.Save();
             return RedirectToAction(nameof(Details), new { orderId = OrderVM.OrderHeader.Id });
        }

上一篇
Day29 合併購物車金額與訂單
系列文
asp.net core 分層架構快速上手31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言