How to refactor this LINQ query for a reports dashboard in Blazor Server Application?

Cenk 991 Reputation points
2024-02-08T07:25:08.1933333+00:00

I am building a reports dashboard on my Blazor Server Application that displays the count of the last 3 years of "Completed" and "Continues" orders. The business rules are:

  1. Completed order means OrderDetails CompletionDateTime is not null (Status = Completed).
  2. There are 4 statuses (Warehouse, Completed, Order Opened, Shipped).
  3. Statuses other than "Completed" should be counted as "Continues".

I need help refactoring my LINQ query to meet these requirements. The code and relevant classes are given below.

public async Task<ICollection<ReportAnnualDto>> GetAnnuallyOrders()
{
    await using var ctx = await _db.CreateDbContextAsync();
    var allYears = Enumerable.Range(DateTime.Now.Year - 2, 3); // last 3 years including this year
    var allStatuses = new List<string> { "Completed", "Continues" };
    var orders = await ctx.Orders.AsNoTracking()
        .GroupBy(x => new { Year = x.OrderDateTime.Year, Status = x.Status })
        .Select(u => new ReportAnnualDto()
        {
            Year = u.Key.Year,
            Status = u.Key.Status,
            Count = u.Count()
        })
        .ToListAsync();
    var result = allYears.SelectMany(year => allStatuses,
        (year, status) => new { Year = year, Status = status })
        .GroupJoin(
            orders,
            all => new { all.Year, all.Status },
            order => new { order.Year, order.Status },
            (all, orderGroup) => orderGroup
                .Select(order => new ReportAnnualDto { Year = all.Year, Status = all.Status, Count = order.Count })
                .DefaultIfEmpty(new ReportAnnualDto { Year = all.Year, Status = all.Status, Count = 0 }))
        .SelectMany(group => group)
        .OrderBy(u => u.Year)
        .ToList();
    return result;
}


public class Order
{
    
    public int Id { get; set; }
    
    [Required]
    public DateTime OrderDateTime { get; set; }
    [Required]
    [MaxLength(250)]
    public int CustomerId { get; set; }
    public string Status { get; set; }
    [MaxLength(50)]
    public string DoneBy { get; set; }
    public List<OrderDetail> OrderDetails { get; set; }
    public Customer Customer { get; set; }
}
public class OrderDetail
{
    public int Id { get; set; }
    [Required]
    [MaxLength(100)]
    public string ProductCode { get; set; }
    [MaxLength(250)]
    public string? ProductName { get; set; }
    [Required]
    public int Quantity { get; set; }
    [Required]
    public double BuyUnitPrice { get; set; }
    public double CostRatio { get; set; }
    public double UnitCost { get; set; }
    public double TotalBuyPrice { get; set; }
    public double? SellUnitPrice { get; set; }
    public double? TotalSellPrice { get; set; }
    [MaxLength(150)]
    public string? ShippingNumber { get; set; }
    public string? Status { get; set; }
    [MaxLength(150)]
    public string? TrackingNumber { get; set; }
    [MaxLength(400)]
    public string? Description { get; set; }
    public string? Currency { get; set; }
    public string? CustomerStockCode { get; set; }
    public string? CustomerOrderNumber { get; set; }
    public int IsActive { get; set; }
    public double? TotalUnitCost { get; set; }
    public int OrderId { get; set; }
    public int VendorId { get; set; }
    public string? Warehouse { get; set; }
    public string? PaymentStatus { get; set; }
    public Order Order { get; set; }
    public Vendor Vendor { get; set; }
    [DataType(DataType.DateTime)]
    public DateTime? CompletionDateTime { get; set; }
    public int? ShippingWeek { get; set; }
    public string? PoNotes { get; set; }
}


User's image

Entity Framework Core
Entity Framework Core
A lightweight, extensible, open-source, and cross-platform version of the Entity Framework data access technology.
726 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,661 questions
{count} votes