OrderResourceCheckService.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. namespace Admin.NET.Plugin.AiDOP.Order;
  2. /// <summary>订单评审资源检查编排。</summary>
  3. public class OrderResourceCheckService : ITransient
  4. {
  5. private readonly ISqlSugarClient _db;
  6. private readonly MaterialRequirementCalculator _calculator;
  7. private readonly ResourceCheckResultWriter _writer;
  8. private readonly CapacityDateCalculator _capacityCalc;
  9. public OrderResourceCheckService(
  10. ISqlSugarClient db,
  11. MaterialRequirementCalculator calculator,
  12. ResourceCheckResultWriter writer,
  13. CapacityDateCalculator capacityCalc)
  14. {
  15. _db = db;
  16. _calculator = calculator;
  17. _writer = writer;
  18. _capacityCalc = capacityCalc;
  19. }
  20. public async Task<OrderResourceCheckResult> RunForEntryAsync(
  21. OrderWorkOrderGenerationService.OrderHeader order,
  22. OrderWorkOrderGenerationService.OrderEntryLine entry,
  23. string workOrd,
  24. string account,
  25. List<string> warnings,
  26. long bangId = 0)
  27. {
  28. var morderId = await ResolveMorderIdAsync(workOrd, entry.TenantId);
  29. var lines = await _calculator.BuildLinesAsync(order, entry, warnings, bangId, workOrd, morderId ?? 0);
  30. return await _writer.WriteAsync(order, entry, workOrd, morderId, lines, account, DateTime.Now);
  31. }
  32. /// <summary>仅运行资源检查计算,不写库、不依赖工单。返回计算结果与 BOM 展开明细。</summary>
  33. public async Task<(OrderResourceCheckResult Result, List<ResourceCheckBomLine> Lines)> CheckOnlyAsync(
  34. OrderWorkOrderGenerationService.OrderHeader order,
  35. OrderWorkOrderGenerationService.OrderEntryLine entry,
  36. List<string> warnings,
  37. long bangId = 0)
  38. {
  39. // 工单尚未生成,占用只能靠 orderentry_id 归属
  40. var lines = await _calculator.BuildLinesAsync(order, entry, warnings, bangId, workOrd: null, morderId: 0);
  41. var activeLines = lines.Where(x => x.IsUse == 1).ToList();
  42. var needTime = entry.SysCapacityDate ?? entry.PlanDate ?? DateTime.Today;
  43. var hasShortage = activeLines.Any(x => x.LackQty > 0);
  44. // 对根行(Level=1)执行产能计算,更新 KittingTime
  45. var rootLine = lines.FirstOrDefault(x => x.Level == 1 && x.IsUse == 1 && x.LackQty > 0);
  46. if (rootLine != null)
  47. {
  48. var planDate = entry.PlanDate ?? DateTime.Today;
  49. rootLine.KittingTime = await _capacityCalc.CalculateAsync(
  50. rootLine.ItemNumber, rootLine.LackQty, needTime, planDate, entry.TenantId);
  51. }
  52. var kittingTime = activeLines
  53. .Where(x => x.LackQty > 0)
  54. .Select(x => x.KittingTime)
  55. .DefaultIfEmpty(needTime)
  56. .Max();
  57. var result = new OrderResourceCheckResult
  58. {
  59. LineCount = activeLines.Count,
  60. HasShortage = hasShortage,
  61. KittingTime = kittingTime,
  62. };
  63. return (result, lines);
  64. }
  65. /// <summary>将已有计算结果写入 b_examine_result / b_bom_child_examine(需先创建工单)。</summary>
  66. public async Task<OrderResourceCheckResult> WriteResultAsync(
  67. OrderWorkOrderGenerationService.OrderHeader order,
  68. OrderWorkOrderGenerationService.OrderEntryLine entry,
  69. string workOrd,
  70. List<ResourceCheckBomLine> lines,
  71. string account)
  72. {
  73. var morderId = await ResolveMorderIdAsync(workOrd, entry.TenantId);
  74. return await _writer.WriteAsync(order, entry, workOrd, morderId, lines, account, DateTime.Now);
  75. }
  76. private async Task<long?> ResolveMorderIdAsync(string workOrd, long tenantId)
  77. {
  78. var id = await _db.Ado.GetLongAsync(
  79. """
  80. SELECT Id FROM mes_morder
  81. WHERE morder_no = @WorkOrd AND tenant_id = @TenantId AND IsDeleted = 0
  82. ORDER BY Id DESC LIMIT 1
  83. """,
  84. new List<SugarParameter>
  85. {
  86. new("@WorkOrd", workOrd),
  87. new("@TenantId", tenantId)
  88. });
  89. return id > 0 ? id : null;
  90. }
  91. }