using Amazon.Runtime.Internal.Util;
using Business.Core.Enum;
using Business.Core.Utilities;
using Business.Domain;
using Business.Dto;
using Business.EntityFrameworkCore;
using Business.EntityFrameworkCore.SqlRepositories;
using Business.ReplenishmentManagement;
using Business.ResourceExamineManagement;
using Business.ResourceExamineManagement.Dto;
using Business.StructuredDB.MES;
using Business.StructuredDB.MES.IC;
using Business.StructuredDB.Production;
using Business.StructuredDB.Replenishment;
using Business.StructuredDB.SaleFcst;
using Business.StructuredDB.WMS;
using Business.SystemJob;
using Business.SystemJobManagement;
using EFCore.BulkExtensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using Newtonsoft.Json;
using NPOI.SS.Formula.Functions;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Data;
using System.Linq;
using System.Reflection;
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.ObjectMapping;
using Volo.Abp.Uow;
using ZstdSharp.Unsafe;
using static Azure.Core.HttpHeader;
using static NetTopologySuite.Geometries.Utilities.GeometryMapper;
namespace Business.Replenishment
{
///
/// 产能分析
///
public class ReplenishmentAppService : ApplicationService, IReplenishmentAppService, ITransientDependency
{
#region 服务
///
/// 雪花算法
///
SnowFlake help = new SnowFlake();
private readonly IRepository _replenishmentROPWeekPlan;
private readonly ISqlRepository _ASNBOLShipperDetail;
private readonly ISqlRepository _ASNBOLShipperMaster;
private readonly ISqlRepository _invTransHist;
private readonly ISqlRepository _invMaster;
private readonly ISqlRepository _SAPInv;
private readonly IRepository _srmPurchase;
///
/// 交货计划
///
private readonly IRepository _icdemandschedule;
///
/// 交货单
///
private readonly ISqlRepository _srmpolistds;
///
/// 采购明细表
///
private readonly ISqlRepository _PurOrdDetail;
///
/// 采购单表
///
private readonly ISqlRepository _PurOrdMaster;
///
/// 优先级配置表
///
private readonly ISqlRepository _PriorityCode;
private ISqlRepository _nbrMaster;
private ISqlRepository _nbrDetail;
///
/// 送货单子表
///
private readonly ISqlRepository _scm_shdzb;
///
/// 交货单异常记录表
///
private readonly ISqlRepository _DeliveryExceptionMaster;
private readonly ISqlRepository _monthlyShipmentPlan;
private readonly ISqlRepository _monthlyShipmentPlanHistory;
private readonly ISqlRepository _generalizedCodeMaster;
private readonly IRepository _ic_item;
private readonly IRepository _mysql_ic_item;
private readonly ISqlRepository _itemMaster;
private readonly IRepository _srm_pr_main;
private readonly IRepository _mysql_srm_pr_main;
private readonly IRepository _srm_po_occupy;
private readonly IRepository _mysql_srm_po_occupy;
private readonly IRepository _mysql_srm_pr_main_occupy;
private readonly IRepository _mes_morder;
private readonly IRepository _mes_moentry;
private readonly IRepository _mes_mooccupy;
private readonly IRepository _mysql_mes_mooccupy;
private readonly IRepository _mysql_b_bom_pretreatment;
private readonly ISqlRepository _workOrdMaster;
private readonly ISqlRepository _prodLineDetail;
private readonly ISqlRepository _lineMaster;
private readonly IRepository _ic_bom;
private readonly IRepository _mysql_ic_bom;
private readonly IRepository _ic_bom_child;
private readonly IRepository _mysql_ic_bom_child;
private readonly ISqlRepository _holidayMaster;
private readonly IRepository _ic_item_stockoccupy;
private readonly IRepository _mysql_ic_item_stockoccupy;
private readonly IRepository _ic_item_stock;
private readonly IRepository _mysql_ic_item_stock;
private readonly IRepository _ic_substitute;
private readonly IRepository _ic_substitute_group;
private readonly IRepository _ic_substitute_group_detail;
private readonly IRepository _mysql_ic_substitute;
private readonly IRepository _mysql_ic_substitute_group;
private readonly IRepository _mysql_ic_substitute_group_detail;
private readonly IRepository _mysql_mes_moentry;
private readonly ISqlRepository _workOrdDetail;
private readonly IRepository _srm_po_list;
private readonly IRepository _mysql_srm_po_list;
private readonly ISqlRepository _routingOpDetail;
private readonly ISqlRepository _productStructureMaster;
private readonly ISqlRepository _shopCalendarWorkCtr;
private readonly ISqlRepository _qualityLineWorkDetail;
private readonly ISqlRepository _custMaster;
private readonly IRepository _srm_po_main;
private readonly IRepository _mysql_srm_po_main;
private readonly IRepository _srm_purchase;
private readonly IRepository _mysql_srm_purchase;
private readonly IRepository _mysql_mes_morder;
private readonly IRepository _mysql_crm_seorder;
private readonly IRepository _mysql_crm_seorderentry;
private readonly IRepository _productionMasterPlan;
private readonly IRepository _replenishmentWeekPlan;
private readonly IRepository _mysql_examine_result;
private readonly IRepository _mysql_bom_child_examine;
private readonly IRepository _replenishmentServiceLevel;
//private readonly IExtSqlRepository _DMS_IN_ITEMMAPPING;
//private readonly IExtSqlRepository _DMS_IN_LOCDETAIL;
//private readonly IExtSqlRepository _DMS_IN_SHIPPINGDETAIL;
private readonly IRepository _ReplenishmentTurnOverSet;
///
/// 成品虚拟件工序关系表
///
private readonly ISqlRepository _productStructureOp;
///
/// 年度销售预测
///
private IRepository _yearDemandManagement;
///
/// 年度销售预测历史记录
///
private IRepository _yearDemandManagementHistory;
///
/// 年度生产大纲
///
private IRepository _replenishmentAnnualProduction;
///
/// 平台库存表
///
private readonly IRepository _PlatformInventory;
///
/// 工单工艺路线明细
///
private ISqlRepository _workOrdRouting;
///
/// 排产结果明细
///
private ISqlRepository _scheduleResultOpMaster;
///
/// 排产记录表
///
private readonly ISqlRepository _periodSequenceDet;
///
/// 计划订单表
///
private IRepository _crm_planorder;
///
/// 平台库存表
///
private IRepository _platformInventory;
///
/// 在途检查
///
private readonly PurchaseOrderAppService _purchaseOrderAppService;
///
/// 计算BOM平铺物料情况
///
private readonly CalcBomViewAppService _CalcBomViewAppService;
///
/// 工单App
///
private readonly MorderAppService _morderAppService;
///
/// 预处理
///
private readonly PretreatmentAppService _pretreatmentAppService;
private readonly SerialNumberAppService _serialNumberAppService;
///
/// 产能检查
///
private readonly ProductExamineAppService _productExamineAppService;
///
/// 账号时效性验证
///
private readonly AccountValidityAppService _AccountValidityAppService;
///
/// 资源检查入参
///
private readonly SeorderentryDto param = new SeorderentryDto();
///
/// 生产线明细表
///
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();
private readonly ISqlRepository _configurationItem;
///
/// 节假日
///
public List holidays = new List();
private List leadTimeList;
private List supplierList;
private readonly BusinessBangDbContext _businessBangDbContext;
private readonly BusinessDbContext _businessDbContext;
private readonly ICurrentTenant _currentTenant;
private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly SystemJobAppService _systemJobAppService;
#endregion
#region 构造函数
///
/// 构造函数
///
public ReplenishmentAppService(
IRepository replenishmentROPWeekPlan,
ISqlRepository ASNBOLShipperDetail,
ISqlRepository ASNBOLShipperMaster,
ISqlRepository invTransHist,
IRepository srmPurchase,
ISqlRepository monthlyShipmentPlan,
ISqlRepository monthlyShipmentPlanHistory,
ISqlRepository generalizedCodeMaster,
ISqlRepository invMaster,
ISqlRepository SAPInv,
IRepository ic_item,
IRepository mysql_ic_item,
ISqlRepository itemMaster,
IRepository srm_pr_main,
IRepository mysql_srm_pr_main,
IRepository srm_po_occupy,
IRepository mysql_srm_po_occupy,
IRepository mysql_srm_pr_main_occupy,
IRepository mes_morder,
IRepository mes_moentry,
IRepository mes_mooccupy,
IRepository mysql_mes_mooccupy,
IRepository mysql_b_bom_pretreatment,
ISqlRepository workOrdMaster,
ISqlRepository prodLineDetail,
ISqlRepository lineMaster,
IRepository ic_bom,
IRepository mysql_ic_bom,
IRepository ic_bom_child,
IRepository mysql_ic_bom_child,
ISqlRepository holidayMaster,
IRepository ic_item_stockoccupy,
IRepository mysql_ic_item_stockoccupy,
IRepository ic_item_stock,
IRepository mysql_ic_item_stock,
IRepository ic_substitute,
IRepository ic_substitute_group,
IRepository ic_substitute_group_detail,
IRepository mysql_ic_substitute,
IRepository mysql_ic_substitute_group,
IRepository mysql_ic_substitute_group_detail,
IRepository mysql_mes_moentry,
ISqlRepository workOrdDetail,
IRepository srm_po_list,
IRepository mysql_srm_po_list,
ISqlRepository routingOpDetail,
ISqlRepository productStructureMaster,
ISqlRepository shopCalendarWorkCtr,
ISqlRepository periodSequenceDet,
ISqlRepository qualityLineWorkDetail,
ISqlRepository scheduleResultOpMaster,
IRepository srm_po_main,
IRepository mysql_srm_po_main,
IRepository srm_purchase,
IRepository mysql_srm_purchase,
IRepository mysql_mes_morder,
IRepository mysql_crm_seorder,
IRepository mysql_crm_seorderentry,
IRepository mes_oorder,
IRepository productionMasterPlan,
ISqlRepository productStructureOp,
IRepository yearDemandManagement,
IRepository replenishmentAnnualProduction,
IRepository yearDemandManagementHistory,
IRepository PlatformInventory,
ISqlRepository workOrdRouting,
ISqlRepository custMaster,
IRepository crm_planorder,
IRepository platformInventory,
IRepository replenishmentWeekPlan,
IRepository mysql_examine_result,
IRepository mysql_bom_child_examine,
IRepository replenishmentServiceLevel,
ISqlRepository nbrMaster,
ISqlRepository nbrDetail,
//IExtSqlRepository DMS_IN_ITEMMAPPING,
//IExtSqlRepository DMS_IN_LOCDETAIL,
//IExtSqlRepository DMS_IN_SHIPPINGDETAIL,
IRepository ReplenishmentTurnOverSet,
ISqlRepository configurationItem,
SerialNumberAppService serialNumberAppService,
PretreatmentAppService pretreatmentAppService,
PurchaseOrderAppService purchaseOrderAppService,
CalcBomViewAppService CalcBomViewAppService,
MorderAppService morderAppService,
AccountValidityAppService AccountValidityAppService,
ProductExamineAppService productExamineAppService,
BusinessBangDbContext businessBangDbContext,
BusinessDbContext businessDbContext,
ICurrentTenant currentTenant,
IRepository icdemandschedule,
ISqlRepository srmpolistds,
ISqlRepository PurOrdDetail,
ISqlRepository PurOrdMaster,
ISqlRepository DeliveryExceptionMaster,
ISqlRepository scm_shdzb,
IUnitOfWorkManager unitOfWorkManager,
ISqlRepository PriorityCode,
SystemJobAppService systemJobAppService)
{
_replenishmentROPWeekPlan = replenishmentROPWeekPlan;
_ASNBOLShipperDetail = ASNBOLShipperDetail;
_ASNBOLShipperMaster = ASNBOLShipperMaster;
_invTransHist = invTransHist;
_srmPurchase = srmPurchase;
_monthlyShipmentPlan = monthlyShipmentPlan;
_monthlyShipmentPlanHistory = monthlyShipmentPlanHistory;
_generalizedCodeMaster = generalizedCodeMaster;
_invMaster = invMaster;
_SAPInv = SAPInv;
_nbrMaster = nbrMaster;
_nbrDetail = nbrDetail;
_ic_item = ic_item;
_mysql_ic_item = mysql_ic_item;
_itemMaster = itemMaster;
_srm_pr_main = srm_pr_main;
_mysql_srm_pr_main = mysql_srm_pr_main;
_srm_po_occupy = srm_po_occupy;
_mysql_srm_po_occupy = mysql_srm_po_occupy;
_mysql_srm_pr_main_occupy = mysql_srm_pr_main_occupy;
_mes_morder = mes_morder;
_mes_moentry = mes_moentry;
_mes_mooccupy = mes_mooccupy;
_mysql_mes_mooccupy = mysql_mes_mooccupy;
_mysql_b_bom_pretreatment = mysql_b_bom_pretreatment;
_workOrdMaster = workOrdMaster;
_scheduleResultOpMaster = scheduleResultOpMaster;
_periodSequenceDet = periodSequenceDet;
_custMaster = custMaster;
_prodLineDetail = prodLineDetail;
_lineMaster = lineMaster;
_ic_bom = ic_bom;
_mysql_ic_bom = mysql_ic_bom;
_ic_bom_child = ic_bom_child;
_mysql_ic_bom_child = mysql_ic_bom_child;
_holidayMaster = holidayMaster;
_ic_item_stockoccupy = ic_item_stockoccupy;
_mysql_ic_item_stockoccupy = mysql_ic_item_stockoccupy;
_ic_item_stock = ic_item_stock;
_mysql_ic_item_stock = mysql_ic_item_stock;
_ic_substitute = ic_substitute;
_ic_substitute_group = ic_substitute_group;
_ic_substitute_group_detail = ic_substitute_group_detail;
_mysql_ic_substitute = mysql_ic_substitute;
_mysql_ic_substitute_group = mysql_ic_substitute_group;
_mysql_ic_substitute_group_detail = mysql_ic_substitute_group_detail;
_mysql_mes_moentry = mysql_mes_moentry;
_workOrdDetail = workOrdDetail;
_srm_po_list = srm_po_list;
_mysql_srm_po_list = mysql_srm_po_list;
_routingOpDetail = routingOpDetail;
_productStructureMaster = productStructureMaster;
_shopCalendarWorkCtr = shopCalendarWorkCtr;
_qualityLineWorkDetail = qualityLineWorkDetail;
_srm_po_main = srm_po_main;
_mysql_srm_po_main = mysql_srm_po_main;
_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;
_productionMasterPlan = productionMasterPlan;
_replenishmentWeekPlan = replenishmentWeekPlan;
_mysql_examine_result = mysql_examine_result;
_mysql_bom_child_examine = mysql_bom_child_examine;
_replenishmentServiceLevel = replenishmentServiceLevel;
_productStructureOp = productStructureOp;
_PlatformInventory = PlatformInventory;
_workOrdRouting = workOrdRouting;
_ASNBOLShipperDetail = ASNBOLShipperDetail;
_yearDemandManagement = yearDemandManagement;
_yearDemandManagementHistory = yearDemandManagementHistory;
_replenishmentAnnualProduction = replenishmentAnnualProduction;
_holidayMaster = holidayMaster;
_crm_planorder = crm_planorder;
_platformInventory = platformInventory;
//_DMS_IN_ITEMMAPPING = DMS_IN_ITEMMAPPING;
//_DMS_IN_LOCDETAIL = DMS_IN_LOCDETAIL;
//_DMS_IN_SHIPPINGDETAIL = DMS_IN_SHIPPINGDETAIL;
_ReplenishmentTurnOverSet = ReplenishmentTurnOverSet;
_configurationItem = configurationItem;
_serialNumberAppService = serialNumberAppService;
_pretreatmentAppService = pretreatmentAppService;
_CalcBomViewAppService = CalcBomViewAppService;
_morderAppService = morderAppService;
_AccountValidityAppService = AccountValidityAppService;
_purchaseOrderAppService = purchaseOrderAppService;
_productExamineAppService = productExamineAppService;
_currentTenant = currentTenant;
_businessBangDbContext = businessBangDbContext;
_businessDbContext = businessDbContext;
_unitOfWorkManager = unitOfWorkManager;
_icdemandschedule = icdemandschedule;
_srmpolistds = srmpolistds;
_PurOrdDetail = PurOrdDetail;
_PurOrdMaster = PurOrdMaster;
_DeliveryExceptionMaster = DeliveryExceptionMaster;
_scm_shdzb = scm_shdzb;
_PriorityCode = PriorityCode;
_systemJobAppService = systemJobAppService;
}
#endregion
///
/// 生成年度生产大纲
///
///
///
///
public async Task SaveAnnualProductionOutline(InputDto input)
{
//来自定时任务的请求
if (input.year == 0 && input.month == 0)
{
input.year = DateTime.Now.Year;
input.month = DateTime.Now.Month;
}
//每年10月份做下一年的销售预测
if (DateTime.Now.Month >= 10)
{
input.year = DateTime.Now.AddYears(1).Year;
input.month = DateTime.Now.Month;
}
//获取当前导入或修改数据
List yearDemands = _yearDemandManagement.GetListAsync(p => p.Year == input.year && p.factory_id == input.factory_id && !p.IsDeleted).Result.OrderBy(p => p.OrderNum).ThenBy(o => o.PlanMonth).ToList();
if (yearDemands == null || yearDemands.Count == 0)
{
input.year = DateTime.Now.Year;
input.month = DateTime.Now.Month;
yearDemands = _yearDemandManagement.GetListAsync(p => p.Year == input.year && p.factory_id == input.factory_id && !p.IsDeleted).Result.OrderBy(p => p.OrderNum).ThenBy(o => o.PlanMonth).ToList();
}
//标准工艺路径表
var sapItemList = yearDemands.Select(m => m.SAPItemNumber).Distinct().ToList();
var planList = _mysql_ic_item.GetListAsync(a => sapItemList.Contains(a.number) && a.factory_id == input.factory_id && !a.IsDeleted).Result.ToList();
var bomList = _mysql_ic_bom.GetListAsync(a => sapItemList.Contains(a.item_number) && !a.IsDeleted && a.factory_id == input.factory_id).Result;
var planItemList = planList.Select(a => a.number).Distinct().ToList();
var expectedList = sapItemList.Except(planItemList).ToList();
if (expectedList.Count > 0)
{
return "年度销售预测物料" + string.Join(",", expectedList) + "在DOP物料表找不到!";
}
var bomItemList = bomList.Select(a => a.item_number).Distinct().ToList();
var expectedBOMList = sapItemList.Except(bomItemList).ToList();
if (expectedBOMList.Count > 0)
{
return "年度销售预测物料" + string.Join(",", expectedBOMList) + "在BOM没有维护!";
}
var itemMasterList = _itemMaster.Select(i => sapItemList.Contains(i.ItemNum) && i.Domain == input.factory_id.ToString());
List routingOps = _routingOpDetail.Select(p => sapItemList.Contains(p.RoutingCode) && p.Domain == input.factory_id.ToString() && p.IsActive);
var routingOpList = routingOps.Where(x => x.Ufld1 == "组装" && x.MilestoneOp).ToList();
//生产线明细表
List prodLines = _prodLineDetail.Select(p => sapItemList.Contains(p.Part) && p.Domain == input.factory_id.ToString() && p.IsActive && routingOpList.Select(m => m.Op).Contains(p.Op)).OrderBy(x => x.Sequence).ToList();
List lineMasters = _lineMaster.Select(p => prodLines.Select(a => a.Line).Distinct().ToList().Contains(p.Line) && p.Domain == input.factory_id.ToString() && p.IsActive).ToList();
List locations = _invMaster.Select(x => sapItemList.Contains(x.ItemNum) && x.Domain == input.factory_id.ToString() && x.IsActive).ToList();
//平台库存
//var DMSItemList = _DMS_IN_ITEMMAPPING.Select(a => sapItemList.Contains(a.CfnERPCode));
//var gkhwStock = _DMS_IN_LOCDETAIL.Select(a => (a.DealerCode == "RQ000005" || a.DealerCode == "RQ000002"));
//var sapInvList = _SAPInv.Select(a => a.WERKS == input.factory_id.ToString() && sapItemList.Contains(a.MATNR) && (a.SOBKZ.ToUpper() == "O"));
// 获取某年某月的起始日期和结束日期
DateTime start = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
DateTime end = start.AddMonths(1).AddDays(-1);
//取当月发货出库记录
var shipList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.RealQty > 0 && yearDemands.Select(p => p.SAPItemNumber).Contains(a.ContainerItem)).Where(s => s.ShipDate >= start && s.ShipDate <= end);
#region 在制数量
//获取在制数量 获取工单数取每年4月到12月底的工单
DateTime startYear = new DateTime(DateTime.Now.AddYears(-1).Year, 4, 1);
DateTime endYear = new DateTime(DateTime.Now.Year, 12, 31);
List workOrdRoutings = _workOrdRouting.Select(x => x.IsActive && x.QtyComplete > 0 && x.Domain == input.factory_id.ToString()).Where(p => p.DueDate >= startYear && p.DueDate <= endYear).ToList();
decimal? InProductionQty = 0.00m;
var workOrds = workOrdRoutings.GroupBy(x => x.WorkOrd).ToList();
Dictionary dictInProduction = new Dictionary();
//按照工单循环
//某工单10-90工序 Max(10-80工序QtyComplete)-90工序QtyComplete =在制数量
foreach (var item in workOrds)
{
var workOrdRoutingList = workOrdRoutings.Where(x => x.WorkOrd == item.Key).OrderByDescending(o => o.OP).ToList();
//找出最大工序
var MaxOp = workOrdRoutingList.FirstOrDefault();
//查询出其他工序最大值
var MaxQtyComplete = workOrdRoutingList.Where(x => x.RecID != MaxOp.RecID).ToList().Max(o => o.QtyComplete);
InProductionQty += MaxQtyComplete - MaxOp.QtyComplete;
if (dictInProduction.ContainsKey(MaxOp.ItemNum))
{
dictInProduction[MaxOp.ItemNum] += InProductionQty.Value;
}
else
{
dictInProduction.Add(MaxOp.ItemNum, InProductionQty.Value);
}
}
#endregion
//年度生产大纲实体
List annualProductionOutlines = new List();
List frontYearDemand = new List();
for (int i = 0; i < yearDemands.Count; i++)
{
if (yearDemands.Where(a => a.SAPItemNumber == yearDemands[i].SAPItemNumber).Count() != 12)
{
return "年度销售预测物料" + yearDemands[i].SAPItemNumber + "年度的12个月数据不完整或者存在重复物料!";
}
frontYearDemand.Add(yearDemands[i]);
var routingOp = routingOps.Where(x => x.RoutingCode == yearDemands[i].SAPItemNumber).ToList();
//组装标准工时
var Assembly = routingOp.Where(x => x.Ufld1 == "组装" && x.MilestoneOp).FirstOrDefault();
//热封标准工时
var HeatSealing = routingOp.Where(x => x.Ufld1 == "热封" && x.MilestoneOp).FirstOrDefault();
//包装标准工时
var Packaging = routingOp.Where(x => x.Ufld1 == "包装" && x.MilestoneOp).FirstOrDefault();
var prodLine = prodLines.Where(x => x.Part == yearDemands[i].SAPItemNumber).OrderBy(x => x.Sequence).FirstOrDefault();
//不同库位库存数量
//5008成品线边库,8001成品合格库,8000成品待检
var locationList = locations.Where(x => x.ItemNum == yearDemands[i].SAPItemNumber && (x.Location == "5008" || x.Location == "5009" || x.Location == "5010" || x.Location == "8000" || x.Location == "8001" || x.Location == "8002" || x.Location == "8002" || x.Location == "8003" || x.Location == "8004" || x.Location == "8005")).ToList();
////平台数据
//decimal? hwStock = 0;
//if (DMSItemList.Find(d => d.CfnERPCode == yearDemands[i].SAPItemNumber) != null)
//{
// var itemDMS = gkhwStock.Where(o => o.UPN == DMSItemList.Find(d => d.CfnERPCode == yearDemands[i].SAPItemNumber).CfnCode && o.DealerCode == "RQ000002").ToList();
// if (itemDMS.Count > 0)
// {
// var maxDate = itemDMS.OrderByDescending(i => i.InventoryDate).First();
// hwStock = itemDMS.Where(i => i.InventoryDate == maxDate.InventoryDate).Sum(q => q.Qty);
// }
//}
//decimal? gkStock = 0;
//if (DMSItemList.Find(d => d.CfnERPCode == yearDemands[i].SAPItemNumber) != null)
//{
// var itemDMS = gkhwStock.Where(o => o.UPN == DMSItemList.Find(d => d.CfnERPCode == yearDemands[i].SAPItemNumber).CfnCode && o.DealerCode == "RQ000005").ToList();
// if (itemDMS.Count > 0)
// {
// var maxDate = itemDMS.OrderByDescending(i => i.InventoryDate).First();
// gkStock = itemDMS.Where(i => i.InventoryDate == maxDate.InventoryDate).Sum(q => q.Qty);
// }
//}
//销售预测 对应 Excel中公式 AVERAGE 如果预测为0不参与计算排产批量
var QtySum = yearDemands.Where(x => x.SAPItemNumber == yearDemands[i].SAPItemNumber && x.Qty > 0).ToList();
//排产批量:(AVG(1 - 12月销售预测)/ 100 )=(0.45 = 1 小数向上取整) *100 = 100
decimal pcpl = 0;
if (QtySum != null && QtySum.Count > 0)
{
pcpl = 1;//Math.Ceiling(QtySum.Average(p => p.Qty));
}
//库存合计 + 在制+已发货 + 灭菌中
var ship = shipList.Where(x => x.ContainerItem == yearDemands[i].SAPItemNumber).ToList();
decimal itemInProduct = 0;
if (dictInProduction.ContainsKey(yearDemands[i].SAPItemNumber))
{
itemInProduct = dictInProduction[yearDemands[i].SAPItemNumber];
}
decimal? InSterilizationQty = 0.00m;
//if (sapInvList.Count > 0 && sapInvList.Any(a => a.MATNR == yearDemands[i].SAPItemNumber))
//{
// InSterilizationQty = sapInvList.Where(a => a.MATNR == yearDemands[i].SAPItemNumber && a.SOBKZ.ToUpper() == "O").Sum(x => Convert.ToDecimal(x.LABST) + Convert.ToDecimal(x.INSME) + Convert.ToDecimal(x.SPEME));
//}
//+ gkStock + hwStock
var locationSum = (locationList.Count == 0 ? 0 : locationList.Sum(x => x.AvailStatusQty.GetValueOrDefault() + x.Assay.GetValueOrDefault())) + (ship.Count == 0 ? 0 : ship.Sum(x => x.QtyToShip)) + itemInProduct + InSterilizationQty;
//前面N个月的生产数量
var frontQtySum = annualProductionOutlines.Where(a => a.SAPItemNumber == yearDemands[i].SAPItemNumber).Sum(x => x.Qty);
//生产数量:3月为例子,if((库存合计和前2月生产数量)-(前2个月销售预测数据)-当月销售预测数据 / 2 < 0)
// { 排产批量 * ((-(库存合计+前12个月生产数量)) + (前12个月销售预测) + 当月销售预测 / 2 ) / 排产批量 ) } else {0}
decimal ProduceQty = 0.00m;
decimal NextMonthQty = 0.00m;
if (yearDemands[i].PlanMonth.Substring(5) != "12")
{
NextMonthQty = yearDemands[i + 1].Qty;
}
else
{
NextMonthQty = pcpl;
}
//判断库存是否满足需要,满足则不用生产
//安全库存
decimal? safeQty = itemMasterList.Find(a => a.ItemNum == yearDemands[i].SAPItemNumber)?.SafetyStk;
//前N个月的需求数量
decimal frontYearDemandQty = frontYearDemand.Where(f => f.SAPItemNumber == yearDemands[i].SAPItemNumber).Sum(m => m.Qty);
if (locationSum.GetValueOrDefault() + frontQtySum - safeQty - frontYearDemandQty - NextMonthQty / 2 < 0)
{
if (pcpl == 0)
{
ProduceQty = 0;
}
else
{
ProduceQty = Math.Ceiling((-locationSum.GetValueOrDefault() - frontQtySum + safeQty.GetValueOrDefault() + frontYearDemandQty + NextMonthQty / 2) / pcpl) * pcpl;
}
}
//生成年度生产大纲
ReplenishmentAnnualProduction annualProductionOutline = new ReplenishmentAnnualProduction();
annualProductionOutline.Year = yearDemands[i].Year;
annualProductionOutline.Area = yearDemands[i].Area;
annualProductionOutline.ProdLine = yearDemands[i].ProdLine;
annualProductionOutline.ProdRange = yearDemands[i].ProdRange;
if (prodLine == null || lineMasters.Find(b => b.Line == prodLine.Line) == null)
{
annualProductionOutline.WorkshopLine = "";
}
else
{
annualProductionOutline.WorkshopLine = lineMasters.Find(b => b.Line == prodLine.Line).Describe;
}
annualProductionOutline.SAPItemNumber = yearDemands[i].SAPItemNumber;
annualProductionOutline.Model = yearDemands[i].Model;
annualProductionOutline.Languages = yearDemands[i].Languages;
annualProductionOutline.PlanMonth = yearDemands[i].PlanMonth;
annualProductionOutline.Qty = ProduceQty;
annualProductionOutline.StandardHours = (Assembly == null ? 0 : Assembly.RunTime) + (HeatSealing == null ? 0 : HeatSealing.RunTime) + (Packaging == null ? 0 : Packaging.RunTime);
//组装热封包装工时乘以数量 =单月工时
annualProductionOutline.AssemblyHours = Assembly == null ? 0 : Assembly.RunTime * ProduceQty;
annualProductionOutline.HeatSealingHours = HeatSealing == null ? 0 : HeatSealing.RunTime * ProduceQty;
annualProductionOutline.PackagingHours = Packaging == null ? 0 : Packaging.RunTime * ProduceQty;
annualProductionOutline.Totalhours = annualProductionOutline.AssemblyHours + annualProductionOutline.HeatSealingHours + annualProductionOutline.Totalhours;
annualProductionOutline.OrderNum = yearDemands[i].OrderNum;
annualProductionOutline.create_time = DateTime.Now;
annualProductionOutline.tenant_id = input.tenant_id;
annualProductionOutline.company_id = input.company_id;
annualProductionOutline.factory_id = input.factory_id;
annualProductionOutline.org_id = input.org_id;
annualProductionOutlines.Add(annualProductionOutline);
}
//保存数据
using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
{
try
{
var toDelete = _businessDbContext.ReplenishmentAnnualProduction.Where(a => a.Year == input.year && a.factory_id == input.factory_id).ToList();
await _businessDbContext.BulkDeleteAsync(toDelete);
await _businessDbContext.BulkInsertAsync(annualProductionOutlines);
await CalcLongPeriodItemPR(input);
await CalcROP(input);
await SaveProductionMasterPlan(input, annualProductionOutlines);
//await CalcWeekPlan(input);
await unitOfWork.CompleteAsync();
}
catch (Exception e)
{
unitOfWork.Dispose();
new NLogHelper("AnnualProductionOutlineAppService").WriteLog("SaveAnnualProductionOutline", "【" + input.year + "年" + "】年度生成大纲生成失败:" + e.Message, _currentTenant.Id.ToString());
return "NO|" + e.Message;
};
}
return "OK";
}
///
/// 生成主计划
///
///
///
public async Task SaveProductionMasterPlan(InputDto input, List annual)
{
//来自定时任务的请求
if (input.year == 0 && input.month == 0)
{
input.year = DateTime.Now.Year;
input.month = DateTime.Now.Month;
}
//计算当前年月的N0,N+1,N+2
List planMons = GetPlanMonth(4);
List productionMasters = new List();
List pre3MonthPlan = _productionMasterPlan.GetListAsync(a => GetPlanMonth(-3).Contains(a.PlanMonth) && a.factory_id == input.factory_id).Result;
//N0,N+1,N+2月度发货计划
var annualProduction = new List();
foreach (var itemMonth in planMons)
{
var annualProductionMonth = _monthlyShipmentPlan.Select(x => itemMonth == x.PlanMonth && !x.IsDeleted && x.factory_id == input.factory_id).OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
if (annualProductionMonth != null && annualProductionMonth.Count > 0)
{
annualProduction.AddRange(annualProductionMonth);
}
else
{
var MaxVersion = _monthlyShipmentPlanHistory.Select(a => a.factory_id == input.factory_id && !a.IsDeleted).Max(b => b.VERSION);
if (!string.IsNullOrEmpty(MaxVersion))
{
var annualProductionMonthHistory = _monthlyShipmentPlanHistory.Select(x => itemMonth == x.PlanMonth && x.VERSION == MaxVersion && !x.IsDeleted && x.factory_id == input.factory_id).OrderByDescending(v => v.VERSION).ThenBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
if (annualProductionMonthHistory != null && annualProductionMonthHistory.Count > 0)
{
var returnlist = ObjectMapper.Map, List>(annualProductionMonthHistory);
annualProduction.AddRange(returnlist);
}
}
}
}
annualProduction = annualProduction.OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
var productionMasterPlan = _productionMasterPlan.GetListAsync(x => planMons.Contains(x.PlanMonth) && !x.IsDeleted && x.factory_id == input.factory_id).Result.OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
List locations = _invMaster.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).Distinct().ToList(), input);
_productExamineAppService.routingOps = _routingOpDetail.Select(p => p.Domain == input.factory_id.ToString()).ToList();
//主生产计划渠道合并,只考虑瑞奇库存不考虑国科海王库存
List shipList = new List();
foreach (var item in annualProduction)
{
if (shipList.Any(a => a.SAPItemNumber == item.SAPItemNumber && a.PlanMonth == item.PlanMonth))
{
shipList.Find(b => b.SAPItemNumber == item.SAPItemNumber && b.PlanMonth == item.PlanMonth).Qty += item.Qty;
}
else
{
shipList.Add(item);
}
}
shipList.OrderBy(a => a.PlanMonth);
var shipItemList = shipList.Select(a => a.SAPItemNumber).Distinct().ToList();
var ropPlan = _replenishmentROPWeekPlan.GetListAsync(x => shipItemList.Contains(x.number) && planMons.Contains(x.planmonth) && !x.IsDeleted && x.factory_id == input.factory_id).Result;
//var sapInvList = _SAPInv.Select(a => a.WERKS == input.factory_id.ToString() && shipItemList.Contains(a.MATNR) && (a.SOBKZ.ToUpper() == "O"));
foreach (var item in shipList)
{
var ropItem = ropPlan.Find(x => x.number == item.SAPItemNumber);
if (ropItem != null)
{
ProductionMasterPlan plan = new ProductionMasterPlan();
plan.Area = item.Area;
plan.ProdLine = item.ProdLine;
plan.ProdRange = item.ProdRange;
plan.WorkshopLine = annual.Find(a => a.PlanMonth == item.PlanMonth && a.SAPItemNumber == item.SAPItemNumber)?.WorkshopLine;
if (plan.WorkshopLine == null)
{
plan.WorkshopLine = "";
}
plan.ItemNumber = item.SAPItemNumber;
plan.Model = item.Model;
plan.Languages = item.Languages;
plan.PlanMonth = item.PlanMonth;
plan.PlanShipQty = item.Qty;
var preMonth = Convert.ToDateTime($"{plan.PlanMonth}-01").AddMonths(-1);
var preMonthStr = $"{preMonth.Year}-{preMonth.Month}";
var preMaster = productionMasters.Find(t => t.ItemNumber == plan.ItemNumber && t.PlanMonth == preMonthStr && t.factory_id == input.factory_id);
var preStock = pre3MonthPlan.Find(t => t.ItemNumber == plan.ItemNumber && t.PlanMonth == preMonthStr && t.factory_id == input.factory_id);
if (preMaster != null)
{
plan.PlanProductQty = Math.Ceiling(item.Qty -
(
preMaster.PlanStockQty -
ropItem.security_stock.GetValueOrDefault()
));//发货计划-(上个月期末库存作为本月期初库存-安全库存)
if (plan.PlanProductQty < 0)
{
plan.PlanProductQty = 0;
}
plan.PlanStockQty = Math.Ceiling(preMaster.PlanStockQty + plan.PlanProductQty - item.Qty);
}
else if (preStock != null)
{
plan.PlanProductQty = Math.Ceiling(item.Qty -
(
preStock.PlanStockQty -
ropItem.security_stock.GetValueOrDefault()
));//发货计划-(上个月期末库存作为本月期初库存-安全库存)
if (plan.PlanProductQty < 0)
{
plan.PlanProductQty = 0;
}
plan.PlanStockQty = Math.Ceiling(preStock.PlanStockQty + plan.PlanProductQty - item.Qty);
}
else
{
decimal itemStockQty = 0;
if (itemStock.Any(a => a.ItemNumber == item.SAPItemNumber))
{
itemStockQty = itemStock.Find(a => a.ItemNumber == item.SAPItemNumber).Qty;
}
decimal itemInProdcutQty = 0;
if (InProdcutQty.Any(a => a.ItemNumber == item.SAPItemNumber))
{
itemInProdcutQty = InProdcutQty.Find(a => a.ItemNumber == item.SAPItemNumber).Qty;
}
plan.PlanProductQty = item.Qty -
(itemStockQty + itemInProdcutQty - ropItem.security_stock.GetValueOrDefault()
);//发货计划-(库存+在制-安全库存)
if (plan.PlanProductQty < 0)
plan.PlanProductQty = 0;
plan.PlanStockQty = Math.Ceiling(
itemStock.Find(a => a.ItemNumber == item.SAPItemNumber).Qty +
InProdcutQty.Find(a => a.ItemNumber == item.SAPItemNumber).Qty +
plan.PlanProductQty - item.Qty);
}
if (locations.FirstOrDefault(a => a.ItemNum == item.SAPItemNumber && a.Location == "8001") != null)
{
plan.Inventory = locations.Where(a => a.ItemNum == item.SAPItemNumber && a.Location == "8001").Sum(c => c.AvailStatusQty.GetValueOrDefault() + c.Assay.GetValueOrDefault());
}
else
{
plan.Inventory = 0;
}
if (locations.FirstOrDefault(a => a.ItemNum == item.SAPItemNumber && a.Location == "8000") != null)
{
plan.Inventory1 = locations.Where(a => a.ItemNum == item.SAPItemNumber && a.Location == "8000").Sum(c => c.AvailStatusQty.GetValueOrDefault() + c.Assay.GetValueOrDefault());
}
else
{
plan.Inventory1 = 0;
}
if (locations.FirstOrDefault(a => a.ItemNum == item.SAPItemNumber && a.Location == "5008") != null)
{
plan.Inventory2 = locations.Where(a => a.ItemNum == item.SAPItemNumber && a.Location == "5008").Sum(c => c.AvailStatusQty.GetValueOrDefault() + c.Assay.GetValueOrDefault());
}
else
{
plan.Inventory2 = 0;
}
decimal InSterilizationQty = 0.00m;
//if (sapInvList.Count > 0 && sapInvList.Any(a => a.MATNR == item.SAPItemNumber && a.SOBKZ.ToUpper() == "O"))
//{
// InSterilizationQty = sapInvList.Where(a => a.MATNR == item.SAPItemNumber && a.SOBKZ.ToUpper() == "O").Sum(x => Convert.ToDecimal(x.LABST) + Convert.ToDecimal(x.INSME) + Convert.ToDecimal(x.SPEME));
//}
plan.DuringSterilization = InSterilizationQty;
plan.InProduction = InProdcutQty.Find(a => a.ItemNumber == item.SAPItemNumber).Qty;
if (pre3MonthPlan.Where(a => a.ItemNumber == item.SAPItemNumber).Count() > 0)
{
plan.EconomicLotSize = pre3MonthPlan.Where(a => a.ItemNumber == item.SAPItemNumber).Average(a => a.PlanProductQty);
}
else
{
plan.EconomicLotSize = plan.PlanProductQty;
}
plan.tenant_id = input.tenant_id;
plan.factory_id = input.factory_id;
plan.company_id = input.company_id;
plan.org_id = input.org_id;
plan.create_time = DateTime.Now;
plan.OrderNum = item.OrderNum;
ProdExamineParamDto prodExamine = new ProdExamineParamDto()
{
ItemNum = plan.ItemNumber,
PlanStart = DateTime.Today,
QtyOrd = plan.PlanProductQty,
Domain = input.factory_id.ToString()
};
int make_time = _productExamineAppService.ProductTime(prodExamine);
plan.ProductionTime = make_time;
productionMasters.Add(plan);
}
else
{
new NLogHelper("AnnualProductionOutlineAppService").WriteLog("SaveProductionMasterPlan", "【" + input.year + "年" + "】主计划找不到发货计划物料:" + item.SAPItemNumber, _currentTenant.Id.ToString());
}
}
//保存数据
using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
{
try
{
var planList = productionMasters.Select(a => a.PlanMonth).ToList();
await _productionMasterPlan.DeleteAsync(a => planList.Contains(a.PlanMonth) && a.factory_id == input.factory_id);
await _businessDbContext.BulkInsertAsync(productionMasters);
await unitOfWork.CompleteAsync();
}
catch (Exception e)
{
unitOfWork.Dispose();
new NLogHelper("AnnualProductionOutlineAppService").WriteLog("SaveProductionMasterPlan", "【" + input.year + "年" + "】主计划生成失败:" + e.Message, _currentTenant.Id.ToString());
return "NO|" + e.Message;
};
}
return "OK";
}
///
/// 获取物料在制数量
///
///
///
///
public List GetProdcutQty(List itemNumbers, InputDto input)
{
List itemQty = new List();
List workOrdMasters = _workOrdMaster.Select(x => x.Domain == param.factoryId.ToString() && string.IsNullOrEmpty(x.Typed) == true && !string.IsNullOrEmpty(x.Status) && x.Status.ToUpper() != "C" && x.Status.ToUpper() != "P" && x.IsActive).ToList();
var workOrds = workOrdMasters.GroupBy(x => x.WorkOrd).ToList();
Dictionary dictInProduction = new Dictionary();
//按照工单循环
foreach (var item in workOrds)
{
var works = workOrdMasters.Where(x => x.WorkOrd == item.Key).ToList().FirstOrDefault();
if (dictInProduction.ContainsKey(works.ItemNum))
{
dictInProduction[works.ItemNum] += works.QtyOrded - works.QtyCompleted;
}
else
{
dictInProduction.Add(works.ItemNum, works.QtyOrded - works.QtyCompleted);
}
}
itemNumbers.ForEach(a =>
{
EOPDto eOP = new EOPDto();
eOP.ItemNumber = a;
eOP.Qty = 0;
if (dictInProduction.ContainsKey(a))
eOP.Qty = dictInProduction[a];
itemQty.Add(eOP);
});
return itemQty;
}
///
/// 获取物料在制数量
///
///
///
///
public List GetInProdcutQty(List itemNumbers, InputDto input)
{
List itemQty = new List();
DateTime startYear = new DateTime(DateTime.Now.AddYears(-1).Year, 1, 1);
DateTime endYear = new DateTime(DateTime.Now.Year, 12, 31);
List workOrdRoutings = _workOrdRouting.Select(x => x.IsActive && x.QtyComplete > 0 && x.Domain == input.factory_id.ToString()).Where(p => p.DueDate >= startYear && p.DueDate <= endYear).ToList();
decimal? InProductionQty = 0.00m;
var workOrds = workOrdRoutings.GroupBy(x => x.WorkOrd).ToList();
Dictionary dictInProduction = new Dictionary();
//按照工单循环
//某工单10-90工序 Max(10-80工序QtyComplete)-90工序QtyComplete =在制数量
foreach (var item in workOrds)
{
var workOrdRoutingList = workOrdRoutings.Where(x => x.WorkOrd == item.Key).OrderByDescending(o => o.OP).ToList();
//找出最大工序
var MaxOp = workOrdRoutingList.FirstOrDefault();
//查询出其他工序最大值
var MaxQtyComplete = workOrdRoutingList.Where(x => x.RecID != MaxOp.RecID).ToList().Max(o => o.QtyComplete);
InProductionQty += MaxQtyComplete - MaxOp.QtyComplete;
if (dictInProduction.ContainsKey(MaxOp.ItemNum))
{
dictInProduction[MaxOp.ItemNum] += InProductionQty.Value;
}
else
{
dictInProduction.Add(MaxOp.ItemNum, InProductionQty.Value);
}
}
itemNumbers.ForEach(a =>
{
EOPDto eOP = new EOPDto();
eOP.ItemNumber = a;
eOP.Qty = 0;
if (dictInProduction.ContainsKey(a))
eOP.Qty = dictInProduction[a];
itemQty.Add(eOP);
});
return itemQty;
}
///
/// 更新年度生产大纲
///
///
///
///
public async Task DemandAnalysis(InputDto input)
{
string productResult = await SaveAnnualProductionOutline(input);
if (productResult != "OK")
return productResult;
return "OK|刷新成功!";
}
///
/// 调整成品ROP和最高库存水位
///
///
///
public async Task CalcROP(InputDto input)
{
//var IsActived = _AccountValidityAppService.IsActived();
//if (!IsActived)
//{
// return "此账号已限制访问";
//}
//来自定时任务的请求
if (input.year == 0 && input.month == 0)
{
input.year = DateTime.Now.Year;
input.month = DateTime.Now.Month;
}
//1.获取补货模型全局参数
ReplenishmentDto replenishmentDto = GetROPParam(input.factory_id.ToString());
List addList = new List();
List updateList = new List();//更新上一个月的实际出库数量
//获取存货周转率设置
var turnOverlist = _ReplenishmentTurnOverSet.GetListAsync(a => a.factory_id == input.factory_id).Result;
//获取补货模型前H周期和未来F个周期的数据
List planMonthList = new List();
for (int j = -replenishmentDto.HistoryOutStockMonth; j < replenishmentDto.SaleFcstMonth; j++)
{
string itemMonth = $"{DateTime.Now.AddMonths(j).Year}-{DateTime.Now.AddMonths(j).Month.ToString("00")}";
planMonthList.Add(itemMonth);
}
var planList = new List();
foreach (var itemMonth in planMonthList)
{
var annualProductionMonth = _monthlyShipmentPlan.Select(x => itemMonth == x.PlanMonth && !x.IsDeleted && x.factory_id == input.factory_id).OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
if (annualProductionMonth != null && annualProductionMonth.Count > 0)
{
planList.AddRange(annualProductionMonth);
}
else
{
var MaxVersion = _monthlyShipmentPlanHistory.Select(a => a.factory_id == input.factory_id && !a.IsDeleted).Max(b => b.VERSION);
if (!string.IsNullOrEmpty(MaxVersion))
{
var annualProductionMonthHistory = _monthlyShipmentPlanHistory.Select(x => itemMonth == x.PlanMonth && x.VERSION == MaxVersion && !x.IsDeleted && x.factory_id == input.factory_id).OrderByDescending(v => v.VERSION).ThenBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
if (annualProductionMonthHistory != null && annualProductionMonthHistory.Count > 0)
{
var returnlist = ObjectMapper.Map, List>(annualProductionMonthHistory);
planList.AddRange(returnlist);
}
}
}
}
planList = planList.OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
//获取BOM用于分解到原材料
var boms = _ic_bom.GetListAsync(a => planList.Select(p => p.SAPItemNumber).Distinct().ToList().Contains(a.item_number) && a.factory_id == input.factory_id).Result;
var planItemList = planList.Select(a => a.SAPItemNumber).Distinct().ToList();
var bomItemList = boms.Select(a => a.item_number).Distinct().ToList();
var expectedList = planItemList.Except(bomItemList).ToList();
if (expectedList.Count > 0)
{
throw new NotImplementedException("月度发货计划物料" + string.Join(",", expectedList) + "没有维护BOM!");
}
var pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
List autoCreates = new List();
boms.ForEach(p =>
{
if (!pretreatments.Where(s => s.sourceid == p.mysql_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 mesItemList = _itemMaster.Select(a => pretreatments.Select(p => p.item_number).Contains(a.ItemNum) && a.Domain == input.factory_id.ToString() && a.IsActive);
var itemProductList = _mysql_ic_item.GetListAsync(a => pretreatments.Select(p => p.item_number).Contains(a.number) && !a.IsDeleted && a.factory_id == input.factory_id).Result;
var itemList = itemProductList.Select(a => a.number).ToList();
var srm_purchaseList = _srmPurchase.GetListAsync(a => pretreatments.Select(p => p.item_number).Contains(a.number) && !a.IsDeleted).Result;
var ropModelList = _replenishmentROPWeekPlan.GetListAsync(a => itemList.Contains(a.number) && planMonthList.Contains(a.planmonth) && a.factory_id == input.factory_id).Result;
//获取成品库存、灭菌库存、在制库存(会从SAP同步的库存表更新到LocationDetail、ic_item表中)
var locations = _invMaster.Select(p => p.Domain == input.factory_id.ToString() && itemList.Contains(p.ItemNum) && p.IsActive);
//国科海王只有成品
//var DMSItemList = _DMS_IN_ITEMMAPPING.Select(a => planList.Select(p => p.SAPItemNumber).ToList().Contains(a.CfnERPCode));
//var gkhwStock = _DMS_IN_LOCDETAIL.Select(a => (a.DealerCode == "RQ000005" || a.DealerCode == "RQ000002"));
decimal? InProductionQty = 0.00m;
//获取在制数量 获取工单数取每年4月到12月底的工单
DateTime startYear = new DateTime(DateTime.Now.Year, 1, 1);
DateTime endYear = new DateTime(DateTime.Now.Year, 12, 31);
List workOrdRoutings = _workOrdRouting.Select(x => x.IsActive && x.QtyComplete > 0 && x.Domain == input.factory_id.ToString()).Where(p => p.DueDate >= startYear && p.DueDate <= endYear).ToList();
var workOrds = workOrdRoutings.GroupBy(x => x.WorkOrd).ToList();
Dictionary dictItemStock = new Dictionary();
//按照工单循环
//某工单10-90工序 Max(10-80工序QtyComplete)-90工序QtyComplete =在制数量
foreach (var item in workOrds)
{
var workOrdRoutingList = workOrdRoutings.Where(x => x.WorkOrd == item.Key).OrderByDescending(o => o.OP).ToList();
//找出最大工序
var MaxOp = workOrdRoutingList.FirstOrDefault();
//查询出其他工序最大值
var MaxQtyComplete = workOrdRoutingList.Where(x => x.RecID != MaxOp.RecID).ToList().Max(o => o.QtyComplete);
InProductionQty += MaxQtyComplete - MaxOp.QtyComplete;
if (dictItemStock.ContainsKey(MaxOp.ItemNum))
{
dictItemStock[MaxOp.ItemNum] += InProductionQty.Value;
}
else
{
dictItemStock.Add(MaxOp.ItemNum, InProductionQty.Value);
}
}
foreach (var item in locations)
{
//库存合计 + 在制 + 灭菌中 (InvMaster没有过滤灭菌中状态可能已经算在可用库存中了)
//5008成品线边库,8001成品合格库,8000成品待检
if (item.Location == "5008" || item.Location == "5009" || item.Location == "5010" || item.Location == "8000" || item.Location == "8001" || item.Location == "8002" || item.Location == "8003" || item.Location == "8004" || item.Location == "8005")
{
if (dictItemStock.ContainsKey(item.ItemNum))
{
dictItemStock[item.ItemNum] += (item.AvailStatusQty.GetValueOrDefault() + item.Assay.GetValueOrDefault());
}
else
{
dictItemStock.Add(item.ItemNum, (item.AvailStatusQty.GetValueOrDefault() + item.Assay.GetValueOrDefault()));
}
}
}
foreach (var item in itemList)
{
if (!dictItemStock.ContainsKey(item))
{
dictItemStock.Add(item, 0);
}
}
//取过去6个月成品发货出库记录
var dateBegin = DateTime.Now.AddMonths(-6);
var datePreBegin = DateTime.Now.AddMonths(-1);
var dateEnd = DateTime.Now;
//获取瑞奇发往国科海王的记录
var gkhwList = _ASNBOLShipperMaster.Select(a => a.Domain == input.factory_id.ToString() && (a.SoldTo == "10002080" || a.SoldTo == "10001981"));
var recidList = gkhwList.Select(a => Convert.ToInt64(a.RecID)).ToList();
//获取瑞奇发货记录
var shipList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.RealQty > 0
&& itemList.Contains(a.ContainerItem) && a.ShipDate >= dateBegin && a.ShipDate <= dateEnd && !recidList.Contains(a.ASNBOLShipperRecID));//瑞奇只算瑞奇排除国科海王
//获取瑞奇上月发货记录
var shipMList = shipList.Where(a => a.ShipDate >= datePreBegin && a.ShipDate <= dateEnd).ToList();//瑞奇只算瑞奇排除国科海王
////获取国科海王发货记录
//var gkItemList = planList.Where(p => p.DistributionChannel == "国科").Select(p => p.SAPItemNumber).ToList();
//var DMSItemListGK = _DMS_IN_ITEMMAPPING.Select(a => gkItemList.Contains(a.CfnERPCode));
//var shipListGK = _DMS_IN_SHIPPINGDETAIL.Select(a =>
//DMSItemListGK.Select(g => g.CfnCode).Contains(a.UPN) && a.ParentDealerCode == "RQ000005" && a.ShipmentDate >= DateOnly.FromDateTime(dateBegin) && a.ShipmentDate <= DateOnly.FromDateTime(dateEnd));//国科
//var hwItemList = planList.Where(p => p.DistributionChannel == "海王").Select(p => p.SAPItemNumber).ToList();
//var DMSItemListHW = _DMS_IN_ITEMMAPPING.Select(a => hwItemList.Contains(a.CfnERPCode));
//var shipListHW = _DMS_IN_SHIPPINGDETAIL.Select(a =>
//DMSItemListHW.Select(g => g.CfnCode).Contains(a.UPN) && a.ParentDealerCode == "RQ000002" && a.ShipmentDate >= DateOnly.FromDateTime(dateBegin) && a.ShipmentDate <= DateOnly.FromDateTime(dateEnd));//海王
//领料出库记录
var pickbilllist = _invTransHist.Select(a => a.Domain == input.factory_id.ToString() && a.TransType == "iss-wo" && a.IsActive && a.CreateTime >= dateBegin && itemList.Contains(a.ItemNum));
//出库记录
var invTransHists = _invTransHist.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.CreateTime >= dateBegin && itemList.Contains(a.ItemNum) && a.QtyChange < 0);
//对账单,取对账日期最新的数据
string sqldzd = @"SELECT ItemNum,1.0*NETPR/PEINH * (1+kbetr) as NETPR FROM (SELECT MATNR AS ItemNum,NETPR,PEINH,kbetr,ROW_NUMBER() OVER (PARTITION BY MATNR ORDER BY BUDAT DESC) AS rn FROM SupplierStatement ) as SupplierStatement WHERE rn = 1";
var supplierStatementDtos = _businessDbContext.SupplierStatementDto.FromSqlRaw(sqldzd).ToList();
List replenishmentROPWeekPlanDtos = GetRopAmount(itemList.Distinct().ToList(), supplierStatementDtos, invTransHists, input);
// var gkCNCCodeList = DMSItemListGK.Select(g => g.CfnCode).ToList();
// var dateOnlyCurrent = DateOnly.FromDateTime(datePreBegin);
// var dateOnlyNow = DateOnly.FromDateTime(dateEnd);
// var shipMListGK = _DMS_IN_SHIPPINGDETAIL.Select(a =>
//gkCNCCodeList.Contains(a.UPN) && a.ParentDealerCode == "RQ000005" && a.ShipmentDate >= dateOnlyCurrent && a.ShipmentDate <= dateOnlyNow);//国科
// var hwCNCCodeList = DMSItemListHW.Select(g => g.CfnCode).ToList();
// var shipMListHW = _DMS_IN_SHIPPINGDETAIL.Select(a =>
//hwCNCCodeList.Contains(a.UPN) && a.ParentDealerCode == "RQ000002" && a.ShipmentDate >= dateOnlyCurrent && a.ShipmentDate <= dateOnlyNow);//海王
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();
//var itemGroupGK = shipListGK.GroupBy(p => p.UPN)
// .Select(p => new ASNBOLShipperDetail
// {
// QtyToShip = p.Sum(a => a.Qty),
// ContainerItem = p.Key
// }).ToList();
//var itemMGroupGK = shipMListGK.GroupBy(p => p.UPN)
// .Select(p => new ASNBOLShipperDetail
// {
// QtyToShip = p.Sum(a => a.Qty),
// ContainerItem = p.Key
// }).ToList();
//var itemGroupHW = shipListHW.GroupBy(p => p.UPN)
// .Select(p => new ASNBOLShipperDetail
// {
// QtyToShip = p.Sum(a => a.Qty),
// ContainerItem = p.Key
// }).ToList();
//var itemMGroupHW = shipMListHW.GroupBy(p => p.UPN)
// .Select(p => new ASNBOLShipperDetail
// {
// QtyToShip = p.Sum(a => a.Qty),
// ContainerItem = p.Key
// }).ToList();
var mathtool = new MathNet.Numerics.Distributions.Normal();
//更新上个月计划发货数据为实际出库数据(先算成品,原材料后面单独计算)
Dictionary preMonthRQQty = new Dictionary();
ropModelList?.Where(r => r.year == DateTime.Now.AddMonths(-1).Year && r.month == DateTime.Now.AddMonths(-1).Month).ToList()?.ForEach
(m =>
{
//只更新成品
if (planList.Any(a => a.SAPItemNumber == m.number))
{
if (m.distributionchannel == "瑞奇")
{
if (!preMonthRQQty.ContainsKey(m.number))
{
preMonthRQQty.Add(m.number, m.plan_out_qty);
}
//成品算销售出库数量
if (itemGroup.Any(a => a.ContainerItem == m.number))
{
m.plan_out_qty = itemGroup.Find(a => a.ContainerItem == m.number)?.QtyToShip;
updateList.Add(m);
preMonthRQQty[m.number] = m.plan_out_qty;
}
}
//else if (m.distributionchannel == "国科")
//{
// if (itemGroupGK.Any(a => a.ContainerItem == m.number))
// {
// m.plan_out_qty = itemGroupGK.Find(a => a.ContainerItem == m.number)?.QtyToShip;
// updateList.Add(m);
// }
//}
//else if (m.distributionchannel == "海王")
//{
// if (itemGroupHW.Any(a => a.ContainerItem == m.number))
// {
// m.plan_out_qty = itemGroupHW.Find(a => a.ContainerItem == m.number)?.QtyToShip;
// updateList.Add(m);
// }
//}
}
});
//更新瑞奇原材料上个月出库次数(按照BOM展开合计汇总)
string planPreMonth = $"{DateTime.Now.AddMonths(-1).Year}-{DateTime.Now.AddMonths(-1).Month.ToString("00")}";
List subItem = new List();
planList.Where(a => a.DistributionChannel == "瑞奇" && a.PlanMonth == planPreMonth).ToList().ForEach(a =>
{
var planBOM = boms.Find(b => b.item_number == a.SAPItemNumber);
if (planBOM == null)
{
new NLogHelper("CalcROP").WriteLog("CalcROP", "CalcROP数据错误:" + a.SAPItemNumber + "不在BOM里", _currentTenant.Id.ToString());
}
else
{
var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList();
var returnlist = ObjectMapper.Map, List>(pretreament);
returnlist = returnlist.OrderBy(s => s.num_order).ToList();
var level1Dto = returnlist[0];
if (preMonthRQQty.ContainsKey(a.SAPItemNumber))
{
level1Dto.needCount = preMonthRQQty[a.SAPItemNumber].GetValueOrDefault();
}
else
{
level1Dto.needCount = a.Qty;
}
CaclMaterialShortage(returnlist);
foreach (var item in returnlist)
{
if (item.item_number != a.SAPItemNumber)
{
if (subItem.Any(s => s.ItemNumber == item.item_number && s.PlanMonth == planPreMonth))
{
subItem.Find(s => s.ItemNumber == item.item_number && s.PlanMonth == planPreMonth).Qty += item.needCount;
}
else
{
subItem.Add(new ReplenishmentSubItemDto { ItemNumber = item.item_number, Qty = item.needCount, PlanMonth = planPreMonth });
}
}
}
}
});
ropModelList?.Where(r => r.year == DateTime.Now.AddMonths(-1).Year && r.month == DateTime.Now.AddMonths(-1).Month && r.distributionchannel == "瑞奇").ToList()?.ForEach
(m =>
{
//只更新原材料
if (!planList.Any(a => a.SAPItemNumber == m.number) && subItem.Any(s => s.ItemNumber == m.number && s.PlanMonth == planPreMonth))
{
m.plan_out_qty = subItem.Find(s => s.ItemNumber == m.number && s.PlanMonth == planPreMonth).Qty;
updateList.Add(m);
}
});
var RQShipPlanList = planList.FindAll(s => s.DistributionChannel == "瑞奇");
List subItemRQList = CalcMonthPlanSubItem(RQShipPlanList, boms, pretreatments);
for (int j = 0; j < replenishmentDto.SaleFcstMonth; j++)
{
string itemMonth = $"{DateTime.Now.AddMonths(j).Year}-{DateTime.Now.AddMonths(j).Month.ToString("00")}";
//先计算成品
planList?.Where(s => s.PlanMonth == itemMonth).ToList()?.ForEach(a =>
{
var icItem = itemProductList.Find(p => p.number == a.SAPItemNumber);
if (icItem != null)
{
bool isExist = ropModelList.Find(r => r.planmonth == itemMonth && r.number == a.SAPItemNumber && r.distributionchannel == a.DistributionChannel) == null ? false : true;
var rop = new ReplenishmentROPWeekPlan();
if (isExist)
{
rop = ropModelList.Find(r => r.planmonth == itemMonth && r.number == a.SAPItemNumber && r.distributionchannel == a.DistributionChannel);
}
rop.number = a.SAPItemNumber;
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.distributionchannel = a.DistributionChannel;
rop.lifecycle = a.LifeCycle;
rop.area = a.Area;
rop.plan_out_qty = Math.Ceiling(a.Qty);
if (planList.Where(i => i.SAPItemNumber == a.SAPItemNumber && i.DistributionChannel == a.DistributionChannel).Count() > 0)
{
rop.monthl_avg_demand = planList.Where(i => i.SAPItemNumber == a.SAPItemNumber && i.DistributionChannel == a.DistributionChannel).Average(a => a.Qty);
var nums = planList.Where(i => i.SAPItemNumber == a.SAPItemNumber && i.DistributionChannel == a.DistributionChannel).Select(a => a.Qty);
if (nums.Count() <= 1)
{
rop.monthl_avg_demand_variance = 0;
}
else
{
rop.monthl_avg_demand_variance = Math.Ceiling(Convert.ToDecimal(Math.Sqrt(nums.Sum(x => Math.Pow(Convert.ToDouble(x) - Convert.ToDouble(rop.monthl_avg_demand), 2)) / (nums.Count() - 1))));
}
}
else
{
rop.monthl_avg_demand = 0;
rop.monthl_avg_demand_variance = 0;
}
//计算月均出库
int MonthCount = 0;
decimal SumOutQty = 0;
for (int k = -1 * replenishmentDto.HistoryOutStockMonth; k < replenishmentDto.SaleFcstMonth; k++)
{
string itemMonth = $"{DateTime.Now.AddMonths(k).Year}-{DateTime.Now.AddMonths(k).Month.ToString("00")}";
if (k < 0)
{
if (ropModelList.Find(z => z.planmonth == itemMonth && z.number == a.SAPItemNumber && z.distributionchannel == a.DistributionChannel) != null)
{
SumOutQty += ropModelList.Find(z => z.planmonth == itemMonth && z.number == a.SAPItemNumber && z.distributionchannel == a.DistributionChannel).plan_out_qty.GetValueOrDefault();
MonthCount++;
}
}
else
{
if (planList.Find(z => z.PlanMonth == itemMonth && z.SAPItemNumber == a.SAPItemNumber && z.DistributionChannel == a.DistributionChannel) != null)
{
SumOutQty += planList.Find(z => z.PlanMonth == itemMonth && z.SAPItemNumber == a.SAPItemNumber && z.DistributionChannel == a.DistributionChannel).Qty;
MonthCount++;
}
}
}
if (MonthCount == 0)
{
rop.monthl_avg_outstock = 0;
}
else
{
rop.monthl_avg_outstock = Math.Ceiling(SumOutQty / MonthCount);
}
rop.year = DateTime.Now.AddMonths(j).Year;
rop.month = DateTime.Now.AddMonths(j).Month;
rop.planmonth = $"{DateTime.Now.AddMonths(j).Year}-{DateTime.Now.AddMonths(j).Month.ToString("00")}";
//供应提前期,成品取物料主数据维护的,原材料从货源清单取取不到取物料维护的
if (icItem.erp_cls == 1)
{
rop.supply_leadtime = icItem.PurLT;//默认
}
else
{
if (srm_purchaseList.Find(s => s.number == rop.number) != null)
{
rop.supply_leadtime = srm_purchaseList.Find(s => s.number == rop.number).lead_time;
}
else
{
rop.supply_leadtime = icItem.PurLT;//默认
}
}
if (rop.supply_leadtime == 0)
rop.supply_leadtime = 22;//默认
//存货周转率先取规格型号,没有再取产品系列,没有取产品线,再没有取物料配置的(主要是原材料),再没有就默认
if (turnOverlist.Find(t => t.Model == rop.model) != null)
{
rop.stock_turnover = turnOverlist.Find(t => t.Model == rop.model).RQTurnOver;
}
else if (turnOverlist.Find(t => t.ProdRange == a.ProdRange) != null)
{
rop.stock_turnover = turnOverlist.Find(t => t.ProdRange == a.ProdRange).RQTurnOver;
}
else if (turnOverlist.Find(t => t.ProdLine == a.ProdLine) != null)
{
rop.stock_turnover = turnOverlist.Find(t => t.ProdLine == a.ProdLine).RQTurnOver;
}
else if (mesItemList.Find(s => s.ItemNum == a.SAPItemNumber) != null)
{
rop.stock_turnover = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber).StockTurnOver;
}
else
{
rop.stock_turnover = 4;
}
CalcFMRAndABC(rop, replenishmentDto, shipList, pickbilllist, replenishmentROPWeekPlanDtos, 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.AddMonths(j).Year, DateTime.Now.AddMonths(months: j).Month));
rop.rop_computed = rop.security_stock + rop.eop;
rop.max_stock_level = rop.monthl_avg_outstock * (12 / rop.stock_turnover);
//瑞奇是ROP和最高库存值两者之间取较小的值,平台是取较大的值。
if (a.DistributionChannel != "瑞奇")
{
rop.rop_revised = Math.Max(rop.rop_computed.Value, rop.max_stock_level.Value);
}
else
{
rop.rop_revised = Math.Min(rop.rop_computed.Value, rop.max_stock_level.Value);
}
//存在上一个月补货
if (updateList.Find(r => r.number == a.SAPItemNumber && r.distributionchannel == a.DistributionChannel && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}") != null)
{
var avaItem = updateList.Find(r => r.number == a.SAPItemNumber && r.distributionchannel == a.DistributionChannel && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}");
rop.avaStockQty = Math.Ceiling(avaItem.avaStockQty.GetValueOrDefault() + avaItem.montheop1.GetValueOrDefault() + avaItem.montheop2.GetValueOrDefault() - a.Qty);
}
else if (addList.Find(r => r.number == a.SAPItemNumber && r.distributionchannel == a.DistributionChannel && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}") != null)
{
var avaItem = addList.Find(r => r.number == a.SAPItemNumber && r.distributionchannel == a.DistributionChannel && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}");
rop.avaStockQty = Math.Ceiling(avaItem.avaStockQty.GetValueOrDefault() + avaItem.montheop1.GetValueOrDefault() + avaItem.montheop2.GetValueOrDefault() - a.Qty);
}
else
{
//取实际库存
//if (a.DistributionChannel == "海王")
//{
// if (DMSItemList.Find(d => d.CfnERPCode == rop.number) != null)
// {
// var itemDMS = gkhwStock.Where(o => o.UPN == DMSItemList.Find(d => d.CfnERPCode == rop.number).CfnCode && o.DealerCode == "RQ000002").ToList();
// if (itemDMS.Count > 0)
// {
// var maxDate = itemDMS.OrderByDescending(i => i.InventoryDate).First();
// rop.avaStockQty = itemDMS.Where(i => i.InventoryDate == maxDate.InventoryDate).Sum(q => q.Qty);
// }
// }
//}
//else if (a.DistributionChannel == "国科")
//{
// if (DMSItemList.Find(d => d.CfnERPCode == rop.number) != null)
// {
// var itemDMS = gkhwStock.Where(o => o.UPN == DMSItemList.Find(d => d.CfnERPCode == rop.number).CfnCode && o.DealerCode == "RQ000005").ToList();
// if (itemDMS.Count > 0)
// {
// var maxDate = itemDMS.OrderByDescending(i => i.InventoryDate).First();
// rop.avaStockQty = itemDMS.Where(i => i.InventoryDate == maxDate.InventoryDate).Sum(q => q.Qty);
// }
// }
//}
//else
//{
rop.avaStockQty = dictItemStock[a.SAPItemNumber];
//}
}
rop.montheop1 = rop.rop_computed > rop.avaStockQty.GetValueOrDefault() ? rop.eop : 0;
rop.montheop2 = rop.security_stock > rop.avaStockQty.GetValueOrDefault() ? rop.eop : 0;
rop.ProdLine = a.ProdLine;
rop.ProdRange = a.ProdRange;
rop.Languages = a.Languages;
rop.tenant_id = input.tenant_id;
rop.company_id = input.company_id;
rop.factory_id = input.factory_id;
rop.create_time = DateTime.Now;
rop.org_id = input.org_id;
if (isExist)
{
updateList.Add(rop);
}
else
{
addList.Add(rop);
}
}
});
//计算原材料
List subItemRQ = subItemRQList.FindAll(a => a.PlanMonth == itemMonth);
foreach (var d in subItemRQ)
{
var icItem = itemProductList.Find(s => s.number == d.ItemNumber);
if (icItem != null && !planList.Select(r => r.SAPItemNumber).ToList().Contains(d.ItemNumber))
{
bool isExist = ropModelList.Find(r => r.planmonth == itemMonth && r.number == d.ItemNumber && r.distributionchannel == "瑞奇") == null ? false : true;
var rop = new ReplenishmentROPWeekPlan();
if (isExist)
{
rop = ropModelList.Find(r => r.planmonth == itemMonth && r.number == d.ItemNumber && r.distributionchannel == "瑞奇");
}
rop.number = d.ItemNumber;
rop.name = icItem.name;
rop.model = icItem.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.distributionchannel = "";
rop.lifecycle = "";
rop.area = "";
rop.plan_out_qty = Math.Ceiling(d.Qty);
//月均需求用几个月的发货计划按照bom展开合计计算
CalcSubItem(subItemRQList, rop, replenishmentDto, d.ItemNumber);
//计算原材料月均出库
rop.monthl_avg_outstock = Math.Ceiling(pickbilllist.Where(z => z.ItemNum == rop.number).Sum(q => q.QtyChange.GetValueOrDefault() * -1) / 6);
rop.year = DateTime.Now.AddMonths(j).Year;
rop.month = DateTime.Now.AddMonths(j).Month;
rop.planmonth = $"{DateTime.Now.AddMonths(j).Year}-{DateTime.Now.AddMonths(j).Month.ToString("00")}";
//供应提前期,成品取物料主数据维护的,原材料从货源清单取取不到取物料维护的
if (icItem.erp_cls == 1)
{
rop.supply_leadtime = icItem.PurLT;//默认
}
else
{
if (srm_purchaseList.Find(s => s.number == rop.number) != null)
{
rop.supply_leadtime = srm_purchaseList.Find(s => s.number == rop.number).lead_time;
}
else
{
rop.supply_leadtime = icItem.PurLT;//默认
}
}
if (rop.supply_leadtime == 0)
rop.supply_leadtime = 22;//默认
//原材料周转率取物料
if (mesItemList.Find(s => s.ItemNum == rop.number) != null)
{
rop.stock_turnover = mesItemList.Find(s => s.ItemNum == rop.number).StockTurnOver;
if (rop.stock_turnover == 0)
{
rop.stock_turnover = 4;
}
}
else
{
rop.stock_turnover = 4;
}
if (rop.stock_turnover == 0)
rop.stock_turnover = 4;
CalcFMRAndABC(rop, replenishmentDto, shipList, pickbilllist, replenishmentROPWeekPlanDtos, 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.AddMonths(j).Year, DateTime.Now.AddMonths(j).Month));
rop.rop_computed = rop.security_stock + rop.eop;
rop.max_stock_level = rop.monthl_avg_outstock * (12 / rop.stock_turnover);
//瑞奇是ROP和最高库存值两者之间取较小的值,平台是取较大的值。
//瑞奇是ROP和最高库存值两者之间取较小的值,平台是取较大的值。
rop.rop_revised = Math.Min(rop.rop_computed.Value, rop.max_stock_level.Value);
//存在上一个月补货
if (updateList.Find(r => r.number == d.ItemNumber && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}") != null)
{
var avaItem = updateList.Find(r => r.number == d.ItemNumber && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}");
rop.avaStockQty = Math.Ceiling(avaItem.avaStockQty.GetValueOrDefault() + avaItem.montheop1.GetValueOrDefault() + avaItem.montheop2.GetValueOrDefault() - d.Qty);
}
else if (addList.Find(r => r.number == d.ItemNumber && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}") != null)
{
var avaItem = addList.Find(r => r.number == d.ItemNumber && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}");
rop.avaStockQty = Math.Ceiling(avaItem.avaStockQty.GetValueOrDefault() + avaItem.montheop1.GetValueOrDefault() + avaItem.montheop2.GetValueOrDefault() - d.Qty);
}
else
{
//取实际库存
//1开始的库位为原料仓
rop.avaStockQty = locations.Where(a => a.ItemNum == rop.number && a.Location.StartsWith("1")).Sum(a => a.AvailStatusQty.GetValueOrDefault() + a.Assay.GetValueOrDefault());
}
rop.montheop1 = rop.rop_computed > rop.avaStockQty.GetValueOrDefault() ? rop.eop : 0;
rop.montheop2 = rop.security_stock > rop.avaStockQty.GetValueOrDefault() ? rop.eop : 0;
rop.ProdLine = "";
rop.ProdRange = "";
rop.Languages = "";
rop.tenant_id = input.tenant_id;
rop.company_id = input.company_id;
rop.factory_id = input.factory_id;
rop.create_time = DateTime.Now;
rop.org_id = input.org_id;
if (isExist)
{
updateList.Add(rop);
}
else
{
addList.Add(rop);
}
}
}
}
addList?.ForEach(item => { item.GenerateNewId(help.NextId()); });
await _businessDbContext.BulkInsertAsync(addList);
await _businessDbContext.BulkUpdateAsync(updateList);
return "OK";
}
private List CalcMonthPlanSubItem(List planList, List boms, List