ProdScheduleAppService.cs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. using Business.Core.Utilities;
  2. using Business.EntityFrameworkCore.SqlRepositories;
  3. using Business.Model.MES.IC;
  4. using Business.Model.Production;
  5. using Business.MongoModel.Production;
  6. using Business.Quartz;
  7. using Newtonsoft.Json;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Linq;
  11. using System.Text;
  12. using System.Threading.Tasks;
  13. using Volo.Abp.Application.Services;
  14. using Volo.Abp.DependencyInjection;
  15. using Volo.Abp.Domain.Repositories;
  16. using Volo.Abp.TenantManagement;
  17. namespace Business.ResourceExamineManagement
  18. {
  19. /// <summary>
  20. /// 生产排产接口实现类
  21. /// </summary>
  22. public class ProdScheduleAppService : ApplicationService
  23. {
  24. /// <summary>
  25. /// 雪花算法帮助类
  26. /// </summary>
  27. SnowFlake help = new SnowFlake();
  28. /// <summary>
  29. /// 生产工单主表
  30. /// </summary>
  31. private readonly IRepository<mes_morder, long> _mysql_mes_morder;
  32. /// <summary>
  33. /// 工艺路线表
  34. /// </summary>
  35. private readonly ISqlRepository<RoutingOpDetail> _routingOpDetail;
  36. /// <summary>
  37. /// 标准BOM表
  38. /// </summary>
  39. private readonly ISqlRepository<ProductStructureMaster> _productStructureMaster;
  40. /// <summary>
  41. /// 工单工序表
  42. /// </summary>
  43. private readonly ISqlRepository<WorkOrdRouting> _workOrdRouting;
  44. /// <summary>
  45. /// 工单主表
  46. /// </summary>
  47. private readonly ISqlRepository<WorkOrdMaster> _workOrdMaster;
  48. /// <summary>
  49. /// 工单物料明细表
  50. /// </summary>
  51. private readonly ISqlRepository<WorkOrdDetail> _workOrdDetail;
  52. /// <summary>
  53. /// 生产排产
  54. /// </summary>
  55. private readonly ProductionScheduleAppService _productionScheduleAppService;
  56. /// <summary>
  57. /// 构造函数
  58. /// </summary>
  59. /// <param name="productionScheduleAppService"></param>
  60. public ProdScheduleAppService(
  61. ProductionScheduleAppService productionScheduleAppService,
  62. IRepository<mes_morder, long> mysql_mes_morder,
  63. ISqlRepository<RoutingOpDetail> routingOpDetail,
  64. ISqlRepository<ProductStructureMaster> productStructureMaster,
  65. ISqlRepository<WorkOrdRouting> workOrdRouting,
  66. ISqlRepository<WorkOrdMaster> workOrdMaster,
  67. ISqlRepository<WorkOrdDetail> workOrdDetail
  68. )
  69. {
  70. _productionScheduleAppService= productionScheduleAppService;
  71. _mysql_mes_morder= mysql_mes_morder;
  72. _routingOpDetail= routingOpDetail;
  73. _productStructureMaster= productStructureMaster;
  74. _workOrdRouting= workOrdRouting;
  75. _workOrdMaster= workOrdMaster;
  76. _workOrdDetail= workOrdDetail;
  77. }
  78. /// <summary>
  79. /// 生产排产
  80. /// </summary>
  81. /// <param name="workOrds">工单编号</param>
  82. /// <returns></returns>
  83. public async Task<string> ProductionSchedule(List<string> workOrds)
  84. {
  85. if (workOrds.Count() == 0)
  86. {
  87. return "";
  88. }
  89. //获取工单数据
  90. var mes_morders = await _mysql_mes_morder.GetListAsync(p => workOrds.Contains(p.morder_no));
  91. CreateWorkOrdDates(mes_morders);
  92. return JsonConvert.SerializeObject("ok");
  93. }
  94. /// <summary>
  95. /// 同步工单等相关数据
  96. /// </summary>
  97. /// <param name="morders"></param>
  98. public async void CreateWorkOrdDates(List<mes_morder> morders)
  99. {
  100. //获取工艺路线数据:product_code=物料编码
  101. List<RoutingOpDetail> allRoutings = _routingOpDetail.Select(p => morders.Select(m => m.product_code).Contains(p.RoutingCode));
  102. //获取标准BOM数据
  103. List<ProductStructureMaster> productStructures = GetProductStructure(morders.Select(p => p.product_code).Distinct().ToList());
  104. //工单主表
  105. List<WorkOrdMaster> workOrds = new List<WorkOrdMaster>();
  106. WorkOrdMaster workOrd;
  107. //工单工艺路线表
  108. List<WorkOrdRouting> workOrdRoutings = new List<WorkOrdRouting>();
  109. WorkOrdRouting woRouting;
  110. //工单物料表
  111. List<WorkOrdDetail> workOrdDetails = new List<WorkOrdDetail>();
  112. WorkOrdDetail woDetail;
  113. foreach (var item in morders)
  114. {
  115. //添加工单数据
  116. workOrd = new WorkOrdMaster();
  117. workOrd.Domain = "1001";
  118. workOrd.OrdDate = item.moentry_sys_stime;
  119. workOrd.ReleaseDate = Convert.ToDateTime(item.moentry_sys_stime.GetValueOrDefault().ToString("u"));
  120. workOrd.WorkOrd = item.morder_no;
  121. workOrd.ItemNum = item.product_code;//物料编码
  122. workOrd.QtyOrded = item.need_number.GetValueOrDefault();
  123. workOrd.RoutingCode = item.product_code;
  124. workOrd.Period = 1;
  125. workOrd.Priority = item.urgent;
  126. workOrd.Status = "";
  127. workOrd.IsActive = true;
  128. workOrd.IsConfirm = true;
  129. workOrds.Add(workOrd);
  130. //添加工单工艺路线数据
  131. var curRoutings = allRoutings.Where(p => p.RoutingCode == item.product_code).ToList();
  132. foreach (var dtl in curRoutings)
  133. {
  134. woRouting = new WorkOrdRouting();
  135. woRouting.Domain = "1001";
  136. woRouting.Descr = dtl.Descr;
  137. woRouting.MilestoneOp = dtl.MilestoneOp;
  138. woRouting.WorkOrd = item.morder_no;
  139. woRouting.OP = dtl.Op;
  140. woRouting.ParentOp = dtl.ParentOp;
  141. woRouting.RunTime = dtl.RunTime;
  142. woRouting.ItemNum = item.product_code;
  143. woRouting.QtyOrded = item.need_number.GetValueOrDefault();
  144. woRouting.OverlapUnits = dtl.OverlapUnits;
  145. woRouting.Status = "";
  146. woRouting.IsActive = true;
  147. workOrdRoutings.Add(woRouting);
  148. }
  149. //添加工单物料数据
  150. var curStructures = productStructures.Where(p => p.ParentItem == item.product_code).ToList();
  151. foreach (var structure in curStructures)
  152. {
  153. //添加工单的物料信息
  154. woDetail = new WorkOrdDetail();
  155. woDetail.Domain = "1001";
  156. woDetail.WorkOrd = item.morder_no;
  157. woDetail.Op = structure.Op;
  158. woDetail.ItemNum = structure.ComponentItem;
  159. woDetail.QtyRequired = item.need_number.GetValueOrDefault() * structure.Qty;
  160. woDetail.QtyPosted = 0m;
  161. woDetail.QtyReturned = 0m;
  162. woDetail.Status = "";
  163. woDetail.IsActive = true;
  164. workOrdDetails.Add(woDetail);
  165. }
  166. }
  167. _workOrdMaster.Insert(workOrds);
  168. _workOrdRouting.Insert(workOrdRoutings);
  169. _workOrdDetail.Insert(workOrdDetails);
  170. //排产
  171. await _productionScheduleAppService.DoProductShcedule(workOrds);
  172. }
  173. /// <summary>
  174. /// 获取标准Bom数据--TODO:存在循环查询数据库问题,后续调整
  175. /// </summary>
  176. /// <param name="itenNums">产品物料编码</param>
  177. /// <returns></returns>
  178. public List<ProductStructureMaster> GetProductStructure(List<string> itenNums)
  179. {
  180. List<ProductStructureMaster> rtnStructures = new List<ProductStructureMaster>();
  181. //根据itemNum获取bom数据
  182. var productStructures = _productStructureMaster.Select(p => itenNums.Contains(p.ParentItem) && p.Domain == "1001" && p.IsActive);
  183. //添加非虚拟件
  184. rtnStructures.AddRange(productStructures.Where(p => p.StructureType.ToUpper() != "X").ToList());
  185. foreach (var item in itenNums)
  186. {
  187. //获取当前产品的虚拟件
  188. var curPhantoms = productStructures.Where(p => p.ParentItem == item && p.StructureType.ToUpper() == "X").ToList();
  189. if (curPhantoms.Count() == 0)
  190. {
  191. continue;
  192. }
  193. //递归获取所有虚拟件对应的子物料
  194. RecursionProductStructure(item, curPhantoms, rtnStructures);
  195. }
  196. return rtnStructures;
  197. }
  198. /// <summary>
  199. /// 递归获取虚拟件的子物料
  200. /// </summary>
  201. /// <param name="parentItem">产品的物料编码</param>
  202. /// <param name="structures">当前产品的虚拟件</param>
  203. /// <param name="rtnStructures"></param>
  204. public void RecursionProductStructure(string parentItem, List<ProductStructureMaster> structures, List<ProductStructureMaster> rtnStructures)
  205. {
  206. //获取虚拟件的子物料
  207. var chdStructures = _productStructureMaster.Select(p => structures.Select(m => m.ComponentItem).Contains(p.ParentItem) && p.Domain == "1001" && p.IsActive);
  208. //非虚拟件
  209. var notPhantoms = chdStructures.Where(p => p.StructureType.ToUpper() != "X").ToList();
  210. //存在非虚拟件
  211. if (notPhantoms.Count() > 0)
  212. {
  213. notPhantoms.ForEach(p =>
  214. {
  215. p.ParentItem = parentItem;
  216. });
  217. rtnStructures.AddRange(notPhantoms);
  218. }
  219. //虚拟件
  220. var phantoms = chdStructures.Where(p => p.StructureType.ToUpper() == "X").ToList();
  221. if (phantoms.Count() > 0)
  222. {
  223. //递归
  224. RecursionProductStructure(parentItem, phantoms, rtnStructures);
  225. }
  226. }
  227. }
  228. }