Browse Source

Implementing the shipping info, and most of the rfid use case

pull/1240/head
espent1004 5 years ago
parent
commit
63cc274360
9 changed files with 332 additions and 59 deletions
  1. +1
    -1
      docker-compose.dcproj
  2. +3
    -0
      src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs
  3. +109
    -24
      src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs
  4. +133
    -0
      src/Services/TenantCustomisations/TenantACustomisations/Controllers/OrderStatusChangedToSubmittedIntegrationEventsController.cs
  5. +7
    -0
      src/Services/TenantCustomisations/TenantACustomisations/Database/TenantAContext.cs
  6. +3
    -3
      src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/OrderStatusChangedToSubmittedIntegrationEvent.cs
  7. +48
    -11
      src/Web/WebMVC/Controllers/OrderController.cs
  8. +18
    -13
      src/Web/WebMVC/Views/Order/Detail.cshtml
  9. +10
    -7
      src/Web/WebMVC/Views/Order/Index.cshtml

+ 1
- 1
docker-compose.dcproj View File

@ -7,7 +7,7 @@
<DockerServiceName>webmvc</DockerServiceName>
<DockerTargetOS>Linux</DockerTargetOS>
<ProjectVersion>2.1</ProjectVersion>
<DockerLaunchAction>LaunchBrowser</DockerLaunchAction>
<DockerLaunchAction>None</DockerLaunchAction>
</PropertyGroup>
<ItemGroup>
<None Include=".dockerignore" />


+ 3
- 0
src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs View File

@ -34,5 +34,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events
[JsonProperty]
public Boolean CheckForCustomisation { get; set; }
/*[JsonProperty]
public String TenantId { get; set; }*/
}
}

+ 109
- 24
src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs View File

