|
|
@@ -28,6 +28,7 @@ using Newtonsoft.Json.Linq;
|
|
|
using MathNet.Numerics.RootFinding;
|
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
using System.ComponentModel.DataAnnotations;
|
|
|
+using System.Collections;
|
|
|
|
|
|
namespace Business.Replenishment
|
|
|
{
|
|
|
@@ -91,11 +92,13 @@ namespace Business.Replenishment
|
|
|
private readonly ISqlRepository<ShopCalendarWorkCtr> _shopCalendarWorkCtr;
|
|
|
private readonly ISqlRepository<PeriodSequenceDet> _periodSequenceDet;
|
|
|
private readonly ISqlRepository<QualityLineWorkDetail> _qualityLineWorkDetail;
|
|
|
+ private readonly ISqlRepository<CustMaster> _custMaster;
|
|
|
private readonly IRepository<mo_srm_po_main, long> _srm_po_main;
|
|
|
private readonly IRepository<srm_po_main, long> _mysql_srm_po_main;
|
|
|
private readonly IRepository<mo_srm_purchase, long> _srm_purchase;
|
|
|
private readonly IRepository<srm_purchase, long> _mysql_srm_purchase;
|
|
|
private readonly IRepository<mes_morder, long> _mysql_mes_morder;
|
|
|
+ private readonly IRepository<crm_seorder, long> _mysql_crm_seorder;
|
|
|
private readonly IRepository<crm_seorderentry, long> _mysql_crm_seorderentry;
|
|
|
private readonly IRepository<mo_mes_oorder, long> _mes_oorder;
|
|
|
private readonly ISqlRepository<ScheduleResultOpMaster> _scheduleResultOpMaster;
|
|
|
@@ -277,6 +280,7 @@ namespace Business.Replenishment
|
|
|
IRepository<mo_srm_purchase, long> srm_purchase,
|
|
|
IRepository<srm_purchase, long> mysql_srm_purchase,
|
|
|
IRepository<mes_morder, long> mysql_mes_morder,
|
|
|
+ IRepository<crm_seorder, long> mysql_crm_seorder,
|
|
|
IRepository<crm_seorderentry, long> mysql_crm_seorderentry,
|
|
|
IRepository<mo_mes_oorder, long> mes_oorder,
|
|
|
ISqlRepository<ScheduleResultOpMaster> scheduleResultOpMaster,
|
|
|
@@ -287,6 +291,7 @@ namespace Business.Replenishment
|
|
|
IRepository<YearDemandManagementHistory, long> yearDemandManagementHistory,
|
|
|
IRepository<WMS_PlatformInventory, long> PlatformInventory,
|
|
|
ISqlRepository<WorkOrdRouting> workOrdRouting,
|
|
|
+ ISqlRepository<CustMaster> custMaster,
|
|
|
IRepository<MonthlyProdCapacity, long> monthlyProdCapacity,
|
|
|
IRepository<MonthlyProdCapacityDtl, long> monthlyProdCapacityDtl,
|
|
|
IRepository<crm_planorder, long> crm_planorder,
|
|
|
@@ -329,6 +334,7 @@ namespace Business.Replenishment
|
|
|
_mysql_mes_mooccupy = mysql_mes_mooccupy;
|
|
|
_mysql_b_bom_pretreatment = mysql_b_bom_pretreatment;
|
|
|
_workOrdMaster = workOrdMaster;
|
|
|
+ _custMaster=custMaster;
|
|
|
_prodLineDetail = prodLineDetail;
|
|
|
_ic_bom = ic_bom;
|
|
|
_mysql_ic_bom = mysql_ic_bom;
|
|
|
@@ -359,6 +365,7 @@ namespace Business.Replenishment
|
|
|
_srm_purchase= srm_purchase;
|
|
|
_mysql_srm_purchase = mysql_srm_purchase;
|
|
|
_mysql_mes_morder = mysql_mes_morder;
|
|
|
+ _mysql_crm_seorder = mysql_crm_seorder;
|
|
|
_mysql_crm_seorderentry = mysql_crm_seorderentry;
|
|
|
_mes_oorder = mes_oorder;
|
|
|
_scheduleResultOpMaster = scheduleResultOpMaster;
|
|
|
@@ -520,6 +527,7 @@ namespace Business.Replenishment
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
+ await _replenishmentAnnualProduction.DeleteAsync(a => a.Year == input.year && a.tenant_id == input.tenant_id && a.factory_id == input.factory_id);
|
|
|
await _replenishmentAnnualProduction.InsertManyAsync(annualProductionOutlines);
|
|
|
await unitOfWork.CompleteAsync();
|
|
|
}
|
|
|
@@ -541,7 +549,7 @@ namespace Business.Replenishment
|
|
|
public async Task<string> SaveProductionMasterPlan(InputDto input)
|
|
|
{
|
|
|
//计算当前年月的N0,N+1,N+2
|
|
|
- List<string> planMons = GetPlanMonth(3);
|
|
|
+ List<string> planMons = GetPlanMonth(4);
|
|
|
List<ProductionMasterPlan> productionMasters= new List<ProductionMasterPlan>();
|
|
|
List<ProductionMasterPlan> pre3MonthPlan = _productionMasterPlan.GetListAsync(a => GetPlanMonth(-3).Contains(a.PlanMonth) && a.factory_id == input.factory_id && a.tenant_id == input.tenant_id && a.company_id == input.company_id).Result;
|
|
|
//N0,N+1,N+2月度发货计划
|
|
|
@@ -551,7 +559,7 @@ namespace Business.Replenishment
|
|
|
List<LocationDetail> locations = _locationDetail.Select(x => annualProduction.Select(m => m.SAPItemNumber).Contains(x.ItemNum) && x.Domain == input.factory_id.ToString() && x.IsActive).ToList();
|
|
|
var InProdcutQty=GetInProdcutQty(annualProduction.Select(m => m.SAPItemNumber).ToList(),input);
|
|
|
var itemStock = CalcStock(annualProduction.Select(m => m.SAPItemNumber).ToList(),input);
|
|
|
- foreach (var item in annualProduction)
|
|
|
+ foreach (var item in annualProduction.Where(a=> GetPlanMonth(4).Contains(a.PlanMonth)))
|
|
|
{
|
|
|
ProductionMasterPlan plan = new ProductionMasterPlan();
|
|
|
plan.Area = item.Area;
|
|
|
@@ -843,7 +851,7 @@ namespace Business.Replenishment
|
|
|
//}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// 调整ROP和最高库存水位
|
|
|
+ /// 调整ROP和最高库存水位(按照成品展开到原材料,原材料用领料算出库)
|
|
|
/// </summary>
|
|
|
/// <param name="input"></param>
|
|
|
/// <returns></returns>
|
|
|
@@ -851,40 +859,44 @@ namespace Business.Replenishment
|
|
|
{
|
|
|
//1.获取补货模型全局参数
|
|
|
ReplenishmentDto replenishmentDto = GetROPParam(input.factory_id.ToString());
|
|
|
-
|
|
|
- //Step1:按照瑞奇、两大平台分别根据历史出库数据和预测出货数据计算ROP
|
|
|
- //Step2:计算瑞奇的M-M+2共12周补货(每次补EOP/4),计算海王的M-M+2共12周补货(每次补EOP/4),计算国科的M-M+2共12周补货(每次补EOP/4)
|
|
|
- //Step3:汇总Step2所有补货,为工厂的制造需求
|
|
|
- //Step4:按照Step3制造需求做资源检查,按月统计各物料消耗预测
|
|
|
- //Step5:按照各SKU的历史出库数据和Step4里计算的预测消耗数量计算参数
|
|
|
- //Step6:计算各SKU的12周采购补货
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
//获取月度发货计划(一次导入三个月的销售预测),因为是固定格式yyyy-MM所以可以用字符串比较,避免写很多字符串判断相等
|
|
|
string planMonth = $"{DateTime.Now.Year}-{DateTime.Now.Month.ToString("00")}";
|
|
|
string planMonthMax = $"{DateTime.Now.AddMonths(replenishmentDto.SaleFcstMonth).Year}-{DateTime.Now.AddMonths(replenishmentDto.SaleFcstMonth).Month.ToString("00")}";
|
|
|
var planList = _monthlyShipmentPlan.Select(a => a.PlanMonth.CompareTo(planMonth) >= 0 && a.PlanMonth.CompareTo(planMonthMax) <= 0 && !a.IsDeleted).ToList();
|
|
|
|
|
|
-
|
|
|
- var itemList = _ic_item.GetListAsync(a => planList.Select(p => p.SAPItemNumber).Contains(a.number) && a.tenant_id == input.tenant_id && a.company_id == input.company_id && !a.IsDeleted).Result;
|
|
|
- var mesItemList = _itemMaster.Select(a => planList.Select(p => p.SAPItemNumber).Contains(a.ItemNum) && a.Domain == input.factory_id.ToString() && a.IsActive);
|
|
|
- var srm_purchaseList = _srmPurchase.GetListAsync(a => planList.Select(p => p.SAPItemNumber).Contains(a.number) && a.tenant_id == input.tenant_id && a.company_id == input.company_id && !a.IsDeleted).Result;
|
|
|
+ var boms = _ic_bom.GetListAsync(a => planList.Select(p => p.SAPItemNumber).ToList().Contains(a.item_number) && a.tenant_id == input.tenant_id && a.factory_id == input.factory_id).Result;
|
|
|
+ var pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
|
|
|
+ List<mo_ic_bom> autoCreates = new List<mo_ic_bom>();
|
|
|
+ boms.ForEach(p =>
|
|
|
+ {
|
|
|
+ if (!pretreatments.Where(s => s.sourceid == p.Id).Any())
|
|
|
+ {
|
|
|
+ autoCreates.Add(p);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (autoCreates.Any())
|
|
|
+ {
|
|
|
+ AutoCreateBomBill(input.company_id.ToString(), autoCreates);
|
|
|
+ pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
|
|
|
+ }
|
|
|
+ var itemList = _ic_item.GetListAsync(a => pretreatments.Select(p => p.item_number).Contains(a.number) && a.tenant_id == input.tenant_id && a.company_id == input.company_id && !a.IsDeleted).Result;
|
|
|
+ var mesItemList = _itemMaster.Select(a => pretreatments.Select(p => p.item_number).Contains(a.ItemNum) && a.Domain == input.factory_id.ToString() && a.IsActive);
|
|
|
+ var srm_purchaseList = _srmPurchase.GetListAsync(a => pretreatments.Select(p => p.item_number).Contains(a.number) && a.tenant_id == input.tenant_id && a.company_id == input.company_id && !a.IsDeleted).Result;
|
|
|
|
|
|
//获取补货模型前H周期和未来F个周期的数据
|
|
|
var ropModelList = _replenishmentROP.GetListAsync(a => a.zero_based_seqno >= -1 * replenishmentDto.HistoryOutStockMonth && a.zero_based_seqno <= replenishmentDto.SaleFcstMonth).Result;
|
|
|
- //发货计划物料列表
|
|
|
- List<string> planItemList = planList?.Select(a => a.SAPItemNumber).ToList();
|
|
|
//获取成品库存、灭菌库存、在制库存(会从SAP同步的库存表更新到LocationDetail、ic_item表中)
|
|
|
//List<SAPInv> sAPInvs = _SAPInv.Select(p => p.WERKS == input.factory_id.ToString() && itemNums.Contains(p.MATNR));
|
|
|
- var locations = _locationDetail.Select(p => p.Domain == input.factory_id.ToString() && planList.Select(a => a.SAPItemNumber).Contains(p.ItemNum) && p.IsActive);
|
|
|
- var sapItemInv = _SAPInv.Select(a => planItemList.Contains(a.MATNR) && a.WERKS == input.factory_id.ToString());
|
|
|
-
|
|
|
- //取上一个月发货出库记录
|
|
|
- var shipList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.RealQty > 0 && planItemList.Contains(a.ContainerItem) && a.ShipDate >= getMonthStartTime(-6) && a.ShipDate <= getMonthEndTime(-1));
|
|
|
+ var locations = _locationDetail.Select(p => p.Domain == input.factory_id.ToString() && pretreatments.Select(p => p.item_number).Contains(p.ItemNum) && p.IsActive);
|
|
|
+ var sapItemInv = _SAPInv.Select(a => pretreatments.Select(p => p.item_number).Contains(a.MATNR) && a.WERKS == input.factory_id.ToString());
|
|
|
|
|
|
+ //取过去6个月发货出库记录
|
|
|
+ var shipList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.RealQty > 0 && pretreatments.Select(p => p.item_number).Contains(a.ContainerItem) && a.ShipDate >= getMonthStartTime(-6) && a.ShipDate <= getMonthEndTime(-1));
|
|
|
+ //领料出库记录
|
|
|
+ //var pickbilllist = _NbrDetail.Select(a => a.Domain == input.factory_id.ToString() && a.Type == "SM" && a.IsActive && a.UpdateTime >= DateTime.Now.AddMonths(replenishmentDto.HistoryOutStockMonth * -1) && itemNumList.Contains(a.ItemNum));
|
|
|
+ var pickbilllist = _invTransHist.Select(a => a.Domain == input.factory_id.ToString() && a.TransType == "iss-wo" && a.IsActive && a.CreateTime >= DateTime.Now.AddMonths(-6) && pretreatments.Select(p => p.item_number).Contains(a.ItemNum));
|
|
|
//取本月发货出库记录
|
|
|
- var shipMList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.RealQty > 0 && planItemList.Contains(a.ContainerItem) && a.ShipDate >= getMonthStartTime(0) && a.ShipDate <= DateTime.Now);
|
|
|
+ var shipMList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.RealQty > 0 && pretreatments.Select(p => p.item_number).Contains(a.ContainerItem) && a.ShipDate >= getMonthStartTime(0) && a.ShipDate <= DateTime.Now);
|
|
|
//按照物料分组统计出货金额
|
|
|
var itemGroup = shipList.GroupBy(p => p.ContainerItem)
|
|
|
.Select(p => new ASNBOLShipperDetail
|
|
|
@@ -914,73 +926,91 @@ namespace Business.Replenishment
|
|
|
//需要按照成品资源检查计算原材料
|
|
|
planList?.Where(s => s.PlanMonth == planMonth).ToList()?.ForEach(a =>
|
|
|
{
|
|
|
- ReplenishmentROP rop = new ReplenishmentROP();
|
|
|
- rop.number = a.SAPItemNumber;
|
|
|
- var icItem = itemList.Find(s => s.number == a.SAPItemNumber);
|
|
|
- if (icItem != null)
|
|
|
- {
|
|
|
- rop.name = icItem.name;
|
|
|
- rop.model = a.Model;
|
|
|
- rop.erp_cls = icItem.erp_cls; //物料属性: 0.配置类 1.自制 2.委外加工 3.外购 4.虚拟件
|
|
|
- rop.fversion = icItem.fversion;
|
|
|
- rop.min_pack_qty = icItem.minpackqty;
|
|
|
- rop.moq = icItem.moq;
|
|
|
- }
|
|
|
- rop.actual_period_start_instock = 0;
|
|
|
- if (rop.distributionchannel == "海王" || rop.distributionchannel == "国科")
|
|
|
- {
|
|
|
- rop.actual_period_start_instock = locations.Find(l => l.ItemNum == a.SAPItemNumber)?.QtyOnHand;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- rop.actual_period_start_instock = sapItemInv.Find(s => s.MATNR == a.SAPItemNumber)?.LABST.ToDecimal();
|
|
|
- }
|
|
|
- rop.distributionchannel = a.DistributionChannel;
|
|
|
- rop.lifecycle = a.LifeCycle;
|
|
|
- rop.area = a.Area;
|
|
|
- rop.plan_out_qty = Math.Ceiling(a.Qty);
|
|
|
- rop.actual_out_qty = 0;
|
|
|
- if (itemMGroup.Any(m => m.ContainerItem == a.SAPItemNumber))
|
|
|
- {
|
|
|
- rop.actual_out_qty = itemMGroup.Find(m => m.ContainerItem == a.SAPItemNumber)?.QtyToShip;
|
|
|
- }
|
|
|
- rop.year = DateTime.Now.Year;
|
|
|
- rop.long_period = "Y";
|
|
|
- rop.short_period = "M";
|
|
|
- rop.seqno = DateTime.Now.Month;
|
|
|
- rop.zero_based_seqno = 0;
|
|
|
- rop.period_start_date = getMonthStartTime(0);
|
|
|
- rop.period_end_date = getMonthEndTime(0);
|
|
|
- rop.monthl_avg_demand = CalcAvgDemand(planList, a.SAPItemNumber);
|
|
|
- rop.monthl_avg_demand_variance = Math.Ceiling(Convert.ToDecimal(CalcVariance(planList, a.SAPItemNumber)));
|
|
|
- rop.monthl_avg_outstock = CalcAvgOutStock(ropModelList, replenishmentDto, rop.actual_out_qty.Value, a.SAPItemNumber);
|
|
|
- rop.supply_leadtime = 1;//默认
|
|
|
- if (mesItemList.Find(s => s.ItemNum == a.SAPItemNumber) != null)
|
|
|
- {
|
|
|
- rop.stock_turnover = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber).StockTurnOver;
|
|
|
- rop.supply_leadtime = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber)?.PurLT;
|
|
|
- rop.stock_turnover = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber)?.StockTurnOver;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- rop.stock_turnover = 4;
|
|
|
- }
|
|
|
- if (srm_purchaseList.Find(s => s.number == a.SAPItemNumber) != null)
|
|
|
+ var itemSourceId = boms.Find(b => b.item_number == a.SAPItemNumber)?.mysql_id;
|
|
|
+ if (itemSourceId != null)
|
|
|
{
|
|
|
- rop.supply_leadtime = srm_purchaseList.Find(s => s.number == a.SAPItemNumber).lead_time;
|
|
|
+ for (int i = 0; i < pretreatments.Count; i++)
|
|
|
+ {
|
|
|
+ if (pretreatments[i].sourceid == itemSourceId)
|
|
|
+ {
|
|
|
+ ReplenishmentROP rop = new ReplenishmentROP();
|
|
|
+ rop.number = pretreatments[i].item_number;
|
|
|
+ var icItem = itemList.Find(s => s.number == pretreatments[i].item_number);
|
|
|
+ if (icItem != null)
|
|
|
+ {
|
|
|
+ rop.name = icItem.name;
|
|
|
+ rop.model = a.Model;
|
|
|
+ rop.erp_cls = icItem.erp_cls; //物料属性: 0.配置类 1.自制 2.委外加工 3.外购 4.虚拟件
|
|
|
+ rop.fversion = icItem.fversion;
|
|
|
+ rop.min_pack_qty = icItem.minpackqty;
|
|
|
+ rop.moq = icItem.moq;
|
|
|
+ }
|
|
|
+ rop.actual_period_start_instock = 0;
|
|
|
+ if (rop.distributionchannel == "海王" || rop.distributionchannel == "国科")
|
|
|
+ {
|
|
|
+ rop.actual_period_start_instock = locations.Find(l => l.ItemNum == pretreatments[i].item_number)?.QtyOnHand;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ rop.actual_period_start_instock = sapItemInv.Find(s => s.MATNR == pretreatments[i].item_number)?.LABST.ToDecimal();
|
|
|
+ }
|
|
|
+ rop.distributionchannel = a.DistributionChannel;
|
|
|
+ rop.lifecycle = a.LifeCycle;
|
|
|
+ rop.area = a.Area;
|
|
|
+ rop.plan_out_qty = Math.Ceiling(a.Qty);
|
|
|
+ rop.actual_out_qty = 0;
|
|
|
+ if (itemMGroup.Any(m => m.ContainerItem == pretreatments[i].item_number))
|
|
|
+ {
|
|
|
+ rop.actual_out_qty = itemMGroup.Find(m => m.ContainerItem == pretreatments[i].item_number)?.QtyToShip;
|
|
|
+ }
|
|
|
+ rop.year = DateTime.Now.Year;
|
|
|
+ rop.long_period = "Y";
|
|
|
+ rop.short_period = "M";
|
|
|
+ rop.seqno = DateTime.Now.Month;
|
|
|
+ rop.zero_based_seqno = 0;
|
|
|
+ rop.period_start_date = getMonthStartTime(0);
|
|
|
+ rop.period_end_date = getMonthEndTime(0);
|
|
|
+ if (rop.erp_cls == 3)
|
|
|
+ {
|
|
|
+ rop.monthl_avg_demand = CalcAvgDemand(planList, pretreatments[i].item_number, rop.erp_cls, pickbilllist);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ rop.monthl_avg_demand = CalcAvgDemand(planList, pretreatments[i].item_number, rop.erp_cls);
|
|
|
+ }
|
|
|
+
|
|
|
+ rop.monthl_avg_demand_variance = Math.Ceiling(Convert.ToDecimal(CalcVariance(planList, pretreatments[i].item_number, rop.erp_cls, rop.monthl_avg_demand, pickbilllist)));
|
|
|
+ rop.monthl_avg_outstock = CalcAvgOutStock(ropModelList, replenishmentDto, rop.actual_out_qty.Value, pretreatments[i].item_number);
|
|
|
+ rop.supply_leadtime = 1;//默认
|
|
|
+ if (mesItemList.Find(s => s.ItemNum == pretreatments[i].item_number) != null)
|
|
|
+ {
|
|
|
+ rop.stock_turnover = mesItemList.Find(s => s.ItemNum == pretreatments[i].item_number).StockTurnOver;
|
|
|
+ rop.supply_leadtime = mesItemList.Find(s => s.ItemNum == pretreatments[i].item_number)?.PurLT;
|
|
|
+ rop.stock_turnover = mesItemList.Find(s => s.ItemNum == pretreatments[i].item_number)?.StockTurnOver;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ rop.stock_turnover = 4;
|
|
|
+ }
|
|
|
+ if (srm_purchaseList.Find(s => s.number == pretreatments[i].item_number) != null)
|
|
|
+ {
|
|
|
+ rop.supply_leadtime = srm_purchaseList.Find(s => s.number == pretreatments[i].item_number).lead_time;
|
|
|
+ }
|
|
|
+ CalcFMRAndABC(rop, replenishmentDto, input);
|
|
|
+ rop.security_stock = Math.Ceiling((decimal)(mathtool.InverseCumulativeDistribution((double)rop.service_level_pct.Value) * (double)rop.monthl_avg_demand_variance));
|
|
|
+ rop.eop = Math.Ceiling(rop.monthl_avg_demand.Value * rop.supply_leadtime.Value / DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month));
|
|
|
+ rop.rop_computed = rop.security_stock + rop.eop;
|
|
|
+ rop.max_stock_level = rop.monthl_avg_outstock * (12 / rop.stock_turnover);
|
|
|
+ rop.rop_revised = Math.Min(rop.rop_computed.Value, rop.max_stock_level.Value);
|
|
|
+ rop.isparam = true;
|
|
|
+ rop.tenant_id = input.tenant_id;
|
|
|
+ rop.factory_id = input.factory_id;
|
|
|
+ rop.create_time = DateTime.Now;
|
|
|
+ rop.org_id = input.org_id;
|
|
|
+ addList.Add(rop);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- CalcFMRAndABC(rop, replenishmentDto, input);
|
|
|
- rop.security_stock = Math.Ceiling((decimal)(mathtool.InverseCumulativeDistribution((double)rop.service_level_pct.Value) * (double)rop.monthl_avg_demand_variance));
|
|
|
- rop.eop = Math.Ceiling(rop.monthl_avg_demand.Value * rop.supply_leadtime.Value / DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month));
|
|
|
- rop.rop_computed = rop.security_stock + rop.eop;
|
|
|
- rop.max_stock_level = rop.monthl_avg_outstock * (12 / rop.stock_turnover);
|
|
|
- rop.rop_revised = Math.Min(rop.rop_computed.Value, rop.max_stock_level.Value);
|
|
|
- rop.isparam = true;
|
|
|
- rop.tenant_id = input.tenant_id;
|
|
|
- rop.factory_id = input.factory_id;
|
|
|
- rop.create_time = DateTime.Now;
|
|
|
- rop.org_id = input.org_id;
|
|
|
- addList.Add(rop);
|
|
|
});
|
|
|
addList?.ForEach(item => { item.GenerateNewId(help.NextId()); });
|
|
|
|
|
|
@@ -1101,8 +1131,8 @@ namespace Business.Replenishment
|
|
|
rop.zero_based_seqno = 0;
|
|
|
rop.period_start_date = getMonthStartTime(0);
|
|
|
rop.period_end_date = getMonthEndTime(0);
|
|
|
- rop.monthl_avg_demand = CalcAvgDemand(planList, a.SAPItemNumber);
|
|
|
- rop.monthl_avg_demand_variance = Math.Ceiling(Convert.ToDecimal(CalcVariance(planList, a.SAPItemNumber)));
|
|
|
+ //rop.monthl_avg_demand = CalcAvgDemand(planList, a.SAPItemNumber);
|
|
|
+ //rop.monthl_avg_demand_variance = Math.Ceiling(Convert.ToDecimal(CalcVariance(planList, a.SAPItemNumber)));
|
|
|
rop.monthl_avg_outstock = CalcAvgOutStock(ropModelList, replenishmentDto, rop.actual_out_qty.Value, a.SAPItemNumber);
|
|
|
if (mesItemList.Find(s => s.ItemNum == a.SAPItemNumber) != null)
|
|
|
{
|
|
|
@@ -1151,7 +1181,11 @@ namespace Business.Replenishment
|
|
|
ReplenishmentDto replenishmentDto = GetROPParam(input.factory_id.ToString());
|
|
|
//DOP运行资源检查每个成品和半成品SKU的可用库存,当可用库存 <= 修正后ROP时,自动生成月度计划订单(MPlan order,MPO48年月日3位流水号)= EOP;可用库存为没有被其他SO和PO占用的(合格成品或半成品库存 + WIP);
|
|
|
var ropModelList = _replenishmentROP.GetListAsync(a =>a.isparam && a.factory_id==input.factory_id && a.company_id==input.company_id && !a.IsDeleted).Result;
|
|
|
- var itemStock=CalcStock(ropModelList.Select(a=>a.number).ToList(),input);
|
|
|
+ var itemStock = CalcStock(ropModelList.Select(a => a.number).ToList(), input);
|
|
|
+ ropModelList.Where(a => a.erp_cls == 1)?.ToList().ForEach(b =>
|
|
|
+ {
|
|
|
+
|
|
|
+ });
|
|
|
//成品半成品取下周一开始+取供应提前期为结束时间
|
|
|
//原材料取第二天开始+取供应提前期为结束时间
|
|
|
|
|
|
@@ -1173,132 +1207,92 @@ namespace Business.Replenishment
|
|
|
|
|
|
|
|
|
|
|
|
- //获取月度发货计划(一次导入三个月的销售预测),因为是固定格式yyyy-MM所以可以用字符串比较,避免写很多字符串判断相等
|
|
|
- string planMonth = $"{DateTime.Now.Year}-{DateTime.Now.Month.ToString("00")}";
|
|
|
- string planMonthMax = $"{DateTime.Now.AddMonths(replenishmentDto.SaleFcstMonth).Year}-{DateTime.Now.AddMonths(replenishmentDto.SaleFcstMonth).Month.ToString("00")}";
|
|
|
- var planList = _monthlyShipmentPlan.Select(a => a.PlanMonth.CompareTo(planMonth) >= 0 && a.PlanMonth.CompareTo(planMonthMax) <= 0 && !a.IsDeleted).ToList();
|
|
|
+ return "OK";
|
|
|
+ }
|
|
|
|
|
|
|
|
|
- var itemList = _ic_item.GetListAsync(a => planList.Select(p => p.SAPItemNumber).Contains(a.number) && a.tenant_id == input.tenant_id && a.company_id == input.company_id && !a.IsDeleted).Result;
|
|
|
- var mesItemList = _itemMaster.Select(a => planList.Select(p => p.SAPItemNumber).Contains(a.ItemNum) && a.Domain == input.factory_id.ToString() && a.IsActive);
|
|
|
- var srm_purchaseList = _srmPurchase.GetListAsync(a => planList.Select(p => p.SAPItemNumber).Contains(a.number) && a.tenant_id == input.tenant_id && a.company_id == input.company_id && !a.IsDeleted).Result;
|
|
|
+ /// <summary>
|
|
|
+ /// 根据工单编号拍优先级
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="workOrdMasters">工单编号列表</param>
|
|
|
+ /// <param name="domain">工厂编码</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ //计算工单优先级
|
|
|
+ public List<WorkOrdMaster> CalcPriority(List<string> workOrdMasters,string domain)
|
|
|
+ {
|
|
|
+ var works= _workOrdMaster.Select(a => workOrdMasters.Contains(a.WorkOrd) && a.Domain == domain && a.IsActive);
|
|
|
+ var saleWordOrd = works.Where(a => !string.IsNullOrEmpty(a.SalesJob));
|
|
|
+ Dictionary<string, int> dict = new Dictionary<string, int>();
|
|
|
+ var soList=_mysql_crm_seorder.GetListAsync(a=> saleWordOrd.Select(b=>b.SalesJob).Contains(a.bill_no)).Result;
|
|
|
+
|
|
|
+ var custList = _custMaster.Select(a => soList.Select(b => b.custom_no).Contains(a.Cust) && a.Domain == domain);
|
|
|
+ //T1海外客户
|
|
|
+ var T1CustList = custList.FindAll(a => a.Terms == "T1" || a.Terms == "海外").Select(a => a.Cust);
|
|
|
+ //国科海王客户
|
|
|
+ var T2CustList = custList.FindAll(a => a.Terms == "国科" || a.Terms == "海王").Select(a => a.Cust);
|
|
|
+ //T1海外订单
|
|
|
+ var T1SOList = soList.Where(a => T1CustList.Contains(a.custom_no)).Select(a => a.bill_no);
|
|
|
+ //国科海王订单
|
|
|
+ var T2SOList = soList.Where(a => T2CustList.Contains(a.custom_no)).Select(a => a.bill_no);
|
|
|
+ //T1海外工单
|
|
|
+ var T1WOList = saleWordOrd.Where(a => T1SOList.Contains(a.SalesJob)).ToList();
|
|
|
+ //国科海王工单
|
|
|
+ var T2WOList = saleWordOrd.Where(a => T2SOList.Contains(a.SalesJob)).ToList();
|
|
|
+ //在制工单
|
|
|
+ var inProductList = _mes_mooccupy.GetListAsync(a => works.Select(a => a.WorkOrd).Contains(a.moo_mo)).Result;
|
|
|
+
|
|
|
+ //优先1:T1、海外销售订单新产生的生产指令;
|
|
|
+ var T1WOListNew=T1WOList.Where(a=> !inProductList.Select(b=>b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a=>a.DueDate).ToList();
|
|
|
+ //优先2:T1、海外销售订单关联的在制生产指令;
|
|
|
+ var T1WOListInProduct = T1WOList.Where(a => inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ToList();
|
|
|
+ //优先3:平台(国科、海王)销售订单新产生的生产指令;
|
|
|
+ var T2WOListNew = T2WOList.Where(a => !inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ToList();
|
|
|
+ //优先4:平台(国科、海王)销售订单关联的在制生产指令;
|
|
|
+ var T2WOListInProduct = T2WOList.Where(a => !inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ToList();
|
|
|
+ //优先5:除销售订单以外,计划补货订单关联的生产指令;
|
|
|
+ var PlanWOList = works.Except(T1WOListNew).ToList();
|
|
|
+ PlanWOList = works.Except(T1WOListInProduct).ToList();
|
|
|
+ PlanWOList = works.Except(T2WOListNew).ToList();
|
|
|
+ PlanWOList = works.Except(T2WOListInProduct).ToList();
|
|
|
+ PlanWOList= PlanWOList.OrderBy(a => a.DueDate).ToList();
|
|
|
+ //先按生产指令的类型,再按生产指令的完工日期顺序排产;
|
|
|
+ List<WorkOrdMaster> orderedList = new List<WorkOrdMaster>();
|
|
|
+ decimal Priority = 1.0m;
|
|
|
+ for (int i=0;i< T1WOListNew.Count;i++)
|
|
|
+ {
|
|
|
+ T1WOListNew[i].Priority = Priority;
|
|
|
+ orderedList.Add(T1WOListNew[i]);
|
|
|
+ Priority = Priority + 1.0m;
|
|
|
+ }
|
|
|
|
|
|
- //发货计划物料列表
|
|
|
- List<string> planItemList = planList?.Select(a => a.SAPItemNumber).ToList();
|
|
|
- //获取成品库存、灭菌库存、在制库存(会从SAP同步的库存表更新到LocationDetail、ic_item表中)
|
|
|
- //List<SAPInv> sAPInvs = _SAPInv.Select(p => p.WERKS == input.factory_id.ToString() && itemNums.Contains(p.MATNR));
|
|
|
- var locations = _locationDetail.Select(p => p.Domain == input.factory_id.ToString() && planList.Select(a => a.SAPItemNumber).Contains(p.ItemNum) && p.IsActive);
|
|
|
- var sapItemInv = _SAPInv.Select(a => planItemList.Contains(a.MATNR) && a.WERKS == input.factory_id.ToString());
|
|
|
+ for (int i = 0; i < T1WOListInProduct.Count; i++)
|
|
|
+ {
|
|
|
+ T1WOListInProduct[i].Priority = Priority;
|
|
|
+ orderedList.Add(T1WOListInProduct[i]);
|
|
|
+ Priority = Priority + 1.0m;
|
|
|
+ }
|
|
|
|
|
|
- //取上一个月发货出库记录
|
|
|
- var shipList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.RealQty > 0 && planItemList.Contains(a.ContainerItem) && a.ShipDate >= getMonthStartTime(-1) && a.ShipDate <= getMonthEndTime(-1));
|
|
|
+ for (int i = 0; i < T2WOListNew.Count; i++)
|
|
|
+ {
|
|
|
+ T2WOListNew[i].Priority = Priority;
|
|
|
+ orderedList.Add(T2WOListNew[i]);
|
|
|
+ Priority = Priority + 1.0m;
|
|
|
+ }
|
|
|
|
|
|
- //取本月发货出库记录
|
|
|
- var shipMList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.RealQty > 0 && planItemList.Contains(a.ContainerItem) && a.ShipDate >= getMonthStartTime(0) && a.ShipDate <= DateTime.Now);
|
|
|
- //按照物料分组统计出货金额
|
|
|
- var itemGroup = shipList.GroupBy(p => p.ContainerItem)
|
|
|
- .Select(p => new ASNBOLShipperDetail
|
|
|
- {
|
|
|
- QtyToShip = p.Sum(a => a.QtyToShip),
|
|
|
- ContainerItem = p.Key
|
|
|
- }).ToList();
|
|
|
- //按照物料分组统计出货金额
|
|
|
- var itemMGroup = shipMList.GroupBy(p => p.ContainerItem)
|
|
|
- .Select(p => new ASNBOLShipperDetail
|
|
|
- {
|
|
|
- QtyToShip = p.Sum(a => a.QtyToShip),
|
|
|
- ContainerItem = p.Key
|
|
|
- }).ToList();
|
|
|
- List<ReplenishmentROP> addList = new List<ReplenishmentROP>();
|
|
|
- List<ReplenishmentROP> updateList = new List<ReplenishmentROP>();//更新上一个月的实际出库数量
|
|
|
- var mathtool = new MathNet.Numerics.Distributions.Normal();
|
|
|
- ropModelList?.Where(r => r.isparam && r.seqno == DateTime.Now.AddMonths(-1).Month && r.year == DateTime.Now.AddMonths(-1).Year).ToList()?.ForEach
|
|
|
- (m =>
|
|
|
- {
|
|
|
- if (itemGroup.Any(a => a.ContainerItem == m.number))
|
|
|
- {
|
|
|
- m.actual_out_qty = itemGroup.Find(a => a.ContainerItem == m.number)?.QtyToShip;
|
|
|
- updateList.Add(m);
|
|
|
- }
|
|
|
- });
|
|
|
- //需要按照成品资源检查计算原材料
|
|
|
- planList?.Where(s => s.PlanMonth == planMonth).ToList()?.ForEach(a =>
|
|
|
+ for (int i = 0; i < T2WOListInProduct.Count; i++)
|
|
|
{
|
|
|
- ReplenishmentROP rop = new ReplenishmentROP();
|
|
|
- rop.number = a.SAPItemNumber;
|
|
|
- var icItem = itemList.Find(s => s.number == a.SAPItemNumber);
|
|
|
- if (icItem != null)
|
|
|
- {
|
|
|
- rop.name = icItem.name;
|
|
|
- rop.model = a.Model;
|
|
|
- rop.erp_cls = icItem.erp_cls; //物料属性: 0.配置类 1.自制 2.委外加工 3.外购 4.虚拟件
|
|
|
- rop.fversion = icItem.fversion;
|
|
|
- rop.min_pack_qty = icItem.minpackqty;
|
|
|
- rop.moq = icItem.moq;
|
|
|
- }
|
|
|
- rop.actual_period_start_instock = 0;
|
|
|
- if (rop.distributionchannel == "海王" || rop.distributionchannel == "国科")
|
|
|
- {
|
|
|
- rop.actual_period_start_instock = locations.Find(l => l.ItemNum == a.SAPItemNumber)?.QtyOnHand;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- rop.actual_period_start_instock = sapItemInv.Find(s => s.MATNR == a.SAPItemNumber)?.LABST.ToDecimal();
|
|
|
- }
|
|
|
- rop.distributionchannel = a.DistributionChannel;
|
|
|
- rop.lifecycle = a.LifeCycle;
|
|
|
- rop.area = a.Area;
|
|
|
- rop.plan_out_qty = Math.Ceiling(a.Qty);
|
|
|
- rop.actual_out_qty = 0;
|
|
|
- if (itemMGroup.Any(m => m.ContainerItem == a.SAPItemNumber))
|
|
|
- {
|
|
|
- rop.actual_out_qty = itemMGroup.Find(m => m.ContainerItem == a.SAPItemNumber)?.QtyToShip;
|
|
|
- }
|
|
|
- rop.year = DateTime.Now.Year;
|
|
|
- rop.long_period = "Y";
|
|
|
- rop.short_period = "M";
|
|
|
- rop.seqno = DateTime.Now.Month;
|
|
|
- rop.zero_based_seqno = 0;
|
|
|
- rop.period_start_date = getMonthStartTime(0);
|
|
|
- rop.period_end_date = getMonthEndTime(0);
|
|
|
- rop.monthl_avg_demand = CalcAvgDemand(planList, a.SAPItemNumber);
|
|
|
- rop.monthl_avg_demand_variance = Math.Ceiling(Convert.ToDecimal(CalcVariance(planList, a.SAPItemNumber)));
|
|
|
- rop.monthl_avg_outstock = CalcAvgOutStock(ropModelList, replenishmentDto, rop.actual_out_qty.Value, a.SAPItemNumber);
|
|
|
- if (mesItemList.Find(s => s.ItemNum == a.SAPItemNumber) != null)
|
|
|
- {
|
|
|
- rop.stock_turnover = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber).StockTurnOver;
|
|
|
- rop.supply_leadtime = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber)?.PurLT;
|
|
|
- rop.stock_turnover = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber)?.StockTurnOver;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- rop.stock_turnover = 4;
|
|
|
- }
|
|
|
- if (srm_purchaseList.Find(s => s.number == a.SAPItemNumber) != null)
|
|
|
- {
|
|
|
- rop.supply_leadtime = srm_purchaseList.Find(s => s.number == a.SAPItemNumber).lead_time;
|
|
|
- }
|
|
|
- CalcFMRAndABC(rop, replenishmentDto, input);
|
|
|
- rop.security_stock = Math.Ceiling((decimal)(mathtool.InverseCumulativeDistribution((double)rop.service_level_pct.Value) * (double)rop.monthl_avg_demand_variance));
|
|
|
- rop.eop = Math.Ceiling(rop.monthl_avg_demand.Value * rop.supply_leadtime.Value / DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month));
|
|
|
- rop.rop_computed = rop.security_stock + rop.eop;
|
|
|
- rop.max_stock_level = rop.monthl_avg_outstock * (12 / rop.stock_turnover);
|
|
|
- rop.rop_revised = Math.Min(rop.rop_computed.Value, rop.max_stock_level.Value);
|
|
|
- rop.isparam = true;
|
|
|
- rop.tenant_id = input.tenant_id;
|
|
|
- rop.factory_id = input.factory_id;
|
|
|
- rop.create_time = DateTime.Now;
|
|
|
- rop.org_id = input.org_id;
|
|
|
- addList.Add(rop);
|
|
|
- });
|
|
|
- addList?.ForEach(item => { item.GenerateNewId(help.NextId()); });
|
|
|
+ T2WOListInProduct[i].Priority = Priority;
|
|
|
+ orderedList.Add(T2WOListInProduct[i]);
|
|
|
+ Priority = Priority + 1.0m;
|
|
|
+ }
|
|
|
|
|
|
- await _replenishmentROP.InsertManyAsync(addList);
|
|
|
- await _replenishmentROP.UpdateManyAsync(updateList);
|
|
|
- var ropModeAllList = _replenishmentROP.GetListAsync(a => a.year != DateTime.Now.Year && a.seqno != DateTime.Now.Month && a.isparam).Result;
|
|
|
- ropModeAllList?.ForEach(item => { item.seqno = item.seqno - 1; });
|
|
|
- await _replenishmentROP.UpdateManyAsync(ropModeAllList);
|
|
|
- return "OK";
|
|
|
+ for (int i = 0; i < PlanWOList.Count; i++)
|
|
|
+ {
|
|
|
+ PlanWOList[i].Priority = Priority;
|
|
|
+ orderedList.Add(PlanWOList[i]);
|
|
|
+ Priority = Priority + 1.0m;
|
|
|
+ }
|
|
|
+ return orderedList;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -2273,7 +2267,7 @@ namespace Business.Replenishment
|
|
|
/// </summary>
|
|
|
public void AutoCreateBomBill(string companyid, List<mo_ic_bom> ic_Boms = null)
|
|
|
{
|
|
|
- ic_Boms ??= _ic_bom.GetListAsync(p => p.company_id.ToString() == companyid && (p.bom_number == "10100012_V1.0" || p.bom_number == "10100241_V1.0" || p.bom_number == "BOM00042070") && !p.IsDeleted).Result.ToList();
|
|
|
+ ic_Boms ??= _ic_bom.GetListAsync(p => p.company_id.ToString() == companyid && !p.IsDeleted).Result.ToList();
|
|
|
var pretreatment = _mysql_b_bom_pretreatment.GetListAsync(s => ic_Boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
|
|
|
|
|
|
param.company_id = long.Parse(companyid);
|
|
|
@@ -2661,7 +2655,7 @@ namespace Business.Replenishment
|
|
|
var shipList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.ShipDate >= DateTime.Now.AddMonths(-6) && a.RealQty > 0 && replenishmentModel.number == a.ContainerItem);
|
|
|
//领料出库记录
|
|
|
//var pickbilllist = _NbrDetail.Select(a => a.Domain == input.factory_id.ToString() && a.Type == "SM" && a.IsActive && a.UpdateTime >= DateTime.Now.AddMonths(replenishmentDto.HistoryOutStockMonth * -1) && itemNumList.Contains(a.ItemNum));
|
|
|
- var pickbilllist = _invTransHist.Select(a => a.Domain == input.factory_id.ToString() && a.TransType == "iss-wo" && a.IsActive && a.CreateTime >= DateTime.Now.AddMonths(-6) && replenishmentModel.number == a.ItemNum);
|
|
|
+ List<InvTransHist> pickbilllist = _invTransHist.Select(a => a.Domain == input.factory_id.ToString() && a.TransType == "iss-wo" && a.IsActive && a.CreateTime >= DateTime.Now.AddMonths(-6) && replenishmentModel.number == a.ItemNum);
|
|
|
//总的移库次数
|
|
|
int totalCount = shipList.Count() + pickbilllist.Count();
|
|
|
//平均出库次数
|
|
|
@@ -2734,9 +2728,25 @@ namespace Business.Replenishment
|
|
|
/// <param name="itemNum"></param>
|
|
|
/// <param name="month"></param>
|
|
|
/// <returns></returns>
|
|
|
- public decimal CalcAvgDemand(List<MonthlyShipmentPlan> list, string itemNum)
|
|
|
+ public decimal CalcAvgDemand(List<MonthlyShipmentPlan> list, string itemNum,int? erp_cls, List<InvTransHist> pickbilllist=null)
|
|
|
{
|
|
|
- return list.Where(i => i.SAPItemNumber == itemNum).Select(a => a.Qty).Average();
|
|
|
+ if(erp_cls!=3)
|
|
|
+ {
|
|
|
+ if(list.Where(i => i.SAPItemNumber == itemNum).Count()>0)
|
|
|
+ {
|
|
|
+ return list.Where(i => i.SAPItemNumber == itemNum).Average(a => a.Qty);
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }else
|
|
|
+ {
|
|
|
+ var pickItemList = pickbilllist.Select(a => a.ItemNum).Distinct();
|
|
|
+ var sumQty = pickbilllist.Where(a => a.ItemNum == itemNum)?.Sum(a => a.QtyChange);
|
|
|
+ var month = pickbilllist.Where(a => a.ItemNum == itemNum)?.Select(a => a.CreateTime.Value.Month).Distinct().Count();
|
|
|
+ if (month == 0)
|
|
|
+ return sumQty.Value;
|
|
|
+ else
|
|
|
+ return sumQty.GetValueOrDefault()/month.Value;
|
|
|
+ }
|
|
|
}
|
|
|
/// <summary>
|
|
|
///
|
|
|
@@ -2751,13 +2761,22 @@ namespace Business.Replenishment
|
|
|
return (list.Where(i => i.number == itemNum && i.zero_based_seqno > 1 - replenishmentDto.HistoryOutStockMonth && i.zero_based_seqno <= 0).Select(a => a.actual_out_qty.Value).Sum() + MQty) / (replenishmentDto.HistoryOutStockMonth + 1);
|
|
|
}
|
|
|
|
|
|
- public double CalcVariance(List<MonthlyShipmentPlan> list, string itemNum)
|
|
|
+ public double CalcVariance(List<MonthlyShipmentPlan> list, string itemNum, int? erp_cls,decimal? monthl_avg_demand, List<InvTransHist> pickbilllist = null)
|
|
|
{
|
|
|
- var avg = CalcAvgDemand(list, itemNum);
|
|
|
- var nums = list.Where(i => i.SAPItemNumber == itemNum).Select(a => a.Qty);
|
|
|
- if (nums.Count() <= 1)
|
|
|
- return 0;
|
|
|
- return Math.Sqrt(nums.Sum(x => Math.Pow(Convert.ToDouble(x) - Convert.ToDouble(avg), 2)) / (nums.Count() - 1));
|
|
|
+ if (erp_cls != 3)
|
|
|
+ {
|
|
|
+ var nums = list.Where(i => i.SAPItemNumber == itemNum).Select(a => a.Qty);
|
|
|
+ if (nums.Count() <= 1)
|
|
|
+ return 0;
|
|
|
+ return Math.Sqrt(nums.Sum(x => Math.Pow(Convert.ToDouble(x) - Convert.ToDouble(monthl_avg_demand), 2)) / (nums.Count() - 1));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var nums = pickbilllist.Where(i => i.ItemNum == itemNum).Select(a =>a.QtyChange);
|
|
|
+ if (nums.Count() <= 1)
|
|
|
+ return 0;
|
|
|
+ return Math.Sqrt(nums.Sum(x => Math.Pow(Convert.ToDouble(x) - Convert.ToDouble(monthl_avg_demand), 2)) / (nums.Count() - 1));
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/// <summary>
|