Bläddra i källkod

fix: S1-S4 multi-tenant audit round 2 - join-level tenant isolation | server 1.0.568

Pengxy 2 dagar sedan
förälder
incheckning
fe3bf913ee
21 ändrade filer med 253 tillägg och 176 borttagningar
  1. 3 3
      server/Admin.NET.Web.Entry/Admin.NET.Web.Entry.csproj
  2. 36 27
      server/Plugins/Admin.NET.Plugin.AiDOP/Order/OrderReviewOrchestrationService.cs
  3. 3 2
      server/Plugins/Admin.NET.Plugin.AiDOP/Order/OrderWorkOrderGenerationService.cs
  4. 2 2
      server/Plugins/Admin.NET.Plugin.AiDOP/ProcurementExecution/IqcReturnQueryService.cs
  5. 2 2
      server/Plugins/Admin.NET.Plugin.AiDOP/ProcurementExecution/PurchaseReturnService.cs
  6. 3 0
      server/Plugins/Admin.NET.Plugin.AiDOP/ProcurementExecution/SupplierDeliveryManagementService.cs
  7. 17 14
      server/Plugins/Admin.NET.Plugin.AiDOP/ProcurementExecution/SupplierShipmentService.cs
  8. 16 11
      server/Plugins/Admin.NET.Plugin.AiDOP/Production/ProductionSchedulingActionService.cs
  9. 1 0
      server/Plugins/Admin.NET.Plugin.AiDOP/Production/ScheduleExceptionService.cs
  10. 2 2
      server/Plugins/Admin.NET.Plugin.AiDOP/Production/WorkOrderSchedulingService.cs
  11. 1 0
      server/Plugins/Admin.NET.Plugin.AiDOP/Supply/DeliveryExceptionService.cs
  12. 34 22
      server/Plugins/Admin.NET.Plugin.AiDOP/Supply/DemandOrderService.cs
  13. 5 4
      server/Plugins/Admin.NET.Plugin.AiDOP/Supply/NumberRuleService.cs
  14. 34 22
      server/Plugins/Admin.NET.Plugin.AiDOP/Supply/OutsourceOrderService.cs
  15. 59 40
      server/Plugins/Admin.NET.Plugin.AiDOP/Supply/ProcessOutsourceOrderService.cs
  16. 8 6
      server/Plugins/Admin.NET.Plugin.AiDOP/Supply/ProcurementPipelineService.cs
  17. 13 9
      server/Plugins/Admin.NET.Plugin.AiDOP/Supply/PurchaseOrderTransferService.cs
  18. 3 2
      server/Plugins/Admin.NET.Plugin.AiDOP/Supply/PurchaseRequestFromShortageService.cs
  19. 4 3
      server/Plugins/Admin.NET.Plugin.AiDOP/Universal/UniversalWorkOrderService.cs
  20. 6 4
      server/Plugins/Admin.NET.Plugin.AiDOP/WorkOrder/WorkOrderMaterialDetailSyncService.cs
  21. 1 1
      server/Plugins/Admin.NET.Plugin.AiDOP/WorkOrder/WorkOrderPickBillService.cs

+ 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.567</AssemblyVersion>
-    <FileVersion>1.0.567</FileVersion>
-    <Version>1.0.567</Version>
+    <AssemblyVersion>1.0.568</AssemblyVersion>
+    <FileVersion>1.0.568</FileVersion>
+    <Version>1.0.568</Version>
   </PropertyGroup>
 
   <ItemGroup>

+ 36 - 27
server/Plugins/Admin.NET.Plugin.AiDOP/Order/OrderReviewOrchestrationService.cs

@@ -112,11 +112,11 @@ public class OrderReviewOrchestrationService : ITransient
                 await _kittingCheckService.WriteBackMFRateAsync(entry.TenantId, wo.WorkOrd);
 
                 // 根据资源检查结果更新明细行系统建议交期
-                await UpdateEntrySysCapacityDateAsync(entry.Id, check.KittingTime, account);
+                await UpdateEntrySysCapacityDateAsync(entry.Id, entry.TenantId, check.KittingTime, account);
             }
 
             // ── 第4步:更新明细行进度为3 ──
-            await UpdateEntriesProgressAsync(entries.Select(e => e.Id).ToList(), "3", account);
+            await UpdateEntriesProgressAsync(order.TenantId, entries.Select(e => e.Id).ToList(), "3", account);
 
             // ── 第4.5步:重新进行生产排程(在事务提交前) ──
             try
@@ -452,7 +452,7 @@ public class OrderReviewOrchestrationService : ITransient
             await _calculator.WriteReviewOccupyAsync(
                 lines, entry.TenantId, entry.Id, order.BillNo ?? "", examineId);
 
-            await UpdateEntryAfterReviewAsync(entry.Id, check.KittingTime, account);
+            await UpdateEntryAfterReviewAsync(entry.Id, entry.TenantId, check.KittingTime, account);
         }
 
         result.EntryCount = entries.Count;
@@ -485,7 +485,7 @@ public class OrderReviewOrchestrationService : ITransient
             // 交期确认:三张占用表 status 0 -> 1
             await ConfirmReviewOccupyAsync(entry.TenantId, entry.Id);
 
-            await UpdateEntryAfterConfirmAsync(entry.Id, confirmDate, account);
+            await UpdateEntryAfterConfirmAsync(entry.Id, entry.TenantId, confirmDate, account);
             result.EntryCount++;
 
             if (woCnt > 0)
@@ -652,7 +652,7 @@ public class OrderReviewOrchestrationService : ITransient
             pars);
     }
 
-    private async Task UpdateEntryAfterReviewAsync(long entryId, DateTime? capacityDate, string account)
+    private async Task UpdateEntryAfterReviewAsync(long entryId, long tenantId, DateTime? capacityDate, string account)
     {
         await _db.Ado.ExecuteCommandAsync(
             """
@@ -660,14 +660,15 @@ public class OrderReviewOrchestrationService : ITransient
             SET progress = '2',
                 sys_capacity_date = @CapacityDate,
                 update_time = @Now
-            WHERE Id = @Id AND IsDeleted = 0
+            WHERE Id = @Id AND IsDeleted = 0 AND tenant_id = @TenantId
             """,
             new SugarParameter("@CapacityDate", capacityDate ?? (object)DBNull.Value),
             new SugarParameter("@Now", DateTime.Now),
-            new SugarParameter("@Id", entryId));
+            new SugarParameter("@Id", entryId),
+            new SugarParameter("@TenantId", tenantId));
     }
 
-    private async Task UpdateEntryAfterConfirmAsync(long entryId, DateTime? confirmDate, string account)
+    private async Task UpdateEntryAfterConfirmAsync(long entryId, long tenantId, DateTime? confirmDate, string account)
     {
         await _db.Ado.ExecuteCommandAsync(
             """
@@ -675,14 +676,15 @@ public class OrderReviewOrchestrationService : ITransient
             SET progress = '3',
                 date = COALESCE(date, @ConfirmDate),
                 update_time = @Now
-            WHERE Id = @Id AND IsDeleted = 0
+            WHERE Id = @Id AND IsDeleted = 0 AND tenant_id = @TenantId
             """,
             new SugarParameter("@ConfirmDate", confirmDate ?? (object)DBNull.Value),
             new SugarParameter("@Now", DateTime.Now),
-            new SugarParameter("@Id", entryId));
+            new SugarParameter("@Id", entryId),
+            new SugarParameter("@TenantId", tenantId));
     }
 
-    private async Task UpdateEntriesProgressAsync(IReadOnlyList<long> entryIds, string progress, string account)
+    private async Task UpdateEntriesProgressAsync(long tenantId, IReadOnlyList<long> entryIds, string progress, string account)
     {
         if (entryIds.Count == 0) return;
         var idList = string.Join(",", entryIds);
@@ -690,10 +692,11 @@ public class OrderReviewOrchestrationService : ITransient
             $"""
             UPDATE crm_seorderentry
             SET progress = @Progress, update_time = @Now
-            WHERE Id IN ({idList}) AND IsDeleted = 0
+            WHERE Id IN ({idList}) AND IsDeleted = 0 AND tenant_id = @TenantId
             """,
             new SugarParameter("@Progress", progress),
-            new SugarParameter("@Now", DateTime.Now));
+            new SugarParameter("@Now", DateTime.Now),
+            new SugarParameter("@TenantId", tenantId));
     }
 
     private static string BuildAggregateMessage(string actionCode, SeOrderReviewExecuteResult r)
@@ -873,7 +876,7 @@ public class OrderReviewOrchestrationService : ITransient
                                 SET QtyOrd = @QtyOrd, CurrQtyOpened = @CurrQtyOpened,
                                     UM = @UM, ItemName = @ItemName,
                                     UpdateUser = @User, UpdateTime = @Now
-                                WHERE RecID = @RecId
+                                WHERE RecID = @RecId AND tenant_id = @TenantId
                                 """,
                                 new SugarParameter("@QtyOrd", newQty),
                                 new SugarParameter("@CurrQtyOpened", newQty),
@@ -881,7 +884,8 @@ public class OrderReviewOrchestrationService : ITransient
                                 new SugarParameter("@ItemName", (object?)newDetail.ItemName ?? DBNull.Value),
                                 new SugarParameter("@User", account),
                                 new SugarParameter("@Now", now),
-                                new SugarParameter("@RecId", existing.RecID));
+                                new SugarParameter("@RecId", existing.RecID),
+                                new SugarParameter("@TenantId", tenantId));
                         }
                         else
                         {
@@ -891,11 +895,12 @@ public class OrderReviewOrchestrationService : ITransient
                                 UPDATE NbrDetail
                                 SET Status = 'C', IsActive = 0,
                                     UpdateUser = @User, UpdateTime = @Now
-                                WHERE RecID = @RecId
+                                WHERE RecID = @RecId AND tenant_id = @TenantId
                                 """,
                                 new SugarParameter("@User", account),
                                 new SugarParameter("@Now", now),
-                                new SugarParameter("@RecId", existing.RecID));
+                                new SugarParameter("@RecId", existing.RecID),
+                                new SugarParameter("@TenantId", tenantId));
                         }
                     }
                     else
@@ -907,7 +912,7 @@ public class OrderReviewOrchestrationService : ITransient
                             SET QtyOrd = @QtyOrd, CurrQtyOpened = @CurrQtyOpened,
                                 UM = @UM, ItemName = @ItemName,
                                 UpdateUser = @User, UpdateTime = @Now
