using Business.Domain; using Business.Dto; using Business.ResourceExamineManagement.Dto; using MongoDB.Driver.Linq; using System; using System.Collections.Generic; using System.Linq; using Volo.Abp.Application.Services; namespace Business.ResourceExamineManagement { /// /// 产能检查 /// public class ProductExamineAppService: ApplicationService { #region 服务 /// /// 生产线明细表 /// public List prodLines = new List(); /// /// 标准工艺路径表 /// public List routingOps = new List(); /// /// 排产记录表 /// public List periodSequences = new List(); /// /// 工作日历 /// public List calendarWorks = new List(); /// /// 休息时间段 /// public List qualityLineWorks = new List(); /// /// 节假日 /// public List holidays = new List(); #endregion /// /// 构造函数 /// public ProductExamineAppService() { } /// /// 根据标准工艺获取生产时长(天) /// /// /// public int ProductTime(ProdExamineParamDto param) { var allOps = routingOps.Where(s => s.RoutingCode == param.ItemNum && s.Domain == param.Domain).ToList(); if (allOps.Any()) { decimal maxRt = allOps.Max(s => s.RunTime); decimal sumRt = allOps.Sum(s => s.RunTime); decimal totalTime = (param.QtyOrd - 1) * maxRt + sumRt;//总计生产小时 return (int)(Math.Ceiling(totalTime / 8)); } return 1; } /// /// 产能计算-批量 /// /// 产能检查入参 /// 生产时长(天) public DateTime ProductiveExamine(ProdExamineParamDto param) { //生产结束时间 DateTime planEnd = param.PlanStart.Date; if (param.QtyOrd <= 0) { return planEnd; } //获取当前产品的工艺路线:主产线,最后一道工序 var curRoutingOps = routingOps.Where(p => p.RoutingCode == param.ItemNum && p.ParentOp == 0).OrderByDescending(p => p.Op).ToList(); if (curRoutingOps.Count == 0) { return planEnd; } var lastOp = curRoutingOps.First(); //获取产线 var curProdLine = prodLines.FirstOrDefault(p => p.Part == param.ItemNum && p.Op == lastOp.Op); if (curProdLine == null) { return planEnd; } //获取产线工作日历 var curCalendars = calendarWorks.Where(p => p.ProdLine == curProdLine.Line).ToList(); if (curCalendars.Count == 0 || curCalendars.Count != 7) { return planEnd; } //获取产线休息时间 var curqualityLines = qualityLineWorks.Where(p=>p.ProdLine == curProdLine.Line).ToList(); //生产数量 decimal sumAmount = 0m; do { //获取工作日 planEnd = GetNextWorkDay(planEnd, curCalendars); //计算工作日的产能 sumAmount += CalcCapacity(planEnd, curProdLine, curCalendars, curqualityLines); planEnd = planEnd.AddDays(1); } while (sumAmount < param.QtyOrd); return planEnd.AddDays(-1); } /// /// 获取工作日 /// /// 当前周几 /// 开始时间:年-月-日 /// 当前产线的工作日历 /// public DateTime GetNextWorkDay(DateTime startTime, List curCalendars) { DateTime rtnData = startTime; int weekDay = (int)startTime.DayOfWeek; var calendar = curCalendars.FirstOrDefault(p => p.WeekDay == weekDay); //判断当天是否是工作日 if (weekDay == 0 || weekDay == 6)//周六,周日 { if (!holidays.Exists(p => p.Dated.GetValueOrDefault().Date == startTime && p.Ufld1 == "调班"))//今天是周末 { //递归继续找下一个工作日 rtnData = GetNextWorkDay(startTime.AddDays(1), curCalendars); return rtnData; } return rtnData; } //今天不是周六周日,需要判断是不是节假日 if (holidays.Exists(p => p.Dated.GetValueOrDefault().Date == startTime && p.Ufld1 == "休假"))//是节假日 { //递归继续找下一个工作日 rtnData = GetNextWorkDay(startTime.AddDays(1), curCalendars); return rtnData; } return rtnData; } /// /// 计算当天的产能 /// /// /// /// /// /// public decimal CalcCapacity(DateTime startTime,ProdLineDetail prodLine, List curCalendars, List curQualityLines) { decimal sumQty = 0m; //获取休息时长(分钟) decimal sumResrt = curQualityLines.Sum(p => p.RestTime); //获取当天的工作时长(分钟) decimal workTime = curCalendars.First(p => p.WeekDay == (int)startTime.DayOfWeek).ShiftsHours1 * 60; //计算产能 sumQty = Math.Ceiling((workTime - sumResrt) / 60 * prodLine.Rate); return sumQty; } /// /// 计算订单行的建议交期(产能/物料) /// /// /// /// public void CalcSuggestTime(List sentrys, List kittingTimes, List icitemlist) { ProdExamineParamDto param; foreach (var item in sentrys) { var dto = kittingTimes.FirstOrDefault(p=>p.sentry_id == item.Id); if (dto == null) { continue; } var icitem = icitemlist.Find(s => s.number == item.item_number); if (dto.LackQty == 0)//当前订单行库存足够 { if (icitem != null) { //加上自检、入库、发运提前期 dto.kitting_time = dto.kitting_time.AddDays((double)(icitem.self_inspection_date.GetValueOrDefault() + icitem.Warehousing_date.GetValueOrDefault() + icitem.Shipping_date.GetValueOrDefault())); dto.kitting_time= dto.kitting_time<=item.plan_date.GetValueOrDefault()? item.plan_date.GetValueOrDefault(): dto.kitting_time; } item.sys_material_date = dto.kitting_time; item.sys_capacity_date = dto.kitting_time; continue; } //计算系统建议交期(物料) param = new ProdExamineParamDto { ItemNum = item.item_number, QtyOrd = dto.LackQty, PlanStart = dto.kitting_time.Date.AddDays(1) }; var time = ProductiveExamine(param); item.sys_material_date = time; item.sys_capacity_date = time; if (icitem != null) { //加上自检、入库、发运提前期 item.sys_material_date = time.AddDays((double)(icitem.self_inspection_date.GetValueOrDefault() + icitem.Warehousing_date.GetValueOrDefault() + icitem.Shipping_date.GetValueOrDefault())); } //param.PlanStart = dto.kitting_time.Date.AddDays(3); //计算系统交期(产能) //获取主线最后一道工序 List schedules = new List(); var routings = routingOps.Where(p => p.RoutingCode == item.item_number && p.ParentOp == 0).OrderBy(p=>p.Op).ToList(); if (routings.Count != 0) { //获取产线 var prodLine = prodLines.FirstOrDefault(p => p.Part == item.item_number && p.Op == routings.Last().Op); if (prodLine != null) { //获取产线空闲开始时间 schedules = periodSequences.Where(p => p.ItemNum == item.item_number && p.Op == prodLine.Op && p.Line == prodLine.Line).OrderByDescending(p => p.PlanDate).ToList(); } } if (schedules.Any()) { //产线空闲开始时间 var lastTime = schedules.First().PlanDate.GetValueOrDefault().Date; if (lastTime >= param.PlanStart)//如果产线空闲时间大于或者等于系统建议交期(物料)的开工时间 { param.PlanStart = lastTime; item.sys_capacity_date = ProductiveExamine(param); } else { item.sys_capacity_date = ProductiveExamine(param); } } else { item.sys_capacity_date = ProductiveExamine(param); } if (icitem != null) { //加上自检、入库、发运提前期 item.sys_capacity_date = item.sys_capacity_date.GetValueOrDefault().AddDays((double)(icitem.self_inspection_date.GetValueOrDefault() + icitem.Warehousing_date.GetValueOrDefault() + icitem.Shipping_date.GetValueOrDefault())); } item.sys_capacity_date = item.sys_capacity_date <= item.plan_date ? item.plan_date : item.sys_capacity_date; } } } }