diff --git a/.gitignore b/.gitignore index 7d3f5e8..0206901 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,4 @@ build/ *.pidb *.log *.scc +*.vs diff --git a/.vs/config/applicationhost.config b/.vs/config/applicationhost.config deleted file mode 100644 index 2cb5d16..0000000 --- a/.vs/config/applicationhost.config +++ /dev/null @@ -1,1038 +0,0 @@ - - - - - - - - -
-
-
-
-
-
-
-
- - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
- -
-
-
-
-
-
- -
-
-
-
-
- -
-
-
- -
-
- -
-
- -
-
-
- - -
-
-
-
-
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/eCommerce.Tests/DomainModelLayer/CartTest.cs b/eCommerce.Tests/DomainModelLayer/CartTest.cs index fd6abdc..326ea12 100644 --- a/eCommerce.Tests/DomainModelLayer/CartTest.cs +++ b/eCommerce.Tests/DomainModelLayer/CartTest.cs @@ -1,10 +1,16 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using FluentAssertions; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; using eCommerce.DomainModelLayer.Carts; +using eCommerce.DomainModelLayer.Countries; +using eCommerce.DomainModelLayer.Customers; using eCommerce.DomainModelLayer.Products; +using eCommerce.DomainModelLayer.Services; +using eCommerce.Helpers.Domain; namespace eCommerce.Tests.DomainModelLayer { @@ -12,77 +18,212 @@ namespace eCommerce.Tests.DomainModelLayer public class CartTest { [TestMethod, TestCategory("Unit")] - public void TotalCost_TwoProductsOneQuantitySummedUp_ReturnsCorrectSum() + public void SharedCart_SharingACart_ReturnsCorrectCustomerId() { - decimal expected = 100; + var cart = CreateCart(); + var recipient = CreateCustomer("receiver"); - Mock cartProduct = new Mock(); - cartProduct.CallBase = true; - cartProduct.SetupGet(x => x.Quantity).Returns(1); - cartProduct.SetupGet(x => x.Cost).Returns(50); + var sharedCart = cart.Share(recipient); - Mock cart = new Mock(); - cart.CallBase = true; - cart.SetupGet(x => x.Products) - .Returns(new ReadOnlyCollection(new List() - { - cartProduct.Object, - cartProduct.Object - })); + recipient.Id.Should().Equals(sharedCart.CustomerId); + } - decimal actual = cart.Object.TotalCost; + [TestMethod, TestCategory("Unit")] + public void TotalCost_TwoProductsOneQuantitySummedUp_ReturnsCorrectSum() + { + var cart = CreateCart(); + var expected = 200; + var actual = cart.TotalCost; actual.ShouldBeEquivalentTo(expected); } [TestMethod, TestCategory("Unit")] public void TotalCost_TwoProductsTwoQuantitiesSummedUp_ReturnsCorrectTotalCostSum() { - decimal expected = 200; + var cart = CreateCart(); - Mock cartProduct = new Mock(); - cartProduct.CallBase = true; - cartProduct.SetupGet(x => x.Quantity).Returns(2); - cartProduct.SetupGet(x => x.Cost).Returns(50); + var expected = 200; + var actual = cart.TotalCost; + actual.ShouldBeEquivalentTo(expected); + } - Mock cart = new Mock(); - cart.CallBase = true; - cart.SetupGet(x => x.Products) - .Returns(new ReadOnlyCollection(new List() - { - cartProduct.Object, - cartProduct.Object - })); + [TestMethod, TestCategory("Unit")] + public void TotalCost_TwoSingleProductsTaxSummedUp_ReturnsCorrectTotalTaxSum() + { + var cart = CreateCart(); + + var expected = 20; + var actual = cart.TotalTax; + actual.ShouldBeEquivalentTo(expected); + } + + [TestMethod, TestCategory("Unit")] + public void SharedCart_SharingACart_ReturnsCorrectProducts() + { + var cart = CreateCart(); + var recipient = CreateCustomer("receiver"); - decimal actual = cart.Object.TotalCost; + var sharedCart = cart.Share(recipient); + var subjectProductIds = cart.Products.Select(x => x.ProductId).ToList(); + var sharedCartIds = sharedCart.Products.Select(x => x.ProductId).ToList(); + subjectProductIds.ForEach(id => Assert.IsTrue(sharedCartIds.Contains(id))); + } + + + [TestMethod, TestCategory("Unit")] + public void SharedCart_SharingACart_ReturnsCorrectTotalTax() + { + var cart = CreateCart(); + var recipient = Customer.Create("receiver", "v", "c@c.com", new Mock().Object); + + var sharedCart = cart.Share(recipient); + + var expected = 20; + var actual = sharedCart.TotalTax; actual.ShouldBeEquivalentTo(expected); } [TestMethod, TestCategory("Unit")] - public void TotalCost_TwoSingleProductsTaxSummedUp_ReturnsCorrectTotalTaxSum() + public void SharedCart_SharingACart_ReturnsCorrectTotalCost() { - decimal expected = 20; + var cart = CreateCart(); + var recipient = CreateCustomer("recipient"); - Mock cartProduct = new Mock(); - cartProduct.CallBase = true; - cartProduct.SetupGet(x => x.Quantity).Returns(1); - cartProduct.SetupGet(x => x.Tax).Returns(10); - cartProduct.SetupGet(x => x.Cost).Returns(100); + var sharedCart = cart.Share(recipient); + + var expected = 200; + var actual = sharedCart.TotalCost; + actual.ShouldBeEquivalentTo(expected); + } + + [TestMethod, TestCategory("Unit")] + public void Add_AddingACartProduct_UpdatesCartProductsCorrectly() + { + var customer = CreateCustomer("customer"); + var cart = Cart.Create(customer); + var product = Product.Create("Cheese Slices", 1, 99, ProductCode.Create("CheeseAbc")); + var expectedCartProduct = CartProduct.Create(customer, cart, product, 1, new Mock().Object); + + cart.Add(expectedCartProduct); + + var contains = cart.Products.Any(p => p.ProductId == product.Id); + contains.Should().BeTrue(); + } + + + [TestMethod, TestCategory("Unit")] + public void Add_AddingACartProduct_RaisesProductAddedEvent() + { + + var cart = CreateCart(); + var cartProduct = CreateCartProduct(); + var expectedEvent = new ProductAddedCart {CartProduct = cartProduct}; + ProductAddedCart actualEvent = null; + DomainEvents.Register(addedCart => actualEvent = addedCart); + + cart.Add(cartProduct); + + actualEvent.Should().NotBeNull().And.Equals(expectedEvent); + } + + + [TestMethod, TestCategory("Unit")] + public void Remove_RemovingACartProduct_RemovesCartProductsCorrectly() + { + var customer = CreateCustomer("receiver"); + var cart = Cart.Create(customer); + var product = Product.Create("Cheese Slices", 1, 99, ProductCode.Create("CheeseAbc")); + var cartProduct = CartProduct.Create(customer, cart, product, 1, new Mock().Object); + cart.Add(cartProduct); + cart.Remove(product); + + var contains = cart.Products.Contains(cartProduct); + + contains.Should().BeFalse(); + } + + [TestMethod, TestCategory("Unit")] + public void Clear_ClearingACart_ClearsAllProducts() + { + var customer = Customer.Create("receiver", "v", "c@c.com", new Mock().Object); + var cart = Cart.Create(customer); + var product = CreateCartProduct(); + cart.Add(product); + + cart.Clear(); + + cart.Products.Count.Should().Be(0); + } + + [TestMethod, TestCategory("Unit")] + public void Create_CreatingANewCart_ReturnsACorrectCart() + { + var customer = Customer.Create("receiver", "v", "c@c.com", new Mock().Object); + + var cart = Cart.Create(customer); + + cart.Should().NotBeNull(); + } + + [TestMethod, TestCategory("Unit")] + [ExpectedException(typeof(ArgumentNullException))] + public void Create_CreatingANewCart_ThrowsExceptionOnNullCustomer() + { + Customer customer = null; + var cart = Cart.Create(customer); + } + + [TestMethod, TestCategory("Unit")] + [ExpectedException(typeof(ArgumentNullException))] + public void Remove_RemovingACartProduct_ThrowsExceptionOnNullProduct() + { + var cart = CreateCart(); + Product nullProduct = null; + cart.Remove(nullProduct); + } + + [TestMethod, TestCategory("Unit")] + [ExpectedException(typeof(ArgumentNullException))] + public void Add_AddingACartProduct_ThrowsExceptionOnNullProduct() + { + var customer = Customer.Create("receiver", "v", "c@c.com", new Mock().Object); + var cart = Cart.Create(customer); + CartProduct cartProduct = null; + cart.Add(cartProduct); + } + + private static Cart CreateCart() + { + var product1 = CreateCartProduct(); + var product2 = CreateCartProduct(); Mock cart = new Mock(); cart.CallBase = true; cart.SetupGet(x => x.Products) .Returns(new ReadOnlyCollection(new List() - { - cartProduct.Object, - cartProduct.Object - })); + { + product1, + product2 + })); - decimal actual = cart.Object.TotalTax; + return cart.Object; + } - actual.ShouldBeEquivalentTo(expected); + private static CartProduct CreateCartProduct() + { + Mock cartProduct = new Mock(); + var productId = Guid.NewGuid(); + cartProduct.CallBase = true; + cartProduct.SetupGet(x => x.Quantity).Returns(1); + cartProduct.SetupGet(x => x.Tax).Returns(10); + cartProduct.SetupGet(x => x.Cost).Returns(100); + cartProduct.SetupGet(x => x.ProductId).Returns(productId); + return cartProduct.Object; } + private static Customer CreateCustomer(string name) + => Customer.Create(name, name.Reverse().ToString(), $"{name}@email.com", new Mock().Object); } -} +} \ No newline at end of file diff --git a/eCommerce.Tests/DomainModelLayer/TaxServiceTest.cs b/eCommerce.Tests/DomainModelLayer/TaxServiceTest.cs index 5b62e5b..a719a07 100644 --- a/eCommerce.Tests/DomainModelLayer/TaxServiceTest.cs +++ b/eCommerce.Tests/DomainModelLayer/TaxServiceTest.cs @@ -3,18 +3,13 @@ using eCommerce.DomainModelLayer.Customers; using Moq; using FluentAssertions; -using eCommerce.DomainModelLayer.Purchases; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using FluentAssertions.Equivalency; -using eCommerce.Helpers.Domain; -using eCommerce.DomainModelLayer.Services; using eCommerce.DomainModelLayer; using eCommerce.Helpers.Repository; using eCommerce.DomainModelLayer.Tax; using eCommerce.DomainModelLayer.Countries; using eCommerce.DomainModelLayer.Products; using eCommerce.DomainModelLayer.Customers.Spec; +using eCommerce.DomainModelLayer.Services; namespace eCommerce.Tests.DomainModelLayer { @@ -48,7 +43,7 @@ public void Calculate_OverallProductTax_ReturnsCorrectTax() product.SetupGet(x => x.Code).Returns(new ProductCode()); //call method - TaxService taxService = new TaxService(settings.Object, repositoryCountryTax.Object); + ITaxService taxService = new TaxService(settings.Object, repositoryCountryTax.Object); decimal actual = taxService.Calculate(customer.Object, product.Object); diff --git a/eCommerce.WebService/App_Start/WebApiConfig.cs b/eCommerce.WebService/App_Start/WebApiConfig.cs index 4ef8406..1fa08c0 100644 --- a/eCommerce.WebService/App_Start/WebApiConfig.cs +++ b/eCommerce.WebService/App_Start/WebApiConfig.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Linq; using System.Web.Http; namespace eCommerce.WebService @@ -8,14 +6,27 @@ namespace eCommerce.WebService public static class WebApiConfig { public static void Register(HttpConfiguration config) + { + MapRoutes(config); + SetJsonToDefaultFormatter(config); + config.EnableSystemDiagnosticsTracing(); + } + + private static void SetJsonToDefaultFormatter(HttpConfiguration config) + { + var appXmlType = + config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => + t.MediaType == "application/xml"); + config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType); + } + + private static void MapRoutes(HttpConfiguration config) { config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { action = "get", id = RouteParameter.Optional } ); - - config.EnableSystemDiagnosticsTracing(); } } } diff --git a/eCommerce.WebService/Controllers/CartController.cs b/eCommerce.WebService/Controllers/CartController.cs index 43e2bbb..c070d6f 100644 --- a/eCommerce.WebService/Controllers/CartController.cs +++ b/eCommerce.WebService/Controllers/CartController.cs @@ -1,10 +1,6 @@ using eCommerce.WebService.Models; using eCommerce.ApplicationLayer.Carts; using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Http; using System.Web.Http; namespace eCommerce.WebService.Controllers @@ -25,73 +21,40 @@ public CartController(ICartService cartService) } [HttpGet] - public Response Add(Guid customerId, [FromUri]CartProductDto cartDto) - { - Response response = new Response(); - try - { - response.Object = this.cartService.Add(customerId, cartDto); - } - catch (Exception ex) - { - //log error - response.Errored = true; - response.ErrorMessage = ex.Message; - } - return response; - } + public Response Add(Guid customerId, [FromUri]CartProductDto cartDto) + => CreateResponse(() => this.cartService.Add(customerId, cartDto)); [HttpGet] - public Response GetById(Guid customerId) - { - Response response = new Response(); - try - { - response.Object = this.cartService.Get(customerId); - } - catch (Exception ex) - { - //log error - response.Errored = true; - response.ErrorMessage = ex.Message; - } - return response; - } + public Response GetById(Guid customerId) + => CreateResponse(() => this.cartService.Get(customerId)); [HttpGet] - public Response Remove(Guid customerId, Guid productId) - { - Response response = new Response(); - try - { - response.Object = this.cartService.Remove(customerId, productId); - } - catch (Exception ex) - { - //log error - response.Errored = true; - response.ErrorMessage = ex.Message; - } - return response; - } + public Response Remove(Guid customerId, Guid productId) + => CreateResponse(() => this.cartService.Remove(customerId, productId)); [HttpGet] - public Response Checkout(Guid customerId) + public Response Checkout(Guid customerId) + => CreateResponse(() => this.cartService.CheckOut(customerId)); + + [HttpGet] + public Response Share(Guid cartOwnerId, Guid cartRecipientId) + => CreateResponse(() => this.cartService.Share(cartOwnerId, cartRecipientId)); + + private Response CreateResponse(Func execute) { - Response response = new Response(); + var response = new Response(); try { - response.Object = this.cartService.CheckOut(customerId); + response.Object = execute(); } catch (Exception ex) { - //log error response.Errored = true; response.ErrorMessage = ex.Message; } + return response; } - } } \ No newline at end of file diff --git a/eCommerce.WebService/Controllers/CustomerController.cs b/eCommerce.WebService/Controllers/CustomerController.cs index 42d972d..c134598 100644 --- a/eCommerce.WebService/Controllers/CustomerController.cs +++ b/eCommerce.WebService/Controllers/CustomerController.cs @@ -1,10 +1,6 @@ using eCommerce.WebService.Models; using eCommerce.ApplicationLayer.Customers; using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Http; using System.Web.Http; namespace eCommerce.WebService.Controllers @@ -16,6 +12,7 @@ namespace eCommerce.WebService.Controllers * http://localhost:50300/api/customer/IsEmailAvailable?email=smith.john@microsoft.com * http://localhost:50300/api/customer/RemoveById/5D5020DA-47DF-4C82-A722-C8DEAF06AE23 * http://localhost:50300/api/customer/update?id=5D5020DA-47DF-4C82-A722-C8DEAF06AE23&Email=smith.john@microsoft.com + * http://localhost:50300/api/customer/add?FirstName=Eddy&LastName=Carmine&Email=e@as.com&countryId=229074bd-2356-4b5a-8619-cdebba71cc21 */ public class CustomerController : ApiController { diff --git a/eCommerce.WebService/Controllers/ProductController.cs b/eCommerce.WebService/Controllers/ProductController.cs index e35b675..48a9d4d 100644 --- a/eCommerce.WebService/Controllers/ProductController.cs +++ b/eCommerce.WebService/Controllers/ProductController.cs @@ -1,10 +1,6 @@ using eCommerce.WebService.Models; using eCommerce.ApplicationLayer.Products; using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Http; using System.Web.Http; namespace eCommerce.WebService.Controllers diff --git a/eCommerce.WebService/Models/ResponseOfTReturn.cs b/eCommerce.WebService/Models/ResponseOfTReturn.cs index 41ad75d..e842b19 100644 --- a/eCommerce.WebService/Models/ResponseOfTReturn.cs +++ b/eCommerce.WebService/Models/ResponseOfTReturn.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; - -namespace eCommerce.WebService.Models +namespace eCommerce.WebService.Models { public sealed class Response : Response { diff --git a/eCommerce/ApplicationLayer/Carts/CartService.cs b/eCommerce/ApplicationLayer/Carts/CartService.cs index d2f2380..7ec501a 100644 --- a/eCommerce/ApplicationLayer/Carts/CartService.cs +++ b/eCommerce/ApplicationLayer/Carts/CartService.cs @@ -15,12 +15,12 @@ public class CartService : ICartService IRepository productRepository; IRepository cartRepository; IUnitOfWork unitOfWork; - TaxService taxDomainService; - CheckoutService checkoutDomainService; + ITaxService taxDomainService; + CheckoutService checkoutDomainService; - public CartService(IRepository customerRepository, - IRepository productRepository, IRepository cartRepository, - IUnitOfWork unitOfWork, TaxService taxDomainService, CheckoutService checkoutDomainService) + public CartService(IRepository customerRepository, + IRepository productRepository, IRepository cartRepository, + IUnitOfWork unitOfWork, ITaxService taxDomainService, CheckoutService checkoutDomainService) { this.customerRepository = customerRepository; this.productRepository = productRepository; @@ -35,21 +35,20 @@ public CartDto Add(Guid customerId, CartProductDto productDto) CartDto cartDto = null; Customer customer = this.customerRepository.FindById(customerId); - if (customer == null) - throw new Exception(String.Format("Customer was not found with this Id: {0}", customerId)); + ValidateCustomer(customerId, customer); Cart cart = this.cartRepository.FindOne(new CustomerCartSpec(customerId)); - if(cart == null) + if (cart == null) { cart = Cart.Create(customer); this.cartRepository.Add(cart); } Product product = this.productRepository.FindById(productDto.ProductId); - this.validateProduct(product.Id, product); + this.ValidateProduct(product.Id, product); //Double Dispatch Pattern - cart.Add(CartProduct.Create(customer, cart, product, + cart.Add(CartProduct.Create(customer, cart, product, productDto.Quantity, taxDomainService)); cartDto = Mapper.Map(cart); @@ -62,10 +61,10 @@ public CartDto Remove(Guid customerId, Guid productId) CartDto cartDto = null; Cart cart = this.cartRepository.FindOne(new CustomerCartSpec(customerId)); - this.validateCart(customerId, cart); + this.ValidateCart(customerId, cart); Product product = this.productRepository.FindById(productId); - this.validateProduct(productId, product); + this.ValidateProduct(productId, product); cart.Remove(product); cartDto = Mapper.Map(cart); @@ -76,7 +75,7 @@ public CartDto Remove(Guid customerId, Guid productId) public CartDto Get(Guid customerId) { Cart cart = this.cartRepository.FindOne(new CustomerCartSpec(customerId)); - this.validateCart(customerId, cart); + this.ValidateCart(customerId, cart); return Mapper.Map(cart); } @@ -86,11 +85,11 @@ public CheckOutResultDto CheckOut(Guid customerId) CheckOutResultDto checkOutResultDto = new CheckOutResultDto(); Cart cart = this.cartRepository.FindOne(new CustomerCartSpec(customerId)); - this.validateCart(customerId, cart); + this.ValidateCart(customerId, cart); Customer customer = this.customerRepository.FindById(cart.CustomerId); - Nullable checkOutIssue = + Nullable checkOutIssue = this.checkoutDomainService.CanCheckOut(customer, cart); if (!checkOutIssue.HasValue) @@ -107,16 +106,36 @@ public CheckOutResultDto CheckOut(Guid customerId) return checkOutResultDto; } - private void validateCart(Guid customerId, Cart cart) + public CartDto Share(Guid cartOwnerId, Guid cartRecipientId) + { + var cart = this.cartRepository.FindOne(new CustomerCartSpec(cartOwnerId)); + this.ValidateCart(cartOwnerId, cart); + + var recipient = this.customerRepository.FindById(cartRecipientId); + ValidateCustomer(cartRecipientId, recipient); + + var sharedCart = cart.Share(recipient); + this.cartRepository.Add(sharedCart); + + return Mapper.Map(sharedCart); + } + + private void ValidateCart(Guid customerId, Cart cart) { if (cart == null) throw new Exception(String.Format("Customer was not found with this Id: {0}", customerId)); } - private void validateProduct(Guid productId, Product product) + private void ValidateProduct(Guid productId, Product product) { if (product == null) throw new Exception(String.Format("Product was not found with this Id: {0}", productId)); } + + private void ValidateCustomer(Guid customerId, Customer customer) + { + if (customer == null) + throw new ArgumentNullException($"Customer was not found with this Id: {customerId}"); + } } -} +} \ No newline at end of file diff --git a/eCommerce/ApplicationLayer/Carts/ICartService.cs b/eCommerce/ApplicationLayer/Carts/ICartService.cs index b26b771..9ebebd5 100644 --- a/eCommerce/ApplicationLayer/Carts/ICartService.cs +++ b/eCommerce/ApplicationLayer/Carts/ICartService.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using eCommerce.DomainModelLayer.Carts; namespace eCommerce.ApplicationLayer.Carts { @@ -12,5 +8,6 @@ public interface ICartService CartDto Remove(Guid customerId, Guid productId); CartDto Get(Guid customerId); CheckOutResultDto CheckOut(Guid customerId); + CartDto Share(Guid cartOwnerId, Guid cartRecipientId); } -} +} \ No newline at end of file diff --git a/eCommerce/ApplicationLayer/Customers/ICustomerService.cs b/eCommerce/ApplicationLayer/Customers/ICustomerService.cs index 30364f2..9308aea 100644 --- a/eCommerce/ApplicationLayer/Customers/ICustomerService.cs +++ b/eCommerce/ApplicationLayer/Customers/ICustomerService.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace eCommerce.ApplicationLayer.Customers { @@ -14,7 +12,6 @@ public interface ICustomerService CustomerDto Get(Guid customerId); CreditCardDto Add(Guid customerId, CreditCardDto creditCard); List GetAllCustomerPurchaseHistoryV1(); - List GetAllCustomerPurchaseHistoryV2(); } -} +} \ No newline at end of file diff --git a/eCommerce/DomainModelLayer/Carts/Cart.cs b/eCommerce/DomainModelLayer/Carts/Cart.cs index 505c2cf..6ee773c 100644 --- a/eCommerce/DomainModelLayer/Carts/Cart.cs +++ b/eCommerce/DomainModelLayer/Carts/Cart.cs @@ -12,41 +12,26 @@ public class Cart : IAggregateRoot { public virtual Guid Id { get; protected set; } - private List cartProducts = new List(); + private readonly List _cartProducts = new List(); - public virtual ReadOnlyCollection Products - { - get { return cartProducts.AsReadOnly(); } - } + public virtual ReadOnlyCollection Products => _cartProducts.AsReadOnly(); public virtual Guid CustomerId { get; protected set; } - public virtual decimal TotalCost - { - get - { - return this.Products.Sum(cartProduct => cartProduct.Quantity * cartProduct.Cost); - } - } + public virtual decimal TotalCost => Products.Sum(cartProduct => cartProduct.Quantity * cartProduct.Cost); - public virtual decimal TotalTax - { - get - { - return this.Products.Sum(cartProducts => cartProducts.Tax); - } - } + public virtual decimal TotalTax => Products.Sum(cartProducts => cartProducts.Tax); public static Cart Create(Customer customer) { if (customer == null) - throw new ArgumentNullException("customer"); + throw new ArgumentNullException(nameof(customer)); Cart cart = new Cart(); cart.Id = Guid.NewGuid(); cart.CustomerId = customer.Id; - DomainEvents.Raise(new CartCreated() { Cart = cart }); + DomainEvents.Raise(new CartCreated { Cart = cart }); return cart; } @@ -56,9 +41,9 @@ public virtual void Add(CartProduct cartProduct) if (cartProduct == null) throw new ArgumentNullException(); - DomainEvents.Raise(new ProductAddedCart() { CartProduct = cartProduct }); + DomainEvents.Raise(new ProductAddedCart { CartProduct = cartProduct }); - this.cartProducts.Add(cartProduct); + _cartProducts.Add(cartProduct); } public virtual void Remove(Product product) @@ -67,16 +52,20 @@ public virtual void Remove(Product product) throw new ArgumentNullException("product"); CartProduct cartProduct = - this.cartProducts.Find(new ProductInCartSpec(product).IsSatisfiedBy); + _cartProducts.Find(new ProductInCartSpec(product).IsSatisfiedBy); - DomainEvents.Raise(new ProductRemovedCart() { CartProduct = cartProduct }); + DomainEvents.Raise(new ProductRemovedCart() { CartProduct = cartProduct }); - this.cartProducts.Remove(cartProduct); + _cartProducts.Remove(cartProduct); } - public virtual void Clear() + public virtual void Clear() => _cartProducts.Clear(); + + public Cart Share(Customer receiver) { - this.cartProducts.Clear(); + var cart = Create(receiver); + Products.ToList().ForEach(product => cart.Add(product)); + return cart; } } } diff --git a/eCommerce/DomainModelLayer/Carts/CartCreated.cs b/eCommerce/DomainModelLayer/Carts/CartCreated.cs index e1b9a60..36adda6 100644 --- a/eCommerce/DomainModelLayer/Carts/CartCreated.cs +++ b/eCommerce/DomainModelLayer/Carts/CartCreated.cs @@ -1,8 +1,4 @@ using eCommerce.Helpers.Domain; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace eCommerce.DomainModelLayer.Carts { diff --git a/eCommerce/DomainModelLayer/Carts/CartProduct.cs b/eCommerce/DomainModelLayer/Carts/CartProduct.cs index c06192f..cd8b072 100644 --- a/eCommerce/DomainModelLayer/Carts/CartProduct.cs +++ b/eCommerce/DomainModelLayer/Carts/CartProduct.cs @@ -1,31 +1,33 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using eCommerce.DomainModelLayer.Products; -using eCommerce.DomainModelLayer.Services; -using eCommerce.Helpers.Domain; using eCommerce.DomainModelLayer.Customers; +using eCommerce.DomainModelLayer.Services; namespace eCommerce.DomainModelLayer.Carts { public class CartProduct { - public virtual Guid CartId { get; protected set; } - public virtual Guid CustomerId { get; protected set; } - public virtual int Quantity { get; protected set; } - public virtual Guid ProductId { get; protected set; } - public virtual DateTime Created { get; protected set; } - public virtual decimal Cost { get; protected set; } - public virtual decimal Tax { get; set; } - - public static CartProduct Create(Customer customer, Cart cart, Product product, int quantity, TaxService taxService) + public virtual Guid CartId { get; private set; } + public virtual Guid CustomerId { get; private set; } + public virtual int Quantity { get; private set; } + public virtual Guid ProductId { get; private set; } + public virtual DateTime Created { get; private set; } + public virtual decimal Cost { get; private set; } + public virtual decimal Tax { get; private set; } + + public static CartProduct Create(Customer customer, Cart cart, Product product, int quantity, ITaxService taxService) { + if (cart == null) + throw new ArgumentNullException(nameof(customer)); + if(cart == null) - throw new ArgumentNullException("cart"); + throw new ArgumentNullException(nameof(cart)); if (product == null) - throw new ArgumentNullException("product"); + throw new ArgumentNullException(nameof(product)); + + if (taxService == null) + throw new ArgumentNullException(nameof(taxService)); CartProduct cartProduct = new CartProduct() { diff --git a/eCommerce/DomainModelLayer/Carts/CheckOutIssue.cs b/eCommerce/DomainModelLayer/Carts/CheckOutIssue.cs index f11e9e5..09b1dc0 100644 --- a/eCommerce/DomainModelLayer/Carts/CheckOutIssue.cs +++ b/eCommerce/DomainModelLayer/Carts/CheckOutIssue.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace eCommerce.DomainModelLayer.Carts +namespace eCommerce.DomainModelLayer.Carts { public enum CheckOutIssue { diff --git a/eCommerce/DomainModelLayer/Carts/CustomerCartSpec.cs b/eCommerce/DomainModelLayer/Carts/CustomerCartSpec.cs index f1f5313..1519434 100644 --- a/eCommerce/DomainModelLayer/Carts/CustomerCartSpec.cs +++ b/eCommerce/DomainModelLayer/Carts/CustomerCartSpec.cs @@ -1,9 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using eCommerce.Helpers.Repository; -using eCommerce.DomainModelLayer.Products; using System.Linq.Expressions; using eCommerce.Helpers.Specification; @@ -11,19 +6,14 @@ namespace eCommerce.DomainModelLayer.Carts { public class CustomerCartSpec : SpecificationBase { - readonly Guid customerId; + private readonly Guid _customerId; public CustomerCartSpec(Guid customerId) { - this.customerId = customerId; + _customerId = customerId; } - public override Expression> SpecExpression - { - get - { - return cart => cart.CustomerId == this.customerId; - } - } + public override Expression> SpecExpression => + cart => cart.CustomerId == _customerId; } -} +} \ No newline at end of file diff --git a/eCommerce/DomainModelLayer/Carts/ProductAddedCart.cs b/eCommerce/DomainModelLayer/Carts/ProductAddedCart.cs index c38e829..e2bf9af 100644 --- a/eCommerce/DomainModelLayer/Carts/ProductAddedCart.cs +++ b/eCommerce/DomainModelLayer/Carts/ProductAddedCart.cs @@ -1,8 +1,4 @@ using eCommerce.Helpers.Domain; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace eCommerce.DomainModelLayer.Carts { @@ -18,4 +14,4 @@ public override void Flatten() this.Args.Add("Quantity", this.CartProduct.Quantity); } } -} +} \ No newline at end of file diff --git a/eCommerce/DomainModelLayer/Carts/ProductInCartSpec.cs b/eCommerce/DomainModelLayer/Carts/ProductInCartSpec.cs index 76941a9..007c5db 100644 --- a/eCommerce/DomainModelLayer/Carts/ProductInCartSpec.cs +++ b/eCommerce/DomainModelLayer/Carts/ProductInCartSpec.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using eCommerce.Helpers.Repository; using eCommerce.DomainModelLayer.Products; using System.Linq.Expressions; using eCommerce.Helpers.Specification; @@ -11,19 +7,14 @@ namespace eCommerce.DomainModelLayer.Carts { public class ProductInCartSpec : SpecificationBase { - readonly Product product; + private readonly Product _product; public ProductInCartSpec(Product product) { - this.product = product; + _product = product; } - public override Expression> SpecExpression - { - get - { - return cartProduct => cartProduct.ProductId == this.product.Id; - } - } + public override Expression> SpecExpression => + cartProduct => cartProduct.ProductId == this._product.Id; } -} +} \ No newline at end of file diff --git a/eCommerce/DomainModelLayer/Carts/ProductRemovedCart.cs b/eCommerce/DomainModelLayer/Carts/ProductRemovedCart.cs index ec1175c..587602e 100644 --- a/eCommerce/DomainModelLayer/Carts/ProductRemovedCart.cs +++ b/eCommerce/DomainModelLayer/Carts/ProductRemovedCart.cs @@ -1,8 +1,4 @@ using eCommerce.Helpers.Domain; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace eCommerce.DomainModelLayer.Carts { diff --git a/eCommerce/DomainModelLayer/Services/ITaxService.cs b/eCommerce/DomainModelLayer/Services/ITaxService.cs new file mode 100644 index 0000000..d8dbe6a --- /dev/null +++ b/eCommerce/DomainModelLayer/Services/ITaxService.cs @@ -0,0 +1,10 @@ +using eCommerce.DomainModelLayer.Customers; +using eCommerce.DomainModelLayer.Products; + +namespace eCommerce.DomainModelLayer.Services +{ + public interface ITaxService + { + decimal Calculate(Customer customer, Product product); + } +} diff --git a/eCommerce/DomainModelLayer/Services/TaxService.cs b/eCommerce/DomainModelLayer/Services/TaxService.cs index 5ba805a..c96d398 100644 --- a/eCommerce/DomainModelLayer/Services/TaxService.cs +++ b/eCommerce/DomainModelLayer/Services/TaxService.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using eCommerce.DomainModelLayer.Customers; using eCommerce.DomainModelLayer.Products; using eCommerce.Helpers.Repository; @@ -11,15 +8,15 @@ namespace eCommerce.DomainModelLayer.Services { - public class TaxService : IDomainService + public class TaxService : IDomainService, ITaxService { - readonly IRepository countryTax; - readonly Settings settings; + readonly IRepository _countryTax; + readonly Settings _settings; public TaxService(Settings settings, IRepository countryTax) { - this.countryTax = countryTax; - this.settings = settings; + _countryTax = countryTax; + _settings = settings; } public decimal Calculate(Customer customer, Product product) @@ -30,8 +27,8 @@ public decimal Calculate(Customer customer, Product product) if (product == null) throw new ArgumentNullException("product"); - CountryTax customerCountryTax = this.countryTax.FindOne(new CountryTypeOfTaxSpec(customer.CountryId, TaxType.Customer)); - CountryTax businessCountryTax = this.countryTax.FindOne(new CountryTypeOfTaxSpec(settings.BusinessCountry.Id, TaxType.Business)); + CountryTax customerCountryTax = this._countryTax.FindOne(new CountryTypeOfTaxSpec(customer.CountryId, TaxType.Customer)); + CountryTax businessCountryTax = this._countryTax.FindOne(new CountryTypeOfTaxSpec(_settings.BusinessCountry.Id, TaxType.Business)); return (product.Cost * customerCountryTax.Percentage) + (product.Cost * businessCountryTax.Percentage); diff --git a/eCommerce/DomainModelLayer/Settings.cs b/eCommerce/DomainModelLayer/Settings.cs index c5ecdf6..e85e53b 100644 --- a/eCommerce/DomainModelLayer/Settings.cs +++ b/eCommerce/DomainModelLayer/Settings.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using eCommerce.DomainModelLayer.Countries; +using eCommerce.DomainModelLayer.Countries; namespace eCommerce.DomainModelLayer { diff --git a/eCommerce/eCommerce.csproj b/eCommerce/eCommerce.csproj index dc7bc9d..fde4b7e 100644 --- a/eCommerce/eCommerce.csproj +++ b/eCommerce/eCommerce.csproj @@ -95,6 +95,7 @@ +