-                            WHERE RecID = @RecId
+                            WHERE RecID = @RecId AND tenant_id = @TenantId
                             """,
                             new SugarParameter("@QtyOrd", newQty),
                             new SugarParameter("@CurrQtyOpened", newQty),
@@ -915,7 +920,8 @@ public class OrderReviewOrchestrationService : ITransient
                             new SugarParameter("@ItemName", (object?)newDetail.ItemName ?? DBNull.Value),
                             new SugarParameter("@User", account),
                             new SugarParameter("@Now", now),
-                            new SugarParameter("@RecId", existing.RecID));
+                            new SugarParameter("@RecId", existing.RecID),
+                            new SugarParameter("@TenantId", tenantId));
                     }
                 }
                 else
@@ -926,11 +932,12 @@ public class OrderReviewOrchestrationService : ITransient
                         UPDATE NbrDetail
                         SET Status = 'C', IsActive = 0,
                             UpdateUser = @User, UpdateTime = @Now
-                        WHERE RecID = @RecId
+                        WHERE RecID = @RecId AND tenant_id = @TenantId
                         """,
                         new SugarParameter("@User", account),
                         new SugarParameter("@Now", now),
-                        new SugarParameter("@RecId", existing.RecID));
+                        new SugarParameter("@RecId", existing.RecID),
+                        new SugarParameter("@TenantId", tenantId));
                 }
             }
 
@@ -981,32 +988,34 @@ public class OrderReviewOrchestrationService : ITransient
                 """
                 UPDATE NbrMaster
                 SET QtyOrd = (SELECT IFNULL(SUM(QtyOrd), 0) FROM NbrDetail
-                              WHERE Nbr = @Nbr AND Type = 'SM' AND IFNULL(IsActive, 1) = 1),
+                              WHERE Nbr = @Nbr AND Type = 'SM' AND IFNULL(IsActive, 1) = 1 AND tenant_id = @TenantId),
                     UpdateUser = @User, UpdateTime = @Now
-                WHERE RecID = @RecId
+                WHERE RecID = @RecId AND tenant_id = @TenantId
                 """,
                 new SugarParameter("@Nbr", nbr.Nbr),
                 new SugarParameter("@User", account),
                 new SugarParameter("@Now", now),
-                new SugarParameter("@RecId", nbr.RecID));
+                new SugarParameter("@RecId", nbr.RecID),
+                new SugarParameter("@TenantId", tenantId));
         }
     }
 
     /// <summary>
     /// 根据资源检查结果更新明细行系统建议交期(sys_capacity_date)。
     /// </summary>
-    private async Task UpdateEntrySysCapacityDateAsync(long entryId, DateTime? kittingTime, string account)
+    private async Task UpdateEntrySysCapacityDateAsync(long entryId, long tenantId, DateTime? kittingTime, string account)
     {
         await _db.Ado.ExecuteCommandAsync(
             """
             UPDATE crm_seorderentry
             SET sys_capacity_date = @CapacityDate,
                 update_time = @Now
-            WHERE Id = @Id AND IsDeleted = 0
+            WHERE Id = @Id AND IsDeleted = 0 AND tenant_id = @TenantId
             """,
             new SugarParameter("@CapacityDate", kittingTime ?? (object)DBNull.Value),
             new SugarParameter("@Now", DateTime.Now),
-            new SugarParameter("@Id", entryId));
+            new SugarParameter("@Id", entryId),
+            new SugarParameter("@TenantId", tenantId));
     }
 
     // ══════════════════════════════════════════════════════════════

+ 3 - 2
server/Plugins/Admin.NET.Plugin.AiDOP/Order/OrderWorkOrderGenerationService.cs

@@ -267,7 +267,7 @@ public class OrderWorkOrderGenerationService : ITransient
                 Urgent = @Urgent,
                 UpdateUser = @User,
                 UpdateTime = @Now
-            WHERE RecID = @RecId
+            WHERE RecID = @RecId AND tenant_id = @TenantId
             """,
             new SugarParameter("@ItemNum", itemNum),
             new SugarParameter("@ItemName", entry.ItemName ?? string.Empty),
@@ -277,7 +277,8 @@ public class OrderWorkOrderGenerationService : ITransient
             new SugarParameter("@Urgent", urgent),
             new SugarParameter("@User", account),
             new SugarParameter("@Now", now),
-            new SugarParameter("@RecId", existing.RecId));
+            new SugarParameter("@RecId", existing.RecId),
+            new SugarParameter("@TenantId", entry.TenantId));
     }
 
     private async Task<long> InsertMesMorderAsync(

+ 2 - 2
server/Plugins/Admin.NET.Plugin.AiDOP/ProcurementExecution/IqcReturnQueryService.cs

@@ -65,7 +65,7 @@ public class IqcReturnQueryService : IDynamicApiController, ITransient
 
         var tenantId = AidopTenantScope.ResolveOrThrow(_userManager);
         var cond = new List<string> { ReturnClfsPredicate };
-        var pars = new List<SugarParameter>();
+        var pars = new List<SugarParameter> { new("@TenantId", tenantId) };
 
         var hasTenantColumn = await _db.Ado.GetIntAsync("""
             SELECT COUNT(1)
@@ -80,7 +80,6 @@ public class IqcReturnQueryService : IDynamicApiController, ITransient
             cond.Add("c.tenant_id = @TenantId");
             cond.Add("b.tenant_id = @TenantId");
             cond.Add("(a.id IS NULL OR a.tenant_id = @TenantId)");
-            pars.Add(new("@TenantId", tenantId));
         }
 
         if (!string.IsNullOrWhiteSpace(input.OrdNbr))
@@ -158,6 +157,7 @@ public class IqcReturnQueryService : IDynamicApiController, ITransient
               AND pod.PurOrd = TRIM(IFNULL(c.FSRCORDERNUM,''))
               AND TRIM(IFNULL(c.FSRCBILLENTRYSEQ,'')) <> ''
               AND CAST(pod.Line AS CHAR(32)) = TRIM(IFNULL(c.FSRCBILLENTRYSEQ,''))
+              AND pod.tenant_id = @TenantId
             WHERE {where}
             """;
 

+ 2 - 2
server/Plugins/Admin.NET.Plugin.AiDOP/ProcurementExecution/PurchaseReturnService.cs

@@ -119,8 +119,8 @@ public class PurchaseReturnService : IDynamicApiController, ITransient
               IFNULL(d1.RctQty, 0) AS RctQty
             FROM PurOrdRctMaster p
             LEFT JOIN PurOrdRctDetail d1 ON p.RecID = d1.PurOrdRctRecID AND d1.RctType='pt' AND d1.IsActive=1
-            LEFT JOIN SuppMaster s ON p.Supp = s.Supp
-            LEFT JOIN DepartmentMaster d ON p.Department = d.Department
+            LEFT JOIN SuppMaster s ON p.Supp = s.Supp AND s.tenant_id = p.tenant_id
+            LEFT JOIN DepartmentMaster d ON p.Department = d.Department AND d.tenant_id = p.tenant_id
             LEFT JOIN ItemMaster i ON d1.ItemNum = i.ItemNum AND (p.tenant_id = i.tenant_id OR p.tenant_id IS NULL)
             WHERE {where}
             """;

+ 3 - 0
server/Plugins/Admin.NET.Plugin.AiDOP/ProcurementExecution/SupplierDeliveryManagementService.cs

@@ -120,6 +120,7 @@ public class SupplierDeliveryManagementService : IDynamicApiController, ITransie
             FROM srm_polist_ds ds
             LEFT JOIN ItemMaster im
               ON ds.itemnum = im.ItemNum
+             AND im.tenant_id = @TenantId
             LEFT JOIN vscm_jhjh a
               ON a.cgdd = ds.ponumber
              AND a.ddhh = ds.poline
@@ -193,6 +194,7 @@ public class SupplierDeliveryManagementService : IDynamicApiController, ITransie
             FROM srm_polist_ds ds
             LEFT JOIN ItemMaster im
               ON ds.itemnum = im.ItemNum
+             AND im.tenant_id = @TenantId
             LEFT JOIN vscm_jhjh a
               ON a.cgdd = ds.ponumber
              AND a.ddhh = ds.poline
@@ -272,6 +274,7 @@ public class SupplierDeliveryManagementService : IDynamicApiController, ITransie
             FROM srm_polist_ds ds
             LEFT JOIN ItemMaster im
               ON ds.itemnum = im.ItemNum
+             AND im.tenant_id = @TenantId
             LEFT JOIN vscm_jhjh a
               ON a.cgdd = ds.ponumber
              AND a.ddhh = ds.poline

+ 17 - 14
server/Plugins/Admin.NET.Plugin.AiDOP/ProcurementExecution/SupplierShipmentService.cs

@@ -380,9 +380,9 @@ public class SupplierShipmentService : IDynamicApiController, ITransient
                      glid, sh_material_code, sh_material_name, sh_material_ggxh, sh_delivery_quantity,
                      sh_material_dw, remarks, bzsl, order_type, po_billno, shdh, shdhh, scrq, scph, xh,
                      gysdm, gysmc, po_billline, bbh, th, yt, ccrq, shpc, jhdbh, jhdhh, tenant_id
