|
|
@@ -56,6 +56,12 @@ namespace Business.ResourceExamineManagement
|
|
|
private ISqlRepository<WorkOrdRouting> _workOrdRouting;
|
|
|
|
|
|
/// <summary>
|
|
|
+ /// 采购订单
|
|
|
+ /// </summary>
|
|
|
+ private ISqlRepository<PurOrdMaster> _purOrdMaster;
|
|
|
+ private ISqlRepository<PurOrdDetail> _purOrdDetail;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
/// 库存主数据
|
|
|
/// </summary>
|
|
|
private ISqlRepository<InvMaster> _invMaster;
|
|
|
@@ -111,6 +117,11 @@ namespace Business.ResourceExamineManagement
|
|
|
private ISqlRepository<ScheduleExceptionMaster> _scheduleExceptionMaster;
|
|
|
|
|
|
/// <summary>
|
|
|
+ /// 排产结果明细
|
|
|
+ /// </summary>
|
|
|
+ private ISqlRepository<ProductScheduleControl> _productScheduleControl;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
/// 雪花算法
|
|
|
/// </summary>
|
|
|
SnowFlake help = new SnowFlake();
|
|
|
@@ -186,6 +197,11 @@ namespace Business.ResourceExamineManagement
|
|
|
/// 排产任务执行时间
|
|
|
/// </summary>
|
|
|
private DateTime scheTime;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 可用设备数
|
|
|
+ /// </summary>
|
|
|
+ private readonly GetAvailableEquipmentAppService _getAvailableEquipmentAppService;
|
|
|
#endregion
|
|
|
|
|
|
#region 构造函数
|
|
|
@@ -212,6 +228,9 @@ namespace Business.ResourceExamineManagement
|
|
|
ISqlRepository<NbrMaster> nbrMaster,
|
|
|
IRepository<mes_morder, long> mysql_mes_morder,
|
|
|
ISqlRepository<WorkOrdSetupTimeRecord> workOrdSetupTimeRecord,
|
|
|
+ ISqlRepository<ProductScheduleControl> productScheduleControl,
|
|
|
+ ISqlRepository<PurOrdMaster> purOrdMaster,
|
|
|
+ ISqlRepository<PurOrdDetail> purOrdDetail,
|
|
|
ISqlRepository<NbrDetail> nbrDetail
|
|
|
)
|
|
|
{
|
|
|
@@ -232,9 +251,12 @@ namespace Business.ResourceExamineManagement
|
|
|
_generalizedCodeMaster = generalizedCodeMaster;
|
|
|
_currentTenant = currentTenant;
|
|
|
_scheduleExceptionMaster = scheduleExceptionMaster;
|
|
|
+ _productScheduleControl = productScheduleControl;
|
|
|
_mysql_mes_morder = mysql_mes_morder;
|
|
|
_workOrdSetupTimeRecord = workOrdSetupTimeRecord;
|
|
|
_nbrDetail = nbrDetail;
|
|
|
+ _purOrdMaster = purOrdMaster;
|
|
|
+ _purOrdDetail = purOrdDetail;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
@@ -370,11 +392,18 @@ 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<ItemMaster> itemMasters = _itemMaster.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 => lines.Contains(p.ProdLine) && p.Domain == domain && p.IsActive);
|
|
|
+ //外协采购订单
|
|
|
+ var pur = _purOrdMaster.Select(p => p.Potype == "PW" && workOrds.Select(m => m.WorkOrd).Contains(p.WorkOrd)).ToList();
|
|
|
+ List<string> purs = pur?.Select(p => p.PurOrd).Distinct().ToList();
|
|
|
+ var purd = _purOrdDetail.Select(p => purs.Contains(p.PurOrd)).ToList();
|
|
|
+ //历史排产记录
|
|
|
+ List<ScheduleResultOpMaster> previouslyOP = _scheduleResultOpMaster.Select(s => workOrds.Select(m => m.WorkOrd).Contains(s.WorkOrd) && s.WorkEndTime < scheTime.Date);
|
|
|
//获取节假日记录数据
|
|
|
holidays = _holidayMaster.Select(p => p.Domain == domain && p.IsActive && p.Dated >= scheTime.Date);
|
|
|
//获取工单的准备开始时间记录
|
|
|
@@ -409,6 +438,11 @@ namespace Business.ResourceExamineManagement
|
|
|
List<ScheduleResultOpMaster> allResults = new List<ScheduleResultOpMaster>();
|
|
|
//按照优先级排序
|
|
|
workOrds = workOrds.OrderBy(p=>p.Priority).ToList();
|
|
|
+
|
|
|
+ var scheduleControl = _productScheduleControl.Select().FirstOrDefault();
|
|
|
+
|
|
|
+ var waitWork = workOrds.Where(w => !string.IsNullOrEmpty(w.WorkOrd)).ToList();
|
|
|
+
|
|
|
for (int i = 0; i < workOrds.Count; i++)
|
|
|
{
|
|
|
//记录产线占用情况
|
|
|
@@ -417,8 +451,51 @@ namespace Business.ResourceExamineManagement
|
|
|
var curRoutings = workOrdRoutings.Where(p => p.WorkOrd == workOrds[i].WorkOrd && p.ItemNum == workOrds[i].ItemNum && p.ParentOp == 0 && p.MilestoneOp).OrderBy(p => p.OP).ToList();
|
|
|
//当前工单的产线明细
|
|
|
var curProdLines = prodLines.Where(p => p.Part == workOrds[i].ItemNum).ToList();
|
|
|
+ //当前工单的物料主数据
|
|
|
+ var itemlist = itemMasters.Where(p => p.ItemNum == workOrds[i].ItemNum).ToList();
|
|
|
+ var check = new ItemMaster();
|
|
|
+ if (!itemlist.Any())
|
|
|
+ {
|
|
|
+ ScheduleExceptionMaster entity = new ScheduleExceptionMaster();
|
|
|
+ entity.Domain = workOrds[i].Domain;
|
|
|
+ entity.WorkOrd = workOrds[i].WorkOrd;
|
|
|
+ entity.ItemNum = workOrds[i].ItemNum;
|
|
|
+ entity.CreateTime = DateTime.Now;
|
|
|
+ entity.Remark = "排产异常:工单主物料在物料主数据中不存在,请维护后再操作!";
|
|
|
+ entity.Type = type == 1 ? "自动排产" : "手动排产";
|
|
|
+ entity.OptTime = DateTime.Now.ToString("yyyyMMddHHmmss");
|
|
|
+ exceptions.Add(entity);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ check = itemMasters.First(p => p.ItemNum == workOrds[i].ItemNum);
|
|
|
+ }
|
|
|
//产线排产
|
|
|
- LineSchedule(workOrds[i], curRoutings, curProdLines, periodSequenceDtls, scheduleMasters, allResults);
|
|
|
+ LineSchedule(workOrds[i], curRoutings, curProdLines, periodSequenceDtls, scheduleMasters, allResults, exceptions, previouslyOP,pur,purd, true, true);
|
|
|
+ waitWork.Remove(workOrds[i]);
|
|
|
+ if (scheduleMasters.Count > 0)
|
|
|
+ {
|
|
|
+ var isy = scheduleMasters.Where(s => s.WorkOrd == workOrds[i].WorkOrd).Count() > 0;
|
|
|
+ //当前工单未排产
|
|
|
+ if (!isy) { continue; }
|
|
|
+ var endTime = scheduleMasters.Where(s => s.WorkOrd == workOrds[i].WorkOrd).Max(s => s.WorkEndTime);
|
|
|
+ //换型优先级提前排产工单
|
|
|
+ var advanceWorkOrdNo = GetShortSetUpTimeWorkOrdNo(endTime, workOrds[i], curRoutings, curProdLines, waitWork, workOrdRoutings, prodLines);
|
|
|
+ if (!string.IsNullOrEmpty(advanceWorkOrdNo))
|
|
|
+ {
|
|
|
+ var advanceWorkOrd = workOrds.Where(w => w.WorkOrd == advanceWorkOrdNo).FirstOrDefault();
|
|
|
+ if (advanceWorkOrd != null && i != workOrds.Count - 1)
|
|
|
+ {
|
|
|
+ var curWork = workOrds[i];
|
|
|
+ //更改顺序为下一个
|
|
|
+ workOrds.Remove(advanceWorkOrd);
|
|
|
+ var index = workOrds.IndexOf(curWork);
|
|
|
+ i = index;
|
|
|
+ workOrds.Insert(index + 1, advanceWorkOrd);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
//回写工单优先级
|
|
|
foreach (var item in workOrds)
|
|
|
@@ -621,6 +698,44 @@ namespace Business.ResourceExamineManagement
|
|
|
return "OK";
|
|
|
}
|
|
|
|
|
|
+ //换型最短工单优先排产
|
|
|
+ public string GetShortSetUpTimeWorkOrdNo(DateTime startTime, WorkOrdMaster workOrd, List<WorkOrdRouting> curRoutings, List<ProdLineDetail> curProdLines, List<WorkOrdMaster> workOrds, List<WorkOrdRouting> workOrdRoutings, List<ProdLineDetail> prodLines)
|
|
|
+ {
|
|
|
+ //三天内的工单
|
|
|
+ var scopeWork = workOrds.Where(p => p.OrdDate >= startTime && p.OrdDate <= startTime.AddDays(3) && p.Priority > workOrd.Priority).ToList();
|
|
|
+ if (scopeWork.Any())
|
|
|
+ {
|
|
|
+ //相同物料的工单
|
|
|
+ var equalWork = scopeWork.Where(p => p.ItemNum == workOrd.ItemNum).OrderBy(p => p.Priority).FirstOrDefault();
|
|
|
+ if (equalWork == null)
|
|
|
+ {
|
|
|
+ //三天范围内工序
|
|
|
+ var scopeWorkNo = scopeWork.Select(p => p.WorkOrd).ToList();
|
|
|
+ var scopeRoutings = workOrdRoutings.Join(prodLines, r => new { ItemNum = r.ItemNum, OP = r.OP }, p => new { ItemNum = p.Part, OP = p.Op }, (r, p) => new { r, p.InternalEquipmentCode, p.MoldTypeCode, p.SetupTime }).Where(n => scopeWorkNo.Contains(n.r.WorkOrd)).ToList();
|
|
|
+ if (!scopeRoutings.Any()) { return ""; }
|
|
|
+ //本工单所有模具
|
|
|
+ var molds = curProdLines.Where(c => !string.IsNullOrEmpty(c.MoldTypeCode)).Select(c => c.MoldTypeCode).Distinct().ToList();
|
|
|
+ if (!molds.Any()) { return ""; }
|
|
|
+ //删除相同模具的准备时间
|
|
|
+ scopeRoutings.RemoveAll(r => molds.Contains(r.MoldTypeCode));
|
|
|
+ if (!scopeRoutings.Any()) { return ""; }
|
|
|
+ //计算剩下工序的总准备时间,取出最小值
|
|
|
+ var routings = scopeRoutings.GroupBy(s => s.r.WorkOrd).Select(g => new { WorkOrd = g.Key, SumTime = g.Sum(p => p.SetupTime) }).OrderBy(g => g.SumTime).ToList();
|
|
|
+ equalWork = scopeWork.Where(s => s.WorkOrd == routings[0].WorkOrd).First();
|
|
|
+ //物料不一样但工序一样导致全部删除的工单换型时间为0
|
|
|
+ if (routings.Count < scopeWorkNo.Count && scopeWorkNo.Count > 0 && routings.Count > 0)
|
|
|
+ {
|
|
|
+ var works = routings.Select(p => p.WorkOrd).ToList();
|
|
|
+ scopeWorkNo.RemoveAll(p => works.Contains(p));
|
|
|
+ equalWork = workOrds.Where(w => scopeWorkNo.Contains(w.WorkOrd)).OrderBy(w => w.Priority).First();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return equalWork == null ? "" : equalWork.WorkOrd;
|
|
|
+ }
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 排产前校验
|
|
|
/// </summary>
|
|
|
@@ -710,7 +825,65 @@ namespace Business.ResourceExamineManagement
|
|
|
exceptions.Add(entity);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ //获取当前工单物料对应的产线信息
|
|
|
+ var curRoutingss = workOrdRoutings.Where(p => p.WorkOrd == item.WorkOrd && p.ItemNum == item.ItemNum && p.MilestoneOp && p.ProcessOut != 1).ToList();
|
|
|
+ lineDetails = prodLines.Where(x => x.Part == item.ItemNum && curRoutingss.Select(c => c.OP).ToList().Contains(x.Op)).ToList();
|
|
|
+ if (exceptions.FindIndex(e => e.WorkOrd == item.WorkOrd) < 0)
|
|
|
+ {
|
|
|
+ if (!lineDetails.Any() || lineDetails?.Count == 0)
|
|
|
+ {
|
|
|
+ //产线物料中找不到时检查工单工序表是否有维护
|
|
|
+ var curRoutingsOp = workOrdRoutings.Where(r => curRoutingss.Select(c => c.OP).ToList().Contains(r.OP) && r.MachBdnRate != 0 && (r.WorkCode != "P" && !string.IsNullOrEmpty(r.Machine) || r.WorkCode == "P")).ToList();
|
|
|
+ if (!curRoutingsOp.Any() || curRoutingsOp?.Count == 0)
|
|
|
+ {
|
|
|
+ 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 ? "自动排产" : "手动排产";
|
|
|
+ entity.OptTime = optTime;
|
|
|
+ exceptions.Add(entity);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var Routings = curRoutingsOp.Where(p => (p.WorkCode != "P" && string.IsNullOrEmpty(p.Machine)) || (p.Engineer != "" && p.Engineer != "/" && p.RunCrew == 0)).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 ? "自动排产" : "手动排产";
|
|
|
+ entity.OptTime = optTime;
|
|
|
+ exceptions.Add(entity);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var line = lineDetails.Where(p => (p.OpType != "P" && string.IsNullOrEmpty(p.InternalEquipmentCode)) || (p.SkillNo != "" && p.SkillNo != "/" && p.StandardStaffCount == 0)).ToList();
|
|
|
+ if (line.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 ? "自动排产" : "手动排产";
|
|
|
+ entity.OptTime = optTime;
|
|
|
+ exceptions.Add(entity);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
//校验主产线关键工序对应的产线是否维护了工作日历
|
|
|
var curCalendars = calendars.Where(x => lineDetails.Select(p => p.Line).Contains(x.ProdLine) || string.IsNullOrEmpty(x.ProdLine)).ToList();
|
|
|
foreach (var rut in lineDetails)
|
|
|
@@ -759,7 +932,7 @@ 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)
|
|
|
+ public void LineSchedule(WorkOrdMaster workOrd, List<WorkOrdRouting> workOrdRoutings, List<ProdLineDetail> prodLines,List<PeriodSequenceDet> periodsDet, List<ScheduleResultOpMaster> scheduleResults, List<ScheduleResultOpMaster> allResults, List<ScheduleExceptionMaster> exceptions, List<ScheduleResultOpMaster> previouslyOP,List<PurOrdMaster> pur,List<PurOrdDetail> purd, bool Check = false, bool UseSkill = true)
|
|
|
{
|
|
|
//生产周期
|
|
|
List<PeriodSequenceDet> curSequences = new List<PeriodSequenceDet>();
|
|
|
@@ -770,28 +943,333 @@ namespace Business.ResourceExamineManagement
|
|
|
//产线开工时间默认为当前时间
|
|
|
lineStart.StartTime = scheTime;
|
|
|
TimeSpan span = TimeSpan.Zero;
|
|
|
+ var remainNum = 0m;
|
|
|
//第一层级工序有几个关键工序,就有几条产线
|
|
|
for (int i = 0; i < workOrdRoutings.Count; i++)
|
|
|
{
|
|
|
+ var Maxednum = 0;
|
|
|
+ List<ScheduleResultOpMaster> LastcurScheduleRsts = new List<ScheduleResultOpMaster>();
|
|
|
+ //获取工序对应的产线,根据优先级排序
|
|
|
+ var lines = prodLines.Where(p => p.Part == workOrd.ItemNum && p.Op == workOrdRoutings[i].OP && p.Bom == workOrd.Refs).OrderBy(p => p.Sequence).ToList();
|
|
|
+ //没有对应工艺且工序表无记录
|
|
|
+ if (!lines.Any() && workOrdRoutings[i].MachBdnRate == 0)
|
|
|
+ {
|
|
|
+ lines = prodLines.Where(p => p.Part == workOrd.ItemNum && p.Op == workOrdRoutings[i].OP).OrderBy(p => p.Sequence).ToList();
|
|
|
+ }
|
|
|
+ var Line = !string.IsNullOrEmpty(workOrdRoutings[i].ProdLine) ? workOrdRoutings[i].ProdLine : (lines.Count > 0 ? lines[0].Line : workOrdRoutings[i].ProdLine);
|
|
|
+ //当前产线的工作日历
|
|
|
+ var mLCalendars = calendars.Where(p => p.WorkCtr == Line || string.IsNullOrEmpty(p.ProdLine)).ToList();
|
|
|
+ //当前产线的休息时间设置
|
|
|
+ var mlqtyWorkDtls = qualityLines.Where(p => p.ProdLine == Line).ToList();
|
|
|
+ var Rate = workOrdRoutings[i].MachBdnRate > 0 ? workOrdRoutings[i].MachBdnRate : (lines.Count > 0 ? lines[0].Rate : workOrdRoutings[i].MachBdnRate);
|
|
|
+ var OpType = !string.IsNullOrEmpty(workOrdRoutings[i].WorkCode) ? workOrdRoutings[i].WorkCode : (lines.Count > 0 ? lines[0].OpType : workOrdRoutings[i].WorkCode);
|
|
|
+ decimal ScaleNum = 1m;
|
|
|
+ if (!Check && lineStart.Rate < Rate && lineStart.Rate != 0 && i != 0)
|
|
|
+ {
|
|
|
+ ScaleNum = lineStart.Rate / Rate;
|
|
|
+ }
|
|
|
+ //var lines = prodLines.Where(p => p.Part == workOrd.ItemNum && p.Op == workOrdRoutings[i].OP).OrderBy(p => p.Sequence).ToList();
|
|
|
+ //外协工序特殊处理,不进入产能计算
|
|
|
+ if (workOrdRoutings[i].ProcessOut == 1)
|
|
|
+ {
|
|
|
+ //对应外协采购订单
|
|
|
+ var curpur = pur.Where(p => p.Potype == "PW" && p.WorkOrd == workOrd.WorkOrd).First();
|
|
|
+ List<string> purs = pur?.Select(p => p.PurOrd).Distinct().ToList();
|
|
|
+ PurOrdDetail curpurd = purd.Where(p => purs.Contains(p.PurOrd) && p.ItemNum == workOrdRoutings[i].ItemNum && p.Op == workOrdRoutings[i].OP).Count() > 0 ? _purOrdDetail.Select(p => purs.Contains(p.PurOrd) && p.ItemNum == workOrdRoutings[i].ItemNum && p.Op == workOrdRoutings[i].OP).First() : null;
|
|
|
+ //前序排产记录
|
|
|
+ LastcurScheduleRsts = curScheduleRsts?.Where(c => c.Op == lineStart.Op).ToList();
|
|
|
+ //如果有采购订单则取订单日期,没有则取上序的开始时间,再没有则取当前日期
|
|
|
+ //DateTime StartTime = purd != null ? pur.Where(p => p.PurOrd == purd.PurOrd).First().OrdDate.GetValueOrDefault() :
|
|
|
+ DateTime StartTime = LastcurScheduleRsts != null && LastcurScheduleRsts.Count > 0 ? LastcurScheduleRsts[LastcurScheduleRsts.Count - 1].WorkStartTime : scheTime;
|
|
|
+ //判断是否工作日
|
|
|
+ var isworkday = CheckIsWorkDay(StartTime);
|
|
|
+ while (!isworkday)
|
|
|
+ {
|
|
|
+ StartTime = StartTime.AddDays(1);
|
|
|
+ isworkday = CheckIsWorkDay(StartTime);
|
|
|
+ }
|
|
|
+ var line = pur.Count > 0 ? pur.Where(p => p.PurOrd == curpur.PurOrd).First().Supp : workOrdRoutings[i].ProcessOutSupp;
|
|
|
+ var qty = purd != null ? curpurd.QtyOrded : workOrd.QtyOrded;
|
|
|
+ //记录生产周期
|
|
|
+ curSequences.Add(new PeriodSequenceDet
|
|
|
+ {
|
|
|
+ Domain = domain,
|
|
|
+ Line = line,
|
|
|
+ ItemNum = workOrd.ItemNum,
|
|
|
+ PlanDate = StartTime.Date,
|
|
|
+ Period = 1,
|
|
|
+ OrdQty = qty,
|
|
|
+ WorkOrds = workOrd.WorkOrd,
|
|
|
+ Op = workOrdRoutings[i].OP,
|
|
|
+ IsActive = true,
|
|
|
+ Status = "",
|
|
|
+ CreateTime = DateTime.Now,
|
|
|
+ UDate2 = StartTime
|
|
|
+ });
|
|
|
+ //记录排产记录
|
|
|
+ curScheduleRsts.Add(new ScheduleResultOpMaster
|
|
|
+ {
|
|
|
+ Domain = domain,
|
|
|
+ WorkOrd = workOrd.WorkOrd,
|
|
|
+ WorkCtr = "",
|
|
|
+ OpDescr = workOrdRoutings[i].Descr,
|
|
|
+ Line = line,
|
|
|
+ ItemNum = workOrd.ItemNum,
|
|
|
+ Op = workOrdRoutings[i].OP,
|
|
|
+ WorkDate = StartTime.Date,
|
|
|
+ WorkQty = qty,
|
|
|
+ WorkStartTime = StartTime,
|
|
|
+ WorkEndTime = curpurd != null ? (curpurd.DueDate.GetValueOrDefault() < StartTime.Date ? StartTime.AddDays(7) : curpurd.DueDate.GetValueOrDefault()) : StartTime.AddDays(7),//默认七天后到
|
|
|
+ CreateTime = DateTime.Now,
|
|
|
+ WorkActivateTime = StartTime,
|
|
|
+ SetupTime = 0,
|
|
|
+ DeviceAllocationCount = 0,
|
|
|
+ InternalEquipmentCode = "",
|
|
|
+ MoldTypeCode = "",
|
|
|
+ MoldAllocationCount = 0
|
|
|
+ });
|
|
|
+ //修改后序开始时间
|
|
|
+ lineStart.QtyRemain = qty;
|
|
|
+ lineStart.StartTime = StartTime;
|
|
|
+ lineStart.OneQty = qty;
|
|
|
+ lineStart.Op = workOrdRoutings[i].OP;
|
|
|
+ lineStart.Line = line;
|
|
|
+ lineStart.Rate = qty;
|
|
|
+ lineStart.setupTime = 0;
|
|
|
+ lineStart.WaitTime = 0;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //委外工序两边不同步
|
|
|
+ if (OpType == "M" && Rate == 0)
|
|
|
+ {
|
|
|
+ var entity = new ScheduleExceptionMaster();
|
|
|
+ entity.Domain = workOrd.Domain;
|
|
|
+ entity.WorkOrd = workOrd.WorkOrd;
|
|
|
+ entity.ItemNum = workOrd.ItemNum;
|
|
|
+ entity.CreateTime = DateTime.Now;
|
|
|
+ entity.Remark = $"{workOrd.WorkOrd}排产异常:{workOrdRoutings[i].OP}-机器工序未维护单位产能!";
|
|
|
+ entity.Type = "手动排产";
|
|
|
+ entity.OptTime = DateTime.Now.ToString("yyyyMMddHHmmss");
|
|
|
+ exceptions.Add(entity);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (OpType == "P" && Rate == 0)
|
|
|
+ {
|
|
|
+ var entity = new ScheduleExceptionMaster();
|
|
|
+ entity.Domain = workOrd.Domain;
|
|
|
+ entity.WorkOrd = workOrd.WorkOrd;
|
|
|
+ entity.ItemNum = workOrd.ItemNum;
|
|
|
+ entity.CreateTime = DateTime.Now;
|
|
|
+ entity.Remark = $"{workOrd.WorkOrd}排产异常:{workOrdRoutings[i].OP}-人工工序未维护单位产能!";
|
|
|
+ entity.Type = "手动排产";
|
|
|
+ entity.OptTime = DateTime.Now.ToString("yyyyMMddHHmmss");
|
|
|
+ exceptions.Add(entity);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (Rate == 0)
|
|
|
+ {
|
|
|
+ var entity = new ScheduleExceptionMaster();
|
|
|
+ entity.Domain = workOrd.Domain;
|
|
|
+ entity.WorkOrd = workOrd.WorkOrd;
|
|
|
+ entity.ItemNum = workOrd.ItemNum;
|
|
|
+ entity.CreateTime = DateTime.Now;
|
|
|
+ entity.Remark = $"{workOrd.WorkOrd}排产异常:{workOrdRoutings[i].OP}-工序未维护单位产能!";
|
|
|
+ entity.Type = "手动排产";
|
|
|
+ entity.OptTime = DateTime.Now.ToString("yyyyMMddHHmmss");
|
|
|
+ exceptions.Add(entity);
|
|
|
+ return;
|
|
|
+ }
|
|
|
//产线实际排产开始时间
|
|
|
if (i == 0)//第一条产线
|
|
|
{
|
|
|
- lineStart = DealStartTime(workOrd, workOrdRoutings[i], prodLines, allResults);
|
|
|
+ lineStart = DealStartTime(workOrd, workOrdRoutings[i], lines, allResults, exceptions, mLCalendars, mlqtyWorkDtls, Check, UseSkill);
|
|
|
+ //var s = _scheduleResultOpMaster.Select(p => p.WorkOrd == workOrd.WorkOrd).ToList();
|
|
|
+ if (lineStart.equipmentNum == 0 && lineStart.OpType != "P" && exceptions.FindIndex(e => e.WorkOrd == workOrd.WorkOrd) < 0)
|
|
|
+ {
|
|
|
+ var entity = new ScheduleExceptionMaster();
|
|
|
+ entity.Domain = workOrd.Domain;
|
|
|
+ entity.WorkOrd = workOrd.WorkOrd;
|
|
|
+ entity.ItemNum = workOrd.ItemNum;
|
|
|
+ entity.CreateTime = DateTime.Now;
|
|
|
+ entity.Remark = $"{workOrd.WorkOrd}排产异常:{workOrdRoutings[i].OP}-{lineStart.InternalEquipmentCode}无可用设备!";
|
|
|
+ entity.Type = "手动排产";
|
|
|
+ entity.OptTime = DateTime.Now.ToString("yyyyMMddHHmmss");
|
|
|
+ exceptions.Add(entity);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //工单剩余制程(产能最小的工序使用最低设备数的时长+1天),排除人工工序和外协工序
|
|
|
+ var minrate = 0m;
|
|
|
+ var rcount = workOrdRoutings.Where(r => r.WorkCode != "P" && r.MachBdnRate > 0).ToList().Count;
|
|
|
+ if (rcount > 0)
|
|
|
+ {
|
|
|
+ minrate = workOrdRoutings.Where(r => r.WorkCode != "P" && r.MachBdnRate > 0).Min(r => r.MachBdnRate);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (prodLines.Where(p => p.Rate > 0).ToList().Count > 0)
|
|
|
+ {
|
|
|
+ rcount = prodLines.Where(p => p.OpType != "P" && p.Rate > 0).ToList().Count;
|
|
|
+ if (rcount > 0)
|
|
|
+ {
|
|
|
+ minrate = prodLines.Where(p => p.OpType != "P" && p.Rate > 0).Min(p => p.Rate);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ minrate = prodLines.Where(p => p.Rate > 0).Min(p => p.Rate);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ rcount = workOrdRoutings.Where(r => r.MachBdnRate > 0).ToList().Count;
|
|
|
+ if (rcount > 0)
|
|
|
+ {
|
|
|
+ minrate = workOrdRoutings.Where(r => r.MachBdnRate > 0).Min(p => p.MachBdnRate);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //>0? workOrdRoutings.Where(r => r.WorkCode != "P" && r.MachBdnRate != 0).Min(r=>r.MachBdnRate) : (prodLines.Where(p => p.OpType != "P" && p.Rate != 0).ToList().Count>0?prodLines.Where(p => p.OpType != "P" && p.Rate != 0).Min(p => p.Rate): prodLines.Where(p => p.Rate > 0).Min(p => p.Rate));
|
|
|
+ //var minrate = prodLines.Where(p => p.OpType != "P" && p.Rate != 0).Min(p => p.Rate);
|
|
|
+ var workMaxTime = (lineStart.QtyRemain / minrate) + 24;
|
|
|
+ //工单预计剩余生产天数
|
|
|
+ var wkspan = workOrd.DueDate.GetValueOrDefault() - lineStart.StartTime;
|
|
|
+ if (wkspan.TotalHours < 0)
|
|
|
+ {
|
|
|
+ wkspan = lineStart.StartTime.AddDays(1) - lineStart.StartTime;
|
|
|
+ }
|
|
|
+ var remainDay = ((decimal)wkspan.TotalHours - workMaxTime) / 2;
|
|
|
+ if (remainDay <= 0)
|
|
|
+ {
|
|
|
+ //remainDay = workMaxTime;
|
|
|
+ remainDay = (decimal)wkspan.TotalHours;
|
|
|
+ }
|
|
|
+ //预估每天生产量
|
|
|
+ remainNum = lineStart.QtyRemain / remainDay * 24;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- //获取前一产线排产开始时间,通过提前期计算当前产线排产开始时间
|
|
|
- lineStart = DealNextStartTime(workOrd, lineStart, workOrdRoutings[i], prodLines, allResults);
|
|
|
+ decimal lastsumqty = 0m;
|
|
|
+ int j = 0;
|
|
|
+ bool ispc = true;
|
|
|
+ //前序排产记录
|
|
|
+ LastcurScheduleRsts = curScheduleRsts.Where(c => c.Op == lineStart.Op).ToList();
|
|
|
+ if (LastcurScheduleRsts.Count == 0)
|
|
|
+ {
|
|
|
+ var entity = new ScheduleExceptionMaster();
|
|
|
+ entity.Domain = workOrd.Domain;
|
|
|
+ entity.WorkOrd = workOrd.WorkOrd;
|
|
|
+ entity.ItemNum = workOrd.ItemNum;
|
|
|
+ entity.CreateTime = DateTime.Now;
|
|
|
+ entity.Remark = $"{workOrd.WorkOrd}排产异常:{workOrdRoutings[i].OP}前序准备时间未刷新!";
|
|
|
+ entity.Type = "手动排产";
|
|
|
+ entity.OptTime = DateTime.Now.ToString("yyyyMMddHHmmss");
|
|
|
+ exceptions.Add(entity);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //每天所需设备数(向上圆整)
|
|
|
+ Maxednum = OpType == "P" && remainNum > 0 ? Convert.ToInt32(Math.Ceiling(remainNum / (Rate * 24))) : (remainNum <= 0 ? 1 : Convert.ToInt32(Math.Ceiling(remainNum / (Rate * 24) / 2)));
|
|
|
+ //非人工工序要获取可用设备数量
|
|
|
+ if (OpType != "P")
|
|
|
+ {
|
|
|
+ //可用数量
|
|
|
+ var numList = new List<string>();
|
|
|
+ //可插班的明细
|
|
|
+ ScheduleResultOpMaster schedule = null;
|
|
|
+ //维修结束时间
|
|
|
+ DateTime wxEndTime = lineStart.StartTime;
|
|
|
+ LineStartDto startDto = new LineStartDto();
|
|
|
+ startDto.InternalEquipmentCode = !string.IsNullOrEmpty(workOrdRoutings[i].Machine) ? workOrdRoutings[i].Machine : (lines.Count > 0 ? lines[0].InternalEquipmentCode : workOrdRoutings[i].Machine);
|
|
|
+ startDto.MoldTypeCode = !string.IsNullOrEmpty(workOrdRoutings[i].ToolCode) ? workOrdRoutings[i].ToolCode : (lines.Count > 0 ? lines[0].MoldTypeCode : workOrdRoutings[i].ToolCode);
|
|
|
+ startDto.WorkCtr = !string.IsNullOrEmpty(workOrdRoutings[i].WorkCtr) ? workOrdRoutings[i].WorkCtr : (lines.Count > 0 ? (lines[0].Site != workOrdRoutings[i].WorkCtr && !string.IsNullOrEmpty(workOrdRoutings[i].WorkCtr) ? workOrdRoutings[i].WorkCtr : lines[0].Site) : workOrdRoutings[i].WorkCtr);
|
|
|
+ startDto.RecID = lines.Count > 0 ? lines[0].RecID : 0;
|
|
|
+ startDto.Line = !string.IsNullOrEmpty(workOrdRoutings[i].ProdLine) ? workOrdRoutings[i].ProdLine : (lines.Count > 0 ? (lines[0].Line != workOrdRoutings[i].ProdLine && !string.IsNullOrEmpty(workOrdRoutings[i].ProdLine) ? workOrdRoutings[i].ProdLine : lines[0].Line) : workOrdRoutings[i].ProdLine);
|
|
|
+ startDto.setupTime = workOrdRoutings[i].StdSetupTime > 0 ? workOrdRoutings[i].StdSetupTime : (lines.Count > 0 ? lines[0].SetupTime : workOrdRoutings[i].StdSetupTime);
|
|
|
+ startDto.SkillNo = !string.IsNullOrEmpty(workOrdRoutings[i].Engineer) ? workOrdRoutings[i].Engineer : (lines.Count > 0 ? lines[0].SkillNo : workOrdRoutings[i].Engineer);
|
|
|
+ startDto.StandardStaffCount = workOrdRoutings[i].RunCrew > 0 ? workOrdRoutings[i].RunCrew : (lines.Count > 0 ? lines[0].StandardStaffCount : workOrdRoutings[i].RunCrew);
|
|
|
+ startDto.Rate = Rate;
|
|
|
+ startDto.OpType = OpType;
|
|
|
+ startDto.Op = workOrdRoutings[i].OP;
|
|
|
+ //设备可用数量和可用时间
|
|
|
+ AvailableQuantity(workOrd, lineStart.StartTime, startDto, lines, allResults, exceptions, out numList, out schedule, out wxEndTime, UseSkill);
|
|
|
+ Maxednum = numList.Count > 0 ? (numList[0].ToInt() > Maxednum ? Maxednum : numList[0].ToInt()) : Maxednum;
|
|
|
+ }
|
|
|
+ //true:按班次,false:按小时
|
|
|
+ var hourNum = Check ? 8 : 1;
|
|
|
+ var NowQty = lines.Count > 0 ? Maxednum * lines[0].Rate * hourNum * ScaleNum : Maxednum * workOrdRoutings[i].MachBdnRate * hourNum * ScaleNum;
|
|
|
+
|
|
|
+ while (ispc)
|
|
|
+ {
|
|
|
+ //前序满足本序产量
|
|
|
+ lineStart.StartTime = j >= LastcurScheduleRsts.Count ? LastcurScheduleRsts[j - 1].WorkEndTime : LastcurScheduleRsts[j].WorkEndTime;
|
|
|
+ lastsumqty += j == LastcurScheduleRsts.Count ? LastcurScheduleRsts[j - 1].WorkQty : LastcurScheduleRsts[j].WorkQty;
|
|
|
+ if (lastsumqty > NowQty || j == LastcurScheduleRsts.Count || i == workOrdRoutings.Count - 1)
|
|
|
+ {
|
|
|
+ if (!Check)
|
|
|
+ {
|
|
|
+ var hours = Math.Ceiling(NowQty / lineStart.Rate);
|
|
|
+ lineStart.StartTime = j == LastcurScheduleRsts.Count ? (LastcurScheduleRsts[j - 1].WorkEndTime > LastcurScheduleRsts[j - 1].WorkActivateTime.AddHours((double)hours) ? LastcurScheduleRsts[j - 1].WorkActivateTime.AddHours((double)hours) : LastcurScheduleRsts[j - 1].WorkEndTime) : (LastcurScheduleRsts[j].WorkEndTime > LastcurScheduleRsts[j].WorkActivateTime.AddHours((double)hours) ? LastcurScheduleRsts[j].WorkActivateTime.AddHours((double)hours) : LastcurScheduleRsts[j].WorkEndTime);
|
|
|
+ }
|
|
|
+ lineStart = DealNextStartTime(workOrd, lineStart, workOrdRoutings[i], lines, allResults, calendars, exceptions, mLCalendars, mlqtyWorkDtls, Check, UseSkill);
|
|
|
+ ispc = false;
|
|
|
+ }
|
|
|
+ j++;
|
|
|
+ }
|
|
|
+ if (lineStart.equipmentNum == 0 && lineStart.OpType != "P" && exceptions.FindIndex(e => e.WorkOrd == workOrd.WorkOrd) < 0)
|
|
|
+ {
|
|
|
+ var entity = new ScheduleExceptionMaster();
|
|
|
+ entity.Domain = workOrd.Domain;
|
|
|
+ entity.WorkOrd = workOrd.WorkOrd;
|
|
|
+ entity.ItemNum = workOrd.ItemNum;
|
|
|
+ entity.CreateTime = DateTime.Now;
|
|
|
+ entity.Remark = $"{workOrd.WorkOrd}排产异常:{workOrdRoutings[i].OP}-{lineStart.InternalEquipmentCode}无可用设备!";
|
|
|
+ entity.Type = "手动排产";
|
|
|
+ entity.OptTime = DateTime.Now.ToString("yyyyMMddHHmmss");
|
|
|
+ exceptions.Add(entity);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (exceptions.FindIndex(e => e.WorkOrd == workOrd.WorkOrd) >= 0)
|
|
|
+ {
|
|
|
+ return;
|
|
|
}
|
|
|
//如果当前工序已经生产完成,则跳过
|
|
|
if (lineStart.QtyRemain == 0)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
- //当前产线的工作日历
|
|
|
- var mLCalendars = calendars.Where(p => p.ProdLine == lineStart.Line || string.IsNullOrEmpty(p.ProdLine)).ToList();
|
|
|
- //当前产线的休息时间设置
|
|
|
- var mlqtyWorkDtls = qualityLines.Where(p => p.ProdLine == lineStart.Line).ToList();
|
|
|
+
|
|
|
+ if (lineStart.StartTime == DateTime.MinValue)
|
|
|
+ {
|
|
|
+ var entity = new ScheduleExceptionMaster();
|
|
|
+ entity.Domain = workOrd.Domain;
|
|
|
+ entity.WorkOrd = workOrd.WorkOrd;
|
|
|
+ entity.ItemNum = workOrd.ItemNum;
|
|
|
+ entity.CreateTime = DateTime.Now;
|
|
|
+ entity.Remark = $"{workOrd.WorkOrd}排产异常:{workOrdRoutings[i].OP}-{lineStart.InternalEquipmentCode}工序准备记录的产线错误!";
|
|
|
+ entity.Type = "手动排产";
|
|
|
+ entity.OptTime = DateTime.Now.ToString("yyyyMMddHHmmss");
|
|
|
+ exceptions.Add(entity);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (lineStart.setupTime > 240)
|
|
|
+ {
|
|
|
+ var entity = new ScheduleExceptionMaster();
|
|
|
+ entity.Domain = workOrd.Domain;
|
|
|
+ entity.WorkOrd = workOrd.WorkOrd;
|
|
|
+ entity.ItemNum = workOrd.ItemNum;
|
|
|
+ entity.CreateTime = DateTime.Now;
|
|
|
+ entity.Remark = $"{workOrd.WorkOrd}排产异常:{workOrdRoutings[i].OP}-{lineStart.InternalEquipmentCode}工序生产准备时长超过10天!";
|
|
|
+ entity.Type = "手动排产";
|
|
|
+ entity.OptTime = DateTime.Now.ToString("yyyyMMddHHmmss");
|
|
|
+ exceptions.Add(entity);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //每天所需设备数(向上圆整)
|
|
|
+ Maxednum = lineStart.OpType == "P" && remainNum > 0 ? Convert.ToInt32(Math.Ceiling(remainNum / (lineStart.Rate * 24))) : (remainNum <= 0 ? 1 : Convert.ToInt32(Math.Ceiling(remainNum / (lineStart.Rate * 24) / 2)));
|
|
|
+ //当前班次可用设备数,无模具取设备数,有模具取模具数
|
|
|
+ lineStart.equipmentNum = lineStart.OpType == "P" ? Maxednum : lineStart.equipmentNum;
|
|
|
+ //实际使用设备数,Maxednum=0代表所需时长超过剩余时长,直接使用所有设备生产
|
|
|
+ lineStart.equipmentNum = Maxednum == 0 ? lineStart.equipmentNum : (lineStart.equipmentNum > Maxednum ? Maxednum : (lineStart.equipmentNum == 0 ? Maxednum : lineStart.equipmentNum));
|
|
|
+
|
|
|
//产线排产开始时间
|
|
|
DateTime workStartTime = lineStart.StartTime;
|
|
|
//正常工单排产
|
|
|
@@ -799,6 +1277,8 @@ namespace Business.ResourceExamineManagement
|
|
|
decimal sumQty = 0m;
|
|
|
//产线准备时间(分钟)
|
|
|
decimal sumTimes = 0m;
|
|
|
+ //之前的排产记录
|
|
|
+ var previouslyOPNum = previouslyOP.Where(s => s.WorkOrd == workOrd.WorkOrd && s.Op == lineStart.Op && s.WorkStartTime < lineStart.StartTime && s.SetupTime > 0).Count();
|
|
|
while (sumQty < lineStart.QtyRemain)
|
|
|
{
|
|
|
//获取当天的产能
|
|
|
@@ -1274,13 +1754,27 @@ namespace Business.ResourceExamineManagement
|
|
|
/// <param name="prodLines">生产线明细</param>
|
|
|
/// <param name="allResults">产线占用记录</param>
|
|
|
/// <returns></returns>
|
|
|
- public LineStartDto DealStartTime(WorkOrdMaster workOrd,WorkOrdRouting routing,List<ProdLineDetail> prodLines, List<ScheduleResultOpMaster> allResults)
|
|
|
+ public LineStartDto DealStartTime(WorkOrdMaster workOrd,WorkOrdRouting routing,List<ProdLineDetail> prodLines, List<ScheduleResultOpMaster> allResults, List<ScheduleExceptionMaster> exceptions, List<ShopCalendarWorkCtr> curCalendars, List<QualityLineWorkDetail> curQtyDtls, bool Check = false, bool UseSkill = true)
|
|
|
{
|
|
|
LineStartDto lineStart = new LineStartDto();
|
|
|
//排产工序
|
|
|
int op = routing.OP;
|
|
|
//排产任务执行时间
|
|
|
DateTime actStart = scheTime;
|
|
|
+
|
|
|
+ lineStart.WorkCtr = !string.IsNullOrEmpty(routing.WorkCtr) ? routing.WorkCtr : (prodLines.Count > 0 ? (prodLines[0].Site != routing.WorkCtr && !string.IsNullOrEmpty(routing.WorkCtr) ? routing.WorkCtr : prodLines[0].Site) : routing.WorkCtr);
|
|
|
+ lineStart.SkillNo = !string.IsNullOrEmpty(routing.Engineer) ? routing.Engineer : (prodLines.Count > 0 ? prodLines[0].SkillNo : routing.Engineer);
|
|
|
+ lineStart.StandardStaffCount = routing.RunCrew > 0 ? routing.RunCrew : (prodLines.Count > 0 ? prodLines[0].StandardStaffCount : routing.RunCrew);
|
|
|
+ lineStart.OpType = !string.IsNullOrEmpty(routing.WorkCode) ? routing.WorkCode : (prodLines.Count > 0 ? prodLines[0].OpType : routing.WorkCode);
|
|
|
+ lineStart.Op = routing.OP;
|
|
|
+ lineStart.InternalEquipmentCode = lineStart.OpType == "P" ? "" : (!string.IsNullOrEmpty(routing.Machine) ? routing.Machine : (prodLines.Count > 0 ? prodLines[0].InternalEquipmentCode : routing.Machine));
|
|
|
+ lineStart.MoldTypeCode = lineStart.OpType == "P" ? "" : (!string.IsNullOrEmpty(routing.ToolCode) ? routing.ToolCode : (prodLines.Count > 0 ? prodLines[0].MoldTypeCode : routing.ToolCode));
|
|
|
+ lineStart.RecID = prodLines.Count > 0 ? prodLines[0].RecID : 0;
|
|
|
+ lineStart.Line = !string.IsNullOrEmpty(routing.ProdLine) ? routing.ProdLine : (prodLines.Count > 0 ? (prodLines[0].Line != routing.ProdLine && !string.IsNullOrEmpty(routing.ProdLine) ? routing.ProdLine : prodLines[0].Line) : routing.ProdLine);
|
|
|
+ lineStart.setupTime = routing.StdSetupTime > 0 ? routing.StdSetupTime : (prodLines.Count > 0 ? prodLines[0].SetupTime : routing.StdSetupTime);
|
|
|
+ lineStart.Rate = routing.MachBdnRate > 0 ? routing.MachBdnRate : (prodLines.Count > 0 ? prodLines[0].Rate : routing.MachBdnRate);
|
|
|
+ lineStart.OldRate = routing.MachBdnRate > 0 ? routing.MachBdnRate : (prodLines.Count > 0 ? prodLines[0].Rate : routing.MachBdnRate);
|
|
|
+
|
|
|
if (!string.IsNullOrEmpty(workOrd.JointTyped) && workOrd.JointTyped.ToUpper() == "B")
|
|
|
{
|
|
|
actStart = workOrd.OrdDate.GetValueOrDefault();
|
|
|
@@ -1297,8 +1791,8 @@ namespace Business.ResourceExamineManagement
|
|
|
{
|
|
|
//计算产线实际开始时间
|
|
|
//产线工作日历:当前产线的工作日历 + 默认工作日历
|
|
|
- var curCalendars = calendars.Where(p => p.ProdLine == curLine.Line || string.IsNullOrEmpty(p.ProdLine)).ToList();
|
|
|
- var curQtyDtls = qualityLines.Where(p => p.ProdLine == curLine.Line).ToList();
|
|
|
+ //var curCalendars = calendars.Where(p => p.ProdLine == curLine.Line || string.IsNullOrEmpty(p.ProdLine)).ToList();
|
|
|
+ //var curQtyDtls = qualityLines.Where(p => p.ProdLine == curLine.Line).ToList();
|
|
|
actStart = CalcActStartTime(curLine.Line, actStart, curCalendars, curQtyDtls);
|
|
|
lineStart.RecID = curLine.RecID;
|
|
|
lineStart.Line = curLine.Line;
|
|
|
@@ -1313,8 +1807,8 @@ namespace Business.ResourceExamineManagement
|
|
|
actStart = schedule == null ? actStart : (schedule.WorkEndTime >= actStart ? schedule.WorkEndTime : actStart);
|
|
|
//计算实际开工时间
|
|
|
//产线工作日历:当前产线的工作日历+默认工作日历
|
|
|
- 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();
|
|
|
+ //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(lines[0].Line, actStart, curCalendars, curQtyDtls);
|
|
|
lineStart.RecID = lines[0].RecID;
|
|
|
lineStart.Line = lines[0].Line;
|
|
|
@@ -1707,7 +2201,7 @@ namespace Business.ResourceExamineManagement
|
|
|
/// <param name="prodLines">产线明细</param>
|
|
|
/// <param name="allResults">产线占用记录</param>
|
|
|
/// <returns></returns>
|
|
|
- public LineStartDto DealNextStartTime(WorkOrdMaster workOrd,LineStartDto lineStart,WorkOrdRouting routing, List<ProdLineDetail> prodLines, List<ScheduleResultOpMaster> allResults)
|
|
|
+ public LineStartDto DealNextStartTime(WorkOrdMaster workOrd,LineStartDto lineStart,WorkOrdRouting routing, List<ProdLineDetail> prodLines, List<ScheduleResultOpMaster> allResults, List<ShopCalendarWorkCtr> calendars, List<ScheduleExceptionMaster> exceptions, List<ShopCalendarWorkCtr> curCalendars, List<QualityLineWorkDetail> curQtyDtls, bool Check = false, bool UseSkill = true)
|
|
|
{
|
|
|
//本序工序编码
|
|
|
int op = routing.OP;
|
|
|
@@ -1730,8 +2224,8 @@ namespace Business.ResourceExamineManagement
|
|
|
var curLine = lines.FirstOrDefault(p => p.Line == curRecord.Line);
|
|
|
if (curLine != null) {
|
|
|
//产线工作日历:当前产线的工作日历 + 默认工作日历
|
|
|
- var curCalendars = calendars.Where(p => p.ProdLine == curLine.Line || string.IsNullOrEmpty(p.ProdLine)).ToList();
|
|
|
- var curQtyDtls = qualityLines.Where(p => p.ProdLine == curLine.Line).ToList();
|
|
|
+ //var curCalendars = calendars.Where(p => p.ProdLine == curLine.Line || string.IsNullOrEmpty(p.ProdLine)).ToList();
|
|
|
+ //var curQtyDtls = qualityLines.Where(p => p.ProdLine == curLine.Line).ToList();
|
|
|
DateTime startTime = CalcActStartTime(curLine.Line, scheTime, curCalendars, curQtyDtls);
|
|
|
startDto.RecID = curLine.RecID;
|
|
|
startDto.Line = curLine.Line;
|
|
|
@@ -1847,6 +2341,142 @@ namespace Business.ResourceExamineManagement
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
+ /// 可用数量和可用时间
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="actStart">开始时间</param>
|
|
|
+ /// <param name="lineStart">工序</param>
|
|
|
+ /// <param name="schedule">可插班明细</param>
|
|
|
+ /// <param name="lines">生产线明细</param>
|
|
|
+ /// <param name="allResults">产线占用记录</param>
|
|
|
+ /// <param name="numList">可用数量</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public void AvailableQuantity(WorkOrdMaster workOrd, DateTime actStart, LineStartDto lineStart, List<ProdLineDetail> lines, List<ScheduleResultOpMaster> allResults, List<ScheduleExceptionMaster> exceptions, out List<string> numList, out ScheduleResultOpMaster schedule, out DateTime wxEndTime, bool UseSkill = true)
|
|
|
+ {
|
|
|
+ wxEndTime = actStart;
|
|
|
+ numList = new List<string>();
|
|
|
+ schedule = null;
|
|
|
+ var num = 0;
|
|
|
+ var scheduleList = lineStart.OpType == "P" ? new List<ScheduleResultOpMaster>() : allResults.Where(p => p.InternalEquipmentCode == lineStart.InternalEquipmentCode && ((p.WorkStartTime <= actStart && p.WorkEndTime > actStart) || p.WorkStartTime >= actStart)).OrderBy(p => p.WorkStartTime).ToList();
|
|
|
+ if (scheduleList.Any())
|
|
|
+ {
|
|
|
+ schedule = null;
|
|
|
+ for (int i = 0; i < scheduleList.Count(); i++)
|
|
|
+ {
|
|
|
+ if (!string.IsNullOrEmpty(lineStart.SkillNo) && UseSkill)
|
|
|
+ numList = _getAvailableEquipmentAppService.GetEquipmentCountBySkillRestrictions(lineStart.SkillNo, lineStart.MoldTypeCode, lineStart.InternalEquipmentCode, actStart, allResults, lineStart.StandardStaffCount);
|
|
|
+ else if (!string.IsNullOrEmpty(lineStart.MoldTypeCode))
|
|
|
+ numList = _getAvailableEquipmentAppService.GetAvailableEquipmentForCurrentTeam(lineStart.InternalEquipmentCode, actStart, allResults, lineStart.MoldTypeCode);
|
|
|
+ else if (!string.IsNullOrEmpty(lineStart.InternalEquipmentCode))
|
|
|
+ numList = _getAvailableEquipmentAppService.GetAvailableEquipmentForCurrentTeam(lineStart.InternalEquipmentCode, actStart, allResults);
|
|
|
+ if (numList.Any() && numList.Count > 0)
|
|
|
+ {
|
|
|
+ if (Convert.ToInt32(numList[0]) > 0)
|
|
|
+ {
|
|
|
+ schedule = scheduleList[i];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ actStart = scheduleList[i].WorkEndTime;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //没有可插班时间
|
|
|
+ if (schedule == null)
|
|
|
+ {
|
|
|
+ schedule = scheduleList[scheduleList.Count - 1];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (!string.IsNullOrEmpty(lineStart.SkillNo) && UseSkill)
|
|
|
+ numList = _getAvailableEquipmentAppService.GetEquipmentCountBySkillRestrictions(lineStart.SkillNo, lineStart.MoldTypeCode, lineStart.InternalEquipmentCode, actStart, allResults, lineStart.StandardStaffCount);
|
|
|
+ else if (!string.IsNullOrEmpty(lineStart.MoldTypeCode))
|
|
|
+ numList = _getAvailableEquipmentAppService.GetAvailableEquipmentForCurrentTeam(lineStart.InternalEquipmentCode, actStart, allResults, lineStart.MoldTypeCode);
|
|
|
+ else if (!string.IsNullOrEmpty(lineStart.InternalEquipmentCode))
|
|
|
+ numList = _getAvailableEquipmentAppService.GetAvailableEquipmentForCurrentTeam(lineStart.InternalEquipmentCode, actStart, allResults);
|
|
|
+ }
|
|
|
+ //占用时间过后依然无可用设备
|
|
|
+ if (scheduleList.Any() && numList.Any() && numList.Count > 0 || (scheduleList.Any() && num == 0 && numList.Count == 0))
|
|
|
+ {
|
|
|
+ num = numList.Count > 0 ? Convert.ToInt32(numList[0]) : 0;
|
|
|
+ //无可用设备
|
|
|
+ if (num <= 0)
|
|
|
+ {
|
|
|
+ if (num == -99)
|
|
|
+ {
|
|
|
+ var entity = new ScheduleExceptionMaster();
|
|
|
+ entity.Domain = workOrd.Domain;
|
|
|
+ entity.WorkOrd = workOrd.WorkOrd;
|
|
|
+ entity.ItemNum = workOrd.ItemNum;
|
|
|
+ entity.CreateTime = DateTime.Now;
|
|
|
+ entity.Remark = $"{workOrd.WorkOrd}排产异常:{lineStart.Op}-{numList[1]}";
|
|
|
+ entity.Type = "手动排产";
|
|
|
+ entity.OptTime = DateTime.Now.ToString("yyyyMMddHHmmss");
|
|
|
+ exceptions.Add(entity);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //是否是维修
|
|
|
+ wxEndTime = num < 0 ? (numList.Count >= 3 ? Convert.ToDateTime(numList[2]) : schedule.WorkEndTime) : schedule.WorkEndTime;
|
|
|
+ if (!string.IsNullOrEmpty(lineStart.SkillNo) && UseSkill)
|
|
|
+ numList = _getAvailableEquipmentAppService.GetEquipmentCountBySkillRestrictions(lineStart.SkillNo, lineStart.MoldTypeCode, lineStart.InternalEquipmentCode, wxEndTime, allResults, lineStart.StandardStaffCount);
|
|
|
+ else if (!string.IsNullOrEmpty(lineStart.MoldTypeCode))
|
|
|
+ numList = _getAvailableEquipmentAppService.GetAvailableEquipmentForCurrentTeam(lineStart.InternalEquipmentCode, wxEndTime, allResults, lineStart.MoldTypeCode);
|
|
|
+ else if (!string.IsNullOrEmpty(lineStart.InternalEquipmentCode))
|
|
|
+ numList = _getAvailableEquipmentAppService.GetAvailableEquipmentForCurrentTeam(lineStart.InternalEquipmentCode, wxEndTime, allResults);
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (numList.Count > 0)
|
|
|
+ {
|
|
|
+ if (Convert.ToInt32(numList[0]) == -99 && exceptions.FindIndex(e => e.WorkOrd == workOrd.WorkOrd) < 0)
|
|
|
+ {
|
|
|
+ var entity = new ScheduleExceptionMaster();
|
|
|
+ entity.Domain = workOrd.Domain;
|
|
|
+ entity.WorkOrd = workOrd.WorkOrd;
|
|
|
+ entity.ItemNum = workOrd.ItemNum;
|
|
|
+ entity.CreateTime = DateTime.Now;
|
|
|
+ entity.Remark = $"{workOrd.WorkOrd}排产异常:{lineStart.Op}-{numList[1]}";
|
|
|
+ entity.Type = "手动排产";
|
|
|
+ entity.OptTime = DateTime.Now.ToString("yyyyMMddHHmmss");
|
|
|
+ exceptions.Add(entity);
|
|
|
+ }
|
|
|
+ else if (Convert.ToInt32(numList[0]) == 0)
|
|
|
+ {
|
|
|
+ for (int i = 1; i < 10; i++)
|
|
|
+ {
|
|
|
+ var newtime = actStart.AddHours(12 * i);
|
|
|
+ if (!string.IsNullOrEmpty(lineStart.SkillNo) && UseSkill)
|
|
|
+ numList = _getAvailableEquipmentAppService.GetEquipmentCountBySkillRestrictions(lineStart.SkillNo, lineStart.MoldTypeCode, lineStart.InternalEquipmentCode, newtime, allResults, lineStart.StandardStaffCount);
|
|
|
+ else if (!string.IsNullOrEmpty(lineStart.MoldTypeCode))
|
|
|
+ numList = _getAvailableEquipmentAppService.GetAvailableEquipmentForCurrentTeam(lineStart.InternalEquipmentCode, newtime, allResults, lineStart.MoldTypeCode);
|
|
|
+ else if (!string.IsNullOrEmpty(lineStart.InternalEquipmentCode))
|
|
|
+ numList = _getAvailableEquipmentAppService.GetAvailableEquipmentForCurrentTeam(lineStart.InternalEquipmentCode, newtime, allResults);
|
|
|
+ if (Convert.ToInt32(numList[0]) > 0)
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (Convert.ToInt32(numList[0]) == -99)
|
|
|
+ {
|
|
|
+ var entity = new ScheduleExceptionMaster();
|
|
|
+ entity.Domain = workOrd.Domain;
|
|
|
+ entity.WorkOrd = workOrd.WorkOrd;
|
|
|
+ entity.ItemNum = workOrd.ItemNum;
|
|
|
+ entity.CreateTime = DateTime.Now;
|
|
|
+ entity.Remark = $"{workOrd.WorkOrd}排产异常:{lineStart.Op}-{numList[1]}";
|
|
|
+ entity.Type = "手动排产";
|
|
|
+ entity.OptTime = DateTime.Now.ToString("yyyyMMddHHmmss");
|
|
|
+ exceptions.Add(entity);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
/// 通过提前期计算产线排产开始时间
|
|
|
/// </summary>
|
|
|
/// <param name="line">产线</param>
|