using Business.Core.MongoDBHelper; using Business.ResourceExamineManagement.Dto; using Bussiness.Model.Production; using Bussiness.Model.Tech; using Bussiness.MongoModel.Production; using Bussiness.MongoModel.Tech; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Volo.Abp.Application.Services; using Volo.Abp.Domain.Repositories; namespace Business.ResourceExamineManagement { /// /// 产能检查 /// public class ProductExamineAppService: ApplicationService { #region 服务 /// /// 工艺路径 /// public List techs = new List(); /// /// 工艺关联工序 /// public List tech_Processes = new List(); /// /// 工序 /// public List process = new List(); /// /// 工艺工序关联工位 /// public List tech_Proc_Workshops = new List(); #endregion /// /// 构造函数 /// public ProductExamineAppService() { } /// /// 产能计算 /// /// 件数 /// 生产时长 public decimal ProductiveExamine(ProdExamineParamDto param) { if (param.packages <= 0) { //throw new NotImplementedException("产能计算参数有误!"); } //过滤数据 //1.1、获取工艺路径数据 mo_mes_technique curTech = techs.FirstOrDefault(p => p.bom == param.bom_number && p.bomver == param.version); if (curTech == null) { return param.packages * 20; //throw new NotImplementedException("工艺路径不存在,请调整!"); } //1.2、获取工艺关联工序数据 List curTechProcess = tech_Processes.Where(p => p.tech_id == curTech.mysql_id).ToList(); if (curTechProcess.Count == 0) { return param.packages * 20; //throw new NotImplementedException("当前工艺路径没有配置工序,请调整!"); } //1.3、获取工序数据 List curProcess = process.Where(p => curTechProcess.Select(m => m.proc_id).Contains(p.mysql_id)).ToList(); if (curProcess.Count == 0) { return param.packages * 20; //throw new NotImplementedException("工序数据不存在,请调整!"); } //1.4、获取工位数据 List curWorkShops = tech_Proc_Workshops.Where(p=> curTechProcess.Select(m=>m.mysql_id).Contains(p.tech_proc_id)).ToList(); ; //2、获取工艺路径下的第一层级工序:目前只考虑第一层级 List fistLevels = curTechProcess.Where(p => p.parentprocid == curTech.mysql_id).ToList(); if (fistLevels.Count == 0) { return param.packages * 20; //throw new NotImplementedException("当前工艺路径没有配置工序,请调整!"); } //工艺预处理 List teches = TechProcPretreatment(fistLevels,param.packages); decimal sumTimes = teches.OrderByDescending(p => p.sumTimes).First().sumTimes; return sumTimes; } /// /// 工序预处理,按照多分支生成多条单独的工艺路径 /// /// 当前工序 /// 工艺关联工序list /// 生产件数 /// private List TechProcPretreatment(List processes,int packages) { //工艺路径预处理dto List techProcDtos = new List(); TechProcDto dto; //获取下一步工序id List nextProcIds = processes.Where(p=>p.nextprocid != null).Select(p => p.nextprocid.GetValueOrDefault()).ToList(); //获取起点工序 var startProcs = processes.Where(p => !nextProcIds.Contains(p.proc_id)).ToList(); //递归处理工序返回值 List rtnList; for (int i = 0; i < startProcs.Count; i++) { dto = new TechProcDto(); rtnList = new List(); GetNextProc(startProcs[i], processes, rtnList); dto.serialno = i + 1; dto.processes = rtnList; //dto.details = CalcTakeTimeByLq(rtnList, packages);//通过Lq计算 dto.details = CalcTakeTimeByLqt(rtnList, packages);//通过Lqt计算 dto.sumTimes = dto.details.Sum(p=>p.wait_time); techProcDtos.Add(dto); } return techProcDtos; } /// /// 递归:根据起始工序,获取后续工序 /// /// /// /// private void GetNextProc(mo_mes_tech_process proc, List processes, List rtnList) { rtnList.Add(proc); //下一工序id为null,终止 if (proc?.nextprocid == null) { return; } //获取下一个工序 var nextProc = processes.FirstOrDefault(p=>p.proc_id == proc.nextprocid); if (nextProc == null) { return; } GetNextProc(nextProc, processes, rtnList); } /// /// 通过Lq计算工艺耗时 /// /// /// /// private List CalcTakeTimeByLq(List Processes, int packages) { //工序需要等待时间记录 List starts = new List(); StartTimeDto dto; foreach (var chd in Processes) { dto = new StartTimeDto(); if (chd.nextprocid == null)//最后一个工序 { //计算最后一个工序耗时 dto = CalcProcTakeTimeByLq(chd, packages, packages); } else { dto = CalcProcTakeTimeByLq(chd, chd.lq.GetValueOrDefault(), packages); } //添加记录 starts.Add(dto); } return starts; } /// /// 通过Lq计算当前工序前置准备时间 /// /// /// LeadQuantity to Start Next /// 件数 /// private StartTimeDto CalcProcTakeTimeByLq(mo_mes_tech_process proc, decimal quantity, int packages) { //记录当前工序耗时 StartTimeDto dto = new StartTimeDto(); //添加耗时记录 dto.tech_id = proc.tech_id; dto.proc_id = proc.proc_id; dto.nextproc_id = proc.nextprocid; if (proc.wctype == 1)//人工型:数量/uph(一小时生产数量)*60(小时转换为分钟)/wsinuse(工位数) { if ( proc.uph.GetValueOrDefault() == 0 || proc.wsinuse.GetValueOrDefault() == 0) { throw new NotImplementedException("当前工序uph或wsinuse参数配置错误,请调整!"); } dto.wait_time = quantity / proc.uph.GetValueOrDefault() * 60 / proc.wsinuse.GetValueOrDefault(); dto.take_time = packages / proc.uph.GetValueOrDefault() * 60 / proc.wsinuse.GetValueOrDefault(); } else if (proc.wctype == 2)//流水线型:数量*ct(生产一件所需时间)/wsinuse(工位数) { if (proc.ct.GetValueOrDefault() == 0 || proc.wsinuse.GetValueOrDefault() == 0) { throw new NotImplementedException("当前工序ct或wsinuse参数配置错误,请调整!"); } dto.wait_time = quantity * proc.ct.GetValueOrDefault() / proc.wsinuse.GetValueOrDefault(); dto.take_time = packages * proc.ct.GetValueOrDefault() / proc.wsinuse.GetValueOrDefault(); } else if (proc.wctype == 3)//设备型:向上取整(数量/一次可加工数量/wsinuse(工位数))*ct(老化一次所需时间) { if (proc.upe.GetValueOrDefault() == 0 || proc.wsinuse.GetValueOrDefault() == 0|| proc.ct.GetValueOrDefault() == 0) { throw new NotImplementedException("当前工序upe或ct或wsinuse参数配置错误,请调整!"); } dto.wait_time = Math.Ceiling(quantity / proc.upe.GetValueOrDefault() / proc.wsinuse.GetValueOrDefault()) * proc.ct.GetValueOrDefault(); dto.take_time = Math.Ceiling(packages / proc.upe.GetValueOrDefault() / proc.wsinuse.GetValueOrDefault()) * proc.ct.GetValueOrDefault(); } return dto; } /// /// 通过Lqt计算工艺耗时 /// /// /// /// private List CalcTakeTimeByLqt(List Processes, int packages) { //工序需要等待时间记录 List starts = new List(); StartTimeDto dto; foreach (var chd in Processes) { dto = new StartTimeDto(); //添加耗时记录 dto.tech_id = chd.tech_id; dto.proc_id = chd.proc_id; dto.nextproc_id = chd.nextprocid; //计算当前工序生产耗时 dto.take_time = CalcProcTakeTime(chd, packages); if (chd.nextprocid == null)//最后一个工序 { dto.wait_time = dto.take_time; } else { dto.wait_time = chd.lqt.Value; } //添加记录 starts.Add(dto); } return starts; } /// /// 计算当前工序生产时间 /// /// /// 件数 /// private decimal CalcProcTakeTime(mo_mes_tech_process proc, int packages) { //当前工序生产时间 decimal takeTiem = 0.00m; if (proc.wctype == 1)//人工型:数量/uph(一小时生产数量)*60(小时转换为分钟)/wsinuse(工位数) { if (proc.uph.GetValueOrDefault() == 0 || proc.wsinuse.GetValueOrDefault() == 0) { throw new NotImplementedException("当前工序uph或wsinuse参数配置错误,请调整!"); } takeTiem = packages / proc.uph.GetValueOrDefault() * 60 / proc.wsinuse.GetValueOrDefault(); } else if (proc.wctype == 2)//流水线型:数量*ct(生产一件所需时间)/wsinuse(工位数) { if (proc.ct.GetValueOrDefault() == 0 || proc.wsinuse.GetValueOrDefault() == 0) { throw new NotImplementedException("当前工序ct或wsinuse参数配置错误,请调整!"); } takeTiem = packages * proc.ct.GetValueOrDefault() / proc.wsinuse.GetValueOrDefault(); } else if (proc.wctype == 3)//设备型:向上取整(数量/一次可加工数量/wsinuse(工位数))*ct(老化一次所需时间) { if (proc.upe.GetValueOrDefault() == 0 || proc.wsinuse.GetValueOrDefault() == 0 || proc.ct.GetValueOrDefault() == 0) { throw new NotImplementedException("当前工序upe或ct或wsinuse参数配置错误,请调整!"); } takeTiem = Math.Ceiling(packages / proc.upe.GetValueOrDefault() / proc.wsinuse.GetValueOrDefault()) * proc.ct.GetValueOrDefault(); } return takeTiem; } } }