-                    FROM scm_shbq WHERE shdh=@shdh;
+                    FROM scm_shbq WHERE shdh=@shdh AND tenant_id=@TenantId;
                     """,
-                    new List<SugarParameter> { new("@shdh", shddh) });
+                    new List<SugarParameter> { new("@shdh", shddh), new("@TenantId", tenantId) });
 
                 // 业务键 shdh 无唯一索引,必须叠加租户条件,否则跨租户重号时会删掉别人的标签
                 await _db.Ado.ExecuteCommandAsync(
@@ -432,6 +432,7 @@ public class SupplierShipmentService : IDynamicApiController, ITransient
                             INNER JOIN scm_shd a ON CAST(a.id AS CHAR) = b.glid
                             SET b.shpc = @shpc
                             WHERE a.shddh = @shddh
+                              AND a.tenant_id = @TenantId
                               AND b.sh_material_code = @wlbm
                               AND IFNULL(b.scph, '') = IFNULL(@scph, '')
                               AND IFNULL(b.shpc, '') = '';
@@ -442,6 +443,7 @@ public class SupplierShipmentService : IDynamicApiController, ITransient
                                 new("@shddh", shddh),
                                 new("@wlbm", p.Wlbm ?? string.Empty),
                                 new("@scph", p.Scph ?? string.Empty),
+                                new("@TenantId", tenantId),
                             });
                     }
 
@@ -481,27 +483,28 @@ public class SupplierShipmentService : IDynamicApiController, ITransient
 
                 // 3) 补 jhdhh(同一发货单:为空的明细按 id 递增,起始 max(jhdhh) or 1000)
                 var shdid = await _db.Ado.GetLongAsync(
-                    "SELECT id FROM scm_shd WHERE shddh=@shddh LIMIT 1",
-                    new List<SugarParameter> { new("@shddh", shddh) });
+                    "SELECT id FROM scm_shd WHERE shddh=@shddh AND tenant_id=@TenantId LIMIT 1",
+                    new List<SugarParameter> { new("@shddh", shddh), new("@TenantId", tenantId) });
 
                 var startNo = await _db.Ado.GetIntAsync(
-                    "SELECT IFNULL(MAX(CAST(IFNULL(jhdhh,'') AS SIGNED)), 1000) FROM scm_shdzb WHERE glid=@glid",
-                    new List<SugarParameter> { new("@glid", shdid.ToString()) });
+                    "SELECT IFNULL(MAX(CAST(IFNULL(jhdhh,'') AS SIGNED)), 1000) FROM scm_shdzb WHERE glid=@glid AND tenant_id=@TenantId",
+                    new List<SugarParameter> { new("@glid", shdid.ToString()), new("@TenantId", tenantId) });
 
                 var jhdhhNeed = await _db.Ado.SqlQueryAsync<IdOnlyRow>(
-                    "SELECT id FROM scm_shdzb WHERE glid=@glid AND IFNULL(jhdhh,'')='' ORDER BY id",
-                    new List<SugarParameter> { new("@glid", shdid.ToString()) });
+                    "SELECT id FROM scm_shdzb WHERE glid=@glid AND IFNULL(jhdhh,'')='' AND tenant_id=@TenantId ORDER BY id",
+                    new List<SugarParameter> { new("@glid", shdid.ToString()), new("@TenantId", tenantId) });
 
                 var seq = startNo;
                 foreach (var r in jhdhhNeed)
                 {
                     seq++;
                     await _db.Ado.ExecuteCommandAsync(
-                        "UPDATE scm_shdzb SET jhdhh=@jhdhh WHERE id=@id",
+                        "UPDATE scm_shdzb SET jhdhh=@jhdhh WHERE id=@id AND tenant_id=@TenantId",
                         new List<SugarParameter>
                         {
                             new("@jhdhh", seq.ToString()),
-                            new("@id", r.Id)
+                            new("@id", r.Id),
+                            new("@TenantId", tenantId)
                         });
                 }
 
@@ -538,9 +541,9 @@ public class SupplierShipmentService : IDynamicApiController, ITransient
                         b.shpc AS shpc
                     FROM scm_shd a
                     INNER JOIN scm_shdzb b ON CAST(a.id AS CHAR) = b.glid
-                    LEFT JOIN PurOrdMaster pm ON pm.PurOrd = b.po_bill
-                    LEFT JOIN PurOrdDetail pd ON pd.PurOrd = b.po_bill AND pd.Line = b.po_billline
-                    LEFT JOIN ItemMaster im ON im.ItemNum = b.sh_material_code
+                    LEFT JOIN PurOrdMaster pm ON pm.PurOrd = b.po_bill AND pm.tenant_id = @TenantId
+                    LEFT JOIN PurOrdDetail pd ON pd.PurOrd = b.po_bill AND pd.Line = b.po_billline AND pd.tenant_id = @TenantId
+                    LEFT JOIN ItemMaster im ON im.ItemNum = b.sh_material_code AND im.tenant_id = @TenantId
                     WHERE a.shddh = @shddh
                       AND a.tenant_id = @TenantId;
                     """,
@@ -1385,7 +1388,7 @@ public class SupplierShipmentService : IDynamicApiController, ITransient
               AND IFNULL(reason, '') LIKE '%收货'
             GROUP BY lot_serial
         ) l ON m.shpc = l.LotSerial
-        LEFT JOIN PurOrdMaster po ON m.po_bill = po.PurOrd
+        LEFT JOIN PurOrdMaster po ON m.po_bill = po.PurOrd AND po.tenant_id = @TenantId
         """;
 
     private sealed class SupplierShipmentListRow

+ 16 - 11
server/Plugins/Admin.NET.Plugin.AiDOP/Production/ProductionSchedulingActionService.cs

@@ -545,7 +545,7 @@ public class ProductionSchedulingActionService : IDynamicApiController, ITransie
                                 SET QtyOrd = @QtyOrd, CurrQtyOpened = @CurrQtyOpened,
                                     UM = @UM, ItemName = @ItemName,
                                     UpdateUser = @User, UpdateTime = @Now
-                                WHERE RecID = @RecId
+                                WHERE RecID = @RecId AND tenant_id = @TenantId
                                 """,
                                 new SugarParameter("@QtyOrd", newQty),
                                 new SugarParameter("@CurrQtyOpened", newQty),
@@ -553,7 +553,8 @@ public class ProductionSchedulingActionService : IDynamicApiController, ITransie
                                 new SugarParameter("@ItemName", (object?)newDetail.ItemName ?? DBNull.Value),
                                 new SugarParameter("@User", account),
                                 new SugarParameter("@Now", now),
-                                new SugarParameter("@RecId", existing.RecID));
+                                new SugarParameter("@RecId", existing.RecID),
+                                new SugarParameter("@TenantId", tenantId));
                         }
                         else
                         {
@@ -563,11 +564,12 @@ public class ProductionSchedulingActionService : IDynamicApiController, ITransie
                                 UPDATE NbrDetail
                                 SET Status = 'C', IsActive = 0,
                                     UpdateUser = @User, UpdateTime = @Now
-                                WHERE RecID = @RecId
+                                WHERE RecID = @RecId AND tenant_id = @TenantId
                                 """,
                                 new SugarParameter("@User", account),
                                 new SugarParameter("@Now", now),
-                                new SugarParameter("@RecId", existing.RecID));
+                                new SugarParameter("@RecId", existing.RecID),
+                                new SugarParameter("@TenantId", tenantId));
                         }
                     }
                     else
@@ -579,7 +581,7 @@ public class ProductionSchedulingActionService : IDynamicApiController, ITransie
                             SET QtyOrd = @QtyOrd, CurrQtyOpened = @CurrQtyOpened,
                                 UM = @UM, ItemName = @ItemName,
                                 UpdateUser = @User, UpdateTime = @Now
-                            WHERE RecID = @RecId
+                            WHERE RecID = @RecId AND tenant_id = @TenantId
                             """,
                             new SugarParameter("@QtyOrd", newQty),
                             new SugarParameter("@CurrQtyOpened", newQty),
@@ -587,7 +589,8 @@ public class ProductionSchedulingActionService : IDynamicApiController, ITransie
                             new SugarParameter("@ItemName", (object?)newDetail.ItemName ?? DBNull.Value),
                             new SugarParameter("@User", account),
                             new SugarParameter("@Now", now),
-                            new SugarParameter("@RecId", existing.RecID));
+                            new SugarParameter("@RecId", existing.RecID),
+                            new SugarParameter("@TenantId", tenantId));
                     }
                 }
                 else
@@ -598,11 +601,12 @@ public class ProductionSchedulingActionService : IDynamicApiController, ITransie
                         UPDATE NbrDetail
                         SET Status = 'C', IsActive = 0,
                             UpdateUser = @User, UpdateTime = @Now
-                        WHERE RecID = @RecId
+                        WHERE RecID = @RecId AND tenant_id = @TenantId
                         """,
                         new SugarParameter("@User", account),
                         new SugarParameter("@Now", now),
-                        new SugarParameter("@RecId", existing.RecID));
+                        new SugarParameter("@RecId", existing.RecID),
+                        new SugarParameter("@TenantId", tenantId));
                 }
             }
 
@@ -653,14 +657,15 @@ public class ProductionSchedulingActionService : IDynamicApiController, ITransie
                 """
                 UPDATE NbrMaster
                 SET QtyOrd = (SELECT IFNULL(SUM(QtyOrd), 0) FROM NbrDetail
-                              WHERE Nbr = @Nbr AND Type = 'SM' AND IFNULL(IsActive, 1) = 1),
+                              WHERE Nbr = @Nbr AND Type = 'SM' AND IFNULL(IsActive, 1) = 1 AND tenant_id = @TenantId),
                     UpdateUser = @User, UpdateTime = @Now
-                WHERE RecID = @RecId
+                WHERE RecID = @RecId AND tenant_id = @TenantId
                 """,
                 new SugarParameter("@Nbr", nbr.Nbr),
                 new SugarParameter("@User", account),
                 new SugarParameter("@Now", now),
-                new SugarParameter("@RecId", nbr.RecID));
+                new SugarParameter("@RecId", nbr.RecID),
+                new SugarParameter("@TenantId", tenantId));
         }
     }
 

+ 1 - 0
server/Plugins/Admin.NET.Plugin.AiDOP/Production/ScheduleExceptionService.cs

@@ -83,6 +83,7 @@ public class ScheduleExceptionService : IDynamicApiController, ITransient
         LEFT JOIN ItemMaster im
             ON (sm.`Domain` COLLATE {coll}) = (im.`Domain` COLLATE {coll})
             AND (sm.ItemNum COLLATE {coll}) = (im.ItemNum COLLATE {coll})
+            AND im.tenant_id = @TenantId
         WHERE {innerWhere}
         """;
     }

+ 2 - 2
server/Plugins/Admin.NET.Plugin.AiDOP/Production/WorkOrderSchedulingService.cs

@@ -1127,8 +1127,8 @@ public class WorkOrderSchedulingService : IDynamicApiController, ITransient
                     @CreateUser,
                     w.`tenant_id`,CAST(IFNULL(a.`MilestoneOp`, 0) AS UNSIGNED),0,0,0
                 FROM WorkOrdMaster w
-                LEFT JOIN RoutingOpDetail a ON w.`ItemNum` = a.`RoutingCode`
-                LEFT JOIN ProdLineDetail b ON a.`RoutingCode` = b.`Part` AND a.`Op` = b.`Op`
+                LEFT JOIN RoutingOpDetail a ON w.`ItemNum` = a.`RoutingCode` AND a.`tenant_id` = w.`tenant_id`
+                LEFT JOIN ProdLineDetail b ON a.`RoutingCode` = b.`Part` AND a.`Op` = b.`Op` AND b.`tenant_id` = w.`tenant_id`
                 WHERE w.`WorkOrd` = @WorkOrd
                   AND {SqlWorkOrdMasterMatchDomainOrTenantAliased("w")}
                   AND IFNULL(a.`IsActive`, 0) = 1

+ 1 - 0
server/Plugins/Admin.NET.Plugin.AiDOP/Supply/DeliveryExceptionService.cs

@@ -67,6 +67,7 @@ public class DeliveryExceptionService : IDynamicApiController, ITransient
         LEFT JOIN ItemMaster im
             ON (dm.Domain COLLATE {C}) = (im.Domain COLLATE {C})
             AND (dm.ItemNum COLLATE {C}) = (im.ItemNum COLLATE {C})
