Feature/respect encapsulation (#349)
* resolve osbsolete method * put all properties as private, align unit test * fix version of version in MD, add instruction to install ef tool * fix url stored
This commit is contained in:
@@ -16,7 +16,7 @@ The **eShopOnWeb** sample is related to the [eShopOnContainers](https://github.c
|
|||||||
The goal for this sample is to demonstrate some of the principles and patterns described in the [eBook](https://aka.ms/webappebook). It is not meant to be an eCommerce reference application, and as such it does not implement many features that would be obvious and/or essential to a real eCommerce application.
|
The goal for this sample is to demonstrate some of the principles and patterns described in the [eBook](https://aka.ms/webappebook). It is not meant to be an eCommerce reference application, and as such it does not implement many features that would be obvious and/or essential to a real eCommerce application.
|
||||||
|
|
||||||
> ### VERSIONS
|
> ### VERSIONS
|
||||||
> #### The `master` branch is currently running ASP.NET Core 2.2.
|
> #### The `master` branch is currently running ASP.NET Core 3.1.
|
||||||
> #### Older versions are tagged.
|
> #### Older versions are tagged.
|
||||||
|
|
||||||
## Topics (eBook TOC)
|
## Topics (eBook TOC)
|
||||||
@@ -58,6 +58,10 @@ You can also run the samples in Docker (see below).
|
|||||||
```
|
```
|
||||||
|
|
||||||
1. Ensure your connection strings in `appsettings.json` point to a local SQL Server instance.
|
1. Ensure your connection strings in `appsettings.json` point to a local SQL Server instance.
|
||||||
|
1. Ensure the tool EF was already installed. You can find some help [here](https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/dotnet)
|
||||||
|
```
|
||||||
|
dotnet tool install --global dotnet-ef
|
||||||
|
```
|
||||||
|
|
||||||
1. Open a command prompt in the Web folder and execute the following commands:
|
1. Open a command prompt in the Web folder and execute the following commands:
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
{
|
{
|
||||||
// This can easily be modified to be BaseEntity<T> and public T Id to support different key types.
|
// This can easily be modified to be BaseEntity<T> and public T Id to support different key types.
|
||||||
// Using non-generic integer types for simplicity and to ease caching logic
|
// Using non-generic integer types for simplicity and to ease caching logic
|
||||||
public class BaseEntity
|
public abstract class BaseEntity
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public virtual int Id { get; protected set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,29 +6,34 @@ namespace Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate
|
|||||||
{
|
{
|
||||||
public class Basket : BaseEntity, IAggregateRoot
|
public class Basket : BaseEntity, IAggregateRoot
|
||||||
{
|
{
|
||||||
public string BuyerId { get; set; }
|
public string BuyerId { get; private set; }
|
||||||
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 Basket(string buyerId)
|
||||||
|
{
|
||||||
|
BuyerId = buyerId;
|
||||||
|
}
|
||||||
|
|
||||||
public void AddItem(int catalogItemId, decimal unitPrice, int quantity = 1)
|
public void AddItem(int catalogItemId, decimal unitPrice, int quantity = 1)
|
||||||
{
|
{
|
||||||
if (!Items.Any(i => i.CatalogItemId == catalogItemId))
|
if (!Items.Any(i => i.CatalogItemId == catalogItemId))
|
||||||
{
|
{
|
||||||
_items.Add(new BasketItem()
|
_items.Add(new BasketItem(catalogItemId, quantity, unitPrice));
|
||||||
{
|
|
||||||
CatalogItemId = catalogItemId,
|
|
||||||
Quantity = quantity,
|
|
||||||
UnitPrice = unitPrice
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var existingItem = Items.FirstOrDefault(i => i.CatalogItemId == catalogItemId);
|
var existingItem = Items.FirstOrDefault(i => i.CatalogItemId == catalogItemId);
|
||||||
existingItem.Quantity += quantity;
|
existingItem.AddQuantity(quantity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveEmptyItems()
|
public void RemoveEmptyItems()
|
||||||
{
|
{
|
||||||
_items.RemoveAll(i => i.Quantity == 0);
|
_items.RemoveAll(i => i.Quantity == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetNewBuyerId(string buyerId)
|
||||||
|
{
|
||||||
|
BuyerId = buyerId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,27 @@
|
|||||||
{
|
{
|
||||||
public class BasketItem : BaseEntity
|
public class BasketItem : BaseEntity
|
||||||
{
|
{
|
||||||
public decimal UnitPrice { get; set; }
|
|
||||||
public int Quantity { get; set; }
|
public decimal UnitPrice { get; private set; }
|
||||||
public int CatalogItemId { get; set; }
|
public int Quantity { get; private set; }
|
||||||
|
public int CatalogItemId { get; private set; }
|
||||||
public int BasketId { get; private set; }
|
public int BasketId { get; private set; }
|
||||||
|
|
||||||
|
public BasketItem(int catalogItemId, int quantity, decimal unitPrice)
|
||||||
|
{
|
||||||
|
CatalogItemId = catalogItemId;
|
||||||
|
Quantity = quantity;
|
||||||
|
UnitPrice = unitPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddQuantity(int quantity)
|
||||||
|
{
|
||||||
|
Quantity += quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetNewQuantity(int quantity)
|
||||||
|
{
|
||||||
|
Quantity = quantity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
{
|
{
|
||||||
public class PaymentMethod : BaseEntity
|
public class PaymentMethod : BaseEntity
|
||||||
{
|
{
|
||||||
public string Alias { get; set; }
|
public string Alias { get; private set; }
|
||||||
public string CardId { get; set; } // actual card data must be stored in a PCI compliant system, like Stripe
|
public string CardId { get; private set; } // actual card data must be stored in a PCI compliant system, like Stripe
|
||||||
public string Last4 { get; set; }
|
public string Last4 { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ namespace Microsoft.eShopWeb.ApplicationCore.Entities
|
|||||||
{
|
{
|
||||||
public class CatalogBrand : BaseEntity, IAggregateRoot
|
public class CatalogBrand : BaseEntity, IAggregateRoot
|
||||||
{
|
{
|
||||||
public string Brand { get; set; }
|
public string Brand { get; private set; }
|
||||||
|
public CatalogBrand(string brand)
|
||||||
|
{
|
||||||
|
Brand = brand;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,34 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
using Ardalis.GuardClauses;
|
||||||
|
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.ApplicationCore.Entities
|
namespace Microsoft.eShopWeb.ApplicationCore.Entities
|
||||||
{
|
{
|
||||||
public class CatalogItem : BaseEntity, IAggregateRoot
|
public class CatalogItem : BaseEntity, IAggregateRoot
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; private set; }
|
||||||
public string Description { get; set; }
|
public string Description { get; private set; }
|
||||||
public decimal Price { get; set; }
|
public decimal Price { get; private set; }
|
||||||
public string PictureUri { get; set; }
|
public string PictureUri { get; private set; }
|
||||||
public int CatalogTypeId { get; set; }
|
public int CatalogTypeId { get; private set; }
|
||||||
public CatalogType CatalogType { get; set; }
|
public CatalogType CatalogType { get; private set; }
|
||||||
public int CatalogBrandId { get; set; }
|
public int CatalogBrandId { get; private set; }
|
||||||
public CatalogBrand CatalogBrand { get; set; }
|
public CatalogBrand CatalogBrand { get; private set; }
|
||||||
|
|
||||||
|
public CatalogItem(int catalogTypeId, int catalogBrandId, string description, string name, decimal price, string pictureUri)
|
||||||
|
{
|
||||||
|
CatalogTypeId = catalogTypeId;
|
||||||
|
CatalogBrandId = catalogBrandId;
|
||||||
|
Description = description;
|
||||||
|
Name = name;
|
||||||
|
Price = price;
|
||||||
|
PictureUri = pictureUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(string name, decimal price)
|
||||||
|
{
|
||||||
|
Guard.Against.NullOrEmpty(name, nameof(name));
|
||||||
|
Name = name;
|
||||||
|
Price = price;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,10 @@ namespace Microsoft.eShopWeb.ApplicationCore.Entities
|
|||||||
{
|
{
|
||||||
public class CatalogType : BaseEntity, IAggregateRoot
|
public class CatalogType : BaseEntity, IAggregateRoot
|
||||||
{
|
{
|
||||||
public string Type { get; set; }
|
public string Type { get; private set; }
|
||||||
|
public CatalogType(string type)
|
||||||
|
{
|
||||||
|
Type = type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ namespace Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate
|
|||||||
{
|
{
|
||||||
public class Address // ValueObject
|
public class Address // ValueObject
|
||||||
{
|
{
|
||||||
public String Street { get; private set; }
|
public string Street { get; private set; }
|
||||||
|
|
||||||
public String City { get; private set; }
|
public string City { get; private set; }
|
||||||
|
|
||||||
public String State { get; private set; }
|
public string State { get; private set; }
|
||||||
|
|
||||||
public String Country { get; private set; }
|
public string Country { get; private set; }
|
||||||
|
|
||||||
public String ZipCode { get; private set; }
|
public string ZipCode { get; private set; }
|
||||||
|
|
||||||
private Address() { }
|
private Address() { }
|
||||||
|
|
||||||
|
|||||||
@@ -59,8 +59,8 @@ namespace Microsoft.eShopWeb.ApplicationCore.Services
|
|||||||
{
|
{
|
||||||
if (quantities.TryGetValue(item.Id.ToString(), out var quantity))
|
if (quantities.TryGetValue(item.Id.ToString(), out var quantity))
|
||||||
{
|
{
|
||||||
if(_logger != null) _logger.LogInformation($"Updating quantity of item ID:{item.Id} to {quantity}.");
|
if (_logger != null) _logger.LogInformation($"Updating quantity of item ID:{item.Id} to {quantity}.");
|
||||||
item.Quantity = quantity;
|
item.SetNewQuantity(quantity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
basket.RemoveEmptyItems();
|
basket.RemoveEmptyItems();
|
||||||
@@ -74,7 +74,7 @@ namespace Microsoft.eShopWeb.ApplicationCore.Services
|
|||||||
var basketSpec = new BasketWithItemsSpecification(anonymousId);
|
var basketSpec = new BasketWithItemsSpecification(anonymousId);
|
||||||
var basket = (await _basketRepository.ListAsync(basketSpec)).FirstOrDefault();
|
var basket = (await _basketRepository.ListAsync(basketSpec)).FirstOrDefault();
|
||||||
if (basket == null) return;
|
if (basket == null) return;
|
||||||
basket.BuyerId = userName;
|
basket.SetNewBuyerId(userName);
|
||||||
await _basketRepository.UpdateAsync(basket);
|
await _basketRepository.UpdateAsync(basket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,14 +11,17 @@ namespace Microsoft.eShopWeb.ApplicationCore.Services
|
|||||||
public class OrderService : IOrderService
|
public class OrderService : IOrderService
|
||||||
{
|
{
|
||||||
private readonly IAsyncRepository<Order> _orderRepository;
|
private readonly IAsyncRepository<Order> _orderRepository;
|
||||||
|
private readonly IUriComposer _uriComposer;
|
||||||
private readonly IAsyncRepository<Basket> _basketRepository;
|
private readonly IAsyncRepository<Basket> _basketRepository;
|
||||||
private readonly IAsyncRepository<CatalogItem> _itemRepository;
|
private readonly IAsyncRepository<CatalogItem> _itemRepository;
|
||||||
|
|
||||||
public OrderService(IAsyncRepository<Basket> basketRepository,
|
public OrderService(IAsyncRepository<Basket> basketRepository,
|
||||||
IAsyncRepository<CatalogItem> itemRepository,
|
IAsyncRepository<CatalogItem> itemRepository,
|
||||||
IAsyncRepository<Order> orderRepository)
|
IAsyncRepository<Order> orderRepository,
|
||||||
|
IUriComposer uriComposer)
|
||||||
{
|
{
|
||||||
_orderRepository = orderRepository;
|
_orderRepository = orderRepository;
|
||||||
|
_uriComposer = uriComposer;
|
||||||
_basketRepository = basketRepository;
|
_basketRepository = basketRepository;
|
||||||
_itemRepository = itemRepository;
|
_itemRepository = itemRepository;
|
||||||
}
|
}
|
||||||
@@ -31,7 +34,7 @@ namespace Microsoft.eShopWeb.ApplicationCore.Services
|
|||||||
foreach (var item in basket.Items)
|
foreach (var item in basket.Items)
|
||||||
{
|
{
|
||||||
var catalogItem = await _itemRepository.GetByIdAsync(item.CatalogItemId);
|
var catalogItem = await _itemRepository.GetByIdAsync(item.CatalogItemId);
|
||||||
var itemOrdered = new CatalogItemOrdered(catalogItem.Id, catalogItem.Name, catalogItem.PictureUri);
|
var itemOrdered = new CatalogItemOrdered(catalogItem.Id, catalogItem.Name,_uriComposer.ComposePicUri(catalogItem.PictureUri));
|
||||||
var orderItem = new OrderItem(itemOrdered, item.UnitPrice, item.Quantity);
|
var orderItem = new OrderItem(itemOrdered, item.UnitPrice, item.Quantity);
|
||||||
items.Add(orderItem);
|
items.Add(orderItem);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,11 +59,11 @@ namespace Microsoft.eShopWeb.Infrastructure.Data
|
|||||||
{
|
{
|
||||||
return new List<CatalogBrand>()
|
return new List<CatalogBrand>()
|
||||||
{
|
{
|
||||||
new CatalogBrand() { Brand = "Azure"},
|
new CatalogBrand("Azure"),
|
||||||
new CatalogBrand() { Brand = ".NET" },
|
new CatalogBrand(".NET"),
|
||||||
new CatalogBrand() { Brand = "Visual Studio" },
|
new CatalogBrand("Visual Studio"),
|
||||||
new CatalogBrand() { Brand = "SQL Server" },
|
new CatalogBrand("SQL Server"),
|
||||||
new CatalogBrand() { Brand = "Other" }
|
new CatalogBrand("Other")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,10 +71,10 @@ namespace Microsoft.eShopWeb.Infrastructure.Data
|
|||||||
{
|
{
|
||||||
return new List<CatalogType>()
|
return new List<CatalogType>()
|
||||||
{
|
{
|
||||||
new CatalogType() { Type = "Mug"},
|
new CatalogType("Mug"),
|
||||||
new CatalogType() { Type = "T-Shirt" },
|
new CatalogType("T-Shirt"),
|
||||||
new CatalogType() { Type = "Sheet" },
|
new CatalogType("Sheet"),
|
||||||
new CatalogType() { Type = "USB Memory Stick" }
|
new CatalogType("USB Memory Stick")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,18 +82,18 @@ namespace Microsoft.eShopWeb.Infrastructure.Data
|
|||||||
{
|
{
|
||||||
return new List<CatalogItem>()
|
return new List<CatalogItem>()
|
||||||
{
|
{
|
||||||
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Bot Black Sweatshirt", Name = ".NET Bot Black Sweatshirt", Price = 19.5M, PictureUri = "http://catalogbaseurltobereplaced/images/products/1.png" },
|
new CatalogItem(2,2, ".NET Bot Black Sweatshirt", ".NET Bot Black Sweatshirt", 19.5M, "http://catalogbaseurltobereplaced/images/products/1.png"),
|
||||||
new CatalogItem() { CatalogTypeId=1,CatalogBrandId=2, Description = ".NET Black & White Mug", Name = ".NET Black & White Mug", Price= 8.50M, PictureUri = "http://catalogbaseurltobereplaced/images/products/2.png" },
|
new CatalogItem(1,2, ".NET Black & White Mug", ".NET Black & White Mug", 8.50M, "http://catalogbaseurltobereplaced/images/products/2.png"),
|
||||||
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PictureUri = "http://catalogbaseurltobereplaced/images/products/3.png" },
|
new CatalogItem(2,5, "Prism White T-Shirt", "Prism White T-Shirt", 12, "http://catalogbaseurltobereplaced/images/products/3.png"),
|
||||||
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Foundation Sweatshirt", Name = ".NET Foundation Sweatshirt", Price = 12, PictureUri = "http://catalogbaseurltobereplaced/images/products/4.png" },
|
new CatalogItem(2,2, ".NET Foundation Sweatshirt", ".NET Foundation Sweatshirt", 12, "http://catalogbaseurltobereplaced/images/products/4.png"),
|
||||||
new CatalogItem() { CatalogTypeId=3,CatalogBrandId=5, Description = "Roslyn Red Sheet", Name = "Roslyn Red Sheet", Price = 8.5M, PictureUri = "http://catalogbaseurltobereplaced/images/products/5.png" },
|
new CatalogItem(3,5, "Roslyn Red Sheet", "Roslyn Red Sheet", 8.5M, "http://catalogbaseurltobereplaced/images/products/5.png"),
|
||||||
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Blue Sweatshirt", Name = ".NET Blue Sweatshirt", Price = 12, PictureUri = "http://catalogbaseurltobereplaced/images/products/6.png" },
|
new CatalogItem(2,2, ".NET Blue Sweatshirt", ".NET Blue Sweatshirt", 12, "http://catalogbaseurltobereplaced/images/products/6.png"),
|
||||||
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PictureUri = "http://catalogbaseurltobereplaced/images/products/7.png" },
|
new CatalogItem(2,5, "Roslyn Red T-Shirt", "Roslyn Red T-Shirt", 12, "http://catalogbaseurltobereplaced/images/products/7.png"),
|
||||||
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Kudu Purple Sweatshirt", Name = "Kudu Purple Sweatshirt", Price = 8.5M, PictureUri = "http://catalogbaseurltobereplaced/images/products/8.png" },
|
new CatalogItem(2,5, "Kudu Purple Sweatshirt", "Kudu Purple Sweatshirt", 8.5M, "http://catalogbaseurltobereplaced/images/products/8.png"),
|
||||||
new CatalogItem() { CatalogTypeId=1,CatalogBrandId=5, Description = "Cup<T> White Mug", Name = "Cup<T> White Mug", Price = 12, PictureUri = "http://catalogbaseurltobereplaced/images/products/9.png" },
|
new CatalogItem(1,5, "Cup<T> White Mug", "Cup<T> White Mug", 12, "http://catalogbaseurltobereplaced/images/products/9.png"),
|
||||||
new CatalogItem() { CatalogTypeId=3,CatalogBrandId=2, Description = ".NET Foundation Sheet", Name = ".NET Foundation Sheet", Price = 12, PictureUri = "http://catalogbaseurltobereplaced/images/products/10.png" },
|
new CatalogItem(3,2, ".NET Foundation Sheet", ".NET Foundation Sheet", 12, "http://catalogbaseurltobereplaced/images/products/10.png"),
|
||||||
new CatalogItem() { CatalogTypeId=3,CatalogBrandId=2, Description = "Cup<T> Sheet", Name = "Cup<T> Sheet", Price = 8.5M, PictureUri = "http://catalogbaseurltobereplaced/images/products/11.png" },
|
new CatalogItem(3,2, "Cup<T> Sheet", "Cup<T> Sheet", 8.5M, "http://catalogbaseurltobereplaced/images/products/11.png"),
|
||||||
new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Prism White TShirt", Name = "Prism White TShirt", Price = 12, PictureUri = "http://catalogbaseurltobereplaced/images/products/12.png" }
|
new CatalogItem(2,5, "Prism White TShirt", "Prism White TShirt", 12, "http://catalogbaseurltobereplaced/images/products/12.png")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace Microsoft.eShopWeb.Infrastructure.Data.Config
|
|||||||
builder.HasKey(ci => ci.Id);
|
builder.HasKey(ci => ci.Id);
|
||||||
|
|
||||||
builder.Property(ci => ci.Id)
|
builder.Property(ci => ci.Id)
|
||||||
.ForSqlServerUseSequenceHiLo("catalog_type_hilo")
|
.UseHiLo("catalog_type_hilo")
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
builder.Property(cb => cb.Type)
|
builder.Property(cb => cb.Type)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace Microsoft.eShopWeb.Web.Pages.Admin
|
|||||||
[BindProperty]
|
[BindProperty]
|
||||||
public CatalogItemViewModel CatalogModel { get; set; } = new CatalogItemViewModel();
|
public CatalogItemViewModel CatalogModel { get; set; } = new CatalogItemViewModel();
|
||||||
|
|
||||||
public async Task OnGet(CatalogItemViewModel catalogModel)
|
public void OnGet(CatalogItemViewModel catalogModel)
|
||||||
{
|
{
|
||||||
CatalogModel = catalogModel;
|
CatalogModel = catalogModel;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ namespace Microsoft.eShopWeb.Web.Services
|
|||||||
|
|
||||||
private async Task<BasketViewModel> CreateBasketForUser(string userId)
|
private async Task<BasketViewModel> CreateBasketForUser(string userId)
|
||||||
{
|
{
|
||||||
var basket = new Basket() { BuyerId = userId };
|
var basket = new Basket(userId);
|
||||||
await _basketRepository.AddAsync(basket);
|
await _basketRepository.AddAsync(basket);
|
||||||
|
|
||||||
return new BasketViewModel()
|
return new BasketViewModel()
|
||||||
|
|||||||
@@ -17,15 +17,9 @@ namespace Microsoft.eShopWeb.Web.Services
|
|||||||
|
|
||||||
public async Task UpdateCatalogItem(CatalogItemViewModel viewModel)
|
public async Task UpdateCatalogItem(CatalogItemViewModel viewModel)
|
||||||
{
|
{
|
||||||
//Get existing CatalogItem
|
|
||||||
var existingCatalogItem = await _catalogItemRepository.GetByIdAsync(viewModel.Id);
|
var existingCatalogItem = await _catalogItemRepository.GetByIdAsync(viewModel.Id);
|
||||||
|
existingCatalogItem.Update(viewModel.Name, viewModel.Price);
|
||||||
//Build updated CatalogItem
|
await _catalogItemRepository.UpdateAsync(existingCatalogItem);
|
||||||
var updatedCatalogItem = existingCatalogItem;
|
|
||||||
updatedCatalogItem.Name = viewModel.Name;
|
|
||||||
updatedCatalogItem.Price = viewModel.Price;
|
|
||||||
|
|
||||||
await _catalogItemRepository.UpdateAsync(updatedCatalogItem);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,19 +48,14 @@ namespace Microsoft.eShopWeb.Web.Services
|
|||||||
// the implementation below using ForEach and Count. We need a List.
|
// the implementation below using ForEach and Count. We need a List.
|
||||||
var itemsOnPage = await _itemRepository.ListAsync(filterPaginatedSpecification);
|
var itemsOnPage = await _itemRepository.ListAsync(filterPaginatedSpecification);
|
||||||
var totalItems = await _itemRepository.CountAsync(filterSpecification);
|
var totalItems = await _itemRepository.CountAsync(filterSpecification);
|
||||||
|
|
||||||
foreach (var itemOnPage in itemsOnPage)
|
|
||||||
{
|
|
||||||
itemOnPage.PictureUri = _uriComposer.ComposePicUri(itemOnPage.PictureUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
var vm = new CatalogIndexViewModel()
|
var vm = new CatalogIndexViewModel()
|
||||||
{
|
{
|
||||||
CatalogItems = itemsOnPage.Select(i => new CatalogItemViewModel()
|
CatalogItems = itemsOnPage.Select(i => new CatalogItemViewModel()
|
||||||
{
|
{
|
||||||
Id = i.Id,
|
Id = i.Id,
|
||||||
Name = i.Name,
|
Name = i.Name,
|
||||||
PictureUri = i.PictureUri,
|
PictureUri = _uriComposer.ComposePicUri(i.PictureUri),
|
||||||
Price = i.Price
|
Price = i.Price
|
||||||
}),
|
}),
|
||||||
Brands = await GetBrands(),
|
Brands = await GetBrands(),
|
||||||
|
|||||||
@@ -6,14 +6,15 @@ namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Entities.BasketTests
|
|||||||
{
|
{
|
||||||
public class BasketAddItem
|
public class BasketAddItem
|
||||||
{
|
{
|
||||||
private int _testCatalogItemId = 123;
|
private readonly int _testCatalogItemId = 123;
|
||||||
private decimal _testUnitPrice = 1.23m;
|
private readonly decimal _testUnitPrice = 1.23m;
|
||||||
private int _testQuantity = 2;
|
private readonly int _testQuantity = 2;
|
||||||
|
private readonly string _buyerId = "Test buyerId";
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AddsBasketItemIfNotPresent()
|
public void AddsBasketItemIfNotPresent()
|
||||||
{
|
{
|
||||||
var basket = new Basket();
|
var basket = new Basket(_buyerId);
|
||||||
basket.AddItem(_testCatalogItemId, _testUnitPrice, _testQuantity);
|
basket.AddItem(_testCatalogItemId, _testUnitPrice, _testQuantity);
|
||||||
|
|
||||||
var firstItem = basket.Items.Single();
|
var firstItem = basket.Items.Single();
|
||||||
@@ -25,7 +26,7 @@ namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Entities.BasketTests
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void IncrementsQuantityOfItemIfPresent()
|
public void IncrementsQuantityOfItemIfPresent()
|
||||||
{
|
{
|
||||||
var basket = new Basket();
|
var basket = new Basket(_buyerId);
|
||||||
basket.AddItem(_testCatalogItemId, _testUnitPrice, _testQuantity);
|
basket.AddItem(_testCatalogItemId, _testUnitPrice, _testQuantity);
|
||||||
basket.AddItem(_testCatalogItemId, _testUnitPrice, _testQuantity);
|
basket.AddItem(_testCatalogItemId, _testUnitPrice, _testQuantity);
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Entities.BasketTests
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void KeepsOriginalUnitPriceIfMoreItemsAdded()
|
public void KeepsOriginalUnitPriceIfMoreItemsAdded()
|
||||||
{
|
{
|
||||||
var basket = new Basket();
|
var basket = new Basket(_buyerId);
|
||||||
basket.AddItem(_testCatalogItemId, _testUnitPrice, _testQuantity);
|
basket.AddItem(_testCatalogItemId, _testUnitPrice, _testQuantity);
|
||||||
basket.AddItem(_testCatalogItemId, _testUnitPrice * 2, _testQuantity);
|
basket.AddItem(_testCatalogItemId, _testUnitPrice * 2, _testQuantity);
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@ namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Entities.BasketTests
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void DefaultsToQuantityOfOne()
|
public void DefaultsToQuantityOfOne()
|
||||||
{
|
{
|
||||||
var basket = new Basket();
|
var basket = new Basket(_buyerId);
|
||||||
basket.AddItem(_testCatalogItemId, _testUnitPrice);
|
basket.AddItem(_testCatalogItemId, _testUnitPrice);
|
||||||
|
|
||||||
var firstItem = basket.Items.Single();
|
var firstItem = basket.Items.Single();
|
||||||
@@ -57,7 +58,7 @@ namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Entities.BasketTests
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void RemoveEmptyItems()
|
public void RemoveEmptyItems()
|
||||||
{
|
{
|
||||||
var basket = new Basket();
|
var basket = new Basket(_buyerId);
|
||||||
basket.AddItem(_testCatalogItemId, _testUnitPrice, 0);
|
basket.AddItem(_testCatalogItemId, _testUnitPrice, 0);
|
||||||
basket.RemoveEmptyItems();
|
basket.RemoveEmptyItems();
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Services.BasketServiceTes
|
|||||||
{
|
{
|
||||||
public class DeleteBasket
|
public class DeleteBasket
|
||||||
{
|
{
|
||||||
private Mock<IAsyncRepository<Basket>> _mockBasketRepo;
|
private readonly string _buyerId = "Test buyerId";
|
||||||
|
private readonly Mock<IAsyncRepository<Basket>> _mockBasketRepo;
|
||||||
|
|
||||||
public DeleteBasket()
|
public DeleteBasket()
|
||||||
{
|
{
|
||||||
@@ -19,7 +20,7 @@ namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Services.BasketServiceTes
|
|||||||
[Fact]
|
[Fact]
|
||||||
public async Task Should_InvokeBasketRepositoryDeleteAsync_Once()
|
public async Task Should_InvokeBasketRepositoryDeleteAsync_Once()
|
||||||
{
|
{
|
||||||
var basket = new Basket();
|
var basket = new Basket(_buyerId);
|
||||||
basket.AddItem(1, It.IsAny<decimal>(), It.IsAny<int>());
|
basket.AddItem(1, It.IsAny<decimal>(), It.IsAny<int>());
|
||||||
basket.AddItem(2, It.IsAny<decimal>(), It.IsAny<int>());
|
basket.AddItem(2, It.IsAny<decimal>(), It.IsAny<int>());
|
||||||
_mockBasketRepo.Setup(x => x.GetByIdAsync(It.IsAny<int>()))
|
_mockBasketRepo.Setup(x => x.GetByIdAsync(It.IsAny<int>()))
|
||||||
|
|||||||
@@ -3,12 +3,14 @@ using Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
using Moq;
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.UnitTests
|
namespace Microsoft.eShopWeb.UnitTests
|
||||||
{
|
{
|
||||||
public class BasketWithItems
|
public class BasketWithItems
|
||||||
{
|
{
|
||||||
private int _testBasketId = 123;
|
private readonly int _testBasketId = 123;
|
||||||
|
private readonly string _buyerId = "Test buyerId";
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void MatchesBasketWithGivenId()
|
public void MatchesBasketWithGivenId()
|
||||||
@@ -37,11 +39,18 @@ namespace Microsoft.eShopWeb.UnitTests
|
|||||||
|
|
||||||
public List<Basket> GetTestBasketCollection()
|
public List<Basket> GetTestBasketCollection()
|
||||||
{
|
{
|
||||||
|
var basket1Mock = new Mock<Basket>(_buyerId);
|
||||||
|
basket1Mock.SetupGet(s => s.Id).Returns(1);
|
||||||
|
var basket2Mock = new Mock<Basket>(_buyerId);
|
||||||
|
basket2Mock.SetupGet(s => s.Id).Returns(2);
|
||||||
|
var basket3Mock = new Mock<Basket>(_buyerId);
|
||||||
|
basket3Mock.SetupGet(s => s.Id).Returns(_testBasketId);
|
||||||
|
|
||||||
return new List<Basket>()
|
return new List<Basket>()
|
||||||
{
|
{
|
||||||
new Basket() { Id = 1 },
|
basket1Mock.Object,
|
||||||
new Basket() { Id = 2 },
|
basket2Mock.Object,
|
||||||
new Basket() { Id = _testBasketId }
|
basket3Mock.Object
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Microsoft.eShopWeb.ApplicationCore.Entities;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
using Moq;
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.UnitTests
|
namespace Microsoft.eShopWeb.UnitTests
|
||||||
{
|
{
|
||||||
@@ -31,11 +32,11 @@ namespace Microsoft.eShopWeb.UnitTests
|
|||||||
{
|
{
|
||||||
return new List<CatalogItem>()
|
return new List<CatalogItem>()
|
||||||
{
|
{
|
||||||
new CatalogItem() { Id = 1, CatalogBrandId = 1, CatalogTypeId= 1 },
|
new CatalogItem(1, 1, "Description", "Name", 0, "FakePath"),
|
||||||
new CatalogItem() { Id = 2, CatalogBrandId = 1, CatalogTypeId= 2 },
|
new CatalogItem(2, 1, "Description", "Name", 0, "FakePath"),
|
||||||
new CatalogItem() { Id = 3, CatalogBrandId = 1, CatalogTypeId= 3 },
|
new CatalogItem(3, 1, "Description", "Name", 0, "FakePath"),
|
||||||
new CatalogItem() { Id = 4, CatalogBrandId = 2, CatalogTypeId= 1 },
|
new CatalogItem(1, 2, "Description", "Name", 0, "FakePath"),
|
||||||
new CatalogItem() { Id = 5, CatalogBrandId = 2, CatalogTypeId= 2 },
|
new CatalogItem(2, 2, "Description", "Name", 0, "FakePath"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate;
|
using Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate;
|
||||||
|
using Moq;
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.UnitTests.Builders
|
namespace Microsoft.eShopWeb.UnitTests.Builders
|
||||||
{
|
{
|
||||||
public class BasketBuilder
|
public class BasketBuilder
|
||||||
{
|
{
|
||||||
private Basket _basket;
|
private Basket _basket;
|
||||||
public string BasketBuyerId => "testbuyerId@test.com";
|
public string BasketBuyerId => "testbuyerId@test.com";
|
||||||
|
|
||||||
public int BasketId => 1;
|
public int BasketId => 1;
|
||||||
|
|
||||||
public BasketBuilder()
|
public BasketBuilder()
|
||||||
@@ -20,13 +22,17 @@ namespace Microsoft.eShopWeb.UnitTests.Builders
|
|||||||
|
|
||||||
public Basket WithNoItems()
|
public Basket WithNoItems()
|
||||||
{
|
{
|
||||||
_basket = new Basket { BuyerId = BasketBuyerId, Id = BasketId };
|
var basketMock = new Mock<Basket>(BasketBuyerId);
|
||||||
|
basketMock.SetupGet(s => s.Id).Returns(BasketId);
|
||||||
|
|
||||||
|
_basket = basketMock.Object;
|
||||||
return _basket;
|
return _basket;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Basket WithOneBasketItem()
|
public Basket WithOneBasketItem()
|
||||||
{
|
{
|
||||||
_basket = new Basket { BuyerId = BasketBuyerId, Id = BasketId };
|
var basketMock = new Mock<Basket>(BasketBuyerId);
|
||||||
|
_basket = basketMock.Object;
|
||||||
_basket.AddItem(2, 3.40m, 4);
|
_basket.AddItem(2, 3.40m, 4);
|
||||||
return _basket;
|
return _basket;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user