using Fake.Application;
using Oms.Domain.ChannelsAggregate.Entities;
namespace Oms.Application.Shared;
///
/// 计重进位区间校验:同一进位制下左开右闭 (start, end],端点相接不算重叠,排序后不允许空洞。
///
public static class WeightRoundingRangeGuard
{
public static void EnsureValidRange(decimal startValue, decimal endValue)
{
if (startValue >= endValue)
{
throw new BusinessException("起始值须小于截止值");
}
}
///
/// (a, b] 与 (c, d] 是否重叠。
///
public static bool Overlaps(decimal startA, decimal endA, decimal startB, decimal endB) =>
startA < endB && startB < endA;
public static void EnsureNoOverlap(
decimal startValue,
decimal endValue,
IEnumerable existing,
int? excludeId = null)
{
EnsureValidRange(startValue, endValue);
foreach (var item in existing)
{
if (excludeId is > 0 && item.Id == excludeId.Value)
{
continue;
}
if (Overlaps(startValue, endValue, item.StartValue, item.EndValue))
{
throw new BusinessException(
$"起始区间 ({startValue}, {endValue}] 与已有区间 ({item.StartValue}, {item.EndValue}] 重叠");
}
}
}
public static void EnsureContiguous(
decimal startValue,
decimal endValue,
IEnumerable existing,
int? excludeId = null)
{
EnsureNoOverlap(startValue, endValue, existing, excludeId);
var merged = existing
.Where(item => excludeId is not > 0 || item.Id != excludeId.Value)
.Select(item => (Start: item.StartValue, End: item.EndValue))
.Append((Start: startValue, End: endValue))
.OrderBy(x => x.Start)
.ThenBy(x => x.End)
.ToList();
for (var i = 0; i < merged.Count - 1; i++)
{
var currentEnd = merged[i].End;
var nextStart = merged[i + 1].Start;
if (currentEnd == nextStart)
{
continue;
}
throw new BusinessException(
$"起始区间必须首尾相接(左开右闭):({merged[i].Start}, {currentEnd}] 与 ({nextStart}, {merged[i + 1].End}] 之间存在缺口");
}
}
}