+            AND im.tenant_id = @TenantId
         WHERE {innerWhere}
         """;
 

+ 34 - 22
server/Plugins/Admin.NET.Plugin.AiDOP/Supply/DemandOrderService.cs

@@ -144,10 +144,11 @@ public class DemandOrderService : IDynamicApiController, ITransient
                 d.PurOrd AS PurOrd,
                 d.PurOrdRecID AS PurOrdRecID
             FROM PurOrdDetail d
-            WHERE d.PurOrd=@PurOrd AND d.Potype='PO'
+            WHERE d.PurOrd=@PurOrd AND d.Potype='PO' AND d.tenant_id=@TenantId
             ORDER BY d.Line
             """,
-            new SugarParameter("@PurOrd", master.PurOrd));
+            new SugarParameter("@PurOrd", master.PurOrd),
+            new SugarParameter("@TenantId", ResolveTenantOrThrow()));
 
         return new { master, details };
     }
@@ -166,6 +167,7 @@ public class DemandOrderService : IDynamicApiController, ITransient
         var usage = string.IsNullOrWhiteSpace(input.Usage) ? "标准" : input.Usage.Trim();
         var fstid = string.Equals(usage, "VMI", StringComparison.OrdinalIgnoreCase) ? "3" : "1";
         if (!string.IsNullOrWhiteSpace(input.Fstid)) fstid = input.Fstid.Trim();
+        var tenantId = ResolveTenantOrThrow();
 
         try
         {
@@ -214,11 +216,12 @@ public class DemandOrderService : IDynamicApiController, ITransient
                     new SugarParameter("@UpdateUser", _userManager.Account),
                     new SugarParameter("@UpdateTime", now),
                     new SugarParameter("@Domain", "100"),
-                    new SugarParameter("@TenantId", ResolveTenantOrThrow())
+                    new SugarParameter("@TenantId", tenantId)
                 );
                 masterId = await _db.Ado.GetIntAsync(
-                    "SELECT IFNULL(MAX(RecID),0) FROM PurOrdMaster WHERE PurOrd=@PurOrd",
-                    new SugarParameter("@PurOrd", purOrd));
+                    "SELECT IFNULL(MAX(RecID),0) FROM PurOrdMaster WHERE PurOrd=@PurOrd AND tenant_id=@TenantId",
+                    new SugarParameter("@PurOrd", purOrd),
+                    new SugarParameter("@TenantId", tenantId));
             }
             else
             {
@@ -230,8 +233,9 @@ public class DemandOrderService : IDynamicApiController, ITransient
                 if (exists <= 0) throw Oops.Oh("记录不存在");
 
                 purOrd = await _db.Ado.GetStringAsync(
-                    "SELECT PurOrd FROM PurOrdMaster WHERE RecID=@Id LIMIT 1",
-                    new SugarParameter("@Id", masterId)) ?? throw Oops.Oh("记录不存在");
+                    "SELECT PurOrd FROM PurOrdMaster WHERE RecID=@Id AND tenant_id=@TenantId LIMIT 1",
+                    new SugarParameter("@Id", masterId),
+                    new SugarParameter("@TenantId", ResolveTenantOrThrow())) ?? throw Oops.Oh("记录不存在");
 
                 await _db.Ado.ExecuteCommandAsync(
                     """
@@ -239,7 +243,7 @@ public class DemandOrderService : IDynamicApiController, ITransient
                     SET OrdDate=@OrdDate,Supp=@Supp,ReqBy=@ReqBy,Buyer=@Buyer,Department=@Department,
                         Curr=@Curr,`Usage`=@Usage,Remark=@Remark,FSTID=@FSTID,
                         UpdateUser=@UpdateUser,UpdateTime=@UpdateTime
-                    WHERE RecID=@Id
+                    WHERE RecID=@Id AND tenant_id=@TenantId
                     """,
                     new SugarParameter("@Id", masterId),
                     new SugarParameter("@OrdDate", ordDate),
@@ -274,10 +278,11 @@ public class DemandOrderService : IDynamicApiController, ITransient
     {
         if (string.IsNullOrWhiteSpace(purOrd)) throw Oops.Oh("缺少要货令单号");
 
+        var tenantId = ResolveTenantOrThrow();
         var delPars = new List<SugarParameter>
         {
             new("@PurOrd", purOrd.Trim()),
-            new("@TenantId", ResolveTenantOrThrow())
+            new("@TenantId", tenantId)
         };
         const string tenantSuffix = " AND tenant_id=@TenantId";
 
@@ -300,12 +305,14 @@ public class DemandOrderService : IDynamicApiController, ITransient
         {
             _db.Ado.BeginTran();
             await _db.Ado.ExecuteCommandAsync(
-                "DELETE FROM PurOrdDetail WHERE PurOrd=@PurOrd AND Potype='PO'",
-                new SugarParameter("@PurOrd", purOrd.Trim()));
+                "DELETE FROM PurOrdDetail WHERE PurOrd=@PurOrd AND Potype='PO' AND tenant_id=@TenantId",
+                new SugarParameter("@PurOrd", purOrd.Trim()),
+                new SugarParameter("@TenantId", tenantId));
             await _db.Ado.ExecuteCommandAsync(
-                "DELETE FROM PurOrdMaster WHERE RecID=@Id AND PurOrd=@PurOrd",
+                "DELETE FROM PurOrdMaster WHERE RecID=@Id AND PurOrd=@PurOrd AND tenant_id=@TenantId",
                 new SugarParameter("@Id", id),
-                new SugarParameter("@PurOrd", purOrd.Trim()));
+                new SugarParameter("@PurOrd", purOrd.Trim()),
+                new SugarParameter("@TenantId", tenantId));
             _db.Ado.CommitTran();
         }
         catch
@@ -434,13 +441,15 @@ public class DemandOrderService : IDynamicApiController, ITransient
 
     private async Task SaveDetailsAsync(int masterId, string purOrd, List<DemandOrderDetailInput> details)
     {
+        var tenantId = ResolveTenantOrThrow();
         var dbDetails = await _db.Ado.SqlQueryAsync<DemandOrderDetailRow>(
             """
             SELECT RecID AS Id, Line AS Line
             FROM PurOrdDetail
-            WHERE PurOrd=@PurOrd AND Potype='PO'
+            WHERE PurOrd=@PurOrd AND Potype='PO' AND tenant_id=@TenantId
             """,
-            new SugarParameter("@PurOrd", purOrd));
+            new SugarParameter("@PurOrd", purOrd),
+            new SugarParameter("@TenantId", tenantId));
         var dbById = dbDetails.ToDictionary(d => d.Id);
         var inputIds = new HashSet<int>(details.Where(d => d.Id is > 0).Select(d => d.Id!.Value));
 
@@ -475,7 +484,7 @@ public class DemandOrderService : IDynamicApiController, ITransient
                     SET ItemNum=@ItemNum,Descr=@Descr,UM=@UM,Location=@Location,QtyOrded=@QtyOrded,
                         DueDate=@DueDate,Rev=@Rev,Drawing=@Drawing,LotSerial=@LotSerial,
                         UpdateUser=@UpdateUser,UpdateTime=@UpdateTime
-                    WHERE RecID=@Id
+                    WHERE RecID=@Id AND tenant_id=@TenantId
                     """,
                     new SugarParameter("@Id", d.Id.Value),
                     new SugarParameter("@ItemNum", item.ItemNum),
@@ -494,8 +503,9 @@ public class DemandOrderService : IDynamicApiController, ITransient
             else
             {
                 var line = d.Line ?? await _db.Ado.GetIntAsync(
-                    "SELECT IFNULL(MAX(Line),0)+1 FROM PurOrdDetail WHERE PurOrd=@PurOrd",
-                    new SugarParameter("@PurOrd", purOrd));
+                    "SELECT IFNULL(MAX(Line),0)+1 FROM PurOrdDetail WHERE PurOrd=@PurOrd AND tenant_id=@TenantId",
+                    new SugarParameter("@PurOrd", purOrd),
+                    new SugarParameter("@TenantId", tenantId));
 
                 await _db.Ado.ExecuteCommandAsync(
                     """
@@ -548,13 +558,15 @@ public class DemandOrderService : IDynamicApiController, ITransient
         foreach (var toDelete in dbDetails.Where(u => !inputIds.Contains(u.Id)))
         {
             var rctQty = await _db.Ado.GetDecimalAsync(
-                "SELECT IFNULL(RctQty,0) FROM PurOrdDetail WHERE RecID=@Id",
-                new SugarParameter("@Id", toDelete.Id));
+                "SELECT IFNULL(RctQty,0) FROM PurOrdDetail WHERE RecID=@Id AND tenant_id=@TenantId",
+                new SugarParameter("@Id", toDelete.Id),
+                new SugarParameter("@TenantId", tenantId));
             if (rctQty > 0) throw Oops.Oh("明细存在收货数量,不允许删除");
 
             await _db.Ado.ExecuteCommandAsync(
-                "DELETE FROM PurOrdDetail WHERE RecID=@Id",
-                new SugarParameter("@Id", toDelete.Id));
+                "DELETE FROM PurOrdDetail WHERE RecID=@Id AND tenant_id=@TenantId",
+                new SugarParameter("@Id", toDelete.Id),
+                new SugarParameter("@TenantId", tenantId));
         }
     }
 

+ 5 - 4
server/Plugins/Admin.NET.Plugin.AiDOP/Supply/NumberRuleService.cs

@@ -126,7 +126,7 @@ public class NumberRuleService : ITransient
         if (dayInfo == null)
             await InsertDayInfoAsync(rule, sequenceDate, lastSerial, operatorNo, now);
         else
-            await UpdateDayInfoAsync(dayInfo.Id, lastSerial, operatorNo, now);
+            await UpdateDayInfoAsync(tenantId, dayInfo.Id, lastSerial, operatorNo, now);
 
         return numbers;
     }
@@ -199,7 +199,7 @@ public class NumberRuleService : ITransient
             new SugarParameter("@TenantId", rule.TenantId));
     }
 
-    private async Task UpdateDayInfoAsync(int dayInfoId, int nextValue, string operatorNo, DateTime now)
+    private async Task UpdateDayInfoAsync(long tenantId, int dayInfoId, int nextValue, string operatorNo, DateTime now)
     {
         await _db.Ado.ExecuteCommandAsync(
             """
@@ -207,12 +207,13 @@ public class NumberRuleService : ITransient
             SET NextValue=@NextValue,
                 UpdateUser=@UpdateUser,
                 UpdateTime=@UpdateTime
-            WHERE RecID=@Id
+            WHERE RecID=@Id AND tenant_id=@TenantId
             """,
             new SugarParameter("@NextValue", nextValue),
             new SugarParameter("@UpdateUser", operatorNo ?? string.Empty),
             new SugarParameter("@UpdateTime", now),
-            new SugarParameter("@Id", dayInfoId));
+            new SugarParameter("@Id", dayInfoId),
+            new SugarParameter("@TenantId", tenantId));
     }
 
     private static int ResolveFirstSerial(NbrControlRuleRow rule, NbrDayInfoRow? dayInfo)

