Files
BI/server/DongfangHydro.Dashboard.Api/Services/DashboardMapper.cs
T

152 lines
4.6 KiB
C#

using DongfangHydro.Dashboard.Api.Contracts;
using DongfangHydro.Dashboard.Api.Domain;
namespace DongfangHydro.Dashboard.Api.Services;
public static class DashboardMapper
{
public static ProductionNodeDto? BuildTree(IReadOnlyCollection<ProductionNode> nodes)
{
var root = nodes
.Where(node => node.ParentNodeId is null)
.OrderBy(node => node.SortOrder)
.FirstOrDefault(node => node.NodeType == "order")
?? nodes.Where(node => node.ParentNodeId is null).OrderBy(node => node.SortOrder).FirstOrDefault();
if (root is null)
{
return null;
}
var childrenByParent = nodes
.Where(node => node.ParentNodeId.HasValue)
.GroupBy(node => node.ParentNodeId!.Value)
.ToDictionary(
group => group.Key,
group => group.OrderBy(node => node.SortOrder).ThenBy(node => node.Code).ToList());
return MapNode(root, childrenByParent, []);
}
public static ProductionNodeDto MapNode(ProductionNode node)
{
return MapNode(node, new Dictionary<Guid, List<ProductionNode>>(), []);
}
public static TrendPointDto MapTrend(ProductionTrendPoint point)
{
return new TrendPointDto(
point.SampleTime.ToLocalTime().ToString("HH:mm:ss"),
point.Completion,
point.Risk,
point.PlannedQty,
point.ActualQty,
Math.Round(point.Achievement, 1));
}
public static RiskEventDto MapRiskEvent(RiskEvent riskEvent)
{
return new RiskEventDto(
riskEvent.Id,
riskEvent.OrderId,
riskEvent.NodeId,
riskEvent.OrderCode,
riskEvent.NodeName,
riskEvent.RiskLevel,
riskEvent.Message,
riskEvent.OccurredAt.ToLocalTime().ToString("HH:mm:ss"),
riskEvent.HandlingStatus);
}
public static OrderSummaryDto MapOrder(
ProductionOrder order,
ProductionNodeDto root,
IReadOnlyList<TrendPointDto> trend,
IReadOnlyList<RiskEventDto> events)
{
return new OrderSummaryDto(
order.Id,
order.Code,
order.ProductName,
order.BatchQty,
order.RequiredQty,
order.CompletedQty,
order.Progress,
order.Status,
order.RiskLevel,
order.DelayDays,
FormatDate(order.PlannedStart),
FormatDate(order.PlannedEnd),
order.LineName,
order.Owner,
Math.Round(order.PlanAchievement, 1),
Math.Round(order.DailyDelta, 1),
order.ThumbnailKey,
root,
trend,
events);
}
private static ProductionNodeDto MapNode(
ProductionNode node,
IReadOnlyDictionary<Guid, List<ProductionNode>> childrenByParent,
HashSet<Guid> ancestors)
{
if (!ancestors.Add(node.Id))
{
throw new InvalidOperationException($"Production node cycle detected at {node.Id}.");
}
var children = childrenByParent.TryGetValue(node.Id, out var childNodes)
? childNodes.Select(child => MapNode(child, childrenByParent, new HashSet<Guid>(ancestors))).ToList()
: [];
return new ProductionNodeDto(
node.Id,
node.OrderId,
node.ParentNodeId,
node.Code,
node.OperationCode,
node.MaterialCode,
node.Name,
node.SourceSequence,
node.Specification,
node.Material,
node.UnitWeight,
node.TotalWeight,
node.UnitWeightText,
node.TotalWeightText,
node.BomQuantity,
node.BomQuantityText,
node.Remark,
node.SourceSheet,
node.SourceRow,
node.Level,
node.NodeType,
node.SupplyType,
node.RequiredQty,
node.CompletedQty,
node.DefectQty,
node.Progress,
node.Status,
node.RiskLevel,
node.DelayDays,
node.DelayReason,
FormatDate(node.PlannedStart),
FormatDate(node.PlannedEnd),
FormatDate(node.ActualStart),
FormatDate(node.ActualEnd),
node.Owner,
node.Vendor,
node.StationName,
node.VisualKey,
Convert.ToBase64String(node.RowVersion),
children);
}
private static string FormatDate(DateTime? value)
{
return value.HasValue ? value.Value.ToString("yyyy-MM-dd") : string.Empty;
}
}