OrderResourceCheckService.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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 lines = await _calculator.BuildLinesAsync(order, entry, warnings, bangId);
  29. var morderId = await ResolveMorderIdAsync(workOrd, entry.TenantId);
  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. var lines = await _calculator.BuildLinesAsync(order, entry, warnings, bangId);
  40. var activeLines = lines.Where(x => x.IsUse == 1).ToList();
  41. var needTime = entry.SysCapacityDate ?? entry.PlanDate ?? DateTime.Today;
  42. var hasShortage = activeLines.Any(x => x.LackQty > 0);
  43. // 对根行(Level=1)执行产能计算,更新 KittingTime
  44. var rootLine = lines.FirstOrDefault(x => x.Level == 1 && x.IsUse == 1 && x.LackQty > 0);
  45. if (rootLine != null)
  46. {
  47. var planDate = entry.PlanDate ?? DateTime.Today;
  48. rootLine.KittingTime = await _capacityCalc.CalculateAsync(
  49. rootLine.ItemNumber, rootLine.LackQty, needTime, planDate, entry.TenantId);
  50. }
  51. var kittingTime = activeLines
  52. .Where(x => x.LackQty > 0)
  53. .Select(x => x.KittingTime)
  54. .DefaultIfEmpty(needTime)
  55. .Max();
  56. var result = new OrderResourceCheckResult
  57. {
  58. LineCount = activeLines.Count,
  59. HasShortage = hasShortage,
  60. KittingTime = kittingTime,
  61. };
  62. return (result, lines);
  63. }
  64. /// <summary>将已有计算结果写入 b_examine_result / b_bom_child_examine(需先创建工单)。</summary>
  65. public async Task<OrderResourceCheckResult> WriteResultAsync(
  66. OrderWorkOrderGenerationService.OrderHeader order,
  67. OrderWorkOrderGenerationService.OrderEntryLine entry,
  68. string workOrd,
  69. List<ResourceCheckBomLine> lines,
  70. string account)
  71. {
  72. var morderId = await ResolveMorderIdAsync(workOrd, entry.TenantId);
  73. return await _writer.WriteAsync(order, entry, workOrd, morderId, lines, account, DateTime.Now);
  74. }
  75. private async Task<long?> ResolveMorderIdAsync(string workOrd, long tenantId)
  76. {
  77. var id = await _db.Ado.GetLongAsync(
  78. """
  79. SELECT Id FROM mes_morder
  80. WHERE morder_no = @WorkOrd AND tenant_id = @TenantId AND IsDeleted = 0
  81. ORDER BY Id DESC LIMIT 1
  82. """,
  83. new List<SugarParameter>
  84. {
  85. new("@WorkOrd", workOrd),
  86. new("@TenantId", tenantId)
  87. });
  88. return id > 0 ? id : null;
  89. }
  90. }