Skip to content

Commit

Permalink
Solving issues with no products in details.
Browse files Browse the repository at this point in the history
The issue was, ValueTuples aren't serialized properly. Here's the link dotnet/runtime#876.
For now, we shouldn't use ValueTuples for DTOs at all, instead we need to create DTO classes for each part of the response.

+ Integration test.
  • Loading branch information
andy-a-o committed Jan 5, 2020
1 parent 9a58e07 commit 4976f9a
Show file tree
Hide file tree
Showing 8 changed files with 293 additions and 48 deletions.
91 changes: 50 additions & 41 deletions src/EventManagement.Web/Pages/Admin/Events/Details.cshtml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,14 @@ public async Task<JsonResult> OnGetParticipants(int? id)
{
if (id == null)
{
return new JsonResult("No event id submitted.");
return new JsonResult("No event id submitted.");
}

var registrations = await _context.Registrations
.Where(
r => r.EventInfoId == id &&
r.Status != RegistrationStatus.Cancelled &&
r.Type == RegistrationType.Participant)
.Include(r => r.Products)
.ThenInclude(p => p.Product)
.Include(r => r.Products)
.ThenInclude(p => p.Variant)
.Include(r => r.Orders)
.ThenInclude(o => o.OrderLines)
.ThenInclude(ol => ol.Product)
Expand All @@ -81,20 +77,19 @@ public async Task<JsonResult> OnGetParticipants(int? id)
Notes = x.Notes,
Employer = x.ParticipantEmployer,
City = x.ParticipantCity,
Products = x.Products.Select(dto => ValueTuple.Create(
new RegistrationsProductVm(dto.Product),
RegistrationsVariantVm.Create(dto.Variant),
dto.Quantity)).ToList(),
Products = x.Products.Select(dto => new RegistrationOrderVm(dto)).ToList(),
HasCertificate = x.HasCertificate,
CertificateId = x.CertificateId,
Status = x.Status.ToString(),
Type = x.Type.ToString()
});

if (vms.Any()) {
if (vms.Any())
{
return new JsonResult(vms);
}
else {
else
{
return new JsonResult("none");
}
}
Expand All @@ -103,18 +98,14 @@ public async Task<JsonResult> OnGetOtherAttendees(int? id)
{
if (id == null)
{
return new JsonResult("No event id submitted.");
return new JsonResult("No event id submitted.");
}

var registrations = await _context.Registrations
.Where(
r => r.EventInfoId == id &&
r.Status != RegistrationStatus.Cancelled &&
r.Type != RegistrationType.Participant)
.Include(r => r.Products)
.ThenInclude(p => p.Product)
.Include(r => r.Products)
.ThenInclude(p => p.Variant)
.Include(r => r.Orders)
.ThenInclude(o => o.OrderLines)
.ThenInclude(ol => ol.Product)
Expand All @@ -134,20 +125,19 @@ public async Task<JsonResult> OnGetOtherAttendees(int? id)
Employer = x.ParticipantEmployer,
City = x.ParticipantCity,
Notes = x.Notes,
Products = x.Products.Select(dto => ValueTuple.Create(
new RegistrationsProductVm(dto.Product),
RegistrationsVariantVm.Create(dto.Variant),
dto.Quantity)).ToList(),
Products = x.Products.Select(dto => new RegistrationOrderVm(dto)).ToList(),
HasCertificate = x.HasCertificate,
CertificateId = x.CertificateId,
Status = x.Status.ToString(),
Type = x.Type.ToString()
});

