initial commit
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
public class AccummulationChartItem
|
||||
{
|
||||
public string X { get; init; } = string.Empty;
|
||||
public double Y { get; init; } = 0.0;
|
||||
public string Text { get; init; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
public class BarDataItem
|
||||
{
|
||||
public string X { get; set; } = string.Empty;
|
||||
public int Y { get; set; }
|
||||
public string TooltipMappingName { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
public class BarSeries
|
||||
{
|
||||
public string Type { get; set; } = string.Empty;
|
||||
public string XName { get; set; } = string.Empty;
|
||||
public int Width { get; set; }
|
||||
public string YName { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public double ColumnSpacing { get; set; }
|
||||
public string TooltipMappingName { get; set; } = string.Empty;
|
||||
public List<BarDataItem> DataSource { get; set; } = new List<BarDataItem>();
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
public class CRMItem
|
||||
{
|
||||
public double? CampaignTotalAmount { get; init; }
|
||||
public double? LeadTotalAmount { get; init; }
|
||||
public double? BudgetTotalAmount { get; init; }
|
||||
public double? ExpenseTotalAmount { get; init; }
|
||||
public double? ClosedTotalAmount { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
public class CardsItem
|
||||
{
|
||||
public double? SalesTotal { get; init; }
|
||||
public double? SalesReturnTotal { get; init; }
|
||||
public double? PurchaseTotal { get; init; }
|
||||
public double? PurchaseReturnTotal { get; init; }
|
||||
public double? DeliveryOrderTotal { get; init; }
|
||||
public double? GoodsReceiveTotal { get; init; }
|
||||
public double? TransferOutTotal { get; init; }
|
||||
public double? TransferInTotal { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
|
||||
public class GetCRMDashboardDto
|
||||
{
|
||||
public CRMItem? CRMDashboard { get; init; }
|
||||
}
|
||||
|
||||
public class GetCRMDashboardResult
|
||||
{
|
||||
public GetCRMDashboardDto? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetCRMDashboardRequest : IRequest<GetCRMDashboardResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetCRMDashboardHandler : IRequestHandler<GetCRMDashboardRequest, GetCRMDashboardResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetCRMDashboardHandler(IQueryContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetCRMDashboardResult> Handle(GetCRMDashboardRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var campaignTotalAmount = await _context.Campaign
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.SumAsync(x => (double?)x.TargetRevenueAmount, cancellationToken);
|
||||
|
||||
var closedTotalAmount = await _context.Lead
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Where(x => x.ClosingStatus == ClosingStatus.ClosedWon)
|
||||
.SumAsync(x => (double?)x.AmountClosed, cancellationToken);
|
||||
|
||||
var leadTotalAmount = await _context.Lead
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.SumAsync(x => (double?)x.AmountTargeted, cancellationToken);
|
||||
|
||||
var budgetTotalAmount = await _context.Budget
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.SumAsync(x => (double?)x.Amount, cancellationToken);
|
||||
|
||||
var expenseTotalAmount = await _context.Expense
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.SumAsync(x => (double?)x.Amount, cancellationToken);
|
||||
|
||||
|
||||
var cardsDashboardData = new CRMItem
|
||||
{
|
||||
CampaignTotalAmount = campaignTotalAmount,
|
||||
LeadTotalAmount = leadTotalAmount,
|
||||
BudgetTotalAmount = budgetTotalAmount,
|
||||
ExpenseTotalAmount = expenseTotalAmount,
|
||||
ClosedTotalAmount = closedTotalAmount
|
||||
};
|
||||
|
||||
|
||||
|
||||
var result = new GetCRMDashboardResult
|
||||
{
|
||||
Data = new GetCRMDashboardDto
|
||||
{
|
||||
CRMDashboard = cardsDashboardData
|
||||
}
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
public class GetCampaignByStatusResult
|
||||
{
|
||||
public List<AccummulationChartItem>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetCampaignByStatusRequest : IRequest<GetCampaignByStatusResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetCampaignByStatusHandler : IRequestHandler<GetCampaignByStatusRequest, GetCampaignByStatusResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetCampaignByStatusHandler(IQueryContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetCampaignByStatusResult> Handle(GetCampaignByStatusRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var groupedCampaigns = await _context.Set<Campaign>()
|
||||
.GroupBy(c => c.Status)
|
||||
.Select(g => new { Status = g.Key, Count = g.Count() })
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var result = groupedCampaigns.Select(g => new AccummulationChartItem
|
||||
{
|
||||
X = g.Status.HasValue ? ((CampaignStatus)g.Status).ToFriendlyName() : string.Empty,
|
||||
Y = (double)g.Count,
|
||||
Text = g.Status.HasValue
|
||||
? $"{((CampaignStatus)g.Status).ToFriendlyName()} ({g.Count})"
|
||||
: $"Unknown ({g.Count})"
|
||||
}).ToList();
|
||||
|
||||
return new GetCampaignByStatusResult { Data = result };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
|
||||
public class GetCardsDashboardDto
|
||||
{
|
||||
public CardsItem? CardsDashboard { get; init; }
|
||||
}
|
||||
|
||||
public class GetCardsDashboardResult
|
||||
{
|
||||
public GetCardsDashboardDto? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetCardsDashboardRequest : IRequest<GetCardsDashboardResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetCardsDashboardHandler : IRequestHandler<GetCardsDashboardRequest, GetCardsDashboardResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetCardsDashboardHandler(IQueryContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetCardsDashboardResult> Handle(GetCardsDashboardRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var salesTotal = await _context.SalesOrderItem
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.SumAsync(x => (double?)x.Quantity, cancellationToken);
|
||||
|
||||
var purchaseTotal = await _context.PurchaseOrderItem
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.SumAsync(x => (double?)x.Quantity, cancellationToken);
|
||||
|
||||
var cardsDashboardData = new CardsItem
|
||||
{
|
||||
SalesTotal = salesTotal,
|
||||
PurchaseTotal = purchaseTotal,
|
||||
};
|
||||
|
||||
|
||||
|
||||
var result = new GetCardsDashboardResult
|
||||
{
|
||||
Data = new GetCardsDashboardDto
|
||||
{
|
||||
CardsDashboard = cardsDashboardData
|
||||
}
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
public class GetLeadActivityByTypeResult
|
||||
{
|
||||
public List<AccummulationChartItem>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadActivityByTypeRequest : IRequest<GetLeadActivityByTypeResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetLeadActivityByTypeHandler : IRequestHandler<GetLeadActivityByTypeRequest, GetLeadActivityByTypeResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetLeadActivityByTypeHandler(IQueryContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetLeadActivityByTypeResult> Handle(GetLeadActivityByTypeRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var groupedActivities = await _context.Set<LeadActivity>()
|
||||
.GroupBy(a => a.Type)
|
||||
.Select(g => new { Type = g.Key, Count = g.Count() })
|
||||
.OrderBy(g => g.Count)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var result = groupedActivities.Select(g => new AccummulationChartItem
|
||||
{
|
||||
X = g.Type.HasValue ? ((LeadActivityType)g.Type).ToFriendlyName() : string.Empty,
|
||||
Y = (double)g.Count,
|
||||
Text = g.Type.HasValue
|
||||
? $"{((LeadActivityType)g.Type).ToFriendlyName()} ({g.Count})"
|
||||
: $"Unknown ({g.Count})"
|
||||
}).ToList();
|
||||
|
||||
return new GetLeadActivityByTypeResult { Data = result };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
public class GetLeadPipelineFunnelResult
|
||||
{
|
||||
public List<AccummulationChartItem>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetLeadPipelineFunnelRequest : IRequest<GetLeadPipelineFunnelResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetLeadPipelineFunnelHandler : IRequestHandler<GetLeadPipelineFunnelRequest, GetLeadPipelineFunnelResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetLeadPipelineFunnelHandler(IQueryContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetLeadPipelineFunnelResult> Handle(GetLeadPipelineFunnelRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var groupedLeads = await _context.Set<Lead>()
|
||||
.GroupBy(l => l.PipelineStage)
|
||||
.Select(g => new { Stage = g.Key, Count = g.Count() })
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var result = groupedLeads.Select(g => new
|
||||
{
|
||||
Item = new AccummulationChartItem
|
||||
{
|
||||
X = g.Stage.HasValue ? ((PipelineStage)g.Stage).ToFriendlyName() : string.Empty,
|
||||
Y = g.Count,
|
||||
Text = g.Stage.HasValue
|
||||
? $"{((PipelineStage)g.Stage).ToFriendlyName()} ({g.Count})"
|
||||
: $"Unknown ({g.Count})"
|
||||
},
|
||||
OrderKey = g.Stage.HasValue ? ((PipelineStage)g.Stage).ToFriendlyName() : string.Empty
|
||||
})
|
||||
.OrderByDescending(i => i.OrderKey)
|
||||
.Select(i => i.Item)
|
||||
.ToList();
|
||||
|
||||
return new GetLeadPipelineFunnelResult { Data = result };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
|
||||
public class GetPurchaseDashboardDto
|
||||
{
|
||||
public List<PurchaseOrderItem>? PurchaseOrderDashboard { get; init; }
|
||||
public List<BarSeries>? PurchaseByVendorGroupDashboard { get; init; }
|
||||
public List<BarSeries>? PurchaseByVendorCategoryDashboard { get; init; }
|
||||
}
|
||||
|
||||
public class GetPurchaseDashboardResult
|
||||
{
|
||||
public GetPurchaseDashboardDto? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetPurchaseDashboardRequest : IRequest<GetPurchaseDashboardResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetPurchaseDashboardHandler : IRequestHandler<GetPurchaseDashboardRequest, GetPurchaseDashboardResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetPurchaseDashboardHandler(IQueryContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetPurchaseDashboardResult> Handle(GetPurchaseDashboardRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var purchaseOrderItemData = await _context.PurchaseOrderItem
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Include(x => x.PurchaseOrder)
|
||||
.Include(x => x.Product)
|
||||
.Where(x => x.PurchaseOrder!.OrderStatus == PurchaseOrderStatus.Confirmed)
|
||||
.OrderByDescending(x => x.PurchaseOrder!.OrderDate)
|
||||
.Take(30)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var purchaseByVendorGroupData = _context.PurchaseOrderItem
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Include(x => x.PurchaseOrder)
|
||||
.ThenInclude(x => x!.Vendor)
|
||||
.ThenInclude(x => x!.VendorGroup)
|
||||
.Include(x => x.Product)
|
||||
.Where(x => x.Product!.Physical == true)
|
||||
.Select(x => new
|
||||
{
|
||||
Status = x.PurchaseOrder!.OrderStatus,
|
||||
VendorGroupName = x.PurchaseOrder!.Vendor!.VendorGroup!.Name,
|
||||
Quantity = x.Quantity
|
||||
})
|
||||
.GroupBy(x => new { x.Status, x.VendorGroupName })
|
||||
.Select(g => new
|
||||
{
|
||||
Status = g.Key.Status,
|
||||
VendorGroupName = g.Key.VendorGroupName,
|
||||
Quantity = g.Sum(x => x.Quantity)
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var purchaseByVendorCategoryDate = _context.PurchaseOrderItem
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Include(x => x.PurchaseOrder)
|
||||
.ThenInclude(x => x!.Vendor)
|
||||
.ThenInclude(x => x!.VendorCategory)
|
||||
.Include(x => x.Product)
|
||||
.Where(x => x.Product!.Physical == true)
|
||||
.Select(x => new
|
||||
{
|
||||
Status = x.PurchaseOrder!.OrderStatus,
|
||||
VendorCategoryName = x.PurchaseOrder!.Vendor!.VendorCategory!.Name,
|
||||
Quantity = x.Quantity
|
||||
})
|
||||
.GroupBy(x => new { x.Status, x.VendorCategoryName })
|
||||
.Select(g => new
|
||||
{
|
||||
Status = g.Key.Status,
|
||||
VendorCategoryName = g.Key.VendorCategoryName,
|
||||
Quantity = g.Sum(x => x.Quantity)
|
||||
})
|
||||
.ToList();
|
||||
|
||||
|
||||
var result = new GetPurchaseDashboardResult
|
||||
{
|
||||
Data = new GetPurchaseDashboardDto
|
||||
{
|
||||
PurchaseOrderDashboard = purchaseOrderItemData,
|
||||
PurchaseByVendorGroupDashboard =
|
||||
Enum.GetValues(typeof(PurchaseOrderStatus))
|
||||
.Cast<PurchaseOrderStatus>()
|
||||
.Select(status => new BarSeries
|
||||
{
|
||||
Type = "Bar",
|
||||
XName = "x",
|
||||
Width = 2,
|
||||
YName = "y",
|
||||
Name = Enum.GetName(typeof(PurchaseOrderStatus), status)!,
|
||||
ColumnSpacing = 0.1,
|
||||
TooltipMappingName = "tooltipMappingName",
|
||||
DataSource = purchaseByVendorGroupData
|
||||
.Where(x => x.Status == status)
|
||||
.Select(x => new BarDataItem
|
||||
{
|
||||
X = x.VendorGroupName ?? "",
|
||||
TooltipMappingName = x.VendorGroupName ?? "",
|
||||
Y = (int)x.Quantity!.Value
|
||||
}).ToList()
|
||||
})
|
||||
.ToList(),
|
||||
PurchaseByVendorCategoryDashboard =
|
||||
Enum.GetValues(typeof(PurchaseOrderStatus))
|
||||
.Cast<PurchaseOrderStatus>()
|
||||
.Select(status => new BarSeries
|
||||
{
|
||||
Type = "Column",
|
||||
XName = "x",
|
||||
Width = 2,
|
||||
YName = "y",
|
||||
Name = Enum.GetName(typeof(PurchaseOrderStatus), status)!,
|
||||
ColumnSpacing = 0.1,
|
||||
TooltipMappingName = "tooltipMappingName",
|
||||
DataSource = purchaseByVendorCategoryDate
|
||||
.Where(x => x.Status == status)
|
||||
.Select(x => new BarDataItem
|
||||
{
|
||||
X = x.VendorCategoryName ?? "",
|
||||
TooltipMappingName = x.VendorCategoryName ?? "",
|
||||
Y = (int)x.Quantity!.Value
|
||||
}).ToList()
|
||||
})
|
||||
.ToList(),
|
||||
}
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Application.Common.Extensions;
|
||||
using Domain.Entities;
|
||||
using Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
|
||||
public class GetSalesDashboardDto
|
||||
{
|
||||
public List<SalesOrderItem>? SalesOrderDashboard { get; init; }
|
||||
public List<BarSeries>? SalesByCustomerGroupDashboard { get; init; }
|
||||
public List<BarSeries>? SalesByCustomerCategoryDashboard { get; init; }
|
||||
}
|
||||
|
||||
public class GetSalesDashboardResult
|
||||
{
|
||||
public GetSalesDashboardDto? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetSalesDashboardRequest : IRequest<GetSalesDashboardResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetSalesDashboardHandler : IRequestHandler<GetSalesDashboardRequest, GetSalesDashboardResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetSalesDashboardHandler(IQueryContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetSalesDashboardResult> Handle(GetSalesDashboardRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var salesOrderItemData = await _context.SalesOrderItem
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Include(x => x.SalesOrder)
|
||||
.Include(x => x.Product)
|
||||
.Where(x => x.SalesOrder!.OrderStatus == SalesOrderStatus.Confirmed)
|
||||
.OrderByDescending(x => x.SalesOrder!.OrderDate)
|
||||
.Take(30)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var salesByCustomerGroupData = _context.SalesOrderItem
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Include(x => x.SalesOrder)
|
||||
.ThenInclude(x => x!.Customer)
|
||||
.ThenInclude(x => x!.CustomerGroup)
|
||||
.Include(x => x.Product)
|
||||
.Where(x => x.Product!.Physical == true)
|
||||
.Select(x => new
|
||||
{
|
||||
Status = x.SalesOrder!.OrderStatus,
|
||||
CustomerGroupName = x.SalesOrder!.Customer!.CustomerGroup!.Name,
|
||||
Quantity = x.Quantity
|
||||
})
|
||||
.GroupBy(x => new { x.Status, x.CustomerGroupName })
|
||||
.Select(g => new
|
||||
{
|
||||
Status = g.Key.Status,
|
||||
CustomerGroupName = g.Key.CustomerGroupName,
|
||||
Quantity = g.Sum(x => x.Quantity)
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var salesByCustomerCategoryData = _context.SalesOrderItem
|
||||
.AsNoTracking()
|
||||
.IsDeletedEqualTo(false)
|
||||
.Include(x => x.SalesOrder)
|
||||
.ThenInclude(x => x!.Customer)
|
||||
.ThenInclude(x => x!.CustomerCategory)
|
||||
.Include(x => x.Product)
|
||||
.Where(x => x.Product!.Physical == true)
|
||||
.Select(x => new
|
||||
{
|
||||
Status = x.SalesOrder!.OrderStatus,
|
||||
CustomerCategoryName = x.SalesOrder!.Customer!.CustomerCategory!.Name,
|
||||
Quantity = x.Quantity
|
||||
})
|
||||
.GroupBy(x => new { x.Status, x.CustomerCategoryName })
|
||||
.Select(g => new
|
||||
{
|
||||
Status = g.Key.Status,
|
||||
CustomerCategoryName = g.Key.CustomerCategoryName,
|
||||
Quantity = g.Sum(x => x.Quantity)
|
||||
})
|
||||
.ToList();
|
||||
|
||||
|
||||
var result = new GetSalesDashboardResult
|
||||
{
|
||||
Data = new GetSalesDashboardDto
|
||||
{
|
||||
SalesOrderDashboard = salesOrderItemData,
|
||||
SalesByCustomerGroupDashboard =
|
||||
Enum.GetValues(typeof(SalesOrderStatus))
|
||||
.Cast<SalesOrderStatus>()
|
||||
.Select(status => new BarSeries
|
||||
{
|
||||
Type = "Column",
|
||||
XName = "x",
|
||||
Width = 2,
|
||||
YName = "y",
|
||||
Name = Enum.GetName(typeof(SalesOrderStatus), status)!,
|
||||
ColumnSpacing = 0.1,
|
||||
TooltipMappingName = "tooltipMappingName",
|
||||
DataSource = salesByCustomerGroupData
|
||||
.Where(x => x.Status == status)
|
||||
.Select(x => new BarDataItem
|
||||
{
|
||||
X = x.CustomerGroupName ?? "",
|
||||
TooltipMappingName = x.CustomerGroupName ?? "",
|
||||
Y = (int)x.Quantity!.Value
|
||||
}).ToList()
|
||||
})
|
||||
.ToList(),
|
||||
SalesByCustomerCategoryDashboard =
|
||||
Enum.GetValues(typeof(SalesOrderStatus))
|
||||
.Cast<SalesOrderStatus>()
|
||||
.Select(status => new BarSeries
|
||||
{
|
||||
Type = "Bar",
|
||||
XName = "x",
|
||||
Width = 2,
|
||||
YName = "y",
|
||||
Name = Enum.GetName(typeof(SalesOrderStatus), status)!,
|
||||
ColumnSpacing = 0.1,
|
||||
TooltipMappingName = "tooltipMappingName",
|
||||
DataSource = salesByCustomerCategoryData
|
||||
.Where(x => x.Status == status)
|
||||
.Select(x => new BarDataItem
|
||||
{
|
||||
X = x.CustomerCategoryName ?? "",
|
||||
TooltipMappingName = x.CustomerCategoryName ?? "",
|
||||
Y = (int)x.Quantity!.Value
|
||||
}).ToList()
|
||||
})
|
||||
.ToList()
|
||||
}
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using Application.Common.CQS.Queries;
|
||||
using Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Application.Features.DashboardManager.Queries;
|
||||
|
||||
public class GetSalesTeamLeadClosingResult
|
||||
{
|
||||
public List<AccummulationChartItem>? Data { get; init; }
|
||||
}
|
||||
|
||||
public class GetSalesTeamLeadClosingRequest : IRequest<GetSalesTeamLeadClosingResult>
|
||||
{
|
||||
}
|
||||
|
||||
public class GetSalesTeamLeadClosingHandler : IRequestHandler<GetSalesTeamLeadClosingRequest, GetSalesTeamLeadClosingResult>
|
||||
{
|
||||
private readonly IQueryContext _context;
|
||||
|
||||
public GetSalesTeamLeadClosingHandler(IQueryContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetSalesTeamLeadClosingResult> Handle(GetSalesTeamLeadClosingRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var groupedLeads = await _context.Set<Lead>()
|
||||
.Include(l => l.SalesTeam)
|
||||
.Where(l => l.SalesTeam != null && l.AmountClosed.HasValue)
|
||||
.GroupBy(l => l.SalesTeam!.Name)
|
||||
.Select(g => new
|
||||
{
|
||||
Name = g.Key,
|
||||
TotalClosed = g.Sum(l => l.AmountClosed ?? 0)
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var totalAmountClosed = groupedLeads.Sum(g => g.TotalClosed);
|
||||
|
||||
var result = groupedLeads.Select(g =>
|
||||
{
|
||||
double percentageValue = totalAmountClosed > 0
|
||||
? (double)g.TotalClosed / totalAmountClosed * 100
|
||||
: 0;
|
||||
var percentage = percentageValue.ToString("F2");
|
||||
|
||||
return new AccummulationChartItem
|
||||
{
|
||||
X = g.Name ?? "Unknown",
|
||||
Y = Math.Round(percentageValue, 2),
|
||||
Text = $"{g.Name ?? "Unknown"} ({Math.Round(percentageValue, 2)}%)"
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
return new GetSalesTeamLeadClosingResult { Data = result };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user