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; } } }