|
|
@@ -179,6 +179,47 @@ public class NeutralTransTypeMappingTests
|
|
|
Assert.Contains("API_INBOUND", api);
|
|
|
}
|
|
|
|
|
|
+ [Theory]
|
|
|
+ [InlineData("MATERIAL", "MATERIAL")]
|
|
|
+ [InlineData(" FG_LINE_LOC ", "FG_LINE_LOC")]
|
|
|
+ // MySQL 默认排序规则不区分大小写,小写值不挡住就会绕过校验入库。
|
|
|
+ [InlineData("material", "MATERIAL")]
|
|
|
+ [InlineData("Unknown", "UNKNOWN")]
|
|
|
+ [InlineData("MATERIAL1", null)]
|
|
|
+ [InlineData("WAREHOUSE", null)]
|
|
|
+ [InlineData("", null)]
|
|
|
+ [InlineData(null, null)]
|
|
|
+ public void NormalizeLocationRole_OnlyAcceptsAllLocationRoles(string? input, string? expected)
|
|
|
+ {
|
|
|
+ Assert.Equal(expected, NeutralTransTypeCodes.NormalizeLocationRole(input));
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>人工保存必须经过白名单,否则写错的角色会让 LocationRules 永远判不出阶段码。</summary>
|
|
|
+ [Fact]
|
|
|
+ public void SaveLocations_ValidatesAgainstWhitelist()
|
|
|
+ {
|
|
|
+ var service = ReadRepoFile("server/Plugins/Admin.NET.Plugin.AiDOP/DataPlatform/MdpSourceMappingService.cs");
|
|
|
+
|
|
|
+ Assert.Contains("NeutralTransTypeCodes.NormalizeLocationRole(row.LocationRole)", service);
|
|
|
+ Assert.Contains("NeutralTransTypeCodes.AllLocationRoles", service);
|
|
|
+ // 旧写法直接把前端传入值落库,不得复活。
|
|
|
+ Assert.DoesNotContain("role = row.LocationRole.Trim()", service);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 前端下拉是 AllLocationRoles 的手写副本,而本类文档禁止在别处再写一份,故逐字钉住两边一致。
|
|
|
+ /// </summary>
|
|
|
+ [Fact]
|
|
|
+ public void FrontendLocationRoleOptions_MatchAllLocationRoles()
|
|
|
+ {
|
|
|
+ var vue = ReadRepoFile("Web/src/views/aidop/data-platform/sourceMappings.vue");
|
|
|
+
|
|
|
+ var expected = "const roles = ["
|
|
|
+ + string.Join(", ", NeutralTransTypeCodes.AllLocationRoles.Select(role => $"'{role}'"))
|
|
|
+ + "];";
|
|
|
+ Assert.Contains(expected, vue);
|
|
|
+ }
|
|
|
+
|
|
|
private static string ReadScript(string name) =>
|
|
|
ReadRepoFile($"server/Admin.NET.Web.Entry/UpdateScripts/{name}");
|
|
|
|