ProductExamineAppService.cs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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 DateTime ProductiveExamine(ProdExamineParamDto param)
  54. {
  55. //生产结束时间
  56. DateTime planEnd = param.PlanStart.Date;
  57. if (param.QtyOrd <= 0)
  58. {
  59. return planEnd;
  60. }
  61. //获取当前产品的工艺路线:主产线,最后一道工序
  62. var curRoutingOps = routingOps.Where(p => p.RoutingCode == param.ItemNum && p.ParentOp == 0).OrderByDescending(p => p.Op).ToList();
  63. if (curRoutingOps.Count == 0)
  64. {
  65. return planEnd;
  66. }
  67. var lastOp = curRoutingOps.First();
  68. //获取产线
  69. var curProdLine = prodLines.FirstOrDefault(p => p.Part == param.ItemNum && p.Op == lastOp.Op);
  70. if (curProdLine == null)
  71. {
  72. return planEnd;
  73. }
  74. //获取产线工作日历
  75. var curCalendars = calendarWorks.Where(p => p.ProdLine == curProdLine.Line).ToList();
  76. if (curCalendars.Count == 0 || curCalendars.Count != 7)
  77. {
  78. return planEnd;
  79. }
  80. //获取产线休息时间
  81. var curqualityLines = qualityLineWorks.Where(p=>p.ProdLine == curProdLine.Line).ToList();
  82. //生产数量
  83. decimal sumAmount = 0m;
  84. do
  85. {
  86. //获取工作日
  87. planEnd = GetNextWorkDay(planEnd, curCalendars);
  88. //计算工作日的产能
  89. sumAmount += CalcCapacity(planEnd, curProdLine, curCalendars, curqualityLines);
  90. planEnd = planEnd.AddDays(1);
  91. } while (sumAmount < param.QtyOrd);
  92. return planEnd.AddDays(-1);
  93. }
  94. /// <summary>
  95. /// 获取工作日
  96. /// </summary>
  97. /// <param name="weekDay">当前周几</param>
  98. /// <param name="startTime">开始时间:年-月-日</param>
  99. /// <param name="curCalendars">当前产线的工作日历</param>
  100. /// <returns></returns>
  101. public DateTime GetNextWorkDay(DateTime startTime, List<ShopCalendarWorkCtr> curCalendars)
  102. {
  103. DateTime rtnData = startTime;
  104. int weekDay = (int)startTime.DayOfWeek;
  105. var calendar = curCalendars.FirstOrDefault(p => p.WeekDay == weekDay);
  106. //判断当天是否是工作日
  107. if (weekDay == 0 || weekDay == 6)//周六,周日
  108. {
  109. if (!holidays.Exists(p => p.Dated.GetValueOrDefault().Date == startTime && p.Ufld1 == "调班"))//今天是周末
  110. {
  111. //递归继续找下一个工作日
  112. rtnData = GetNextWorkDay(startTime.AddDays(1), curCalendars);
  113. return rtnData;
  114. }
  115. return rtnData;
  116. }
  117. //今天不是周六周日,需要判断是不是节假日
  118. if (holidays.Exists(p => p.Dated.GetValueOrDefault().Date == startTime && p.Ufld1 == "休假"))//是节假日
  119. {
  120. //递归继续找下一个工作日
  121. rtnData = GetNextWorkDay(startTime.AddDays(1), curCalendars);
  122. return rtnData;
  123. }
  124. return rtnData;
  125. }
  126. /// <summary>
  127. /// 计算当天的产能
  128. /// </summary>
  129. /// <param name="startTime"></param>
  130. /// <param name="prodLine"></param>
  131. /// <param name="curCalendars"></param>
  132. /// <param name="curQualityLines"></param>
  133. /// <returns></returns>
  134. public decimal CalcCapacity(DateTime startTime,ProdLineDetail prodLine, List<ShopCalendarWorkCtr> curCalendars, List<QualityLineWorkDetail> curQualityLines)
  135. {
  136. decimal sumQty = 0m;
  137. //获取休息时长(分钟)
  138. decimal sumResrt = curQualityLines.Sum(p => p.RestTime);
  139. //获取当天的工作时长(分钟)
  140. decimal workTime = curCalendars.First(p => p.WeekDay == (int)startTime.DayOfWeek).ShiftsHours1 * 60;
  141. //计算产能
  142. sumQty = Math.Floor((workTime - sumResrt) / 60 * prodLine.Rate);
  143. return sumQty;
  144. }
  145. /// <summary>
  146. /// 计算订单行的建议交期(产能/物料)
  147. /// </summary>
  148. /// <param name="sentrys"></param>
  149. /// <param name="kittingTimes"></param>
  150. /// <returns></returns>
  151. public void CalcSuggestTime(List<crm_seorderentry> sentrys, List<KittingTimeDto> kittingTimes, List<mo_ic_item> icitemlist)
  152. {
  153. ProdExamineParamDto param;
  154. foreach (var item in sentrys)
  155. {
  156. var dto = kittingTimes.FirstOrDefault(p=>p.sentry_id == item.Id);
  157. if (dto == null)
  158. {
  159. continue;
  160. }
  161. var icitem = icitemlist.Find(s => s.number == item.item_number);
  162. if (dto.LackQty == 0)//当前订单行库存足够
  163. {
  164. if (icitem != null)
  165. {
  166. //加上自检、入库、发运提前期
  167. dto.kitting_time = dto.kitting_time.AddDays((double)(icitem.self_inspection_date.GetValueOrDefault() + icitem.Warehousing_date.GetValueOrDefault() + icitem.Shipping_date.GetValueOrDefault()));
  168. }
  169. item.sys_material_date = dto.kitting_time;
  170. item.sys_capacity_date = dto.kitting_time;
  171. return;
  172. }
  173. //计算系统建议交期(物料)
  174. param = new ProdExamineParamDto
  175. {
  176. ItemNum = item.item_number,
  177. QtyOrd = dto.LackQty,
  178. PlanStart = dto.kitting_time.Date.AddDays(1)
  179. };
  180. var time = ProductiveExamine(param);
  181. item.sys_material_date = time;
  182. item.sys_capacity_date = time;
  183. if (icitem != null)
  184. {
  185. //加上自检、入库、发运提前期
  186. item.sys_material_date = time.AddDays((double)(icitem.self_inspection_date.GetValueOrDefault() + icitem.Warehousing_date.GetValueOrDefault() + icitem.Shipping_date.GetValueOrDefault()));
  187. }
  188. //param.PlanStart = dto.kitting_time.Date.AddDays(3);
  189. //计算系统交期(产能)
  190. //获取主线最后一道工序
  191. List<PeriodSequenceDet> schedules = new List<PeriodSequenceDet>();
  192. var routings = routingOps.Where(p => p.RoutingCode == item.item_number && p.ParentOp == 0).OrderBy(p=>p.Op).ToList();
  193. if (routings.Count != 0)
  194. {
  195. //获取产线
  196. var prodLine = prodLines.FirstOrDefault(p => p.Part == item.item_number && p.Op == routings.Last().Op);
  197. if (prodLine != null)
  198. {
  199. //获取产线空闲开始时间
  200. schedules = periodSequences.Where(p => p.ItemNum == item.item_number && p.Op == prodLine.Op && p.Line == prodLine.Line).OrderByDescending(p => p.PlanDate).ToList();
  201. }
  202. }
  203. if (schedules.Any())
  204. {
  205. //产线空闲开始时间
  206. var lastTime = schedules.First().PlanDate.GetValueOrDefault().Date;
  207. if (lastTime >= param.PlanStart)//如果产线空闲时间大于或者等于系统建议交期(物料)的开工时间
  208. {
  209. param.PlanStart = lastTime;
  210. item.sys_capacity_date = ProductiveExamine(param);
  211. }
  212. else {
  213. item.sys_capacity_date = ProductiveExamine(param);
  214. }
  215. }
  216. else {
  217. item.sys_capacity_date = ProductiveExamine(param);
  218. }
  219. if (icitem != null)
  220. {
  221. //加上自检、入库、发运提前期
  222. item.sys_capacity_date = item.sys_capacity_date.GetValueOrDefault().AddDays((double)(icitem.self_inspection_date.GetValueOrDefault() + icitem.Warehousing_date.GetValueOrDefault() + icitem.Shipping_date.GetValueOrDefault()));
  223. }
  224. }
  225. }
  226. }
  227. }