Refactor to eliminate unneeded BasketQueryService
This commit is contained in:
@@ -10,6 +10,9 @@ public class Basket : BaseEntity, IAggregateRoot
|
|||||||
private readonly List<BasketItem> _items = new List<BasketItem>();
|
private readonly List<BasketItem> _items = new List<BasketItem>();
|
||||||
public IReadOnlyCollection<BasketItem> Items => _items.AsReadOnly();
|
public IReadOnlyCollection<BasketItem> Items => _items.AsReadOnly();
|
||||||
|
|
||||||
|
public int TotalItems => _items.Sum(i => i.Quantity);
|
||||||
|
|
||||||
|
|
||||||
public Basket(string buyerId)
|
public Basket(string buyerId)
|
||||||
{
|
{
|
||||||
BuyerId = buyerId;
|
BuyerId = buyerId;
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
|
||||||
|
|
||||||
public interface IBasketQueryService
|
|
||||||
{
|
|
||||||
Task<int> CountTotalBasketItems(string username);
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.Infrastructure.Data;
|
|
||||||
|
|
||||||
public class BasketQueryService : IBasketQueryService
|
|
||||||
{
|
|
||||||
private readonly CatalogContext _dbContext;
|
|
||||||
|
|
||||||
public BasketQueryService(CatalogContext dbContext)
|
|
||||||
{
|
|
||||||
_dbContext = dbContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<int> CountTotalBasketItems(string username)
|
|
||||||
{
|
|
||||||
var totalItems = await _dbContext.Baskets
|
|
||||||
.Where(basket => basket.BuyerId == username)
|
|
||||||
.SelectMany(item => item.Items)
|
|
||||||
.SumAsync(sum => sum.Quantity);
|
|
||||||
|
|
||||||
return totalItems;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -18,7 +18,6 @@ public static class ConfigureCoreServices
|
|||||||
|
|
||||||
services.AddScoped<IBasketService, BasketService>();
|
services.AddScoped<IBasketService, BasketService>();
|
||||||
services.AddScoped<IOrderService, OrderService>();
|
services.AddScoped<IOrderService, OrderService>();
|
||||||
services.AddScoped<IBasketQueryService, BasketQueryService>();
|
|
||||||
services.AddSingleton<IUriComposer>(new UriComposer(configuration.Get<CatalogSettings>()));
|
services.AddSingleton<IUriComposer>(new UriComposer(configuration.Get<CatalogSettings>()));
|
||||||
services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>));
|
services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>));
|
||||||
services.AddTransient<IEmailSender, EmailSender>();
|
services.AddTransient<IEmailSender, EmailSender>();
|
||||||
|
|||||||
@@ -7,8 +7,5 @@ namespace Microsoft.eShopWeb.Web.Interfaces;
|
|||||||
public interface IBasketViewModelService
|
public interface IBasketViewModelService
|
||||||
{
|
{
|
||||||
Task<BasketViewModel> GetOrCreateBasketForUser(string userName);
|
Task<BasketViewModel> GetOrCreateBasketForUser(string userName);
|
||||||
|
|
||||||
Task<int> CountTotalBasketItems(string username);
|
|
||||||
|
|
||||||
Task<BasketViewModel> Map(Basket basket);
|
Task<BasketViewModel> Map(Basket basket);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<section class="esh-basket-item">
|
<section class="esh-basket-item">
|
||||||
<a asp-page="/Index" class="btn esh-basket-checkout text-white">[ Continue Shopping..]</a>
|
<a asp-page="/Index" class="btn esh-basket-checkout text-white">[ Continue Shopping ]</a>
|
||||||
</section>
|
</section>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<section class="esh-basket-item col-xs-1">
|
<section class="esh-basket-item col-xs-1">
|
||||||
<a asp-page="/Index" class="btn esh-basket-checkout text-white">[ Continue Shopping..]</a>
|
<a asp-page="/Index" class="btn esh-basket-checkout text-white">[ Continue Shopping ]</a>
|
||||||
</section>
|
</section>
|
||||||
<section class="esh-basket-item col-xs-push-7 col-xs-4">
|
<section class="esh-basket-item col-xs-push-7 col-xs-4">
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<section class="esh-basket-item">
|
<section class="esh-basket-item">
|
||||||
<a asp-page="/Index" class="btn esh-basket-checkout text-white">[ Continue Shopping..]</a>
|
<a asp-page="/Index" class="btn esh-basket-checkout text-white">[ Continue Shopping ]</a>
|
||||||
</section>
|
</section>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,21 +2,27 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
||||||
|
using Microsoft.eShopWeb.ApplicationCore.Specifications;
|
||||||
using Microsoft.eShopWeb.Infrastructure.Identity;
|
using Microsoft.eShopWeb.Infrastructure.Identity;
|
||||||
using Microsoft.eShopWeb.Web.Interfaces;
|
using Microsoft.eShopWeb.Web.Interfaces;
|
||||||
using Microsoft.eShopWeb.Web.ViewModels;
|
using Microsoft.eShopWeb.Web.ViewModels;
|
||||||
|
using BasketEntity = Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate.Basket;
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.Web.Pages.Shared.Components.BasketComponent;
|
namespace Microsoft.eShopWeb.Web.Pages.Shared.Components.BasketComponent;
|
||||||
|
|
||||||
public class Basket : ViewComponent
|
public class Basket : ViewComponent
|
||||||
{
|
{
|
||||||
private readonly IBasketViewModelService _basketService;
|
private readonly IBasketViewModelService _basketViewModelService;
|
||||||
|
private readonly IReadRepository<BasketEntity> _basketRepository;
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||||
|
|
||||||
public Basket(IBasketViewModelService basketService,
|
public Basket(IBasketViewModelService basketViewModelService,
|
||||||
SignInManager<ApplicationUser> signInManager)
|
IReadRepository<BasketEntity> basketRepository,
|
||||||
|
SignInManager<ApplicationUser> signInManager)
|
||||||
{
|
{
|
||||||
_basketService = basketService;
|
_basketViewModelService = basketViewModelService;
|
||||||
|
_basketRepository = basketRepository;
|
||||||
_signInManager = signInManager;
|
_signInManager = signInManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,18 +39,26 @@ public class Basket : ViewComponent
|
|||||||
{
|
{
|
||||||
if (_signInManager.IsSignedIn(HttpContext.User))
|
if (_signInManager.IsSignedIn(HttpContext.User))
|
||||||
{
|
{
|
||||||
return await _basketService.CountTotalBasketItems(User.Identity.Name);
|
var userNameSpec = new BasketWithItemsSpecification(User.Identity.Name);
|
||||||
|
|
||||||
|
var userBasket = await _basketRepository.GetBySpecAsync(userNameSpec);
|
||||||
|
if (userBasket == null) return 0;
|
||||||
|
return userBasket.TotalItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
string anonymousId = GetAnnonymousIdFromCookie();
|
string anonymousId = GetAnnonymousIdFromCookie();
|
||||||
if (anonymousId == null)
|
if (anonymousId == null)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return await _basketService.CountTotalBasketItems(anonymousId);
|
var anonymousSpec = new BasketWithItemsSpecification(anonymousId);
|
||||||
|
var anonymousBasket = await _basketRepository.GetBySpecAsync(anonymousSpec);
|
||||||
|
if (anonymousBasket == null) return 0;
|
||||||
|
return anonymousBasket.TotalItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetAnnonymousIdFromCookie()
|
private string GetAnnonymousIdFromCookie()
|
||||||
{
|
{
|
||||||
|
// TODO: Add a prefix to anonymous cookie values so they cannot collide with user names
|
||||||
if (Request.Cookies.ContainsKey(Constants.BASKET_COOKIENAME))
|
if (Request.Cookies.ContainsKey(Constants.BASKET_COOKIENAME))
|
||||||
{
|
{
|
||||||
var id = Request.Cookies[Constants.BASKET_COOKIENAME];
|
var id = Request.Cookies[Constants.BASKET_COOKIENAME];
|
||||||
|
|||||||
@@ -14,17 +14,14 @@ public class BasketViewModelService : IBasketViewModelService
|
|||||||
{
|
{
|
||||||
private readonly IRepository<Basket> _basketRepository;
|
private readonly IRepository<Basket> _basketRepository;
|
||||||
private readonly IUriComposer _uriComposer;
|
private readonly IUriComposer _uriComposer;
|
||||||
private readonly IBasketQueryService _basketQueryService;
|
private readonly IReadRepository<CatalogItem> _itemRepository;
|
||||||
private readonly IRepository<CatalogItem> _itemRepository;
|
|
||||||
|
|
||||||
public BasketViewModelService(IRepository<Basket> basketRepository,
|
public BasketViewModelService(IRepository<Basket> basketRepository,
|
||||||
IRepository<CatalogItem> itemRepository,
|
IReadRepository<CatalogItem> itemRepository,
|
||||||
IUriComposer uriComposer,
|
IUriComposer uriComposer)
|
||||||
IBasketQueryService basketQueryService)
|
|
||||||
{
|
{
|
||||||
_basketRepository = basketRepository;
|
_basketRepository = basketRepository;
|
||||||
_uriComposer = uriComposer;
|
_uriComposer = uriComposer;
|
||||||
_basketQueryService = basketQueryService;
|
|
||||||
_itemRepository = itemRepository;
|
_itemRepository = itemRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,11 +83,4 @@ public class BasketViewModelService : IBasketViewModelService
|
|||||||
Items = await GetBasketItems(basket.Items)
|
Items = await GetBasketItems(basket.Items)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> CountTotalBasketItems(string username)
|
|
||||||
{
|
|
||||||
var counter = await _basketQueryService.CountTotalBasketItems(username);
|
|
||||||
|
|
||||||
return counter;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Entities.BasketTests;
|
||||||
|
|
||||||
|
public class BasketTotalItems
|
||||||
|
{
|
||||||
|
private readonly int _testCatalogItemId = 123;
|
||||||
|
private readonly decimal _testUnitPrice = 1.23m;
|
||||||
|
private readonly int _testQuantity = 2;
|
||||||
|
private readonly string _buyerId = "Test buyerId";
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ReturnsTotalQuantityWithOneItem()
|
||||||
|
{
|
||||||
|
var basket = new Basket(_buyerId);
|
||||||
|
basket.AddItem(_testCatalogItemId, _testUnitPrice, _testQuantity);
|
||||||
|
|
||||||
|
var result = basket.TotalItems;
|
||||||
|
|
||||||
|
Assert.Equal(_testQuantity, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ReturnsTotalQuantityWithMultipleItems()
|
||||||
|
{
|
||||||
|
var basket = new Basket(_buyerId);
|
||||||
|
basket.AddItem(_testCatalogItemId, _testUnitPrice, _testQuantity);
|
||||||
|
basket.AddItem(_testCatalogItemId, _testUnitPrice, _testQuantity*2);
|
||||||
|
|
||||||
|
var result = basket.TotalItems;
|
||||||
|
|
||||||
|
Assert.Equal(_testQuantity*3, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user