ProductExamineAppService.cs 10 KB

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