if (vms.Any()) {
if (vms.Any())
{
return new JsonResult(vms);
}
else {
else
{
return new JsonResult("none");
}
}
Expand All @@ -156,14 +146,15 @@ public async Task<JsonResult> OnGetCancelled(int? id)
{
if (id == null)
{
return new JsonResult("No event id submitted.");
return new JsonResult("No event id submitted.");
}

var registrations = await _context.Registrations
.Where(
r => r.EventInfoId == id &&
r.Status == RegistrationStatus.Cancelled)
.Select ( x=> new RegistrationsVm{
.Select(x => new RegistrationsVm
{
RegistrationId = x.RegistrationId,
Name = x.User.Name,
Email = x.User.Email,
Expand All @@ -177,34 +168,35 @@ public async Task<JsonResult> OnGetCancelled(int? id)
CertificateId = x.CertificateId,
Status = x.Status.ToString(),
Type = x.Type.ToString()
})
})
.ToListAsync();

if (registrations.Any()) {
if (registrations.Any())
{
return new JsonResult(registrations);
}
else {
else
{
return new JsonResult("none");
}
}

internal class RegistrationsVm
{
public int RegistrationId {get;set;}
public string Name { set;get;}
public string Email { set;get;}
public string userId {get;set;}
public string Phone { set;get;}
public string Employer {get;set;}
public string Notes {get;set;}
public string JobTitle {get;set;}
public string City {get;set;}
public int RegistrationId { get; set; }
public string Name { set; get; }
public string Email { set; get; }
public string userId { get; set; }
public string Phone { set; get; }
public string Employer { get; set; }
public string Notes { get; set; }
public string JobTitle { get; set; }
public string City { get; set; }
public bool HasCertificate { get; set; }
public int? CertificateId {get; set; }
public string Status {get;set;}
public string Type {get;set;}
// public List<(Product, ProductVariant, int)> Products { get; set; }
public List<(RegistrationsProductVm, RegistrationsVariantVm, int)> Products { get; set; }
public int? CertificateId { get; set; }
public string Status { get; set; }
public string Type { get; set; }
public List<RegistrationOrderVm> Products { get; set; }
}

internal class RegistrationsProductVm
Expand Down Expand Up @@ -233,5 +225,22 @@ public RegistrationsVariantVm(ProductVariant variant)
variant == null ? null : new RegistrationsVariantVm(variant);
}

internal class RegistrationOrderVm
{
public RegistrationsProductVm Item1 { get; }
public RegistrationsVariantVm Item2 { get; }
public int Item3 { get; }

public RegistrationOrderVm(OrderDTO dto) : this(dto.Product, dto.Variant, dto.Quantity)
{
}

public RegistrationOrderVm(Product product, ProductVariant variant, int quantity)
{
this.Item1 = new RegistrationsProductVm(product);
this.Item2 = RegistrationsVariantVm.Create(variant);
this.Item3 = quantity;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,112 @@
using losol.EventManagement.Domain;
using losol.EventManagement.Infrastructure;
using System;
using System.Linq;
using System.Threading.Tasks;

namespace losol.EventManagement.IntegrationTests
{
public static class ApplicationDbContextExtensions
{
public static async Task<IDisposableEntity<Registration>> NewRegistrationAsync(
public const string Placeholder = "__Placeholder__";

public static async Task<IDisposableEntity<EventInfo>> CreateEventAsync(
this ApplicationDbContext context,
string title = Placeholder,
string description = Placeholder,
string code = Placeholder,
string city = Placeholder,
EventInfo.EventInfoType eventInfoType = EventInfo.EventInfoType.Conference,
bool featured = false,
DateTime? dateStart = null,
DateTime? dateEnd = null,
Product[] products = null)
{
if (title == Placeholder)
{
title = $"Test Event {Guid.NewGuid()}";
}

if (description == Placeholder)
{
description = $"Test Event Description {Guid.NewGuid()}";
}

if (code == Placeholder)
{
code = Guid.NewGuid().ToString();
}

var eventInfo = new EventInfo
{
Title = title,
Description = description,
Code = code,
Featured = featured,
DateStart = dateStart,
DateEnd = dateEnd,
Type = eventInfoType,
City = city,
Products = products?.ToList()
};
context.EventInfos.Add(eventInfo);
await context.SaveChangesAsync();
return new DisposableEntity<EventInfo>(eventInfo, context);
}

public static async Task<IDisposableEntity<Product>> CreateProductAsync(
this ApplicationDbContext context,
EventInfo eventInfo,
string name = Placeholder,
int vatPercent = 5,
int minimumQuantity = 1,
ProductVariant[] variants = null)
{

if (name == Placeholder)
{
name = $"Test Product {Guid.NewGuid()}";
}

var product = new Product
{
Name = name,
Eventinfo = eventInfo,
VatPercent = vatPercent,
MinimumQuantity = minimumQuantity,
ProductVariants = variants?.ToList()
};

context.Products.Add(product);
await context.SaveChangesAsync();
return new DisposableEntity<Product>(product, context);
}

public static async Task<IDisposableEntity<ProductVariant>> CreateProductVariantAsync(
this ApplicationDbContext context,
Product product,
string name = Placeholder,
int vatPercent = 5)
{
if (name == Placeholder)
{
name = $"Test Product Variant {Guid.NewGuid()}";
}

var variant = new ProductVariant
{
Product = product,
Name = name,
VatPercent = vatPercent
// TODO: add other props
};

context.ProductVariants.Add(variant);
await context.SaveChangesAsync();
return new DisposableEntity<ProductVariant>(variant, context);
}

public static async Task<IDisposableEntity<Registration>> CreateRegistrationAsync(
this ApplicationDbContext context,
EventInfo eventInfo,
ApplicationUser user,
Expand All @@ -24,5 +124,30 @@ public static class ApplicationDbContextExtensions
await context.SaveChangesAsync();
return new DisposableEntity<Registration>(registration, context);
}

public static async Task<IDisposableEntity<Order>> CreateOrderAsync(
this ApplicationDbContext context,
Registration registration,
Product[] products,
Order.OrderStatus status = Order.OrderStatus.Verified)
{
var order = new Order
{
Registration = registration,
Status = status,
OrderLines = products?.Select(p => new OrderLine
{
Product = p,
VatPercent = p.VatPercent,
Price = p.Price,
ProductName = p.Name,
Quantity = p.MinimumQuantity
}).ToList()
};

context.Orders.Add(order);
await context.SaveChangesAsync();
return new DisposableEntity<Order>(order, context);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ public async Task Should_Send_Register_Email(string languageCode, string textToC
var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

var eventInfo = SeedData.Events[0];
using var user = await scope.ServiceProvider.NewUserAsync();
using var registration = await context.NewRegistrationAsync(eventInfo, user.Entity);
using var user = await scope.ServiceProvider.CreateUserAsync();
using var registration = await context.CreateRegistrationAsync(eventInfo, user.Entity);

var emailExpectation = this.factory.EmailSenderMock
.ExpectEmail()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ public async Task Should_Send_Email_To_Participants(string languageCode, string
var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

var eventInfo = SeedData.Events[0];
using var user = await scope.ServiceProvider.NewUserAsync();
using var registration = await context.NewRegistrationAsync(eventInfo, user.Entity);
using var user = await scope.ServiceProvider.CreateUserAsync();
using var registration = await context.CreateRegistrationAsync(eventInfo, user.Entity);

var emailExpectation = this.factory.EmailSenderMock
.ExpectEmail()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public async Task Should_Send_Magic_Link_Email(string languageCode, string textT
client.AcceptLanguage(languageCode);

using var scope = this.factory.Services.NewScope();
using var user = await scope.ServiceProvider.NewUserAsync();
using var user = await scope.ServiceProvider.CreateUserAsync();

var emailExpectation = this.factory.EmailSenderMock
.ExpectEmail()
Expand Down
Loading

0 comments on commit 4976f9a

Please sign in to comment.