admin/src/Oms.Tests/RulesSnapshotHelperPublishTests.cs
zzh bb8c0a906c
All checks were successful
Build and Deploy / deploy (push) Successful in 1m0s
feat: 卖价/规则发布钉 KPI 分区包,快照只存引用
分区明细独立版本化并缓存加载,计费包缺失严格失败;同步态接口不再拉全文。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-07 16:42:42 +08:00

107 lines
4.3 KiB
C#

using System.Linq.Expressions;
using FluentAssertions;
using Moq;
using Oms.Application.Dtos.Orders;
using Oms.Application.Shared;
using Oms.Domain.ChannelsAggregate.Entities;
using Oms.Domain.ChannelsAggregate.Repositories;
namespace Oms.Tests;
public class RulesSnapshotHelperPublishTests
{
[Fact]
public async Task ApplyRulesToSnapshotAsync_ShouldPinBlacklistRemotePacksAndEmbedWeight()
{
var product = new SalesProduct
{
Id = 1,
ProductCode = "test01",
BlacklistAreaId = 10,
RemoteAreaId = 20,
WeightRuleId = 1,
WeightRoundingId = 2
};
var areas = new Dictionary<int, KpiArea>
{
[10] = new() { Id = 10, Name = "黑名单区", AreaType = "blacklist" },
[20] = new() { Id = 20, Name = "偏远区", AreaType = "remote" }
};
var kpiMock = new Mock<IKpiAreaRepository>();
kpiMock.Setup(x => x.FirstOrDefaultAsync(It.IsAny<Expression<Func<KpiArea, bool>>>(), default))
.ReturnsAsync((Expression<Func<KpiArea, bool>> expr, CancellationToken _) =>
areas.Values.FirstOrDefault(expr.Compile()));
kpiMock.Setup(x => x.GetAllInfosByAreaIdAsync(10, default))
.ReturnsAsync(
[
new KpiAreaInfo { Id = 1, AreaId = 10, CountryCode = "US", LeftPostcode = "90000", RightPostcode = "90010" }
]);
kpiMock.Setup(x => x.GetAllInfosByAreaIdAsync(20, default))
.ReturnsAsync(
[
new KpiAreaInfo { Id = 2, AreaId = 20, CountryCode = "US", LeftPostcode = "06000", RightPostcode = "06999" }
]);
kpiMock.Setup(x => x.FindPublishByAreaIdAndContentHashAsync(It.IsAny<int>(), It.IsAny<string>(), default))
.ReturnsAsync((KpiAreaPublishRecord?)null);
kpiMock.Setup(x => x.InsertPublishRecordAsync(It.IsAny<KpiAreaPublishRecord>(), default))
.ReturnsAsync((KpiAreaPublishRecord r, CancellationToken _) =>
{
r.Id = r.AreaId * 100;
return r;
});
var weightRuleMock = new Mock<IWeightRuleRepository>();
weightRuleMock.Setup(x => x.FirstOrDefaultAsync(It.IsAny<Expression<Func<WeightRule, bool>>>(), default))
.ReturnsAsync(new WeightRule { Id = 1, Name = "标准计重" });
weightRuleMock.Setup(x => x.GetAllInfosByRuleIdAsync(1, default))
.ReturnsAsync(
[
new WeightRuleInfo
{
Id = 1,
RuleId = 1,
Condition = "gw>vw",
BillableWeight = "gw",
VolumetricFactor = "6000"
}
]);
var roundingMock = new Mock<IWeightRoundingRepository>();
roundingMock.Setup(x => x.FirstOrDefaultAsync(It.IsAny<Expression<Func<WeightRounding, bool>>>(), default))
.ReturnsAsync(new WeightRounding { Id = 2, Name = "标准进位" });
roundingMock.Setup(x => x.GetAllInfosByRoundingIdAsync(2, default))
.ReturnsAsync(
[
new WeightRoundingInfo { Id = 1, RoundingId = 2, StartValue = 0, EndValue = 20, Public = "0.5" }
]);
var packService = new KpiAreaPackService(kpiMock.Object);
var snapshot = new SalesProductRulesPublishSnapshotDto();
await RulesSnapshotHelper.ApplyRulesToSnapshotAsync(
snapshot,
product,
kpiMock.Object,
weightRuleMock.Object,
roundingMock.Object,
packService,
"tester");
snapshot.BlacklistAreaId.Should().Be(10);
snapshot.BlacklistAreaRef.Should().NotBeNull();
snapshot.BlacklistAreaRef!.PackVersion.Should().NotBeNullOrWhiteSpace();
snapshot.BlacklistAreaInfos.Should().BeEmpty();
snapshot.RemoteAreaRef.Should().NotBeNull();
snapshot.RemoteAreaRef!.AreaId.Should().Be(20);
snapshot.WeightRuleInfos.Should().HaveCount(1);
snapshot.WeightRoundingInfos.Should().HaveCount(1);
var json = OmsDocHelper.SerializeSnapshotJson(snapshot)!;
json.Should().Contain("blacklistAreaRef");
json.Should().Contain("remoteAreaRef");
json.Should().NotContain("blacklistAreaInfos");
json.Should().NotContain("remoteAreaInfos");
}
}