Moved Create Order from MVC logic client to Purchase logic.
This commit is contained in:
parent
2a2f3a4da1
commit
2a81a080ba
@ -26,7 +26,7 @@
|
|||||||
"DownstreamHost": "purchasebff",
|
"DownstreamHost": "purchasebff",
|
||||||
"DownstreamPort": 80,
|
"DownstreamPort": 80,
|
||||||
"UpstreamPathTemplate": "/purchase-bff/{everything}",
|
"UpstreamPathTemplate": "/purchase-bff/{everything}",
|
||||||
"UpstreamHttpMethod": [ "POST", "PUT" ],
|
"UpstreamHttpMethod": [ "POST", "PUT", "GET" ],
|
||||||
"AuthenticationOptions": {
|
"AuthenticationOptions": {
|
||||||
"AuthenticationProviderKey": "IdentityApiKey",
|
"AuthenticationProviderKey": "IdentityApiKey",
|
||||||
"AllowedScopes": []
|
"AllowedScopes": []
|
||||||
|
40
src/BFFs/PurchaseBff/Controllers/OrderController.cs
Normal file
40
src/BFFs/PurchaseBff/Controllers/OrderController.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using PurchaseBff.Services;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PurchaseBff.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/v1/[controller]")]
|
||||||
|
[Authorize]
|
||||||
|
public class OrderController : Controller
|
||||||
|
{
|
||||||
|
private readonly IBasketService _basketService;
|
||||||
|
public OrderController(IBasketService basketService)
|
||||||
|
{
|
||||||
|
_basketService = basketService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("draft/{basketId}")]
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<IActionResult> GetOrderDraft(string basketId)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(basketId))
|
||||||
|
{
|
||||||
|
return BadRequest("Need a valid basketid");
|
||||||
|
}
|
||||||
|
// Get the basket data and build a order draft based on it
|
||||||
|
var basket = await _basketService.GetById(basketId);
|
||||||
|
if (basket == null)
|
||||||
|
{
|
||||||
|
return BadRequest($"No basket found for id {basketId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var order = _basketService.MapBasketToOrder(basket, isDraft: true);
|
||||||
|
return Ok(order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
src/BFFs/PurchaseBff/Models/OrderData.cs
Normal file
33
src/BFFs/PurchaseBff/Models/OrderData.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PurchaseBff.Models
|
||||||
|
{
|
||||||
|
public class OrderData
|
||||||
|
{
|
||||||
|
public string OrderNumber { get; set; }
|
||||||
|
public DateTime Date { get; set; }
|
||||||
|
public string Status { get; set; }
|
||||||
|
public decimal Total { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
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 bool IsDraft { get; set; }
|
||||||
|
public DateTime CardExpiration { get; set; }
|
||||||
|
public string CardExpirationShort { get; set; }
|
||||||
|
public string CardSecurityNumber { get; set; }
|
||||||
|
|
||||||
|
public int CardTypeId { get; set; }
|
||||||
|
|
||||||
|
public string Buyer { get; set; }
|
||||||
|
|
||||||
|
public List<OrderItemData> OrderItems { get; } = new List<OrderItemData>();
|
||||||
|
}
|
||||||
|
}
|
17
src/BFFs/PurchaseBff/Models/OrderItemData.cs
Normal file
17
src/BFFs/PurchaseBff/Models/OrderItemData.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PurchaseBff.Models
|
||||||
|
{
|
||||||
|
public class OrderItemData
|
||||||
|
{
|
||||||
|
public int ProductId { get; set; }
|
||||||
|
public string ProductName { get; set; }
|
||||||
|
public decimal UnitPrice { get; set; }
|
||||||
|
public decimal Discount { get; set; }
|
||||||
|
public int Units { get; set; }
|
||||||
|
public string PictureUrl { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
"windowsAuthentication": false,
|
"windowsAuthentication": false,
|
||||||
"anonymousAuthentication": true,
|
"anonymousAuthentication": true,
|
||||||
"iisExpress": {
|
"iisExpress": {
|
||||||
"applicationUrl": "http://localhost:61631/",
|
"applicationUrl": "http://localhost:58243/",
|
||||||
"sslPort": 0
|
"sslPort": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -26,4 +26,4 @@
|
|||||||
"applicationUrl": "http://localhost:61632/"
|
"applicationUrl": "http://localhost:61632/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -44,6 +44,31 @@ namespace PurchaseBff.Services
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public OrderData MapBasketToOrder(BasketData basket, bool isDraft)
|
||||||
|
{
|
||||||
|
var order = new OrderData
|
||||||
|
{
|
||||||
|
Total = 0,
|
||||||
|
IsDraft = isDraft
|
||||||
|
};
|
||||||
|
|
||||||
|
basket.Items.ForEach(x =>
|
||||||
|
{
|
||||||
|
order.OrderItems.Add(new OrderItemData()
|
||||||
|
{
|
||||||
|
ProductId = int.Parse(x.ProductId),
|
||||||
|
|
||||||
|
PictureUrl = x.PictureUrl,
|
||||||
|
ProductName = x.ProductName,
|
||||||
|
Units = x.Quantity,
|
||||||
|
UnitPrice = x.UnitPrice
|
||||||
|
});
|
||||||
|
order.Total += (x.Quantity * x.UnitPrice);
|
||||||
|
});
|
||||||
|
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
async Task<string> GetUserTokenAsync()
|
async Task<string> GetUserTokenAsync()
|
||||||
{
|
{
|
||||||
var context = _httpContextAccessor.HttpContext;
|
var context = _httpContextAccessor.HttpContext;
|
||||||
|
@ -10,5 +10,7 @@ namespace PurchaseBff.Services
|
|||||||
{
|
{
|
||||||
Task<BasketData> GetById(string id);
|
Task<BasketData> GetById(string id);
|
||||||
Task Update(BasketData currentBasket);
|
Task Update(BasketData currentBasket);
|
||||||
|
|
||||||
|
OrderData MapBasketToOrder(BasketData basket, bool isDraft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"windowsAuthentication": false,
|
"windowsAuthentication": false,
|
||||||
"anonymousAuthentication": true,
|
"anonymousAuthentication": true,
|
||||||
"iisExpress": {
|
"iisExpress": {
|
||||||
"applicationUrl": "http://localhost:56695/",
|
"applicationUrl": "http://localhost:57622/",
|
||||||
"sslPort": 0
|
"sslPort": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"windowsAuthentication": false,
|
"windowsAuthentication": false,
|
||||||
"anonymousAuthentication": true,
|
"anonymousAuthentication": true,
|
||||||
"iisExpress": {
|
"iisExpress": {
|
||||||
"applicationUrl": "http://localhost:56698/",
|
"applicationUrl": "http://localhost:57623/",
|
||||||
"sslPort": 0
|
"sslPort": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -49,10 +49,8 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
|||||||
{
|
{
|
||||||
var user = _appUserParser.Parse(HttpContext.User);
|
var user = _appUserParser.Parse(HttpContext.User);
|
||||||
var basket = await _basketSvc.SetQuantities(user, quantities);
|
var basket = await _basketSvc.SetQuantities(user, quantities);
|
||||||
|
|
||||||
if (action == "[ Checkout ]")
|
if (action == "[ Checkout ]")
|
||||||
{
|
{
|
||||||
var order = _basketSvc.MapBasketToOrder(basket);
|
|
||||||
return RedirectToAction("Create", "Order");
|
return RedirectToAction("Create", "Order");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,9 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
|||||||
|
|
||||||
public async Task<IActionResult> Create()
|
public async Task<IActionResult> Create()
|
||||||
{
|
{
|
||||||
|
|
||||||
var user = _appUserParser.Parse(HttpContext.User);
|
var user = _appUserParser.Parse(HttpContext.User);
|
||||||
var basket = await _basketSvc.GetBasket(user);
|
var order = await _basketSvc.GetOrderDraft(user.Id);
|
||||||
var order = _basketSvc.MapBasketToOrder(basket);
|
|
||||||
var vm = _orderSvc.MapUserInfoIntoOrder(user, order);
|
var vm = _orderSvc.MapUserInfoIntoOrder(user, order);
|
||||||
vm.CardExpirationShortFormat();
|
vm.CardExpirationShortFormat();
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@ namespace WebMVC.Infrastructure
|
|||||||
{
|
{
|
||||||
public static string AddItemToBasket(string baseUri) => $"{baseUri}/basket/items";
|
public static string AddItemToBasket(string baseUri) => $"{baseUri}/basket/items";
|
||||||
public static string UpdateBasketItem(string baseUri) => $"{baseUri}/basket/items";
|
public static string UpdateBasketItem(string baseUri) => $"{baseUri}/basket/items";
|
||||||
|
|
||||||
|
public static string GetOrderDraft(string baseUri, string basketId) => $"{baseUri}/order/draft/{basketId}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Basket
|
public static class Basket
|
||||||
|
@ -93,28 +93,16 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
|
|||||||
return JsonConvert.DeserializeObject<Basket>(jsonResponse);
|
return JsonConvert.DeserializeObject<Basket>(jsonResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Order MapBasketToOrder(Basket basket)
|
public async Task<Order> GetOrderDraft(string basketId)
|
||||||
{
|
{
|
||||||
var order = new Order();
|
var token = await GetUserTokenAsync();
|
||||||
order.Total = 0;
|
var draftOrderUri = API.Purchase.GetOrderDraft(_purchaseUrl, basketId);
|
||||||
|
var json = await _apiClient.GetStringAsync(draftOrderUri, token);
|
||||||
basket.Items.ForEach(x =>
|
return JsonConvert.DeserializeObject<Order>(json);
|
||||||
{
|
|
||||||
order.OrderItems.Add(new OrderItem()
|
|
||||||
{
|
|
||||||
ProductId = int.Parse(x.ProductId),
|
|
||||||
|
|
||||||
PictureUrl = x.PictureUrl,
|
|
||||||
ProductName = x.ProductName,
|
|
||||||
Units = x.Quantity,
|
|
||||||
UnitPrice = x.UnitPrice
|
|
||||||
});
|
|
||||||
order.Total += (x.Quantity * x.UnitPrice);
|
|
||||||
});
|
|
||||||
|
|
||||||
return order;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public async Task AddItemToBasket(ApplicationUser user, int productId)
|
public async Task AddItemToBasket(ApplicationUser user, int productId)
|
||||||
{
|
{
|
||||||
var token = await GetUserTokenAsync();
|
var token = await GetUserTokenAsync();
|
||||||
|
@ -14,6 +14,6 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
|
|||||||
Task<Basket> UpdateBasket(Basket basket);
|
Task<Basket> UpdateBasket(Basket basket);
|
||||||
Task Checkout(BasketDTO basket);
|
Task Checkout(BasketDTO basket);
|
||||||
Task<Basket> SetQuantities(ApplicationUser user, Dictionary<string, int> quantities);
|
Task<Basket> SetQuantities(ApplicationUser user, Dictionary<string, int> quantities);
|
||||||
Order MapBasketToOrder(Basket basket);
|
Task<Order> GetOrderDraft(string basketId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"windowsAuthentication": false,
|
"windowsAuthentication": false,
|
||||||
"anonymousAuthentication": true,
|
"anonymousAuthentication": true,
|
||||||
"iisExpress": {
|
"iisExpress": {
|
||||||
"applicationUrl": "http://localhost:56727/",
|
"applicationUrl": "http://localhost:57625/",
|
||||||
"sslPort": 0
|
"sslPort": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -68,40 +68,7 @@ namespace UnitTest.Ordering.Application
|
|||||||
Assert.IsAssignableFrom<Order>(viewResult.ViewData.Model);
|
Assert.IsAssignableFrom<Order>(viewResult.ViewData.Model);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task Get_create_order_success()
|
|
||||||
{
|
|
||||||
//Arrange
|
|
||||||
var fakeBuyerId = "1";
|
|
||||||
var fakeBasket = GetFakeBasket(fakeBuyerId);
|
|
||||||
var fakeOrder = GetFakeOrder();
|
|
||||||
|
|
||||||
_basketServiceMock.Setup(x => x.GetBasket(It.IsAny<ApplicationUser>()))
|
|
||||||
.Returns(Task.FromResult(fakeBasket));
|
|
||||||
|
|
||||||
_basketServiceMock.Setup(x => x.MapBasketToOrder(It.IsAny<BasketModel>()))
|
|
||||||
.Returns(fakeOrder);
|
|
||||||
|
|
||||||
_orderServiceMock.Setup(x => x.MapUserInfoIntoOrder(It.IsAny<ApplicationUser>(), It.IsAny<Order>()))
|
|
||||||
.Returns(fakeOrder);
|
|
||||||
|
|
||||||
//Act
|
|
||||||
var orderController = new OrderController(_orderServiceMock.Object, _basketServiceMock.Object, _identityParserMock.Object);
|
|
||||||
orderController.ControllerContext.HttpContext = _contextMock.Object;
|
|
||||||
var actionResult = await orderController.Create();
|
|
||||||
|
|
||||||
//Assert
|
|
||||||
var viewResult = Assert.IsType<ViewResult>(actionResult);
|
|
||||||
Assert.IsAssignableFrom<Order>(viewResult.ViewData.Model);
|
|
||||||
}
|
|
||||||
|
|
||||||
private BasketModel GetFakeBasket(string buyerId)
|
|
||||||
{
|
|
||||||
return new BasketModel()
|
|
||||||
{
|
|
||||||
BuyerId = buyerId
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private Order GetFakeOrder()
|
private Order GetFakeOrder()
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user