Carlos Cañizares Estévez 8 years ago
parent
commit
9ffc8fa101
41 changed files with 438 additions and 939 deletions
  1. +51
    -51
      eShopOnContainers-ServicesAndWebApps.sln
  2. +2
    -2
      src/Services/Ordering/Ordering.API/Application/Commands/NewOrderCommand.cs
  3. +8
    -8
      src/Services/Ordering/Ordering.API/Application/Commands/NewOrderCommandHandler.cs
  4. +1
    -1
      src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs
  5. +1
    -1
      src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs
  6. +0
    -118
      src/Services/Ordering/Ordering.Application/Commands/NewOrderREquestHandler.cs
  7. +0
    -48
      src/Services/Ordering/Ordering.Application/Commands/NewOrderRequest.cs
  8. +0
    -34
      src/Services/Ordering/Ordering.Application/Decorators/LogDecorator.cs
  9. +0
    -19
      src/Services/Ordering/Ordering.Application/Ordering.Application.xproj
  10. +0
    -19
      src/Services/Ordering/Ordering.Application/Properties/AssemblyInfo.cs
  11. +0
    -13
      src/Services/Ordering/Ordering.Application/Queries/IOrderQueries.cs
  12. +0
    -128
      src/Services/Ordering/Ordering.Application/Queries/OrderQueries.cs
  13. +0
    -21
      src/Services/Ordering/Ordering.Application/project.json
  14. +0
    -5
      src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs
  15. +111
    -0
      src/Web/WebSPA/eShopOnContainers.WebSPA/.sass-lint.yml
  16. +6
    -3
      src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/app.component.html
  17. +2
    -6
      src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/basket/basket.component.html
  18. +1
    -20
      src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/basket/basket.component.scss
  19. +1
    -1
      src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/basket/basket.module.ts
  20. +0
    -4
      src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.component.ts
  21. +0
    -1
      src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.module.ts
  22. +1
    -5
      src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/orders/orders-detail/orders-detail.component.html
  23. +0
    -19
      src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/orders/orders-detail/orders-detail.component.scss
  24. +2
    -6
      src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/orders/orders.component.html
  25. +26
    -0
      src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/orders/orders.component.scss
  26. +1
    -1
      src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/orders/orders.module.ts
  27. +7
    -0
      src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/header/header.html
  28. +21
    -0
      src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/header/header.scss
  29. +11
    -0
      src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/header/header.ts
  30. +34
    -7
      src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/identity/identity.html
  31. +41
    -48
      src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/identity/identity.scss
  32. +7
    -4
      src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/shared.module.ts
  33. +4
    -2
      src/Web/WebSPA/eShopOnContainers.WebSPA/package.json
  34. +0
    -178
      src/Web/WebSPA/eShopOnContainers.WebSPA/tslint.json
  35. +63
    -0
      test/Services/FunctionalTests/Services/Basket/RedisBasketRepositoryTests.cs
  36. +1
    -1
      test/Services/FunctionalTests/Services/Catalog/CatalogScenarioBase.cs
  37. +2
    -2
      test/Services/FunctionalTests/Services/Catalog/CatalogScenarios.cs
  38. +1
    -1
      test/Services/FunctionalTests/Services/Ordering/OrderingScenarios.cs
  39. +5
    -2
      test/Services/FunctionalTests/project.json
  40. +27
    -24
      test/Services/UnitTest/Ordering/Application/NewOrderCommandHandlerTest.cs
  41. +0
    -136
      test/Services/UnitTest/Ordering/Controllers/OrderControllerTest.cs

+ 51
- 51
eShopOnContainers-ServicesAndWebApps.sln View File

@ -39,12 +39,12 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "eShopOnContainers.WebMVC",
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "eShopOnContainers.WebSPA", "src\Web\WebSPA\eShopOnContainers.WebSPA\eShopOnContainers.WebSPA.xproj", "{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Ordering.Application", "src\Services\Ordering\Ordering.Application\Ordering.Application.xproj", "{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Ordering.Infrastructure", "src\Services\Ordering\Ordering.Infrastructure\Ordering.Infrastructure.xproj", "{95F1F07C-4D92-4742-BD07-E5B805AAB651}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "FunctionalTests", "test\Services\FunctionalTests\FunctionalTests.xproj", "{621E7211-58D0-45FD-9600-1CB490BD930E}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "UnitTest", "test\Services\UnitTest\UnitTest.xproj", "{7796F5D8-31FC-45A4-B673-19DE5BA194CF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
@ -251,54 +251,6 @@ Global
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Release|x64.Build.0 = Release|Any CPU
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Release|x86.ActiveCfg = Release|Any CPU
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2}.Release|x86.Build.0 = Release|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.AppStore|ARM.ActiveCfg = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.AppStore|ARM.Build.0 = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.AppStore|iPhone.Build.0 = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.AppStore|x64.ActiveCfg = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.AppStore|x64.Build.0 = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.AppStore|x86.ActiveCfg = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.AppStore|x86.Build.0 = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Debug|ARM.ActiveCfg = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Debug|ARM.Build.0 = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Debug|iPhone.Build.0 = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Debug|x64.ActiveCfg = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Debug|x64.Build.0 = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Debug|x86.ActiveCfg = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Debug|x86.Build.0 = Debug|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Release|Any CPU.Build.0 = Release|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Release|ARM.ActiveCfg = Release|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Release|ARM.Build.0 = Release|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Release|iPhone.ActiveCfg = Release|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Release|iPhone.Build.0 = Release|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Release|x64.ActiveCfg = Release|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Release|x64.Build.0 = Release|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Release|x86.ActiveCfg = Release|Any CPU
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7}.Release|x86.Build.0 = Release|Any CPU
{95F1F07C-4D92-4742-BD07-E5B805AAB651}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{95F1F07C-4D92-4742-BD07-E5B805AAB651}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{95F1F07C-4D92-4742-BD07-E5B805AAB651}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
@ -395,6 +347,54 @@ Global
{621E7211-58D0-45FD-9600-1CB490BD930E}.Release|x64.Build.0 = Release|Any CPU
{621E7211-58D0-45FD-9600-1CB490BD930E}.Release|x86.ActiveCfg = Release|Any CPU
{621E7211-58D0-45FD-9600-1CB490BD930E}.Release|x86.Build.0 = Release|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.AppStore|ARM.ActiveCfg = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.AppStore|ARM.Build.0 = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.AppStore|iPhone.Build.0 = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.AppStore|x64.ActiveCfg = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.AppStore|x64.Build.0 = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.AppStore|x86.ActiveCfg = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.AppStore|x86.Build.0 = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Debug|ARM.ActiveCfg = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Debug|ARM.Build.0 = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Debug|iPhone.Build.0 = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Debug|x64.ActiveCfg = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Debug|x64.Build.0 = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Debug|x86.ActiveCfg = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Debug|x86.Build.0 = Debug|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Release|Any CPU.Build.0 = Release|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Release|ARM.ActiveCfg = Release|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Release|ARM.Build.0 = Release|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Release|iPhone.ActiveCfg = Release|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Release|iPhone.Build.0 = Release|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Release|x64.ActiveCfg = Release|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Release|x64.Build.0 = Release|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Release|x86.ActiveCfg = Release|Any CPU
{7796F5D8-31FC-45A4-B673-19DE5BA194CF}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -412,8 +412,8 @@ Global
{EF0337F2-ED00-4643-89FD-EE10863F1870} = {A857AD10-40FF-4303-BEC2-FF1C58D5735E}
{F0333D8E-0B27-42B7-B2C6-78F3657624E2} = {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04}
{9842DB3A-1391-48C7-A49C-2FABD0A18AC2} = {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04}
{4193CAA3-A1C3-4818-A06F-A2D85FDE77E7} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B}
{95F1F07C-4D92-4742-BD07-E5B805AAB651} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B}
{621E7211-58D0-45FD-9600-1CB490BD930E} = {EF0337F2-ED00-4643-89FD-EE10863F1870}
{7796F5D8-31FC-45A4-B673-19DE5BA194CF} = {EF0337F2-ED00-4643-89FD-EE10863F1870}
EndGlobalSection
EndGlobal

