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}] 之间存在缺口"); } } }