WorkOrderRoutingSyncService.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. namespace Admin.NET.Plugin.AiDOP.WorkOrder;
  2. /// <summary>从标准工艺路线同步工单工序明细(WorkOrdRouting)。</summary>
  3. public class WorkOrderRoutingSyncService : ITransient
  4. {
  5. private readonly ISqlSugarClient _db;
  6. public WorkOrderRoutingSyncService(ISqlSugarClient db)
  7. {
  8. _db = db;
  9. }
  10. /// <summary>为租户内尚无工序明细的待排产工单补齐标准工艺路线。</summary>
  11. public async Task<int> EnsureAllPendingAsync(long tenantId, string account)
  12. {
  13. var workOrders = await _db.Ado.SqlQueryAsync<string>(
  14. """
  15. SELECT w.WorkOrd
  16. FROM WorkOrdMaster w
  17. WHERE w.tenant_id = @TenantId
  18. AND LOWER(IFNULL(w.Status, '')) IN ('p', 'r')
  19. AND IFNULL(w.WorkOrd, '') <> ''
  20. AND NOT EXISTS (
  21. SELECT 1
  22. FROM WorkOrdRouting wr
  23. WHERE wr.tenant_id = w.tenant_id
  24. AND wr.WorkOrd = w.WorkOrd
  25. AND IFNULL(wr.IsActive, 0) = 1
  26. )
  27. ORDER BY w.RecID
  28. """,
  29. new SugarParameter("@TenantId", tenantId));
  30. var affected = 0;
  31. foreach (var workOrd in workOrders.Where(x => !string.IsNullOrWhiteSpace(x)).Distinct(StringComparer.OrdinalIgnoreCase))
  32. affected += await EnsureFromRoutingAsync(tenantId, workOrd, account);
  33. return affected;
  34. }
  35. /// <summary>
  36. /// 确保工单有工艺路线数据;若已有活跃行则跳过。
  37. /// 返回插入行数。
  38. /// </summary>
  39. public async Task<int> EnsureFromRoutingAsync(long tenantId, string workOrd, string account)
  40. {
  41. var existing = await _db.Ado.GetIntAsync(
  42. """
  43. SELECT COUNT(*) FROM WorkOrdRouting
  44. WHERE tenant_id = @TenantId AND WorkOrd = @WorkOrd AND IFNULL(IsActive, 0) = 1
  45. """,
  46. new SugarParameter("@TenantId", tenantId),
  47. new SugarParameter("@WorkOrd", workOrd));
  48. if (existing > 0)
  49. return 0;
  50. var createUser = account.Length > 24 ? account[..24] : account;
  51. // 映射口径(G2):
  52. // StdRunTime = 1/Rate(小时/件);RunCrew ← ProdLineDetail.RunCrew;
  53. // Line/ProdLine ← TRIM(Line);MachBdnRate 恢复成本语义(不再承载 Rate)
  54. var affected = await _db.Ado.ExecuteCommandAsync(
  55. """
  56. INSERT INTO WorkOrdRouting (
  57. `Descr`, `Domain`, `ChargeCode`, `Machine`, `RunCrew`, `MilestoneOp`, `OP`, `StdOp`, `ItemNum`, `WorkCtr`,
  58. `Ufld1`, `Ufld3`, `Setup`, `MachinesperOp`, `Labor`, `RunTime`, `MachBdnRate`, `WorkCode`, `StdSetupTime`, `Engineer`,
  59. `WorkOrd`, `WorkOrdMasterRecID`, `ERPfld1`, `QtyOrded`, `ProcessOut`, `ProcessOutDay`, `ProcessOutSupp`,
  60. `IsActive`, `Status`, `ProdLine`, `Line`, `StdRunTime`,
  61. `CreateTime`, `CreateUser`, `tenant_id`, `CommentIndex`, `WaitTime`, `QtyComplete`, `ParentOp`
  62. )
  63. SELECT
  64. a.`Descr`,
  65. LEFT(TRIM(COALESCE(NULLIF(TRIM(IFNULL(w.`Domain`, '')), ''), NULLIF(TRIM(IFNULL(a.`Domain`, '')), ''), ' ')), 8),
  66. '',
  67. b.`InternalEquipmentCode`,
  68. CAST(IFNULL(NULLIF(TRIM(IFNULL(b.`RunCrew`, '')), ''), '0') AS DECIMAL(18, 4)),
  69. CAST(IFNULL(a.`MilestoneOp`, 0) AS UNSIGNED),
  70. IFNULL(a.`Op`, 0),
  71. a.`StdOp`,
  72. a.`RoutingCode`,
  73. LEFT(IFNULL(b.`Site`, ''), 8),
  74. '',
  75. '',
  76. IFNULL(a.`UDeci1`, 0),
  77. IFNULL(a.`UDeci2`, 0),
  78. IFNULL(a.`UDeci3`, 0),
  79. IFNULL(a.`UDeci3`, 0) / 3600.0,
  80. 0,
  81. b.`OpType`,
  82. IFNULL(b.`SetupTime`, 0),
  83. b.`SkillNo`,
  84. w.`WorkOrd`,
  85. w.`RecID`,
  86. w.`ERPfld1`,
  87. IFNULL(w.`QtyOrded`, 0),
  88. CAST(IFNULL(a.`UDeci5`, 0) AS SIGNED),
  89. IFNULL(a.`ProcessOutDay`, 0),
  90. a.`ProcessOutSupp`,
  91. b'1',
  92. 'r',
  93. LEFT(TRIM(IFNULL(b.`Line`, '')), 8),
  94. LEFT(TRIM(IFNULL(b.`Line`, '')), 8),
  95. CASE WHEN IFNULL(b.`Rate`, 0) > 0 THEN 1.0 / b.`Rate` ELSE NULL END,
  96. NOW(3),
  97. @CreateUser,
  98. w.`tenant_id`,
  99. CAST(IFNULL(a.`MilestoneOp`, 0) AS UNSIGNED),
  100. 0, 0, 0
  101. FROM WorkOrdMaster w
  102. LEFT JOIN RoutingOpDetail a ON w.`ItemNum` = a.`RoutingCode`
  103. LEFT JOIN ProdLineDetail b ON a.`RoutingCode` = b.`Part` AND a.`Op` = b.`Op`
  104. WHERE w.`WorkOrd` = @WorkOrd
  105. AND w.`tenant_id` = @TenantId
  106. AND IFNULL(a.`IsActive`, 0) = 1
  107. AND a.`MilestoneOp` IS NOT NULL
  108. """,
  109. new SugarParameter("@WorkOrd", workOrd),
  110. new SugarParameter("@TenantId", tenantId),
  111. new SugarParameter("@CreateUser", createUser));
  112. return affected;
  113. }
  114. }