ProductExamineAppService.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. using Business.Domain;
  2. using Business.Dto;
  3. using Business.ResourceExamineManagement.Dto;
  4. using MongoDB.Driver.Linq;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using Volo.Abp.Application.Services;
  9. namespace Business.ResourceExamineManagement
  10. {
  11. /// <summary>
  12. /// 产能检查
  13. /// </summary>
  14. public class ProductExamineAppService: ApplicationService
  15. {
  16. #region 服务
  17. /// <summary>
  18. /// 生产线明细表
  19. /// </summary>
  20. public List<ProdLineDetail> prodLines = new List<ProdLineDetail>();
  21. /// <summary>
  22. /// 标准工艺路径表
  23. /// </summary>
  24. public List<RoutingOpDetail> routingOps = new List<RoutingOpDetail>();
  25. /// <summary>
  26. /// 排产记录表
  27. /// </summary>
  28. public List<PeriodSequenceDet> periodSequences = new List<PeriodSequenceDet>();
  29. /// <summary>
  30. /// 工作日历
  31. /// </summary>
  32. public List<ShopCalendarWorkCtr> calendarWorks = new List<ShopCalendarWorkCtr>();
  33. /// <summary>
  34. /// 休息时间段
  35. /// </summary>
  36. public List<QualityLineWorkDetail> qualityLineWorks = new List<QualityLineWorkDetail>();
  37. /// <summary>
  38. /// 节假日
  39. /// </summary>
  40. public List<HolidayMaster> holidays = new List<HolidayMaster>();
  41. #endregion
  42. /// <summary>
  43. /// 构造函数
  44. /// </summary>
  45. public ProductExamineAppService()
  46. {
  47. }
  48. /// <summary>
  49. /// 根据标准工艺获取生产时长(天)
  50. /// </summary>
  51. /// <param name="param"></param>
  52. /// <returns></returns>
  53. public int ProductTime(ProdExamineParamDto param)
  54. {
  55. var allOps = routingOps.Where(s => s.RoutingCode == param.ItemNum && s.Domain == param.Domain).ToList();
  56. if (allOps.Any())
  57. {
  58. decimal maxRt = allOps.Max(s => s.RunTime);
  59. decimal sumRt = allOps.Sum(s => s.RunTime);
  60. decimal totalTime = (param.QtyOrd - 1) * maxRt + sumRt;//总计生产小时
  61. return (int)(Math.Ceiling(totalTime / 8));
  62. }
  63. return 1;
  64. }
  65. /// <summary>
  66. /// 产能计算-批量
  67. /// </summary>
  68. /// <param name="param">产能检查入参</param>
  69. /// <returns>生产时长(天)</returns>
  70. public DateTime ProductiveExamine(ProdExamineParamDto param)
  71. {
  72. //生产结束时间
  73. DateTime planEnd = param.PlanStart.Date;
  74. if (param.QtyOrd <= 0)
  75. {
  76. return planEnd;
  77. }
  78. //获取当前产品的工艺路线:主产线,最后一道工序
  79. var curRoutingOps = routingOps.Where(p => p.RoutingCode == param.ItemNum && p.ParentOp == 0).OrderByDescending(p => p.Op).ToList();
  80. if (curRoutingOps.Count == 0)
  81. {
  82. return planEnd;
  83. }
  84. var lastOp = curRoutingOps.First();
  85. //获取产线
  86. var curProdLine = prodLines.FirstOrDefault(p => p.Part == param.ItemNum && p.Op == lastOp.Op);
  87. if (curProdLine == null)
  88. {
  89. return planEnd;
  90. }
  91. //获取产线工作日历
  92. var curCalendars = calendarWorks.Where(p => p.ProdLine == curProdLine.Line).ToList();
  93. if (curCalendars.Count == 0 || curCalendars.Count != 7)
  94. {
  95. return planEnd;
  96. }
  97. //获取产线休息时间
  98. var curqualityLines = qualityLineWorks.Where(p=>p.ProdLine == curProdLine.Line).ToList();
  99. //生产数量
  100. decimal sumAmount = 0m;
  101. do
  102. {
  103. //获取工作日
  104. planEnd = GetNextWorkDay(planEnd, curCalendars);
  105. //计算工作日的产能
  106. sumAmount += CalcCapacity(planEnd, curProdLine, curCalendars, curqualityLines);
  107. planEnd = planEnd.AddDays(1);
  108. } while (sumAmount < param.QtyOrd);
  109. return planEnd.AddDays(-1);
  110. }
  111. /// <summary>
  112. /// 获取工作日
  113. /// </summary>
  114. /// <param name="weekDay">当前周几</param>
  115. /// <param name="startTime">开始时间:年-月-日</param>
  116. /// <param name="curCalendars">当前产线的工作日历</param>
  117. /// <returns></returns>
  118. public DateTime GetNextWorkDay(DateTime startTime, List<ShopCalendarWorkCtr> curCalendars)
  119. {
  120. DateTime rtnData = startTime;
  121. int weekDay = (int)startTime.DayOfWeek;
  122. var calendar = curCalendars.FirstOrDefault(p => p.WeekDay == weekDay);
  123. //判断当天是否是工作日
  124. if (weekDay == 0 || weekDay == 6)//周六,周日
  125. {
  126. if (!holidays.Exists(p => p.Dated.GetValueOrDefault().Date == startTime && p.Ufld1 == "调班"))//今天是周末
  127. {
  128. //递归继续找下一个工作日
  129. rtnData = GetNextWorkDay(startTime.AddDays(1), curCalendars);
  130. return rtnData;
  131. }
  132. return rtnData;
  133. }
  134. //今天不是周六周日,需要判断是不是节假日
  135. if (holidays.Exists(p => p.Dated.GetValueOrDefault().Date == startTime && p.Ufld1 == "休假"))//是节假日
  136. {
  137. //递归继续找下一个工作日
  138. rtnData = GetNextWorkDay(startTime.AddDays(1), curCalendars);
  139. return rtnData;
  140. }
  141. return rtnData;
  142. }
  143. /// <summary>
  144. /// 计算当天的产能
  145. /// </summary>
  146. /// <param name="startTime"></param>
  147. /// <param name="prodLine"></param>
  148. /// <param name="curCalendars"></param>
  149. /// <param name="curQualityLines"></param>
  150. /// <returns></returns>
  151. public decimal CalcCapacity(DateTime startTime,ProdLineDetail prodLine, List<ShopCalendarWorkCtr> curCalendars, List<QualityLineWorkDetail> curQualityLines)
  152. {
  153. decimal sumQty = 0m;
  154. //获取休息时长(分钟)
  155. decimal sumResrt = curQualityLines.Sum(p => p.RestTime);
  156. //获取当天的工作时长(分钟)
  157. decimal workTime = curCalendars.First(p => p.WeekDay == (int)startTime.DayOfWeek).ShiftsHours1 * 60;
  158. //计算产能
  159. sumQty = Math.Ceiling((workTime - sumResrt) / 60 * prodLine.Rate);
  160. return sumQty;
  161. }
  162. /// <summary>
  163. /// 计算订单行的建议交期(产能/物料)
  164. /// </summary>
  165. /// <param name="sentrys"></param>
  166. /// <param name="kittingTimes"></param>
  167. /// <returns></returns>
  168. public void CalcSuggestTime(List<crm_seorderentry> sentrys, List<KittingTimeDto> kittingTimes, List<mo_ic_item> icitemlist)
  169. {
  170. ProdExamineParamDto param;
  171. foreach (var item in sentrys)
  172. {
  173. var dto = kittingTimes.FirstOrDefault(p=>p.sentry_id == item.Id);
  174. if (dto == null)
  175. {
  176. continue;
  177. }
  178. var icitem = icitemlist.Find(s => s.number == item.item_number);
  179. if (dto.LackQty == 0)//当前订单行库存足够
  180. {
  181. if (icitem != null)
  182. {
  183. //加上自检、入库、发运提前期
  184. dto.kitting_time = dto.kitting_time.AddDays((double)(icitem.self_inspection_date.GetValueOrDefault() + icitem.Warehousing_date.GetValueOrDefault() + icitem.Shipping_date.GetValueOrDefault()+icitem.RoutingDesignTime.GetValueOrDefault()));
  185. dto.kitting_time= dto.kitting_time<=item.plan_date.GetValueOrDefault()? item.plan_date.GetValueOrDefault(): dto.kitting_time;
  186. }
  187. item.sys_material_date = dto.kitting_time;
  188. item.sys_capacity_date = dto.kitting_time;
  189. continue;
  190. }
  191. //计算系统建议交期(物料)
  192. param = new ProdExamineParamDto
  193. {
  194. ItemNum = item.item_number,
  195. QtyOrd = dto.LackQty,
  196. PlanStart = dto.kitting_time.Date.AddDays(1)
  197. };
  198. var time = ProductiveExamine(param);
  199. item.sys_material_date = time;
  200. item.sys_capacity_date = time;
  201. if (icitem != null)
  202. {
  203. //加上自检、入库、发运提前期
  204. item.sys_material_date = time.AddDays((double)(icitem.self_inspection_date.GetValueOrDefault() + icitem.Warehousing_date.GetValueOrDefault() + icitem.Shipping_date.GetValueOrDefault() + icitem.RoutingDesignTime.GetValueOrDefault()));
  205. }
  206. //param.PlanStart = dto.kitting_time.Date.AddDays(3);
  207. //计算系统交期(产能)
  208. //获取主线最后一道工序
  209. List<PeriodSequenceDet> schedules = new List<PeriodSequenceDet>();
  210. var routings = routingOps.Where(p => p.RoutingCode == item.item_number && p.ParentOp == 0).OrderBy(p=>p.Op).ToList();
  211. if (routings.Count != 0)
  212. {
  213. //获取产线
  214. var prodLine = prodLines.FirstOrDefault(p => p.Part == item.item_number && p.Op == routings.Last().Op);
  215. if (prodLine != null)
  216. {
  217. //获取产线空闲开始时间
  218. schedules = periodSequences.Where(p => p.ItemNum == item.item_number && p.Op == prodLine.Op && p.Line == prodLine.Line).OrderByDescending(p => p.PlanDate).ToList();
  219. }
  220. }
  221. if (schedules.Any())
  222. {
  223. //产线空闲开始时间
  224. var lastTime = schedules.First().PlanDate.GetValueOrDefault().Date;
  225. if (lastTime >= param.PlanStart)//如果产线空闲时间大于或者等于系统建议交期(物料)的开工时间
  226. {
  227. param.PlanStart = lastTime;
  228. item.sys_capacity_date = ProductiveExamine(param);
  229. }
  230. else {
  231. item.sys_capacity_date = ProductiveExamine(param);
  232. }
  233. }
  234. else {
  235. item.sys_capacity_date = ProductiveExamine(param);
  236. }
  237. if (icitem != null)
  238. {
  239. //加上自检、入库、发运提前期
  240. item.sys_capacity_date = item.sys_capacity_date.GetValueOrDefault().AddDays((double)(icitem.self_inspection_date.GetValueOrDefault() + icitem.Warehousing_date.GetValueOrDefault() + icitem.Shipping_date.GetValueOrDefault() + icitem.RoutingDesignTime.GetValueOrDefault()));
  241. }
  242. item.sys_capacity_date = item.sys_capacity_date <= item.plan_date ? item.plan_date : item.sys_capacity_date;
  243. }
  244. }
  245. }
  246. }