|
|
@@ -183,7 +183,7 @@ namespace Business.ResourceExamineManagement
|
|
|
#endregion
|
|
|
|
|
|
/// <summary>
|
|
|
- /// 执行生产排产
|
|
|
+ /// 生产排产-定时任务
|
|
|
/// </summary>
|
|
|
public async void DoExt()
|
|
|
{
|
|
|
@@ -191,24 +191,21 @@ namespace Business.ResourceExamineManagement
|
|
|
IConfiguration configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).Build();
|
|
|
domain = configuration.GetConnectionString("Factory_id");
|
|
|
|
|
|
- //获取提前期
|
|
|
- var generalizedCodeMaster = _generalizedCodeMaster.Select(x => x.FldName == "SystemConfig" && x.Val == "WorkOrderLockPeriod" && x.Domain == domain).FirstOrDefault();
|
|
|
- decimal Udecil = 0;
|
|
|
- if (generalizedCodeMaster != null)
|
|
|
- {
|
|
|
- Udecil = generalizedCodeMaster.UDeci1;
|
|
|
- }
|
|
|
- //排产取4周工单排产
|
|
|
- DateTime dateTime = DateTime.Now.AddDays(30);
|
|
|
- DateTime date = DateTime.Now.AddDays((double)Udecil);
|
|
|
- var workOrds = _workOrdMaster.Select(x => x.IsActive && x.Domain == domain && x.OrdDate < dateTime && x.OrdDate > date && x.Status == "初始").ToList();
|
|
|
+ //获取排产锁定期
|
|
|
+ var generalizedCodeMaster = _generalizedCodeMaster.Select(p => p.FldName == "SystemConfig" && p.Val == "WorkOrderLockPeriod" && p.Domain == domain && p.IsActive).FirstOrDefault();
|
|
|
+ decimal lockDays = generalizedCodeMaster != null ? generalizedCodeMaster.UDeci1 : 0;
|
|
|
+
|
|
|
+ //获取需要排产的工单(获取四周的工单:正常工单+已审批通过的特殊工单)
|
|
|
+ DateTime endDate = DateTime.Now.Date.AddWeeks(4).AddDays(1);
|
|
|
+ DateTime startDate = DateTime.Now.Date;
|
|
|
+ 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();
|
|
|
await DoProductSchedule(workOrds, domain, 1);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 生产排产
|
|
|
/// </summary>
|
|
|
- /// <param name="workOrds">工单:定时任务执行时count=0;资源检查调用count>0</param>
|
|
|
+ /// <param name="workOrds">工单</param>
|
|
|
/// <param name="factoryid">工单的工厂id</param>
|
|
|
/// <param name="type">排产类型:1-自动排产;2-手动排产</param>
|
|
|
/// <returns></returns>
|
|
|
@@ -223,9 +220,16 @@ namespace Business.ResourceExamineManagement
|
|
|
//获取排产工单的最早计划开工日期
|
|
|
DateTime earlist = DateTime.Now.Date.AddDays(1);
|
|
|
|
|
|
+ //特殊工单指定时间开工,不需要计算产能,只需要计算时长即可
|
|
|
+ var tsWorkOrds = workOrds.Where(p => !string.IsNullOrEmpty(p.Typed)).ToList();
|
|
|
+ //正常工单
|
|
|
+ var zcWorkOrds = workOrds.Where(p => string.IsNullOrEmpty(p.Typed)).ToList();
|
|
|
+
|
|
|
//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);
|
|
|
+ //特殊工单的工艺路线
|
|
|
+ List<WorkOrdRouting> tsWoRoutings = workOrdRoutings.Where(p => tsWorkOrds.Select(m => m.WorkOrd).Contains(p.WorkOrd)).ToList();
|
|
|
//获取物料对应的生产线信息:物料、工序对应的生产线
|
|
|
List<ProdLineDetail> prodLines = _prodLineDetail.Select(p => workOrds.Select(m => m.ItemNum).Contains(p.Part) && p.Domain == domain && p.IsActive);
|
|
|
List<string> lines = prodLines.Select(p => p.Line).ToList();
|
|
|
@@ -233,9 +237,9 @@ namespace Business.ResourceExamineManagement
|
|
|
prodLineDetailRunCrews = _prodLineDetailRunCrew.Select(x => prodLines.Select(p => p.RecID).Contains(x.ProdLineDetailRecID) && x.IsActive && x.Domain == domain).ToList();
|
|
|
//获取加班设置
|
|
|
resourceOccupancyTimes = _resourceOccupancyTime.Select(x => prodLines.Select(p => p.Line).Contains(x.Resource) && x.IsActive && x.Domain == domain && x.StartTime.Value > DateTime.Now).ToList();
|
|
|
- //获取生产周期数据
|
|
|
+ //获取生产周期数据,TODO:需要过滤锁定期之外的工单
|
|
|
List<PeriodSequenceDet> dbPeriodSequences = _periodSequenceDet.Select(p => lines.Contains(p.Line) && p.PlanDate >= earlist && p.Domain == domain && p.IsActive);
|
|
|
- //获取当前日期往后的排产记录数据
|
|
|
+ //获取当前日期往后的排产记录数据,TODO:需要过滤锁定期之外的工单
|
|
|
List<ScheduleResultOpMaster> dbSchedules = _scheduleResultOpMaster.Select(p => lines.Contains(p.Line) && p.WorkDate >= earlist && p.Domain == domain);
|
|
|
//获取工作日历数据:产线的工作日历+默认的工作日历
|
|
|
calendars = _shopCalendarWorkCtr.Select(p => (lines.Contains(p.ProdLine) || string.IsNullOrEmpty(p.ProdLine)) && p.Domain == domain && p.IsActive);
|
|
|
@@ -273,7 +277,9 @@ namespace Business.ResourceExamineManagement
|
|
|
//排产结果
|
|
|
List<ScheduleResultOpMaster> allResults = new List<ScheduleResultOpMaster>();
|
|
|
allResults.AddRange(dbSchedules);
|
|
|
- foreach (var item in workOrds)
|
|
|
+ //记录特殊工单排产结果
|
|
|
+ List<string> ypcWorkOrds = new List<string>();
|
|
|
+ foreach (var item in zcWorkOrds)
|
|
|
{
|
|
|
//记录产线占用情况
|
|
|
allResults.AddRange(scheduleMasters);
|
|
|
@@ -283,7 +289,7 @@ namespace Business.ResourceExamineManagement
|
|
|
var curProdLines = prodLines.Where(p => p.Part == item.ItemNum).ToList();
|
|
|
|
|
|
//产线排产
|
|
|
- LineSchedule(item, curRoutings, curProdLines, periodSequenceDtls, scheduleMasters, allResults);
|
|
|
+ LineSchedule(item, curRoutings, curProdLines, periodSequenceDtls, scheduleMasters, allResults, tsWorkOrds, ypcWorkOrds, tsWoRoutings);
|
|
|
|
|
|
List<ScheduleResultOpMaster> scheduleList = scheduleMasters.Where(s => s.WorkOrd == item.WorkOrd).ToList();
|
|
|
if (scheduleList.Any())
|
|
|
@@ -324,6 +330,23 @@ namespace Business.ResourceExamineManagement
|
|
|
ScheduleExceptionMaster entity;
|
|
|
foreach (var item in workOrds)
|
|
|
{
|
|
|
+ if (!string.IsNullOrEmpty(item.Typed))//特殊工单
|
|
|
+ {
|
|
|
+ //只需要校验有没有维护工艺路线即可
|
|
|
+ var routings = workOrdRoutings.Where(p=>p.ItemNum == item.ItemNum).ToList();
|
|
|
+ if (!routings.Any())
|
|
|
+ {
|
|
|
+ entity = new ScheduleExceptionMaster();
|
|
|
+ entity.Domain = item.Domain;
|
|
|
+ entity.WorkOrd = item.WorkOrd;
|
|
|
+ entity.ItemNum = item.ItemNum;
|
|
|
+ entity.CreateTime = DateTime.Now;
|
|
|
+ entity.Remark = "排产异常:工单没有维护工艺路线,请维护后再操作!";
|
|
|
+ entity.Type = type == 1 ? "自动排产" : "手动排产";
|
|
|
+ exceptions.Add(entity);
|
|
|
+ }
|
|
|
+ continue;
|
|
|
+ }
|
|
|
var curRoutings = workOrdRoutings.Where(p => p.ItemNum == item.ItemNum && p.MilestoneOp).OrderBy(p=>p.OP).Select(p=>p.OP).ToList();
|
|
|
//判断当前工单主产线是否设置了关键工序
|
|
|
if (!curRoutings.Any())//当前工单没有维护关键工序
|
|
|
@@ -440,7 +463,10 @@ namespace Business.ResourceExamineManagement
|
|
|
/// <param name="periodsDet">生产周期</param>
|
|
|
/// <param name="scheduleResults">排产结果</param>
|
|
|
/// <param name="allResults">产线占用记录</param>
|
|
|
- public void LineSchedule(WorkOrdMaster workOrd, List<WorkOrdRouting> workOrdRoutings, List<ProdLineDetail> prodLines,List<PeriodSequenceDet> periodsDet, List<ScheduleResultOpMaster> scheduleResults, List<ScheduleResultOpMaster> allResults)
|
|
|
+ /// <param name="tsWorkOrds">特殊工单</param>
|
|
|
+ /// <param name="ypcWorkOrds">已排产特殊工单的工单编号</param>
|
|
|
+ /// <param name="tsWoRoutings">特殊工单的工艺路线</param>
|
|
|
+ public void LineSchedule(WorkOrdMaster workOrd, List<WorkOrdRouting> workOrdRoutings, List<ProdLineDetail> prodLines,List<PeriodSequenceDet> periodsDet, List<ScheduleResultOpMaster> scheduleResults, List<ScheduleResultOpMaster> allResults,List<WorkOrdMaster> tsWorkOrds,List<string> ypcWorkOrds, List<WorkOrdRouting> tsWoRoutings)
|
|
|
{
|
|
|
//生产周期
|
|
|
List<PeriodSequenceDet> curSequences = new List<PeriodSequenceDet>();
|
|
|
@@ -448,6 +474,7 @@ namespace Business.ResourceExamineManagement
|
|
|
List<ScheduleResultOpMaster> curScheduleRsts = new List<ScheduleResultOpMaster>();
|
|
|
//记录上一产线排产开始时间
|
|
|
LineStartDto lineStart = new LineStartDto();
|
|
|
+ TimeSpan span = TimeSpan.Zero;
|
|
|
//第一层级工序有几个关键工序,就有几条产线
|
|
|
for (int i = 0; i < workOrdRoutings.Count; i++)
|
|
|
{
|
|
|
@@ -471,6 +498,254 @@ namespace Business.ResourceExamineManagement
|
|
|
decimal sumTimes = 0m;
|
|
|
//产线排产开始时间
|
|
|
DateTime workStartTime = lineStart.StartTime;
|
|
|
+ //记录特殊工单:获取第一天是否有特殊工单
|
|
|
+ var 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
|
|
|
+ });
|
|
|
+ }
|
|
|
+ //特殊工单工作时长
|
|
|
+ decimal sumTsTimes = fstWOMasters.Sum(p=>p.LbrVar);
|
|
|
+ //特殊工单排产结束当天占用的产能时长
|
|
|
+ decimal dayOccupyTimes = 0m;
|
|
|
+ while (sumTsTimes > 0) //产线排产开始当天安排了特殊工单,则先安排特殊工单
|
|
|
+ {
|
|
|
+ //获取当天的产能
|
|
|
+ LineScheduledDto dto = GetScheduledPoint(lineStart, workStartTime, mLCalendars, mlqtyWorkDtls);
|
|
|
+ //获取当天的工作时间段
|
|
|
+ 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);
|
|
|
+ if (dto.EffTime >= sumTsTimes)//当天的可用产能满足特殊工单生产时长
|
|
|
+ {
|
|
|
+ DateTime beginTime = workStartTime;
|
|
|
+ DateTime endTime = DateTime.Now;
|
|
|
+ foreach (var item in workDtos)
|
|
|
+ {
|
|
|
+ if (item.LbrVar == item.Worked)//当前工单已排产
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //工单排产完成,排产时长=工单工作时长
|
|
|
+ item.Worked = item.LbrVar;
|
|
|
+ //当前工单还需工作时长
|
|
|
+ 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)//当前工作时间段即可满足产能
|
|
|
+ {
|
|
|
+ endTime = beginTime.AddMinutes((double)needTime);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //获取后续生产时间段
|
|
|
+ var nextPoints = workPoints.Where(p => p.Level > curPoint.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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //记录生产周期
|
|
|
+ curSequences.Add(new PeriodSequenceDet
|
|
|
+ {
|
|
|
+ Domain = domain,
|
|
|
+ Line = lineStart.Line,
|
|
|
+ ItemNum = item.ItemNum,
|
|
|
+ PlanDate = beginTime.Date,
|
|
|
+ Period = dto.Period,
|
|
|
+ OrdQty = item.QtyOrded - item.QtyWorked,
|
|
|
+ WorkOrds = item.WorkOrd,
|
|
|
+ Op = item.Op,
|
|
|
+ IsActive = true,
|
|
|
+ Status = "",
|
|
|
+ CreateTime = DateTime.Now
|
|
|
+ });
|
|
|
+ //记录排产记录
|
|
|
+ curScheduleRsts.Add(new ScheduleResultOpMaster
|
|
|
+ {
|
|
|
+ Domain = domain,
|
|
|
+ WorkOrd = item.WorkOrd,
|
|
|
+ Line = lineStart.Line,
|
|
|
+ ItemNum = item.ItemNum,
|
|
|
+ Op = item.Op,
|
|
|
+ WorkDate = beginTime.Date,
|
|
|
+ WorkQty = item.QtyOrded - item.QtyWorked,
|
|
|
+ WorkStartTime = beginTime,
|
|
|
+ WorkEndTime = endTime,
|
|
|
+ CreateTime = DateTime.Now
|
|
|
+ });
|
|
|
+ //下一工单开始时间=当前工单结束时间,如果位于工作区间结尾,则为下一工作区间开始时间
|
|
|
+ curPoint = workPoints.Find(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
|
|
|
+ if (endTime == curPoint.EndPoint)//结束时间位于工作区间结尾
|
|
|
+ {
|
|
|
+ //获取后续生产时间段
|
|
|
+ var nextPoint = workPoints.Where(p => p.Level == curPoint.Level + 1).FirstOrDefault();
|
|
|
+ if (nextPoint != null)//存在后续工作区间
|
|
|
+ {
|
|
|
+ endTime = nextPoint.StartPoint;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ beginTime = endTime;
|
|
|
+ }
|
|
|
+ dayOccupyTimes = sumTsTimes;
|
|
|
+ if (dto.EffTime == sumTsTimes)//当天产能完全占用
|
|
|
+ {
|
|
|
+ //获取下一个工作日
|
|
|
+ workStartTime = GetNextWorkDay((int)workStartTime.DayOfWeek, workStartTime, mLCalendars);
|
|
|
+ dayOccupyTimes = 0m;
|
|
|
+ }
|
|
|
+ sumTsTimes = 0;//排产完毕,特殊工单时长置0
|
|
|
+ }
|
|
|
+ else//当天的可用产能不满足特殊工单生产时长
|
|
|
+ {
|
|
|
+ decimal residueTime = dto.EffTime * 60;//当天产能剩余产能(分钟)
|
|
|
+ DateTime beginTime = workStartTime;//排产开始时间
|
|
|
+ DateTime endTime = dto.EndTime;//排产结束时间
|
|
|
+ foreach (var item in workDtos)
|
|
|
+ {
|
|
|
+ if (item.LbrVar == item.Worked)//当前工单已排产
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //当前工单剩余待排产时长(分钟)
|
|
|
+ decimal needTime = item.LbrVar - item.Worked;
|
|
|
+ if (residueTime >= needTime)//当天剩余产能满足当前工单的剩余待排产时长
|
|
|
+ {
|
|
|
+ //计算工单排产结束时间
|
|
|
+ var 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
|
|
|
+ {
|
|
|
+ //获取后续生产时间段
|
|
|
+ var nextPoints = workPoints.Where(p => p.Level > curPoint.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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //记录生产周期
|
|
|
+ curSequences.Add(new PeriodSequenceDet
|
|
|
+ {
|
|
|
+ Domain = domain,
|
|
|
+ Line = lineStart.Line,
|
|
|
+ ItemNum = item.ItemNum,
|
|
|
+ PlanDate = beginTime.Date,
|
|
|
+ Period = dto.Period,
|
|
|
+ OrdQty = item.QtyOrded - item.QtyWorked,
|
|
|
+ WorkOrds = item.WorkOrd,
|
|
|
+ Op = item.Op,
|
|
|
+ IsActive = true,
|
|
|
+ Status = "",
|
|
|
+ CreateTime = DateTime.Now
|
|
|
+ });
|
|
|
+ //记录排产记录
|
|
|
+ curScheduleRsts.Add(new ScheduleResultOpMaster
|
|
|
+ {
|
|
|
+ Domain = domain,
|
|
|
+ WorkOrd = item.WorkOrd,
|
|
|
+ Line = lineStart.Line,
|
|
|
+ ItemNum = item.ItemNum,
|
|
|
+ Op = item.Op,
|
|
|
+ WorkDate = beginTime.Date,
|
|
|
+ WorkQty = item.QtyOrded - item.QtyWorked,
|
|
|
+ WorkStartTime = beginTime,
|
|
|
+ WorkEndTime = endTime,
|
|
|
+ CreateTime = DateTime.Now
|
|
|
+ });
|
|
|
+ beginTime = endTime;
|
|
|
+ //当前工单已排产完成,已排产时间=工单生产时长,已排产数量=工单数量
|
|
|
+ item.Worked = item.LbrVar;
|
|
|
+ item.QtyWorked = item.QtyWorked;
|
|
|
+ //当天剩余产能
|
|
|
+ residueTime -= needTime;
|
|
|
+ if (residueTime == 0)
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else//当天剩余产能不满足当前工单的剩余待排产时长
|
|
|
+ {
|
|
|
+ //计算生产数量
|
|
|
+ decimal qty = Math.Ceiling(residueTime / item.LbrVar * item.QtyOrded);
|
|
|
+ //记录生产周期
|
|
|
+ curSequences.Add(new PeriodSequenceDet
|
|
|
+ {
|
|
|
+ Domain = domain,
|
|
|
+ Line = lineStart.Line,
|
|
|
+ ItemNum = item.ItemNum,
|
|
|
+ PlanDate = beginTime.Date,
|
|
|
+ Period = dto.Period,
|
|
|
+ OrdQty = qty,
|
|
|
+ WorkOrds = item.WorkOrd,
|
|
|
+ Op = item.Op,
|
|
|
+ IsActive = true,
|
|
|
+ Status = "",
|
|
|
+ CreateTime = DateTime.Now
|
|
|
+ });
|
|
|
+ //记录排产记录
|
|
|
+ curScheduleRsts.Add(new ScheduleResultOpMaster
|
|
|
+ {
|
|
|
+ Domain = domain,
|
|
|
+ WorkOrd = item.WorkOrd,
|
|
|
+ Line = lineStart.Line,
|
|
|
+ ItemNum = item.ItemNum,
|
|
|
+ Op = item.Op,
|
|
|
+ WorkDate = beginTime.Date,
|
|
|
+ WorkQty = qty,
|
|
|
+ WorkStartTime = beginTime,
|
|
|
+ WorkEndTime = endTime,
|
|
|
+ CreateTime = DateTime.Now
|
|
|
+ });
|
|
|
+ item.Worked += residueTime;
|
|
|
+ item.QtyWorked += qty;
|
|
|
+ residueTime = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //特殊工单剩余待排产时长
|
|
|
+ sumTsTimes -= dto.EffTime;
|
|
|
+ //获取下一个工作日
|
|
|
+ workStartTime = GetNextWorkDay((int)workStartTime.DayOfWeek, workStartTime, mLCalendars);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //记录排产开始第二天及以后安排的特殊工单
|
|
|
+ var secWOMasters = new List<WorkOrdMaster>();
|
|
|
//排产
|
|
|
while (sumQty < workOrd.QtyOrded)
|
|
|
{
|
|
|
@@ -533,11 +808,11 @@ namespace Business.ResourceExamineManagement
|
|
|
{
|
|
|
curCalendar = mLCalendars.FirstOrDefault(p => string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == (int)workStartTime.DayOfWeek);
|
|
|
}
|
|
|
- List<LineWorkPointDto> workPoints = DealWorkDayToLevels(workStartTime, curCalendar, mlqtyWorkDtls);
|
|
|
+ List<LineWorkPointDto> workPoints = DealWorkDayToLevels(lineStart.Line, workStartTime, curCalendar, mlqtyWorkDtls);
|
|
|
var curPoint = workPoints.Find(p => p.StartPoint <= workStartTime && workStartTime <= p.EndPoint);
|
|
|
if (curPoint != null)
|
|
|
{
|
|
|
- TimeSpan span = curPoint.EndPoint - workStartTime;
|
|
|
+ span = curPoint.EndPoint - workStartTime;
|
|
|
//当天工作时间段的有效生产时间
|
|
|
decimal effMins = (decimal)span.TotalMinutes;
|
|
|
DateTime workEndTime = workStartTime;
|
|
|
@@ -595,14 +870,16 @@ namespace Business.ResourceExamineManagement
|
|
|
}
|
|
|
sumTimes = lineStart.setupTime;
|
|
|
}
|
|
|
- else {
|
|
|
+ else
|
|
|
+ {
|
|
|
//当天的可用生产时长不能满足提前期
|
|
|
sumTimes += dto.EffTime;
|
|
|
//获取下一个工作日
|
|
|
workStartTime = GetNextWorkDay((int)workStartTime.DayOfWeek, workStartTime, mLCalendars);
|
|
|
}
|
|
|
}
|
|
|
- else {
|
|
|
+ else
|
|
|
+ {
|
|
|
//判断已排产数量+当天的产能是否超过工单数量
|
|
|
if (sumQty + dto.ProductQty <= workOrd.QtyOrded)//当天的产能需要全部排产
|
|
|
{
|
|
|
@@ -613,7 +890,7 @@ namespace Business.ResourceExamineManagement
|
|
|
Line = lineStart.Line,
|
|
|
ItemNum = workOrd.ItemNum,
|
|
|
PlanDate = workStartTime.Date,
|
|
|
- Period = dto.Period,//目前只考虑一班制
|
|
|
+ Period = dto.Period,
|
|
|
OrdQty = dto.ProductQty,
|
|
|
WorkOrds = workOrd.WorkOrd,
|
|
|
Op = lineStart.Op,
|
|
|
@@ -652,65 +929,62 @@ namespace Business.ResourceExamineManagement
|
|
|
{
|
|
|
curCalendar = mLCalendars.FirstOrDefault(p => string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == (int)workStartTime.DayOfWeek);
|
|
|
}
|
|
|
- List<LineWorkPointDto> workPoints = DealWorkDayToLevels(workStartTime, curCalendar, mlqtyWorkDtls);
|
|
|
+ List<LineWorkPointDto> workPoints = DealWorkDayToLevels(lineStart.Line, workStartTime, curCalendar, mlqtyWorkDtls);
|
|
|
var curPoint = workPoints.Find(p => p.StartPoint <= workStartTime && workStartTime <= p.EndPoint);
|
|
|
- if (curPoint != null)
|
|
|
+ span = curPoint.EndPoint - workStartTime;
|
|
|
+ //当天工作时间段的有效生产时间
|
|
|
+ decimal effMins = (decimal)span.TotalMinutes;
|
|
|
+ DateTime workEndTime = workStartTime;
|
|
|
+ if (effMins >= workTime)//当前工作时间段即可满足产能
|
|
|
{
|
|
|
- TimeSpan span = curPoint.EndPoint - workStartTime;
|
|
|
- //当天工作时间段的有效生产时间
|
|
|
- decimal effMins = (decimal)span.TotalMinutes;
|
|
|
- DateTime workEndTime = workStartTime;
|
|
|
- if (effMins >= workTime)//当前工作时间段即可满足产能
|
|
|
- {
|
|
|
- workEndTime = workStartTime.AddMinutes((double)workTime);
|
|
|
- }
|
|
|
- else
|
|
|
+ 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)
|
|
|
{
|
|
|
- //获取后续生产时间段
|
|
|
- var nextPoints = workPoints.Where(p => p.Level > curPoint.Level).ToList();
|
|
|
- //剩余需要工作时长
|
|
|
- decimal nextMins = workTime - effMins;
|
|
|
- foreach (var p in nextPoints)
|
|
|
+ if (p.WorkMinutes >= nextMins)
|
|
|
{
|
|
|
- if (p.WorkMinutes >= nextMins)
|
|
|
- {
|
|
|
- workEndTime = p.StartPoint.AddMinutes((double)nextMins);
|
|
|
- break;
|
|
|
- }
|
|
|
- nextMins -= p.WorkMinutes;
|
|
|
+ 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
|
|
|
- });
|
|
|
}
|
|
|
+ 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
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -743,7 +1017,7 @@ namespace Business.ResourceExamineManagement
|
|
|
shopCal = curCalendars.Where(p =>string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == weekDay).FirstOrDefault();
|
|
|
}
|
|
|
//当前日期的工作时间段
|
|
|
- List<LineWorkPointDto> workPoints = DealWorkDayToLevels(startTime, shopCal, curQtyDtls);
|
|
|
+ List<LineWorkPointDto> workPoints = DealWorkDayToLevels(lineStart.Line, startTime, shopCal, curQtyDtls);
|
|
|
//当天排产结束时间
|
|
|
scheduledDto.EndTime = workPoints.Last().EndPoint;
|
|
|
//计算starttime处于那个工作时间段
|
|
|
@@ -757,9 +1031,9 @@ namespace Business.ResourceExamineManagement
|
|
|
span = item.EndPoint - item.StartPoint;
|
|
|
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));
|
|
|
+ ////判断产线当天有没有加班
|
|
|
+ //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
|
|
|
var curRunCrews = prodLineDetailRunCrews.Where(p=>p.ProdLineDetailRecID == lineStart.RecID).ToList();
|
|
|
//判断当前日期是否配置了UPH
|
|
|
@@ -798,7 +1072,7 @@ namespace Business.ResourceExamineManagement
|
|
|
//产线工作日历:当前产线的工作日历+默认工作日历
|
|
|
var curCalendars = calendars.Where(p => p.ProdLine == lines[0].Line || string.IsNullOrEmpty(p.ProdLine)).ToList();
|
|
|
var curQtyDtls = qualityLines.Where(p=>p.ProdLine == lines[0].Line).ToList();
|
|
|
- actStart = CalcActStartTime(actStart, curCalendars, curQtyDtls);
|
|
|
+ actStart = CalcActStartTime(lines[0].Line, actStart, curCalendars, curQtyDtls);
|
|
|
lineStart.RecID = lines[0].RecID;
|
|
|
lineStart.Line = lines[0].Line;
|
|
|
lineStart.StartTime = actStart;
|
|
|
@@ -814,7 +1088,7 @@ namespace Business.ResourceExamineManagement
|
|
|
//产线工作日历:当前产线的工作日历+默认工作日历
|
|
|
curCalendars = calendars.Where(p => p.ProdLine == lines[i].Line || string.IsNullOrEmpty(p.ProdLine)).ToList();
|
|
|
curQtyDtls = qualityLines.Where(p => p.ProdLine == lines[i].Line).ToList();
|
|
|
- StartTime = CalcActStartTime(StartTime, curCalendars, curQtyDtls);
|
|
|
+ StartTime = CalcActStartTime(lines[0].Line, StartTime, curCalendars, curQtyDtls);
|
|
|
if (StartTime < lineStart.StartTime)
|
|
|
{
|
|
|
lineStart.RecID = lines[i].RecID;
|
|
|
@@ -831,11 +1105,12 @@ namespace Business.ResourceExamineManagement
|
|
|
/// <summary>
|
|
|
/// 计算主产线实际排产开始时间
|
|
|
/// </summary>
|
|
|
+ /// <param name="prodLine">生产线</param>
|
|
|
/// <param name="startTime">开始时间</param>
|
|
|
/// <param name="curCalendars">当前产线工作日历+默认工作日历</param>
|
|
|
/// <param name="curQtyDtls">当前产线休息记录</param>
|
|
|
/// <returns></returns>
|
|
|
- public DateTime CalcActStartTime(DateTime startTime, List<ShopCalendarWorkCtr> curCalendars, List<QualityLineWorkDetail> curQtyDtls)
|
|
|
+ public DateTime CalcActStartTime(string prodLine,DateTime startTime, List<ShopCalendarWorkCtr> curCalendars, List<QualityLineWorkDetail> curQtyDtls)
|
|
|
{
|
|
|
//实际排产开始时间
|
|
|
DateTime actStart = startTime;
|
|
|
@@ -858,7 +1133,7 @@ namespace Business.ResourceExamineManagement
|
|
|
shopCal = curCalendars.Where(p => string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == weekDay).FirstOrDefault();
|
|
|
}
|
|
|
//当前日期的工作时间段
|
|
|
- List<LineWorkPointDto> workPoints = DealWorkDayToLevels(startTime, shopCal, curQtyDtls);
|
|
|
+ List<LineWorkPointDto> workPoints = DealWorkDayToLevels(prodLine, startTime, shopCal, curQtyDtls);
|
|
|
//计算starttime处于那个工作时间段
|
|
|
var curPoint = workPoints.Where(p => startTime >= p.StartPoint && startTime <= p.EndPoint).FirstOrDefault();
|
|
|
if (curPoint == null)//不处于工作时间段
|
|
|
@@ -1032,7 +1307,7 @@ namespace Business.ResourceExamineManagement
|
|
|
//当前产线的休息时间设置
|
|
|
var curQtyDtls = qualityLines.Where(p => p.ProdLine == line.Line).ToList();
|
|
|
//当前日期的工作时间段
|
|
|
- List<LineWorkPointDto> workPoints = DealWorkDayToLevels(startTime, shopCal, curQtyDtls);
|
|
|
+ List<LineWorkPointDto> workPoints = DealWorkDayToLevels(line.Line, startTime, shopCal, curQtyDtls);
|
|
|
//计算starttime处于那个工作时间段
|
|
|
var curPoint = workPoints.Where(p => startTime >= p.StartPoint && startTime <= p.EndPoint).FirstOrDefault();
|
|
|
//当前时间段可用时长
|
|
|
@@ -1076,7 +1351,7 @@ namespace Business.ResourceExamineManagement
|
|
|
{
|
|
|
curCalendar = calendars.Where(p => string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == weekDay).FirstOrDefault();
|
|
|
}
|
|
|
- workPoints = DealWorkDayToLevels(nextStartTime, curCalendar, curQtyDtls).OrderBy(p => p.Level).ToList();
|
|
|
+ workPoints = DealWorkDayToLevels(line.Line, nextStartTime, curCalendar, curQtyDtls).OrderBy(p => p.Level).ToList();
|
|
|
//当天的工作时长(分钟)
|
|
|
decimal sumWorkMins = workPoints.Sum(p => p.WorkMinutes);
|
|
|
if (sumWorkMins >= needMinute)//当天可用提前期满足
|
|
|
@@ -1149,11 +1424,12 @@ namespace Business.ResourceExamineManagement
|
|
|
/// <summary>
|
|
|
/// 处理当前日期的工作时间段
|
|
|
/// </summary>
|
|
|
+ /// <param name="prodLine"></param>
|
|
|
/// <param name="startTime"></param>
|
|
|
/// <param name="shopCal">当前产线的工作日历-周几</param>
|
|
|
/// <param name="curQtyDtls">每天休息记录</param>
|
|
|
/// <returns></returns>
|
|
|
- public List<LineWorkPointDto> DealWorkDayToLevels(DateTime startTime, ShopCalendarWorkCtr shopCal, List<QualityLineWorkDetail> curQtyDtls)
|
|
|
+ public List<LineWorkPointDto> DealWorkDayToLevels(string prodLine, DateTime startTime, ShopCalendarWorkCtr shopCal, List<QualityLineWorkDetail> curQtyDtls)
|
|
|
{
|
|
|
//年-月-日
|
|
|
string date = startTime.Date.ToString("yyyy-MM-dd");
|
|
|
@@ -1170,7 +1446,7 @@ namespace Business.ResourceExamineManagement
|
|
|
//结束时间
|
|
|
DateTime dayEndPoint = dayStartPoint.AddHours((double)(shopCal.ShiftsHours1 + shopCal.ShiftsHours2));
|
|
|
dto.Level = level;
|
|
|
- dto.Line = shopCal.ProdLine;
|
|
|
+ dto.Line = prodLine;
|
|
|
dto.WeekDay = weekDay;
|
|
|
dto.StartPoint = dayStartPoint;
|
|
|
//按照产线休息时间切分时间段
|
|
|
@@ -1185,7 +1461,7 @@ namespace Business.ResourceExamineManagement
|
|
|
level++;
|
|
|
dto = new LineWorkPointDto();
|
|
|
dto.Level = level;
|
|
|
- dto.Line = shopCal.ProdLine;
|
|
|
+ dto.Line = prodLine;
|
|
|
dto.WeekDay = weekDay;
|
|
|
dto.StartPoint = endPoint.AddMinutes(item.RestTime);
|
|
|
}
|
|
|
@@ -1193,6 +1469,20 @@ namespace Business.ResourceExamineManagement
|
|
|
span = dto.EndPoint - dto.StartPoint;
|
|
|
dto.WorkMinutes = (decimal)span.TotalMinutes;
|
|
|
workPoints.Add(dto);
|
|
|
+ //产线当天加班设置
|
|
|
+ var curOccupyTimes = resourceOccupancyTimes.Where(p => p.Resource == prodLine && p.StartTime.GetValueOrDefault().Date == startTime.Date).OrderBy(p=>p.StartTime).ToList();
|
|
|
+ foreach (var item in curOccupyTimes)
|
|
|
+ {
|
|
|
+ level++;
|
|
|
+ dto = new LineWorkPointDto();
|
|
|
+ dto.Level = level;
|
|
|
+ dto.Line = prodLine;
|
|
|
+ dto.WeekDay = weekDay;
|
|
|
+ dto.StartPoint = item.StartTime.GetValueOrDefault();
|
|
|
+ dto.EndPoint = dto.StartPoint.AddHours(Convert.ToDouble(item.Ufld1));
|
|
|
+ dto.WorkMinutes = Convert.ToDecimal(item.Ufld1) * 60;
|
|
|
+ workPoints.Add(dto);
|
|
|
+ }
|
|
|
|
|
|
return workPoints.OrderBy(p => p.Level).ToList();
|
|
|
}
|