[.NET領域驅動設計實戰系列]專題六:DDD實踐案例:網上書店訂單功能的實現


一、引言

   上一專題已經為網上書店實現了購物車的功能了,在這一專題中,將繼續對網上書店案例進行完善,本專題將對網上書店訂單功能的實現進行介紹,現在廢話不多說了,讓我們來一起看看訂單功能是如何實現的吧。

二、訂單功能的實現思路

   在網上購過物的朋友,對於訂單功能的流程自然不陌生,這里我還是先來梳理下下訂單的一個流程:

  • 用戶點擊我的購物車,可以勾選對應的商品進行結算
  • 在結算頁面可以提交訂單來創建一個訂單
  • 創建訂單成功之后就是進行付款了。

  一般購物網站下訂單的流程分上面3步,由於在本案例中並沒有對接第三方的支付平台,所以這里就沒有上面第三步的過程了。即在網上書店案例中訂單提交成功之后就是已付款狀態。

  從上面下訂單流程我們就可以知道訂單功能的實現思路:

  • 用戶點擊購物車中購買商品按鈕來進行下訂單,此時觸發控制器中的結算方法進行調用
  • 結算方法通過調用OrderService服務中的結算方法
  • 由於訂單的創建涉及了3個實體操作,包括購物車實體,購物車項實體和訂單實體。所以這里需要引入領域服務。因為創建訂單這個操作涉及了多個實體,則這個業務邏輯放在每個實體中都不合適,因為並屬於單獨一個實體的邏輯。所以這里引入領域服務來實現這種涉及多個實體的操作。
  • 則OrderService服務中的結算方法通過調用領域服務中的CreateOrder方法來完成訂單創建的功能。
  • 領域服務中可以調用對應的實體倉儲來完成實體的持久化。這里需要注意的一點:因為領域服務涉及多個實體的持久化,則需要引入工作單元模式將這些實體的操作進行統一提交,要不都成功,要不都不成功。這也就是引入工作單元初衷。

  上面的思路就是訂單功能的實現思路。有了上面的思路之后,實現訂單功能也一目了然了。下面讓我們一起在網上書店案例中實現下看看。

三、網上書店訂單功能的實現

   這里我們按照上面的實現思路由下至上地去實現訂單功能。

  1. 首先我們需要訂單倉儲來完成訂單實體的持久化。具體訂單倉儲接口和實現如下代碼所示:
// 訂單倉儲接口
    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/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM