using System.Globalization;
using YY.Admin.Core.Entity;
namespace YY.Admin.Core.Util;
///
/// 「已入场重量」桌面端本地累计计算器。
/// 与后端 IMesXslRawMaterialEntryService.sumEnteredWeightByBillNos 保持同一口径:
/// ① 把 totalPortions / portionWeight 按 "x/y/z/" 拆分
/// ② 逐位 (份数 × 每份重量) 累加,得到该 entry 的小计
/// ③ 同一榜单(BillNo)下所有 entry 的小计再次累加
/// 任一位置解析失败或缺失:静默跳过,保证 UI 降级可用。
///
public static class EnteredWeightCalculator
{
/// 累计一条入场记录的小计。
public static double SumOneEntry(string? totalPortions, string? portionWeight)
{
var portions = SplitJoined(totalPortions);
var weights = SplitJoined(portionWeight);
if (portions.Length == 0 || weights.Length == 0)
{
return 0d;
}
var n = Math.Min(portions.Length, weights.Length);
double sum = 0d;
for (var i = 0; i < n; i++)
{
if (!TryParse(portions[i], out var p) || !TryParse(weights[i], out var w))
{
continue;
}
sum += p * w;
}
return sum;
}
/// 按 BillNo 分组累计「已入场重量」。返回 Dictionary<BillNo, 总和>。
public static Dictionary SumByBillNos(
IEnumerable entries,
IEnumerable billNos)
{
var keys = new HashSet(StringComparer.OrdinalIgnoreCase);
foreach (var b in billNos)
{
if (!string.IsNullOrWhiteSpace(b)) keys.Add(b!);
}
var result = new Dictionary(StringComparer.OrdinalIgnoreCase);
if (keys.Count == 0)
{
return result;
}
foreach (var e in entries)
{
if (string.IsNullOrWhiteSpace(e.BillNo) || !keys.Contains(e.BillNo!))
{
continue;
}
var sub = SumOneEntry(e.TotalPortions, e.PortionWeight);
if (sub == 0d)
{
continue;
}
if (result.TryGetValue(e.BillNo!, out var acc))
{
result[e.BillNo!] = acc + sub;
}
else
{
result[e.BillNo!] = sub;
}
}
return result;
}
private static string[] SplitJoined(string? value)
{
// 兼容 "x/y/z" 与 "x/y/z/" 两种格式;过滤空段
if (string.IsNullOrWhiteSpace(value))
{
return Array.Empty();
}
return value.Split('/')
.Select(s => s.Trim())
.Where(s => s.Length > 0)
.ToArray();
}
private static bool TryParse(string s, out double v) =>
double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out v);
}