ProdScheduleAppService.cs 10 KB

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