持久层重构为独立 MiGu.DB 工程并优化集成
- 新增 MiGu.DB 项目,迁移所有领域实体与枚举,统一模型约定 - 实现 Entity/Repository/UoW/Provider/Exception 等接口与实现 - 支持数据修补机制,完善 Sqlite 初始迁移与数据库管理 - Server 侧移除 EF Core 相关,依赖 MiGu.DB,PlatformPersistence 适配 - 业务服务注入 UoW/Repository,状态字段统一用 enum 及辅助类 - 统一异常处理,Controller 映射 HTTP 状态码 - 配置项与文档补充数据库启动、SchemaMode、迁移说明 - 新增 GlobalUsings.Db.cs、WmsStatusAliases.cs 简化类型引用 - 新增 HttpActorContextMiddleware 支持操作者上下文一致性 - 新增 MiGuDbContextModelSnapshot 追踪数据库结构 - 优化代码结构,解耦领域与持久层,提升扩展性与安全性
This commit is contained in:
@@ -13,11 +13,12 @@ public sealed class WmsTransportPlanner
|
||||
|
||||
public async Task<TransportCandidatePreview> PreviewAsync(WmsTransportRequest request)
|
||||
{
|
||||
if (!WmsTransportTriggerTypes.All.Contains(request.TriggerType))
|
||||
if (!WmsTransportTriggerTypes.IsDefined(request.TriggerType))
|
||||
throw new InvalidOperationException("触发类型无效");
|
||||
|
||||
var trigger = WmsTransportTriggerTypes.ParseOr(request.TriggerType);
|
||||
var ctx = await BuildContextAsync();
|
||||
var rules = await LoadRulesAsync(request);
|
||||
var rules = await LoadRulesAsync(request, trigger);
|
||||
var ruleResults = new List<RulePreviewResult>();
|
||||
var candidates = new List<TransportCandidatePair>();
|
||||
|
||||
@@ -26,7 +27,7 @@ public sealed class WmsTransportPlanner
|
||||
var sourceSelector = TransportSelectorParser.ParseSelector(rule.SourceSelectorJson);
|
||||
var targetSelector = TransportSelectorParser.ParseSelector(rule.TargetSelectorJson);
|
||||
var options = TransportSelectorParser.ParseTaskOptions(rule.TaskOptionsJson);
|
||||
var ruleCandidates = BuildCandidates(ctx, request, rule, sourceSelector, targetSelector, options);
|
||||
var ruleCandidates = BuildCandidates(ctx, request, trigger, rule, sourceSelector, targetSelector, options);
|
||||
var rejectReasons = ruleCandidates.Count == 0
|
||||
? new List<string> { "未找到满足条件的起点/终点组合" }
|
||||
: new List<string>();
|
||||
@@ -52,10 +53,10 @@ public sealed class WmsTransportPlanner
|
||||
return preview.Candidates.FirstOrDefault();
|
||||
}
|
||||
|
||||
private async Task<List<WmsTransportRule>> LoadRulesAsync(WmsTransportRequest request)
|
||||
private async Task<List<WmsTransportRule>> LoadRulesAsync(WmsTransportRequest request, WmsTransportTriggerType trigger)
|
||||
{
|
||||
var query = _db.WmsTransportRules.AsNoTracking()
|
||||
.Where(x => x.Enabled && x.TriggerType == request.TriggerType);
|
||||
.Where(x => x.Enabled && x.TriggerType == trigger);
|
||||
if (request.RuleId.HasValue)
|
||||
query = query.Where(x => x.Id == request.RuleId.Value);
|
||||
return await query.OrderByDescending(x => x.Priority).ThenBy(x => x.Code).ToListAsync();
|
||||
@@ -94,17 +95,18 @@ public sealed class WmsTransportPlanner
|
||||
private List<TransportCandidatePair> BuildCandidates(
|
||||
PlannerContext ctx,
|
||||
WmsTransportRequest request,
|
||||
WmsTransportTriggerType trigger,
|
||||
WmsTransportRule rule,
|
||||
TransportSelector sourceSelector,
|
||||
TransportSelector targetSelector,
|
||||
TransportTaskOptions options)
|
||||
{
|
||||
var results = new List<TransportCandidatePair>();
|
||||
var sources = BuildSourceCandidates(ctx, request, sourceSelector, options);
|
||||
var sources = BuildSourceCandidates(ctx, request, trigger, sourceSelector, options);
|
||||
|
||||
foreach (var src in sources)
|
||||
{
|
||||
var targets = BuildTargetCandidates(ctx, request, targetSelector, options, src.StorageId);
|
||||
var targets = BuildTargetCandidates(ctx, request, trigger, targetSelector, options, src.StorageId);
|
||||
foreach (var tgt in targets)
|
||||
{
|
||||
var score = rule.Priority * 1000 + src.Score + tgt.Score;
|
||||
@@ -124,6 +126,7 @@ public sealed class WmsTransportPlanner
|
||||
private List<SourceCandidate> BuildSourceCandidates(
|
||||
PlannerContext ctx,
|
||||
WmsTransportRequest request,
|
||||
WmsTransportTriggerType trigger,
|
||||
TransportSelector selector,
|
||||
TransportTaskOptions options)
|
||||
{
|
||||
@@ -145,7 +148,7 @@ public sealed class WmsTransportPlanner
|
||||
continue;
|
||||
|
||||
if (request.RequestSiteId is { Length: > 0 } siteId &&
|
||||
string.Equals(request.TriggerType, WmsTransportTriggerTypes.FinishedGoodsOffline, StringComparison.OrdinalIgnoreCase) &&
|
||||
trigger == WmsTransportTriggerTypes.FinishedGoodsOffline &&
|
||||
!string.Equals(storage.SiteId, siteId, StringComparison.OrdinalIgnoreCase))
|
||||
continue;
|
||||
|
||||
@@ -162,6 +165,7 @@ public sealed class WmsTransportPlanner
|
||||
private List<TargetCandidate> BuildTargetCandidates(
|
||||
PlannerContext ctx,
|
||||
WmsTransportRequest request,
|
||||
WmsTransportTriggerType trigger,
|
||||
TransportSelector selector,
|
||||
TransportTaskOptions options,
|
||||
Guid sourceStorageId)
|
||||
@@ -176,7 +180,7 @@ public sealed class WmsTransportPlanner
|
||||
if (ctx.ReservedTargetStorages.Contains(storage.Id)) continue;
|
||||
|
||||
if (request.RequestSiteId is { Length: > 0 } siteId &&
|
||||
string.Equals(request.TriggerType, WmsTransportTriggerTypes.MaterialCall, StringComparison.OrdinalIgnoreCase) &&
|
||||
trigger == WmsTransportTriggerTypes.MaterialCall &&
|
||||
selector.Storage?.SiteIds is { Count: 0 } &&
|
||||
!string.Equals(storage.SiteId, siteId, StringComparison.OrdinalIgnoreCase))
|
||||
continue;
|
||||
@@ -200,7 +204,8 @@ public sealed class WmsTransportPlanner
|
||||
{
|
||||
if (request.MaterialId.HasValue && row.MaterialId != request.MaterialId.Value) continue;
|
||||
if (filter?.MaterialIds is { Count: > 0 } ids && !ids.Contains(row.MaterialId.ToString("D"))) continue;
|
||||
if (filter?.StatusIn is { Count: > 0 } st && !st.Contains(row.Status, StringComparer.OrdinalIgnoreCase)) continue;
|
||||
if (filter?.StatusIn is { Count: > 0 } st &&
|
||||
!st.Contains(row.Status.ToString(), StringComparer.OrdinalIgnoreCase)) continue;
|
||||
if (filter?.MinQuantity is { } min && row.Quantity < min) continue;
|
||||
if (request.Quantity is { } reqQty && row.Quantity < reqQty) continue;
|
||||
if (request.BatchNo is { Length: > 0 } batch && !string.Equals(row.BatchNo, batch, StringComparison.OrdinalIgnoreCase)) continue;
|
||||
@@ -220,7 +225,8 @@ public sealed class WmsTransportPlanner
|
||||
if (filter.AreaIds is { Count: > 0 } && !filter.AreaIds.Contains(storage.AreaId.ToString("D"))) return false;
|
||||
if (filter.StorageTypes is { Count: > 0 } && !filter.StorageTypes.Contains(storage.StorageType, StringComparer.OrdinalIgnoreCase)) return false;
|
||||
if (filter.ZoneCodes is { Count: > 0 } && !filter.ZoneCodes.Contains(storage.ZoneCode, StringComparer.OrdinalIgnoreCase)) return false;
|
||||
if (filter.StatusIn is { Count: > 0 } && !filter.StatusIn.Contains(storage.Status, StringComparer.OrdinalIgnoreCase)) return false;
|
||||
if (filter.StatusIn is { Count: > 0 } &&
|
||||
!filter.StatusIn.Contains(storage.Status.ToString(), StringComparer.OrdinalIgnoreCase)) return false;
|
||||
if (filter.SiteIds is { Count: > 0 } && !filter.SiteIds.Contains(storage.SiteId, StringComparer.OrdinalIgnoreCase)) return false;
|
||||
if (filter.AllowInbound == true && !storage.AllowInbound) return false;
|
||||
if (filter.AllowOutbound == true && !storage.AllowOutbound) return false;
|
||||
@@ -236,7 +242,8 @@ public sealed class WmsTransportPlanner
|
||||
{
|
||||
if (filter == null) return true;
|
||||
if (filter.ContainerTypes is { Count: > 0 } && !filter.ContainerTypes.Contains(container.ContainerType, StringComparer.OrdinalIgnoreCase)) return false;
|
||||
if (filter.StatusIn is { Count: > 0 } && !filter.StatusIn.Contains(container.Status, StringComparer.OrdinalIgnoreCase)) return false;
|
||||
if (filter.StatusIn is { Count: > 0 } &&
|
||||
!filter.StatusIn.Contains(container.Status.ToString(), StringComparer.OrdinalIgnoreCase)) return false;
|
||||
if (filter.ExcludeReserved &&
|
||||
(ctx.ReservedContainers.Contains(container.Id) || ctx.TaskReservedContainers.Contains(container.Id)))
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user