Quellcode durchsuchen

fix(s0): block deletes with downstream references

Bump backend version to 1.0.165.
YY968XX vor 3 Monaten
Ursprung
Commit
4a890119ec

+ 3 - 3
server/Admin.NET.Web.Entry/Admin.NET.Web.Entry.csproj

@@ -11,9 +11,9 @@
     <GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
     <Copyright>Admin.NET</Copyright>
     <Description>Admin.NET 通用权限开发平台</Description>
-    <AssemblyVersion>1.0.158</AssemblyVersion>
-    <FileVersion>1.0.158</FileVersion>
-    <Version>1.0.158</Version>
+    <AssemblyVersion>1.0.165</AssemblyVersion>
+    <FileVersion>1.0.165</FileVersion>
+    <Version>1.0.165</Version>
   </PropertyGroup>
 
   <ItemGroup>

+ 6 - 0
server/Plugins/Admin.NET.Plugin.AiDOP/Controllers/S0/Manufacturing/AdoS0MfgWorkCentersController.cs

@@ -117,6 +117,12 @@ public class AdoS0MfgWorkCentersController : ControllerBase
     {
         var item = await _rep.GetByIdAsync(id);
         if (item == null) return NotFound();
+
+        var refInfo = await _refChecker.WorkCenterReferencesAsync(item.WorkCtr);
+        if (refInfo is { } r)
+            return AdoS0ApiErrors.Conflict(AdoS0ErrorCodes.DeleteBlocked,
+                $"存在 {r.Count} 条 {r.Table} 引用该工作中心,无法删除");
+
         await _rep.DeleteAsync(item);
         return Ok(new { message = "删除成功" });
     }

+ 31 - 0
server/Plugins/Admin.NET.Plugin.AiDOP/Infrastructure/AdoS0ReferenceChecker.cs

@@ -198,6 +198,11 @@ public sealed class AdoS0ReferenceChecker
             .CountAsync();
         if (sub > 0) return (sub, "物料替代关系 (ItemSubstituteDetail)");
 
+        var lineMat = await _db.Queryable<AdoS0ProdLineDetail>()
+            .Where(x => x.Part == itemNum)
+            .CountAsync();
+        if (lineMat > 0) return (lineMat, "线边物料 (ProdLineDetail.Part)");
+
         // 不查 SRM:srm_purchase.icitem_id 是上游系统(金蝶等)的物料 ID,
         // 与本地 AdoS0ItemMaster.Id 不在同一坐标系,无法直接 JOIN;
         // SRM 表也没有物料编码 (ItemNum) 字符串列。
@@ -222,6 +227,32 @@ public sealed class AdoS0ReferenceChecker
             "SrmPurchase.SupplierNumber");
         if (srm > 0) return (srm, "货源清单 (SrmPurchase)");
 
+        var routSupp = await _db.Queryable<AdoS0MfgRoutingOpDetail>()
+            .Where(x => x.SupplierCode == supp)
+            .CountAsync();
+        if (routSupp > 0) return (routSupp, "工艺路线明细供应商 (RoutingOpDetail.SupplierCode)");
+
+        return null;
+    }
+
+    /// <summary>
+    /// 工作中心(WorkCtrMaster)删除前引用检查。
+    /// 覆盖下游:工艺路线明细 / 线边物料。
+    /// </summary>
+    public async Task<(int Count, string Table)?> WorkCenterReferencesAsync(string? workCtr)
+    {
+        if (string.IsNullOrWhiteSpace(workCtr)) return null;
+
+        var routing = await _db.Queryable<AdoS0MfgRoutingOpDetail>()
+            .Where(x => x.WorkCenterCode == workCtr)
+            .CountAsync();
+        if (routing > 0) return (routing, "工艺路线明细 (RoutingOpDetail.WorkCenterCode)");
+
+        var lineSite = await _db.Queryable<AdoS0ProdLineDetail>()
+            .Where(x => x.Site == workCtr)
+            .CountAsync();
+        if (lineSite > 0) return (lineSite, "线边物料工作中心 (ProdLineDetail.Site)");
+
         return null;
     }