using Abp.Application.Services;
using Business.Core.Utilities;
using Business.Dto;
using Business.EntityFrameworkCore;
using Business.EntityFrameworkCore.SqlRepositories;
using Business.Model.MES.IC;
using Business.Model.Production;
using Business.Model.SRM;
using Business.MongoModel.MES.IC;
using Business.MongoModel.Production;
using Business.MongoModel.SRM;
using Business.ResourceExamineManagement;
using Business.SaleForecast;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.EntityFrameworkCore.Migrations;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
namespace Business.SaleForecastManagement
{
///
/// 产能分析
///
public class MonthlyCapacityLoadAppService : ApplicationService, IMonthlyCapacityLoadAppService, ITransientDependency
{
#region 服务
///
/// 物料
///
private IRepository _ic_item;
///
/// 整体需求计划明细
///
private ISqlRepository _overallDemandPlanDtl;
///
/// 生产线明细
///
private ISqlRepository _prodLineDetail;
///
/// 工作日历数据
///
private ISqlRepository _shopCalendarWorkCtr;
///
/// 产线休息时间记录表
///
private ISqlRepository _qualityLineWorkDetail;
///
/// 节假日记录表
///
private ISqlRepository _holidayMaster;
///
/// 月度产能共识主表
///
private ISqlRepository _monthlyProdCapacityMain;
///
/// 月度产能共识明细表
///
private ISqlRepository _monthlyProdCapacityDtl;
///
/// 标准物料规格型号设置表
///
private ISqlRepository _standardItemModelSet;
///
/// 工作单元
///
private readonly IUnitOfWorkManager _unitOfWorkManager;
///
/// 日志
///
private readonly ICurrentTenant _currentTenant;
///
/// 雪花算法
///
SnowFlake help = new SnowFlake();
#endregion
#region 构造函数
///
/// 构造函数
///
public MonthlyCapacityLoadAppService(
IRepository ic_item,
ISqlRepository overallDemandPlanDtl,
ISqlRepository prodLineDetail,
ISqlRepository shopCalendarWorkCtr,
ISqlRepository qualityLineWorkDetail,
ISqlRepository holidayMaster,
ISqlRepository monthlyProdCapacityMain,
ISqlRepository monthlyProdCapacityDtl,
IUnitOfWorkManager unitOfWorkManager,
ICurrentTenant currentTenant,
ISqlRepository standardItemModelSet
)
{
_ic_item= ic_item;
_overallDemandPlanDtl= overallDemandPlanDtl;
_prodLineDetail= prodLineDetail;
_shopCalendarWorkCtr= shopCalendarWorkCtr;
_qualityLineWorkDetail= qualityLineWorkDetail;
_holidayMaster= holidayMaster;
_monthlyProdCapacityMain= monthlyProdCapacityMain;
_monthlyProdCapacityDtl= monthlyProdCapacityDtl;
_unitOfWorkManager= unitOfWorkManager;
_currentTenant= currentTenant;
_standardItemModelSet= standardItemModelSet;
}
#endregion
///
/// 产能分析
///
///
///
///
public async Task CapacityAnalysis(InputDto input)
{
//1、获取数据
//1.1 根据年、月、版本号获取整体需求计划明细
List planDtls = _overallDemandPlanDtl.Select(p=>p.Year == input.year && p.Month == input.month && p.Version == input.version && p.tenant_id == input.tenant_id && p.factory_id == input.factory_id).OrderBy(p=>p.ProdLine).ThenBy(p=>p.ProdRange).ThenBy(p=>p.Model).ThenBy(p=>p.PlanDate).ToList();
//1.2 根据规格型号获取物料数据
List models = planDtls.Select(p => p.Model).Distinct().ToList();
List standards = _standardItemModelSet.Select(p=> models.Contains(p.Model) && p.tenant_id == input.tenant_id && p.factory_id == input.factory_id);
//1.3 根据物料编码获取产线数据
List lines = _prodLineDetail.Select(p => standards.Select(m => m.ItemNumber).Contains(p.Part) && p.Domain == input.factory_id.ToString() && p.IsActive);
//1.4 根据产线获取工作日历数据和产线休息配置数据
List calendars = _shopCalendarWorkCtr.Select(p=> lines.Select(m=>m.Line).Contains(p.ProdLine) && p.Domain == input.factory_id.ToString() && p.IsActive);
List lineWorks = _qualityLineWorkDetail.Select(p => lines.Select(m => m.Line).Contains(p.ProdLine) && p.Domain == input.factory_id.ToString() && p.IsActive);
//1.5 获取当前年和下一年的节假日配置数据
List holidays = _holidayMaster.Select(p => (p.Dated.Value.Year == input.year || p.Dated.Value.Year == (input.year + 1)) && p.Domain == input.factory_id.ToString() && p.IsActive);
//月度产能共识主表
List capacityMains = new List();
//月度产能共识明细表
List capacityDtls = new List();
foreach (var item in planDtls)
{
//获取当前产品的生产线
var std = standards.FirstOrDefault(p => p.Model == item.Model);
if (std == null)
{
new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("CapacityAnalysis", "规格型号【" + item.Model + "】没有维护标准物料数据", _currentTenant.Id.ToString());
return "NO|规格型号【" + item.Model + "】没有维护标准物料数据,请维护后再发布!";
}
var curLines = lines.Where(p=>p.Part == std.ItemNumber).OrderBy(p => p.Line).ToList();
//过滤产线
var distLines = curLines.Select(p => p.Line).Distinct().ToList();
if (distLines.Count() == 0)
{
new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("CapacityAnalysis", "物料【" + std.ItemNumber + "】没有维护产线数据", _currentTenant.Id.ToString());
return "NO|物料【" + std.ItemNumber + "】没有维护产线数据,请维护后再发布!";
}
foreach (var dl in distLines)
{
//添加月度产能共识主表数据
MonthlyProdCapacityMain main = new MonthlyProdCapacityMain();
main.Id = help.NextId();
main.Version = input.version;//整体需求计划版本号
main.Year = Convert.ToInt16(item.PlanDate.Substring(0, 4));
main.Month = Convert.ToInt16(item.PlanDate.Substring(4, 2));
main.ProdRange = item.ProdRange;
main.Model = item.Model;
main.ProdQty = item.Qty;
main.ProdLine = dl;
main.Qty = item.Qty;
main.tenant_id = item.tenant_id;
main.factory_id = item.factory_id;
main.Version = item.Version;
main.CreateTime = DateTime.Now;
capacityMains.Add(main);
//添加月度产能共识产能效率数据
MonthlyProdCapacityDtl dtl = new MonthlyProdCapacityDtl();
dtl.MainId = main.Id;
dtl.Version = input.version;
dtl.Year = main.Year;
dtl.Month = main.Month;
dtl.ProdLine = dl;
//计算每天工作时间
var curCal = calendars.FirstOrDefault(p => p.ProdLine == dl);
if (curCal == null) {
continue;
}
dtl.DailyWorks = curCal.ShiftsHours1;
dtl.FlightQty = 1;
//计算当月工作天数
var curHoildays = holidays.Where(p => p.Dated.Value.Year == main.Year && p.Dated.Value.Month == main.Month).ToList();
//当月天数
int days = DateTime.DaysInMonth(main.Year.Value, main.Month.Value);
//当月周末天数
int weekDays = CalcWeekDays(days,Convert.ToDateTime(main.Year.ToString()+"-"+main.Month.ToString()+"-01"));
dtl.YearWorks= days-weekDays-curHoildays.Where(p=>p.Ufld1 == "休假").Count() + curHoildays.Where(p=>p.Ufld1 == "调班").Count();
dtl.AvailableTimes= dtl.DailyWorks * dtl.FlightQty * dtl.YearWorks;
//计算产线耗时
var line = curLines.Where(p => p.Line == dl).OrderByDescending(p=>p.Op).First();
dtl.NeedWorks= line.Rate == 0? 0:( Math.Ceiling(main.Qty.GetValueOrDefault() / line.Rate));
dtl.ProdRate= 100;
dtl.Rate= dtl.AvailableTimes == 0? 0: Math.Floor(dtl.NeedWorks.GetValueOrDefault()/ dtl.AvailableTimes.GetValueOrDefault() * 100);
dtl.IsOverTime = dtl.NeedWorks > dtl.YearWorks ? "是" : "否";
dtl.OverTimes = dtl.IsOverTime == "是" ? (dtl.NeedWorks - dtl.YearWorks) : 0;
dtl.tenant_id = main.tenant_id;
dtl.factory_id = main.factory_id;
capacityDtls.Add(dtl);
}
}
//保存数据
using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
{
try
{
//先删除数据
_monthlyProdCapacityMain.Delete(p =>p.tenant_id == input.tenant_id && p.factory_id == input.factory_id && p.Version.Contains(input.version.Substring(0, 7)));
_monthlyProdCapacityDtl.Delete(p => p.tenant_id == input.tenant_id && p.factory_id == input.factory_id && p.Version.Contains(input.version.Substring(0, 7)));
//插入数据
_monthlyProdCapacityMain.Insert(capacityMains);
_monthlyProdCapacityDtl.Insert(capacityDtls);
await unitOfWork.CompleteAsync();
}
catch (Exception e)
{
unitOfWork.Dispose();
new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("CapacityAnalysis", "生成【"+input.year+"年"+input.month+"月】月度产能共识失败:" + e.Message, _currentTenant.Id.ToString());
return "NO|" + e.Message;
};
}
return "OK|发布成功!";
}
///
/// 计算当月有多少个周末
///
///
///
///
private int CalcWeekDays(int days, DateTime startDay)
{
int sumDays = 0;
for (int i = 0; i < days; i++)
{
int weekDays = (int)startDay.AddDays(i).DayOfWeek;
if (weekDays == 0 || weekDays == 6)
{
sumDays++;
}
}
return sumDays;
}
}
}