|
@@ -217,9 +217,8 @@ namespace Business.ResourceExamineManagement
|
|
|
{
|
|
{
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- //获取排产工单的最早计划开工日期
|
|
|
|
|
|
|
+ //工单排产的最早日期
|
|
|
DateTime earlist = DateTime.Now.Date.AddDays(1);
|
|
DateTime earlist = DateTime.Now.Date.AddDays(1);
|
|
|
-
|
|
|
|
|
//特殊工单指定时间开工,不需要计算产能,只需要计算时长即可
|
|
//特殊工单指定时间开工,不需要计算产能,只需要计算时长即可
|
|
|
var tsWorkOrds = workOrds.Where(p => !string.IsNullOrEmpty(p.Typed)).ToList();
|
|
var tsWorkOrds = workOrds.Where(p => !string.IsNullOrEmpty(p.Typed)).ToList();
|
|
|
//正常工单
|
|
//正常工单
|
|
@@ -294,8 +293,38 @@ namespace Business.ResourceExamineManagement
|
|
|
List<ScheduleResultOpMaster> scheduleList = scheduleMasters.Where(s => s.WorkOrd == item.WorkOrd).ToList();
|
|
List<ScheduleResultOpMaster> scheduleList = scheduleMasters.Where(s => s.WorkOrd == item.WorkOrd).ToList();
|
|
|
if (scheduleList.Any())
|
|
if (scheduleList.Any())
|
|
|
{
|
|
{
|
|
|
- item.OrdDate = scheduleList.Min(s => s.WorkStartTime.Date);
|
|
|
|
|
- item.DueDate = scheduleList.Max(s => s.WorkEndTime.Date);
|
|
|
|
|
|
|
+ item.OrdDate = scheduleList.Min(s => s.WorkStartTime);
|
|
|
|
|
+ item.DueDate = scheduleList.Max(s => s.WorkEndTime);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ //判断是否有特殊工单没有排产,如果有,则对剩余特殊工单排产
|
|
|
|
|
+ var notSchedules = tsWorkOrds.Where(p => !ypcWorkOrds.Contains(p.WorkOrd)).ToList();
|
|
|
|
|
+ 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;
|
|
|
|
|
+ workDtos.Add(new WorkOrdMstDto
|
|
|
|
|
+ {
|
|
|
|
|
+ WorkOrd = item.WorkOrd,
|
|
|
|
|
+ ItemNum = item.ItemNum,
|
|
|
|
|
+ QtyOrded = item.QtyOrded,
|
|
|
|
|
+ OrdDate = item.OrdDate.GetValueOrDefault(),
|
|
|
|
|
+ ProdLine = item.ProdLine,
|
|
|
|
|
+ LbrVar = item.LbrVar,
|
|
|
|
|
+ Worked = 0,
|
|
|
|
|
+ QtyWorked = 0,
|
|
|
|
|
+ Op = op
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ TsLineSchedule(workDtos, periodSequenceDtls, scheduleMasters);
|
|
|
|
|
+ //处理特殊工单计划开始日期、计划结束日期
|
|
|
|
|
+ foreach (var item in tsWorkOrds)
|
|
|
|
|
+ {
|
|
|
|
|
+ List<ScheduleResultOpMaster> scheduleList = scheduleMasters.Where(s => s.WorkOrd == item.WorkOrd).ToList();
|
|
|
|
|
+ if (scheduleList.Any())
|
|
|
|
|
+ {
|
|
|
|
|
+ item.OrdDate = scheduleList.Min(s => s.WorkStartTime);
|
|
|
|
|
+ item.DueDate = scheduleList.Max(s => s.WorkEndTime);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
using (TransactionScope scope = new TransactionScope())
|
|
using (TransactionScope scope = new TransactionScope())
|
|
@@ -514,8 +543,6 @@ namespace Business.ResourceExamineManagement
|
|
|
var secWOMasters = new List<WorkOrdMaster>();
|
|
var secWOMasters = new List<WorkOrdMaster>();
|
|
|
//特殊工单工作时长(分钟)
|
|
//特殊工单工作时长(分钟)
|
|
|
decimal sumTsTimes = fstWOMasters.Sum(p => p.LbrVar) * 60;
|
|
decimal sumTsTimes = fstWOMasters.Sum(p => p.LbrVar) * 60;
|
|
|
- //特殊工单排产结束当天占用的产能时长(分钟)
|
|
|
|
|
- decimal dayOccupyTimes = 0m;
|
|
|
|
|
while (sumTsTimes > 0) //产线排产开始当天安排了特殊工单,则先安排特殊工单
|
|
while (sumTsTimes > 0) //产线排产开始当天安排了特殊工单,则先安排特殊工单
|
|
|
{
|
|
{
|
|
|
secWOMasters.Clear();
|
|
secWOMasters.Clear();
|
|
@@ -550,7 +577,7 @@ namespace Business.ResourceExamineManagement
|
|
|
Op = op
|
|
Op = op
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
- //特殊工单待排产时长增加新增带排产特殊工单生产时长
|
|
|
|
|
|
|
+ //特殊工单待排产时长增加新增的特殊工单生产时长
|
|
|
sumTsTimes += secWOMasters.Sum(p => p.LbrVar) * 60;
|
|
sumTsTimes += secWOMasters.Sum(p => p.LbrVar) * 60;
|
|
|
}
|
|
}
|
|
|
if (dto.EffTime * 60 >= sumTsTimes)//当天的可用产能满足特殊工单生产时长
|
|
if (dto.EffTime * 60 >= sumTsTimes)//当天的可用产能满足特殊工单生产时长
|
|
@@ -635,7 +662,6 @@ namespace Business.ResourceExamineManagement
|
|
|
item.Worked = item.LbrVar;
|
|
item.Worked = item.LbrVar;
|
|
|
sumTsTimes -= needTime;
|
|
sumTsTimes -= needTime;
|
|
|
}
|
|
}
|
|
|
- dayOccupyTimes = sumTsTimes;
|
|
|
|
|
if (dto.EffTime * 60 == sumTsTimes)//当天产能完全占用
|
|
if (dto.EffTime * 60 == sumTsTimes)//当天产能完全占用
|
|
|
{
|
|
{
|
|
|
sumTsTimes = 0;//排产完毕,特殊工单时长置0
|
|
sumTsTimes = 0;//排产完毕,特殊工单时长置0
|
|
@@ -662,7 +688,6 @@ namespace Business.ResourceExamineManagement
|
|
|
}
|
|
}
|
|
|
//特殊工单待排产时长增加新增带排产特殊工单生产时长
|
|
//特殊工单待排产时长增加新增带排产特殊工单生产时长
|
|
|
sumTsTimes += secWOMasters.Sum(p => p.LbrVar) * 60;
|
|
sumTsTimes += secWOMasters.Sum(p => p.LbrVar) * 60;
|
|
|
- dayOccupyTimes = 0m;
|
|
|
|
|
}
|
|
}
|
|
|
else {
|
|
else {
|
|
|
sumTsTimes = 0;//排产完毕,特殊工单时长置0
|
|
sumTsTimes = 0;//排产完毕,特殊工单时长置0
|
|
@@ -818,12 +843,6 @@ namespace Business.ResourceExamineManagement
|
|
|
secWOMasters.Clear();
|
|
secWOMasters.Clear();
|
|
|
//获取当天的产能
|
|
//获取当天的产能
|
|
|
LineScheduledDto dto = GetScheduledPoint(lineStart, workStartTime, mLCalendars, mlqtyWorkDtls);
|
|
LineScheduledDto dto = GetScheduledPoint(lineStart, workStartTime, mLCalendars, mlqtyWorkDtls);
|
|
|
- //当天产能被特殊工单占用部分,需要先剔除
|
|
|
|
|
- if (dayOccupyTimes > 0)
|
|
|
|
|
- {
|
|
|
|
|
- dto.EffTime -= Math.Ceiling(dayOccupyTimes / 60);
|
|
|
|
|
- dayOccupyTimes = 0;
|
|
|
|
|
- }
|
|
|
|
|
//正常工单排产第一天没有特殊工单,第一天之后才需要考虑是否有特殊工单
|
|
//正常工单排产第一天没有特殊工单,第一天之后才需要考虑是否有特殊工单
|
|
|
if (!isFstDay)
|
|
if (!isFstDay)
|
|
|
{
|
|
{
|
|
@@ -2071,6 +2090,145 @@ namespace Business.ResourceExamineManagement
|
|
|
scheduleResults.AddRange(curScheduleRsts);
|
|
scheduleResults.AddRange(curScheduleRsts);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// 特殊工单排产:和正常工单不共用产线的特殊工单
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ /// <param name="workOrds">特殊工单</param>
|
|
|
|
|
+ /// <param name="periodsDet">生产周期</param>
|
|
|
|
|
+ /// <param name="scheduleResults">排产结果</param>
|
|
|
|
|
+ public void TsLineSchedule(List<WorkOrdMstDto> workOrds, List<PeriodSequenceDet> periodsDet, List<ScheduleResultOpMaster> scheduleResults)
|
|
|
|
|
+ {
|
|
|
|
|
+ foreach (var item in workOrds)
|
|
|
|
|
+ {
|
|
|
|
|
+ //工单的生产时长(小时)
|
|
|
|
|
+ decimal sumTimes = item.LbrVar;
|
|
|
|
|
+ //工单的排产开始时间
|
|
|
|
|
+ DateTime workStartTime = item.OrdDate;
|
|
|
|
|
+ //当前产线的工作日历
|
|
|
|
|
+ var mLCalendars = calendars.Where(p => p.ProdLine == item.ProdLine || string.IsNullOrEmpty(p.ProdLine)).ToList();
|
|
|
|
|
+ //当前产线的休息时间设置
|
|
|
|
|
+ var mlqtyWorkDtls = qualityLines.Where(p => p.ProdLine == item.ProdLine).ToList();
|
|
|
|
|
+ LineStartDto lineStart = new LineStartDto();
|
|
|
|
|
+ lineStart.Line = item.ProdLine;
|
|
|
|
|
+ lineStart.Op = item.Op;
|
|
|
|
|
+ lineStart.StartTime = workStartTime;
|
|
|
|
|
+ lineStart.Rate = 0;
|
|
|
|
|
+ while (sumTimes > 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ //获取当天的工作时间段
|
|
|
|
|
+ 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(lineStart.Line, workStartTime, curCalendar, mlqtyWorkDtls);
|
|
|
|
|
+ //获取当天的产能
|
|
|
|
|
+ LineScheduledDto dto = GetScheduledPoint(lineStart, workStartTime, mLCalendars, mlqtyWorkDtls);
|
|
|
|
|
+ //当天的可用生产时长不能满足特殊工单生产时长
|
|
|
|
|
+ if (dto.EffTime <= sumTimes)
|
|
|
|
|
+ {
|
|
|
|
|
+ decimal qty = Math.Ceiling(dto.EffTime / item.LbrVar * item.QtyOrded);
|
|
|
|
|
+ //记录生产周期
|
|
|
|
|
+ periodsDet.Add(new PeriodSequenceDet
|
|
|
|
|
+ {
|
|
|
|
|
+ Domain = domain,
|
|
|
|
|
+ Line = item.ProdLine,
|
|
|
|
|
+ ItemNum = item.ItemNum,
|
|
|
|
|
+ PlanDate = workStartTime.Date,
|
|
|
|
|
+ Period = dto.Period,
|
|
|
|
|
+ OrdQty = qty,
|
|
|
|
|
+ WorkOrds = item.WorkOrd,
|
|
|
|
|
+ Op = item.Op,
|
|
|
|
|
+ IsActive = true,
|
|
|
|
|
+ Status = "",
|
|
|
|
|
+ CreateTime = DateTime.Now
|
|
|
|
|
+ });
|
|
|
|
|
+ //记录排产记录
|
|
|
|
|
+ scheduleResults.Add(new ScheduleResultOpMaster
|
|
|
|
|
+ {
|
|
|
|
|
+ Domain = domain,
|
|
|
|
|
+ WorkOrd = item.WorkOrd,
|
|
|
|
|
+ Line = item.ProdLine,
|
|
|
|
|
+ ItemNum = item.ItemNum,
|
|
|
|
|
+ Op = item.Op,
|
|
|
|
|
+ WorkDate = workStartTime.Date,
|
|
|
|
|
+ WorkQty = qty,
|
|
|
|
|
+ WorkStartTime = dto.StartTime,
|
|
|
|
|
+ WorkEndTime = dto.EndTime,
|
|
|
|
|
+ CreateTime = DateTime.Now
|
|
|
|
|
+ });
|
|
|
|
|
+ //剩余待排产时长
|
|
|
|
|
+ sumTimes -= dto.EffTime;
|
|
|
|
|
+ //已排产数量
|
|
|
|
|
+ item.QtyWorked += qty;
|
|
|
|
|
+ //继续排下一个工作日
|
|
|
|
|
+ workStartTime = GetNextWorkDay((int)workStartTime.DayOfWeek, workStartTime, mLCalendars);
|
|
|
|
|
+ }
|
|
|
|
|
+ else// 最后一天的产能只能占用一部分
|
|
|
|
|
+ {
|
|
|
|
|
+ //剩余生产时长(分钟)
|
|
|
|
|
+ decimal workTime = sumTimes * 60;
|
|
|
|
|
+ var curPoint = workPoints.Find(p => p.StartPoint <= workStartTime && workStartTime <= p.EndPoint);
|
|
|
|
|
+ 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;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ //记录生产周期
|
|
|
|
|
+ periodsDet.Add(new PeriodSequenceDet
|
|
|
|
|
+ {
|
|
|
|
|
+ Domain = domain,
|
|
|
|
|
+ Line = item.ProdLine,
|
|
|
|
|
+ ItemNum = item.ItemNum,
|
|
|
|
|
+ PlanDate = workStartTime.Date,
|
|
|
|
|
+ Period = dto.Period,
|
|
|
|
|
+ OrdQty = item.QtyOrded - item.QtyWorked,
|
|
|
|
|
+ WorkOrds = item.WorkOrd,
|
|
|
|
|
+ Op = item.Op,
|
|
|
|
|
+ IsActive = true,
|
|
|
|
|
+ Status = "",
|
|
|
|
|
+ CreateTime = DateTime.Now
|
|
|
|
|
+ });
|
|
|
|
|
+ //记录排产记录
|
|
|
|
|
+ scheduleResults.Add(new ScheduleResultOpMaster
|
|
|
|
|
+ {
|
|
|
|
|
+ Domain = domain,
|
|
|
|
|
+ WorkOrd = item.WorkOrd,
|
|
|
|
|
+ Line = item.ProdLine,
|
|
|
|
|
+ ItemNum = item.ItemNum,
|
|
|
|
|
+ Op = item.Op,
|
|
|
|
|
+ WorkDate = workStartTime.Date,
|
|
|
|
|
+ WorkQty = item.QtyOrded - item.QtyWorked,
|
|
|
|
|
+ WorkStartTime = workStartTime,
|
|
|
|
|
+ WorkEndTime = workEndTime,
|
|
|
|
|
+ CreateTime = DateTime.Now
|
|
|
|
|
+ });
|
|
|
|
|
+ sumTimes = 0;
|
|
|
|
|
+ item.QtyWorked = item.QtyOrded;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// 获取产线当天的开工时间,结束时间,有效工作时长,生产数量
|
|
/// 获取产线当天的开工时间,结束时间,有效工作时长,生产数量
|
|
|
/// </summary>
|
|
/// </summary>
|
|
@@ -2108,9 +2266,6 @@ namespace Business.ResourceExamineManagement
|
|
|
span = item.EndPoint - item.StartPoint;
|
|
span = item.EndPoint - item.StartPoint;
|
|
|
scheduledDto.EffTime += (decimal)span.TotalHours;
|
|
scheduledDto.EffTime += (decimal)span.TotalHours;
|
|
|
}
|
|
}
|
|
|
- ////判断产线当天有没有加班
|
|
|
|
|
- //var curOccupyTimes = resourceOccupancyTimes.Where(p=> p.Resource == lineStart.Line && p.StartTime.GetValueOrDefault().Date == startTime.Date).ToList();
|
|
|
|
|
- //scheduledDto.EffTime += curOccupyTimes.Sum(p=> Convert.ToDecimal(p.Ufld1));
|
|
|
|
|
//判断当前产线的UPH
|
|
//判断当前产线的UPH
|
|
|
var curRunCrews = prodLineDetailRunCrews.Where(p=>p.ProdLineDetailRecID == lineStart.RecID).ToList();
|
|
var curRunCrews = prodLineDetailRunCrews.Where(p=>p.ProdLineDetailRecID == lineStart.RecID).ToList();
|
|
|
//判断当前日期是否配置了UPH
|
|
//判断当前日期是否配置了UPH
|
|
@@ -2120,7 +2275,7 @@ namespace Business.ResourceExamineManagement
|
|
|
//计算当天的产能(向下取整)
|
|
//计算当天的产能(向下取整)
|
|
|
scheduledDto.ProductQty = Math.Floor(scheduledDto.EffTime * rate);
|
|
scheduledDto.ProductQty = Math.Floor(scheduledDto.EffTime * rate);
|
|
|
//计算班次
|
|
//计算班次
|
|
|
- scheduledDto.Period = 1;//默认一般制
|
|
|
|
|
|
|
+ scheduledDto.Period = 1;//默认一班制
|
|
|
if (shopCal.ShiftsStart2 != 0 && shopCal.ShiftsHours2 != 0)
|
|
if (shopCal.ShiftsStart2 != 0 && shopCal.ShiftsHours2 != 0)
|
|
|
{
|
|
{
|
|
|
scheduledDto.Period = 2;
|
|
scheduledDto.Period = 2;
|