+ 34 - 22
server/Plugins/Admin.NET.Plugin.AiDOP/Supply/OutsourceOrderService.cs

@@ -156,6 +156,7 @@ public class OutsourceOrderService : IDynamicApiController, ITransient
 
         if (input.Id is null or <= 0)
         {
+            var tenantId = ResolveTenantOrThrow();
             try
             {
                 _db.Ado.BeginTran();
@@ -197,11 +198,12 @@ public class OutsourceOrderService : IDynamicApiController, ITransient
                     new SugarParameter("@CreateTime", now),
                     new SugarParameter("@UpdateUser", _userManager.Account),
                     new SugarParameter("@UpdateTime", now),
-                    new SugarParameter("@TenantId", ResolveTenantOrThrow())
+                    new SugarParameter("@TenantId", tenantId)
                 );
                 var id = await _db.Ado.GetIntAsync(
-                    "SELECT IFNULL(MAX(RecID),0) FROM PurOrdMaster WHERE PurOrd=@PurOrd",
-                    new SugarParameter("@PurOrd", purOrd));
+                    "SELECT IFNULL(MAX(RecID),0) FROM PurOrdMaster WHERE PurOrd=@PurOrd AND tenant_id=@TenantId",
+                    new SugarParameter("@PurOrd", purOrd),
+                    new SugarParameter("@TenantId", tenantId));
                 _db.Ado.CommitTran();
                 return new { id, purOrd, message = "新增成功" };
             }
@@ -219,7 +221,7 @@ public class OutsourceOrderService : IDynamicApiController, ITransient
             """
             UPDATE PurOrdMaster
             SET OrdDate=@OrdDate,Supp=@Supp,ReqBy=@ReqBy,Buyer=@Buyer,Department=@Department,`Usage`=@Usage,Remark=@Remark,UpdateUser=@UpdateUser,UpdateTime=@UpdateTime
-            WHERE RecID=@Id
+            WHERE RecID=@Id AND tenant_id=@TenantId
             """,
             new SugarParameter("@Id", input.Id.Value),
             new SugarParameter("@OrdDate", ordDate),
@@ -230,7 +232,8 @@ public class OutsourceOrderService : IDynamicApiController, ITransient
             new SugarParameter("@Usage", usage),
             new SugarParameter("@Remark", input.Remark?.Trim()),
             new SugarParameter("@UpdateUser", _userManager.Account),
-            new SugarParameter("@UpdateTime", now)
+            new SugarParameter("@UpdateTime", now),
+            new SugarParameter("@TenantId", ResolveTenantOrThrow())
         );
         return new { id = input.Id, message = "编辑成功" };
     }
@@ -240,22 +243,26 @@ public class OutsourceOrderService : IDynamicApiController, ITransient
     public async Task<object> DeleteOrder(int id, [FromQuery] string purOrd)
     {
         if (string.IsNullOrWhiteSpace(purOrd)) throw Oops.Oh("缺少采购订单号");
+        var tenantId = ResolveTenantOrThrow();
         var hasReceipt = await _db.Ado.GetIntAsync(
             "SELECT COUNT(1) FROM PurOrdRctDetail WHERE OrdNbr=@PurOrd AND IFNULL(QtyReceived,0)>0 AND tenant_id=@TenantId",
-            new[] { new SugarParameter("@PurOrd", purOrd.Trim()), new SugarParameter("@TenantId", ResolveTenantOrThrow()) });
+            new[] { new SugarParameter("@PurOrd", purOrd.Trim()), new SugarParameter("@TenantId", tenantId) });
         if (hasReceipt > 0) throw Oops.Oh("存在收货数量,不允许删除");
 
         var hasShip = await _db.Ado.GetIntAsync(
             "SELECT COUNT(1) FROM scm_shdzb WHERE po_bill=@PurOrd AND tenant_id=@TenantId",
-            new[] { new SugarParameter("@PurOrd", purOrd.Trim()), new SugarParameter("@TenantId", ResolveTenantOrThrow()) });
+            new[] { new SugarParameter("@PurOrd", purOrd.Trim()), new SugarParameter("@TenantId", tenantId) });
         if (hasShip > 0) throw Oops.Oh("存在发货单,不允许删除");
 
         try
         {
             _db.Ado.BeginTran();
-            await _db.Ado.ExecuteCommandAsync("DELETE FROM PurOrdDetailBatch WHERE PurOrd=@PurOrd", new SugarParameter("@PurOrd", purOrd.Trim()));
-            await _db.Ado.ExecuteCommandAsync("DELETE FROM PurOrdDetail WHERE PurOrd=@PurOrd", new SugarParameter("@PurOrd", purOrd.Trim()));
-            await _db.Ado.ExecuteCommandAsync("DELETE FROM PurOrdMaster WHERE RecID=@Id AND PurOrd=@PurOrd", new SugarParameter("@Id", id), new SugarParameter("@PurOrd", purOrd.Trim()));
+            await _db.Ado.ExecuteCommandAsync("DELETE FROM PurOrdDetailBatch WHERE PurOrd=@PurOrd AND tenant_id=@TenantId",
+                new SugarParameter("@PurOrd", purOrd.Trim()), new SugarParameter("@TenantId", tenantId));
+            await _db.Ado.ExecuteCommandAsync("DELETE FROM PurOrdDetail WHERE PurOrd=@PurOrd AND tenant_id=@TenantId",
+                new SugarParameter("@PurOrd", purOrd.Trim()), new SugarParameter("@TenantId", tenantId));
+            await _db.Ado.ExecuteCommandAsync("DELETE FROM PurOrdMaster WHERE RecID=@Id AND PurOrd=@PurOrd AND tenant_id=@TenantId",
+                new SugarParameter("@Id", id), new SugarParameter("@PurOrd", purOrd.Trim()), new SugarParameter("@TenantId", tenantId));
             _db.Ado.CommitTran();
         }
         catch
@@ -308,7 +315,7 @@ public class OutsourceOrderService : IDynamicApiController, ITransient
 
         var fromSql = $"""
             FROM PurOrdDetail d
-            LEFT JOIN ItemMaster i ON d.ItemNum=i.ItemNum
+            LEFT JOIN ItemMaster i ON d.ItemNum=i.ItemNum AND i.tenant_id=@TenantId
             WHERE {string.Join(" AND ", where)}
             """;
         var total = await _db.Ado.GetIntAsync($"SELECT COUNT(1) {fromSql}", pars);
@@ -339,7 +346,7 @@ public class OutsourceOrderService : IDynamicApiController, ITransient
                 d.DueDate AS DueDate,d.Line AS Line,d.Location AS Location,d.UM AS UM,d.RecID AS Id,d.Rev AS Rev,d.Drawing AS Drawing,
                 d.WorkOrd AS WorkOrd,d.LotSerial AS LotSerial,d.Status AS Status,IFNULL(i.Descr,'') AS Descr,d.PurOrdRecID AS PurOrdRecID
             FROM PurOrdDetail d
-            LEFT JOIN ItemMaster i ON d.ItemNum=i.ItemNum
+            LEFT JOIN ItemMaster i ON d.ItemNum=i.ItemNum AND i.tenant_id=@TenantId
             WHERE d.RecID=@Id{tenantWhere}
             LIMIT 1
             """,
@@ -368,6 +375,7 @@ public class OutsourceOrderService : IDynamicApiController, ITransient
         if (input.PurOrdRecID <= 0) throw Oops.Oh("采购订单主键值不能为空");
         if (string.IsNullOrWhiteSpace(input.ItemNum)) throw Oops.Oh("请选择物料");
         if (!input.QtyOrded.HasValue || input.QtyOrded.Value <= 0) throw Oops.Oh("订单数量必须大于0");
+        var tenantId = ResolveTenantOrThrow();
 
         var item = (await _db.Ado.SqlQueryAsync<ItemLookupRow>(
             """
@@ -386,7 +394,7 @@ public class OutsourceOrderService : IDynamicApiController, ITransient
             int line;
             if (input.Id is null or <= 0)
             {
-                line = input.Line ?? await _db.Ado.GetIntAsync("SELECT IFNULL(MAX(Line),0)+1 FROM PurOrdDetail WHERE PurOrd=@PurOrd", new SugarParameter("@PurOrd", input.PurOrd.Trim()));
+                line = input.Line ?? await _db.Ado.GetIntAsync("SELECT IFNULL(MAX(Line),0)+1 FROM PurOrdDetail WHERE PurOrd=@PurOrd AND tenant_id=@TenantId", new SugarParameter("@PurOrd", input.PurOrd.Trim()), new SugarParameter("@TenantId", tenantId));
                 await _db.Ado.ExecuteCommandAsync(
                     """
                     INSERT INTO PurOrdDetail
@@ -432,17 +440,17 @@ public class OutsourceOrderService : IDynamicApiController, ITransient
                     new SugarParameter("@UpdateTime", DateTime.Now),
                     new SugarParameter("@TenantId", ResolveTenantOrThrow())
                 );
-                detailId = await _db.Ado.GetIntAsync("SELECT IFNULL(MAX(RecID),0) FROM PurOrdDetail WHERE PurOrd=@PurOrd AND Line=@Line", new SugarParameter("@PurOrd", input.PurOrd.Trim()), new SugarParameter("@Line", line));
+                detailId = await _db.Ado.GetIntAsync("SELECT IFNULL(MAX(RecID),0) FROM PurOrdDetail WHERE PurOrd=@PurOrd AND Line=@Line AND tenant_id=@TenantId", new SugarParameter("@PurOrd", input.PurOrd.Trim()), new SugarParameter("@Line", line), new SugarParameter("@TenantId", tenantId));
             }
             else
             {
                 detailId = input.Id.Value;
-                line = input.Line ?? await _db.Ado.GetIntAsync("SELECT IFNULL(Line,0) FROM PurOrdDetail WHERE RecID=@Id", new SugarParameter("@Id", detailId));
+                line = input.Line ?? await _db.Ado.GetIntAsync("SELECT IFNULL(Line,0) FROM PurOrdDetail WHERE RecID=@Id AND tenant_id=@TenantId", new SugarParameter("@Id", detailId), new SugarParameter("@TenantId", tenantId));
                 await _db.Ado.ExecuteCommandAsync(
                     """
                     UPDATE PurOrdDetail
                     SET ItemNum=@ItemNum,Descr=@Descr,UM=@UM,Rev=@Rev,Drawing=@Drawing,Location=@Location,QtyOrded=@QtyOrded,DueDate=@DueDate,UpdateUser=@UpdateUser,UpdateTime=@UpdateTime
-                    WHERE RecID=@Id
+                    WHERE RecID=@Id AND tenant_id=@TenantId
                     """,
                     new SugarParameter("@Id", detailId),
                     new SugarParameter("@ItemNum", item.ItemNum),
@@ -458,7 +466,7 @@ public class OutsourceOrderService : IDynamicApiController, ITransient
                 );
             }
 
-            await _db.Ado.ExecuteCommandAsync("DELETE FROM PurOrdDetailBatch WHERE PurOrdDetailRecID=@RecID", new SugarParameter("@RecID", detailId));
+            await _db.Ado.ExecuteCommandAsync("DELETE FROM PurOrdDetailBatch WHERE PurOrdDetailRecID=@RecID AND tenant_id=@TenantId", new SugarParameter("@RecID", detailId), new SugarParameter("@TenantId", tenantId));
 
             var batchNo = 1;
             foreach (var b in input.Batches)
@@ -533,8 +541,8 @@ public class OutsourceOrderService : IDynamicApiController, ITransient
         try
         {
             _db.Ado.BeginTran();
-            await _db.Ado.ExecuteCommandAsync("DELETE FROM PurOrdDetailBatch WHERE PurOrdDetailRecID=@Id", new SugarParameter("@Id", id));
-            await _db.Ado.ExecuteCommandAsync("DELETE FROM PurOrdDetail WHERE RecID=@Id", new SugarParameter("@Id", id));
+            await _db.Ado.ExecuteCommandAsync("DELETE FROM PurOrdDetailBatch WHERE PurOrdDetailRecID=@Id AND tenant_id=@TenantId", new SugarParameter("@Id", id), new SugarParameter("@TenantId", ResolveTenantOrThrow()));
+            await _db.Ado.ExecuteCommandAsync("DELETE FROM PurOrdDetail WHERE RecID=@Id AND tenant_id=@TenantId", new SugarParameter("@Id", id), new SugarParameter("@TenantId", ResolveTenantOrThrow()));
             _db.Ado.CommitTran();
         }
         catch
@@ -685,11 +693,15 @@ public class OutsourceOrderService : IDynamicApiController, ITransient
                 IFNULL(psm.UM, im.UM) AS UM,
                 im.Descr AS ItemName
             FROM ProductStructureMaster psm
-            LEFT JOIN ItemMaster im ON psm.ComponentItem = im.ItemNum
-            WHERE psm.ParentItem = @itemNum
+            LEFT JOIN ItemMaster im ON psm.ComponentItem = im.ItemNum AND im.tenant_id = @TenantId
+            WHERE psm.ParentItem = @itemNum AND psm.tenant_id = @TenantId
             ORDER BY psm.ComponentItem
             """,
-            new { itemNum = itemNum.Trim() });
+            new List<SugarParameter>
+            {
+                new("@itemNum", itemNum.Trim()),
+                new("@TenantId", ResolveTenantOrThrow())
+            });
         return new { list };
     }
 

