|
|
@@ -16,6 +16,8 @@ using Volo.Abp.Application.Services;
|
|
|
using Volo.Abp.MultiTenancy;
|
|
|
using Microsoft.Extensions.Configuration;
|
|
|
using MongoDB.Driver.Linq;
|
|
|
+using Amazon.Runtime.Internal.Util;
|
|
|
+using IdentityModel.Client;
|
|
|
|
|
|
namespace Business.ResourceExamineManagement
|
|
|
{
|
|
|
@@ -74,23 +76,32 @@ namespace Business.ResourceExamineManagement
|
|
|
/// 产线休息时间记录表
|
|
|
/// </summary>
|
|
|
private ISqlRepository<QualityLineWorkDetail> _qualityLineWorkDetail;
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 产线人员配置表
|
|
|
/// </summary>
|
|
|
private ISqlRepository<ProdLineDetailRunCrew> _prodLineDetailRunCrew;
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 加班设置表
|
|
|
/// </summary>
|
|
|
private ISqlRepository<ResourceOccupancyTime> _resourceOccupancyTime;
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 加班设置表
|
|
|
/// </summary>
|
|
|
private ISqlRepository<GeneralizedCodeMaster> _generalizedCodeMaster;
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 节假日记录表
|
|
|
/// </summary>
|
|
|
private ISqlRepository<HolidayMaster> _holidayMaster;
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 排产异常记录
|
|
|
+ /// </summary>
|
|
|
+ private ISqlRepository<ScheduleExceptionMaster> _scheduleExceptionMaster;
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 雪花算法
|
|
|
/// </summary>
|
|
|
@@ -148,7 +159,8 @@ namespace Business.ResourceExamineManagement
|
|
|
ISqlRepository<QualityLineWorkDetail> qualityLineWorkDetail,
|
|
|
ISqlRepository<HolidayMaster> holidayMaster,
|
|
|
ISqlRepository<GeneralizedCodeMaster> generalizedCodeMaster,
|
|
|
- ICurrentTenant currentTenant
|
|
|
+ ICurrentTenant currentTenant,
|
|
|
+ ISqlRepository<ScheduleExceptionMaster> scheduleExceptionMaster
|
|
|
)
|
|
|
{
|
|
|
_itemMaster = itemMaster;
|
|
|
@@ -166,11 +178,12 @@ namespace Business.ResourceExamineManagement
|
|
|
_holidayMaster = holidayMaster;
|
|
|
_generalizedCodeMaster = generalizedCodeMaster;
|
|
|
_currentTenant = currentTenant;
|
|
|
+ _scheduleExceptionMaster = scheduleExceptionMaster;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
/// <summary>
|
|
|
- /// 执行生产排产
|
|
|
+ /// 生产排产-定时任务
|
|
|
/// </summary>
|
|
|
public async void DoExt()
|
|
|
{
|
|
|
@@ -178,27 +191,25 @@ 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();
|
|
|
- await DoProductShcedule(workOrds, domain);
|
|
|
+ //获取排产锁定期
|
|
|
+ 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>
|
|
|
- public async Task DoProductShcedule(List<WorkOrdMaster> workOrds, string factoryid)
|
|
|
+ public async Task DoProductSchedule(List<WorkOrdMaster> workOrds, string factoryid,int type)
|
|
|
{
|
|
|
//记录工厂id
|
|
|
domain = factoryid;
|
|
|
@@ -209,19 +220,26 @@ 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();
|
|
|
//获取非标准产线人员配置
|
|
|
prodLineDetailRunCrews = _prodLineDetailRunCrew.Select(x => prodLines.Select(p => p.RecID).Contains(x.ProdLineDetailRecID) && x.IsActive && x.Domain == domain).ToList();
|
|
|
//获取加班设置
|
|
|
- List<ResourceOccupancyTime> resourceOccupancyTimes = _resourceOccupancyTime.Select(x => prodLines.Select(p => p.Line).Contains(x.Resource) && x.IsActive && x.Domain == domain && x.StartTime.Value > DateTime.Now).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);
|
|
|
@@ -230,6 +248,27 @@ namespace Business.ResourceExamineManagement
|
|
|
//获取节假日记录数据
|
|
|
holidays = _holidayMaster.Select(p => p.Domain == domain && p.IsActive && p.Dated >= earlist);
|
|
|
|
|
|
+ //排产前校验
|
|
|
+ List<ScheduleExceptionMaster> exceptions = BeforeScheduleCheck(workOrds, workOrdRoutings, prodLines,type);
|
|
|
+ if (exceptions.Any())
|
|
|
+ {
|
|
|
+ using (TransactionScope scope = new TransactionScope())
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ //记录排产异常数据
|
|
|
+ _scheduleExceptionMaster.Insert(exceptions);
|
|
|
+ scope.Complete();
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ new NLogHelper("ProductionScheduleAppService").WriteLog("DoProductSchedule", "保存排产异常数据失败:" + ex.Message, _currentTenant.Id.ToString());
|
|
|
+ scope.Dispose();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
//3、排产
|
|
|
//生产周期
|
|
|
List<PeriodSequenceDet> periodSequenceDtls = new List<PeriodSequenceDet>();
|
|
|
@@ -238,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);
|
|
|
@@ -247,55 +288,8 @@ namespace Business.ResourceExamineManagement
|
|
|
//当前工单的产线明细
|
|
|
var curProdLines = prodLines.Where(p => p.Part == item.ItemNum).ToList();
|
|
|
|
|
|
- #region 校验
|
|
|
- //工单工艺多产线关键工序、物料对应的生产线信息:物料,工序对应的生产线、工作日历数据
|
|
|
- if (curRoutings.Count == 0)
|
|
|
- {
|
|
|
- //记录排产异常原因
|
|
|
- new NLogHelper("ProductionScheduleAppService").WriteLog("DoProductShcedule", "工单<" + item.WorkOrd + ">的工单工艺流程数据维护为空", _currentTenant.Id.ToString());
|
|
|
- continue;
|
|
|
- }
|
|
|
- //TODO:多个关键工序校验
|
|
|
-
|
|
|
- //物料对应生产线校验
|
|
|
- var ProdLineDetails = prodLines.Where(x => x.Part == item.ItemNum).ToList();
|
|
|
- if (ProdLineDetails.Count == 0)
|
|
|
- {
|
|
|
- //记录排产异常原因
|
|
|
- new NLogHelper("ProductionScheduleAppService").WriteLog("DoProductShcedule", "工单<" + item.WorkOrd + ">的生产线物料数据维护为空", _currentTenant.Id.ToString());
|
|
|
- continue;
|
|
|
- }
|
|
|
- var calendarsList = calendars.Where(x => ProdLineDetails.Select(p => p.Line).Contains(x.ProdLine) || string.IsNullOrEmpty(x.ProdLine)).ToList();
|
|
|
- //校验每个层级是否维护了工作日历
|
|
|
- bool flag = false;
|
|
|
- foreach (var rut in ProdLineDetails)
|
|
|
- {
|
|
|
- var lineCals = calendarsList.Where(p => p.ProdLine == rut.Line).ToList();
|
|
|
- //当前产线未配置工作日历取标准无产线工作日历使用
|
|
|
- if (lineCals.Count == 0)
|
|
|
- {
|
|
|
- lineCals = calendars.Where(p => string.IsNullOrEmpty(p.ProdLine)).ToList();
|
|
|
- if (lineCals.Count == 0)
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (lineCals.Select(p => p.WeekDay).Distinct().Count() != 7)
|
|
|
- {
|
|
|
- flag = true;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (flag)
|
|
|
- {
|
|
|
- //记录排产异常原因
|
|
|
- new NLogHelper("ProductionScheduleAppService").WriteLog("DoProductShcedule", "工单<" + item.WorkOrd + ">的<" + item.ProdLine + ">工作日历数据维护错误", _currentTenant.Id.ToString());
|
|
|
- continue;
|
|
|
- }
|
|
|
- #endregion
|
|
|
-
|
|
|
//产线排产
|
|
|
- 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())
|
|
|
@@ -316,11 +310,148 @@ namespace Business.ResourceExamineManagement
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
- new NLogHelper("ProductionScheduleAppService").WriteLog("DoProductShcedule", "记录排产数据失败:" + ex.Message, _currentTenant.Id.ToString());
|
|
|
+ new NLogHelper("ProductionScheduleAppService").WriteLog("DoProductSchedule", "保存排产数据失败:" + ex.Message, _currentTenant.Id.ToString());
|
|
|
scope.Dispose();
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 排产前校验
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="workOrds">待排产工单</param>
|
|
|
+ /// <param name="workOrdRoutings">工单工艺路线</param>
|
|
|
+ /// <param name="prodLines">产线明细</param>
|
|
|
+ /// <param name="type">排产类型:1-自动排产,2-手动排产</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public List<ScheduleExceptionMaster> BeforeScheduleCheck(List<WorkOrdMaster> workOrds,List<WorkOrdRouting> workOrdRoutings, List<ProdLineDetail> prodLines,int type)
|
|
|
+ {
|
|
|
+ List<ScheduleExceptionMaster> exceptions = new List<ScheduleExceptionMaster>();
|
|
|
+ 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())//当前工单没有维护关键工序
|
|
|
+ {
|
|
|
+ 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 lineDetails = prodLines.Where(x => x.Part == item.ItemNum && curRoutings.Contains(x.Op)).ToList();
|
|
|
+ if (!lineDetails.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;
|
|
|
+ }
|
|
|
+ //校验关键工序是否维护了产线
|
|
|
+ List<LineStartDto> lines = new List<LineStartDto>();
|
|
|
+ foreach (var op in curRoutings)
|
|
|
+ {
|
|
|
+ var curLines = lineDetails.Where(p => p.Op == op).ToList();
|
|
|
+ if (!curLines.Any())//当前Op没有维护产线
|
|
|
+ {
|
|
|
+ entity = new ScheduleExceptionMaster();
|
|
|
+ entity.Domain = item.Domain;
|
|
|
+ entity.WorkOrd = item.WorkOrd;
|
|
|
+ entity.ItemNum = item.ItemNum;
|
|
|
+ entity.CreateTime = DateTime.Now;
|
|
|
+ entity.Remark = "排产异常:工单的关键工序["+ op + "]没有维护产线数据,请维护后再操作!";
|
|
|
+ entity.Type = type == 1 ? "自动排产" : "手动排产";
|
|
|
+ exceptions.Add(entity);
|
|
|
+ }
|
|
|
+ foreach (var line in curLines)
|
|
|
+ {
|
|
|
+ lines.Add(new LineStartDto {
|
|
|
+ Line = line.Line,
|
|
|
+ Op = op
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //校验一条产线是否维护了多个关键工序
|
|
|
+ List<string> pdLines = lines.Select(p => p.Line).Distinct().ToList();
|
|
|
+ foreach (var line in pdLines)
|
|
|
+ {
|
|
|
+ var curLines = lines.Where(p => p.Line == line).ToList();
|
|
|
+ if (curLines.Count() > 1)//当前物料的多个关键工序对应一条产线
|
|
|
+ {
|
|
|
+ entity = new ScheduleExceptionMaster();
|
|
|
+ entity.Domain = item.Domain;
|
|
|
+ entity.WorkOrd = item.WorkOrd;
|
|
|
+ entity.ItemNum = item.ItemNum;
|
|
|
+ entity.CreateTime = DateTime.Now;
|
|
|
+ entity.Remark = "排产异常:工单的多个关键工序[" + string.Join("、",curLines.Select(p=>p.Op).ToList()) + "]对应同一条产线,请调整后再操作!";
|
|
|
+ entity.Type = type == 1 ? "自动排产" : "手动排产";
|
|
|
+ exceptions.Add(entity);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //校验主产线关键工序对应的产线是否维护了工作日历
|
|
|
+ var curCalendars = calendars.Where(x => lineDetails.Select(p => p.Line).Contains(x.ProdLine) || string.IsNullOrEmpty(x.ProdLine)).ToList();
|
|
|
+ foreach (var rut in lineDetails)
|
|
|
+ {
|
|
|
+ //获取当前产线维护的工作日历
|
|
|
+ var lineCals = curCalendars.Where(p => p.ProdLine == rut.Line).ToList();
|
|
|
+ if (!lineCals.Any())//当前产线未维护工作日历
|
|
|
+ {
|
|
|
+ lineCals = calendars.Where(p => string.IsNullOrEmpty(p.ProdLine)).ToList();
|
|
|
+ if (!lineCals.Any() || lineCals.Select(p => p.WeekDay).Distinct().Count() != 7)
|
|
|
+ {
|
|
|
+ entity = new ScheduleExceptionMaster();
|
|
|
+ entity.Domain = item.Domain;
|
|
|
+ entity.WorkOrd = item.WorkOrd;
|
|
|
+ entity.ItemNum = item.ItemNum;
|
|
|
+ entity.CreateTime = DateTime.Now;
|
|
|
+ entity.Remark = "排产异常:产线["+rut.Line+ "]没有维护工作日历且标准工作日历未维护完全,请维护后再操作!";
|
|
|
+ entity.Type = type == 1 ? "自动排产" : "手动排产";
|
|
|
+ exceptions.Add(entity);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (lineCals.Select(p => p.WeekDay).Distinct().Count() != 7)//当前产线维护了工作日历,但是没有维护完全
|
|
|
+ {
|
|
|
+ entity = new ScheduleExceptionMaster();
|
|
|
+ entity.Domain = item.Domain;
|
|
|
+ entity.WorkOrd = item.WorkOrd;
|
|
|
+ entity.ItemNum = item.ItemNum;
|
|
|
+ entity.CreateTime = DateTime.Now;
|
|
|
+ entity.Remark = "排产异常:产线[" + rut.Line + "]工作日历没有维护完整,请维护后再操作!";
|
|
|
+ entity.Type = type == 1 ? "自动排产" : "手动排产";
|
|
|
+ exceptions.Add(entity);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return exceptions;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -332,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>();
|
|
|
@@ -340,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++)
|
|
|
{
|
|
|
@@ -363,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)
|
|
|
{
|
|
|
@@ -374,7 +757,6 @@ namespace Business.ResourceExamineManagement
|
|
|
//判断当天的可用生产时长能满足提前期
|
|
|
if (dto.EffTime >= lineStart.setupTime - sumTimes)
|
|
|
{
|
|
|
- sumTimes = lineStart.setupTime;
|
|
|
//当天剩余产能
|
|
|
decimal sumAmount = dto.ProductQty - Math.Floor(dto.Rate * (lineStart.setupTime - sumTimes));
|
|
|
//判断已排产数量+当天的产能是否超过工单数量
|
|
|
@@ -426,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;
|
|
|
@@ -486,15 +868,18 @@ 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)//当天的产能需要全部排产
|
|
|
{
|
|
|
@@ -505,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,
|
|
|
@@ -544,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
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -635,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处于那个工作时间段
|
|
|
@@ -649,16 +1031,16 @@ 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
|
|
|
var curLevel = curRunCrews.FirstOrDefault(p => p.StartDate.GetValueOrDefault().Date <= startTime.Date && p.EndDate.GetValueOrDefault().Date >= startTime.Date);
|
|
|
decimal rate = curLevel == null ? lineStart.Rate : curLevel.Rate;
|
|
|
scheduledDto.Rate = rate;
|
|
|
- //计算当天的产能
|
|
|
+ //计算当天的产能(向下取整)
|
|
|
scheduledDto.ProductQty = Math.Floor(scheduledDto.EffTime * rate);
|
|
|
//计算班次
|
|
|
scheduledDto.Period = 1;//默认一般制
|
|
|
@@ -690,12 +1072,13 @@ 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;
|
|
|
lineStart.setupTime = lines[0].SetupTime;
|
|
|
lineStart.Rate = lines[0].Rate;
|
|
|
+ lineStart.Op = op;
|
|
|
//循环其他产线
|
|
|
for (int i = 1; i < lines.Count; i++)
|
|
|
{
|
|
|
@@ -705,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;
|
|
|
@@ -713,6 +1096,7 @@ namespace Business.ResourceExamineManagement
|
|
|
lineStart.StartTime = StartTime;
|
|
|
lineStart.setupTime = lines[i].SetupTime;
|
|
|
lineStart.Rate = lines[i].Rate;
|
|
|
+ lineStart.Op = op;
|
|
|
}
|
|
|
}
|
|
|
return lineStart;
|
|
|
@@ -721,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;
|
|
|
@@ -748,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)//不处于工作时间段
|
|
|
@@ -877,6 +1262,7 @@ namespace Business.ResourceExamineManagement
|
|
|
startDto.setupTime = lines[0].SetupTime;
|
|
|
startDto.StartTime = schedule == null ? startTime : (startTime < schedule.WorkEndTime ? schedule.WorkEndTime : startTime);
|
|
|
startDto.Rate = lines[0].Rate;
|
|
|
+ startDto.Op = op;
|
|
|
//循环剩余产线,找到最早可开工产线
|
|
|
for (int i = 1; i < lines.Count(); i++)
|
|
|
{
|
|
|
@@ -890,6 +1276,7 @@ namespace Business.ResourceExamineManagement
|
|
|
startDto.setupTime = lines[i].SetupTime;
|
|
|
startDto.StartTime = startTime;
|
|
|
startDto.Rate = lines[0].Rate;
|
|
|
+ startDto.Op = op;
|
|
|
}
|
|
|
}
|
|
|
return startDto;
|
|
|
@@ -920,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();
|
|
|
//当前时间段可用时长
|
|
|
@@ -964,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)//当天可用提前期满足
|
|
|
@@ -1037,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");
|
|
|
@@ -1058,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;
|
|
|
//按照产线休息时间切分时间段
|
|
|
@@ -1073,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);
|
|
|
}
|
|
|
@@ -1081,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();
|
|
|
}
|