|
|
@@ -142,6 +142,21 @@ namespace Business.ResourceExamineManagement
|
|
|
/// </summary>
|
|
|
private ISqlRepository<NbrMaster> _nbrMaster;
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 工单工序开始准备时间记录
|
|
|
+ /// </summary>
|
|
|
+ private ISqlRepository<WorkOrdSetupTimeRecord> _workOrdSetupTimeRecord;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 工单工序开始准备时间记录
|
|
|
+ /// </summary>
|
|
|
+ private List<WorkOrdSetupTimeRecord> timeRecords;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 新增工序准备开始时间记录
|
|
|
+ /// </summary>
|
|
|
+ private List<WorkOrdSetupTimeRecord> inserts;
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 生产工单主表
|
|
|
/// </summary>
|
|
|
@@ -151,6 +166,11 @@ namespace Business.ResourceExamineManagement
|
|
|
/// 工厂id
|
|
|
/// </summary>
|
|
|
private string domain = "";
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 排产任务执行时间
|
|
|
+ /// </summary>
|
|
|
+ private DateTime scheTime;
|
|
|
#endregion
|
|
|
|
|
|
#region 构造函数
|
|
|
@@ -175,7 +195,8 @@ namespace Business.ResourceExamineManagement
|
|
|
ICurrentTenant currentTenant,
|
|
|
ISqlRepository<ScheduleExceptionMaster> scheduleExceptionMaster,
|
|
|
ISqlRepository<NbrMaster> nbrMaster,
|
|
|
- IRepository<mes_morder, long> mysql_mes_morder
|
|
|
+ IRepository<mes_morder, long> mysql_mes_morder,
|
|
|
+ ISqlRepository<WorkOrdSetupTimeRecord> workOrdSetupTimeRecord
|
|
|
)
|
|
|
{
|
|
|
_itemMaster = itemMaster;
|
|
|
@@ -196,6 +217,7 @@ namespace Business.ResourceExamineManagement
|
|
|
_currentTenant = currentTenant;
|
|
|
_scheduleExceptionMaster = scheduleExceptionMaster;
|
|
|
_mysql_mes_morder = mysql_mes_morder;
|
|
|
+ _workOrdSetupTimeRecord = workOrdSetupTimeRecord;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
@@ -210,29 +232,38 @@ namespace Business.ResourceExamineManagement
|
|
|
|
|
|
//获取需要排产的工单(获取四周的工单:正常工单+已审批通过的特殊工单)
|
|
|
DateTime endDate = DateTime.Now.Date.AddDays(28).AddDays(1);
|
|
|
- //取数开始时间为当前天的下一天
|
|
|
- DateTime startDate = DateTime.Now.Date.AddDays(1);
|
|
|
+ //取数开始时间为当前时间
|
|
|
+ DateTime startTime = DateTime.Now;
|
|
|
+ scheTime = startTime;
|
|
|
//尚未开始生产的工单+正在生产的工单
|
|
|
- var workOrds = _workOrdMaster.Select(p => p.IsActive && p.Domain == domain && ((p.OrdDate < endDate && p.OrdDate >= startDate && (string.IsNullOrEmpty(p.Typed) || (!string.IsNullOrEmpty(p.Typed) && p.Typed.ToUpper() != "PW" && p.BusinessID >0 ))) || p.Status.ToLower() == "w")).ToList();
|
|
|
+ var workOrds = _workOrdMaster.Select(p => p.IsActive && p.Domain == domain && ((p.OrdDate < endDate && p.OrdDate >= startTime && p.Status.ToUpper() =="P" && (string.IsNullOrEmpty(p.Typed) || (!string.IsNullOrEmpty(p.Typed) && p.Typed.ToUpper() != "PW" && p.BusinessID >0 ))) || p.Status.ToUpper() == "W")).ToList();
|
|
|
if (workOrds.Any())
|
|
|
{
|
|
|
- await DoProductSchedule(workOrds, domain, 1);
|
|
|
+ await DoProductSchedule(startTime, workOrds, domain, 1);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 生产排产
|
|
|
/// </summary>
|
|
|
+ /// <param name="startTime">排产开始时间</param>
|
|
|
/// <param name="workOrds">需要重新排产的工单</param>
|
|
|
/// <param name="factoryid">工单的工厂id</param>
|
|
|
/// <param name="type">排产类型:1-自动排产;2-手动排产</param>
|
|
|
/// <returns></returns>
|
|
|
- public async Task<string> DoProductSchedule(List<WorkOrdMaster> workOrds, string factoryid,int type)
|
|
|
+ public async Task<string> DoProductSchedule(DateTime startTime,List<WorkOrdMaster> workOrds, string factoryid,int type)
|
|
|
{
|
|
|
//记录工厂id
|
|
|
domain = factoryid;
|
|
|
- //工单排产的最早日期
|
|
|
- DateTime earlist = DateTime.Now.Date.AddDays(1);
|
|
|
+ //记录排产开始时间
|
|
|
+ scheTime = startTime;
|
|
|
+
|
|
|
+ //记录正在投产工单的优先级
|
|
|
+ var dbWorkOrds = workOrds.Where(p => p.Status.ToUpper() == "W").ToList();
|
|
|
+ //正在投产工单的优先级设为负数,确保重新排产时,正在投产的工单优先级最高
|
|
|
+ workOrds.ForEach(p => {
|
|
|
+ p.Priority = p.Status.ToUpper() == "W" ? -1 : p.Priority;
|
|
|
+ });
|
|
|
//特殊工单指定时间开工,不需要计算产能,只需要计算时长即可
|
|
|
var tsWorkOrds = workOrds.Where(p => !string.IsNullOrEmpty(p.Typed)).ToList();
|
|
|
//正常工单
|
|
|
@@ -250,21 +281,20 @@ 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();
|
|
|
- //获取生产周期数据
|
|
|
- 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);
|
|
|
- ////获取锁定期之外的工单排产数据
|
|
|
- //List<PeriodSequenceDet> delPeriodSequences = dbPeriodSequences.Where(p => workOrds.Select(m => m.WorkOrd).Contains(p.WorkOrds)).ToList();
|
|
|
- //List<ScheduleResultOpMaster> delSchedules = dbSchedules.Where(p => workOrds.Select(m => m.WorkOrd).Contains(p.WorkOrd)).ToList();
|
|
|
- ////产线占用记录排除锁定期之前的工单
|
|
|
- //dbSchedules = dbSchedules.Where(p => !workOrds.Select(m => m.WorkOrd).Contains(p.WorkOrd)).ToList();
|
|
|
+
|
|
|
//获取工作日历数据:产线的工作日历+默认的工作日历
|
|
|
calendars = _shopCalendarWorkCtr.Select(p => (lines.Contains(p.ProdLine) || string.IsNullOrEmpty(p.ProdLine)) && 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);
|
|
|
+ holidays = _holidayMaster.Select(p => p.Domain == domain && p.IsActive && p.Dated >= scheTime.Date);
|
|
|
+ //获取工单的准备开始时间记录
|
|
|
+ timeRecords = _workOrdSetupTimeRecord.Select(p=>p.Domain == domain && workOrds.Select(m => m.WorkOrd).Contains(p.WorkOrd));
|
|
|
+
|
|
|
+ //获取当天的生产周期数据
|
|
|
+ List<PeriodSequenceDet> dbPeriodSequences = _periodSequenceDet.Select(p => lines.Contains(p.Line) && p.PlanDate == scheTime.Date && p.Domain == domain && p.IsActive);
|
|
|
+ //获取当前日期往后的排产记录数据
|
|
|
+ List<ScheduleResultOpMaster> dbSchedules = _scheduleResultOpMaster.Select(p => lines.Contains(p.Line) && p.WorkDate == scheTime.Date && p.Domain == domain);
|
|
|
|
|
|
//排产前校验
|
|
|
List<ScheduleExceptionMaster> exceptions = BeforeScheduleCheck(workOrds, workOrdRoutings, prodLines,type);
|
|
|
@@ -294,13 +324,17 @@ namespace Business.ResourceExamineManagement
|
|
|
List<ScheduleResultOpMaster> scheduleMasters = new List<ScheduleResultOpMaster>();
|
|
|
//记录排产结果
|
|
|
List<ScheduleResultOpMaster> allResults = new List<ScheduleResultOpMaster>();
|
|
|
- //allResults.AddRange(dbSchedules);
|
|
|
//记录特殊工单排产结果
|
|
|
List<string> ypcWorkOrds = new List<string>();
|
|
|
//按照优先级排序
|
|
|
zcWorkOrds = zcWorkOrds.OrderBy(p=>p.Priority).ToList();
|
|
|
foreach (var item in zcWorkOrds)
|
|
|
{
|
|
|
+ //如果工单预计开工日期在排产时间之后,则跳过
|
|
|
+ if (item.OrdDate > scheTime)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
//记录产线占用情况
|
|
|
allResults.AddRange(scheduleMasters);
|
|
|
//当前工单工艺路线主产线的关键工序
|
|
|
@@ -310,13 +344,6 @@ namespace Business.ResourceExamineManagement
|
|
|
|
|
|
//产线排产
|
|
|
LineSchedule(item, curRoutings, curProdLines, periodSequenceDtls, scheduleMasters, allResults, tsWorkOrds, ypcWorkOrds, tsWoRoutings);
|
|
|
-
|
|
|
- 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);
|
|
|
- }
|
|
|
}
|
|
|
//判断是否有特殊工单没有排产,如果有,则对剩余特殊工单排产
|
|
|
var notSchedules = tsWorkOrds.Where(p => !ypcWorkOrds.Contains(p.WorkOrd)).ToList();
|
|
|
@@ -329,7 +356,7 @@ namespace Business.ResourceExamineManagement
|
|
|
//剩余工作时长(分钟)
|
|
|
decimal usedTime = Math.Ceiling(qtyNeed / item.QtyOrded * item.LbrVar * 60);
|
|
|
//特殊工单排产开始时间
|
|
|
- DateTime startTime = item.OrdDate.GetValueOrDefault();
|
|
|
+ DateTime tStartTime = item.OrdDate.GetValueOrDefault();
|
|
|
//如果当前特殊工单正在生产,则开工日期为当天的下一个工作日
|
|
|
if (item.Status.ToLower() == "w" && item.JointTyped.ToUpper() != "B")
|
|
|
{
|
|
|
@@ -344,7 +371,7 @@ namespace Business.ResourceExamineManagement
|
|
|
WorkOrd = item.WorkOrd,
|
|
|
ItemNum = item.ItemNum,
|
|
|
QtyOrded = qtyNeed,
|
|
|
- OrdDate = startTime,
|
|
|
+ OrdDate = tStartTime,
|
|
|
ProdLine = item.ProdLine,
|
|
|
LbrVar = usedTime,
|
|
|
Worked = 0,
|
|
|
@@ -354,15 +381,26 @@ namespace Business.ResourceExamineManagement
|
|
|
});
|
|
|
}
|
|
|
TsLineSchedule(workDtos, periodSequenceDtls, scheduleMasters);
|
|
|
- //处理特殊工单计划开始日期、计划结束日期
|
|
|
- foreach (var item in tsWorkOrds)
|
|
|
+ //处理工单计划开始日期、计划结束日期
|
|
|
+ foreach (var item in workOrds)
|
|
|
{
|
|
|
+ //如果工单正在投产,则不需要回写
|
|
|
+ if (item.Status.ToUpper() == "W")
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
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);
|
|
|
}
|
|
|
+ //当前工单正在投产,则需要回写优先级
|
|
|
+ var curInfo = dbWorkOrds.FirstOrDefault(p => p.WorkOrd == item.WorkOrd);
|
|
|
+ if (curInfo != null)
|
|
|
+ {
|
|
|
+ item.Priority = curInfo.Priority;
|
|
|
+ }
|
|
|
}
|
|
|
var mesMorder = _mysql_mes_morder.GetListAsync(s => workOrds.Select(x => x.WorkOrd).Contains(s.morder_no) && s.factory_id.ToString() == domain).Result;
|
|
|
if(mesMorder.Any()) {
|
|
|
@@ -387,8 +425,17 @@ namespace Business.ResourceExamineManagement
|
|
|
await _mysql_mes_morder.UpdateManyAsync(mesMorder);
|
|
|
}
|
|
|
//删除当前日期下一天开始的工单排产记录
|
|
|
- _periodSequenceDet.Delete(dbPeriodSequences);
|
|
|
- _scheduleResultOpMaster.Delete(dbSchedules);
|
|
|
+ _periodSequenceDet.Delete(p=>p.PlanDate >scheTime.Date && p.Domain == domain);
|
|
|
+ _scheduleResultOpMaster.Delete(p=>p.WorkDate > scheTime.Date && p.Domain == domain);
|
|
|
+
|
|
|
+ //添加工单工序准备开始时间记录
|
|
|
+ if (inserts.Any())
|
|
|
+ {
|
|
|
+ _workOrdSetupTimeRecord.Insert(inserts);
|
|
|
+ }
|
|
|
+
|
|
|
+ //TODO:当天日计划数据调整
|
|
|
+
|
|
|
//保存排产记录
|
|
|
_periodSequenceDet.Insert(periodSequenceDtls);
|
|
|
_scheduleResultOpMaster.Insert(scheduleMasters);
|
|
|
@@ -3778,7 +3825,7 @@ namespace Business.ResourceExamineManagement
|
|
|
public LineStartDto DealStartTime(WorkOrdMaster workOrd,WorkOrdRouting routing,List<ProdLineDetail> prodLines, List<ScheduleResultOpMaster> allResults)
|
|
|
{
|
|
|
int op = routing.OP;
|
|
|
- DateTime actStart = DateTime.Now.Date.AddDays(1);
|
|
|
+ DateTime actStart = scheTime;
|
|
|
LineStartDto lineStart = new LineStartDto();
|
|
|
//获取工序对应的产线,根据优先级排序
|
|
|
var lines = prodLines.Where(p => p.Part == workOrd.ItemNum && p.Op == op).OrderBy(p => p.Sequence).ToList();
|
|
|
@@ -3814,17 +3861,162 @@ namespace Business.ResourceExamineManagement
|
|
|
lineStart.Rate = lines[i].Rate;
|
|
|
}
|
|
|
}
|
|
|
- //如果当前工单正在排产,且是连续排产时,重新排产不需要考虑产线准备时间
|
|
|
- if (workOrd.Status.ToLower() == "w" && workOrd.JointTyped.ToUpper() !="B")
|
|
|
+ //计算准备开始时间点与当前时间点的有效时长
|
|
|
+ decimal sumTimes = 0m;
|
|
|
+ //获取工序开始准备时长记录
|
|
|
+ var curRecord = timeRecords.FirstOrDefault(p =>p.Domain == domain && p.WorkOrd == workOrd.WorkOrd && p.Op == op);
|
|
|
+ if (curRecord != null)
|
|
|
+ {
|
|
|
+ sumTimes = CalcTimeMins(curRecord.StartTime, lineStart.StartTime, lineStart.Line);
|
|
|
+ //如果当前工单状态为生产中"W",但是,调整了日计划开工时间,则需要重新准备
|
|
|
+ if (workOrd.Status.ToUpper() == "W" && workOrd.JointTyped.ToUpper() == "B")
|
|
|
+ {
|
|
|
+ sumTimes = 0m;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //工单没有准备开始时间记录
|
|
|
+ else
|
|
|
{
|
|
|
- lineStart.setupTime = 0m;
|
|
|
+ inserts.Add(new WorkOrdSetupTimeRecord
|
|
|
+ {
|
|
|
+ Domain = workOrd.Domain,
|
|
|
+ WorkOrd = workOrd.WorkOrd,
|
|
|
+ ItemNum = workOrd.ItemNum,
|
|
|
+ Op = op,
|
|
|
+ StartTime = lineStart.StartTime,
|
|
|
+ CreateTime = DateTime.Now
|
|
|
+ });
|
|
|
}
|
|
|
+ //产线准备完成之后到当前时间点剩余时长(小时)
|
|
|
+ decimal restTime = lineStart.setupTime - sumTimes / 60;
|
|
|
+ lineStart.setupTime = restTime <= 0 ? 0 : restTime;
|
|
|
lineStart.Op = op;
|
|
|
lineStart.WaitTime = routing.WaitTime * 60;
|
|
|
- lineStart.QtyRemain = workOrd.QtyOrded - routing.QtyComplete;
|
|
|
+ //计算上次报工到当前时间点的预估生产数量,如果没有报工记录,则计算产线准备时间完成到当前时间点的预估生产数量
|
|
|
+ decimal planQty = 0m;
|
|
|
+ if (routing.Last == null && Math.Abs(restTime)>0)
|
|
|
+ {
|
|
|
+ //工序没有报工,使用产线准备完成之后到当前时间点剩余时长计算预估生产数量
|
|
|
+ planQty = Math.Floor(Math.Abs(restTime) * lineStart.Rate);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ //工序存在报工记录,计算报工时间点到当前时间点的有效生产时长,然后计算预估生产数量
|
|
|
+ sumTimes = CalcTimeMins(routing.Last.GetValueOrDefault(), lineStart.StartTime, lineStart.Line);
|
|
|
+ planQty = Math.Floor(sumTimes / 60 * lineStart.Rate);
|
|
|
+ }
|
|
|
+ //剩余待排产数量=工单数量-已报工数量-预估数量
|
|
|
+ lineStart.QtyRemain = workOrd.QtyOrded - routing.QtyComplete - planQty;
|
|
|
return lineStart;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 计算两个时间点之间的有效时长
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="startTime">开始时间</param>
|
|
|
+ /// <param name="endTime">结束时间</param>
|
|
|
+ /// <param name="line">产线</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public decimal CalcTimeMins(DateTime startTime, DateTime endTime, string line)
|
|
|
+ {
|
|
|
+ decimal sumTimes = 0m;
|
|
|
+ //如果开始时间大于结束时间直接返回0
|
|
|
+ if (endTime <= startTime)
|
|
|
+ {
|
|
|
+ return sumTimes;
|
|
|
+ }
|
|
|
+
|
|
|
+ TimeSpan span = TimeSpan.Zero;
|
|
|
+ //产线休息时间段设置
|
|
|
+ var curQtyDtls = qualityLines.Where(p => p.ProdLine == line).ToList();
|
|
|
+ //获取产线在开始时间当天的工作时间段
|
|
|
+ var curCalendar = calendars.FirstOrDefault(p => p.ProdLine == line && p.WeekDay == (int)startTime.DayOfWeek);
|
|
|
+ if (curCalendar == null)
|
|
|
+ {
|
|
|
+ curCalendar = calendars.FirstOrDefault(p => string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == (int)startTime.DayOfWeek);
|
|
|
+ }
|
|
|
+ List<LineWorkPointDto> workPoints = DealWorkDayToLevels(line, startTime, curCalendar, curQtyDtls);
|
|
|
+ //开始时间所处时间段
|
|
|
+ var srtPoint = workPoints.FirstOrDefault(p => p.StartPoint <= startTime && startTime <= p.EndPoint);
|
|
|
+ if (srtPoint == null)
|
|
|
+ {
|
|
|
+ //获取开始时间最近的时间段
|
|
|
+ srtPoint = workPoints.Where(p => p.EndPoint <= startTime).OrderBy(p => p.Level).Last();
|
|
|
+ startTime = srtPoint.EndPoint;
|
|
|
+ }
|
|
|
+ //开始时间、结束时间处于同一天
|
|
|
+ if (startTime.Date == endTime.Date)
|
|
|
+ {
|
|
|
+ //结束时间所处时间段
|
|
|
+ var lstPoint = workPoints.FirstOrDefault(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
|
|
|
+ //结束时间位于休息时间段
|
|
|
+ if (lstPoint == null)
|
|
|
+ {
|
|
|
+ //获取结束时间最近的时间段
|
|
|
+ lstPoint = workPoints.Where(p => p.EndPoint <= endTime).OrderBy(p => p.Level).Last();
|
|
|
+ endTime = lstPoint.EndPoint;
|
|
|
+ }
|
|
|
+ //开始时间和结束时间位于同一时间段
|
|
|
+ if (srtPoint.Level == lstPoint.Level)
|
|
|
+ {
|
|
|
+ span = endTime - startTime;
|
|
|
+ sumTimes = (decimal)span.TotalMinutes;
|
|
|
+ return sumTimes;
|
|
|
+ }
|
|
|
+ //开始时间,结束时间位于不同时间段
|
|
|
+ //计算开始时间所处时间段的有效时长
|
|
|
+ span = srtPoint.EndPoint - startTime;
|
|
|
+ sumTimes += (decimal)span.TotalMinutes;
|
|
|
+ //计算结束时间所处时间段的有效时长
|
|
|
+ span = endTime - lstPoint.StartPoint;
|
|
|
+ sumTimes += (decimal)span.TotalMinutes;
|
|
|
+ //计算开始时间,结束时间中间的工作时长
|
|
|
+ var others = workPoints.Where(p => p.Level > srtPoint.Level && p.Level < lstPoint.Level).ToList();
|
|
|
+ sumTimes += others.Sum(p => p.WorkMinutes);
|
|
|
+ return sumTimes;
|
|
|
+ }
|
|
|
+ //开始时间、结束时间不处于同一天
|
|
|
+ //1、计算开始时间所在当天剩余有效工作时长
|
|
|
+ span = srtPoint.EndPoint - startTime;
|
|
|
+ sumTimes += (decimal)span.TotalMinutes;
|
|
|
+ var nextPoints = workPoints.Where(p => p.Level > srtPoint.Level);
|
|
|
+ sumTimes += nextPoints.Sum(p => p.WorkMinutes);
|
|
|
+ //2、计算结束时间所在当天有效工作时长
|
|
|
+ curCalendar = calendars.FirstOrDefault(p => p.ProdLine == line && p.WeekDay == (int)endTime.DayOfWeek);
|
|
|
+ if (curCalendar == null)
|
|
|
+ {
|
|
|
+ curCalendar = calendars.FirstOrDefault(p => string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == (int)endTime.DayOfWeek);
|
|
|
+ }
|
|
|
+ workPoints = DealWorkDayToLevels(line, endTime, curCalendar, curQtyDtls);
|
|
|
+ var curPoint = workPoints.FirstOrDefault(p => p.StartPoint <= endTime && endTime <= p.EndPoint);
|
|
|
+ if (curPoint == null)
|
|
|
+ {
|
|
|
+ //获取结束时间最近的时间段
|
|
|
+ curPoint = workPoints.Where(p => p.EndPoint <= endTime).OrderBy(p => p.Level).Last();
|
|
|
+ endTime = curPoint.EndPoint;
|
|
|
+ }
|
|
|
+ span = endTime - curPoint.StartPoint;
|
|
|
+ sumTimes += (decimal)span.TotalMinutes;
|
|
|
+ nextPoints = workPoints.Where(p => p.Level < curPoint.Level);
|
|
|
+ sumTimes += nextPoints.Sum(p => p.WorkMinutes);
|
|
|
+ //3、计算中间天数的有效工作时长
|
|
|
+ span = endTime.Date - startTime.Date;
|
|
|
+ int days = span.Days;
|
|
|
+ for (int i = 1; i < days; i++)
|
|
|
+ {
|
|
|
+ var newDate = startTime.Date.AddDays(i);
|
|
|
+ //获取产线的工作时间段
|
|
|
+ curCalendar = calendars.FirstOrDefault(p => p.ProdLine == line && p.WeekDay == (int)newDate.DayOfWeek);
|
|
|
+ if (curCalendar == null)
|
|
|
+ {
|
|
|
+ curCalendar = calendars.FirstOrDefault(p => string.IsNullOrEmpty(p.ProdLine) && p.WeekDay == (int)newDate.DayOfWeek);
|
|
|
+ }
|
|
|
+ workPoints = DealWorkDayToLevels(line, newDate, curCalendar, curQtyDtls);
|
|
|
+ //当天的有效工作时长
|
|
|
+ sumTimes += workPoints.Sum(p => p.WorkMinutes);
|
|
|
+ }
|
|
|
+ return sumTimes;
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 计算主产线实际排产开始时间
|
|
|
/// </summary>
|
|
|
@@ -3974,13 +4166,21 @@ namespace Business.ResourceExamineManagement
|
|
|
/// <returns></returns>
|
|
|
public LineStartDto DealNextStartTime(WorkOrdMaster workOrd,LineStartDto lineStart,WorkOrdRouting routing, List<ProdLineDetail> prodLines, List<ScheduleResultOpMaster> allResults)
|
|
|
{
|
|
|
+ //本序工序编码
|
|
|
int op = routing.OP;
|
|
|
+ //获取上序实际开工时间
|
|
|
+ DateTime preStartTime = lineStart.StartTime;
|
|
|
+ var preRecord = timeRecords.FirstOrDefault(p=>p.WorkOrd == workOrd.WorkOrd && p.Domain == domain && p.Op == lineStart.Op);
|
|
|
+ if (preRecord != null)
|
|
|
+ {
|
|
|
+ preStartTime = preRecord.StartTime;
|
|
|
+ }
|
|
|
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);
|
|
|
+ DateTime startTime = CalcStartTimeWithSetUpTime(lines[0], preStartTime, lineStart.setupTime + lines[0].OverlapTime);
|
|
|
startDto.RecID = lines[0].RecID;
|
|
|
startDto.Line = lines[0].Line;
|
|
|
startDto.setupTime = lines[0].SetupTime;
|
|
|
@@ -3990,7 +4190,7 @@ namespace Business.ResourceExamineManagement
|
|
|
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 = CalcStartTimeWithSetUpTime(lines[i], preStartTime, lineStart.setupTime + lines[i].OverlapTime);
|
|
|
startTime = schedule == null ? startTime : (startTime < schedule.WorkEndTime ? schedule.WorkEndTime : startTime);
|
|
|
if (startTime < startDto.StartTime)
|
|
|
{
|