+ 59 - 40
server/Plugins/Admin.NET.Plugin.AiDOP/Supply/ProcessOutsourceOrderService.cs

@@ -86,16 +86,16 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
                 p.`Usage` AS `Usage`,
                 p.Curr AS Curr,
                 p.Remark AS Remark,
-                (CASE WHEN EXISTS(SELECT 1 FROM PurOrdDetail pd WHERE pd.PurOrd=p.PurOrd AND IFNULL(pd.QtyReceived,0)>0) THEN 1 ELSE 0 END) AS HasReceived
+                (CASE WHEN EXISTS(SELECT 1 FROM PurOrdDetail pd WHERE pd.PurOrd=p.PurOrd AND IFNULL(pd.QtyReceived,0)>0 AND pd.tenant_id=@TenantId) THEN 1 ELSE 0 END) AS HasReceived
             FROM PurOrdMaster p
-            LEFT JOIN SuppMaster s ON p.Supp=s.Supp
-            LEFT JOIN DepartmentMaster d ON p.Department=d.Department
-            LEFT JOIN EmployeeMaster e ON p.Buyer=e.Employee
-            LEFT JOIN PurOrdDetail f ON p.PurOrd=f.PurOrd
-            LEFT JOIN RoutingOpDetail r ON f.Op=r.Op AND f.ItemNum=r.RoutingCode
-            LEFT JOIN ItemMaster i ON f.ItemNum=i.ItemNum
-            LEFT JOIN PurOrdRctMaster o ON o.OrdNbr=p.PurOrd
-            LEFT JOIN NbrMaster n ON p.WorkOrd=n.WorkOrd AND n.Type='CA'
+            LEFT JOIN SuppMaster s ON p.Supp=s.Supp AND s.tenant_id=@TenantId
+            LEFT JOIN DepartmentMaster d ON p.Department=d.Department AND d.tenant_id=@TenantId
+            LEFT JOIN EmployeeMaster e ON p.Buyer=e.Employee AND e.tenant_id=@TenantId
+            LEFT JOIN PurOrdDetail f ON p.PurOrd=f.PurOrd AND f.tenant_id=@TenantId
+            LEFT JOIN RoutingOpDetail r ON f.Op=r.Op AND f.ItemNum=r.RoutingCode AND r.tenant_id=@TenantId
+            LEFT JOIN ItemMaster i ON f.ItemNum=i.ItemNum AND i.tenant_id=@TenantId
+            LEFT JOIN PurOrdRctMaster o ON o.OrdNbr=p.PurOrd AND o.tenant_id=@TenantId
+            LEFT JOIN NbrMaster n ON p.WorkOrd=n.WorkOrd AND n.Type='CA' AND n.tenant_id=@TenantId
             WHERE {string.Join(" AND ", where)}
             """;
 
@@ -152,11 +152,12 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
                 d.PurOrd AS PurOrd,
                 d.PurOrdRecID AS PurOrdRecID
             FROM PurOrdDetail d
-            LEFT JOIN ItemMaster i ON d.ItemNum=i.ItemNum
-            WHERE d.PurOrdRecID=@PurOrdRecID
+            LEFT JOIN ItemMaster i ON d.ItemNum=i.ItemNum AND i.tenant_id=@TenantId
+            WHERE d.PurOrdRecID=@PurOrdRecID AND d.tenant_id=@TenantId
             ORDER BY d.Line,d.RecID
             """,
-            new SugarParameter("@PurOrdRecID", id));
+            new SugarParameter("@PurOrdRecID", id),
+            new SugarParameter("@TenantId", ResolveTenantOrThrow()));
 
         return new { master, details };
     }
@@ -167,6 +168,7 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
     {
         if (string.IsNullOrWhiteSpace(input.WorkOrd)) throw Oops.Oh("请选择工单");
         var workOrd = input.WorkOrd.Trim();
+        var tenantId = ResolveTenantOrThrow();
 
         // 先筛出“当前工单且未生成采购单”的外协供应商清单(等价于存储过程内 @v_temp_supp)。
         var suppliers = await _db.Ado.SqlQueryAsync<SuppRow>(
@@ -175,14 +177,16 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
             FROM WorkOrdMaster m
             LEFT JOIN WorkOrdRouting r ON m.WorkOrd=r.WorkOrd
             LEFT JOIN RoutingOpDetail d ON r.Op=d.Op AND r.ItemNum=d.RoutingCode
-            LEFT JOIN PurOrdMaster p ON m.WorkOrd=p.WorkOrd AND d.SupplierCode=p.Supp
+            LEFT JOIN PurOrdMaster p ON m.WorkOrd=p.WorkOrd AND d.SupplierCode=p.Supp AND p.tenant_id=@TenantId
             WHERE r.ProcessOut=1
               AND m.WorkOrd=@WorkOrd
+              AND m.tenant_id=@TenantId
               AND p.RecID IS NULL
               AND IFNULL(TRIM(d.SupplierCode),'')<>''
             ORDER BY d.SupplierCode
             """,
-            new SugarParameter("@WorkOrd", workOrd));
+            new SugarParameter("@WorkOrd", workOrd),
+            new SugarParameter("@TenantId", tenantId));
         if (suppliers.Count == 0)
             throw Oops.Oh("当前工单无需生成外协采购订单。");
 
@@ -190,10 +194,11 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
             """
             SELECT IFNULL(TRIM(Domain),'')
             FROM WorkOrdMaster
-            WHERE WorkOrd=@WorkOrd
+            WHERE WorkOrd=@WorkOrd AND tenant_id=@TenantId
             LIMIT 1
             """,
-            new SugarParameter("@WorkOrd", workOrd)) ?? string.Empty;
+            new SugarParameter("@WorkOrd", workOrd),
+            new SugarParameter("@TenantId", tenantId)) ?? string.Empty;
 
         var created = new List<IdPurOrdRow>();
         try
@@ -242,7 +247,7 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
                         m.WorkOrd,
                         @TenantId
                     FROM WorkOrdMaster m
-                    WHERE m.WorkOrd=@WorkOrd
+                    WHERE m.WorkOrd=@WorkOrd AND m.tenant_id=@TenantId
                     LIMIT 1
                     """,
                     new SugarParameter("@Buyer", _userManager.Account),
@@ -254,8 +259,9 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
                     new SugarParameter("@TenantId", ResolveTenantOrThrow()));
 
                 var masterId = await _db.Ado.GetIntAsync(
-                    "SELECT IFNULL(MAX(RecID),0) FROM PurOrdMaster WHERE PurOrd=@PurOrd",
-                    new SugarParameter("@PurOrd", purOrd));
+                    "SELECT IFNULL(MAX(RecID),0) FROM PurOrdMaster WHERE PurOrd=@PurOrd AND tenant_id=@TenantId",
+                    new SugarParameter("@PurOrd", purOrd),
+                    new SugarParameter("@TenantId", tenantId));
                 if (masterId <= 0)
                     throw Oops.Oh("采购订单生成失败。");
 
@@ -274,16 +280,18 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
                         IFNULL(m.RecID,0) AS WorkOrdID,
                         IFNULL(d.OutsourcedLeadTime,0) AS ProcessOutDay
                     FROM WorkOrdMaster m
-                    LEFT JOIN WorkOrdRouting r ON m.WorkOrd=r.WorkOrd
-                    LEFT JOIN RoutingOpDetail d ON r.Op=d.Op AND r.ItemNum=d.RoutingCode
-                    LEFT JOIN ItemMaster i ON r.ItemNum=i.ItemNum
+                    LEFT JOIN WorkOrdRouting r ON m.WorkOrd=r.WorkOrd AND r.tenant_id=@TenantId
+                    LEFT JOIN RoutingOpDetail d ON r.Op=d.Op AND r.ItemNum=d.RoutingCode AND d.tenant_id=@TenantId
+                    LEFT JOIN ItemMaster i ON r.ItemNum=i.ItemNum AND i.tenant_id=@TenantId
                     WHERE r.ProcessOut=1
                       AND m.WorkOrd=@WorkOrd
