using Business.Domain;
using Business.Dto;
using Business.ResourceExamineManagement.Dto;
using MongoDB.Driver.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp.Application.Services;
namespace Business.ResourceExamineManagement
{
///
/// 产能检查
///
public class ProductExamineAppService: ApplicationService
{
#region 服务
///
/// 生产线明细表
///
public List prodLines = new List();
///
/// 标准工艺路径表
///
public List routingOps = new List();
///
/// 排产记录表
///
public List periodSequences = new List();
///
/// 工作日历
///
public List calendarWorks = new List();
///
/// 休息时间段
///
public List qualityLineWorks = new List();
///
/// 节假日
///
public List holidays = new List();
#endregion
///
/// 构造函数
///
public ProductExamineAppService()
{
}
///
/// 根据标准工艺获取生产时长(天)
///
///
///
public int ProductTime(ProdExamineParamDto param)
{
var allOps = routingOps.Where(s => s.RoutingCode == param.ItemNum && s.Domain == param.Domain).ToList();
if (allOps.Any())
{
decimal maxRt = allOps.Max(s => s.RunTime);
decimal sumRt = allOps.Sum(s => s.RunTime);
decimal totalTime = (param.QtyOrd - 1) * maxRt + sumRt;//总计生产小时
return (int)(Math.Ceiling(totalTime / 8));
}
return 1;
}
///
/// 产能计算-批量
///
/// 产能检查入参
/// 生产时长(天)
public DateTime ProductiveExamine(ProdExamineParamDto param)
{
//生产结束时间
DateTime planEnd = param.PlanStart.Date;
if (param.QtyOrd <= 0)
{
return planEnd;
}
//获取当前产品的工艺路线:主产线,最后一道工序
var curRoutingOps = routingOps.Where(p => p.RoutingCode == param.ItemNum && p.ParentOp == 0).OrderByDescending(p => p.Op).ToList();
if (curRoutingOps.Count == 0)
{
return planEnd;
}
var lastOp = curRoutingOps.First();
//获取产线
var curProdLine = prodLines.FirstOrDefault(p => p.Part == param.ItemNum && p.Op == lastOp.Op);
if (curProdLine == null)
{
return planEnd;
}
//获取产线工作日历
var curCalendars = calendarWorks.Where(p => p.ProdLine == curProdLine.Line).ToList();
if (curCalendars.Count == 0 || curCalendars.Count != 7)
{
return planEnd;
}
//获取产线休息时间
var curqualityLines = qualityLineWorks.Where(p=>p.ProdLine == curProdLine.Line).ToList();
//生产数量
decimal sumAmount = 0m;
do
{
//获取工作日
planEnd = GetNextWorkDay(planEnd, curCalendars);
//计算工作日的产能
sumAmount += CalcCapacity(planEnd, curProdLine, curCalendars, curqualityLines);
planEnd = planEnd.AddDays(1);
} while (sumAmount < param.QtyOrd);
return planEnd.AddDays(-1);
}
///
/// 获取工作日
///
/// 当前周几
/// 开始时间:年-月-日
/// 当前产线的工作日历
///
public DateTime GetNextWorkDay(DateTime startTime, List curCalendars)
{
DateTime rtnData = startTime;
int weekDay = (int)startTime.DayOfWeek;
var calendar = curCalendars.FirstOrDefault(p => p.WeekDay == weekDay);
//判断当天是否是工作日
if (weekDay == 0 || weekDay == 6)//周六,周日
{
if (!holidays.Exists(p => p.Dated.GetValueOrDefault().Date == startTime && p.Ufld1 == "调班"))//今天是周末
{
//递归继续找下一个工作日
rtnData = GetNextWorkDay(startTime.AddDays(1), curCalendars);
return rtnData;
}
return rtnData;
}
//今天不是周六周日,需要判断是不是节假日
if (holidays.Exists(p => p.Dated.GetValueOrDefault().Date == startTime && p.Ufld1 == "休假"))//是节假日
{
//递归继续找下一个工作日
rtnData = GetNextWorkDay(startTime.AddDays(1), curCalendars);
return rtnData;
}
return rtnData;
}
///
/// 计算当天的产能
///
///
///
///
///
///
public decimal CalcCapacity(DateTime startTime,ProdLineDetail prodLine, List curCalendars, List curQualityLines)
{
decimal sumQty = 0m;
//获取休息时长(分钟)
decimal sumResrt = curQualityLines.Sum(p => p.RestTime);
//获取当天的工作时长(分钟)
decimal workTime = curCalendars.First(p => p.WeekDay == (int)startTime.DayOfWeek).ShiftsHours1 * 60;
//计算产能
sumQty = Math.Ceiling((workTime - sumResrt) / 60 * prodLine.Rate);
return sumQty;
}
///
/// 计算订单行的建议交期(产能/物料)
///
///
///
///
public void CalcSuggestTime(List sentrys, List kittingTimes, List icitemlist)
{
ProdExamineParamDto param;
foreach (var item in sentrys)
{
var dto = kittingTimes.FirstOrDefault(p=>p.sentry_id == item.Id);
if (dto == null)
{
continue;
}
var icitem = icitemlist.Find(s => s.number == item.item_number);
if (dto.LackQty == 0)//当前订单行库存足够
{
if (icitem != null)
{
//加上自检、入库、发运提前期
dto.kitting_time = dto.kitting_time.AddDays((double)(icitem.self_inspection_date.GetValueOrDefault() + icitem.Warehousing_date.GetValueOrDefault() + icitem.Shipping_date.GetValueOrDefault()+icitem.RoutingDesignTime.GetValueOrDefault()));
dto.kitting_time= dto.kitting_time<=item.plan_date.GetValueOrDefault()? item.plan_date.GetValueOrDefault(): dto.kitting_time;
}
item.sys_material_date = dto.kitting_time;
item.sys_capacity_date = dto.kitting_time;
continue;
}
//计算系统建议交期(物料)
param = new ProdExamineParamDto
{
ItemNum = item.item_number,
QtyOrd = dto.LackQty,
PlanStart = dto.kitting_time.Date.AddDays(1)
};
var time = ProductiveExamine(param);
item.sys_material_date = time;
item.sys_capacity_date = time;
if (icitem != null)
{
//加上自检、入库、发运提前期
item.sys_material_date = time.AddDays((double)(icitem.self_inspection_date.GetValueOrDefault() + icitem.Warehousing_date.GetValueOrDefault() + icitem.Shipping_date.GetValueOrDefault() + icitem.RoutingDesignTime.GetValueOrDefault()));
}
//param.PlanStart = dto.kitting_time.Date.AddDays(3);
//计算系统交期(产能)
//获取主线最后一道工序
List schedules = new List();
var routings = routingOps.Where(p => p.RoutingCode == item.item_number && p.ParentOp == 0).OrderBy(p=>p.Op).ToList();
if (routings.Count != 0)
{
//获取产线
var prodLine = prodLines.FirstOrDefault(p => p.Part == item.item_number && p.Op == routings.Last().Op);
if (prodLine != null)
{
//获取产线空闲开始时间
schedules = periodSequences.Where(p => p.ItemNum == item.item_number && p.Op == prodLine.Op && p.Line == prodLine.Line).OrderByDescending(p => p.PlanDate).ToList();
}
}
if (schedules.Any())
{
//产线空闲开始时间
var lastTime = schedules.First().PlanDate.GetValueOrDefault().Date;
if (lastTime >= param.PlanStart)//如果产线空闲时间大于或者等于系统建议交期(物料)的开工时间
{
param.PlanStart = lastTime;
item.sys_capacity_date = ProductiveExamine(param);
}
else {
item.sys_capacity_date = ProductiveExamine(param);
}
}
else {
item.sys_capacity_date = ProductiveExamine(param);
}
if (icitem != null)
{
//加上自检、入库、发运提前期
item.sys_capacity_date = item.sys_capacity_date.GetValueOrDefault().AddDays((double)(icitem.self_inspection_date.GetValueOrDefault() + icitem.Warehousing_date.GetValueOrDefault() + icitem.Shipping_date.GetValueOrDefault() + icitem.RoutingDesignTime.GetValueOrDefault()));
}
item.sys_capacity_date = item.sys_capacity_date <= item.plan_date ? item.plan_date : item.sys_capacity_date;
}
}
}
}