标签 标签 标签

  • 一句话的事儿:

一、引言

  上一专题已经为网上书店实现了购物车的功能了,在这一专题中,将继续对网上书店案例进行完善,本专题将对网上书店订单功能的实现进行介绍,现在废话不多说了,让我们来一起看看订单功能是如何实现的吧。

二、订单功能的实现思路

  在网上购过物的朋友,对于订单功能的流程自然不陌生,这里我还是先来梳理下下订单的一个流程:

  • 用户点击我的购物车,可以勾选对应的商品进行结算
  • 在结算页面可以提交订单来创建一个订单
  • 创建订单成功之后就是进行付款了。

  一般购物网站下订单的流程分上面3步,由于在本案例中并没有对接第三方的支付平台,所以这里就没有上面第三步的过程了。即在网上书店案例中订单提交成功之后就是已付款状态。
  从上面下订单流程我们就可以知道订单功能的实现思路:

  • 用户点击购物车中购买商品按钮来进行下订单,此时触发控制器中的结算方法进行调用
  • 结算方法通过调用OrderService服务中的结算方法
  • 由于订单的创建涉及了3个实体操作,包括购物车实体,购物车项实体和订单实体。所以这里需要引入领域服务。因为创建订单这个操作涉及了多个实体,则这个业务逻辑放在每个实体中都不合适,因为并属于单独一个实体的逻辑。所以这里引入领域服务来实现这种涉及多个实体的操作。
  • 则OrderService服务中的结算方法通过调用领域服务中的CreateOrder方法来完成订单创建的功能。
  • 领域服务中可以调用对应的实体仓储来完成实体的持久化。这里需要注意的一点:因为领域服务涉及多个实体的持久化,则需要引入工作单元模式将这些实体的操作进行统一提交,要不都成功,要不都不成功。这也就是引入工作单元初衷。

  上面的思路就是订单功能的实现思路。有了上面的思路之后,实现订单功能也一目了然了。下面让我们一起在网上书店案例中实现下看看。