src/Services/Ordering/Ordering.API/Application/Commands/NewOrderRequest.cs → src/Services/Ordering/Ordering.API/Application/Commands/NewOrderCommand.cs View File

@ -6,7 +6,7 @@
using System.Collections;
using System.Collections.Generic;
public class NewOrderRequest
public class NewOrderCommand
:IAsyncRequest<bool>
{
@ -40,7 +40,7 @@
_orderItems.Add(item);
}
public NewOrderRequest()
public NewOrderCommand()
{
_orderItems = new List<OrderItem>();
}

src/Services/Ordering/Ordering.API/Application/Commands/NewOrderRequestHandler.cs → src/Services/Ordering/Ordering.API/Application/Commands/NewOrderCommandHandler.cs View File

@ -7,13 +7,13 @@
using System.Threading.Tasks;
using Domain;
public class NewOrderRequestHandler
: IAsyncRequestHandler<NewOrderRequest, bool>
public class NewOrderCommandHandler
: IAsyncRequestHandler<NewOrderCommand, bool>
{
private readonly IBuyerRepository _buyerRepository;
private readonly IOrderRepository _orderRepository;
public NewOrderRequestHandler(IBuyerRepository buyerRepository,IOrderRepository orderRepository)
public NewOrderCommandHandler(IBuyerRepository buyerRepository,IOrderRepository orderRepository)
{
if (buyerRepository == null)
{
@ -28,7 +28,7 @@
_buyerRepository = buyerRepository;
_orderRepository = orderRepository;
}
public async Task<bool> Handle(NewOrderRequest message)
public async Task<bool> Handle(NewOrderCommand message)
{
//find buyer/payment or add a new one buyer/payment
@ -70,7 +70,7 @@
Payment GetExistingPaymentOrAddANewOne(Buyer buyer, NewOrderRequest message)
Payment GetExistingPaymentOrAddANewOne(Buyer buyer, NewOrderCommand message)
{
Payment payment = PaymentAlreadyExist(buyer, message);
@ -84,7 +84,7 @@
}
Payment PaymentAlreadyExist(Domain.Buyer buyer, NewOrderRequest message)
Payment PaymentAlreadyExist(Domain.Buyer buyer, NewOrderCommand message)
{
return buyer.Payments
.SingleOrDefault(p =>
@ -99,7 +99,7 @@
});
}
Buyer CreateBuyer(NewOrderRequest message)
Buyer CreateBuyer(NewOrderCommand message)
{
return _buyerRepository.Add(
new Buyer(message.Buyer));
@ -110,7 +110,7 @@
return new Order(buyerId, paymentId);
}
Payment CreatePayment(NewOrderRequest message)
Payment CreatePayment(NewOrderCommand message)
{
return new Payment(message.CardNumber, message.CardSecurityNumber, message.CardHolderName, message.CardExpiration, message.CardTypeId);
}

+ 1
- 1
src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs View File

@ -43,7 +43,7 @@
[Route("new")]
[HttpPost]
public async Task<IActionResult> AddOrder([FromBody]NewOrderRequest order)
public async Task<IActionResult> AddOrder([FromBody]NewOrderCommand order)
{
if (order.CardTypeId == 0)
order.CardTypeId = 1;


+ 1
- 1
src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs View File

@ -16,7 +16,7 @@
builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly)
.AsImplementedInterfaces();
builder.RegisterAssemblyTypes(typeof(NewOrderRequest).GetTypeInfo().Assembly)
builder.RegisterAssemblyTypes(typeof(NewOrderCommand).GetTypeInfo().Assembly)
.As(o => o.GetInterfaces()
.Where(i => i.IsClosedTypeOf(typeof(IAsyncRequestHandler<,>)))
.Select(i => new KeyedService("IAsyncRequestHandler", i)));


+ 0
- 118
src/Services/Ordering/Ordering.Application/Commands/NewOrderREquestHandler.cs View File

@ -1,118 +0,0 @@
namespace Microsoft.eShopOnContainers.Services.Ordering.Application.Commands
{
using Domain.Repositories;
using MediatR;
using System.Linq;
using System;
using System.Threading.Tasks;
using Domain;
public class NewOrderRequestHandler
: IAsyncRequestHandler<NewOrderRequest, bool>
{
private readonly IBuyerRepository _buyerRepository;
private readonly IOrderRepository _orderRepository;
public NewOrderRequestHandler(IBuyerRepository buyerRepository,IOrderRepository orderRepository)
{
if (buyerRepository == null)
{
throw new ArgumentNullException(nameof(buyerRepository));
}
if (orderRepository == null)
{
throw new ArgumentNullException(nameof(orderRepository));
}
_buyerRepository = buyerRepository;
_orderRepository = orderRepository;
}
public async Task<bool> Handle(NewOrderRequest message)
{
//find buyer/payment or add a new one buyer/payment
var buyer = await _buyerRepository.FindAsync(message.Buyer);
if (buyer == null)
{
buyer = CreateBuyer(message);
}
var payment = GetExistingPaymentOrAddANewOne(buyer, message);
await _buyerRepository.UnitOfWork
.SaveChangesAsync();
//create order for buyer and payment method
var order = CreateOrder(buyer.Id, payment.Id, 0);
order.SetAddress( new Address()
{
City = message.City,
State = message.State,
Street = message.Street,
ZipCode = message.ZipCode
});
foreach (var item in message.OrderItems)
{
order.AddOrderItem(item);
}
_orderRepository.Add(order);
var result = await _orderRepository.UnitOfWork
.SaveChangesAsync();
return result > 0;
}
Payment GetExistingPaymentOrAddANewOne(Buyer buyer, NewOrderRequest message)
{
Payment payment = PaymentAlreadyExist(buyer, message);
if (payment == null)
{
payment = CreatePayment(message);
buyer.Payments.Add(payment);
}
return payment;
}
Payment PaymentAlreadyExist(Domain.Buyer buyer, NewOrderRequest message)
{
return buyer.Payments
.SingleOrDefault(p =>
{
return p.CardHolderName == message.CardHolderName
&&
p.CardNumber == message.CardNumber
&&
p.Expiration == message.CardExpiration
&&
p.SecurityNumber == message.CardSecurityNumber;
});
}
Buyer CreateBuyer(NewOrderRequest message)
{
return _buyerRepository.Add(
new Buyer(message.Buyer));
}
Order CreateOrder(int buyerId, int paymentId, int addressId)
{
return new Order(buyerId, paymentId);
}
Payment CreatePayment(NewOrderRequest message)
{
return new Payment(message.CardNumber, message.CardSecurityNumber, message.CardHolderName, message.CardExpiration, message.CardTypeId);
}
}
}

+ 0
- 48
src/Services/Ordering/Ordering.Application/Commands/NewOrderRequest.cs View File

@ -1,48 +0,0 @@
namespace Microsoft.eShopOnContainers.Services.Ordering.Application.Commands
{
using System;
using MediatR;
using Domain;
using System.Collections;
using System.Collections.Generic;
public class NewOrderRequest
:IAsyncRequest<bool>
{
private readonly List<OrderItem> _orderItems;
public string City { get; set; }
public string Street { get; set; }
public string State { get; set; }
public string Country { get; set; }
public string ZipCode { get; set; }
public string CardNumber { get; set; }
public string CardHolderName { get; set; }
public DateTime CardExpiration { get; set; }
public string CardSecurityNumber { get; set; }
public int CardTypeId { get; set; }
public string Buyer { get; set; }
public IEnumerable<OrderItem> OrderItems => _orderItems;
public void AddOrderItem(OrderItem item)
{
_orderItems.Add(item);
}
public NewOrderRequest()
{
_orderItems = new List<OrderItem>();
}
}
}

+ 0
- 34
src/Services/Ordering/Ordering.Application/Decorators/LogDecorator.cs View File

@ -1,34 +0,0 @@
namespace Microsoft.eShopOnContainers.Services.Ordering.Application.Decorators
{
using Extensions.Logging;
using MediatR;
using System.Threading.Tasks;
public class LogDecorator<TRequest, TResponse>
: IAsyncRequestHandler<TRequest, TResponse>
where TRequest : IAsyncRequest<TResponse>
{
private readonly IAsyncRequestHandler<TRequest, TResponse> _inner;
private readonly ILogger<LogDecorator<TRequest, TResponse>> _logger;
public LogDecorator(
IAsyncRequestHandler<TRequest, TResponse> inner,
ILogger<LogDecorator<TRequest, TResponse>> logger)
{
_inner = inner;
_logger = logger;
}
public async Task<TResponse> Handle(TRequest message)
{
_logger.LogInformation($"Executing command {_inner.GetType().FullName}");
var response = await _inner.Handle(message);
_logger.LogInformation($"Succedded executed command {_inner.GetType().FullName}");
return response;
}
}
}

+ 0
- 19
src/Services/Ordering/Ordering.Application/Ordering.Application.xproj View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>4193caa3-a1c3-4818-a06f-a2d85fde77e7</ProjectGuid>
<RootNamespace>Microsoft.eShopOnContainers.Services.Ordering.Application</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

+ 0
- 19
src/Services/Ordering/Ordering.Application/Properties/AssemblyInfo.cs View File

@ -1,19 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Ordering.Application")]
[assembly: AssemblyTrademark("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("4193caa3-a1c3-4818-a06f-a2d85fde77e7")]

+ 0
- 13
src/Services/Ordering/Ordering.Application/Queries/IOrderQueries.cs View File

@ -1,13 +0,0 @@
namespace Microsoft.eShopOnContainers.Services.Ordering.Application.Queries
{
using System.Threading.Tasks;
public interface IOrderQueries
{
Task<dynamic> GetOrder(int id);
Task<dynamic> GetOrders();
Task<dynamic> GetCardTypes();
}
}

+ 0
- 128
src/Services/Ordering/Ordering.Application/Queries/OrderQueries.cs View File

@ -1,128 +0,0 @@
namespace Microsoft.eShopOnContainers.Services.Ordering.Application.Queries
{
using Dapper;
using Microsoft.Extensions.Configuration;
using System.Data.SqlClient;
using System.Threading.Tasks;
using System;
using System.Dynamic;
using System.Collections.Generic;
using System.Linq;
public class OrderQueries
: IOrderQueries
{
private string _connectionString = string.Empty;
public OrderQueries(IConfiguration configuration)
{
_connectionString = configuration["ConnectionString"];
}
public async Task<dynamic> GetOrder(int id)
{
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
var result = await connection.QueryAsync<dynamic>(
@"select o.[Id] as ordernumber,o.OrderDate as date, os.Name as status,
oi.ProductName as productname, oi.Units as units, oi.UnitPrice as unitprice, oi.PictureUrl as pictureurl,
oa.Street as street, oa.City as city, oa.Country as country, oa.State as state, oa.ZipCode as zipcode
FROM ordering.Orders o
LEFT JOIN ordering.Orderitems oi ON o.Id = oi.orderid
LEFT JOIN ordering.orderstatus os on o.StatusId = os.Id
LEFT JOIN ordering.address oa on o.ShippingAddressId = oa.Id
WHERE o.Id=@id"
, new { id }
);
if (result.AsList().Count == 0)
throw new KeyNotFoundException();
return MapOrderItems(result);
}
}
public async Task<dynamic> GetOrders()
{
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
return await connection.QueryAsync<dynamic>(@"SELECT o.[Id] as ordernumber,o.[OrderDate] as [date],os.[Name] as [status],SUM(oi.units*oi.unitprice) as total
FROM [ordering].[Orders] o
LEFT JOIN[ordering].[orderitems] oi ON o.Id = oi.orderid
LEFT JOIN[ordering].[orderstatus] os on o.StatusId = os.Id
GROUP BY o.[Id], o.[OrderDate], os.[Name]");
}
}
public async Task<dynamic> GetCardTypes()
{
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
return await connection.QueryAsync<dynamic>("SELECT * FROM ordering.cardtypes");
}
}
private dynamic MapOrderItems(dynamic result)
{
dynamic order = new ExpandoObject();
order.ordernumber = result[0].ordernumber;
order.date = result[0].date;
order.status = result[0].status;
order.street = result[0].street;
order.city = result[0].city;
order.zipcode = result[0].zipcode;
order.country = result[0].country;
order.orderitems = new List<dynamic>();
order.total = 0;
foreach (dynamic item in result)
{
dynamic orderitem = new ExpandoObject();
orderitem.productname = item.productname;
orderitem.units = item.units;
orderitem.unitprice = item.unitprice;
orderitem.pictureurl = item.pictureurl;
order.total += item.units * item.unitprice;
order.orderitems.Add(orderitem);
}
return order;
}
//TODO/CCE: try to use this method instead actual.
//private object MapOrderItems(dynamic result)
//{
// IEnumerable<dynamic> items = (result as System.Collections.IEnumerable).Cast<dynamic>();
// var order = new
// {
// ordernumber = result[0].ordernumbe,
// date = result[0].date,
// status = result[0].status,
// street = result[0].street,
// city = result[0].city,
// zipcode = result[0].zipcode,
// country = result[0].country,
// total = items.Select(r => (int)r.units * (int)r.unitprice).Sum(),
// orderItems = items.Select(r => new
// {
// productname = r.productname,
// units = r.units,
// unitprice = r.unitprice,
// pictureurl = r.pictureurl
// })
// };
// return order;
//}
}
}

+ 0
- 21
src/Services/Ordering/Ordering.Application/project.json View File

@ -1,21 +0,0 @@
{
"version": "1.0.0-*",
"dependencies": {
"NETStandard.Library": "1.6.0",
"MediatR": "2.1.0",
"Dapper": "1.50.2",
"System.Dynamic.Runtime": "4.0.11",
"Microsoft.CSharp": "4.0.1",
"Microsoft.Extensions.Configuration": "1.0.0",
"System.Data.SqlClient": "4.1.0",
"Microsoft.Extensions.Logging.Abstractions": "1.0.0",
"Ordering.Domain": "1.0.0-*"
},
"frameworks": {
"netstandard1.6": {
"imports": "dnxcore50"
}
}
}

+ 0
- 5
src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs View File

@ -39,13 +39,8 @@
modelBuilder.Entity<CardType>(ConfigureCardTypes);
modelBuilder.Entity<OrderStatus>(ConfigureOrderStatus);
modelBuilder.Entity<Address>(ConfigureAddress);
modelBuilder.Entity<Address>()
.ToTable("address", DEFAULT_SCHEMA);
}
void ConfigureBuyer(EntityTypeBuilder<Buyer> buyerConfiguration)
{
buyerConfiguration.ToTable("buyers", DEFAULT_SCHEMA);


+ 111
- 0
src/Web/WebSPA/eShopOnContainers.WebSPA/.sass-lint.yml View File

@ -0,0 +1,111 @@
rules:
# https://github.com/sasstools/sass-lint/tree/master/docs/rules
# 0 = disabled - 1 = warning - 2 = error
# Extends
extends-before-mixins: 1
extends-before-declarations: 2
placeholder-in-extend: 0
# Mixins
mixins-before-declarations: 2
# Line Spacing
one-declaration-per-line: 2
empty-line-between-blocks: 2
single-line-per-selector: 2
# Disallows
# We disable some of that because we know that
# if you use it is because is necessary
no-attribute-selectors: 0
no-color-hex: 0
no-color-keywords: 2
no-color-literals: 0
no-combinators: 0
no-css-comments: 0
no-debug: 1
no-disallowed-properties: 0
no-duplicate-properties: 2
no-empty-rulesets: 1
no-extends: 0
no-ids: 2
no-important: 0
no-invalid-hex: 2
no-mergeable-selectors: 1
no-misspelled-properties: 2
no-qualifying-elements: 0
no-trailing-whitespace: 2
no-trailing-zero: 2
no-transition-all: 0
no-universal-selectors: 0
no-url-domains: 0
no-url-protocols: 0
no-vendor-prefixes: 2
no-warn: 2
property-units: 0
# Nesting
declarations-before-nesting: 2
force-attribute-nesting: 0
force-element-nesting: 0
force-pseudo-nesting: 0
# Name Formats
class-name-format: 0
function-name-format: 0
id-name-format: 0
mixin-name-format: 0
placeholder-name-format:
- 1
- allow-leading-underscore: true
- convention: hyphenatedlowercase
variable-name-format:
- 1
- allow-leading-underscore: true
- convention: hyphenatedlowercase
# Style Guide
attribute-quotes: 2
# We know that always 1 level
bem-depth: 0
border-zero: 2
brace-style:
- 2
- style: 1tbs
clean-import-paths: 2
empty-args: 2
hex-length:
- 2
- style: long
hex-notation:
- 2
- style: uppercase
indentation:
- 2
- size: 4
leading-zero: 2
max-line-length: 0
max-file-line-count: 0
nesting-depth: 0
# alphabetically
property-sort-order: 2
pseudo-element: 0
quotes: 2
shorthand-values: 0
url-quotes: 0
variable-for-property: 0
zero-unit: 2
# Inner Spacing
space-after-comma: 2
space-before-colon: 2
space-after-colon: 2
space-before-brace: 2
space-before-bang: 2
space-after-bang: 2
space-between-parens: 2
space-around-operator: 2
# Final Items
trailing-semicolon: 2
final-newline: 2

+ 6
- 3
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/app.component.html View File

@ -2,17 +2,20 @@
<div class="container">
<article class="row">
<section class="col-sm-10">
<section class="col-lg-7 col-md-6 col-xs-12">
<a class="navbar-brand" routerLink="catalog">
<img src="../images/brand.png" />
</a>
</section>
<section class="col-sm-2">
<esh-basket-status *ngIf="Authenticated"></esh-basket-status>
<section class="col-lg-4 col-md-5 col-xs-12">
<esh-identity></esh-identity>
</section>
<section class="col-lg-1 col-xs-12">
<esh-basket-status *ngIf="Authenticated"></esh-basket-status>
</section>
</article>
</div>
</header>


+ 2
- 6
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/basket/basket.component.html View File

@ -1,9 +1,5 @@
<div class="esh-basket">
<div class="esh-basket-header">
<div class="container">
<a class="esh-basket-back" routerLink="/catalog">Back to catalog</a>
</div>
</div>
<esh-header url="/catalog">Back to catalog</esh-header>
<div class="container">
<article class="esh-basket-titles row">
@ -29,7 +25,7 @@
[(ngModel)]="item.quantity"
(change)="itemQuantityChanged(item)" />
</section>
<section class="esh-basket-item esh-basket-item--middle col-xs-2">$ {{item.unitPrice * item.quantity}}</section>
<section class="esh-basket-item esh-basket-item--middle esh-basket-item--mark col-xs-2">$ {{item.unitPrice * item.quantity}}</section>
</article>
</div>


+ 1
- 20
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/basket/basket.component.scss View File

@ -3,25 +3,6 @@
.esh-basket {
min-height: 80vh;
$header-height: 4rem;
&-header {
background-color: #00A69C;
height: $header-height;
}
&-back {
color: rgba($color-foreground-brighter, .4);
line-height: $header-height;
text-transform: uppercase;
text-decoration: none;
transition: color $animation-speed-default;
&:hover {
color: $color-foreground-brighter;
transition: color $animation-speed-default;
}
}
&-titles {
padding-bottom: 1rem;
padding-top: 2rem;
@ -61,7 +42,7 @@
}
&--mark {
color: $color-secondary;
color: $color-brand;
}
}


+ 1
- 1
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/basket/basket.module.ts View File

@ -4,8 +4,8 @@ import { BrowserModule } from '@angular/platform-browser';
import { SharedModule } from '../shared/shared.module';
import { BasketComponent } from './basket.component';
import { BasketStatusComponent } from './basket-status/basket-status.component';
//import { routing } from './basket.routes';
import { BasketService } from './basket.service';
import { Header } from '../shared/components/header/header';
@NgModule({
imports: [SharedModule],


+ 0
- 4
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.component.ts View File

@ -57,7 +57,6 @@ export class CatalogComponent implements OnInit {
getCatalog(pageSize:number, pageIndex: number, brand?: number, type?: number) {
this.service.getCatalog(pageIndex, pageSize, brand, type).subscribe(catalog => {
this.catalog = catalog;
//console.log('catalog items retrieved: ' + catalog.count);
this.paginationInfo = {
actualPage : catalog.pageIndex,
@ -67,7 +66,6 @@ export class CatalogComponent implements OnInit {
items: catalog.pageSize
};
//console.log(this.paginationInfo);
});
}
@ -76,7 +74,6 @@ export class CatalogComponent implements OnInit {
this.types = types;
let alltypes = { id: null, type: 'All' };
this.types.unshift(alltypes);
//console.log('types retrieved: ' + types.length);
});
}
@ -85,7 +82,6 @@ export class CatalogComponent implements OnInit {
this.brands = brands;
let allBrands = { id: null, brand: 'All' };
this.brands.unshift(allBrands);
//console.log('brands retrieved: ' + brands.length);
});
}
}


+ 0
- 1
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.module.ts View File

@ -3,7 +3,6 @@ import { BrowserModule } from '@angular/platform-browser';
import { SharedModule } from '../shared/shared.module';
import { CatalogComponent } from './catalog.component';
//import { routing } from './catalog.routes';
import { CatalogService } from './catalog.service';
import { Pager } from '../shared/components/pager/pager';


+ 1
- 5
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/orders/orders-detail/orders-detail.component.html View File

@ -1,9 +1,5 @@
<div class="esh-orders_detail">
<div class="esh-orders_detail-header">
<div class="container">
<a class="esh-orders_detail-back" routerLink="/orders">Back to list</a>
</div>
</div>
<esh-header url="/orders">Back to list</esh-header>
<div class="container">
<section class="esh-orders_detail-section">


+ 0
- 19
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/orders/orders-detail/orders-detail.component.scss View File

@ -3,25 +3,6 @@
.esh-orders_detail {
min-height: 80vh;
$header-height: 4rem;
&-header {
background-color: #00A69C;
height: $header-height;
}
&-back {
color: rgba($color-foreground-brighter, .4);
line-height: $header-height;
text-transform: uppercase;
text-decoration: none;
transition: color $animation-speed-default;
&:hover {
color: $color-foreground-brighter;
transition: color $animation-speed-default;
}
}
&-section {
padding: 1rem 0;


+ 2
- 6
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/orders/orders.component.html View File

@ -1,9 +1,5 @@
<div class="esh-orders">
<div class="esh-orders-header">
<div class="container">
<a class="esh-orders-back" routerLink="/catalog">Back to catalog</a>
</div>
</div>
<esh-header url="/catalog">Back to catalog</esh-header>
<div class="container">
<article class="esh-orders-titles row">
@ -20,7 +16,7 @@
<section class="esh-orders-item col-xs-4">{{order.date | date:'short'}}</section>
<section class="esh-orders-item col-xs-2">$ {{order.total}}</section>
<section class="esh-orders-item col-xs-2">{{order.status}}</section>
<section class="esh-orders-item col-xs-2">
<section class="esh-orders-item esh-orders-item--hover col-xs-2">
<a class="esh-orders-link" routerLink="/orders/{{order.ordernumber}}">Detail</a>
</section>
</article>


+ 26
- 0
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/orders/orders.component.scss View File

@ -2,6 +2,7 @@
.esh-orders {
min-height: 80vh;
overflow-x: hidden;
$header-height: 4rem;
&-header {
@ -35,10 +36,35 @@
$height: 2rem;
height: $height;
line-height: $height;
position: relative;
&:nth-of-type(2n + 1) {
&:before {
background-color: $color-background-bright;
content: '';
height: 100%;
left: 0;
margin-left: -100vw;
position: absolute;
top: 0;
width: 200vw;
z-index: -1;
}
}
}
&-item {
font-weight: $font-weight-semilight;
&--hover {
opacity: 0;
pointer-events: none;
}
}
&-items:hover &-item--hover {
opacity: 1;
pointer-events: all;
}
&-link {


+ 1
- 1
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/orders/orders.module.ts View File

@ -6,7 +6,7 @@ import { OrdersComponent } from './orders.component';
import { OrdersDetailComponent } from './orders-detail/orders-detail.component';
import { OrdersNewComponent } from './orders-new/orders-new.component';
import { OrdersService } from './orders.service';
import { Pager } from '../shared/components/pager/pager';
import { Header } from '../shared/components/header/header';
@NgModule({
imports: [BrowserModule, SharedModule],


+ 7
- 0
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/header/header.html View File

@ -0,0 +1,7 @@
<div class="esh-header">
<div class="container">
<a class="esh-header-back" routerLink="{{url}}">
<ng-content></ng-content>
</a>
</div>
</div>

+ 21
- 0
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/header/header.scss View File

@ -0,0 +1,21 @@
@import "../../../variables";
.esh-header {
$header-height: 4rem;
background-color: $color-brand;
height: $header-height;
&-back {
color: rgba($color-foreground-brighter, .5);
line-height: $header-height;
text-transform: uppercase;
text-decoration: none;
transition: color $animation-speed-default;
&:hover {
color: $color-foreground-brighter;
transition: color $animation-speed-default;
}
}
}

+ 11
- 0
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/header/header.ts View File

@ -0,0 +1,11 @@
import { Component, Input } from '@angular/core';
@Component({
selector: 'esh-header',
templateUrl: './header.html',
styleUrls: ['./header.scss']
})
export class Header {
@Input()
url: string;
}

+ 34
- 7
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/identity/identity.html View File

@ -1,8 +1,35 @@
<button *ngIf="!authenticated" class="identity-login" (click)="login()">Login</button>
<div *ngIf="authenticated" class="identity-user">
<div><span>{{userName}}</span></div><div style="float: right;top: 0;right: -15px;position: absolute;"><img src="../../../../images/arrow-down.png" class="identity-downArrow"></div>
<div class="identity-userDropdown">
<div [routerLink]="['orders']">MY ORDERS<img src="../../../../images/my_orders.png"></div>
<div (click)="logoutClicked($event)">LOG OUT<img src="../../../../images/logout.png"></div>
</div>
<div class="esh-identity">
<section class="esh-identity-section"
*ngIf="!authenticated">
<div class="esh-identity-item"
(click)="login()">
<div class="esh-identity-name esh-identity-name--upper">Login</div>
</div>
</section>
<section class="esh-identity-section"
*ngIf="authenticated">
<div class="esh-identity-name">{{userName}}</div>
<img class="esh-identity-image" src="../../../../images/arrow-down.png">
</section>
<section class="esh-identity-drop"
*ngIf="authenticated">
<div class="esh-identity-item"
[routerLink]="['orders']">
<div class="esh-identity-name esh-identity-name--upper">My orders</div>
<img class="esh-identity-image" src="../../../../images/my_orders.png">
</div>
<div class="esh-identity-item"
(click)="logoutClicked($event)">
<div class="esh-identity-name esh-identity-name--upper">Log Out</div>
<img class="esh-identity-image" src="../../../../images/logout.png">
</div>
</section>
</div>

+ 41
- 48
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/identity/identity.scss View File

@ -1,63 +1,56 @@
.identity {
&-user {
position: absolute !important;
top: 30px;
right: 120px;
cursor: pointer;
@import "../../../variables";
&:hover .identity-userDropdown {
display: block;
}
}
.esh-identity {
line-height: 3rem;
position: relative;
text-align: right;
&-userDropdown {
display: none;
position: absolute;
background-color: #FFFFFF;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
right: -15px;
z-index: 3;
&-section {
display: inline-block;
width: 100%;
}
&:hover {
display: block;
}
&-name {
display: inline-block;
& div {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: right;
&--upper {
text-transform: uppercase;
}
&:hover {
color: #83d01b;
}
@media screen and (max-width: $media-screen-s) {
font-size: $font-size-s;
}
}
&-downArrow {
height: 7px;
width: 10px;
&-image {
display: inline-block;
margin-left: 20px;
}
&:hover > identity.userDropdown {
display: block;
}
&-drop {
background: $color-background-brighter;
height: 0;
min-width: 14rem;
right: 0;
overflow: hidden;
padding: .5rem;
position: absolute;
top: 2.5rem;
transition: height $animation-speed-default;
}
&:hover &-drop {
border: $border-light solid $color-foreground-bright;
height: 7rem;
transition: height $animation-speed-default;
}
&-login {
border: 1px solid #00a69c;
height: 36px !important;
margin-right: 10px;
margin-top: 10px;
background-color: #fff;
color: #00a69c;
text-transform: uppercase;
max-width: 140px;
width: 140px;
padding-top: 8px !important;
&-item {
cursor: pointer;
transition: color $animation-speed-default;
&:hover {
color: $color-secondary-dark;
transition: color $animation-speed-default;
}
}
}

+ 7
- 4
src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/shared.module.ts View File

@ -20,8 +20,9 @@ import { BasketWrapperService} from './services/basket.wrapper.service';
import { SecurityService } from './services/security.service';
//Components:
import {Pager } from './components/pager/pager';
import {Identity } from './components/identity/identity';
import { Pager } from './components/pager/pager';
import { Header } from './components/header/header';
import { Identity } from './components/identity/identity';
@NgModule({
imports: [
@ -41,7 +42,8 @@ import {Identity } from './components/identity/identity';
ErrorSummaryComponent,
PageHeadingComponent,
UppercasePipe,
Pager,
Pager,
Header,
Identity
],
exports: [
@ -60,7 +62,8 @@ import {Identity } from './components/identity/identity';
//HeaderComponent,
PageHeadingComponent,
UppercasePipe,
Pager,
Pager,
Header,
Identity
]
})


+ 4
- 2
src/Web/WebSPA/eShopOnContainers.WebSPA/package.json View File

@ -29,9 +29,10 @@
"build:main": "node node_modules/webpack/bin/webpack.js --config config/webpack.config.js",
"setdev": "set ASPNETCORE_ENVIRONMENT=Development",
"setprod": "set ASPNETCORE_ENVIRONMENT=Production",
"build:dev": "npm run setdev && npm run clean:dist && npm run build:vendor && npm run build:main",
"build:dev": "npm run lint:sass && npm run setdev && npm run clean:dist && npm run build:vendor && npm run build:main",
"build:prod": "npm run setprod && npm run clean:dist && npm run build:vendor && npm run build:main",
"version": "npm run build"
"version": "npm run build",
"lint:sass": "sass-lint -c .sass-lint.yml Client/**/*.scss --verbose"
},
"dependencies": {
"@angular/common": "2.1.2",
@ -87,6 +88,7 @@
"node-sass": "3.9.3",
"parse5": "2.1.5",
"rimraf": "2.5.4",
"sass-lint": "^1.10.2",
"sass-loader": "4.0.2",
"ts-helpers": "1.1.1",
"ts-node": "1.4.3",


+ 0
- 178
src/Web/WebSPA/eShopOnContainers.WebSPA/tslint.json View File

@ -1,178 +0,0 @@
{
"rulesDirectory": [
"node_modules/codelyzer"
],
"rules": {
"directive-selector-name": [
true,
"camelCase"
],
"component-selector-name": [
true,
"kebab-case"
],
"directive-selector-type": [
true,
"attribute"
],
"component-selector-type": [
true,
"element"
],
"directive-selector-prefix": [
true,
"appd"
],
"component-selector-prefix": [
true,
"appc"
],
"use-input-property-decorator": true,
"use-output-property-decorator": true,
"use-host-property-decorator": true,
"no-attribute-parameter-decorator": true,
"no-input-rename": true,
"no-output-rename": true,
"no-forward-ref": true,
"use-life-cycle-interface": true,
"use-pipe-transform-interface": true,
"pipe-naming": [
true,
"camelCase",
"appf"
],
"component-class-suffix": true,
"directive-class-suffix": true,
"import-destructuring-spacing": true,
"member-access": false,
"member-ordering": [
true,
"public-before-private",
"static-before-instance",
"variables-before-functions"
],
"no-any": false,
"no-inferrable-types": false,
"no-internal-module": true,
"no-var-requires": false,
"typedef": false,
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
},
{
"call-signature": "space",
"index-signature": "space",
"parameter": "space",
"property-declaration": "space",
"variable-declaration": "space"
}
],
"ban": false,
"curly": false,
"forin": true,
"label-position": true,
"label-undefined": true,
"no-arg": true,
"no-bitwise": true,
"no-conditional-assignment": true,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-construct": true,
"no-debugger": true,
"no-duplicate-key": true,
"no-duplicate-variable": true,
"no-empty": false,
"no-eval": true,
"no-null-keyword": true,
"no-shadowed-variable": true,
"no-string-literal": true,
"no-switch-case-fall-through": true,
"no-unreachable": true,
"no-unused-expression": true,
"no-unused-variable": false,
"no-use-before-declare": true,
"no-var-keyword": true,
"radix": true,
"switch-default": true,
"triple-equals": [
true,
"allow-null-check"
],
"use-strict": [
true,
"check-module"
],
"eofline": true,
"indent": [
true,
"spaces"
],
"max-line-length": [
true,
200
],
"no-require-imports": false,
"no-trailing-whitespace": true,
"object-literal-sort-keys": false,
"trailing-comma": [
true,
{
"multiline": "never",
"singleline": "never"
}
],
"align": false,
"class-name": true,
"comment-format": [
true,
"check-space"
],
"interface-name": false,
"jsdoc-format": true,
"no-consecutive-blank-lines": false,
"no-constructor-vars": false,
"one-line": [
true,
"check-open-brace",
"check-catch",
"check-else",
"check-finally",
"check-whitespace"
],
"quotemark": [
true,
"single",
"avoid-escape"
],
"semicolon": [
true,
"always"
],
"variable-name": [
true,
"check-format",
"allow-leading-underscore",
"ban-keywords"
],
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
]
}
}

+ 63
- 0
test/Services/FunctionalTests/Services/Basket/RedisBasketRepositoryTests.cs View File

@ -0,0 +1,63 @@

//namespace FunctionalTests.Services.Basket
//{
// using Microsoft.eShopOnContainers.Services.Basket.API;
// using Microsoft.eShopOnContainers.Services.Basket.API.Model;
// using Microsoft.Extensions.Logging;
// using Microsoft.Extensions.Options;
// using System.Collections.Generic;
// using System.Threading.Tasks;
// using Xunit;
// public class RedisBasketRepositoryTests
// {
// [Fact]
// public async Task UpdateBasket_return_and_add_basket()
// {
// var redisBasketRepository = BuildBasketRepository();
// var basket = await redisBasketRepository.UpdateBasket(new CustomerBasket("customerId")
// {
// BuyerId = "buyerId",
// Items = BuildBasketItems()
// });
// Assert.NotNull(basket);
// Assert.Equal(1, basket.Items.Count);
// }
// [Fact]
// public async Task GetBasket_return_existing_basket()
// {
// }
// RedisBasketRepository BuildBasketRepository()
// {
// var loggerFactory = new LoggerFactory();
// var options = Options.Create<BasketSettings>(new BasketSettings()
// {
// ConnectionString = "127.0.0.1"
// });
// return new RedisBasketRepository(options, loggerFactory);
// }
// List<BasketItem> BuildBasketItems()
// {
// return new List<BasketItem>()
// {
// new BasketItem()
// {
// Id = "basketId",
// PictureUrl = "pictureurl",
// ProductId = "productId",
// ProductName = "productName",
// Quantity = 1,
// UnitPrice = 1
// }
// };
// }
// }
//}

+ 1
- 1
test/Services/FunctionalTests/Services/Catalog/CatalogScenarioBase.cs View File

@ -31,7 +31,7 @@ namespace FunctionalTests.Services.Catalog
return $"api/v1/catalog/items?pageIndex={pageIndex}&pageSize={pageCount}";
}
public static string Filtered(int catalogTypeId,int catalogBrandId)
public static string Filtered(int catalogTypeId, int catalogBrandId)
{
return $"api/v1/catalog/items/type/{catalogTypeId}/brand/{catalogBrandId}";
}


+ 2
- 2
test/Services/FunctionalTests/Services/Catalog/CatalogScenarios.cs View File

@ -4,7 +4,7 @@
using Xunit;
public class CatalogScenarios
:CatalogScenarioBase
: CatalogScenarioBase
{
[Fact]
public async Task Get_get_all_catalogitems_and_response_ok_status_code()
@ -24,7 +24,7 @@
using (var server = CreateServer())
{
var response = await server.CreateClient()
.GetAsync(Get.Paginated(0,4));
.GetAsync(Get.Paginated(0, 4));
response.EnsureSuccessStatusCode();
}


+ 1
- 1
test/Services/FunctionalTests/Services/Ordering/OrderingScenarios.cs View File

@ -56,7 +56,7 @@
var content = new StringContent(BuildOrderWithInvalidExperationTime(), UTF8Encoding.UTF8, "application/json");
var response = await server.CreateClient()
.PostAsync(Post.AddNewOrder,content);
.PostAsync(Post.AddNewOrder, content);
Assert.True(response.StatusCode == System.Net.HttpStatusCode.BadRequest);
}


+ 5
- 2
test/Services/FunctionalTests/project.json View File

@ -2,14 +2,17 @@
"version": "1.0.0-*",
"dependencies": {
"Ordering.API": "1.0.0-*",
"Microsoft.NETCore.App": "1.1.0",
"Microsoft.AspNetCore.TestHost": "1.1.0",
"dotnet-test-xunit": "2.2.0-preview2-build1029",
"xunit": "2.2.0-beta4-build3444",
"Catalog.API": "1.0.0-*",
"xunit": "2.2.0-beta4-build3444"
"Ordering.API": "1.0.0-*"
},
"testRunner": "xunit",
"runtimes": {
"win10-x64": {}
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {


+ 27
- 24
test/Services/UnitTest/Ordering/Application/NewOrderCommandHandlerTest.cs View File

@ -1,18 +1,15 @@
using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.Api.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.Domain;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Repositories;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork;
using Moq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace UnitTest.Ordering.Application
namespace UnitTest.Ordering.Application
{
using Microsoft.eShopOnContainers.Services.Ordering.Api.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.Domain;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Repositories;
using Moq;
using System;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
public class NewOrderRequestHandlerTest
{
private readonly Mock<IBuyerRepository> _buyerRepositoryMock;
@ -20,25 +17,29 @@ namespace UnitTest.Ordering.Application
public NewOrderRequestHandlerTest()
{
//Mocks;
_buyerRepositoryMock = new Mock<IBuyerRepository>();
_orderRepositoryMock = new Mock<IOrderRepository>();
}
[Fact]
public async Task Handle_ReturnsTrue_WhenOrderIsPersistedSuccesfully()
public async Task Handle_returns_true_when_order_is_persisted_succesfully()
{
// Arrange
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.FindAsync(FakeOrderRequestWithBuyer().Buyer))
.Returns(Task.FromResult<Buyer>(FakeBuyer()));
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
.Returns(Task.FromResult(1));
_orderRepositoryMock.Setup(or => or.Add(FakeOrder())).Returns(FakeOrder());
_orderRepositoryMock.Setup(or => or.UnitOfWork.SaveChangesAsync(default(CancellationToken))).Returns(Task.FromResult(1));
_orderRepositoryMock.Setup(or => or.Add(FakeOrder()))
.Returns(FakeOrder());
_orderRepositoryMock.Setup(or => or.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
.Returns(Task.FromResult(1));
//Act
var handler = new NewOrderRequestHandler(_buyerRepositoryMock.Object, _orderRepositoryMock.Object);
var handler = new NewOrderCommandHandler(_buyerRepositoryMock.Object, _orderRepositoryMock.Object);
var result = await handler.Handle(FakeOrderRequestWithBuyer());
//Assert
@ -46,18 +47,20 @@ namespace UnitTest.Ordering.Application
}
[Fact]
public async Task Handle_ReturnsFalse_WhenOrderIsNotPersisted()
public async Task Handle_return_false_if_order_is_not_persisted()
{
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.FindAsync(FakeOrderRequestWithBuyer().Buyer))
.Returns(Task.FromResult<Buyer>(FakeBuyer()));
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
.Returns(Task.FromResult(1));
_orderRepositoryMock.Setup(or => or.Add(FakeOrder())).Returns(FakeOrder());
_orderRepositoryMock.Setup(or => or.UnitOfWork.SaveChangesAsync(default(CancellationToken))).Returns(Task.FromResult(0));
_orderRepositoryMock.Setup(or => or.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
.Returns(Task.FromResult(0));
//Act
var handler = new NewOrderRequestHandler(_buyerRepositoryMock.Object, _orderRepositoryMock.Object);
var handler = new NewOrderCommandHandler(_buyerRepositoryMock.Object, _orderRepositoryMock.Object);
var result = await handler.Handle(FakeOrderRequestWithBuyer());
//Assert
@ -77,9 +80,9 @@ namespace UnitTest.Ordering.Application
};
}
private NewOrderRequest FakeOrderRequestWithBuyer()
private NewOrderCommand FakeOrderRequestWithBuyer()
{
return new NewOrderRequest
return new NewOrderCommand
{
Buyer = "1234",
CardNumber = "1234",


+ 0
- 136
test/Services/UnitTest/Ordering/Controllers/OrderControllerTest.cs View File

@ -1,136 +0,0 @@
using System;
using Xunit;
using System.Threading.Tasks;
using Moq;
using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.API.Controllers;
using Microsoft.eShopOnContainers.Services.Ordering.Api.Application.Commands;
using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services;
using Microsoft.eShopOnContainers.Services.Ordering.Api.Application.Queries;
using System.Collections.Generic;
namespace UnitTest.Ordering.Controllers
{
public class OrderControllerTest
{
private readonly Mock<IMediator> _mediatorMock;
private readonly Mock<IIdentityService> _identityMock;
private readonly Mock<IOrderQueries> _queriesMock;
private readonly string _userIdentity;
public OrderControllerTest()
{
//Mocks;
_mediatorMock = new Mock<IMediator>();
_identityMock = new Mock<IIdentityService>();
_queriesMock = new Mock<IOrderQueries>();
_userIdentity = Guid.NewGuid().ToString();
}
[Fact]
public async Task AddOrder_ReturnsBadRequestResult_WhenPersitenceOperationFails()
{
// Arrange
var orderRequest = new object() as IAsyncRequest<bool>;
_mediatorMock.Setup(mediator => mediator.SendAsync(OrderFakeNotExpired()))
.Returns(Task.FromResult(false));
_identityMock.Setup(identity => identity.GetUserIdentity())
.Returns(Guid.NewGuid().ToString());
var controller = new OrdersController(_mediatorMock.Object, _queriesMock.Object, _identityMock.Object);
// Act
var badRequestResult = await controller.AddOrder(OrderFakeNotExpired());
// Assert
Assert.IsType<BadRequestResult>(badRequestResult);
}
[Fact]
public async Task GetOrder_ReturnsNotFound_WhenItemNotFound()
{
// Arrange
_queriesMock.Setup(queries => queries.GetOrder(1))
.Throws(new KeyNotFoundException());
var controller = new OrdersController(_mediatorMock.Object, _queriesMock.Object, _identityMock.Object);
// Act
var notFoundResult = await controller.GetOrder(1);
// Assert
Assert.IsType<NotFoundResult>(notFoundResult);
}
[Fact]
public async Task GetOrder_ReturnsOkObjecResult_WheItemFound()
{
// Arrange
_queriesMock.Setup(queries => queries.GetOrder(1))
.Returns(Task.FromResult(new object()));
var controller = new OrdersController(_mediatorMock.Object, _queriesMock.Object, _identityMock.Object);
// Act
var OkObjectResult = await controller.GetOrder(1);
// Assert
Assert.IsType<OkObjectResult>(OkObjectResult);
}
[Fact]
public async Task GetOrders_ReturnsOkObjectResult()
{
// Arrange
_queriesMock.Setup(queries => queries.GetOrders())
.Returns(Task.FromResult(new object()));
var controller = new OrdersController(_mediatorMock.Object, _queriesMock.Object, _identityMock.Object);
// Act
var OkObjectResult = await controller.GetOrders();
// Assert
Assert.IsType<OkObjectResult>(OkObjectResult);
}
[Fact]
public async Task GetCardTypes()
{
// Arrange
_queriesMock.Setup(queries => queries.GetCardTypes())
.Returns(Task.FromResult(new object()));
var controller = new OrdersController(_mediatorMock.Object, _queriesMock.Object, _identityMock.Object);
// Act
var OkObjectResult = await controller.GetCardTypes();
// Assert
Assert.IsType<OkObjectResult>(OkObjectResult);
}
//Fakes
private NewOrderRequest OrderFakeNotExpired()
{
return new NewOrderRequest()
{
CardTypeId = 1,
CardExpiration = new DateTime(2020, 12, 12),
Buyer = _userIdentity
};
}
private NewOrderRequest OrderFakeExpired()
{
return new NewOrderRequest()
{
CardTypeId = 1,
CardExpiration = DateTime.Now.AddYears(-1)
};
}
}
}

Loading…
Cancel
Save