# Conflicts: # src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cspull/223/head
@ -0,0 +1,21 @@ | |||
using MediatR; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Runtime.Serialization; | |||
using System.Threading.Tasks; | |||
namespace Ordering.API.Application.Commands | |||
{ | |||
public class ShipOrderCommand : IAsyncRequest<bool> | |||
{ | |||
[DataMember] | |||
public int OrderNumber { get; private set; } | |||
public ShipOrderCommand(int orderNumber) | |||
{ | |||
OrderNumber = orderNumber; | |||
} | |||
} | |||
} |
@ -0,0 +1,9 @@ | |||
namespace Payment.API.IntegrationEvents | |||
{ | |||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; | |||
public interface IPaymentIntegrationEventService | |||
{ | |||
void PublishThroughEventBus(IntegrationEvent evt); | |||
} | |||
} |
@ -0,0 +1,21 @@ | |||
namespace Payment.API.IntegrationEvents | |||
{ | |||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; | |||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; | |||
using System; | |||
public class PaymentIntegrationEventService : IPaymentIntegrationEventService | |||
{ | |||
private readonly IEventBus _eventBus; | |||
public PaymentIntegrationEventService(IEventBus eventBus) | |||
{ | |||
_eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); | |||
} | |||
public void PublishThroughEventBus(IntegrationEvent evt) | |||
{ | |||
_eventBus.Publish(evt); ; | |||
} | |||
} | |||
} |
@ -0,0 +1,43 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using Microsoft.AspNetCore.Mvc; | |||
using WebMVC.Models; | |||
using Microsoft.eShopOnContainers.WebMVC.Services; | |||
using Microsoft.eShopOnContainers.WebMVC.ViewModels; | |||
using Microsoft.AspNetCore.Authorization; | |||
namespace WebMVC.Controllers | |||
{ | |||
[Authorize] | |||
public class OrderManagementController : Controller | |||
{ | |||
private IOrderingService _orderSvc; | |||
private readonly IIdentityParser<ApplicationUser> _appUserParser; | |||
public OrderManagementController(IOrderingService orderSvc, IIdentityParser<ApplicationUser> appUserParser) | |||
{ | |||
_appUserParser = appUserParser; | |||
_orderSvc = orderSvc; | |||
} | |||
public async Task<IActionResult> Index() | |||
{ | |||
var user = _appUserParser.Parse(HttpContext.User); | |||
var vm = await _orderSvc.GetMyOrders(user); | |||
return View(vm); | |||
} | |||
[HttpPost] | |||
public async Task<IActionResult> OrderProcess(string orderId, string actionCode) | |||
{ | |||
if (OrderProcessAction.Ship.Code == actionCode) | |||
{ | |||
await _orderSvc.ShipOrder(orderId); | |||
} | |||
return RedirectToAction("Index"); | |||
} | |||
} | |||
} |
@ -0,0 +1,11 @@ | |||
using System; | |||
using System.ComponentModel.DataAnnotations; | |||
namespace WebMVC.Models | |||
{ | |||
public class OrderDTO | |||
{ | |||
[Required] | |||
public string OrderNumber { get; set; } | |||
} | |||
} |
@ -0,0 +1,25 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace WebMVC.Models | |||
{ | |||
public class OrderProcessAction | |||
{ | |||
public string Code { get; private set; } | |||
public string Name { get; private set; } | |||
public static OrderProcessAction Ship = new OrderProcessAction(nameof(Ship).ToLowerInvariant(), "Ship"); | |||
protected OrderProcessAction() | |||
{ | |||
} | |||
public OrderProcessAction(string code, string name) | |||
{ | |||
Code = code; | |||
Name = name; | |||
} | |||
} | |||
} |
@ -0,0 +1,43 @@ | |||
@using Microsoft.eShopOnContainers.WebMVC.ViewModels | |||
@model IEnumerable<Microsoft.eShopOnContainers.WebMVC.ViewModels.Order> | |||
@{ | |||
ViewData["Title"] = "My Orders"; | |||
} | |||
<div class="esh-orders"> | |||
@Html.Partial("_Header", new List<Header>() { | |||
new Header() { Controller = "Catalog", Text = "Back to catalog" } }) | |||
<div class="container"> | |||
<article class="esh-orders-titles row"> | |||
<section class="esh-orders-title col-xs-2">Order number</section> | |||
<section class="esh-orders-title col-xs-4">Date</section> | |||
<section class="esh-orders-title col-xs-2">Total</section> | |||
<section class="esh-orders-title col-xs-2">Status</section> | |||
<section class="esh-orders-title col-xs-2"></section> | |||
</article> | |||
@foreach (var item in Model) | |||
{ | |||
<article class="esh-orders-items row"> | |||
<section class="esh-orders-item col-xs-2">@Html.DisplayFor(modelItem => item.OrderNumber)</section> | |||
<section class="esh-orders-item col-xs-4">@Html.DisplayFor(modelItem => item.Date)</section> | |||
<section class="esh-orders-item col-xs-2">$ @Html.DisplayFor(modelItem => item.Total)</section> | |||
<section class="esh-orders-item col-xs-2">@Html.DisplayFor(modelItem => item.Status)</section> | |||
<section class="esh-orders-item col-xs-2"> | |||
<form asp-action="OrderProcess" id="orderForm+@item.OrderNumber" method="post"> | |||
<input type="hidden" name="orderId" value="@item.OrderNumber" /> | |||
<select name="actionCode" asp-items="@item.ActionCodeSelectList" | |||
disabled=@(item.Status != "paid") | |||
onchange="document.getElementById('orderForm+@item.OrderNumber').submit()"> | |||
<option value=""> Select Action</option> | |||
<option value="">------------------</option> | |||
</select> | |||
</form> | |||
</section> | |||
</article> | |||
} | |||
</div> | |||
</div> |
@ -1,7 +1,11 @@ | |||
@model Microsoft.eShopOnContainers.WebMVC.ViewModels.Header | |||
@model IEnumerable<Microsoft.eShopOnContainers.WebMVC.ViewModels.Header> | |||
<div class="esh-header"> | |||
<div class="container"> | |||
<a class="esh-header-back" asp-area="" asp-controller="@Model.Controller" asp-action="Index">@Model.Text</a> | |||
@foreach (var header in @Model) | |||
{ | |||
<a class="esh-header-title" asp-area="" asp-controller="@header.Controller" asp-action="Index">@header.Text</a> | |||
} | |||
</div> | |||
</div> |
@ -0,0 +1,16 @@ | |||
export interface IBasketCheckout { | |||
city: number; | |||
street: string; | |||
state: string; | |||
country: number; | |||
zipcode: string; | |||
cardnumber: string; | |||
cardexpiration: Date; | |||
expiration: string; | |||
cardsecuritynumber: string; | |||
cardholdername: string; | |||
cardtypeid: number; | |||
buyer: string; | |||
ordernumber: string; | |||
total: number; | |||
} |
@ -0,0 +1,36 @@ | |||
using Microsoft.AspNetCore.Hosting; | |||
using Microsoft.AspNetCore.TestHost; | |||
using Microsoft.eShopOnContainers.Services.Basket.API; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Text; | |||
namespace IntegrationTests.Services.Basket | |||
{ | |||
public class BasketScenarioBase | |||
{ | |||
public TestServer CreateServer() | |||
{ | |||
var webHostBuilder = new WebHostBuilder(); | |||
webHostBuilder.UseContentRoot(Directory.GetCurrentDirectory() + "\\Services\\basket"); | |||
webHostBuilder.UseStartup<BasketTestsStartup>(); | |||
return new TestServer(webHostBuilder); | |||
} | |||
public static class Get | |||
{ | |||
public static string GetBasket(int id) | |||
{ | |||
return $"api/v1/basket/{id}"; | |||
} | |||
} | |||
public static class Post | |||
{ | |||
public static string Basket = "api/v1/basket"; | |||
public static string CheckoutOrder = "api/v1/basket/checkout"; | |||
} | |||
} | |||
} |
@ -0,0 +1,80 @@ | |||
using Microsoft.eShopOnContainers.Services.Basket.API.Model; | |||
using Newtonsoft.Json; | |||
using System; | |||
using System.Net.Http; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using WebMVC.Models; | |||
using Xunit; | |||
namespace IntegrationTests.Services.Basket | |||
{ | |||
public class BasketScenarios | |||
: BasketScenarioBase | |||
{ | |||
[Fact] | |||
public async Task Post_basket_and_response_ok_status_code() | |||
{ | |||
using (var server = CreateServer()) | |||
{ | |||
var content = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); | |||
var response = await server.CreateClient() | |||
.PostAsync(Post.Basket, content); | |||
response.EnsureSuccessStatusCode(); | |||
} | |||
} | |||
[Fact] | |||
public async Task Get_basket_and_response_ok_status_code() | |||
{ | |||
using (var server = CreateServer()) | |||
{ | |||
var response = await server.CreateClient() | |||
.GetAsync(Get.GetBasket(1)); | |||
response.EnsureSuccessStatusCode(); | |||
} | |||
} | |||
[Fact] | |||
public async Task Send_Checkout_basket_and_response_ok_status_code() | |||
{ | |||
using (var server = CreateServer()) | |||
{ | |||
var content = new StringContent(BuildCheckout(), UTF8Encoding.UTF8, "application/json"); | |||
var response = await server.CreateClient() | |||
.PostAsync(Post.CheckoutOrder, content); | |||
response.EnsureSuccessStatusCode(); | |||
} | |||
} | |||
string BuildBasket() | |||
{ | |||
var order = new CustomerBasket("1"); | |||
return JsonConvert.SerializeObject(order); | |||
} | |||
string BuildCheckout() | |||
{ | |||
var checkoutBasket = new BasketDTO() | |||
{ | |||
City = "city", | |||
Street = "street", | |||
State = "state", | |||
Country = "coutry", | |||
ZipCode = "zipcode", | |||
CardNumber = "CardNumber", | |||
CardHolderName = "CardHolderName", | |||
CardExpiration = DateTime.UtcNow, | |||
CardSecurityNumber = "1234", | |||
CardTypeId = 1, | |||
Buyer = "Buyer", | |||
RequestId = Guid.NewGuid() | |||
}; | |||
return JsonConvert.SerializeObject(checkoutBasket); | |||
} | |||
} | |||
} |
@ -0,0 +1,26 @@ | |||
using IntegrationTests.Middleware; | |||
using Microsoft.AspNetCore.Builder; | |||
using Microsoft.AspNetCore.Hosting; | |||
using Microsoft.eShopOnContainers.Services.Basket.API; | |||
namespace IntegrationTests.Services.Basket | |||
{ | |||
public class BasketTestsStartup : Startup | |||
{ | |||
public BasketTestsStartup(IHostingEnvironment env) : base(env) | |||
{ | |||
} | |||
protected override void ConfigureAuth(IApplicationBuilder app) | |||
{ | |||
if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) | |||
{ | |||
app.UseMiddleware<AutoAuthorizeMiddleware>(); | |||
} | |||
else | |||
{ | |||
base.ConfigureAuth(app); | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,8 @@ | |||
{ | |||
"ConnectionString": "127.0.0.1", | |||
"IdentityUrl": "http://localhost:5105", | |||
"isTest": "true", | |||
"EventBusConnection": "localhost" | |||
} | |||
@ -1,112 +1,61 @@ | |||
namespace IntegrationTests.Services.Ordering | |||
{ | |||
using IntegrationTests.Services.Extensions; | |||
using Microsoft.AspNetCore.TestHost; | |||
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; | |||
using Newtonsoft.Json; | |||
using System; | |||
using System.Net.Http; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using WebMVC.Models; | |||
using Xunit; | |||
using System.Collections; | |||
using static Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands.CreateOrderCommand; | |||
using System.Collections.Generic; | |||
public class OrderingScenarios | |||
: OrderingScenarioBase | |||
{ | |||
// [Fact] | |||
// public async Task Get_get_all_stored_orders_and_response_ok_status_code() | |||
// { | |||
// using (var server = CreateServer()) | |||
// { | |||
// var response = await server.CreateClient() | |||
// .GetAsync(Get.Orders); | |||
// response.EnsureSuccessStatusCode(); | |||
// } | |||
// } | |||
// [Fact] | |||
// public async Task AddNewOrder_add_new_order_and_response_ok_status_code() | |||
// { | |||
// using (var server = CreateServer()) | |||
// { | |||
// var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"); | |||
// var response = await server.CreateIdempotentClient() | |||
// .PostAsync(Post.AddNewOrder, content); | |||
// response.EnsureSuccessStatusCode(); | |||
// } | |||
// } | |||
// [Fact] | |||
// public async Task AddNewOrder_response_bad_request_if_card_expiration_is_invalid() | |||
// { | |||
// using (var server = CreateServer()) | |||
// { | |||
// var content = new StringContent(BuildOrderWithInvalidExperationTime(), UTF8Encoding.UTF8, "application/json"); | |||
// var response = await server.CreateIdempotentClient() | |||
// .PostAsync(Post.AddNewOrder, content); | |||
// Assert.True(response.StatusCode == System.Net.HttpStatusCode.BadRequest); | |||
// } | |||
// } | |||
// //public CreateOrderCommand(string city, string street, string state, string country, string zipcode, | |||
// // string cardNumber, string cardHolderName, DateTime cardExpiration, | |||
// // string cardSecurityNumber, int cardTypeId, int paymentId, int buyerId) : this() | |||
// string BuildOrder() | |||
// { | |||
// List<OrderItemDTO> orderItemsList = new List<OrderItemDTO>(); | |||
// orderItemsList.Add(new OrderItemDTO() | |||
// { | |||
// ProductId = 1, | |||
// Discount = 10M, | |||
// UnitPrice = 10, | |||
// Units = 1, | |||
// ProductName = "Some name" | |||
// } | |||
// ); | |||
// var order = new CreateOrderCommand( | |||
// orderItemsList, | |||
// cardExpiration: DateTime.UtcNow.AddYears(1), | |||
// cardNumber: "5145-555-5555", | |||
// cardHolderName: "Jhon Senna", | |||
// cardSecurityNumber: "232", | |||
// cardTypeId: 1, | |||
// city: "Redmon", | |||
// country: "USA", | |||
// state: "WA", | |||
// street: "One way", | |||
// zipcode: "zipcode" | |||
// ); | |||
// return JsonConvert.SerializeObject(order); | |||
// } | |||
// string BuildOrderWithInvalidExperationTime() | |||
// { | |||
// var order = new CreateOrderCommand( | |||
// null, | |||
// cardExpiration: DateTime.UtcNow.AddYears(-1), | |||
// cardNumber: "5145-555-5555", | |||
// cardHolderName: "Jhon Senna", | |||
// cardSecurityNumber: "232", | |||
// cardTypeId: 1, | |||
// city: "Redmon", | |||
// country: "USA", | |||
// state: "WA", | |||
// street: "One way", | |||
// zipcode: "zipcode", | |||
// buyerId: 1, | |||
// paymentId:1 | |||
// ); | |||
// return JsonConvert.SerializeObject(order); | |||
// } | |||
[Fact] | |||
public async Task Get_get_all_stored_orders_and_response_ok_status_code() | |||
{ | |||
using (var server = CreateServer()) | |||
{ | |||
var response = await server.CreateClient() | |||
.GetAsync(Get.Orders); | |||
response.EnsureSuccessStatusCode(); | |||
} | |||
} | |||
[Fact] | |||
public async Task Cancel_order_and_response_ok_status_code() | |||
{ | |||
using (var server = CreateServer()) | |||
{ | |||
var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"); | |||
var response = await server.CreateIdempotentClient() | |||
.PutAsync(Put.CancelOrder, content); | |||
response.EnsureSuccessStatusCode(); | |||
} | |||
} | |||
[Fact] | |||
public async Task Ship_order_and_response_bad_status_code() | |||
{ | |||
using (var server = CreateServer()) | |||
{ | |||
var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"); | |||
var response = await server.CreateIdempotentClient() | |||
.PutAsync(Put.ShipOrder, content); | |||
response.EnsureSuccessStatusCode(); | |||
} | |||
} | |||
string BuildOrder() | |||
{ | |||
var order = new OrderDTO() | |||
{ | |||
OrderNumber = "1" | |||
}; | |||
return JsonConvert.SerializeObject(order); | |||
} | |||
} | |||
} |