三、网上书店订单功能的实现

  这里我们按照上面的实现思路由下至上地去实现订单功能。

  1. 首先我们需要订单仓储来完成订单实体的持久化。具体订单仓储接口和实现如下代码所示:
    1. // 订单仓储接口
    2. public interface IOrderRepository : IRepository<Order>
    3. {
    4. }
    5. // 订单仓储的实现类
    6. public class OrderRepository : EntityFrameworkRepository<Order>, IOrderRepository
    7. {
    8. public OrderRepository(IRepositoryContext context) : base(context)
    9. {
    10. }
    11. }
      2. 领域服务的实现。具体的领域服务接口和实现代码如下所示: ```csharp // 领域服务接口 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;

  1. /// <summary>
  2. /// 创建订单,涉及到的操作有2个:1. 把购物车中的项中购物车移除; 2.创建一个订单。
  3. /// 这两个操作必须同时完成或失败。
  4. /// </summary>
  5. /// <param name="user"></param>
  6. /// <param name="shoppingCart"></param>
  7. /// <returns></returns>
  8. public Order CreateOrder(User user, ShoppingCart shoppingCart)
  9. {
  10. var order = new Order();
  11. var shoppingCartItems =
  12. _shoppingCartItemRepository.GetAll(
  13. new ExpressionSpecification<ShoppingCartItem>(s => s.ShoopingCart.Id == shoppingCart.Id));
  14. if (shoppingCartItems == null || !shoppingCartItems.Any())
  15. throw new InvalidOperationException("购物篮中没有任何物品");
  16. order.OrderItems = new List<OrderItem>();
  17. foreach (var shoppingCartItem in shoppingCartItems)
  18. {
  19. var orderItem = shoppingCartItem.ConvertToOrderItem();
  20. orderItem.Order = order;
  21. order.OrderItems.Add(orderItem);
  22. _shoppingCartItemRepository.Remove(shoppingCartItem);
  23. }
  24. order.User = user;
  25. order.Status = OrderStatus.Paid;
  26. _orderRepository.Add(order);
  27. _repositoryContext.Commit();
  28. return order;
  29. }

}

  1.   3. 订单服务的实现。具体订单服务实现代码如下所示:
  2. ```csharp
  3. public class OrderServiceImp : ApplicationService, IOrderService
  4. {
  5. #region Private Fileds
  6. private readonly IShoppingCartRepository _shoppingCartRepository;
  7. private readonly IShoppingCartItemRepository _shoppingCartItemRepository;
  8. private readonly IUserRepository _userRepository;
  9. private readonly IOrderRepository _orderRepository;
  10. private readonly IProductRepository _productRepository;
  11. private readonly IDomainService _domainService;
  12. private readonly IEventBus _eventBus;
  13. #endregion
  14. #region Ctor
  15. public OrderServiceImp(IRepositoryContext context,
  16. IUserRepository userRepository,
  17. IShoppingCartRepository shoppingCartRepository,
  18. IProductRepository productRepository,
  19. IShoppingCartItemRepository shoppingCartItemRepository,
  20. IDomainService domainService,
  21. IOrderRepository orderRepository,
  22. IEventBus eventBus) : base(context)
  23. {
  24. _userRepository = userRepository;
  25. _shoppingCartRepository = shoppingCartRepository;
  26. _productRepository = productRepository;
  27. _shoppingCartItemRepository = shoppingCartItemRepository;
  28. _domainService = domainService;
  29. _orderRepository = orderRepository;
  30. _eventBus = eventBus;
  31. }
  32. #endregion
  33. public OrderDto Checkout(Guid customerId)
  34. {
  35. var user = _userRepository.GetByKey(customerId);
  36. var shoppingCart = _shoppingCartRepository.GetByExpression(s => s.User.Id == user.Id);
  37. var order = _domainService.CreateOrder(user, shoppingCart);
  38. return Mapper.Map<Order, OrderDto>(order);
  39. }
  40. public OrderDto GetOrder(Guid orderId)
  41. {
  42. var order = _orderRepository.GetBySpecification(new ExpressionSpecification<Order>(o=>o.Id.Equals(orderId)), elp=>elp.OrderItems);
  43. return Mapper.Map<Order, OrderDto>(order);
  44. }
  45. // 获得指定用户的所有订单
  46. public IList<OrderDto> GetOrdersForUser(Guid userId)
  47. {
  48. var user = _userRepository.GetByKey(userId);
  49. var orders = _orderRepository.GetAll(new ExpressionSpecification<Order>(o => o.User.Id == userId), sp => sp.CreatedDate, SortOrder.Descending, elp=>elp.OrderItems);
  50. var orderDtos = new List<OrderDto>();
  51. orders
  52. .ToList()
  53. .ForEach(o=>orderDtos.Add(Mapper.Map<Order, OrderDto>(o)));
  54. return orderDtos;
  55. }
  56. }

  4. HomeController控制器中Checkout操作的实现。具体实现代码如下所示:

  1. public class HomeController : ControllerBase
  2. {
  3. /// <summary>
  4. /// 结算操作
  5. /// </summary>
  6. /// <returns></returns>
  7. [Authorize]
  8. public ActionResult Checkout()
  9. {
  10. using (var proxy = new OrderServiceClient())
  11. {
  12. var model = proxy.Checkout(this.UserId);
  13. return View(model);
  14. }
  15. }
  16. [Authorize]
  17. public ActionResult Orders()
  18. {
  19. using (var proxy = new OrderServiceClient())
  20. {
  21. var model = proxy.GetOrdersForUser(this.UserId);
  22. return View(model);
  23. }
  24. }
  25. [Authorize]
  26. public ActionResult Order(string id)
  27. {
  28. using (var proxy = new OrderServiceClient())
  29. {
  30. var model = proxy.GetOrder(new Guid(id));
  31. return View(model);
  32. }
  33. }
  34. }

  这样我们就在网上书店中实现了订单功能了。具体的视图界面也就是上一专题中实现的购物车页面。下面具体看看订单的具体实现效果:
  结算页面:
专题六:DDD实践案例:网上书店订单功能的实现 - 图1
  点击确认购买按钮,在弹出框中点击确认来完成订单的创建:
专题六:DDD实践案例:网上书店订单功能的实现 - 图2
  通过我的订单来查看所有订单页面:
专题六:DDD实践案例:网上书店订单功能的实现 - 图3

四、总结

  到此,网上书店案例的订单功能的实现就完成了,在接下来的专题将继续对该案例进行完善,在下一专题中将为该案例引入后台管理操作。商家或管理员可以进入后台管理来对用户订单进行确认发货,以及添加商品,分类等操作。具体实现请见下一专题。
  本专题中所有实现源码下载:https://github.com/lizhi5753186/OnlineStore_Second/


  • 本文作者:GeekPower - Felix Sun
  • 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!