using System; using System.Linq; using System.Threading.Tasks; using Ardalis.GuardClauses; using Microsoft.eShopWeb.ApplicationCore.Entities; using Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate; using Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate; using Microsoft.eShopWeb.ApplicationCore.Interfaces; using Microsoft.eShopWeb.ApplicationCore.Specifications; namespace Microsoft.eShopWeb.ApplicationCore.Services; public class OrderService : IOrderService { private readonly IRepository<Order> _orderRepository; private readonly IRepository<Basket> _basketRepository; private readonly IRepository<CatalogItem> _itemRepository; private readonly IUriComposer _uriComposer; public OrderService(IRepository<Basket> basketRepository, IRepository<CatalogItem> itemRepository, IRepository<Order> orderRepository, IUriComposer uriComposer) { _orderRepository = orderRepository; _uriComposer = uriComposer; _basketRepository = basketRepository; _itemRepository = itemRepository; } public async Task<Order> CreateOrderAsync(int basketId, Address shippingAddress) { var basket = await _basketRepository.GetByIdAsync(basketId); Guard.Against.NullBasket(basketId, basket); Guard.Against.EmptyBasketOnCheckout(basket.Items); var catalogItemsSpecification = new CatalogItemsSpecification(basket.Items.Select(item => item.CatalogItemId).ToArray()); var catalogItems = await _itemRepository.ListAsync(catalogItemsSpecification); var items = basket.Items.Select(basketItem => { var catalogItem = catalogItems.First(c => c.Id == basketItem.CatalogItemId); var itemOrdered = new CatalogItemOrdered(catalogItem.Id, catalogItem.Name, _uriComposer.ComposePicUri(catalogItem.PictureUri)); var orderItem = new OrderItem(itemOrdered, basketItem.UnitPrice, basketItem.Quantity); return orderItem; }).ToList(); var now = DateTime.UtcNow; var order = new Order(basket.BuyerId, shippingAddress, items, now); await _orderRepository.AddAsync(order); return order; } } public class OrderServiceWithInterface : IOrderService { private readonly IRepository<Order> _orderRepository; private readonly IUriComposer _uriComposer; private readonly IRepository<Basket> _basketRepository; private readonly IRepository<CatalogItem> _itemRepository; private readonly IDateTime _dateTime; public OrderServiceWithInterface(IRepository<Basket> basketRepository, IRepository<CatalogItem> itemRepository, IRepository<Order> orderRepository, IUriComposer uriComposer, IDateTime dateTime) { _orderRepository = orderRepository; _uriComposer = uriComposer; _dateTime = dateTime; _basketRepository = basketRepository; _itemRepository = itemRepository; } public async Task<Order> CreateOrderAsync(int basketId, Address shippingAddress) { var basket = await _basketRepository.GetByIdAsync(basketId); Guard.Against.NullBasket(basketId, basket); Guard.Against.EmptyBasketOnCheckout(basket.Items); var catalogItemsSpecification = new CatalogItemsSpecification(basket.Items.Select(item => item.CatalogItemId).ToArray()); var catalogItems = await _itemRepository.ListAsync(catalogItemsSpecification); var items = basket.Items.Select(basketItem => { var catalogItem = catalogItems.First(c => c.Id == basketItem.CatalogItemId); var itemOrdered = new CatalogItemOrdered(catalogItem.Id, catalogItem.Name, _uriComposer.ComposePicUri(catalogItem.PictureUri)); var orderItem = new OrderItem(itemOrdered, basketItem.UnitPrice, basketItem.Quantity); return orderItem; }).ToList(); var now = _dateTime.UtcNow(); var order = new Order(basket.BuyerId, shippingAddress, items, now); await _orderRepository.AddAsync(order); return order; } } public class OrderServiceDelegate : IOrderService { private readonly IRepository<Order> _orderRepository; private readonly IUriComposer _uriComposer; private readonly UtcNow _utcNow; private readonly IRepository<Basket> _basketRepository; private readonly IRepository<CatalogItem> _itemRepository; public OrderServiceDelegate(IRepository<Basket> basketRepository, IRepository<CatalogItem> itemRepository, IRepository<Order> orderRepository, IUriComposer uriComposer, UtcNow utcNow) { _orderRepository = orderRepository; _uriComposer = uriComposer; _utcNow = utcNow; _basketRepository = basketRepository; _itemRepository = itemRepository; } public async Task<Order> CreateOrderAsync(int basketId, Address shippingAddress) { var basket = await _basketRepository.GetByIdAsync(basketId); Guard.Against.NullBasket(basketId, basket); Guard.Against.EmptyBasketOnCheckout(basket.Items); var catalogItemsSpecification = new CatalogItemsSpecification(basket.Items.Select(item => item.CatalogItemId).ToArray()); var catalogItems = await _itemRepository.ListAsync(catalogItemsSpecification); var items = basket.Items.Select(basketItem => { var catalogItem = catalogItems.First(c => c.Id == basketItem.CatalogItemId); var itemOrdered = new CatalogItemOrdered(catalogItem.Id, catalogItem.Name, _uriComposer.ComposePicUri(catalogItem.PictureUri)); var orderItem = new OrderItem(itemOrdered, basketItem.UnitPrice, basketItem.Quantity); return orderItem; }).ToList(); var now = _utcNow(); var order = new Order(basket.BuyerId, shippingAddress, items, now); await _orderRepository.AddAsync(order); return order; } } public class OrderServiceValue : IOrderServiceValue { private readonly IRepository<Order> _orderRepository; private readonly IUriComposer _uriComposer; private readonly IRepository<Basket> _basketRepository; private readonly IRepository<CatalogItem> _itemRepository; public OrderServiceValue(IRepository<Basket> basketRepository, IRepository<CatalogItem> itemRepository, IRepository<Order> orderRepository, IUriComposer uriComposer) { _orderRepository = orderRepository; _uriComposer = uriComposer; _basketRepository = basketRepository; _itemRepository = itemRepository; } public async Task<Order> CreateOrderAsync(int basketId, Address shippingAddress, DateTimeOffset orderDate) { var basket = await _basketRepository.GetByIdAsync(basketId); Guard.Against.NullBasket(basketId, basket); Guard.Against.EmptyBasketOnCheckout(basket.Items); var catalogItemsSpecification = new CatalogItemsSpecification(basket.Items.Select(item => item.CatalogItemId).ToArray()); var catalogItems = await _itemRepository.ListAsync(catalogItemsSpecification); var items = basket.Items.Select(basketItem => { var catalogItem = catalogItems.First(c => c.Id == basketItem.CatalogItemId); var itemOrdered = new CatalogItemOrdered(catalogItem.Id, catalogItem.Name, _uriComposer.ComposePicUri(catalogItem.PictureUri)); var orderItem = new OrderItem(itemOrdered, basketItem.UnitPrice, basketItem.Quantity); return orderItem; }).ToList(); var order = new Order(basket.BuyerId, shippingAddress, items, orderDate); await _orderRepository.AddAsync(order); return order; } }