using Business.Core.Utilities;
using Business.Domain;
using Business.Dto;
using Business.EntityFrameworkCore;
using Business.EntityFrameworkCore.SqlRepositories;
using Business.PriorityManagement;
using Business.ReplenishmentManagement;
using Business.ResourceExamineManagement.Dto;
using Business.ResourceExamineManagement;
using Business.StructuredDB.SaleFcst;
using Business.StructuredDB.WMS;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
using Newtonsoft.Json;
using EFCore.BulkExtensions;
using Business.Core.Enum;
using Org.BouncyCastle.Crypto;
using Business.StructuredDB.Replenishment;
using System.ComponentModel.Design;
using Newtonsoft.Json.Linq;
using MathNet.Numerics.RootFinding;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.Collections;
using MongoDB.Driver.Linq;
using System.Reflection;
using MongoDB.Driver;
namespace Business.Replenishment
{
///
/// 产能分析
///
public class ReplenishmentAppService : ApplicationService, IReplenishmentAppService, ITransientDependency
{
#region 服务
///
/// 雪花算法
///
SnowFlake help = new SnowFlake();
private readonly IRepository _replenishmentROP;
private readonly IRepository _domesticTerminalFcst;
private readonly ISqlRepository _ASNBOLShipperDetail;
private readonly IRepository _standardItemModelSet;
private readonly ISqlRepository _invTransHist;
private readonly ISqlRepository _SAPInv;
private readonly IRepository _srmPurchase;
private readonly ISqlRepository _monthlyShipmentPlan;
private readonly ISqlRepository _generalizedCodeMaster;
private readonly ISqlRepository _rf_serialnumber;
private readonly ISqlRepository _locationDetail;
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 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 _periodSequenceDet;
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 _mes_oorder;
private readonly ISqlRepository _scheduleResultOpMaster;
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 IRepository _yearDemandManagement;
///
/// 年度销售预测历史记录
///
private IRepository _yearDemandManagementHistory;
///
/// 年度生产大纲
///
private IRepository _replenishmentAnnualProduction;
///
/// 平台库存表
///
private readonly IRepository _PlatformInventory;
///
/// 工单工艺路线明细
///
private ISqlRepository _workOrdRouting;
///
/// 月度产能共识表
///
private IRepository _monthlyProdCapacity;
///
/// 月度产能共识明细表
///
private IRepository _monthlyProdCapacityDtl;
///
/// 计划订单表
///
private IRepository _crm_planorder;
///
/// 平台库存表
///
private IRepository _platformInventory;
///
/// 在途检查
///
private readonly PurchaseOrderAppService _purchaseOrderAppService;
///
/// 计算BOM平铺物料情况
///
private readonly CalcBomViewAppService _CalcBomViewAppService;
///
/// 预处理
///
private readonly PretreatmentAppService _pretreatmentAppService;
private readonly SerialNumberAppService _serialNumberAppService;
///
/// 产能检查
///
private readonly ProductExamineAppService _productExamineAppService;
///
/// 资源检查入参
///
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();
///
/// 节假日
///
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;
#endregion
#region 构造函数
///
/// 构造函数
///
public ReplenishmentAppService(
IRepository replenishmentROP,
IRepository domesticTerminalFcst,
ISqlRepository ASNBOLShipperDetail,
IRepository standardItemModelSet,
ISqlRepository invTransHist,
ISqlRepository SAPInv,
IRepository srmPurchase,
ISqlRepository monthlyShipmentPlan,
ISqlRepository generalizedCodeMaster,
ISqlRepository rf_serialnumber,
ISqlRepository locationDetail,
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,
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,
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,
ISqlRepository scheduleResultOpMaster,
IRepository productionMasterPlan,
IRepository yearDemandManagement,
IRepository replenishmentAnnualProduction,
IRepository yearDemandManagementHistory,
IRepository PlatformInventory,
ISqlRepository workOrdRouting,
ISqlRepository custMaster,
IRepository monthlyProdCapacity,
IRepository monthlyProdCapacityDtl,
IRepository crm_planorder,
IRepository platformInventory,
IRepository replenishmentWeekPlan,
IRepository mysql_examine_result,
IRepository mysql_bom_child_examine,
IRepository replenishmentServiceLevel,
SerialNumberAppService serialNumberAppService,
PretreatmentAppService pretreatmentAppService,
PurchaseOrderAppService purchaseOrderAppService,
CalcBomViewAppService CalcBomViewAppService,
ProductExamineAppService productExamineAppService,
BusinessBangDbContext businessBangDbContext,
BusinessDbContext businessDbContext,
ICurrentTenant currentTenant,
IUnitOfWorkManager unitOfWorkManager)
{
_replenishmentROP = replenishmentROP;
_domesticTerminalFcst = domesticTerminalFcst;
_ASNBOLShipperDetail = ASNBOLShipperDetail;
_standardItemModelSet = standardItemModelSet;
_invTransHist = invTransHist;
_SAPInv = SAPInv;
_srmPurchase = srmPurchase;
_monthlyShipmentPlan = monthlyShipmentPlan;
_generalizedCodeMaster = generalizedCodeMaster;
_rf_serialnumber=rf_serialnumber;
_locationDetail = locationDetail;
_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;
_custMaster=custMaster;
_prodLineDetail = prodLineDetail;
_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;
_periodSequenceDet = periodSequenceDet;
_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;
_mes_oorder = mes_oorder;
_scheduleResultOpMaster = scheduleResultOpMaster;
_productionMasterPlan=productionMasterPlan;
_replenishmentWeekPlan=replenishmentWeekPlan;
_mysql_examine_result = mysql_examine_result;
_mysql_bom_child_examine= mysql_bom_child_examine;
_replenishmentServiceLevel = replenishmentServiceLevel;
_PlatformInventory = PlatformInventory;
_workOrdRouting = workOrdRouting;
_ASNBOLShipperDetail = ASNBOLShipperDetail;
_yearDemandManagement = yearDemandManagement;
_yearDemandManagementHistory = yearDemandManagementHistory;
_replenishmentAnnualProduction = replenishmentAnnualProduction;
_holidayMaster = holidayMaster;
_monthlyProdCapacity = monthlyProdCapacity;
_monthlyProdCapacityDtl = monthlyProdCapacityDtl;
_crm_planorder = crm_planorder;
_platformInventory = platformInventory;
_serialNumberAppService= serialNumberAppService;
_pretreatmentAppService = pretreatmentAppService;
_CalcBomViewAppService = CalcBomViewAppService;
_purchaseOrderAppService = purchaseOrderAppService;
_productExamineAppService = productExamineAppService;
_currentTenant =currentTenant;
_businessBangDbContext= businessBangDbContext;
_businessDbContext = businessDbContext;
_unitOfWorkManager = unitOfWorkManager;
}
#endregion
///
/// 生成年度生产大纲
///
///
///
///
public async Task SaveAnnualProductionOutline(InputDto input)
{
//获取当前导入或修改数据
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();
//标准工艺路径表
var sapItemList = yearDemands.Select(m => m.SAPItemNumber).Distinct().ToList();
List routingOps = _routingOpDetail.Select(p => sapItemList.Contains(p.RoutingCode) && p.Domain == input.factory_id.ToString() && p.IsActive);
var routingOpList = routingOps.Where(x => x.Descr == "去溢料").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 locations = _locationDetail.Select(x => sapItemList.Contains(x.ItemNum) && x.Domain == input.factory_id.ToString() && x.IsActive).ToList();
//平台库存
var platformInvList = _PlatformInventory.GetListAsync(a => sapItemList.Contains(a.SAPItemNumber) && a.factory_id == input.factory_id && !a.IsDeleted).Result;
var replenishmentModels = _replenishmentROP.GetListAsync(x => !x.IsDeleted && x.isparam && sapItemList.Contains(x.number)).Result.ToList();
// 获取某年某月的起始日期和结束日期
int year = input.year;
int month = DateTime.Now.Month;
DateTime start = new DateTime(year, 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(year, 4, 1);
DateTime endYear = new DateTime(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();
foreach (var item in yearDemands)
{
var routingOp = routingOps.Where(x => x.RoutingCode == item.SAPItemNumber).ToList();
//组装标准工时
var Assembly = routingOp.Where(x => x.Descr == "组装").FirstOrDefault();
//热封标准工时
var HeatSealing = routingOp.Where(x => x.Descr == "热封").FirstOrDefault();
//包装标准工时
var Packaging = routingOp.Where(x => x.Descr == "包装").FirstOrDefault();
var prodLine = prodLines.Where(x => x.Part == item.SAPItemNumber).OrderBy(x => x.Sequence).FirstOrDefault();
//不同库位库存数量
var locationList = locations.Where(x => x.ItemNum == item.SAPItemNumber).ToList();
//平台数据
var platformInvs = platformInvList.Where(x => x.SAPItemNumber == item.SAPItemNumber).ToList();
//销售预测 对应 Excel中公式 AVERAGE 如果预测为0不参与计算排产批量
var QtySum = yearDemands.Where(x => x.SAPItemNumber == item.SAPItemNumber && x.Qty > 0).ToList();
//排产批量:(AVG(1 - 12月销售预测)/ 100 )=(0.45 = 1 小数向上取整) *100 = 100
var pcpl = Math.Ceiling(QtySum.Sum(p => p.Qty) / (QtySum.Count()*100)) * 100;
//库存合计 + 在制+已发货 + 灭菌中 TODO: 灭菌中取值待确定
var ship = shipList.Where(x => x.ContainerItem == item.SAPItemNumber).ToList();
decimal itemInProduct = 0;
if(dictInProduction.ContainsKey(item.SAPItemNumber))
{
itemInProduct = dictInProduction[item.SAPItemNumber];
}
var locationSum = (locationList.Count == 0 ? 0 : locationList.Sum(x => x.QtyOnHand)) + (platformInvs.Count == 0 ? 0 : platformInvs.Sum(x => x.InventoryQuantity)) + (ship.Count == 0 ? 0 : ship.Sum(x => x.RealQty)) + itemInProduct + 0;
//前面N个月的生产数量
var frontQtySum = annualProductionOutlines.Sum(x => x.Qty);
//生产数量:3月为例子,if((库存合计和前2月生产数量)-(前2个月销售预测数据+安全库存)-当月销售预测数据 / 2 < 0)
// { 排产批量 * ((-(库存合计+前2个月生产数量)) + (安全库存+前2个月销售预测) + 当月销售预测 / 2 ) / 排产批量 ) } else {0}
decimal ProduceQty = 0.00m;
//判断库存是否满足需要,满足则不用生产
var num = (locationSum.Value + frontQtySum) - frontYearDemand.Sum(m => m.Qty) + 0 - item.Qty / 2;
if (num < 0)
{
ProduceQty = pcpl * Math.Ceiling((-(locationSum.Value + frontQtySum)) + (frontYearDemand.Sum(m => m.Qty) + 0) + item.Qty / 2);
}
else
{
ProduceQty = 0;
}
//生成年度生产大纲
ReplenishmentAnnualProduction annualProductionOutline = new ReplenishmentAnnualProduction();
annualProductionOutline.Year = item.Year;
annualProductionOutline.Area = item.Area;
annualProductionOutline.ProdLine = item.ProdLine;
annualProductionOutline.ProdRange = item.ProdRange;
annualProductionOutline.WorkshopLine = prodLine == null ? "" : prodLine.Line;
annualProductionOutline.SAPItemNumber = item.SAPItemNumber;
annualProductionOutline.Model = item.Model;
annualProductionOutline.Languages = item.Languages;
annualProductionOutline.PlanMonth = item.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 = item.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);
frontYearDemand.Add(item);
}
//保存数据
using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
{
try
{
await _replenishmentAnnualProduction.HardDeleteAsync(a => a.Year == input.year && a.factory_id == input.factory_id);
await _replenishmentAnnualProduction.InsertManyAsync(annualProductionOutlines);
await CalcLongPeriodItemPR(input);
await CalcROP(input);
await SaveProductionMasterPlan(input, annualProductionOutlines);
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)
{
//计算当前年月的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 = _monthlyShipmentPlan.Select(x => planMons.Contains(x.PlanMonth) && !x.IsDeleted && x.factory_id == input.factory_id).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 = _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.Where(a=> GetPlanMonth(4).Contains(a.PlanMonth)))
{
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;
plan.ItemNumber = item.SAPItemNumber;
plan.Model = item.Model;
plan.Languages = item.Languages;
plan.PlanMonth = item.PlanMonth;
plan.PlanShipQty = item.Qty;
//计划生产数量取下个月计划发货数量的一半
plan.PlanProductQty = item.Qty- itemStock.Find(a => a.ItemNumber == item.SAPItemNumber).Qty- InProdcutQty.Find(a => a.ItemNumber == item.SAPItemNumber).Qty;//发货计划-(库存+在制)
plan.PlanStockQty= item.Qty;//TODO:期末库存怎么算?
if(locations.FirstOrDefault(a => a.ItemNum == item.SAPItemNumber && a.Location == "8001")!=null)
{
plan.Inventory = locations.FirstOrDefault(a => a.ItemNum == item.SAPItemNumber && a.Location == "8001").QtyOnHand;
}else
{
plan.Inventory = 0;
}
if (locations.FirstOrDefault(a => a.ItemNum == item.SAPItemNumber && a.Location == "8000") != null)
{
plan.Inventory1 = locations.FirstOrDefault(a => a.ItemNum == item.SAPItemNumber && a.Location == "8000").QtyOnHand;
}
else
{
plan.Inventory1 = 0;
}
if (locations.FirstOrDefault(a => a.ItemNum == item.SAPItemNumber && a.Location == "5008") != null)
{
plan.Inventory2 = locations.FirstOrDefault(a => a.ItemNum == item.SAPItemNumber && a.Location == "5008").QtyOnHand;
}
else
{
plan.Inventory2 = 0;
}
plan.DuringSterilization = 0;//TODO:灭菌中需要从委外订单接口获取
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;
productionMasters.Add(plan);
}
//保存数据
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 _productionMasterPlan.InsertManyAsync(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 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|刷新成功!";
}
///
/// 计算当月有多少个周末
///
///
///
///
private int CalcWeekDays(int days, DateTime startDay)
{
int sumDays = 0;
for (int i = 0; i < days; i++)
{
int weekDays = (int)startDay.AddDays(i).DayOfWeek;
if (weekDays == 0 || weekDays == 6)
{
sumDays++;
}
}
return sumDays;
}
///
/// 调整ROP和最高库存水位(按照成品展开到原材料,原材料用领料算出库)
///
///
///
public async Task CalcROP(InputDto input)
{
//1.获取补货模型全局参数
ReplenishmentDto replenishmentDto = GetROPParam(input.factory_id.ToString());
//获取月度发货计划(一次导入三个月的销售预测),因为是固定格式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 boms = _ic_bom.GetListAsync(a => planList.Select(p => p.SAPItemNumber).ToList().Contains(a.item_number) && 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 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 itemList = _ic_item.GetListAsync(a => pretreatments.Select(p => p.item_number).Contains(a.number) && !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.IsDeleted).Result;
//获取补货模型前H周期和未来F个周期的数据
var ropModelList = _replenishmentROP.GetListAsync(a => a.zero_based_seqno >= -1 * replenishmentDto.HistoryOutStockMonth && a.zero_based_seqno <= replenishmentDto.SaleFcstMonth).Result;
//获取成品库存、灭菌库存、在制库存(会从SAP同步的库存表更新到LocationDetail、ic_item表中)
//List 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() && 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 && 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
{
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 addList = new List();
List updateList = new List();//更新上一个月的实际出库数量
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);
}
});
var serviceList=_replenishmentServiceLevel.GetListAsync(a => a.factory_id == input.factory_id).Result;
List addServiceLevelList = new List();
List updateServiceLevelList = new List();
//需要按照成品资源检查计算原材料
planList?.Where(s => s.PlanMonth == planMonth).ToList()?.ForEach(a =>
{
var itemSourceId = boms.Find(b => b.item_number == a.SAPItemNumber)?.mysql_id;
if (itemSourceId != null)
{
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, shipList, pickbilllist, input);
if(serviceList.Any(s=>s.number==rop.number))
{
var rs = serviceList.Find(s => s.number == rop.number);
//总的移库次数
int totalCount = shipList.Count() + pickbilllist.Count();
//平均出库次数
decimal avgOutStock = totalCount / replenishmentDto.HistoryOutStockMonth;
//总出货金额
decimal? totalPrice = shipList.Sum(a => a.Price * a.QtyToShip);
//按照物料分组统计出货金额
var itemGroup = shipList.GroupBy(p => p.ContainerItem)
.Select(p => new ASNBOLShipperDetail
{
Price = p.Sum(a => a.Price * a.QtyToShip) * 100 / totalPrice,
ContainerItem = p.Key
}).ToList().OrderByDescending(c => c.Price).ThenByDescending(c => c.ContainerItem);
rs.number = rop.number;
rs.name = rop.name;
rs.model = rop.model;
rs.item_type = icItem.item_type;
rs.fversion = rop.fversion;
rs.totalCount = totalCount;
rs.avgOutStock = avgOutStock;
rs.totalPrice = totalPrice;
if(itemGroup.Count()>0 && itemGroup.First(p => p.ContainerItem == rop.number)!=null)
{
rs.Price= itemGroup.First(p => p.ContainerItem == rop.number).Price;
}else
{
rs.Price = 0;
}
rs.abc = rop.abc;
rs.fmr = rop.fmr;
rs.service_level_pct = rop.service_level_pct;
rs.factory_id = input.factory_id;
rs.tenant_id = input.tenant_id;
rs.company_id = input.company_id;
rs.update_time = DateTime.Now;
updateServiceLevelList.Add(rs);
}
else
{
//总的移库次数
int totalCount = shipList.Count() + pickbilllist.Count();
//平均出库次数
decimal avgOutStock = totalCount / replenishmentDto.HistoryOutStockMonth;
//总出货金额
decimal? totalPrice = shipList.Sum(a => a.Price * a.QtyToShip);
//按照物料分组统计出货金额
var itemGroup = shipList.GroupBy(p => p.ContainerItem)
.Select(p => new ASNBOLShipperDetail
{
Price = p.Sum(a => a.Price * a.QtyToShip) * 100 / totalPrice,
ContainerItem = p.Key
}).ToList().OrderByDescending(c => c.Price).ThenByDescending(c => c.ContainerItem);
ReplenishmentServiceLevel rs = new ReplenishmentServiceLevel();
rs.number = rop.number;
rs.name = rop.name;
rs.model = rop.model;
rs.item_type = icItem.item_type;
rs.fversion = rop.fversion;
rs.totalCount = totalCount;
rs.avgOutStock = avgOutStock;
rs.totalPrice = totalPrice;
if (itemGroup.Count() > 0 && itemGroup.First(p => p.ContainerItem == rop.number) != null)
{
rs.Price = itemGroup.First(p => p.ContainerItem == rop.number).Price;
}
else
{
rs.Price = 0;
}
rs.abc = rop.abc;
rs.fmr = rop.fmr;
rs.service_level_pct = rop.service_level_pct;
rs.factory_id = input.factory_id;
rs.tenant_id = input.tenant_id;
rs.company_id = input.company_id;
rs.create_time = DateTime.Now;
rs.GenerateNewId(help.NextId());
addServiceLevelList.Add(rs);
}
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()); });
addServiceLevelList?.ForEach(item => { item.GenerateNewId(help.NextId()); });
await _replenishmentROP.InsertManyAsync(addList);
await _replenishmentROP.UpdateManyAsync(updateList);
await _replenishmentServiceLevel.InsertManyAsync(addServiceLevelList);
await _replenishmentServiceLevel.UpdateManyAsync(updateServiceLevelList);
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";
}
///
/// 根据月计划生产周计划
///
///
///
public async Task CalcWeekPlan(InputDto input)
{
//1.获取补货模型全局参数
ReplenishmentDto replenishmentDto = GetROPParam(input.factory_id.ToString());
//获取月度发货计划(一次导入三个月的销售预测),因为是固定格式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();
//发货计划物料列表
List planItemList = planList?.Select(a => a.SAPItemNumber).Distinct().ToList();
var itemList = _ic_item.GetListAsync(a => planList.Select(p => p.SAPItemNumber).Contains(a.number) && !a.IsDeleted).Result;
var bomList = _ic_bom.GetListAsync(a => planItemList.Contains(a.item_number) && !a.IsDeleted && a.factory_id == input.factory_id).Result;
var monthPlan = _productionMasterPlan.GetListAsync(a => planItemList.Contains(a.ItemNumber) && !a.IsDeleted && a.factory_id == input.factory_id).Result;
//获取补货模型前H周期和未来F个周期的数据
var ropModelList = _replenishmentROP.GetListAsync(a => a.zero_based_seqno >= -1 * replenishmentDto.HistoryOutStockMonth && a.zero_based_seqno <= replenishmentDto.SaleFcstMonth && planItemList.Contains(a.number)).Result;
planList = planList.OrderBy(a => a.OrderNum).ToList();
List moList = new List();
List moentryList = new List();
List weekPlan = new List();
long bang_id = help.NextId();
DateTime currentTime = DateTime.Now;
int week = Convert.ToInt32(currentTime.DayOfWeek);
week = week == 0 ? 7 : week;
int count = planItemList.Count * 12;
var list = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "MPO", count, "", 1);
var nbrlistDto = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "M5", count, "", 1);
int j = 0;
for (int i=0;i<12;i++)
{
planList.Where(c=>c.PlanMonth== planMonth).ToList().ForEach(a =>
{
var ic_item = itemList.Find(x => x.number == a.SAPItemNumber);
var itemrop= ropModelList.Find(x=>x.number == a.SAPItemNumber);
var monthPlanItem = monthPlan.Find(x => x.ItemNumber == a.SAPItemNumber);
if (ic_item?.erp_cls == 1 && itemrop!=null)
{
var bom = bomList.Find(b => b.item_number == a.SAPItemNumber);
mes_morder mes_Morder = new mes_morder();
mes_Morder.GenerateNewId(help.NextId());
mes_Morder.morder_type = MorderEnum.JhMorder;
//mes_Morder.morder_icitem_type
mes_Morder.work_order_type = MorderEnum.FhMorder;
mes_Morder.morder_state = MorderEnum.Initial_state;
mes_Morder.morder_no = list[j].NbrResult;
mes_Morder.fms_number = ic_item.fms_number;
mes_Morder.bom_number = bom.bom_number;
mes_Morder.fmodel = ic_item.model;
mes_Morder.urgent = 1;
mes_Morder.moentry_startup_status = 0;
mes_Morder.tenant_id = input.tenant_id;
mes_Morder.factory_id = input.factory_id;
mes_Morder.company_id = input.company_id;
mes_Morder.org_id = input.org_id;
mes_Morder.product_code = ic_item.number;
mes_Morder.product_name = ic_item.name;
mes_Morder.morder_date = DateTime.Now.Date.AddDays(1);
//成品半成品取周一开始 + 取供应提前期为结束时间
mes_Morder.moentry_stime = currentTime.AddDays(1 - week + 7 * (i + 1));
mes_Morder.moentry_sys_etime = currentTime.AddDays(1 - week + 7*(i+1)+ Convert.ToDouble(itemrop.supply_leadtime));
//mes_Morder.morder_fstate = "计划";
//TODO:目前没有取值位置
mes_Morder.moentry_prd = null;
mes_Morder.moentry_prdname = null;
mes_Morder.moentry_wrkc = null;
mes_Morder.moentry_wrkcname = null;
mes_Morder.picking_qty = 0;
//TODO:可删除主表字段
mes_Morder.unit = ic_item.unit;
mes_Morder.morder_production_number = itemrop.eop/4;
mes_Morder.need_number = itemrop.eop/4;
mes_Morder.remaining_number = 0;
mes_Morder.create_time = DateTime.Now;
mes_Morder.bang_id = bang_id;
//生成工单子表数据
mes_moentry mes_Moentry = new mes_moentry();
mes_Moentry.GenerateNewId(help.NextId());
mes_Moentry.moentry_moid = mes_Morder.Id;
mes_Moentry.moentry_mono = mes_Morder.morder_no;
mes_Moentry.unit = ic_item.unit;
mes_Moentry.morder_production_number = itemrop.eop/4;
mes_Moentry.need_number = itemrop.eop/4;
mes_Moentry.remaining_number = 0;
mes_Moentry.tenant_id = input.tenant_id;
mes_Moentry.factory_id = input.factory_id;
mes_Moentry.company_id = input.company_id;
mes_Moentry.org_id = input.org_id;
mes_Moentry.create_time = DateTime.Now;
mes_Moentry.bang_id = bang_id;
moList.Add(mes_Morder);
moentryList.Add(mes_Moentry);
ReplenishmentWeekPlan weekItem = new ReplenishmentWeekPlan();
weekItem.Priority = 1;
weekItem.Area = itemrop.area;
weekItem.PlanStartDate = mes_Morder.moentry_stime.Value;
weekItem.Week =$"WK{GetWeekOfYear(mes_Morder.moentry_stime.Value).ToString("00")}";
weekItem.OrderNO = list[j].NbrResult;
weekItem.ProductionOrder = nbrlistDto[j].NbrResult;
weekItem.SAPOrderNO = "";
weekItem.OrderType = "量产";
weekItem.ProductionBatch = "";
weekItem.ProductionStatus = "";
weekItem.ProdLine =a.ProdLine;
weekItem.ProdRange =a.ProdRange;
weekItem.Line = monthPlanItem.WorkshopLine;
weekItem.ItemNumber =a.SAPItemNumber;
weekItem.Model =a.Model;
weekItem.Languages =a.Languages;
weekItem.Qty = mes_Morder.morder_production_number.Value;
weekItem.ItemStatus = "";
weekItem.PlanKittingDate = DateTime.Now;
weekItem.tenant_id = input.tenant_id;
weekItem.factory_id = input.factory_id;
weekItem.company_id = input.company_id;
weekItem.org_id = input.org_id;
weekItem.create_time = DateTime.Now;
if (itemrop.area=="国内")
{
weekItem.SterilizationDate = mes_Morder.moentry_sys_etime.Value.AddDays(8);
}else
{
weekItem.SterilizationDate = mes_Morder.moentry_sys_etime.Value.AddDays(15);
}
weekItem.InStockDate = mes_Morder.moentry_sys_etime;
weekItem.AssembleHours = 0;
weekItem.HeatSealHours = 0;
weekItem.PackageHours = 0;
weekItem.TotalHours = 0;
weekPlan.Add(weekItem);
j++;
}
});
}
await _mysql_mes_morder.InsertManyAsync(moList);
await _mysql_mes_moentry.InsertManyAsync(moentryList);
await PlanOrderResourceCheck(moList, moentryList, bang_id, input);
List routingOps = _routingOpDetail.Select(p => planItemList.Contains(p.RoutingCode) && p.Domain == input.factory_id.ToString() && p.IsActive);
var examine_resultList= _mysql_examine_result.GetListAsync(a=>a.bangid == bang_id).Result;
//批量保存 后期考虑子工单
List workOrds = new List();
List workOrdRoutings = new List();
List workOrdDetails = new List();
if (moList.Any())
{
moList.ForEach(s => { s.create_time = DateTime.Now; });
List childExamineList = _mysql_bom_child_examine.GetListAsync(c => examine_resultList.Select(x => x.Id).Contains(c.examine_id.GetValueOrDefault())).Result;
//同步工单
CreateWorkOrdDates(moList, routingOps, workOrds, workOrdRoutings, workOrdDetails, examine_resultList, childExamineList);
}
if (workOrds.Any())
{
workOrds=CalcPriority(workOrds, input.factory_id.ToString());
_workOrdMaster.Insert(workOrds);
}
var DBworkOrdList = _workOrdMaster.Select(a => a.Domain == workOrds[0].Domain && workOrds.Select(c => c.WorkOrd).Contains(a.WorkOrd));
if (workOrdRoutings.Any())
{
workOrdRoutings.ForEach(c =>
{
c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID;
});
_workOrdRouting.Insert(workOrdRoutings);
}
if (workOrdDetails.Any())
{
workOrdDetails.ForEach(c =>
{
c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID;
});
_workOrdDetail.Insert(workOrdDetails);
}
weekPlan.ForEach(a =>
{
var moItem = examine_resultList.Find(b => b.morder_no == a.OrderNO);
var routingOp = routingOps.Where(x => x.RoutingCode == a.ItemNumber).ToList();
//组装标准工时
var Assembly = routingOp.Where(x => x.Descr == "组装").FirstOrDefault();
//热封标准工时
var HeatSealing = routingOp.Where(x => x.Descr == "热封").FirstOrDefault();
//包装标准工时
var Packaging = routingOp.Where(x => x.Descr == "包装").FirstOrDefault();
if (moItem!=null && moItem.kitting_times b.WorkOrd == a.OrderNO);
if(workOrd!=null)
{
a.Priority = workOrd.Priority;
}
});
await _replenishmentWeekPlan.InsertManyAsync(weekPlan);
return "OK";
}
///
/// 发布周计划
///
///
///
public async Task PublishWeekPlan(InputDto input)
{
DateTime nextWeekMonday = getPreWeekStartTime().AddDays(14);
DateTime next2WeekMonday = getPreWeekStartTime().AddDays(28);
var weekPlan = _replenishmentWeekPlan.GetListAsync(a => a.PlanStartDate >= nextWeekMonday && a.PlanStartDate < next2WeekMonday).Result;
var workMasters = _workOrdMaster.Select(a => weekPlan.Select(s=>s.ItemNumber).Contains(a.ItemNum) && weekPlan.Select(p=>p.OrderNO).Contains(a.WorkOrd) && a.Domain == input.factory_id.ToString());
weekPlan?.ForEach(a =>
{
a.ProductionStatus = "已发布";
workMasters.ForEach(b =>
{
if (b.ItemNum == a.ItemNumber && b.WorkOrd == a.OrderNO)
{
b.Priority = a.Priority;
}
});
});
_workOrdMaster.Update(workMasters);
await _replenishmentWeekPlan.UpdateManyAsync(weekPlan);
return "OK";
}
///
/// 每天补货
///
///
///
public async Task CalcDayPlan(InputDto input)
{
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.IsDeleted).Result;
var itemStock = CalcStock(ropModelList.Select(a => a.number).ToList(), input);
var bomList = _ic_bom.GetListAsync(a => ropModelList.Select(a => a.number).ToList().Contains(a.item_number) && !a.IsDeleted && a.factory_id == input.factory_id).Result;
List moList = new List();
List moentryList = new List();
var itemNeedPRList = ropModelList.Where(a => a.erp_cls == 1).ToList();
int count = 0;
itemNeedPRList.ForEach(a => {
if (itemStock.First(c => c.ItemNumber == a.number).Qty < a.rop_revised)
{
count++;
}
});
var list = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "MPO", count, "", 1);
var nbrlistDto = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "M5", count, "", 1);
int j = 0;
DateTime currentTime = DateTime.Now;
int week = Convert.ToInt32(currentTime.DayOfWeek);
week = week == 0 ? 7 : week;
long bang_id = help.NextId();
ropModelList.Where(a => a.erp_cls == 1)?.ToList().ForEach(b =>
{
if(itemStock.First(c=>c.ItemNumber==b.number).Qty c.item_number ==b.number);
mes_morder mes_Morder = new mes_morder();
mes_Morder.GenerateNewId(help.NextId());
mes_Morder.morder_type = MorderEnum.JhMorder;
//mes_Morder.morder_icitem_type
mes_Morder.work_order_type = MorderEnum.FhMorder;
mes_Morder.morder_state = MorderEnum.Initial_state;
mes_Morder.morder_no = list[j].NbrResult;
mes_Morder.fms_number =b.number;
mes_Morder.bom_number = bom.bom_number;
mes_Morder.fmodel = b.model;
mes_Morder.urgent = 1;
mes_Morder.moentry_startup_status = 0;
mes_Morder.tenant_id = input.tenant_id;
mes_Morder.factory_id = input.factory_id;
mes_Morder.company_id = input.company_id;
mes_Morder.org_id = input.org_id;
mes_Morder.product_code = b.number;
mes_Morder.product_name = b.name;
mes_Morder.morder_date = DateTime.Now.Date.AddDays(1);
//成品半成品取周一开始 + 取供应提前期为结束时间
mes_Morder.moentry_stime = currentTime.AddDays(1 - week + 7);
mes_Morder.moentry_sys_etime = currentTime.AddDays(1 - week + 7 + Convert.ToDouble(b.supply_leadtime));
//mes_Morder.morder_fstate = "计划";
//TODO:目前没有取值位置
mes_Morder.moentry_prd = null;
mes_Morder.moentry_prdname = null;
mes_Morder.moentry_wrkc = null;
mes_Morder.moentry_wrkcname = null;
mes_Morder.picking_qty = 0;
//TODO:可删除主表字段
mes_Morder.unit = "";
mes_Morder.morder_production_number = b.eop;
mes_Morder.need_number = b.eop;
mes_Morder.remaining_number = 0;
mes_Morder.create_time = DateTime.Now;
mes_Morder.bang_id = bang_id;
//生成工单子表数据
mes_moentry mes_Moentry = new mes_moentry();
mes_Moentry.GenerateNewId(help.NextId());
mes_Moentry.moentry_moid = mes_Morder.Id;
mes_Moentry.moentry_mono = mes_Morder.morder_no;
mes_Moentry.unit = "";
mes_Moentry.morder_production_number = b.eop;
mes_Moentry.need_number = b.eop;
mes_Moentry.remaining_number = 0;
mes_Moentry.tenant_id = input.tenant_id;
mes_Moentry.factory_id = input.factory_id;
mes_Moentry.company_id = input.company_id;
mes_Moentry.org_id = input.org_id;
mes_Moentry.create_time = DateTime.Now;
mes_Moentry.bang_id = bang_id;
moList.Add(mes_Morder);
moentryList.Add(mes_Moentry);
j++;
}
});
await PlanOrderResourceCheck(moList, moentryList, bang_id, input);
List routingOps = _routingOpDetail.Select(p => ropModelList.Where(a=>a.erp_cls==1).Select(a => a.number).ToList().Contains(p.RoutingCode) && p.Domain == input.factory_id.ToString() && p.IsActive);
var examine_resultList = _mysql_examine_result.GetListAsync(a => a.bangid == bang_id).Result;
//批量保存 后期考虑子工单
List workOrds = new List();
List workOrdRoutings = new List();
List workOrdDetails = new List();
if (moList.Any())
{
moList.ForEach(s => { s.create_time = DateTime.Now; });
List childExamineList = _mysql_bom_child_examine.GetListAsync(c => examine_resultList.Select(x => x.Id).Contains(c.examine_id.GetValueOrDefault())).Result;
//同步工单
CreateWorkOrdDates(moList, routingOps, workOrds, workOrdRoutings, workOrdDetails, examine_resultList, childExamineList);
}
if (workOrds.Any())
{
workOrds = CalcPriority(workOrds, input.factory_id.ToString());
_workOrdMaster.Insert(workOrds);
}
var DBworkOrdList = _workOrdMaster.Select(a => a.Domain == workOrds[0].Domain && workOrds.Select(c => c.WorkOrd).Contains(a.WorkOrd));
if (workOrdRoutings.Any())
{
workOrdRoutings.ForEach(c =>
{
c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID;
});
_workOrdRouting.Insert(workOrdRoutings);
}
if (workOrdDetails.Any())
{
workOrdDetails.ForEach(c =>
{
c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID;
});
_workOrdDetail.Insert(workOrdDetails);
}
//成品半成品取下周一开始+取供应提前期为结束时间
//原材料取第二天开始+取供应提前期为结束时间
//DOP运行资源检查每个原材料SKU的可用库存,当可用库存<=修正后ROP时,自动生成月度采购申请(Purchase request,PR46年月日4位流水号)=EOP;可用库存为没有被其他SO和PO占用的(合格原材料库存+在途库存);
var planList = _ic_item.GetListAsync().Result;
List< srm_pr_main> prList = new List();
var numbers = ropModelList.Where(a => a.erp_cls == 3).Select(b => b.number).ToList();
var icItemList = _mysql_ic_item.GetListAsync(c => numbers.Contains(c.number)).Result;
var srm_pr_mains = _srm_pr_main.GetListAsync(x => icItemList.Select(p => p.Id).ToList().Contains(x.icitem_id.Value) && x.state != 0 && !x.IsDeleted && x.state!=4).Result;
var quarter_srm_pr_mains=srm_pr_mains.Where(s => s.pr_psend_date >= _CalcBomViewAppService.quarter_starttime && s.pr_psend_date < _CalcBomViewAppService.quarter_endtime).ToList();
ropModelList.Where(a => a.erp_cls ==3)?.ToList().ForEach(b =>
{
if (itemStock.First(c => c.ItemNumber == b.number).Qty < b.rop_revised)
{
mo_srm_purchase supplier = null;
var plan = planList.Find(x => x.number == b.number);
var item = icItemList.Find(d => d.number == b.number);
var supplist = supplierList.Where(s => s.number == b.number).ToList();
decimal day = 0;
var plan_date = DateTime.Now.AddDays(1 + Convert.ToDouble(b.supply_leadtime));
//判断当前时间与交期还剩余多少天
var timesp = plan_date - DateTime.Now.Date;
//交期-生产时长-物料前处理周期
day = timesp.Days;
if (day > 0)
{
supplist = supplist.Where(s => s.lead_time.GetValueOrDefault() < day).ToList();
if (supplist.Any())
{
//TODO:走配额管理
List itemPrlist = quarter_srm_pr_mains.Where(s => s.icitem_id == item.Id).ToList();
if (itemPrlist.Any())
{
decimal qtyCount = itemPrlist.Sum(x => x.pr_aqty).GetValueOrDefault();
//按配额比例,计算使用哪个供应商。
List PrPurchaseDtoList = new List();
supplist.ForEach(s => {
PrPurchaseDto purDto = new PrPurchaseDto();
purDto.pr_purchaseid = s.supplier_id;
purDto.num = itemPrlist.Where(x => x.pr_purchaseid == s.supplier_id).Sum(c => c.pr_aqty.GetValueOrDefault());
purDto.ratio = Math.Round(purDto.num / qtyCount, 2, MidpointRounding.AwayFromZero);
purDto.quota_priority = s.quota_priority;
purDto.quota_rate = s.quota_rate.GetValueOrDefault();
PrPurchaseDtoList.Add(purDto);
});
//首先取出占比还小于配额比的数据
var priorityPurlist = PrPurchaseDtoList.Where(s => s.quota_rate - s.ratio > 2).ToList();
if (!priorityPurlist.Any())
{
//没有则取出当前集合中的供应商的数据,计算差额
priorityPurlist = PrPurchaseDtoList;
}
//还没有达到配额比的供应商,优先分配
decimal difference = 0;
PrPurchaseDto dto1 = priorityPurlist[0];
priorityPurlist.ForEach(s => {
decimal diff = s.quota_rate - s.ratio;
if (diff > difference)
{
difference = diff;
dto1 = s;
}
});
supplier = supplist.Find(s => s.supplier_id == dto1.pr_purchaseid);
}
else
{
supplier = supplist.OrderBy(s => s.quota_priority).FirstOrDefault();//默认取配额优先级
}
}
else
{
supplier = supplist.OrderBy(s => s.quota_priority).FirstOrDefault();//默认取配额优先级
}
}
else
{
supplier = supplist.OrderBy(s => s.quota_priority).FirstOrDefault();//默认取配额优先级
}
srm_pr_main srm_Pr = new srm_pr_main();
srm_Pr.GenerateNewId(help.NextId());
srm_Pr.IsRequireGoods = supplier.IsRequireGoods;
srm_Pr.pr_purchaseid = supplier.supplier_id;//供应商id
srm_Pr.pr_purchasenumber = supplier.supplier_number;//供应商编码
srm_Pr.pr_purchasename = supplier.supplier_name;//供应商名称
srm_Pr.pr_purchaser = supplier.order_rector_name;//采购员
srm_Pr.pr_purchaser_num = supplier.order_rector_num;//采购员工号(采购信息表)
//数量圆整 按最小包装量向上圆整
decimal qty =b.eop.Value;
//判断最小起订量
qty = qty > supplier.qty_min ? qty : supplier.qty_min.GetValueOrDefault();
srm_Pr.pr_rqty = qty;//需求数量
srm_Pr.pr_aqty = qty;//申请数量
srm_Pr.pr_sqty = qty;//建议数量
srm_Pr.icitem_id = item.Id;//物料id
srm_Pr.icitem_name = b.name;//物料名称
srm_Pr.pr_order_type = 1;//单据类型
srm_Pr.pr_ssend_date = DateTime.Now.Date.AddDays(1);//系统建议下单日期
srm_Pr.pr_sarrive_date = DateTime.Now.AddDays((double)supplier.lead_time.GetValueOrDefault());//系统建议到达日期(建议到货日期)
srm_Pr.pr_sysprice = supplier.order_price;//系统价格(含税)
srm_Pr.pr_orderprice = qty * supplier.order_price;//订单价格(含税)
srm_Pr.pr_price = supplier.netpurchase_price;//采购净价(不含税)
srm_Pr.pr_rate = supplier.taxrate;//税率
srm_Pr.pr_unit = item.unit;//单位
srm_Pr.state = 1;//状态
srm_Pr.old_apply_aqty = 0;//已申请数量
srm_Pr.pr_type = b.erp_cls;//申请类型
srm_Pr.currencytype = supplier.currency_type == null ? 1 : supplier.currency_type.Value;//币种
srm_Pr.secInv_ratio = plan.secinv_ratio;//安全库存触发采购比例
srm_Pr.tenant_id =input.tenant_id;
srm_Pr.company_id = input.company_id;
srm_Pr.factory_id = input.factory_id;
srm_Pr.create_time = DateTime.Now;
srm_Pr.create_by_name = "admin";
srm_Pr.update_time = DateTime.Now;
srm_Pr.update_by_name = "admin";
prList.Add(srm_Pr);
}
});
prList.ForEach(a =>
{
a.GenerateNewId(help.NextId());
});
await _mysql_srm_pr_main.InsertManyAsync(prList);
await CalcDayPlanSafeStock(input);
//每天DOP检查每个SKU的可用库存<=SS时,第二次触发PO或PR,每次补货数量=圆整后EOP;SKU可用库存=实际库存+WIP或在途库存-销售订单占用-计划订单占用;当M+1\M+2实际有销售订单产生时,相同SKU的销售订单和计划订单先进行冲销;
//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周采购补货
return "OK";
}
///
/// 每天补货
///
///
///
public async Task CalcDayPlanSafeStock(InputDto input)
{
ReplenishmentDto replenishmentDto = GetROPParam(input.factory_id.ToString());
var ropModelList = _replenishmentROP.GetListAsync(a => a.isparam && a.factory_id == input.factory_id && !a.IsDeleted).Result;
var itemStock = CalcStock(ropModelList.Select(a => a.number).ToList(), input);
var bomList = _ic_bom.GetListAsync(a => ropModelList.Select(a => a.number).ToList().Contains(a.item_number) && !a.IsDeleted && a.factory_id == input.factory_id).Result;
List moList = new List();
List moentryList = new List();
var itemNeedPRList = ropModelList.Where(a => a.erp_cls == 1).ToList();
int count = 0;
itemNeedPRList.ForEach(a => {
if (itemStock.First(c => c.ItemNumber == a.number).Qty < a.security_stock)
{
count++;
}
});
var list = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "MPO", count, "", 1);
var nbrlistDto = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "M5", count, "", 1);
int j = 0;
DateTime currentTime = DateTime.Now;
int week = Convert.ToInt32(currentTime.DayOfWeek);
week = week == 0 ? 7 : week;
long bang_id = help.NextId();
ropModelList.Where(a => a.erp_cls == 1)?.ToList().ForEach(b =>
{
if (itemStock.First(c => c.ItemNumber == b.number).Qty < b.rop_revised)
{
var bom = bomList.Find(c => c.item_number == b.number);
mes_morder mes_Morder = new mes_morder();
mes_Morder.GenerateNewId(help.NextId());
mes_Morder.morder_type = MorderEnum.JhMorder;
//mes_Morder.morder_icitem_type
mes_Morder.work_order_type = MorderEnum.FhMorder;
mes_Morder.morder_state = MorderEnum.Initial_state;
mes_Morder.morder_no = list[j].NbrResult;
mes_Morder.fms_number = b.number;
mes_Morder.bom_number = bom.bom_number;
mes_Morder.fmodel = b.model;
mes_Morder.urgent = 1;
mes_Morder.moentry_startup_status = 0;
mes_Morder.tenant_id = input.tenant_id;
mes_Morder.factory_id = input.factory_id;
mes_Morder.company_id = input.company_id;
mes_Morder.org_id = input.org_id;
mes_Morder.product_code = b.number;
mes_Morder.product_name = b.name;
mes_Morder.morder_date = DateTime.Now.Date.AddDays(1);
//成品半成品取周一开始 + 取供应提前期为结束时间
mes_Morder.moentry_stime = currentTime.AddDays(1 - week + 7);
mes_Morder.moentry_sys_etime = currentTime.AddDays(1 - week + 7 + Convert.ToDouble(b.supply_leadtime));
//mes_Morder.morder_fstate = "计划";
//TODO:目前没有取值位置
mes_Morder.moentry_prd = null;
mes_Morder.moentry_prdname = null;
mes_Morder.moentry_wrkc = null;
mes_Morder.moentry_wrkcname = null;
mes_Morder.picking_qty = 0;
//TODO:可删除主表字段
mes_Morder.unit = "";
mes_Morder.morder_production_number = b.eop;
mes_Morder.need_number = b.eop;
mes_Morder.remaining_number = 0;
mes_Morder.create_time = DateTime.Now;
mes_Morder.bang_id = bang_id;
//生成工单子表数据
mes_moentry mes_Moentry = new mes_moentry();
mes_Moentry.GenerateNewId(help.NextId());
mes_Moentry.moentry_moid = mes_Morder.Id;
mes_Moentry.moentry_mono = mes_Morder.morder_no;
mes_Moentry.unit = "";
mes_Moentry.morder_production_number = b.eop;
mes_Moentry.need_number = b.eop;
mes_Moentry.remaining_number = 0;
mes_Moentry.tenant_id = input.tenant_id;
mes_Moentry.factory_id = input.factory_id;
mes_Moentry.company_id = input.company_id;
mes_Moentry.org_id = input.org_id;
mes_Moentry.create_time = DateTime.Now;
mes_Moentry.bang_id = bang_id;
moList.Add(mes_Morder);
moentryList.Add(mes_Moentry);
j++;
}
});
await PlanOrderResourceCheck(moList, moentryList, bang_id, input);
List routingOps = _routingOpDetail.Select(p => ropModelList.Where(a => a.erp_cls == 1).Select(a => a.number).ToList().Contains(p.RoutingCode) && p.Domain == input.factory_id.ToString() && p.IsActive);
var examine_resultList = _mysql_examine_result.GetListAsync(a => a.bangid == bang_id).Result;
//批量保存 后期考虑子工单
List workOrds = new List();
List workOrdRoutings = new List();
List workOrdDetails = new List();
if (moList.Any())
{
moList.ForEach(s => { s.create_time = DateTime.Now; });
List childExamineList = _mysql_bom_child_examine.GetListAsync(c => examine_resultList.Select(x => x.Id).Contains(c.examine_id.GetValueOrDefault())).Result;
//同步工单
CreateWorkOrdDates(moList, routingOps, workOrds, workOrdRoutings, workOrdDetails, examine_resultList, childExamineList);
}
if (workOrds.Any())
{
workOrds = CalcPriority(workOrds, input.factory_id.ToString());
_workOrdMaster.Insert(workOrds);
}
var DBworkOrdList = _workOrdMaster.Select(a => a.Domain == workOrds[0].Domain && workOrds.Select(c => c.WorkOrd).Contains(a.WorkOrd));
if (workOrdRoutings.Any())
{
workOrdRoutings.ForEach(c =>
{
c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID;
});
_workOrdRouting.Insert(workOrdRoutings);
}
if (workOrdDetails.Any())
{
workOrdDetails.ForEach(c =>
{
c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID;
});
_workOrdDetail.Insert(workOrdDetails);
}
//成品半成品取下周一开始+取供应提前期为结束时间
//原材料取第二天开始+取供应提前期为结束时间
//DOP运行资源检查每个原材料SKU的可用库存,当可用库存<=修正后ROP时,自动生成月度采购申请(Purchase request,PR46年月日4位流水号)=EOP;可用库存为没有被其他SO和PO占用的(合格原材料库存+在途库存);
var planList = _ic_item.GetListAsync().Result;
List prList = new List();
var numbers = ropModelList.Where(a => a.erp_cls == 3).Select(b => b.number).ToList();
var icItemList = _mysql_ic_item.GetListAsync(c => numbers.Contains(c.number)).Result;
var srm_pr_mains = _srm_pr_main.GetListAsync(x => icItemList.Select(p => p.Id).ToList().Contains(x.icitem_id.Value) && x.state != 0 && !x.IsDeleted && x.state != 4).Result;
var quarter_srm_pr_mains = srm_pr_mains.Where(s => s.pr_psend_date >= _CalcBomViewAppService.quarter_starttime && s.pr_psend_date < _CalcBomViewAppService.quarter_endtime).ToList();
ropModelList.Where(a => a.erp_cls == 3)?.ToList().ForEach(b =>
{
if (itemStock.First(c => c.ItemNumber == b.number).Qty < b.security_stock)
{
mo_srm_purchase supplier = null;
var plan = planList.Find(x => x.number == b.number);
var item = icItemList.Find(d => d.number == b.number);
var supplist = supplierList.Where(s => s.number == b.number).ToList();
decimal day = 0;
var plan_date = DateTime.Now.AddDays(1 + Convert.ToDouble(b.supply_leadtime));
//判断当前时间与交期还剩余多少天
var timesp = plan_date - DateTime.Now.Date;
//交期-生产时长-物料前处理周期
day = timesp.Days;
if (day > 0)
{
supplist = supplist.Where(s => s.lead_time.GetValueOrDefault() < day).ToList();
if (supplist.Any())
{
//TODO:走配额管理
List itemPrlist = quarter_srm_pr_mains.Where(s => s.icitem_id == item.Id).ToList();
if (itemPrlist.Any())
{
decimal qtyCount = itemPrlist.Sum(x => x.pr_aqty).GetValueOrDefault();
//按配额比例,计算使用哪个供应商。
List PrPurchaseDtoList = new List