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;
}
}
}