81 lines
3.1 KiB
C#
81 lines
3.1 KiB
C#
using System.Globalization;
|
|
using YY.Admin.Core.Entity;
|
|
|
|
namespace YY.Admin.Services.Service.MixerMaterialTareStrategy;
|
|
|
|
/// <summary>
|
|
/// 密炼物料皮重策略匹配:按密炼物料、供应商、入场日期、每份重量(对应策略物料规格)筛选。
|
|
/// </summary>
|
|
public static class MixerMaterialTareStrategyMatcher
|
|
{
|
|
public static List<MesXslMixerMaterialTareStrategy> FilterCandidates(
|
|
IEnumerable<MesXslMixerMaterialTareStrategy> strategies,
|
|
string? mixerMaterialId,
|
|
string? supplierId,
|
|
DateTime? entryDate,
|
|
double? portionWeight)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(mixerMaterialId) || string.IsNullOrWhiteSpace(supplierId))
|
|
{
|
|
return new List<MesXslMixerMaterialTareStrategy>();
|
|
}
|
|
|
|
var entryDay = entryDate?.Date;
|
|
return strategies
|
|
.Where(s => string.Equals(s.MixerMaterialId, mixerMaterialId, StringComparison.OrdinalIgnoreCase))
|
|
.Where(s => string.Equals(s.SupplierId, supplierId, StringComparison.OrdinalIgnoreCase))
|
|
.Where(s => IsEntryDateInRange(entryDay, s.EffectiveStartDate, s.EffectiveEndDate))
|
|
.Where(s => MaterialSpecMatchesPortionWeight(s.MaterialSpec, portionWeight))
|
|
.OrderByDescending(s => s.EffectiveStartDate ?? DateTime.MinValue)
|
|
.ThenByDescending(s => s.CreateTime ?? DateTime.MinValue)
|
|
.ToList();
|
|
}
|
|
|
|
public static MesXslMixerMaterialTareStrategy? PickBestMatch(
|
|
IEnumerable<MesXslMixerMaterialTareStrategy> strategies,
|
|
string? mixerMaterialId,
|
|
string? supplierId,
|
|
DateTime? entryDate,
|
|
double? portionWeight)
|
|
{
|
|
var list = FilterCandidates(strategies, mixerMaterialId, supplierId, entryDate, portionWeight);
|
|
return list.FirstOrDefault();
|
|
}
|
|
|
|
public static bool IsEntryDateInRange(DateTime? entryDay, DateTime? start, DateTime? end)
|
|
{
|
|
if (!entryDay.HasValue || !start.HasValue || !end.HasValue)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var day = entryDay.Value.Date;
|
|
return day >= start.Value.Date && day <= end.Value.Date;
|
|
}
|
|
|
|
/// <summary>策略「物料规格」与拆码明细「每份重量」比对(支持数值或文本形式)。</summary>
|
|
public static bool MaterialSpecMatchesPortionWeight(string? materialSpec, double? portionWeight)
|
|
{
|
|
if (!portionWeight.HasValue)
|
|
{
|
|
return string.IsNullOrWhiteSpace(materialSpec);
|
|
}
|
|
|
|
var weight = portionWeight.Value;
|
|
if (string.IsNullOrWhiteSpace(materialSpec))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var spec = materialSpec.Trim();
|
|
if (double.TryParse(spec, NumberStyles.Float, CultureInfo.InvariantCulture, out var specNum))
|
|
{
|
|
return Math.Abs(specNum - weight) < 0.0001d;
|
|
}
|
|
|
|
var weightText = weight.ToString("0.##", CultureInfo.InvariantCulture);
|
|
return string.Equals(spec, weightText, StringComparison.OrdinalIgnoreCase)
|
|
|| string.Equals(spec, weight.ToString(CultureInfo.InvariantCulture), StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
}
|