using Azure.Identity;
using Business.Core.Utilities;
using Business.Domain;
using Business.Dto;
using Business.EntityFrameworkCore.SqlRepositories;
using Business.ResourceExamineManagement.Dto;
using Business.SaleForecast;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Spire.Pdf.General.Render.Decode.Jpeg2000.j2k.quantization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
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 readonly IUnitOfWorkManager _unitOfWorkManager;
///
/// 日志
///
private readonly ICurrentTenant _currentTenant;
///
/// 年度生产需求大纲
///
private IRepository _yearDemandManagement;
///
/// 年度生产需求大纲历史记录
///
private IRepository _yearDemandManagementHistory;
///
/// 国内终端预测
///
private IRepository _domesticTerminalFcst;
///
/// 海外销售预测
///
private IRepository _overseasSaleFcst;
///
/// 平台预测收集
///
private IRepository _platformFcstCollect;
///
/// 标准物料规格型号设置表
///
private IRepository _standardItemModelSet;
///
/// 库存明细表
///
private ISqlRepository _locationDetail;
///
/// 工单
///
private ISqlRepository _workOrdMaster;
///
/// 雪花算法
///
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,
IRepository standardItemModelSet,
IRepository yearDemandManagement,
IRepository domesticTerminalFcst,
IRepository overseasSaleFcst,
IRepository platformFcstCollect,
IRepository yearDemandManagementHistory,
ISqlRepository locationDetail,
ISqlRepository workOrdMaster
)
{
_ic_item = ic_item;
_overallDemandPlanDtl = overallDemandPlanDtl;
_prodLineDetail = prodLineDetail;
_shopCalendarWorkCtr = shopCalendarWorkCtr;
_qualityLineWorkDetail = qualityLineWorkDetail;
_holidayMaster = holidayMaster;
_monthlyProdCapacityMain = monthlyProdCapacityMain;
_monthlyProdCapacityDtl = monthlyProdCapacityDtl;
_unitOfWorkManager = unitOfWorkManager;
_currentTenant = currentTenant;
_standardItemModelSet = standardItemModelSet;
_yearDemandManagement= yearDemandManagement;
_domesticTerminalFcst= domesticTerminalFcst;
_overseasSaleFcst = overseasSaleFcst;
_platformFcstCollect= platformFcstCollect;
_yearDemandManagementHistory= yearDemandManagementHistory;
_locationDetail = locationDetail;
_workOrdMaster = workOrdMaster;
}
#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;
}
///
/// 月度需求预测更新
///
///
///
///
public async Task DemandAnalysis(InputDto input)
{
//1.0 获取当前年年度生产需求大纲
List yearDemands = _yearDemandManagement.GetListAsync(p => p.Year == input.year && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result.OrderBy(p=>p.OrderNum).ToList();
//1.0 获取下一年年度生产大纲
List nextYearDemands = _yearDemandManagement.GetListAsync(p => p.Year == (input.year+1) && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result.OrderBy(p => p.OrderNum).ToList();
//记录历史版本:当前年+下一年
var updateMonth = input.year.ToString() + "-" + input.month.ToString("00");
var histories = ObjectMapper.Map, List>(yearDemands);
histories.ForEach(p => {
p.UpdateMonth = updateMonth;
});
var nextHistories = ObjectMapper.Map, List>(nextYearDemands);
nextHistories.ForEach(p => {
p.UpdateMonth = updateMonth;
});
//1.1、获取海外销售预测数据
List overseasSales = _overseasSaleFcst.GetListAsync(p => p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
//1.2、获取平台预测收集数据
List platformFcsts = _platformFcstCollect.GetListAsync(p => p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
//1.3、获取国内终端预测-T1汇总数据
List domesticFcst = _domesticTerminalFcst.GetListAsync(p =>p.TypeEnum == 2 && p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
//1.4、根据年度生产大纲,获取规格型号对应的补货周期
List allModels = yearDemands.Select(p=>p.Model).Distinct().ToList();
if (nextYearDemands.Any())
{
allModels.AddRange(nextYearDemands.Select(p => p.Model).ToList());
allModels = allModels.Distinct().ToList();
}
List standards = _standardItemModelSet.GetListAsync(p => allModels.Contains(p.Model) && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
//1.5、获取规格型号对应的标准SKU数据:获取最小包装单位
List itemNums = standards.Select(p=>p.ItemNumber).Distinct().ToList();
List items = _ic_item.GetListAsync(p=> itemNums.Contains(p.number) && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
//1.6、获取成品库存、灭菌库存
//List locations = _locationDetail.Select(p=>p.Domain == input.factory_id.ToString() && p.IsActive && itemNums.Contains(p.ItemNum));
//1.7、获取在制库存:计划开始时间、计划结束时间都在本月,并且未关闭的工单
//DateTime monStart = Convert.ToDateTime(input.year + "-" + input.month + "-01");
//DateTime monEnd = monStart.AddMonths(1).AddDays(-1);
//List workOrds = _workOrdMaster.Select(p=>p.Domain);
//1.9、获取节假日设置
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);
#region 数据校验
//1、校验当前年的年度生产大纲是否导入
if (!yearDemands.Any())
{
new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入" + input.year + "年的年度生产需求后再操作!", _currentTenant.Id.ToString());
return "NO|请导入" + input.year + "年的年度生产需求后再操作!";
}
//2、如果当前月份大于10,则需校验下一年的年度生产大纲
if (input.month > 10 && !nextYearDemands.Any())
{
new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入" + (input.year+1) + "年的年度生产需求后再操作!", _currentTenant.Id.ToString());
return "NO|请导入" + (input.year + 1) + "年的年度生产需求后再操作!";
}
//3、校验当前月份的海外销售预测是否导入
if (!overseasSales.Any())
{
new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入" + input.year + "年" + input.month + "月海外销售预测后再操作!", _currentTenant.Id.ToString());
return "NO|请导入" + input.year + "年" + input.month + "月海外销售预测后再操作!";
}
//4、校验当前月份的平台预测收集是否导入
if (!platformFcsts.Any())
{
new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入" + input.year + "年" + input.month + "月平台需求收集后再操作!", _currentTenant.Id.ToString());
return "NO|请导入" + input.year + "年" + input.month + "月平台需求收集后再操作!";
}
//5、校验当前月份的国内终端预测是否导入
if (!domesticFcst.Any())
{
new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入" + input.year + "年" + input.month + "月国内终端预测后再操作!", _currentTenant.Id.ToString());
return "NO|请导入" + input.year + "年" + input.month + "月国内终端预测后再操作!";
}
//6、校验终端+平台导入的规格型号是否已维护标准SKU
if (allModels.Count() != standards.Count())
{
allModels.RemoveAll(standards.Select(p=>p.Model).ToList());
new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "规格型号【" + string.Join(",",allModels) + "】没有维护标准SKU,请维护后再操作!", _currentTenant.Id.ToString());
return "NO|规格型号【" + string.Join(",", allModels) + "】没有维护标准SKU,请维护后再操作!";
}
//7、校验是否已维护补货周期
var zeros = standards.Where(p => p.ReplenishCycle == 0).ToList();
if (zeros.Any())
{
new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "规格型号【" + string.Join(",", zeros.Select(p=>p.Model).ToList()) + "】没有维护补货周期,请维护后再操作!", _currentTenant.Id.ToString());
return "NO|规格型号【" + string.Join(",", zeros.Select(p => p.Model).ToList()) + "】没有维护补货周期,请维护后再操作!";
}
#endregion
//计算当前年月的N+1,N+2
int newYear = input.month == 12 ? input.year + 1 : input.year;
int newMonth = input.month == 12 ? 1 : input.month + 1;
string strN1 = newYear.ToString() + "-" + newMonth.ToString("00");
newYear = newMonth == 12 ? newYear + 1 : newYear;
newMonth = newMonth == 12 ? 1 : newMonth + 1;
string strN2 = newYear.ToString() + "-" + newMonth.ToString("00");
//需要回写的数据
List updates = new List();
#region 计算国内终端预测,回写年度生产大纲
//获取导入的T1、平台数据
List gnModels = new List();
if (domesticFcst.Any())
{
gnModels.AddRange(domesticFcst.Select(p => p.Model).ToList());
}
if (platformFcsts.Any())
{
gnModels.AddRange(platformFcsts.Select(p => p.Model).ToList());
}
gnModels = gnModels.Distinct().ToList();
foreach (var gnModel in gnModels)
{
//N+1月
YearDemandManagement monthN1 = new YearDemandManagement();
//N+2月
YearDemandManagement monthN2 = new YearDemandManagement();
//获取需要回写的数据
if (input.month < 11)
{
monthN1 = yearDemands.FirstOrDefault(p => p.Area == "国内" && p.Model == gnModel && p.PlanMonth == strN1);
monthN2 = yearDemands.FirstOrDefault(p => p.Area == "国内" && p.Model == gnModel && p.PlanMonth == strN2);
}
if (input.month == 11)
{
monthN1 = yearDemands.FirstOrDefault(p => p.Area == "国内" && p.Model == gnModel && p.PlanMonth == strN1);
monthN2 = nextYearDemands.FirstOrDefault(p => p.Area == "国内" && p.Model == gnModel && p.PlanMonth == strN2);
}
if (input.month == 12)
{
monthN1 = nextYearDemands.FirstOrDefault(p => p.Area == "国内" && p.Model == gnModel && p.PlanMonth == strN1);
monthN2 = nextYearDemands.FirstOrDefault(p => p.Area == "国内" && p.Model == gnModel && p.PlanMonth == strN2);
}
if (monthN1 == null || monthN2 == null)
{
continue;
}
//T1
var sumT1N1 = domesticFcst.Where(p => p.Model == gnModel && p.PlanMonth == strN1).Sum(p=>p.Qty);
var sumT1N2 = domesticFcst.Where(p => p.Model == gnModel && p.PlanMonth == strN2).Sum(p => p.Qty);
//平台
var sumPN1 = platformFcsts.Where(p => p.Model == gnModel && p.PlanMonth == strN1).Sum(p => p.Qty);
var sumPN2 = platformFcsts.Where(p => p.Model == gnModel && p.PlanMonth == strN2).Sum(p => p.Qty);
//合计
var sumN1 = sumT1N1+ sumPN1;
var sumN2 = sumT1N2 + sumPN2;
//当前规格型号对应标准SKU的最小包装单位、补货周期
var curStd = standards.FirstOrDefault(p => p.Model == gnModel);
decimal packQty = 1m;//最小包装单位
decimal cycle = 0m;//补货周期
if (curStd != null)
{
var curItem = items.FirstOrDefault(p => p.number == curStd.ItemNumber);
packQty = curItem == null ? 1 : (curItem.minpackqty.GetValueOrDefault() == 0.0m ? 1 : curItem.minpackqty.Value);
cycle = curStd.ReplenishCycle;
}
//TODO:获取成品库存、在制库存、灭菌库存,参与计算
//N+1月使用N+2月的再订货点参与计算
decimal rop = CalcRop(strN2+"-01", sumN2, packQty, holidays, cycle);
monthN1.Qty = Math.Ceiling((sumN1 / 2 + sumN2 / 2 + rop - 0 - 0 - 0) / packQty) * packQty;
//N+2月使用本月的需求量,下一月的工作天数
rop = CalcRop(Convert.ToDateTime(strN2 + "-01").AddMonths(1).ToString("yyyy-MM-dd"), sumN2, packQty, holidays, cycle);
monthN2.Qty = Math.Ceiling((sumN2 + rop - 0 - 0 - 0) / packQty) * packQty;
//负数置0
monthN1.Qty = monthN1.Qty < 0 ? 0m : monthN1.Qty;
monthN2.Qty = monthN2.Qty < 0 ? 0m : monthN2.Qty;
//记录需要回写的数据
updates.Add(monthN1);
updates.Add(monthN2);
}
#endregion
#region 海外销售预测,回写年度生产大纲
List hwModels = overseasSales.Select(p => p.Model).Distinct().ToList();
foreach (var hwModel in hwModels)
{
//N+1月
YearDemandManagement monthN1 = new YearDemandManagement();
//N+2月
YearDemandManagement monthN2 = new YearDemandManagement();
//获取需要回写的数据
if (input.month < 11)
{
monthN1 = yearDemands.FirstOrDefault(p => p.Area == "海外" && p.Model == hwModel && p.PlanMonth == strN1);
monthN2 = yearDemands.FirstOrDefault(p => p.Area == "海外" && p.Model == hwModel && p.PlanMonth == strN2);
}
if (input.month == 11)
{
monthN1 = yearDemands.FirstOrDefault(p => p.Area == "海外" && p.Model == hwModel && p.PlanMonth == strN1);
monthN2 = nextYearDemands.FirstOrDefault(p => p.Area == "海外" && p.Model == hwModel && p.PlanMonth == strN2);
}
if (input.month == 12)
{
monthN1 = nextYearDemands.FirstOrDefault(p => p.Area == "海外" && p.Model == hwModel && p.PlanMonth == strN1);
monthN2 = nextYearDemands.FirstOrDefault(p => p.Area == "海外" && p.Model == hwModel && p.PlanMonth == strN2);
}
if (monthN1 == null || monthN2 == null) {
continue;
}
var sumN1 = overseasSales.Where(p => p.Model == hwModel && p.PlanMonth == strN1).Sum(p => p.Qty);
var sumN2 = overseasSales.Where(p => p.Model == hwModel && p.PlanMonth == strN2).Sum(p => p.Qty);
//当前规格型号对应标准SKU的最小包装单位、补货周期
var curStd = standards.FirstOrDefault(p => p.Model == hwModel);
decimal packQty = 1m;//最小包装单位
if (curStd != null)
{
var curItem = items.FirstOrDefault(p => p.number == curStd.ItemNumber);
packQty = curItem == null ? 1 : (curItem.minpackqty.GetValueOrDefault() == 0.0m ? 1 : curItem.minpackqty.Value);
}
//海外生产需求量=当月的50%+下一月的50%-成品库存-在制库存-灭菌库存
//TODO:获取成品库存、在制库存、灭菌库存,参与运算
//计算N+1月,N+2月
monthN1.Qty = Math.Ceiling((sumN1 / 2 + sumN2 / 2 - 0 - 0 - 0) / packQty) * packQty;
monthN2.Qty = Math.Ceiling((sumN2 - 0 - 0 - 0) / packQty) *packQty; ;
//负数置0
monthN1.Qty = monthN1.Qty < 0 ? 0m : monthN1.Qty;
monthN2.Qty = monthN2.Qty < 0 ? 0m : monthN2.Qty;
//记录需要回写的数据
updates.Add(monthN1);
updates.Add(monthN2);
}
#endregion
//保存数据
using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
{
try
{
//判断是否存在当前年月的历史版本,不存在则插入
var dbHistory = _yearDemandManagementHistory.GetListAsync(p=>p.Year ==input.year && p.UpdateMonth == updateMonth && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id).Result;
if (!dbHistory.Any())
{
await _yearDemandManagementHistory.InsertManyAsync(histories);
}
if (input.month > 10)
{
//判断是否存在下一年月的历史版本,不存在则插入
dbHistory = _yearDemandManagementHistory.GetListAsync(p =>(p.Year == input.year + 1) && p.UpdateMonth == updateMonth && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id).Result;
if (!dbHistory.Any())
{
await _yearDemandManagementHistory.InsertManyAsync(nextHistories);
}
}
//回写年度生产大纲
await _yearDemandManagement.UpdateManyAsync(updates);
await unitOfWork.CompleteAsync();
}
catch (Exception e)
{
unitOfWork.Dispose();
new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "【" + input.year + "年" + input.month + "月】月度需求预测更新失败:" + e.Message, _currentTenant.Id.ToString());
return "NO|" + e.Message;
};
}
return "OK|修订成功!";
}
///
/// 计算再订货点
///
/// 计划年月(yyyy-MM-dd)
/// 需求量
/// 最小包装数量
/// 节假日
/// 补货周期
///
private decimal CalcRop(string planMonth,decimal qty,decimal packQty,List holidays,decimal replenishCycle)
{
decimal rop = 0.0m;
//获取当月天数
int year = Convert.ToInt16(planMonth.Substring(0, 4));
int month = Convert.ToInt16(planMonth.Substring(5, 2));
int days = DateTime.DaysInMonth(year, month);
//计算当前月的周末天数
int weeks = CalcWeekDays(days, Convert.ToDateTime(planMonth));
//获取当前年月的节假日设置
var curHolidays = holidays.Where(p => p.Dated.Value.Year == year && p.Dated.Value.Month == month).ToList();
//当月工作天数
int workDays = days - weeks - curHolidays.Where(p => p.Ufld1 == "休假").Count() + curHolidays.Where(p => p.Ufld1 == "调班").Count();
//rop = (需求量/月工作天数*补货周期)=>按照最小包装单位元整
rop = Math.Ceiling(qty / workDays * replenishCycle / packQty) * packQty;
return rop;
}
}
}