@ -12,10 +12,14 @@ using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using RabbitMQ.Client.Exceptions;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
{
@ -28,15 +32,20 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
private readonly IEventBusSubscriptionsManager _subsManager;
private readonly ILifetimeScope _autofac;
private readonly string AUTOFAC_SCOPE_NAME = "eshop_event_bus";
private static readonly String tenantACustomisationUrl = @"http://tenantacustomisation/";
private static readonly String tenantManagerUrl = @"http://tenantmanager/";
private readonly int _retryCount;
private IModel _consumerChannel;
private string _queueName;
public EventBusRabbitMQ(IRabbitMQPersistentConnection persistentConnection, ILogger<EventBusRabbitMQ> logger,
ILifetimeScope autofac, IEventBusSubscriptionsManager subsManager, string queueName = null, int retryCount = 5)
ILifetimeScope autofac, IEventBusSubscriptionsManager subsManager, string queueName = null,
int retryCount = 5)
{
_persistentConnection = persistentConnection ?? throw new ArgumentNullException(nameof(persistentConnection));
_persistentConnection =
persistentConnection ?? throw new ArgumentNullException(nameof(persistentConnection));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_subsManager = subsManager ?? new InMemoryEventBusSubscriptionsManager();
_queueName = queueName;
@ -76,18 +85,21 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
var policy = RetryPolicy.Handle<BrokerUnreachableException>()
.Or<SocketException>()
.WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) =>
{
_logger.LogWarning(ex, "Could not publish event: {EventId} after {Timeout}s ({ExceptionMessage})", @event.Id, $"{time.TotalSeconds:n1}", ex.Message);
});
.WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
(ex, time) =>
{
_logger.LogWarning(ex,
"Could not publish event: {EventId} after {Timeout}s ({ExceptionMessage})", @event.Id,
$"{time.TotalSeconds:n1}", ex.Message);
});
var eventName = @event.GetType().Name;
_logger.LogWarning("Creating RabbitMQ channel to publish event: {EventId} ({EventName})", @event.Id, eventName);
_logger.LogWarning("Creating RabbitMQ channel to publish event: {EventId} ({EventName})", @event.Id,
eventName);
using (var channel = _persistentConnection.CreateModel())
{
_logger.LogWarning("Declaring RabbitMQ exchange to publish event: {EventId}", @event.Id);
channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct");
@ -115,7 +127,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
public void SubscribeDynamic<TH>(string eventName)
where TH : IDynamicIntegrationEventHandler
{
_logger.LogInformation("Subscribing to dynamic event {EventName} with {EventHandler}", eventName, typeof(TH).GetGenericTypeName());
_logger.LogInformation("Subscribing to dynamic event {EventName} with {EventHandler}", eventName,
typeof(TH).GetGenericTypeName());
DoInternalSubscription(eventName);
_subsManager.AddDynamicSubscription<TH>(eventName);
@ -129,7 +142,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
var eventName = _subsManager.GetEventKey<T>();
DoInternalSubscription(eventName);
_logger.LogInformation("Subscribing to event {EventName} with {EventHandler}", eventName, typeof(TH).GetGenericTypeName());
_logger.LogInformation("Subscribing to event {EventName} with {EventHandler}", eventName,
typeof(TH).GetGenericTypeName());
_subsManager.AddSubscription<T, TH>();
StartBasicConsume();
@ -148,8 +162,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
using (var channel = _persistentConnection.CreateModel())
{
channel.QueueBind(queue: _queueName,
exchange: BROKER_NAME,
routingKey: eventName);
exchange: BROKER_NAME,
routingKey: eventName);
}
}
}
@ -239,13 +253,13 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
var channel = _persistentConnection.CreateModel();
channel.ExchangeDeclare(exchange: BROKER_NAME,
type: "direct");
type: "direct");
channel.QueueDeclare(queue: _queueName,
durable: true,
exclusive: false,
autoDelete: false,
arguments: null);
durable: true,
exclusive: false,
autoDelete: false,
arguments: null);
channel.CallbackException += (sender, ea) =>
{
@ -258,6 +272,60 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
return channel;
}
private async void SendEventToTenant(Object @event)
{
string myJson = JsonConvert.SerializeObject(@event);
using (var client = new HttpClient())
{
try
{
//TODO replace URL with response from tenantmanager
var response = await client.PostAsync(
tenantACustomisationUrl + "api/OrderStatusChangedToSubmittedIntegrationEvents",
new StringContent(myJson, Encoding.UTF8, "application/json"));
response.EnsureSuccessStatusCode();
_logger.LogInformation("----- Event sent to tenant{@event} -----", @event);
}
catch (Exception e)
{
_logger.LogInformation("----- Exception{@e} -- Event{@event} -----", e, @event);
}
}
}
private async Task<Boolean> IsEventCustomised(String eventName, String tenantId)
{
Boolean isCustomised = false;
var builder = new UriBuilder(tenantManagerUrl + "api/Customisations");
builder.Port = -1;
var query = HttpUtility.ParseQueryString(builder.Query);
query["eventName"] = eventName;
query["tenantId"] = tenantId;
builder.Query = query.ToString();
string url = builder.ToString();
using (var client = new HttpClient())
{
try
{
var response = await client.GetAsync(
url);
response.EnsureSuccessStatusCode();
isCustomised =
JsonConvert.DeserializeObject<Boolean>(response.Content.ReadAsStringAsync().Result);
}
catch (Exception e)
{
_logger.LogInformation("----- Exception{@e}", e);
}
}
return isCustomised;
}
private async Task ProcessEvent(string eventName, string message)
{
_logger.LogWarning("Processing RabbitMQ event: {EventName}", eventName);
@ -271,7 +339,9 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
{
if (subscription.IsDynamic)
{
var handler = scope.ResolveOptional(subscription.HandlerType) as IDynamicIntegrationEventHandler;
//TODO check if it is required here aswell
var handler =
scope.ResolveOptional(subscription.HandlerType) as IDynamicIntegrationEventHandler;
if (handler == null) continue;
dynamic eventData = JObject.Parse(message);
@ -281,17 +351,32 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
else
{
var handler = scope.ResolveOptional(subscription.HandlerType);
if (eventName.Equals("OrderStatusChangedToSubmittedIntegrationEvent") || eventName.Equals("UserCheckoutAcceptedIntegrationEvent"))
{
Debug.WriteLine("Here");
}
if (handler == null) continue;
var eventType = _subsManager.GetEventTypeByName(eventName);
var integrationEvent = JsonConvert.DeserializeObject(message, eventType);
//IsEventCustomised(eventName, integrationEvent.TenantId);
if (eventName.Equals("OrderStatusChangedToSubmittedIntegrationEvent") &&
integrationEvent is IntegrationEvent) //TODO replace with tenantmanager
{
//Casting
IntegrationEvent evt = (IntegrationEvent) integrationEvent;
//Checking if event should be sent to tenant, or handled normally
//Can instead create an endpoint in the tenant manager that also handles all the events that a tenant wants to postpone
//Additionally, an endpoint in the tenant manager is required, where the tenant
//Issue with the tenant knowing the id of the event
if (evt.CheckForCustomisation)
{
SendEventToTenant(integrationEvent);
break;
}
}
var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType);
await Task.Yield();
await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent });
await (Task) concreteType.GetMethod("Handle")
.Invoke(handler, new object[] {integrationEvent});
}
}
}
@ -302,4 +387,4 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ
}
}
}
}
}

