Skip to content

Commit

Permalink
Solving issues with no products in details. (#340)
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 authored and losolio committed Jan 5, 2020
1 parent 9a58e07 commit 2c8a919
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 2c8a919

Please sign in to comment.