+                      AND m.tenant_id=@TenantId
                       AND d.SupplierCode=@Supp
                     ORDER BY r.RecID
                     """,
                     new SugarParameter("@WorkOrd", workOrd),
-                    new SugarParameter("@Supp", supp));
+                    new SugarParameter("@Supp", supp),
+                    new SugarParameter("@TenantId", tenantId));
 
                 for (var lineIndex = 0; lineIndex < lines.Count; lineIndex++)
                 {
@@ -332,10 +340,10 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
                         new SugarParameter("@WorkOrd", row.WorkOrd),
                         new SugarParameter("@Drawing", row.Drawing),
                         new SugarParameter("@PurOrdRecID", masterId),
-                        new SugarParameter("@TenantId", ResolveTenantOrThrow()));
+                        new SugarParameter("@TenantId", tenantId));
                 }
 
-                await UpsertProcessOutsourceMdpAsync(purOrd, now);
+                await UpsertProcessOutsourceMdpAsync(purOrd, tenantId, now);
                 created.Add(new IdPurOrdRow { Id = masterId, PurOrd = purOrd });
             }
 
@@ -352,7 +360,7 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
         return new { id = latest.Id, purOrd = latest.PurOrd, message = "采购订单生成成功。" };
     }
 
-    private async Task UpsertProcessOutsourceMdpAsync(string purOrd, DateTime now)
+    private async Task UpsertProcessOutsourceMdpAsync(string purOrd, long tenantId, DateTime now)
     {
         var batchId = $"S3_OUTSOURCE_{now:yyyyMMddHHmmss}";
         // S8-RULE01-AUTHORITY-SINGLE-WRITER:已移除对 mdp_std_purchase_order 的直写。
@@ -385,6 +393,7 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
             FROM PurOrdMaster m
             JOIN PurOrdDetail d ON m.RecID = d.PurOrdRecID
             WHERE m.PurOrd = @PurOrd
+              AND m.tenant_id = @TenantId
               AND m.Potype = 'PW'
               AND IFNULL(m.WorkOrd, '') <> ''
               AND IFNULL(d.ItemNum, '') <> ''
@@ -402,6 +411,7 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
                 update_time=CURRENT_TIMESTAMP
             """,
             new SugarParameter("@PurOrd", purOrd),
+            new SugarParameter("@TenantId", tenantId),
             new SugarParameter("@BatchId", batchId),
             new SugarParameter("@Now", now));
 
@@ -442,7 +452,7 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
                 """
                 UPDATE PurOrdMaster
                 SET OrdDate=@OrdDate,Supp=@Supp,ReqBy=@ReqBy,WorkOrd=@WorkOrd,Buyer=@Buyer,Department=@Department,`Usage`=@Usage,Curr=@Curr,Remark=@Remark,UpdateUser=@UpdateUser,UpdateTime=@UpdateTime
-                WHERE RecID=@Id
+                WHERE RecID=@Id AND tenant_id=@TenantId
                 """,
                 new SugarParameter("@Id", input.Id),
                 new SugarParameter("@OrdDate", ParseDate(input.OrdDate)),
@@ -455,7 +465,8 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
                 new SugarParameter("@Curr", input.Curr?.Trim()),
                 new SugarParameter("@Remark", input.Remark?.Trim()),
                 new SugarParameter("@UpdateUser", _userManager.Account),
-                new SugarParameter("@UpdateTime", DateTime.Now)
+                new SugarParameter("@UpdateTime", DateTime.Now),
+                new SugarParameter("@TenantId", ResolveTenantOrThrow())
             );
 
             await SaveDetailsAsync(input.Id, input.PurOrd!.Trim(), input.WorkOrd, input.Details);
@@ -479,13 +490,15 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
     /// </summary>
     private async Task SaveDetailsAsync(int masterId, string purOrd, string? workOrd, List<ProcessOutsourceOrderDetailInput> details)
     {
+        var tenantId = ResolveTenantOrThrow();
         var dbDetails = await _db.Ado.SqlQueryAsync<DbDetailRow>(
-            "SELECT RecID AS Id FROM PurOrdDetail WHERE PurOrdRecID=@PurOrdRecID",
-            new SugarParameter("@PurOrdRecID", masterId));
+            "SELECT RecID AS Id FROM PurOrdDetail WHERE PurOrdRecID=@PurOrdRecID AND tenant_id=@TenantId",
+            new SugarParameter("@PurOrdRecID", masterId),
+            new SugarParameter("@TenantId", tenantId));
         var dbById = dbDetails.ToDictionary(x => x.Id);
         var inputIds = new HashSet<int>(details.Where(x => x.Id.HasValue && x.Id.Value > 0).Select(x => x.Id!.Value));
 
-        var maxLine = await _db.Ado.GetIntAsync("SELECT IFNULL(MAX(Line),0) FROM PurOrdDetail WHERE PurOrdRecID=@PurOrdRecID", new SugarParameter("@PurOrdRecID", masterId));
+        var maxLine = await _db.Ado.GetIntAsync("SELECT IFNULL(MAX(Line),0) FROM PurOrdDetail WHERE PurOrdRecID=@PurOrdRecID AND tenant_id=@TenantId", new SugarParameter("@PurOrdRecID", masterId), new SugarParameter("@TenantId", tenantId));
         var lineSeed = maxLine;
 
         for (var i = 0; i < details.Count; i++)
@@ -515,7 +528,7 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
                     """
                     UPDATE PurOrdDetail
                     SET Line=@Line,ItemNum=@ItemNum,Descr=@Descr,Op=@Op,UM=@UM,Location=@Location,QtyOrded=@QtyOrded,QtyReceived=@QtyReceived,ReceiptQty=@ReceiptQty,DueDate=@DueDate,LotSerial=@LotSerial,Potype='PW',PurOrd=@PurOrd,PurOrdRecID=@PurOrdRecID,WorkOrd=@WorkOrd,UpdateUser=@UpdateUser,UpdateTime=@UpdateTime
-                    WHERE RecID=@Id
+                    WHERE RecID=@Id AND tenant_id=@TenantId
                     """,
                     new SugarParameter("@Id", item.Id.Value),
                     new SugarParameter("@Line", line),
@@ -533,7 +546,8 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
                     new SugarParameter("@PurOrdRecID", masterId),
                     new SugarParameter("@WorkOrd", workOrd?.Trim()),
                     new SugarParameter("@UpdateUser", _userManager.Account),
-                    new SugarParameter("@UpdateTime", DateTime.Now)
+                    new SugarParameter("@UpdateTime", DateTime.Now),
+                    new SugarParameter("@TenantId", tenantId)
                 );
             }
             else
@@ -570,7 +584,7 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
 
         foreach (var toDelete in dbDetails.Where(x => !inputIds.Contains(x.Id)))
         {
-            await _db.Ado.ExecuteCommandAsync("DELETE FROM PurOrdDetail WHERE RecID=@Id", new SugarParameter("@Id", toDelete.Id));
+            await _db.Ado.ExecuteCommandAsync("DELETE FROM PurOrdDetail WHERE RecID=@Id AND tenant_id=@TenantId", new SugarParameter("@Id", toDelete.Id), new SugarParameter("@TenantId", tenantId));
         }
     }
 
@@ -580,22 +594,25 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
     {
         if (string.IsNullOrWhiteSpace(purOrd)) throw Oops.Oh("缺少采购单号");
         var ordNo = purOrd.Trim();
+        var tenantId = ResolveTenantOrThrow();
 
         var hasReceipt = await _db.Ado.GetIntAsync(
             "SELECT COUNT(1) FROM PurOrdRctDetail WHERE OrdNbr=@PurOrd AND IFNULL(QtyReceived,0)>0 AND tenant_id=@TenantId",
-            new[] { new SugarParameter("@PurOrd", ordNo), new SugarParameter("@TenantId", ResolveTenantOrThrow()) });
+            new[] { new SugarParameter("@PurOrd", ordNo), new SugarParameter("@TenantId", tenantId) });
         if (hasReceipt > 0) throw Oops.Oh("存在收货数量,不允许删除");
 
         var hasShip = await _db.Ado.GetIntAsync(
             "SELECT COUNT(1) FROM scm_shdzb WHERE po_bill=@PurOrd AND tenant_id=@TenantId",
-            new[] { new SugarParameter("@PurOrd", ordNo), new SugarParameter("@TenantId", ResolveTenantOrThrow()) });
+            new[] { new SugarParameter("@PurOrd", ordNo), new SugarParameter("@TenantId", tenantId) });
         if (hasShip > 0) throw Oops.Oh("存在发货单,不允许删除");
 
         try
         {
             _db.Ado.BeginTran();
-            await _db.Ado.ExecuteCommandAsync("DELETE FROM PurOrdDetail WHERE PurOrd=@PurOrd", new SugarParameter("@PurOrd", ordNo));
-            await _db.Ado.ExecuteCommandAsync("DELETE FROM PurOrdMaster WHERE RecID=@Id AND PurOrd=@PurOrd", new SugarParameter("@Id", id), new SugarParameter("@PurOrd", ordNo));
+            await _db.Ado.ExecuteCommandAsync("DELETE FROM PurOrdDetail WHERE PurOrd=@PurOrd AND tenant_id=@TenantId",
+                new SugarParameter("@PurOrd", ordNo), new SugarParameter("@TenantId", tenantId));
+            await _db.Ado.ExecuteCommandAsync("DELETE FROM PurOrdMaster WHERE RecID=@Id AND PurOrd=@PurOrd AND tenant_id=@TenantId",
+                new SugarParameter("@Id", id), new SugarParameter("@PurOrd", ordNo), new SugarParameter("@TenantId", tenantId));
             _db.Ado.CommitTran();
         }
         catch
@@ -684,10 +701,12 @@ public class ProcessOutsourceOrderService : IDynamicApiController, ITransient
             SELECT DISTINCT CAST(Op AS CHAR(50)) AS Value, CONCAT(TRIM(CAST(Op AS CHAR(50))),' ',TRIM(IFNULL(Descr,''))) AS Label
             FROM RoutingOpDetail
             WHERE UDeci5!=0
-              AND RoutingCode IN (SELECT ItemNum FROM PurOrdDetail WHERE PurOrdRecID=@PurOrdRecID)
+              AND tenant_id=@TenantId
+              AND RoutingCode IN (SELECT ItemNum FROM PurOrdDetail WHERE PurOrdRecID=@PurOrdRecID AND tenant_id=@TenantId)
             ORDER BY Value
             """,
-            new SugarParameter("@PurOrdRecID", purOrdRecId));
+            new SugarParameter("@PurOrdRecID", purOrdRecId),
+            new SugarParameter("@TenantId", ResolveTenantOrThrow()));
         return new { list };
     }
 

+ 8 - 6
server/Plugins/Admin.NET.Plugin.AiDOP/Supply/ProcurementPipelineService.cs

@@ -179,11 +179,12 @@ public class ProcurementPipelineService : IDynamicApiController, ITransient
                         """
                         UPDATE srm_pr_main
                         SET IsDeleted = 1, update_by_name = @User, update_time = @Now