+ 133
- 0
src/Services/TenantCustomisations/TenantACustomisations/Controllers/OrderStatusChangedToSubmittedIntegrationEventsController.cs View File

@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.Extensions.Logging;
using TenantACustomisations.Database;
using TenantACustomisations.IntegrationEvents.Events;
namespace TenantACustomisations.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class OrderStatusChangedToSubmittedIntegrationEventsController : ControllerBase
{
private readonly TenantAContext _context;
private readonly IEventBus _eventBus;
private readonly ILogger<OrderStatusChangedToSubmittedIntegrationEventsController> _logger;
public OrderStatusChangedToSubmittedIntegrationEventsController(TenantAContext context, IEventBus eventBus, ILogger<OrderStatusChangedToSubmittedIntegrationEventsController> logger)
{
_context = context;
_eventBus = eventBus;
_logger = logger;
}
// GET: api/OrderStatusChangedToSubmittedIntegrationEvents
[HttpGet]
public async Task<ActionResult<IEnumerable<OrderStatusChangedToSubmittedIntegrationEvent>>> GetOrderStatusChangedToSubmittedIntegrationEvent(String orderId)
{
if (String.IsNullOrEmpty(orderId))
{
return await _context.OrderStatusChangedToSubmittedIntegrationEvent.ToListAsync();
}
else
{
var orderStatusChangedToSubmittedIntegrationEvent = _context.OrderStatusChangedToSubmittedIntegrationEvent.Where(x => x.OrderId == Int32.Parse(orderId)).ToListAsync();
return await orderStatusChangedToSubmittedIntegrationEvent;
}
}
// GET: api/OrderStatusChangedToSubmittedIntegrationEvents/5
[HttpGet("{id}")]
public async Task<ActionResult<OrderStatusChangedToSubmittedIntegrationEvent>> GetOrderStatusChangedToSubmittedIntegrationEvent(Guid id)
{
var orderStatusChangedToSubmittedIntegrationEvent = await _context.OrderStatusChangedToSubmittedIntegrationEvent.FindAsync(id);
if (orderStatusChangedToSubmittedIntegrationEvent == null)
{
return NotFound();
}
return orderStatusChangedToSubmittedIntegrationEvent;
}
// PUT: api/OrderStatusChangedToSubmittedIntegrationEvents/5
[HttpPut("{id}")]
public async Task<IActionResult> PutOrderStatusChangedToSubmittedIntegrationEvent(Guid id, OrderStatusChangedToSubmittedIntegrationEvent orderStatusChangedToSubmittedIntegrationEvent)
{
if (id != orderStatusChangedToSubmittedIntegrationEvent.Id)
{
return BadRequest();
}
_context.Entry(orderStatusChangedToSubmittedIntegrationEvent).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!OrderStatusChangedToSubmittedIntegrationEventExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
// POST: api/OrderStatusChangedToSubmittedIntegrationEvents
[HttpPost]
public async Task<ActionResult<OrderStatusChangedToSubmittedIntegrationEvent>> PostOrderStatusChangedToSubmittedIntegrationEvent(OrderStatusChangedToSubmittedIntegrationEvent orderStatusChangedToSubmittedIntegrationEvent)
{
_context.OrderStatusChangedToSubmittedIntegrationEvent.Add(orderStatusChangedToSubmittedIntegrationEvent);
await _context.SaveChangesAsync();
return CreatedAtAction("GetOrderStatusChangedToSubmittedIntegrationEvent", new { id = orderStatusChangedToSubmittedIntegrationEvent.Id }, orderStatusChangedToSubmittedIntegrationEvent);
}
// DELETE: api/OrderStatusChangedToSubmittedIntegrationEvents/5
[HttpDelete("{id}")]
public async Task<ActionResult<OrderStatusChangedToSubmittedIntegrationEvent>> DeleteOrderStatusChangedToSubmittedIntegrationEvent(Guid id)
{
var orderStatusChangedToSubmittedIntegrationEvent = await _context.OrderStatusChangedToSubmittedIntegrationEvent.FindAsync(id);
if (orderStatusChangedToSubmittedIntegrationEvent == null)
{
return NotFound();
}
try
{
_logger.LogInformation("----- Publishing integration event: {IntegrationEventId} from OrderStatusChangedToSubmittedIntegrationEventsController - ({@IntegrationEvent})", orderStatusChangedToSubmittedIntegrationEvent.Id, orderStatusChangedToSubmittedIntegrationEvent);
orderStatusChangedToSubmittedIntegrationEvent.CheckForCustomisation = false;
_eventBus.Publish(orderStatusChangedToSubmittedIntegrationEvent);
_context.OrderStatusChangedToSubmittedIntegrationEvent.Remove(orderStatusChangedToSubmittedIntegrationEvent);
await _context.SaveChangesAsync();
return orderStatusChangedToSubmittedIntegrationEvent;
}
catch (Exception ex)
{
_logger.LogError(ex, "ERROR Publishing integration event: {IntegrationEventId} from OrderStatusChangedToSubmittedIntegrationEventsController", orderStatusChangedToSubmittedIntegrationEvent.Id);
throw;
}
}
private bool OrderStatusChangedToSubmittedIntegrationEventExists(Guid id)
{
return _context.OrderStatusChangedToSubmittedIntegrationEvent.Any(e => e.Id == id);
}
}
}

