|
|
@@ -197,7 +197,7 @@ namespace Business.ResourceExamineManagement
|
|
|
decimal lockDays = generalizedCodeMaster != null ? generalizedCodeMaster.UDeci1 : 0;
|
|
|
|
|
|
//获取需要排产的工单(获取四周的工单:正常工单+已审批通过的特殊工单)
|
|
|
- DateTime endDate = DateTime.Now.Date.AddWeeks(4).AddDays(1);
|
|
|
+ DateTime endDate = DateTime.Now.Date.AddDays(28).AddDays(1);
|
|
|
//取数开始时间需要排除掉锁定期内的工单
|
|
|
DateTime startDate = DateTime.Now.Date.AddDays(1).AddDays((double)lockDays);
|
|
|
var workOrds = _workOrdMaster.Select(p => p.IsActive && p.Domain == domain && p.OrdDate < endDate && p.OrdDate >= startDate && string.IsNullOrEmpty(p.Status) && (string.IsNullOrEmpty(p.Typed) || (!string.IsNullOrEmpty(p.Typed) && p.BusinessID >0 ))).ToList();
|
|
|
@@ -309,7 +309,7 @@ namespace Business.ResourceExamineManagement
|
|
|
List<WorkOrdMstDto> workDtos = new List<WorkOrdMstDto>();
|
|
|
foreach (var item in notSchedules)
|
|
|
{
|
|
|
- int op = tsWoRoutings.Where(p => p.WorkOrd == item.WorkOrd).OrderByDescending(p => p.OP).First().OP;
|
|
|
+ var curOp = tsWoRoutings.Where(p => p.WorkOrd == item.WorkOrd).OrderByDescending(p => p.OP).First();
|
|
|
workDtos.Add(new WorkOrdMstDto
|
|
|
{
|
|
|
WorkOrd = item.WorkOrd,
|
|
|
@@ -320,7 +320,8 @@ namespace Business.ResourceExamineManagement
|
|
|
LbrVar = item.LbrVar * 60,
|
|
|
Worked = 0,
|
|
|
QtyWorked = 0,
|
|
|
- Op = op
|
|
|
+ Op = curOp.OP,
|
|
|
+ WaitTime = curOp.WaitTime * 60
|
|
|
});
|
|
|
}
|
|
|
TsLineSchedule(workDtos, periodSequenceDtls, scheduleMasters);
|
|
|
@@ -567,24 +568,42 @@ namespace Business.ResourceExamineManagement
|
|
|
//记录特殊工单:获取第一天是否有特殊工单
|
|
|
List<WorkOrdMaster> fstWOMasters = tsWorkOrds.Where(p => p.ProdLine == lineStart.Line && p.OrdDate.Value.Date == workStartTime.Date).OrderBy(p => p.OrdDate).ToList();
|
|
|
List<WorkOrdMstDto> workDtos = new List<WorkOrdMstDto>();
|
|
|
- foreach (var item in fstWOMasters)
|
|
|
- {
|
|
|
- int op = tsWoRoutings.Where(p => p.WorkOrd == item.WorkOrd).OrderByDescending(p => p.OP).First().OP;
|
|
|
- workDtos.Add(new WorkOrdMstDto{
|
|
|
- WorkOrd = item.WorkOrd,
|
|
|
- ItemNum = item.ItemNum,
|
|
|
- QtyOrded = item.QtyOrded,
|
|
|
- LbrVar = item.LbrVar * 60,
|
|
|
- Worked = 0,
|
|
|
- QtyWorked = 0,
|
|
|
- Op = op
|
|
|
- });
|
|
|
- }
|
|
|
//记录排产开始第二天及以后安排的特殊工单
|
|
|
var secWOMasters = new List<WorkOrdMaster>();
|
|
|
- //特殊工单工作时长(分钟)
|
|
|
- decimal sumTsTimes = fstWOMasters.Sum(p => p.LbrVar) * 60;
|
|
|
- while (sumTsTimes > 0) //产线排产开始当天安排了特殊工单,则先安排特殊工单
|
|
|
+ //特殊工单总清场时长(分钟)
|
|
|
+ decimal sumCleanTimes = 0m;
|
|
|
+ //最后一个特殊工单的清场时长(分钟)
|
|
|
+ decimal lstCleanTime = 0m;
|
|
|
+ //新增特殊工单最后一个清场时长
|
|
|
+ decimal secCleanTime = 0m;
|
|
|
+ if (fstWOMasters.Any())
|
|
|
+ {
|
|
|
+ foreach (var item in fstWOMasters)
|
|
|
+ {
|
|
|
+ var curOp = tsWoRoutings.Where(p => p.WorkOrd == item.WorkOrd).OrderByDescending(p => p.OP).First();
|
|
|
+ workDtos.Add(new WorkOrdMstDto
|
|
|
+ {
|
|
|
+ WorkOrd = item.WorkOrd,
|
|
|
+ ItemNum = item.ItemNum,
|
|
|
+ QtyOrded = item.QtyOrded,
|
|
|
+ LbrVar = item.LbrVar * 60,
|
|
|
+ Worked = 0,
|
|
|
+ QtyWorked = 0,
|
|
|
+ Op = curOp.OP,
|
|
|
+ WaitTime = curOp.WaitTime * 60
|
|
|
+ });
|
|
|
+ sumCleanTimes += curOp.WaitTime * 60;
|
|
|
+ }
|
|
|
+ //获取最后一个特殊工单的清场时长
|
|
|
+ var last = fstWOMasters.Last();
|
|
|
+ lstCleanTime = tsWoRoutings.Where(p => p.WorkOrd == last.WorkOrd).OrderByDescending(p => p.OP).First().WaitTime * 60;
|
|
|
+ }
|
|
|
+ //特殊工单排产需要考虑的时长=特殊工单工作时长(分钟)+除最后一个特殊工单之外的清场时长
|
|
|
+ decimal sumTsTimes = fstWOMasters.Sum(p => p.LbrVar) * 60 + sumCleanTimes - lstCleanTime;
|
|
|
+ //工单排产第一天标识
|
|
|
+ bool isFstDay = true;
|
|
|
+ //产线排产开始当天安排了特殊工单,则先安排特殊工单
|
|
|
+ while (sumTsTimes > 0)
|
|
|
{
|
|
|
secWOMasters.Clear();
|
|
|
//获取当天的产能
|
|
|
@@ -596,67 +615,130 @@ namespace Business.ResourceExamineManagement
|
|
|
curCalendar = mLCalendars.FirstOrDefault(p => string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == (int)workStartTime.DayOfWeek);
|
|
|
}
|
|
|
List<LineWorkPointDto> workPoints = DealWorkDayToLevels(lineStart.Line, workStartTime, curCalendar, mlqtyWorkDtls);
|
|
|
- //如果当天的可用产能大于特殊工单生产时长,此时需要考虑当天是否安排了其他的特殊工单
|
|
|
- if (dto.EffTime > sumTsTimes)
|
|
|
+ //特殊工单排产第一天之后:如果当天的可用产能大于特殊工单生产时长,此时需要考虑当天是否安排了其他的特殊工单
|
|
|
+ if (dto.EffTime > sumTsTimes && !isFstDay)
|
|
|
{
|
|
|
//获取特殊工单
|
|
|
secWOMasters = tsWorkOrds.Where(p => p.ProdLine == lineStart.Line && p.OrdDate.Value.Date == workStartTime.Date).OrderBy(p => p.OrdDate).ToList();
|
|
|
- //此时需要过滤掉第一天的工单
|
|
|
- secWOMasters = secWOMasters.Where(p=> !workDtos.Select(m=>m.WorkOrd).Contains(p.WorkOrd)).ToList();
|
|
|
- //记录新增待排产特殊工单
|
|
|
- foreach (var item in secWOMasters)
|
|
|
+ if (secWOMasters.Any())
|
|
|
{
|
|
|
- int op = tsWoRoutings.Where(p => p.WorkOrd == item.WorkOrd).OrderByDescending(p => p.OP).First().OP;
|
|
|
- workDtos.Add(new WorkOrdMstDto
|
|
|
+ sumCleanTimes = 0m;
|
|
|
+ //新增特殊工单最后一个清场时长
|
|
|
+ secCleanTime = 0m;
|
|
|
+ //记录新增待排产特殊工单
|
|
|
+ foreach (var item in secWOMasters)
|
|
|
{
|
|
|
- WorkOrd = item.WorkOrd,
|
|
|
- ItemNum = item.ItemNum,
|
|
|
- QtyOrded = item.QtyOrded,
|
|
|
- LbrVar = item.LbrVar * 60,
|
|
|
- Worked = 0,
|
|
|
- QtyWorked = 0,
|
|
|
- Op = op
|
|
|
- });
|
|
|
+ var curOp = tsWoRoutings.Where(p => p.WorkOrd == item.WorkOrd).OrderByDescending(p => p.OP).First();
|
|
|
+ workDtos.Add(new WorkOrdMstDto
|
|
|
+ {
|
|
|
+ WorkOrd = item.WorkOrd,
|
|
|
+ ItemNum = item.ItemNum,
|
|
|
+ QtyOrded = item.QtyOrded,
|
|
|
+ LbrVar = item.LbrVar * 60,
|
|
|
+ Worked = 0,
|
|
|
+ QtyWorked = 0,
|
|
|
+ Op = curOp.OP,
|
|
|
+ WaitTime = curOp.WaitTime * 60
|
|
|
+ });
|
|
|
+ sumCleanTimes += curOp.WaitTime * 60;
|
|
|
+ }
|
|
|
+ //获取最后一个特殊工单的清场时长
|
|
|
+ var last = secWOMasters.Last();
|
|
|
+ secCleanTime = tsWoRoutings.Where(p => p.WorkOrd == last.WorkOrd).OrderByDescending(p => p.OP).First().WaitTime * 60;
|
|
|
+ //特殊工单待排产时长=前一天特殊工单到最后一个清场时长+新增的特殊工单生产时长+新增特殊工单除最后一个清场时长之外的清场时长之和
|
|
|
+ sumTsTimes += (lstCleanTime + secWOMasters.Sum(p => p.LbrVar) * 60 + sumCleanTimes - secCleanTime);
|
|
|
+ lstCleanTime = secCleanTime;
|
|
|
}
|
|
|
- //特殊工单待排产时长增加新增的特殊工单生产时长
|
|
|
- sumTsTimes += secWOMasters.Sum(p => p.LbrVar) * 60;
|
|
|
}
|
|
|
- if (dto.EffTime >= sumTsTimes)//当天的可用生产时长满足特殊工单生产时长
|
|
|
+ //当天的可用生产时长满足特殊工单生产时长+清场时间(最后一个工单清场时间除外)
|
|
|
+ if (dto.EffTime >= sumTsTimes)
|
|
|
{
|
|
|
+ //可用生产时长(分钟)
|
|
|
+ decimal remainTime = dto.EffTime;
|
|
|
DateTime beginTime = workStartTime;
|
|
|
DateTime endTime = dto.EndTime;
|
|
|
+ //获取最后一个工单
|
|
|
+ var lastWork = workDtos.Last();
|
|
|
+ //开始或结束时间所处时间段
|
|
|
+ var curPoint = new LineWorkPointDto();
|
|
|
+ //特殊工单排产
|
|
|
foreach (var item in workDtos)
|
|
|
{
|
|
|
- if (item.LbrVar == item.Worked)//当前工单已排产,跳过
|
|
|
+ //当前工单已排产,跳过
|
|
|
+ if (item.LbrVar == item.Worked)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
- //当前工单还需工作时长
|
|
|
- decimal needTime = item.LbrVar - item.Worked;
|
|
|
- //计算工单排产结束时间
|
|
|
- var curPoint = workPoints.Find(p => p.StartPoint <= beginTime && beginTime <= p.EndPoint);
|
|
|
- span = curPoint.EndPoint - beginTime;
|
|
|
- //当天工作时间段的有效生产时间(分钟)
|
|
|
- decimal effMins = (decimal)span.TotalMinutes;
|
|
|
- if (effMins >= needTime)//当前工作时间段即可满足产能
|
|
|
+ //当前工单排产需要时长
|
|
|
+ decimal needTime = 0m;
|
|
|
+ //最后一个特殊工单
|
|
|
+ if (item.WorkOrd == lastWork.WorkOrd)
|
|
|
{
|
|
|
- endTime = beginTime.AddMinutes((double)needTime);
|
|
|
+ //最后一个工单的生产时长+清场时长
|
|
|
+ needTime = lastWork.QtyOrded - lastWork.QtyWorked + lastWork.WaitTime;
|
|
|
+ //剩余可用工作时长满足最后一个特殊工单的生产时长+清场时长
|
|
|
+ if (remainTime >= needTime)
|
|
|
+ {
|
|
|
+ //获取排产结束时间所处以及之后的生产时间段
|
|
|
+ var nextPoints = workPoints.Where(p => p.Level >= curPoint.Level).OrderBy(p => p.Level).ToList();
|
|
|
+ //处理第一个时间段的开始时间
|
|
|
+ nextPoints[0].StartPoint = beginTime;
|
|
|
+ foreach (var p in nextPoints)
|
|
|
+ {
|
|
|
+ span = p.EndPoint - p.StartPoint;
|
|
|
+ //当前工作时间段的有效生产时间
|
|
|
+ decimal effMins = (decimal)span.TotalMinutes;
|
|
|
+ if (effMins >= needTime)
|
|
|
+ {
|
|
|
+ endTime = p.StartPoint.AddMinutes((double)needTime);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ needTime -= effMins;
|
|
|
+ }
|
|
|
+ remainTime -= needTime;
|
|
|
+ }
|
|
|
+ //剩余可用工作时长不能满足清场时长
|
|
|
+ else
|
|
|
+ {
|
|
|
+ endTime = dto.EndTime;
|
|
|
+ //还需排产的清场时间
|
|
|
+ decimal qcTime = needTime - remainTime;
|
|
|
+ endTime.AddMinutes((double)qcTime);
|
|
|
+ remainTime = 0;
|
|
|
+ }
|
|
|
+ //最后一个工单的清场时长
|
|
|
+ lstCleanTime = 0m;
|
|
|
}
|
|
|
- else
|
|
|
- {
|
|
|
- //获取后续生产时间段
|
|
|
- var nextPoints = workPoints.Where(p => p.Level > curPoint.Level).OrderBy(p => p.Level).ToList();
|
|
|
- //剩余需要工作时长
|
|
|
- decimal nextMins = needTime - effMins;
|
|
|
- foreach (var p in nextPoints)
|
|
|
+ //最后一个特殊工单之前的工单:剩余排产时长和清场时间全部排产
|
|
|
+ else {
|
|
|
+ //当前工单还需工作时长+工单的清场时长
|
|
|
+ needTime = item.LbrVar - item.Worked + item.WaitTime;
|
|
|
+ //计算工单排产结束时间
|
|
|
+ curPoint = workPoints.Find(p => p.StartPoint <= beginTime && beginTime <= p.EndPoint);
|
|
|
+ span = curPoint.EndPoint - beginTime;
|
|
|
+ //当天工作时间段的有效生产时间(分钟)
|
|
|
+ decimal effMins = (decimal)span.TotalMinutes;
|
|
|
+ if (effMins >= needTime)//当前工作时间段即可满足产能
|
|
|
+ {
|
|
|
+ endTime = beginTime.AddMinutes((double)needTime);
|
|
|
+ }
|
|
|
+ else
|
|
|
{
|
|
|
- if (p.WorkMinutes >= nextMins)
|
|
|
+ //获取后续生产时间段
|
|
|
+ var nextPoints = workPoints.Where(p => p.Level > curPoint.Level).OrderBy(p => p.Level).ToList();
|
|
|
+ //剩余需要工作时长
|
|
|
+ decimal nextMins = needTime - effMins;
|
|
|
+ foreach (var p in nextPoints)
|
|
|
{
|
|
|
- endTime = p.StartPoint.AddMinutes((double)nextMins);
|
|
|
- break;
|
|
|
+ if (p.WorkMinutes >= nextMins)
|
|
|
+ {
|
|
|
+ endTime = p.StartPoint.AddMinutes((double)nextMins);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ nextMins -= p.WorkMinutes;
|
|
|
}
|
|
|
- nextMins -= p.WorkMinutes;
|
|
|
}
|
|
|
+ remainTime -= needTime;
|
|
|
}
|
|
|
//记录生产周期
|
|
|
curSequences.Add(new PeriodSequenceDet
|
|
|
@@ -688,54 +770,70 @@ namespace Business.ResourceExamineManagement
|
|
|
CreateTime = DateTime.Now
|
|
|
});
|
|
|
//下一工单开始时间=当前工单结束时间,如果位于工作区间结尾,则为下一工作区间开始时间
|
|
|
- curPoint = workPoints.Find(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
|
|
|
- if (endTime == curPoint.EndPoint)//结束时间位于工作区间结尾
|
|
|
+ curPoint = workPoints.FirstOrDefault(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
|
|
|
+ //结束时间位于工作区间结尾
|
|
|
+ if (curPoint != null && endTime == curPoint.EndPoint)
|
|
|
{
|
|
|
//获取后续生产时间段
|
|
|
- var nextPoint = workPoints.Where(p => p.Level == curPoint.Level + 1).FirstOrDefault();
|
|
|
- if (nextPoint != null)//存在后续工作区间
|
|
|
+ curPoint = workPoints.Where(p => p.Level == curPoint.Level + 1).FirstOrDefault();
|
|
|
+ //存在后续工作区间
|
|
|
+ if (curPoint != null)
|
|
|
{
|
|
|
- endTime = nextPoint.StartPoint;
|
|
|
+ endTime = curPoint.StartPoint;
|
|
|
}
|
|
|
}
|
|
|
beginTime = endTime;
|
|
|
//工单排产完成,排产时长=工单工作时长
|
|
|
item.Worked = item.LbrVar;
|
|
|
item.QtyWorked = item.QtyOrded;
|
|
|
- sumTsTimes -= needTime;
|
|
|
}
|
|
|
- if (dto.EffTime == sumTsTimes)//当天产能完全占用
|
|
|
+ //当天产能完全占用,且清场时间在下班后
|
|
|
+ if (curPoint == null)
|
|
|
{
|
|
|
sumTsTimes = 0;//排产完毕,特殊工单时长置0
|
|
|
//获取下一个工作日
|
|
|
workStartTime = GetNextWorkDay((int)workStartTime.DayOfWeek, workStartTime, mLCalendars);
|
|
|
+ isFstDay = true;
|
|
|
//特殊工单排产完成,占用了当天的全部产能,则需要判断下一个工作日是否存在特殊工单,如果存在,则需要继续排特殊工单
|
|
|
secWOMasters = tsWorkOrds.Where(p => p.ProdLine == lineStart.Line && p.OrdDate.Value.Date == workStartTime.Date).OrderBy(p => p.OrdDate).ToList();
|
|
|
- //此时需要过滤掉已排产的工单
|
|
|
- secWOMasters = secWOMasters.Where(p => !workDtos.Select(m => m.WorkOrd).Contains(p.WorkOrd)).ToList();
|
|
|
//记录新增待排产特殊工单
|
|
|
- foreach (var item in secWOMasters)
|
|
|
+ if (secWOMasters.Any())
|
|
|
{
|
|
|
- int op = tsWoRoutings.Where(p => p.WorkOrd == item.WorkOrd).OrderByDescending(p => p.OP).First().OP;
|
|
|
- workDtos.Add(new WorkOrdMstDto
|
|
|
+ sumCleanTimes = 0m;
|
|
|
+ //新增特殊工单最后一个清场时长(分钟)
|
|
|
+ secCleanTime = 0m;
|
|
|
+ foreach (var item in secWOMasters)
|
|
|
{
|
|
|
- WorkOrd = item.WorkOrd,
|
|
|
- ItemNum = item.ItemNum,
|
|
|
- QtyOrded = item.QtyOrded,
|
|
|
- LbrVar = item.LbrVar * 60,
|
|
|
- Worked = 0,
|
|
|
- QtyWorked = 0,
|
|
|
- Op = op
|
|
|
- });
|
|
|
+ var curOp = tsWoRoutings.Where(p => p.WorkOrd == item.WorkOrd).OrderByDescending(p => p.OP).First();
|
|
|
+ workDtos.Add(new WorkOrdMstDto
|
|
|
+ {
|
|
|
+ WorkOrd = item.WorkOrd,
|
|
|
+ ItemNum = item.ItemNum,
|
|
|
+ QtyOrded = item.QtyOrded,
|
|
|
+ LbrVar = item.LbrVar * 60,
|
|
|
+ Worked = 0,
|
|
|
+ QtyWorked = 0,
|
|
|
+ Op = curOp.OP,
|
|
|
+ WaitTime = curOp.WaitTime * 60
|
|
|
+ });
|
|
|
+ sumCleanTimes += curOp.WaitTime * 60;
|
|
|
+ }
|
|
|
+ //获取最后一个特殊工单的清场时长
|
|
|
+ var last = secWOMasters.Last();
|
|
|
+ secCleanTime = tsWoRoutings.Where(p => p.WorkOrd == last.WorkOrd).OrderByDescending(p => p.OP).First().WaitTime * 60;
|
|
|
+ //特殊工单待排产时长=前一天特殊工单到最后一个清场时长+新增的特殊工单生产时长+新增特殊工单除最后一个清场时长之外的清场时长之和
|
|
|
+ sumTsTimes += (lstCleanTime + secWOMasters.Sum(p => p.LbrVar) * 60 + sumCleanTimes - secCleanTime);
|
|
|
+ lstCleanTime = secCleanTime;
|
|
|
}
|
|
|
- //特殊工单待排产时长增加新增带排产特殊工单生产时长
|
|
|
- sumTsTimes += secWOMasters.Sum(p => p.LbrVar) * 60;
|
|
|
}
|
|
|
- else {//当天可用生产时长大于特殊工单生产时长
|
|
|
- sumTsTimes = 0;//排产完毕,特殊工单时长置0
|
|
|
+ //当天可用生产时长大于特殊工单生产时长+清场时长
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //排产完毕,特殊工单时长置0
|
|
|
+ sumTsTimes = 0;
|
|
|
//处理workStartTime
|
|
|
workStartTime = endTime;
|
|
|
- var curPoint = workPoints.Find(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
|
|
|
+ curPoint = workPoints.Find(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
|
|
|
if (endTime == curPoint.EndPoint)
|
|
|
{
|
|
|
var nextPoint = workPoints.Find(p => p.Level == curPoint.Level + 1);
|
|
|
@@ -746,7 +844,8 @@ namespace Business.ResourceExamineManagement
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- else//当天的可用产能不满足特殊工单生产时长,则当天产能全部排特殊工单
|
|
|
+ //当天的可用产能不满足特殊工单生产时长,则当天产能全部排特殊工单(至少最后一个特殊工单的生产时长不能满足)
|
|
|
+ else
|
|
|
{
|
|
|
decimal residueTime = dto.EffTime;//当天产能剩余产能(分钟)
|
|
|
DateTime beginTime = workStartTime;//排产开始时间
|
|
|
@@ -759,7 +858,8 @@ namespace Business.ResourceExamineManagement
|
|
|
}
|
|
|
//当前工单剩余待排产时长(分钟)
|
|
|
decimal needTime = item.LbrVar - item.Worked;
|
|
|
- if (residueTime >= needTime)//当天剩余产能满足当前工单的剩余待排产时长
|
|
|
+ //当天剩余产能满足当前工单的剩余待排产时长
|
|
|
+ if (residueTime >= needTime)
|
|
|
{
|
|
|
//计算工单排产结束时间
|
|
|
var curPoint = workPoints.Find(p => p.StartPoint <= beginTime && beginTime <= p.EndPoint);
|
|
|
@@ -786,6 +886,50 @@ namespace Business.ResourceExamineManagement
|
|
|
nextMins -= p.WorkMinutes;
|
|
|
}
|
|
|
}
|
|
|
+ //当天剩余产能
|
|
|
+ residueTime -= needTime;
|
|
|
+ //处理清场时间,两种场景:
|
|
|
+ //1、residueTime<=item.WaitTime,结束时间加上剩余清场时长
|
|
|
+ if (residueTime <= item.WaitTime)
|
|
|
+ {
|
|
|
+ decimal otherTime = item.WaitTime - residueTime;
|
|
|
+ endTime = dto.EndTime.AddMinutes((double)otherTime);
|
|
|
+ residueTime = 0;
|
|
|
+ }
|
|
|
+ //2、residueTime>item.WaitTime,剩余时长大于,清场时长,需要过滤休息时间
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //清场时长
|
|
|
+ needTime = item.WaitTime;
|
|
|
+ //获取工单排产结束时间所处时间段
|
|
|
+ curPoint = workPoints.Find(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
|
|
|
+ span = curPoint.EndPoint - endTime;
|
|
|
+ //当前工作时间段的有效生产时间(分钟)
|
|
|
+ effMins = (decimal)span.TotalMinutes;
|
|
|
+ //当前工作时间段即可清场时长
|
|
|
+ if (effMins >= needTime)
|
|
|
+ {
|
|
|
+ endTime = endTime.AddMinutes((double)needTime);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //获取后续生产时间段
|
|
|
+ var nextPoints = workPoints.Where(p => p.Level > curPoint.Level).OrderBy(p => p.Level).ToList();
|
|
|
+ //剩余需要工作时长
|
|
|
+ decimal nextMins = needTime - effMins;
|
|
|
+ foreach (var p in nextPoints)
|
|
|
+ {
|
|
|
+ if (p.WorkMinutes >= nextMins)
|
|
|
+ {
|
|
|
+ endTime = p.StartPoint.AddMinutes((double)nextMins);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ nextMins -= p.WorkMinutes;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ residueTime -= needTime;
|
|
|
+ }
|
|
|
+
|
|
|
//记录生产周期
|
|
|
curSequences.Add(new PeriodSequenceDet
|
|
|
{
|
|
|
@@ -815,27 +959,28 @@ namespace Business.ResourceExamineManagement
|
|
|
WorkEndTime = endTime,
|
|
|
CreateTime = DateTime.Now
|
|
|
});
|
|
|
+ //当前工单已排产完成,已排产时间=工单生产时长,已排产数量=工单数量
|
|
|
+ item.Worked = item.LbrVar;
|
|
|
+ item.QtyWorked = item.QtyWorked;
|
|
|
+
|
|
|
beginTime = endTime;
|
|
|
+ //获取结束时间所处时间段
|
|
|
curPoint = workPoints.Find(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
|
|
|
- if (endTime == curPoint.EndPoint)
|
|
|
+ if (curPoint != null && endTime == curPoint.EndPoint)
|
|
|
{
|
|
|
var nextPoint = workPoints.Find(p => p.Level == curPoint.Level + 1);
|
|
|
if (nextPoint != null)
|
|
|
{
|
|
|
- beginTime = nextPoint.StartPoint;
|
|
|
+ endTime = nextPoint.StartPoint;
|
|
|
}
|
|
|
+ beginTime = endTime;
|
|
|
}
|
|
|
- //当前工单已排产完成,已排产时间=工单生产时长,已排产数量=工单数量
|
|
|
- item.Worked = item.LbrVar;
|
|
|
- item.QtyWorked = item.QtyWorked;
|
|
|
- //当天剩余产能
|
|
|
- residueTime -= needTime;
|
|
|
- if (residueTime == 0)
|
|
|
- {
|
|
|
+ else {
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
- else//当天剩余产能不满足当前工单的剩余待排产时长
|
|
|
+ //当天剩余产能不满足当前工单的剩余待排产时长
|
|
|
+ else
|
|
|
{
|
|
|
//计算生产数量
|
|
|
decimal qty = Math.Ceiling(residueTime / item.LbrVar * item.QtyOrded);
|
|
|
@@ -871,13 +1016,14 @@ namespace Business.ResourceExamineManagement
|
|
|
item.Worked += residueTime;
|
|
|
item.QtyWorked += qty;
|
|
|
residueTime = 0;
|
|
|
+ //特殊工单剩余待排产时长(分钟)
|
|
|
+ sumTsTimes -= residueTime;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
- //特殊工单剩余待排产时长(分钟)
|
|
|
- sumTsTimes -= dto.EffTime;
|
|
|
//获取下一个工作日
|
|
|
workStartTime = GetNextWorkDay((int)workStartTime.DayOfWeek, workStartTime, mLCalendars);
|
|
|
+ isFstDay = false;
|
|
|
}
|
|
|
}
|
|
|
//记录已排产特殊工单
|
|
|
@@ -891,8 +1037,8 @@ namespace Business.ResourceExamineManagement
|
|
|
fstWOMasters.Clear();
|
|
|
workDtos.Clear();
|
|
|
sumTsTimes = 0m;
|
|
|
- //正常工单排产第一天标识
|
|
|
- bool isFstDay = true;
|
|
|
+ //工单排产第一天标识
|
|
|
+ isFstDay = true;
|
|
|
//前一天是否有特殊工单未排产完全
|
|
|
bool isFullPC = true;
|
|
|
while (sumQty < workOrd.QtyOrded || sumTsTimes > 0)
|
|
|
@@ -2593,7 +2739,7 @@ namespace Business.ResourceExamineManagement
|
|
|
{
|
|
|
foreach (var item in workOrds)
|
|
|
{
|
|
|
- //工单的生产时长(分钟)
|
|
|
+ //工单生产时长(分钟)
|
|
|
decimal sumTimes = item.LbrVar;
|
|
|
//工单的排产开始时间
|
|
|
DateTime workStartTime = item.OrdDate;
|
|
|
@@ -2619,7 +2765,7 @@ namespace Business.ResourceExamineManagement
|
|
|
//获取当天的产能
|
|
|
LineScheduledDto dto = GetScheduledPoint(lineStart, workStartTime, mLCalendars, mlqtyWorkDtls);
|
|
|
//当天的可用生产时长不能满足特殊工单生产时长
|
|
|
- if (dto.EffTime <= sumTimes)
|
|
|
+ if (dto.EffTime < sumTimes)
|
|
|
{
|
|
|
decimal qty = Math.Ceiling(dto.EffTime / item.LbrVar * item.QtyOrded);
|
|
|
//记录生产周期
|
|
|
@@ -2655,14 +2801,19 @@ namespace Business.ResourceExamineManagement
|
|
|
sumTimes -= dto.EffTime;
|
|
|
//已排产数量
|
|
|
item.QtyWorked += qty;
|
|
|
+ item.Worked += dto.EffTime;
|
|
|
//继续排下一个工作日
|
|
|
workStartTime = GetNextWorkDay((int)workStartTime.DayOfWeek, workStartTime, mLCalendars);
|
|
|
}
|
|
|
- else// 最后一天的产能只能占用一部分
|
|
|
+ //最后一天的产能全部占用或只能占用一部分
|
|
|
+ else
|
|
|
{
|
|
|
//剩余生产时长(分钟)
|
|
|
decimal workTime = sumTimes;
|
|
|
+ //排产开始时间位于哪个时间段
|
|
|
var curPoint = workPoints.Find(p => p.StartPoint <= workStartTime && workStartTime <= p.EndPoint);
|
|
|
+ //结束时间位于时间段
|
|
|
+ var lastPoint = new LineWorkPointDto();
|
|
|
TimeSpan span = curPoint.EndPoint - workStartTime;
|
|
|
//当前工作时间段的有效生产时间
|
|
|
decimal effMins = (decimal)span.TotalMinutes;
|
|
|
@@ -2681,12 +2832,45 @@ namespace Business.ResourceExamineManagement
|
|
|
{
|
|
|
if (p.WorkMinutes >= nextMins)
|
|
|
{
|
|
|
+ //记录结束时间位于哪个时间段
|
|
|
+ lastPoint = p;
|
|
|
workEndTime = p.StartPoint.AddMinutes((double)nextMins);
|
|
|
break;
|
|
|
}
|
|
|
nextMins -= p.WorkMinutes;
|
|
|
}
|
|
|
}
|
|
|
+ //计算清场时间
|
|
|
+ //剩余可用工作时长(分钟)
|
|
|
+ decimal remainTime = CalcRemainWorkTime(workEndTime,workPoints);
|
|
|
+ //剩余可用工作时长满足清场时长
|
|
|
+ if (remainTime >= item.WaitTime)
|
|
|
+ {
|
|
|
+ //清场需要时长(分钟)
|
|
|
+ decimal needTime = item.WaitTime;
|
|
|
+ //获取排产结束时间所处以及之后的生产时间段
|
|
|
+ var nextPoints = workPoints.Where(p => p.Level >= lastPoint.Level).OrderBy(p => p.Level).ToList();
|
|
|
+ //处理第一个时间段的开始时间
|
|
|
+ nextPoints[0].StartPoint = workEndTime;
|
|
|
+ foreach (var p in nextPoints)
|
|
|
+ {
|
|
|
+ span = p.EndPoint - p.StartPoint;
|
|
|
+ //当前工作时间段的有效生产时间
|
|
|
+ effMins = (decimal)span.TotalMinutes;
|
|
|
+ if (effMins >= needTime)
|
|
|
+ {
|
|
|
+ workEndTime = p.StartPoint.AddMinutes((double)needTime);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ needTime -= effMins;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //剩余可用工作时长不能满足清场时长
|
|
|
+ else
|
|
|
+ {
|
|
|
+ decimal needTime = item.WaitTime - remainTime;
|
|
|
+ workEndTime.AddMinutes((double)needTime);
|
|
|
+ }
|
|
|
//记录生产周期
|
|
|
periodsDet.Add(new PeriodSequenceDet
|
|
|
{
|
|
|
@@ -2723,6 +2907,26 @@ namespace Business.ResourceExamineManagement
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 计算当天排产完成的剩余生产时长
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="endTime">排产结束时间</param>
|
|
|
+ /// <param name="workPoints">当天的工作时间段</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public decimal CalcRemainWorkTime(DateTime endTime, List<LineWorkPointDto> workPoints)
|
|
|
+ {
|
|
|
+ decimal remainTime = 0m;
|
|
|
+ var curPoint = workPoints.Find(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
|
|
|
+ TimeSpan span = curPoint.EndPoint - endTime;
|
|
|
+ remainTime = (decimal)span.TotalMinutes;
|
|
|
+ var nextPoints = workPoints.Where(p => p.Level > curPoint.Level).OrderBy(p => p.Level).ToList();
|
|
|
+ foreach (var item in nextPoints)
|
|
|
+ {
|
|
|
+ remainTime += item.WorkMinutes;
|
|
|
+ }
|
|
|
+ return remainTime;
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 获取产线当天的开工时间,结束时间,有效工作时长,生产数量
|
|
|
/// </summary>
|