一、引言
上一專題已經為網上書店實現了購物車的功能了,在這一專題中,將繼續對網上書店案例進行完善,本專題將對網上書店訂單功能的實現進行介紹,現在廢話不多說了,讓我們來一起看看訂單功能是如何實現的吧。
二、訂單功能的實現思路
在網上購過物的朋友,對於訂單功能的流程自然不陌生,這里我還是先來梳理下下訂單的一個流程:
- 用戶點擊我的購物車,可以勾選對應的商品進行結算
- 在結算頁面可以提交訂單來創建一個訂單
- 創建訂單成功之后就是進行付款了。
一般購物網站下訂單的流程分上面3步,由於在本案例中並沒有對接第三方的支付平台,所以這里就沒有上面第三步的過程了。即在網上書店案例中訂單提交成功之后就是已付款狀態。
從上面下訂單流程我們就可以知道訂單功能的實現思路:
- 用戶點擊購物車中購買商品按鈕來進行下訂單,此時觸發控制器中的結算方法進行調用
- 結算方法通過調用OrderService服務中的結算方法
- 由於訂單的創建涉及了3個實體操作,包括購物車實體,購物車項實體和訂單實體。所以這里需要引入領域服務。因為創建訂單這個操作涉及了多個實體,則這個業務邏輯放在每個實體中都不合適,因為並屬於單獨一個實體的邏輯。所以這里引入領域服務來實現這種涉及多個實體的操作。
- 則OrderService服務中的結算方法通過調用領域服務中的CreateOrder方法來完成訂單創建的功能。
- 領域服務中可以調用對應的實體倉儲來完成實體的持久化。這里需要注意的一點:因為領域服務涉及多個實體的持久化,則需要引入工作單元模式將這些實體的操作進行統一提交,要不都成功,要不都不成功。這也就是引入工作單元初衷。
上面的思路就是訂單功能的實現思路。有了上面的思路之后,實現訂單功能也一目了然了。下面讓我們一起在網上書店案例中實現下看看。
三、網上書店訂單功能的實現
這里我們按照上面的實現思路由下至上地去實現訂單功能。
- 首先我們需要訂單倉儲來完成訂單實體的持久化。具體訂單倉儲接口和實現如下代碼所示:
// 訂單倉儲接口 public interface IOrderRepository : IRepository<Order> { } // 訂單倉儲的實現類 public class OrderRepository : EntityFrameworkRepository<Order>, IOrderRepository { public OrderRepository(IRepositoryContext context) : base(context) { } }
2. 領域服務的實現。具體的領域服務接口和實現代碼如下所示:
// 領域服務接口 public interface IDomainService { Order CreateOrder(User user, ShoppingCart shoppingCart); } // 領域服務類型 // 牽涉到多個實體的操作可以把這些操作封裝到領域服務里 public class DomainService : IDomainService { private readonly IRepositoryContext _repositoryContext; private readonly IShoppingCartItemRepository _shoppingCartItemRepository; private readonly IOrderRepository _orderRepository; /// <summary> /// 創建訂單,涉及到的操作有2個:1. 把購物車中的項中購物車移除; 2.創建一個訂單。 /// 這兩個操作必須同時完成或失敗。 /// </summary> /// <param name="user"></param> /// <param name="shoppingCart"></param> /// <returns></returns> public Order CreateOrder(User user, ShoppingCart shoppingCart) { var order = new Order(); var shoppingCartItems = _shoppingCartItemRepository.GetAll( new ExpressionSpecification<ShoppingCartItem>(s => s.ShoopingCart.Id == shoppingCart.Id)); if (shoppingCartItems == null || !shoppingCartItems.Any()) throw new InvalidOperationException("購物籃中沒有任何物品"); order.OrderItems = new List<OrderItem>(); foreach (var shoppingCartItem in shoppingCartItems) { var orderItem = shoppingCartItem.ConvertToOrderItem(); orderItem.Order = order; order.OrderItems.Add(orderItem); _shoppingCartItemRepository.Remove(shoppingCartItem); } order.User = user; order.Status = OrderStatus.Paid; _orderRepository.Add(order); _repositoryContext.Commit(); return order; } }
3. 訂單服務的實現。具體訂單服務實現代碼如下所示:
public class OrderServiceImp : ApplicationService, IOrderService { #region Private Fileds private readonly IShoppingCartRepository _shoppingCartRepository; private readonly IShoppingCartItemRepository _shoppingCartItemRepository; private readonly IUserRepository _userRepository; private readonly IOrderRepository _orderRepository; private readonly IProductRepository _productRepository; private readonly IDomainService _domainService; private readonly IEventBus _eventBus; #endregion #region Ctor public OrderServiceImp(IRepositoryContext context, IUserRepository userRepository, IShoppingCartRepository shoppingCartRepository, IProductRepository productRepository, IShoppingCartItemRepository shoppingCartItemRepository, IDomainService domainService, IOrderRepository orderRepository, IEventBus eventBus) : base(context) { _userRepository = userRepository; _shoppingCartRepository = shoppingCartRepository; _productRepository = productRepository; _shoppingCartItemRepository = shoppingCartItemRepository; _domainService = domainService; _orderRepository = orderRepository; _eventBus = eventBus; } #endregion public OrderDto Checkout(Guid customerId) { var user = _userRepository.GetByKey(customerId); var shoppingCart = _shoppingCartRepository.GetByExpression(s => s.User.Id == user.Id); var order = _domainService.CreateOrder(user, shoppingCart); return Mapper.Map<Order, OrderDto>(order); } public OrderDto GetOrder(Guid orderId) { var order = _orderRepository.GetBySpecification(new ExpressionSpecification<Order>(o=>o.Id.Equals(orderId)), elp=>elp.OrderItems); return Mapper.Map<Order, OrderDto>(order); } // 獲得指定用戶的所有訂單 public IList<OrderDto> GetOrdersForUser(Guid userId) { var user = _userRepository.GetByKey(userId); var orders = _orderRepository.GetAll(new ExpressionSpecification<Order>(o => o.User.Id == userId), sp => sp.CreatedDate, SortOrder.Descending, elp=>elp.OrderItems); var orderDtos = new List<OrderDto>(); orders .ToList() .ForEach(o=>orderDtos.Add(Mapper.Map<Order, OrderDto>(o))); return orderDtos; }
4. HomeController控制器中Checkout操作的實現。具體實現代碼如下所示:
public class HomeController : ControllerBase { /// <summary> /// 結算操作 /// </summary> /// <returns></returns> [Authorize] public ActionResult Checkout() { using (var proxy = new OrderServiceClient()) { var model = proxy.Checkout(this.UserId); return View(model); } } [Authorize] public ActionResult Orders() { using (var proxy = new OrderServiceClient()) { var model = proxy.GetOrdersForUser(this.UserId); return View(model); } } [Authorize] public ActionResult Order(string id) { using (var proxy = new OrderServiceClient()) { var model = proxy.GetOrder(new Guid(id)); return View(model); } } }
這樣我們就在網上書店中實現了訂單功能了。具體的視圖界面也就是上一專題中實現的購物車頁面。下面具體看看訂單的具體實現效果:
結算頁面:
點擊確認購買按鈕,在彈出框中點擊確認來完成訂單的創建:
通過我的訂單來查看所有訂單頁面:
四、總結
到此,網上書店案例的訂單功能的實現就完成了,在接下來的專題將繼續對該案例進行完善,在下一專題中將為該案例引入后台管理操作。商家或管理員可以進入后台管理來對用戶訂單進行確認發貨,以及添加商品,分類等操作。具體實現請見下一專題。
本專題中所有實現源碼下載:https://github.com/lizhi5753186/OnlineStore_Second/