+ 7
- 0
src/Services/TenantCustomisations/TenantACustomisations/Database/TenantAContext.cs View File

@ -5,6 +5,7 @@ using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using TenantACustomisations.ExternalServices;
using TenantACustomisations.IntegrationEvents.Events;
namespace TenantACustomisations.Database
{
@ -17,6 +18,12 @@ namespace TenantACustomisations.Database
public DbSet<ShippingInformation> ShippingInformation { get; set; }
public DbSet<OrderStatusChangedToSubmittedIntegrationEvent> OrderStatusChangedToSubmittedIntegrationEvent
{
get;
set;
}
}
public class TenantAContextDesignFactory : IDesignTimeDbContextFactory<TenantAContext>
{


+ 3
- 3
src/Services/TenantCustomisations/TenantACustomisations/IntegrationEvents/Events/OrderStatusChangedToSubmittedIntegrationEvent.cs View File

@ -8,9 +8,9 @@ namespace TenantACustomisations.IntegrationEvents.Events
{
public class OrderStatusChangedToSubmittedIntegrationEvent : IntegrationEvent
{
public int OrderId { get; }
public string OrderStatus { get; }
public string BuyerName { get; }
public int OrderId { get; set; }
public string OrderStatus { get; set; }
public string BuyerName { get; set; }
public OrderStatusChangedToSubmittedIntegrationEvent(int orderId, string orderStatus, string buyerName)
{


+ 48
- 11
src/Web/WebMVC/Controllers/OrderController.cs View File

@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopOnContainers.WebMVC.Services;
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
using Microsoft.eShopOnContainers.WebMVC.ViewModels.Customisation;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Polly.CircuitBreaker;
using System;
@ -11,6 +12,7 @@ using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
namespace Microsoft.eShopOnContainers.WebMVC.Controllers
{
@ -20,18 +22,21 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
private IOrderingService _orderSvc;
private IBasketService _basketSvc;
private readonly IIdentityParser<ApplicationUser> _appUserParser;
private static String url = @"http://tenantacustomisation/";
private static String tenantACustomisationsUrl = @"http://tenantacustomisation/";
private readonly ILogger<OrderController> _logger;
public OrderController(IOrderingService orderSvc, IBasketService basketSvc, IIdentityParser<ApplicationUser> appUserParser)
public OrderController(IOrderingService orderSvc, IBasketService basketSvc,
IIdentityParser<ApplicationUser> appUserParser, ILogger<OrderController> logger)
{
_appUserParser = appUserParser;
_orderSvc = orderSvc;
_basketSvc = basketSvc;
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task<IActionResult> Create()
{
var user = _appUserParser.Parse(HttpContext.User);
var order = await _basketSvc.GetOrderDraft(user.Id);
var vm = _orderSvc.MapUserInfoIntoOrder(user, order);
@ -58,7 +63,8 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
}
catch (BrokenCircuitException)
{
ModelState.AddModelError("Error", "It was not possible to create a new order, please try later on. (Business Msg Due to Circuit-Breaker)");
ModelState.AddModelError("Error",
"It was not possible to create a new order, please try later on. (Business Msg Due to Circuit-Breaker)");
}
return View("Create", model);
@ -75,6 +81,8 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
public async Task<IActionResult> Detail(string orderId)
{
var user = _appUserParser.Parse(HttpContext.User);
Boolean RFIDScanned = await AllGoodsRFIDScanned(orderId);
ViewData["RFIDScanned"] = RFIDScanned;
var order = await _orderSvc.GetOrder(user, orderId);
return View(order);
@ -85,34 +93,63 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
var user = _appUserParser.Parse(HttpContext.User);
var vm = await _orderSvc.GetMyOrders(user);
List<ShippingInformation> shippingInformation = GetShippingInfo(vm);
_logger.LogInformation("----- Shipping info{@ShippingInformation}", shippingInformation);
ViewData["ShippingInfo"] = shippingInformation;
return View(vm);
}
private async Task<Boolean> AllGoodsRFIDScanned(String orderId)
{
var builder = new UriBuilder(tenantACustomisationsUrl + "api/OrderStatusChangedToSubmittedIntegrationEvents");
builder.Port = -1;
var query = HttpUtility.ParseQueryString(builder.Query);
query["orderId"] = orderId;
builder.Query = query.ToString();
string url = builder.ToString();
using (var client = new HttpClient())
{
var response = await client.GetAsync(
url);
if (response.StatusCode.Equals(HttpStatusCode.NotFound))
{
return true;
}
return false;
}
}
private List<ShippingInformation> GetShippingInfo(List<Order> orders)
{
List<ShippingInformation> shippingInformation = new List<ShippingInformation>();
using (var client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }))
using (var client = new HttpClient(new HttpClientHandler
{AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate}))
{
client.BaseAddress = new Uri(url);
client.BaseAddress = new Uri(tenantACustomisationsUrl);
try
{
HttpResponseMessage response = client.GetAsync("api/shippinginformation").Result;
HttpResponseMessage response = client.GetAsync("api/shippinginformations").Result;
response.EnsureSuccessStatusCode();
string result = response.Content.ReadAsStringAsync().Result;
List<ShippingInformation> results = JsonConvert.DeserializeObject<List<ShippingInformation>>(result);
results.ForEach( s =>
_logger.LogInformation("----- Result{@result} -----", result);
List<ShippingInformation>
results = JsonConvert.DeserializeObject<List<ShippingInformation>>(result);
results.ForEach(s =>
{
if(orders.Any(item => item.OrderNumber.Equals(s.OrderNumber)))
if (orders.Any(item => item.OrderNumber.Equals(s.OrderNumber)))
{
shippingInformation.Add(s);
}
});
}
catch (Exception e)
{
Console.WriteLine(e);
_logger.LogInformation("----- Exception{@e} -----", e);
}
}


+ 18
- 13
src/Web/WebMVC/Views/Order/Detail.cshtml View File

@ -3,9 +3,12 @@
@model Microsoft.eShopOnContainers.WebMVC.ViewModels.Order
@{
ViewData["Title"] = "Order Detail";
var headerList= new List<Header>() {
new Header() { Controller = "Catalog", Text = "Back to catalog" } };
ViewData["Title"] = "Order Detail";
var headerList = new List<Header>()
{
new Header() {Controller = "Catalog", Text = "Back to catalog"}
};
var rfidScanned = ViewData["RFIDScanned"];
}
<div class="esh-orders_detail">
@ -14,20 +17,22 @@
<div class="container">
<section class="esh-orders_detail-section">
<article class="esh-orders_detail-titles row">
<section class="esh-orders_detail-title col-3">Order number</section>
<section class="esh-orders_detail-title col-3">Date</section>
<section class="esh-orders_detail-title col-3">Total</section>
<section class="esh-orders_detail-title col-3">Status</section>
<section class="esh-orders_detail-title col-2">Order number</section>
<section class="esh-orders_detail-title col-2">Date</section>
<section class="esh-orders_detail-title col-2">Total</section>
<section class="esh-orders_detail-title col-2">Status</section>
<section class="esh-orders_detail-title col-2">RFID Scanned</section>
</article>
<article class="esh-orders_detail-items row">
<section class="esh-orders_detail-item col-3">@Model.OrderNumber</section>
<section class="esh-orders_detail-item col-3">@Model.Date</section>
<section class="esh-orders_detail-item col-3">$@Model.Total</section>
<section class="esh-orders_detail-title col-3">@Model.Status</section>
<section class="esh-orders_detail-item col-2">$@Model.Total</section>
<section class="esh-orders_detail-item col-2">@Model.OrderNumber</section>
<section class="esh-orders_detail-item col-2">@Model.Date</section>
<section class="esh-orders_detail-title col-2">@Model.Status</section>
<section class="esh-orders_detail-title col-2">@rfidScanned</section>
</article>
</section>
<section class="esh-orders_detail-section">
<article class="esh-orders_detail-titles row">
<section class="esh-orders_detail-title col-12">Description</section>
@ -88,4 +93,4 @@
</article>
</section>
</div>
</div>
</div>

+ 10
- 7
src/Web/WebMVC/Views/Order/Index.cshtml View File

@ -18,7 +18,7 @@
<div class="container">
<article class="esh-orders-titles row">
<section class="esh-orders-title col-2">Order number</section>
<section class="esh-orders-title col-1">Order number</section>
<section class="esh-orders-title col-2">Date</section>
<section class="esh-orders-title col-1">Total</section>
<section class="esh-orders-title col-1">Status</section>
@ -32,26 +32,29 @@
foreach (var item in Model)
{
<article class="esh-orders-items row">
<section class="esh-orders-item col-2">@Html.DisplayFor(modelItem => item.OrderNumber)</section>
<section class="esh-orders-item col-2">@Html.DisplayFor(modelItem => item.Date)</section>
<section class="esh-orders-item col-1">@Html.DisplayFor(modelItem => item.OrderNumber)</section>
<section class="esh-orders-item col-2">@item.Date.ToShortDateString()</section>
<section class="esh-orders-item col-1">$ @Html.DisplayFor(modelItem => item.Total)</section>
<section class="esh-orders-item col-1">@Html.DisplayFor(modelItem => item.Status)</section>
<section class="esh-orders-item col-2">
@for (var i = 0; i < shippingInfo.Count(); i++)
{
var si = shippingInfo[i];
if (si.OrderNumber.Equals(item.OrderNumber)){
@si.ShippingTime
if (si.OrderNumber.Equals(item.OrderNumber))
{
@si.ShippingTime.ToShortDateString();
break;
}
}
</section>
</section>
<section class="esh-orders-item col-2">
@for (var i = 0; i < shippingInfo.Count(); i++)
{
var si = shippingInfo[i];
if (si.OrderNumber.Equals(item.OrderNumber))
{
@si.ArrivalTime
@si.ArrivalTime.ToShortDateString();
break;
}
}
</section>


Loading…
Cancel
Save