-                        WHERE voucher = @Voucher
+                        WHERE voucher = @Voucher AND tenant_id = @TenantId
                         """,
                         new SugarParameter("@User", account),
                         new SugarParameter("@Now", DateTime.Now),
-                        new SugarParameter("@Voucher", v));
+                        new SugarParameter("@Voucher", v),
+                        new SugarParameter("@TenantId", tenantId));
                 }
                 result.PrDeletedCount = deleteVouchers.Count;
             }
@@ -201,7 +202,7 @@ public class ProcurementPipelineService : IDynamicApiController, ITransient
                 result.PoTransferredPrCount = transfer.TransferredPrCount;
                 result.PoOccupyRehangedCount = transfer.PoOccupyRehangedCount;
                 result.CreatedPoNumbers = transfer.CreatedOrders;
-                await PersistPrStateUpdatesAsync(transfer.TransferredPrIds, 4, account);
+                await PersistPrStateUpdatesAsync(transfer.TransferredPrIds, 4, account, tenantId);
             }
 
             await _db.Ado.CommitTranAsync();
@@ -359,7 +360,7 @@ public class ProcurementPipelineService : IDynamicApiController, ITransient
         }
     }
 
-    private async Task PersistPrStateUpdatesAsync(IReadOnlyList<long> prIds, int state, string account)
+    private async Task PersistPrStateUpdatesAsync(IReadOnlyList<long> prIds, int state, string account, long tenantId)
     {
         if (prIds.Count == 0) return;
         foreach (var id in prIds.Distinct())
@@ -368,12 +369,13 @@ public class ProcurementPipelineService : IDynamicApiController, ITransient
                 """
                 UPDATE srm_pr_main
                 SET state = @State, update_by_name = @User, update_time = @Now
-                WHERE Id = @Id
+                WHERE Id = @Id AND tenant_id = @TenantId
                 """,
                 new SugarParameter("@State", state),
                 new SugarParameter("@User", account),
                 new SugarParameter("@Now", DateTime.Now),
-                new SugarParameter("@Id", id));
+                new SugarParameter("@Id", id),
+                new SugarParameter("@TenantId", tenantId));
         }
     }
 

+ 13 - 9
server/Plugins/Admin.NET.Plugin.AiDOP/Supply/PurchaseOrderTransferService.cs

@@ -85,8 +85,9 @@ public class PurchaseOrderTransferService : ITransient
 
             await InsertPurchaseOrderMasterAsync(purOrd, poType, reqBy, usage, buyer, supplierCode, now, account, group.Key.TenantId);
             var masterId = await _db.Ado.GetIntAsync(
-                "SELECT IFNULL(MAX(RecID),0) FROM PurOrdMaster WHERE PurOrd=@PurOrd",
-                new SugarParameter("@PurOrd", purOrd));
+                "SELECT IFNULL(MAX(RecID),0) FROM PurOrdMaster WHERE PurOrd=@PurOrd AND tenant_id=@TenantId",
+                new SugarParameter("@PurOrd", purOrd),
+                new SugarParameter("@TenantId", group.Key.TenantId));
             if (masterId <= 0) throw Oops.Oh("采购订单主表生成失败。");
 
             for (var lineIndex = 0; lineIndex < rows.Count; lineIndex++)
@@ -229,11 +230,12 @@ public class PurchaseOrderTransferService : ITransient
                 IFNULL(im.Rev, '') AS Rev,
                 IFNULL(im.Drawing, '') AS Drawing
             FROM ic_item ic
-            LEFT JOIN ItemMaster im ON ic.number = im.ItemNum
+            LEFT JOIN ItemMaster im ON ic.number = im.ItemNum AND im.tenant_id = @TenantId
             WHERE ic.Id = @IcitemId
             LIMIT 1
             """,
-            new SugarParameter("@IcitemId", pr.IcitemId))).FirstOrDefault();
+            new SugarParameter("@IcitemId", pr.IcitemId),
+            new SugarParameter("@TenantId", pr.TenantId))).FirstOrDefault();
 
         await _db.Ado.ExecuteCommandAsync(
             """
@@ -282,9 +284,10 @@ public class PurchaseOrderTransferService : ITransient
             new SugarParameter("@TenantId", pr.TenantId <= 0 ? null : pr.TenantId));
 
         var detailRecId = await _db.Ado.GetIntAsync(
-            "SELECT IFNULL(MAX(RecID),0) FROM PurOrdDetail WHERE PurOrd=@PurOrd AND Line=@Line",
+            "SELECT IFNULL(MAX(RecID),0) FROM PurOrdDetail WHERE PurOrd=@PurOrd AND Line=@Line AND tenant_id=@TenantId",
             new SugarParameter("@PurOrd", purOrd),
-            new SugarParameter("@Line", line));
+            new SugarParameter("@Line", line),
+            new SugarParameter("@TenantId", pr.TenantId));
 
         return (detailRecId, item?.ItemNum ?? pr.IcitemName ?? string.Empty);
     }
@@ -303,11 +306,12 @@ public class PurchaseOrderTransferService : ITransient
                 IFNULL(im.ItemNum, psm.ComponentItem) AS ItemNum,
                 IFNULL(im.Location, '') AS Location
             FROM ProductStructureMaster psm
-            LEFT JOIN ItemMaster im ON psm.ComponentItem = im.ItemNum
-            WHERE psm.ParentItem = @ParentItem
+            LEFT JOIN ItemMaster im ON psm.ComponentItem = im.ItemNum AND im.tenant_id = @TenantId
+            WHERE psm.ParentItem = @ParentItem AND psm.tenant_id = @TenantId
             ORDER BY psm.ComponentItem
             """,
-            new SugarParameter("@ParentItem", parentItem));
+            new SugarParameter("@ParentItem", parentItem),
+            new SugarParameter("@TenantId", tenantId));
 
         var batchNo = 1;
         foreach (var comp in components)

+ 3 - 2
server/Plugins/Admin.NET.Plugin.AiDOP/Supply/PurchaseRequestFromShortageService.cs

@@ -151,12 +151,13 @@ public class PurchaseRequestFromShortageService : ITransient
                         UPDATE srm_pr_main
                         SET pr_rqty = @Rqty, pr_aqty = @Rqty, pr_sqty = @Rqty,
                             update_by_name = @User, update_time = @Now
-                        WHERE voucher = @Voucher
+                        WHERE voucher = @Voucher AND tenant_id = @TenantId
                         """,
                         new SugarParameter("@Rqty", newPr.PrRqty),
                         new SugarParameter("@User", account),
                         new SugarParameter("@Now", now),
-                        new SugarParameter("@Voucher", existing.Voucher));
+                        new SugarParameter("@Voucher", existing.Voucher),
+                        new SugarParameter("@TenantId", tenantId));
                 }
             }
             else

+ 4 - 3
server/Plugins/Admin.NET.Plugin.AiDOP/Universal/UniversalWorkOrderService.cs

@@ -39,13 +39,14 @@ public class UniversalWorkOrderService : IDynamicApiController, ITransient
             @"EXISTS (
                 SELECT 1
                 FROM WorkOrdRouting r
-                INNER JOIN RoutingOpDetail d ON r.Op = d.Op AND r.ItemNum = d.RoutingCode
+                INNER JOIN RoutingOpDetail d ON r.Op = d.Op AND r.ItemNum = d.RoutingCode AND d.tenant_id = @TenantId
                 WHERE r.WorkOrd = a.WorkOrd
+                  AND r.tenant_id = @TenantId
                   AND r.ProcessOut = 1
                   AND IFNULL(TRIM(d.SupplierCode),'') <> ''
                   AND NOT EXISTS (
                       SELECT 1 FROM PurOrdMaster p
-                      WHERE p.WorkOrd = a.WorkOrd AND p.Supp = d.SupplierCode AND p.Potype = 'PW'
+                      WHERE p.WorkOrd = a.WorkOrd AND p.tenant_id = @TenantId AND p.Supp = d.SupplierCode AND p.Potype = 'PW'
                   )
             )"
         };
@@ -58,7 +59,7 @@ public class UniversalWorkOrderService : IDynamicApiController, ITransient
 
         var fromSql = $"""
             FROM WorkOrdMaster a
-            LEFT JOIN ItemMaster b ON a.ItemNum=b.ItemNum
+            LEFT JOIN ItemMaster b ON a.ItemNum=b.ItemNum AND b.tenant_id=@TenantId
             WHERE {string.Join(" AND ", where)}
             """;
 

+ 6 - 4
server/Plugins/Admin.NET.Plugin.AiDOP/WorkOrder/WorkOrderMaterialDetailSyncService.cs

@@ -47,12 +47,13 @@ public class WorkOrderMaterialDetailSyncService : ITransient
                         """
                         UPDATE WorkOrdDetail
                         SET QtyRequired = @QtyRequired, UpdateUser = @User, UpdateTime = @Now
-                        WHERE RecID = @RecID
+                        WHERE RecID = @RecID AND tenant_id = @TenantId
                         """,
                         new SugarParameter("@QtyRequired", c.QtyRequired),
                         new SugarParameter("@User", account),
                         new SugarParameter("@Now", now),
-                        new SugarParameter("@RecID", ex.RecID));
+                        new SugarParameter("@RecID", ex.RecID),
+                        new SugarParameter("@TenantId", tenantId));
                 }
                 existingMap.Remove(c.ItemNumber);
             }
@@ -92,8 +93,9 @@ public class WorkOrderMaterialDetailSyncService : ITransient
         foreach (var stale in existingMap.Values)
         {
             await _db.Ado.ExecuteCommandAsync(
-                "DELETE FROM WorkOrdDetail WHERE RecID = @RecID",
-                new SugarParameter("@RecID", stale.RecID));
+                "DELETE FROM WorkOrdDetail WHERE RecID = @RecID AND tenant_id = @TenantId",
+                new SugarParameter("@RecID", stale.RecID),
+                new SugarParameter("@TenantId", tenantId));
         }
 
         return components.Count;

+ 1 - 1
server/Plugins/Admin.NET.Plugin.AiDOP/WorkOrder/WorkOrderPickBillService.cs

@@ -219,7 +219,7 @@ public class WorkOrderPickBillService : ITransient
                 MAX(IFNULL(d.UM, im.Um)) AS Unit,
                 MAX(im.Descr) AS ItemName
             FROM WorkOrdDetail d
-            LEFT JOIN ItemMaster im ON d.ItemNum = im.ItemNum
+            LEFT JOIN ItemMaster im ON d.ItemNum = im.ItemNum AND im.tenant_id = @TenantId
             WHERE d.tenant_id = @TenantId AND d.WorkOrd = @WorkOrd AND IFNULL(d.IsActive, 0) = 1
             GROUP BY d.ItemNum
             HAVING SUM(d.QtyRequired) > 0