|
|
@@ -15,6 +15,8 @@ using System.Transactions;
|
|
|
using Volo.Abp.Application.Services;
|
|
|
using Volo.Abp.MultiTenancy;
|
|
|
using Microsoft.Extensions.Configuration;
|
|
|
+using Org.BouncyCastle.Asn1.Crmf;
|
|
|
+using System.Runtime.CompilerServices;
|
|
|
|
|
|
namespace Business.ResourceExamineManagement
|
|
|
{
|
|
|
@@ -161,7 +163,7 @@ namespace Business.ResourceExamineManagement
|
|
|
IConfiguration configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).Build();
|
|
|
domain = configuration.GetConnectionString("Factory_id");
|
|
|
|
|
|
- //获取需要排产的工单
|
|
|
+ //获取需要排产的工单:TODO-郑立阳
|
|
|
List<WorkOrdMaster> workOrds = new List<WorkOrdMaster>();
|
|
|
|
|
|
await DoProductShcedule(workOrds, domain);
|
|
|
@@ -182,8 +184,8 @@ namespace Business.ResourceExamineManagement
|
|
|
return;
|
|
|
}
|
|
|
//获取排产工单的最早计划开工日期
|
|
|
- DateTime earlist = workOrds.Min(p => p.OrdDate.GetValueOrDefault()).Date;
|
|
|
-
|
|
|
+ DateTime earlist = DateTime.Now.Date.AddDays(1);
|
|
|
+
|
|
|
//2、获取数据
|
|
|
//获取工单工艺路径数据
|
|
|
List<WorkOrdRouting> workOrdRoutings = _workOrdRouting.Select(p => workOrds.Select(m => m.WorkOrd).Contains(p.WorkOrd) && p.ParentOp == 0 && p.Domain == domain && p.Status != "C" && p.IsActive);
|
|
|
@@ -198,10 +200,10 @@ namespace Business.ResourceExamineManagement
|
|
|
List<PeriodSequenceDet> dbPeriodSequences = _periodSequenceDet.Select(p => lines.Contains(p.Line) && p.PlanDate >= earlist && p.Domain == domain && p.IsActive);
|
|
|
//获取当前日期往后的排产记录数据
|
|
|
List<ScheduleResultOpMaster> dbSchedules = _scheduleResultOpMaster.Select(p => lines.Contains(p.Line) && p.WorkDate >= earlist && p.Domain == domain);
|
|
|
- //获取工作日历数据
|
|
|
- calendars = _shopCalendarWorkCtr.Select(p => p.Domain == domain && p.IsActive);
|
|
|
+ //获取工作日历数据:产线的工作日历+默认的工作日历
|
|
|
+ calendars = _shopCalendarWorkCtr.Select(p => (lines.Contains(p.ProdLine) || string.IsNullOrEmpty(p.ProdLine)) && p.Domain == domain && p.IsActive);
|
|
|
//获取产线休息记录数据
|
|
|
- qualityLines = _qualityLineWorkDetail.Select(p => p.Domain == domain && p.IsActive);
|
|
|
+ qualityLines = _qualityLineWorkDetail.Select(p => lines.Contains(p.ProdLine) && p.Domain == domain && p.IsActive);
|
|
|
//获取节假日记录数据
|
|
|
holidays = _holidayMaster.Select(p => p.Domain == domain && p.IsActive && p.Dated >= earlist);
|
|
|
|
|
|
@@ -215,56 +217,16 @@ namespace Business.ResourceExamineManagement
|
|
|
allResults.AddRange(dbSchedules);
|
|
|
foreach (var item in workOrds)
|
|
|
{
|
|
|
- ////当前工单的排产计划开始时间:年-月-日
|
|
|
- //DateTime planStart = item.OrdDate.GetValueOrDefault().Date;
|
|
|
- ////当前工单对应的产线数据
|
|
|
- //var curLines = prodLines.Where(p => p.Part == item.ItemNum).Select(m=>m.Line).Distinct().ToList();
|
|
|
- ////当前工单的对应的产线排产记录
|
|
|
- //var curSchedules = dbSchedules.Where(p => curLines.Contains(p.Line)).ToList();
|
|
|
+ //记录产线占用情况
|
|
|
allResults.AddRange(scheduleMasters);
|
|
|
-
|
|
|
- //计算当前物料排产开始产线
|
|
|
- List<WorkOrdRoutingDto> routingDtos = ProcPretreatment(item, workOrdRoutings.Where(p => p.WorkOrd == item.WorkOrd).ToList(), prodLines, allResults);
|
|
|
-
|
|
|
- //排产前的数据校验
|
|
|
- if (routingDtos.Count == 0)//没有维护主工序
|
|
|
- {
|
|
|
- //记录排产异常原因
|
|
|
- new NLogHelper("ProductionScheduleAppService").WriteLog("DoProductShcedule", "工单<" + item.WorkOrd + ">的工序数据维护错误", _currentTenant.Id.ToString());
|
|
|
- continue;
|
|
|
- }
|
|
|
- //校验每层级工序是否都维护了产线
|
|
|
- if (routingDtos.Exists(p => string.IsNullOrEmpty(p.Line)))
|
|
|
- {
|
|
|
- //记录排产异常原因
|
|
|
- new NLogHelper("ProductionScheduleAppService").WriteLog("DoProductShcedule", "工单<" + item.WorkOrd + ">的产线数据维护错误", _currentTenant.Id.ToString());
|
|
|
- continue;
|
|
|
- }
|
|
|
- //校验每个层级是否维护了工作日历
|
|
|
- bool flag = false;
|
|
|
- foreach (var rut in routingDtos)
|
|
|
- {
|
|
|
- var lineCals = calendars.Where(p => p.ProdLine == rut.Line).ToList();
|
|
|
- //当前产线未配置工作日历取标准无产线工作日历使用
|
|
|
- if (lineCals.Count == 0)
|
|
|
- {
|
|
|
- lineCals = calendars.Where(p => string.IsNullOrEmpty(p.ProdLine)).ToList();
|
|
|
- }
|
|
|
- if (lineCals.Select(p => p.WeekDay).Distinct().Count() != 7)
|
|
|
- {
|
|
|
- flag = true;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (flag)
|
|
|
- {
|
|
|
- //记录排产异常原因
|
|
|
- new NLogHelper("ProductionScheduleAppService").WriteLog("DoProductShcedule", "工单<" + item.WorkOrd + ">的产线工作日历数据维护错误", _currentTenant.Id.ToString());
|
|
|
- continue;
|
|
|
- }
|
|
|
+ //当前工单工艺路线主产线的关键工序
|
|
|
+ var curRoutings = workOrdRoutings.Where(p => p.ItemNum == item.ItemNum && p.ParentOp == 0 && p.MilestoneOp).OrderBy(p=>p.OP).ToList();
|
|
|
+ //当前工单的产线明细
|
|
|
+ var curProdLines = prodLines.Where(p => p.Part == item.ItemNum).ToList();
|
|
|
+ //排产前数据校验:TODO-郑立阳
|
|
|
|
|
|
//产线排产
|
|
|
- LineSchedule(item, routingDtos.OrderBy(p => p.level).ToList(), periodSequenceDtls, scheduleMasters);
|
|
|
+ LineSchedule(item, curRoutings, curProdLines, periodSequenceDtls, scheduleMasters,allResults);
|
|
|
|
|
|
List<ScheduleResultOpMaster> scheduleList = scheduleMasters.Where(s => s.WorkOrd == item.WorkOrd).ToList();
|
|
|
if (scheduleList.Any())
|
|
|
@@ -299,159 +261,284 @@ namespace Business.ResourceExamineManagement
|
|
|
/// 排产
|
|
|
/// </summary>
|
|
|
/// <param name="workOrd">工单</param>
|
|
|
- /// <param name="routingDtos">每层级工序对应的产线信息,从小到大排序</param>
|
|
|
+ /// <param name="workOrdRoutings">当前工单的工艺路线的关键工序(有几个关键工序就有几条产线)</param>
|
|
|
+ /// <param name="prodLines">当前工单的产线明细</param>
|
|
|
/// <param name="periodsDet">生产周期</param>
|
|
|
/// <param name="scheduleResults">排产结果</param>
|
|
|
- public void LineSchedule(WorkOrdMaster workOrd, List<WorkOrdRoutingDto> routingDtos, List<PeriodSequenceDet> periodsDet, List<ScheduleResultOpMaster> scheduleResults)
|
|
|
+ /// <param name="allResults">产线占用记录</param>
|
|
|
+ public void LineSchedule(WorkOrdMaster workOrd, List<WorkOrdRouting> workOrdRoutings, List<ProdLineDetail> prodLines,List<PeriodSequenceDet> periodsDet, List<ScheduleResultOpMaster> scheduleResults, List<ScheduleResultOpMaster> allResults)
|
|
|
{
|
|
|
//生产周期
|
|
|
List<PeriodSequenceDet> curSequences = new List<PeriodSequenceDet>();
|
|
|
//排产明细
|
|
|
List<ScheduleResultOpMaster> curScheduleRsts = new List<ScheduleResultOpMaster>();
|
|
|
- //产线排产开始时间
|
|
|
- List<LineStartDto> lineStarts = new List<LineStartDto>();
|
|
|
-
|
|
|
- //循环产线,排产
|
|
|
- foreach (var item in routingDtos)
|
|
|
+ //记录上一产线排产开始时间
|
|
|
+ LineStartDto lineStart = new LineStartDto();
|
|
|
+ //第一层级工序有几个关键工序,就有几条产线
|
|
|
+ for (int i = 0; i < workOrdRoutings.Count; i++)
|
|
|
{
|
|
|
- //当前产线的工作日历
|
|
|
- var mLCalendars = calendars.Where(p => p.ProdLine == item.Line).ToList();
|
|
|
- //当前产线的每天休息时间记录
|
|
|
- var mlqtyWorkDtls = qualityLines.Where(p => p.ProdLine == item.Line).OrderBy(p => p.Line).ToList();
|
|
|
-
|
|
|
- //产线已排产数量
|
|
|
- decimal sumQty = 0m;
|
|
|
//产线实际排产开始时间
|
|
|
- DateTime workStartTime;
|
|
|
- if (item.level == 1)//主产线
|
|
|
+ if (i == 0)//第一条产线
|
|
|
{
|
|
|
- workStartTime = DealStartTime(item.StartTime, mLCalendars, mlqtyWorkDtls);
|
|
|
+ lineStart = DealStartTime(workOrd, workOrdRoutings[i].OP, prodLines, allResults);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- //子产线获取实际排产开始日期
|
|
|
- //获取父级排产开始时间
|
|
|
- DateTime parentStartTime = lineStarts.First(p => p.ChdParentOps.Contains(item.ParentOp)).StartTime;
|
|
|
- workStartTime = DealChildStartTime(parentStartTime, item.SetupTime, mLCalendars, mlqtyWorkDtls);
|
|
|
+ //获取前一产线排产开始时间,通过提前期计算当前产线排产开始时间
|
|
|
+ lineStart = DealNextStartTime(workOrd,lineStart, workOrdRoutings[i].OP, prodLines, allResults);
|
|
|
}
|
|
|
- //记录产线排产开始时间
|
|
|
- lineStarts.Add(new LineStartDto
|
|
|
- {
|
|
|
- level = item.level,
|
|
|
- Line = item.Line,
|
|
|
- Op = item.Op,
|
|
|
- StartTime = workStartTime,
|
|
|
- ChdParentOps = item.ChdParentOps
|
|
|
- });
|
|
|
+ //当前产线的工作日历
|
|
|
+ var mLCalendars = calendars.Where(p => p.ProdLine == lineStart.Line || string.IsNullOrEmpty(p.ProdLine)).ToList();
|
|
|
+ //当前产线的休息时间设置
|
|
|
+ var mlqtyWorkDtls = qualityLines.Where(p => p.ProdLine == lineStart.Line).ToList();
|
|
|
+ //产线已排产数量
|
|
|
+ decimal sumQty = 0m;
|
|
|
+ //产线准备时间
|
|
|
+ decimal sumTimes = 0m;
|
|
|
+ //产线排产开始时间
|
|
|
+ DateTime workStartTime = lineStart.StartTime;
|
|
|
//排产
|
|
|
while (sumQty < workOrd.QtyOrded)
|
|
|
{
|
|
|
//获取当天的产能
|
|
|
- LineScheduledDto dto = GetScheduledPoint(item, workStartTime, mLCalendars, mlqtyWorkDtls);
|
|
|
- //判断已排产数量+当天的产能是否超过工单数量
|
|
|
- if (sumQty + dto.ProductQty <= workOrd.QtyOrded)//当天的产能需要全部排产
|
|
|
+ LineScheduledDto dto = GetScheduledPoint(lineStart.Rate, workStartTime, mLCalendars, mlqtyWorkDtls);
|
|
|
+ //排产开始时,需要先减去产线准备时间
|
|
|
+ if (sumTimes < lineStart.setupTime)
|
|
|
{
|
|
|
- //记录生产周期
|
|
|
- curSequences.Add(new PeriodSequenceDet
|
|
|
+ //判断当天的可用生产时长能满足提前期
|
|
|
+ if (dto.EffTime >= lineStart.setupTime)
|
|
|
{
|
|
|
- Domain = domain,
|
|
|
- Line = item.Line,
|
|
|
- ItemNum = workOrd.ItemNum,
|
|
|
- PlanDate = workStartTime.Date,
|
|
|
- Period = 1,//目前只考虑一班制
|
|
|
- OrdQty = dto.ProductQty,
|
|
|
- WorkOrds = workOrd.WorkOrd,
|
|
|
- Op = item.Op,
|
|
|
- IsActive = true,
|
|
|
- Status = "",
|
|
|
- CreateTime = DateTime.Now
|
|
|
- });
|
|
|
- //记录排产记录
|
|
|
- curScheduleRsts.Add(new ScheduleResultOpMaster
|
|
|
- {
|
|
|
- Domain = domain,
|
|
|
- WorkOrd = workOrd.WorkOrd,
|
|
|
- Line = item.Line,
|
|
|
- ItemNum = workOrd.ItemNum,
|
|
|
- Op = item.Op,
|
|
|
- WorkDate = workStartTime.Date,
|
|
|
- WorkQty = dto.ProductQty,
|
|
|
- WorkStartTime = dto.StartTime,
|
|
|
- WorkEndTime = dto.EndTime,
|
|
|
- CreateTime = DateTime.Now
|
|
|
- });
|
|
|
- //累计已排产数量
|
|
|
- sumQty += dto.ProductQty;
|
|
|
- //继续排下一个工作日
|
|
|
- workStartTime = GetNextWorkDay((int)workStartTime.DayOfWeek, workStartTime, mLCalendars);
|
|
|
- }
|
|
|
- else// 最后一天的产能只能占用一部分
|
|
|
- {
|
|
|
- //剩余需要排产的数量
|
|
|
- decimal residueQty = workOrd.QtyOrded - sumQty;
|
|
|
- //剩余数量生产需要时长(分钟)
|
|
|
- decimal workTime = Math.Ceiling(residueQty / item.Rate * 60);
|
|
|
- //获取当天的工作时间段
|
|
|
- List<LineWorkPointDto> workPoints = DealWorkDayToLevels(workStartTime, mLCalendars.First(p => p.WeekDay == (int)workStartTime.DayOfWeek), mlqtyWorkDtls);
|
|
|
- var curPoint = workPoints.Find(p => p.StartPoint <= workStartTime && workStartTime <= p.EndPoint);
|
|
|
- if (curPoint == null)
|
|
|
- {
|
|
|
- continue;
|
|
|
+ sumTimes = lineStart.setupTime;
|
|
|
+ //当天剩余产能
|
|
|
+ decimal sumAmount = dto.ProductQty - Math.Floor(lineStart.Rate * lineStart.setupTime);
|
|
|
+ //判断已排产数量+当天的产能是否超过工单数量
|
|
|
+ if (sumQty + sumAmount <= workOrd.QtyOrded)//当天的产能需要全部排产
|
|
|
+ {
|
|
|
+ //记录生产周期
|
|
|
+ curSequences.Add(new PeriodSequenceDet
|
|
|
+ {
|
|
|
+ Domain = domain,
|
|
|
+ Line = lineStart.Line,
|
|
|
+ ItemNum = workOrd.ItemNum,
|
|
|
+ PlanDate = workStartTime.Date,
|
|
|
+ Period = dto.Period,
|
|
|
+ OrdQty = sumAmount,
|
|
|
+ WorkOrds = workOrd.WorkOrd,
|
|
|
+ Op = lineStart.Op,
|
|
|
+ IsActive = true,
|
|
|
+ Status = "",
|
|
|
+ CreateTime = DateTime.Now
|
|
|
+ });
|
|
|
+ //记录排产记录
|
|
|
+ curScheduleRsts.Add(new ScheduleResultOpMaster
|
|
|
+ {
|
|
|
+ Domain = domain,
|
|
|
+ WorkOrd = workOrd.WorkOrd,
|
|
|
+ Line = lineStart.Line,
|
|
|
+ ItemNum = workOrd.ItemNum,
|
|
|
+ Op = lineStart.Op,
|
|
|
+ WorkDate = workStartTime.Date,
|
|
|
+ WorkQty = sumAmount,
|
|
|
+ WorkStartTime = dto.StartTime,
|
|
|
+ WorkEndTime = dto.EndTime,
|
|
|
+ CreateTime = DateTime.Now
|
|
|
+ });
|
|
|
+ //累计已排产数量
|
|
|
+ sumQty += sumAmount;
|
|
|
+ //继续排下一个工作日
|
|
|
+ workStartTime = GetNextWorkDay((int)workStartTime.DayOfWeek, workStartTime, mLCalendars);
|
|
|
+ }
|
|
|
+ else// 最后一天的产能只能占用一部分
|
|
|
+ {
|
|
|
+ //剩余需要排产的数量
|
|
|
+ decimal residueQty = workOrd.QtyOrded - sumQty;
|
|
|
+ //剩余数量生产需要时长(分钟)
|
|
|
+ decimal workTime = Math.Ceiling(residueQty / lineStart.Rate * 60);
|
|
|
+ //获取当天的工作时间段
|
|
|
+ var curCalendar = mLCalendars.FirstOrDefault(p => !string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == (int)workStartTime.DayOfWeek);
|
|
|
+ if (curCalendar == null)
|
|
|
+ {
|
|
|
+ curCalendar = mLCalendars.FirstOrDefault(p => string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == (int)workStartTime.DayOfWeek);
|
|
|
+ }
|
|
|
+ List<LineWorkPointDto> workPoints = DealWorkDayToLevels(workStartTime, curCalendar, mlqtyWorkDtls);
|
|
|
+ var curPoint = workPoints.Find(p => p.StartPoint <= workStartTime && workStartTime <= p.EndPoint);
|
|
|
+ if (curPoint != null)
|
|
|
+ {
|
|
|
+ TimeSpan span = curPoint.EndPoint - workStartTime;
|
|
|
+ //当天工作时间段的有效生产时间
|
|
|
+ decimal effMins = (decimal)span.TotalMinutes;
|
|
|
+ DateTime workEndTime = workStartTime;
|
|
|
+ if (effMins >= workTime)//当前工作时间段即可满足产能
|
|
|
+ {
|
|
|
+ workEndTime = workStartTime.AddMinutes((double)workTime);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //获取后续生产时间段
|
|
|
+ var nextPoints = workPoints.Where(p => p.Level > curPoint.Level).ToList();
|
|
|
+ //剩余需要工作时长
|
|
|
+ decimal nextMins = workTime - effMins;
|
|
|
+ foreach (var p in nextPoints)
|
|
|
+ {
|
|
|
+ if (p.WorkMinutes >= nextMins)
|
|
|
+ {
|
|
|
+ workEndTime = p.StartPoint.AddMinutes((double)nextMins);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ nextMins -= p.WorkMinutes;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sumQty = workOrd.QtyOrded;
|
|
|
+ //记录生产周期
|
|
|
+ curSequences.Add(new PeriodSequenceDet
|
|
|
+ {
|
|
|
+ Domain = domain,
|
|
|
+ Line = lineStart.Line,
|
|
|
+ ItemNum = workOrd.ItemNum,
|
|
|
+ PlanDate = workStartTime.Date,
|
|
|
+ Period = dto.Period,
|
|
|
+ OrdQty = residueQty,
|
|
|
+ WorkOrds = workOrd.WorkOrd,
|
|
|
+ Op = lineStart.Op,
|
|
|
+ IsActive = true,
|
|
|
+ Status = "",
|
|
|
+ CreateTime = DateTime.Now
|
|
|
+ });
|
|
|
+ //记录排产记录
|
|
|
+ curScheduleRsts.Add(new ScheduleResultOpMaster
|
|
|
+ {
|
|
|
+ Domain = domain,
|
|
|
+ WorkOrd = workOrd.WorkOrd,
|
|
|
+ Line = lineStart.Line,
|
|
|
+ ItemNum = workOrd.ItemNum,
|
|
|
+ Op = lineStart.Op,
|
|
|
+ WorkDate = workStartTime.Date,
|
|
|
+ WorkQty = residueQty,
|
|
|
+ WorkStartTime = workStartTime,
|
|
|
+ WorkEndTime = workEndTime,
|
|
|
+ CreateTime = DateTime.Now
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- TimeSpan span = curPoint.EndPoint - workStartTime;
|
|
|
- //当天工作时间段的有效生产时间
|
|
|
- decimal effMins = (decimal)span.TotalMinutes;
|
|
|
- DateTime workEndTime = workStartTime;
|
|
|
- if (effMins >= workTime)//当前工作时间段即可满足产能
|
|
|
+ else {
|
|
|
+ //当天的可用生产时长不能满足提前期
|
|
|
+ sumTimes += dto.EffTime;
|
|
|
+ //获取下一个工作日
|
|
|
+ workStartTime = GetNextWorkDay((int)workStartTime.DayOfWeek, workStartTime, mLCalendars);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ //判断已排产数量+当天的产能是否超过工单数量
|
|
|
+ if (sumQty + dto.ProductQty <= workOrd.QtyOrded)//当天的产能需要全部排产
|
|
|
{
|
|
|
- workEndTime = workStartTime.AddMinutes((double)workTime);
|
|
|
+ //记录生产周期
|
|
|
+ curSequences.Add(new PeriodSequenceDet
|
|
|
+ {
|
|
|
+ Domain = domain,
|
|
|
+ Line = lineStart.Line,
|
|
|
+ ItemNum = workOrd.ItemNum,
|
|
|
+ PlanDate = workStartTime.Date,
|
|
|
+ Period = dto.Period,//目前只考虑一班制
|
|
|
+ OrdQty = dto.ProductQty,
|
|
|
+ WorkOrds = workOrd.WorkOrd,
|
|
|
+ Op = lineStart.Op,
|
|
|
+ IsActive = true,
|
|
|
+ Status = "",
|
|
|
+ CreateTime = DateTime.Now
|
|
|
+ });
|
|
|
+ //记录排产记录
|
|
|
+ curScheduleRsts.Add(new ScheduleResultOpMaster
|
|
|
+ {
|
|
|
+ Domain = domain,
|
|
|
+ WorkOrd = workOrd.WorkOrd,
|
|
|
+ Line = lineStart.Line,
|
|
|
+ ItemNum = workOrd.ItemNum,
|
|
|
+ Op = lineStart.Op,
|
|
|
+ WorkDate = workStartTime.Date,
|
|
|
+ WorkQty = dto.ProductQty,
|
|
|
+ WorkStartTime = dto.StartTime,
|
|
|
+ WorkEndTime = dto.EndTime,
|
|
|
+ CreateTime = DateTime.Now
|
|
|
+ });
|
|
|
+ //累计已排产数量
|
|
|
+ sumQty += dto.ProductQty;
|
|
|
+ //继续排下一个工作日
|
|
|
+ workStartTime = GetNextWorkDay((int)workStartTime.DayOfWeek, workStartTime, mLCalendars);
|
|
|
}
|
|
|
- else
|
|
|
+ else// 最后一天的产能只能占用一部分
|
|
|
{
|
|
|
- //获取后续生产时间段
|
|
|
- var nextPoints = workPoints.Where(p => p.Level > curPoint.Level).ToList();
|
|
|
- //剩余需要工作时长
|
|
|
- decimal nextMins = workTime - effMins;
|
|
|
- foreach (var p in nextPoints)
|
|
|
+ //剩余需要排产的数量
|
|
|
+ decimal residueQty = workOrd.QtyOrded - sumQty;
|
|
|
+ //剩余数量生产需要时长(分钟)
|
|
|
+ decimal workTime = Math.Ceiling(residueQty / lineStart.Rate * 60);
|
|
|
+ //获取当天的工作时间段
|
|
|
+ var curCalendar = mLCalendars.FirstOrDefault(p => !string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == (int)workStartTime.DayOfWeek);
|
|
|
+ if (curCalendar == null)
|
|
|
+ {
|
|
|
+ curCalendar = mLCalendars.FirstOrDefault(p => string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == (int)workStartTime.DayOfWeek);
|
|
|
+ }
|
|
|
+ List<LineWorkPointDto> workPoints = DealWorkDayToLevels(workStartTime, curCalendar, mlqtyWorkDtls);
|
|
|
+ var curPoint = workPoints.Find(p => p.StartPoint <= workStartTime && workStartTime <= p.EndPoint);
|
|
|
+ if (curPoint == null)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ TimeSpan span = curPoint.EndPoint - workStartTime;
|
|
|
+ //当天工作时间段的有效生产时间
|
|
|
+ decimal effMins = (decimal)span.TotalMinutes;
|
|
|
+ DateTime workEndTime = workStartTime;
|
|
|
+ if (effMins >= workTime)//当前工作时间段即可满足产能
|
|
|
{
|
|
|
- if (p.WorkMinutes >= nextMins)
|
|
|
+ workEndTime = workStartTime.AddMinutes((double)workTime);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //获取后续生产时间段
|
|
|
+ var nextPoints = workPoints.Where(p => p.Level > curPoint.Level).ToList();
|
|
|
+ //剩余需要工作时长
|
|
|
+ decimal nextMins = workTime - effMins;
|
|
|
+ foreach (var p in nextPoints)
|
|
|
{
|
|
|
- workEndTime = p.StartPoint.AddMinutes((double)nextMins);
|
|
|
- break;
|
|
|
+ if (p.WorkMinutes >= nextMins)
|
|
|
+ {
|
|
|
+ workEndTime = p.StartPoint.AddMinutes((double)nextMins);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ nextMins -= p.WorkMinutes;
|
|
|
}
|
|
|
- nextMins -= p.WorkMinutes;
|
|
|
}
|
|
|
+ sumQty = workOrd.QtyOrded;
|
|
|
+ //记录生产周期
|
|
|
+ curSequences.Add(new PeriodSequenceDet
|
|
|
+ {
|
|
|
+ Domain = domain,
|
|
|
+ Line = lineStart.Line,
|
|
|
+ ItemNum = workOrd.ItemNum,
|
|
|
+ PlanDate = workStartTime.Date,
|
|
|
+ Period = dto.Period,//目前只考虑一班制
|
|
|
+ OrdQty = residueQty,
|
|
|
+ WorkOrds = workOrd.WorkOrd,
|
|
|
+ Op = lineStart.Op,
|
|
|
+ IsActive = true,
|
|
|
+ Status = "",
|
|
|
+ CreateTime = DateTime.Now
|
|
|
+ });
|
|
|
+ //记录排产记录
|
|
|
+ curScheduleRsts.Add(new ScheduleResultOpMaster
|
|
|
+ {
|
|
|
+ Domain = domain,
|
|
|
+ WorkOrd = workOrd.WorkOrd,
|
|
|
+ Line = lineStart.Line,
|
|
|
+ ItemNum = workOrd.ItemNum,
|
|
|
+ Op = lineStart.Op,
|
|
|
+ WorkDate = workStartTime.Date,
|
|
|
+ WorkQty = residueQty,
|
|
|
+ WorkStartTime = workStartTime,
|
|
|
+ WorkEndTime = workEndTime,
|
|
|
+ CreateTime = DateTime.Now
|
|
|
+ });
|
|
|
}
|
|
|
- sumQty = workOrd.QtyOrded;
|
|
|
- //记录生产周期
|
|
|
- curSequences.Add(new PeriodSequenceDet
|
|
|
- {
|
|
|
- Domain = domain,
|
|
|
- Line = item.Line,
|
|
|
- ItemNum = workOrd.ItemNum,
|
|
|
- PlanDate = workStartTime.Date,
|
|
|
- Period = 1,//目前只考虑一班制
|
|
|
- OrdQty = residueQty,
|
|
|
- WorkOrds = workOrd.WorkOrd,
|
|
|
- Op = item.Op,
|
|
|
- IsActive = true,
|
|
|
- Status = "",
|
|
|
- CreateTime = DateTime.Now
|
|
|
- });
|
|
|
- //记录排产记录
|
|
|
- curScheduleRsts.Add(new ScheduleResultOpMaster
|
|
|
- {
|
|
|
- Domain = domain,
|
|
|
- WorkOrd = workOrd.WorkOrd,
|
|
|
- Line = item.Line,
|
|
|
- ItemNum = workOrd.ItemNum,
|
|
|
- Op = item.Op,
|
|
|
- WorkDate = workStartTime.Date,
|
|
|
- WorkQty = residueQty,
|
|
|
- WorkStartTime = workStartTime,
|
|
|
- WorkEndTime = workEndTime,
|
|
|
- CreateTime = DateTime.Now
|
|
|
- });
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -463,12 +550,12 @@ namespace Business.ResourceExamineManagement
|
|
|
/// <summary>
|
|
|
/// 获取产线当天的开工时间,结束时间,有效工作时长,生产数量
|
|
|
/// </summary>
|
|
|
- /// <param name="routingDto">产线</param>
|
|
|
- /// <param name="startTime"></param>
|
|
|
+ /// <param name="rate">产线UPH</param>
|
|
|
+ /// <param name="startTime">产线排产开始时间</param>
|
|
|
/// <param name="curCalendars"></param>
|
|
|
/// <param name="curQtyDtls"></param>
|
|
|
/// <returns></returns>
|
|
|
- public LineScheduledDto GetScheduledPoint(WorkOrdRoutingDto routingDto, DateTime startTime, List<ShopCalendarWorkCtr> curCalendars, List<QualityLineWorkDetail> curQtyDtls)
|
|
|
+ public LineScheduledDto GetScheduledPoint(decimal rate, DateTime startTime, List<ShopCalendarWorkCtr> curCalendars, List<QualityLineWorkDetail> curQtyDtls)
|
|
|
{
|
|
|
LineScheduledDto scheduledDto = new LineScheduledDto();
|
|
|
//当天排产开始时间
|
|
|
@@ -476,7 +563,12 @@ namespace Business.ResourceExamineManagement
|
|
|
//开始时间是周几
|
|
|
int weekDay = (int)startTime.DayOfWeek;
|
|
|
//当天的工作日历
|
|
|
- var shopCal = curCalendars.Where(p => p.WeekDay == weekDay).First();
|
|
|
+ var shopCal = curCalendars.Where(p => !string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == weekDay).FirstOrDefault();
|
|
|
+ if (shopCal == null)//当前产线当天没有设置工作日历
|
|
|
+ {
|
|
|
+ //取默认工作日历
|
|
|
+ shopCal = curCalendars.Where(p =>string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == weekDay).FirstOrDefault();
|
|
|
+ }
|
|
|
//当前日期的工作时间段
|
|
|
List<LineWorkPointDto> workPoints = DealWorkDayToLevels(startTime, shopCal, curQtyDtls);
|
|
|
//当天排产结束时间
|
|
|
@@ -493,18 +585,69 @@ namespace Business.ResourceExamineManagement
|
|
|
scheduledDto.EffTime += (decimal)span.TotalHours;
|
|
|
}
|
|
|
//计算当天的产能
|
|
|
- scheduledDto.ProductQty = Math.Floor(scheduledDto.EffTime * routingDto.Rate);
|
|
|
+ scheduledDto.ProductQty = Math.Floor(scheduledDto.EffTime * rate);
|
|
|
+ //计算班次
|
|
|
+ scheduledDto.Period = 1;//默认一般制
|
|
|
+ if (shopCal.ShiftsStart2 != 0 && shopCal.ShiftsHours2 != 0)
|
|
|
+ {
|
|
|
+ scheduledDto.Period = 2;
|
|
|
+ }
|
|
|
return scheduledDto;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 计算主产线实际排产开始时间
|
|
|
/// </summary>
|
|
|
- /// <param name="startTime">工单排产开始时间</param>
|
|
|
+ /// <param name="workOrd">工单</param>
|
|
|
+ /// <param name="op">工序</param>
|
|
|
+ /// <param name="prodLines">生产线明细</param>
|
|
|
+ /// <param name="allResults">产线占用记录</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public LineStartDto DealStartTime(WorkOrdMaster workOrd,int op,List<ProdLineDetail> prodLines, List<ScheduleResultOpMaster> allResults)
|
|
|
+ {
|
|
|
+ DateTime actStart = DateTime.Now.Date.AddDays(1);
|
|
|
+ LineStartDto lineStart = new LineStartDto();
|
|
|
+ //获取工序对应的产线,根据优先级排序
|
|
|
+ var lines = prodLines.Where(p => p.Part == workOrd.ItemNum && p.Op == op).OrderBy(p => p.Sequence).ToList();
|
|
|
+ //获取第一条产线排产结束时间
|
|
|
+ var schedule = allResults.Where(p => p.Line == lines[0].Line).OrderByDescending(p => p.WorkEndTime).FirstOrDefault();
|
|
|
+ actStart = schedule == null ? actStart : schedule.WorkEndTime;
|
|
|
+ //计算实际开工时间
|
|
|
+ var curCalendars = calendars.Where(p => p.ProdLine == lines[0].Line).ToList();
|
|
|
+ var curQtyDtls = qualityLines.Where(p=>p.ProdLine == lines[0].Line).ToList();
|
|
|
+ actStart = CalcActStartTime(actStart, curCalendars, curQtyDtls);
|
|
|
+ lineStart.Line = lines[0].Line;
|
|
|
+ lineStart.StartTime = actStart;
|
|
|
+ lineStart.setupTime = lines[0].SetupTime;
|
|
|
+ lineStart.Rate = lines[0].Rate;
|
|
|
+ //循环其他产线
|
|
|
+ for (int i = 1; i < lines.Count; i++)
|
|
|
+ {
|
|
|
+ schedule = allResults.Where(p => p.Line == lines[i].Line).OrderByDescending(p => p.WorkEndTime).FirstOrDefault();
|
|
|
+ DateTime StartTime = schedule == null ? actStart : schedule.WorkEndTime;
|
|
|
+ //计算实际开工时间
|
|
|
+ curCalendars = calendars.Where(p => p.ProdLine == lines[i].Line).ToList();
|
|
|
+ curQtyDtls = qualityLines.Where(p => p.ProdLine == lines[i].Line).ToList();
|
|
|
+ StartTime = CalcActStartTime(StartTime, curCalendars, curQtyDtls);
|
|
|
+ if (StartTime < lineStart.StartTime)
|
|
|
+ {
|
|
|
+ lineStart.Line = lines[i].Line;
|
|
|
+ lineStart.StartTime = StartTime;
|
|
|
+ lineStart.setupTime = lines[i].SetupTime;
|
|
|
+ lineStart.Rate = lines[i].Rate;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return lineStart;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 计算主产线实际排产开始时间
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="startTime">开始时间</param>
|
|
|
/// <param name="curCalendars">当前产线工作日历</param>
|
|
|
/// <param name="curQtyDtls">当前产线休息记录</param>
|
|
|
/// <returns></returns>
|
|
|
- public DateTime DealStartTime(DateTime startTime, List<ShopCalendarWorkCtr> curCalendars, List<QualityLineWorkDetail> curQtyDtls)
|
|
|
+ public DateTime CalcActStartTime(DateTime startTime, List<ShopCalendarWorkCtr> curCalendars, List<QualityLineWorkDetail> curQtyDtls)
|
|
|
{
|
|
|
//实际排产开始时间
|
|
|
DateTime actStart = startTime;
|
|
|
@@ -519,8 +662,6 @@ namespace Business.ResourceExamineManagement
|
|
|
return actStart;
|
|
|
}
|
|
|
|
|
|
- //开始时间往后推到半小时/整点节点
|
|
|
- //actStart = CalcStartTimeAfter(actStart);
|
|
|
//当天的工作日历
|
|
|
var shopCal = curCalendars.Where(p => p.WeekDay == weekDay).First();
|
|
|
//当前日期的工作时间段
|
|
|
@@ -632,14 +773,51 @@ namespace Business.ResourceExamineManagement
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// 计算子产线实际排产开始时间
|
|
|
+ /// 计算下一产线实际排产开始时间
|
|
|
/// </summary>
|
|
|
- /// <param name="startTime">父级工单排产开始时间</param>
|
|
|
- /// <param name="setupTime">当前产线提前期(小时)-需要提前生产时长,不包括休息时间</param>
|
|
|
- /// <param name="curCalendars">当前产线工作日历</param>
|
|
|
- /// <param name="curQtyDtls">当前产线休息记录</param>
|
|
|
+ /// <param name="workOrd">工单</param>
|
|
|
+ /// <param name="lineStart">上一产线开始时间</param>
|
|
|
+ /// <param name="op">工序</param>
|
|
|
+ /// <param name="prodLines">产线明细</param>
|
|
|
+ /// <param name="allResults">产线占用记录</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public LineStartDto DealNextStartTime(WorkOrdMaster workOrd,LineStartDto lineStart,int op, List<ProdLineDetail> prodLines, List<ScheduleResultOpMaster> allResults)
|
|
|
+ {
|
|
|
+ LineStartDto startDto = new LineStartDto();
|
|
|
+ //获取产线
|
|
|
+ var lines = prodLines.Where(p => p.Part == workOrd.ItemNum && p.Op == op).OrderBy(p=>p.Sequence).ToList();
|
|
|
+ //获取第一条产线排产结束时间
|
|
|
+ var schedule = allResults.Where(p => p.Line == lines[0].Line).OrderByDescending(p => p.WorkEndTime).FirstOrDefault();
|
|
|
+ DateTime startTime = CalcStartTimeWithSetUpTime(lines[0], lineStart.StartTime, lineStart.setupTime + lines[0].OverlapTime);
|
|
|
+ startDto.Line = lines[0].Line;
|
|
|
+ startDto.setupTime = lines[0].SetupTime;
|
|
|
+ startDto.StartTime = schedule == null ? startTime : (startTime < schedule.WorkEndTime ? schedule.WorkEndTime : startTime);
|
|
|
+ startDto.Rate = lines[0].Rate;
|
|
|
+ //循环剩余产线,找到最早可开工产线
|
|
|
+ for (int i = 1; i < lines.Count(); i++)
|
|
|
+ {
|
|
|
+ schedule = allResults.Where(p => p.Line == lines[i].Line).OrderByDescending(p => p.WorkEndTime).FirstOrDefault();
|
|
|
+ startTime = CalcStartTimeWithSetUpTime(lines[i], lineStart.StartTime, lineStart.setupTime + lines[i].OverlapTime);
|
|
|
+ startTime = schedule == null ? startTime : (startTime < schedule.WorkEndTime ? schedule.WorkEndTime : startTime);
|
|
|
+ if (startTime < startDto.StartTime)
|
|
|
+ {
|
|
|
+ startDto.Line = lines[i].Line;
|
|
|
+ startDto.setupTime = lines[i].SetupTime;
|
|
|
+ startDto.StartTime = startTime;
|
|
|
+ startDto.Rate = lines[0].Rate;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return startDto;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 通过提前期计算产线排产开始时间
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="line">产线</param>
|
|
|
+ /// <param name="startTime">上一产线开始时间</param>
|
|
|
+ /// <param name="setupTime">上一产线准备时间+当前产线提前期</param>
|
|
|
/// <returns></returns>
|
|
|
- public DateTime DealChildStartTime(DateTime startTime, decimal setupTime, List<ShopCalendarWorkCtr> curCalendars, List<QualityLineWorkDetail> curQtyDtls)
|
|
|
+ public DateTime CalcStartTimeWithSetUpTime(ProdLineDetail line, DateTime startTime, decimal setupTime)
|
|
|
{
|
|
|
//提前期转换成分钟
|
|
|
decimal needMinute = setupTime * 60;
|
|
|
@@ -648,32 +826,32 @@ namespace Business.ResourceExamineManagement
|
|
|
//开始时间是周几
|
|
|
int weekDay = (int)startTime.DayOfWeek;
|
|
|
//当天的工作日历
|
|
|
- var shopCal = curCalendars.Where(p => p.WeekDay == weekDay).First();
|
|
|
+ var shopCal = calendars.Where(p => p.ProdLine == line.Line && p.WeekDay == weekDay).First();
|
|
|
+ //当前产线的休息时间设置
|
|
|
+ var curQtyDtls = qualityLines.Where(p => p.ProdLine == line.Line).ToList();
|
|
|
//当前日期的工作时间段
|
|
|
List<LineWorkPointDto> workPoints = DealWorkDayToLevels(startTime, shopCal, curQtyDtls);
|
|
|
//计算starttime处于那个工作时间段
|
|
|
var curPoint = workPoints.Where(p => startTime >= p.StartPoint && startTime <= p.EndPoint).FirstOrDefault();
|
|
|
- //当前时间段可用提前期
|
|
|
- TimeSpan span = startTime - curPoint.StartPoint;
|
|
|
+ //当前时间段可用时长
|
|
|
+ TimeSpan span = curPoint.EndPoint - startTime;
|
|
|
decimal curMins = (decimal)span.TotalMinutes;
|
|
|
- if (curMins >= needMinute)//当前时间段的可用提前期满足
|
|
|
+ if (curMins >= needMinute)//当前时间段的可用时长满足提前期
|
|
|
{
|
|
|
- actStart = startTime.AddMinutes((double)-needMinute);
|
|
|
- //开始时间往前推到半小时/整点节点
|
|
|
- actStart = CalcStartTimeBefore(actStart);
|
|
|
+ actStart = startTime.AddMinutes((double)needMinute);
|
|
|
return actStart;
|
|
|
}
|
|
|
- //当前时间段的可用提前期不满足
|
|
|
+ //当前时间段的可用时长不满足
|
|
|
//剩余提前期
|
|
|
needMinute -= curMins;
|
|
|
- //获取前层级时间段
|
|
|
- var prePoints = workPoints.Where(p => p.Level < curPoint.Level).OrderByDescending(p => p.Level).ToList();
|
|
|
+ //获取后层级时间段
|
|
|
+ var prePoints = workPoints.Where(p => p.Level > curPoint.Level).OrderBy(p => p.Level).ToList();
|
|
|
bool flag = true;//标志位
|
|
|
foreach (var item in prePoints)
|
|
|
{
|
|
|
- if (item.WorkMinutes >= needMinute)//当前时间段的可用提前期满足
|
|
|
+ if (item.WorkMinutes >= needMinute)//当前时间段的可用时长满足
|
|
|
{
|
|
|
- actStart = item.EndPoint.AddMinutes((double)-needMinute);
|
|
|
+ actStart = item.StartPoint.AddMinutes((double)needMinute);
|
|
|
flag = false;
|
|
|
break;
|
|
|
}
|
|
|
@@ -681,18 +859,17 @@ namespace Business.ResourceExamineManagement
|
|
|
}
|
|
|
if (!flag)
|
|
|
{
|
|
|
- //开始时间往前推到半小时/整点节点
|
|
|
- actStart = CalcStartTimeBefore(actStart);
|
|
|
return actStart;
|
|
|
}
|
|
|
- //今天可用提前期不够,往前工作日找
|
|
|
- DateTime perStartTime = startTime;
|
|
|
+ //今天可用时长不够,往后工作日找
|
|
|
+ DateTime nextStartTime = startTime;
|
|
|
while (flag)
|
|
|
{
|
|
|
- //获取前一个工作日
|
|
|
- perStartTime = GetPreWorkDay(perStartTime, curCalendars);
|
|
|
- //获取前一个工作日的工作时间段数据,倒序排
|
|
|
- workPoints = DealWorkDayToLevels(perStartTime, shopCal, curQtyDtls).OrderByDescending(p => p.Level).ToList();
|
|
|
+ //获取下一个工作日
|
|
|
+ nextStartTime = GetNextWorkDay(weekDay, startTime, calendars.Where(p => p.ProdLine == line.Line).ToList());
|
|
|
+ weekDay = (int)nextStartTime.DayOfWeek;
|
|
|
+ //获取前一个工作日的工作时间段数据,level顺排
|
|
|
+ workPoints = DealWorkDayToLevels(nextStartTime, calendars.Where(p=>p.ProdLine == line.Line && p.WeekDay == weekDay).First(), curQtyDtls).OrderBy(p => p.Level).ToList();
|
|
|
//当天的工作时长(分钟)
|
|
|
decimal sumWorkMins = workPoints.Sum(p => p.WorkMinutes);
|
|
|
if (sumWorkMins >= needMinute)//当天可用提前期满足
|
|
|
@@ -702,7 +879,7 @@ namespace Business.ResourceExamineManagement
|
|
|
{
|
|
|
if (item.WorkMinutes >= needMinute)//当前时间段满足
|
|
|
{
|
|
|
- actStart = item.EndPoint.AddMinutes((double)-needMinute);
|
|
|
+ actStart = item.StartPoint.AddMinutes((double)needMinute);
|
|
|
break;
|
|
|
}
|
|
|
needMinute -= item.WorkMinutes;
|
|
|
@@ -715,8 +892,6 @@ namespace Business.ResourceExamineManagement
|
|
|
needMinute -= sumWorkMins;
|
|
|
}
|
|
|
}
|
|
|
- //开始时间往前推到半小时/整点节点
|
|
|
- actStart = CalcStartTimeBefore(actStart);
|
|
|
return actStart;
|
|
|
}
|
|
|
|
|
|
@@ -734,7 +909,12 @@ namespace Business.ResourceExamineManagement
|
|
|
DateTime nextDate = startTime.Date.AddDays(1);
|
|
|
//下一天是周几
|
|
|
int nextWeekDay = (weekDay + 1) % 7;
|
|
|
- var calendar = curCalendars.FirstOrDefault(p => p.WeekDay == nextWeekDay);
|
|
|
+ //获取工作日历:先获取当前产线的工作日历,若没有维护,则获取默认工作日历
|
|
|
+ var calendar = curCalendars.FirstOrDefault(p =>!string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == nextWeekDay);
|
|
|
+ if (calendar == null)
|
|
|
+ {
|
|
|
+ calendar = curCalendars.FirstOrDefault(p => string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == nextWeekDay);
|
|
|
+ }
|
|
|
string strStart = calendar.ShiftsStart1.ToString("0.00").Replace(".", ":");
|
|
|
//判断下一天是否是工作日
|
|
|
if (nextWeekDay == 0 || nextWeekDay == 6)//下一天是周六或者周日,需要判断是否调班,需要加班
|
|
|
@@ -810,19 +990,22 @@ namespace Business.ResourceExamineManagement
|
|
|
string date = startTime.Date.ToString("yyyy-MM-dd");
|
|
|
//排产记录结束日期是周几
|
|
|
int weekDay = (int)startTime.DayOfWeek;
|
|
|
- //计算当天的开工时间点,停工时间点
|
|
|
- string strStart = shopCal.ShiftsStart1.ToString("0.00").Replace(".", ":");
|
|
|
- DateTime dayStartPoint = Convert.ToDateTime(date + " " + strStart);
|
|
|
- DateTime dayEndPoint = dayStartPoint.AddHours(Convert.ToDouble(shopCal.ShiftsHours1));
|
|
|
//工作时间段
|
|
|
List<LineWorkPointDto> workPoints = new List<LineWorkPointDto>();
|
|
|
LineWorkPointDto dto = new LineWorkPointDto();
|
|
|
- dto.Level = 1;
|
|
|
+ int level = 1;
|
|
|
+ TimeSpan span = TimeSpan.Zero;
|
|
|
+ //开始时间
|
|
|
+ string strStart = shopCal.ShiftsStart1.ToString("0.00").Replace(".", ":");
|
|
|
+ DateTime dayStartPoint = Convert.ToDateTime(date + " " + strStart);
|
|
|
+ //结束时间
|
|
|
+ DateTime dayEndPoint = CalcEndPoint(startTime, shopCal);
|
|
|
+ dto.Level = level;
|
|
|
dto.Line = shopCal.ProdLine;
|
|
|
dto.WeekDay = weekDay;
|
|
|
dto.StartPoint = dayStartPoint;
|
|
|
- int level = 1;
|
|
|
- TimeSpan span = TimeSpan.Zero;
|
|
|
+ //按照产线休息时间切分时间段
|
|
|
+ curQtyDtls = curQtyDtls.OrderBy(p => p.RestTimePoint).ToList();
|
|
|
foreach (var item in curQtyDtls)
|
|
|
{
|
|
|
DateTime endPoint = Convert.ToDateTime(date + " " + item.RestTimePoint);
|
|
|
@@ -846,51 +1029,62 @@ namespace Business.ResourceExamineManagement
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// 工单工艺路线预处理
|
|
|
+ /// 计算当前班次结束时间
|
|
|
/// </summary>
|
|
|
- /// <param name="workOrd">工单</param>
|
|
|
- /// <param name="woRuntings">当前工单对应的工序</param>
|
|
|
- /// <param name="prodLines">产线</param>
|
|
|
- /// <param name="schedules">当前工单对应产品的排产记录</param>
|
|
|
+ /// <param name="startTime"></param>
|
|
|
+ /// <param name="shopCal"></param>
|
|
|
/// <returns></returns>
|
|
|
- public List<WorkOrdRoutingDto> ProcPretreatment(WorkOrdMaster workOrd, List<WorkOrdRouting> woRuntings, List<ProdLineDetail> prodLines, List<ScheduleResultOpMaster> schedules)
|
|
|
+ public DateTime CalcEndPoint(DateTime startTime, ShopCalendarWorkCtr shopCal)
|
|
|
{
|
|
|
- List<WorkOrdRoutingDto> routingDtos = new List<WorkOrdRoutingDto>();
|
|
|
- //当前工单计划开始时间(默认加两天)
|
|
|
- DateTime planStart = workOrd.OrdDate.GetValueOrDefault();
|
|
|
- //取主工序(第一层级工序)
|
|
|
- var firsts = woRuntings.Where(p => p.ParentOp == 0 && p.MilestoneOp).OrderByDescending(p => p.OP).ToList();
|
|
|
- if (firsts.Count == 0)
|
|
|
- {
|
|
|
- return routingDtos;
|
|
|
- }
|
|
|
- WorkOrdRoutingDto dto = new WorkOrdRoutingDto();
|
|
|
- //主工序按照Op排序,取最大Op
|
|
|
- var lastOp = firsts.First();
|
|
|
- dto.ParentOp = lastOp.ParentOp;
|
|
|
- dto.level = 1;
|
|
|
- dto.Op = lastOp.OP;
|
|
|
- dto.ChdParentOps = new List<int>();
|
|
|
- //获取当前层级工序中有子级的工序集合
|
|
|
- var childs = woRuntings.Where(p => firsts.Select(m => m.OP).Contains(p.ParentOp)).Select(m => m.ParentOp).Distinct().ToList();
|
|
|
- if (childs.Count > 0)
|
|
|
+ //年-月-日
|
|
|
+ string date = startTime.Date.ToString("yyyy-MM-dd");
|
|
|
+ string strStart = "";
|
|
|
+ DateTime dayStartPoint = DateTime.Now;
|
|
|
+ DateTime dayEndPoint = DateTime.Now;
|
|
|
+ if (shopCal.ShiftsStart2 != 0 && shopCal.ShiftsHours2 != 0)//设置了第二班
|
|
|
{
|
|
|
- dto.ChdParentOps = childs;
|
|
|
+ strStart = shopCal.ShiftsStart2.ToString("0.00").Replace(".", ":");
|
|
|
+ dayStartPoint = Convert.ToDateTime(date + " " + strStart);
|
|
|
+ dayEndPoint = dayStartPoint.AddHours(Convert.ToDouble(shopCal.ShiftsHours2));
|
|
|
+ return dayEndPoint;
|
|
|
}
|
|
|
- //主工序对应的产线(目前只考虑一个产品对应一条产线的情况)
|
|
|
- var line = prodLines.Where(p => p.Part == lastOp.ItemNum && p.Op == lastOp.OP).FirstOrDefault();
|
|
|
- if (line != null)
|
|
|
+ strStart = shopCal.ShiftsStart1.ToString("0.00").Replace(".", ":");
|
|
|
+ dayStartPoint = Convert.ToDateTime(date + " " + strStart);
|
|
|
+ dayEndPoint = dayStartPoint.AddHours(Convert.ToDouble(shopCal.ShiftsHours1));
|
|
|
+ return dayEndPoint;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 计算第一条产线开始时间
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="workOrd">工单</param>
|
|
|
+ /// <param name="op">关键工序</param>
|
|
|
+ /// <param name="prodLines">产线明细</param>
|
|
|
+ /// <param name="scheduleResults">排产结果</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public LineStartDto CalcLineStart(WorkOrdMaster workOrd, int op, List<ProdLineDetail> prodLines, List<ScheduleResultOpMaster> scheduleResults)
|
|
|
+ {
|
|
|
+ LineStartDto dto = new LineStartDto();
|
|
|
+ //获取工序对应的产线,根据优先级排序
|
|
|
+ var lines = prodLines.Where(p => p.Part == workOrd.ItemNum && p.Op == op).OrderBy(p=>p.Sequence).ToList();
|
|
|
+ //第一条产线:使用工单OrdDate计算开始排产时间,不需要考虑提前期
|
|
|
+ //获取当前产线排产结束时间
|
|
|
+ var schedule = scheduleResults.Where(p => p.Line == lines[0].Line).OrderByDescending(p => p.WorkEndTime).FirstOrDefault();
|
|
|
+ dto.Line = lines[0].Line;
|
|
|
+ dto.Op = op;
|
|
|
+ dto.StartTime = schedule == null ? workOrd.OrdDate.GetValueOrDefault() : (schedule.WorkEndTime <= workOrd.OrdDate ? workOrd.OrdDate.GetValueOrDefault() : schedule.WorkEndTime);
|
|
|
+ //循环其他产线
|
|
|
+ for (int i = 1; i < lines.Count; i++)
|
|
|
{
|
|
|
- dto.Line = line.Line;
|
|
|
- dto.Rate = line.Rate;
|
|
|
- dto.SetupTime = 0;
|
|
|
- //获取产线占用结束时间
|
|
|
- var schedule = schedules.Where(p => p.Line == line.Line).OrderByDescending(p => p.WorkEndTime).FirstOrDefault();
|
|
|
- dto.StartTime = schedule == null ? planStart : schedule.WorkEndTime <= planStart ? planStart : schedule.WorkEndTime;
|
|
|
+ schedule = scheduleResults.Where(p => p.Line == lines[i].Line).OrderByDescending(p => p.WorkEndTime).FirstOrDefault();
|
|
|
+ DateTime StartTime = schedule == null ? workOrd.OrdDate.GetValueOrDefault() : (schedule.WorkEndTime <= workOrd.OrdDate ? workOrd.OrdDate.GetValueOrDefault() : schedule.WorkEndTime);
|
|
|
+ if (StartTime < dto.StartTime)
|
|
|
+ {
|
|
|
+ dto.Line = lines[i].Line;
|
|
|
+ dto.StartTime = StartTime;
|
|
|
+ }
|
|
|
}
|
|
|
- routingDtos.Add(dto);
|
|
|
-
|
|
|
- return routingDtos;
|
|
|
+ return dto;
|
|
|
}
|
|
|
}
|
|
|
}
|