|
@@ -12,6 +12,7 @@ using System.Collections.Generic;
|
|
|
using System.Linq;
|
|
using System.Linq;
|
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.CompilerServices;
|
|
|
using System.Threading.Tasks;
|
|
using System.Threading.Tasks;
|
|
|
|
|
+using ThoughtWorks.QRCode.Geom;
|
|
|
using Volo.Abp.Application.Services;
|
|
using Volo.Abp.Application.Services;
|
|
|
using Volo.Abp.DependencyInjection;
|
|
using Volo.Abp.DependencyInjection;
|
|
|
using Volo.Abp.Domain.Repositories;
|
|
using Volo.Abp.Domain.Repositories;
|
|
@@ -112,6 +113,21 @@ namespace Business.SaleForecastManagement
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
private IRepository<MonthlyProdCapacity, long> _monthlyProdCapacity;
|
|
private IRepository<MonthlyProdCapacity, long> _monthlyProdCapacity;
|
|
|
|
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// 月度产能共识明细表
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ private IRepository<MonthlyProdCapacityDtl, long> _monthlyProdCapacityDtl;
|
|
|
|
|
+
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// SKU版本维护表
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ private IRepository<SkuVersionSet, long> _skuVersionSet;
|
|
|
|
|
+
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// 计划订单表
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ private IRepository<crm_planorder, long> _crm_planorder;
|
|
|
|
|
+
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// 雪花算法
|
|
/// 雪花算法
|
|
|
/// </summary>
|
|
/// </summary>
|
|
@@ -139,7 +155,10 @@ namespace Business.SaleForecastManagement
|
|
|
IRepository<YearDemandManagementHistory, long> yearDemandManagementHistory,
|
|
IRepository<YearDemandManagementHistory, long> yearDemandManagementHistory,
|
|
|
ISqlRepository<LocationDetail> locationDetail,
|
|
ISqlRepository<LocationDetail> locationDetail,
|
|
|
ISqlRepository<WorkOrdMaster> workOrdMaster,
|
|
ISqlRepository<WorkOrdMaster> workOrdMaster,
|
|
|
- IRepository<OverallDemandPlan, long> overallDemandPlan
|
|
|
|
|
|
|
+ IRepository<OverallDemandPlan, long> overallDemandPlan,
|
|
|
|
|
+ IRepository<MonthlyProdCapacityDtl, long> monthlyProdCapacityDtl,
|
|
|
|
|
+ IRepository<SkuVersionSet, long> skuVersionSet,
|
|
|
|
|
+ IRepository<crm_planorder, long> crm_planorder
|
|
|
)
|
|
)
|
|
|
{
|
|
{
|
|
|
_ic_item = ic_item;
|
|
_ic_item = ic_item;
|
|
@@ -159,6 +178,9 @@ namespace Business.SaleForecastManagement
|
|
|
_locationDetail = locationDetail;
|
|
_locationDetail = locationDetail;
|
|
|
_workOrdMaster = workOrdMaster;
|
|
_workOrdMaster = workOrdMaster;
|
|
|
_overallDemandPlan = overallDemandPlan;
|
|
_overallDemandPlan = overallDemandPlan;
|
|
|
|
|
+ _monthlyProdCapacityDtl = monthlyProdCapacityDtl;
|
|
|
|
|
+ _skuVersionSet= skuVersionSet;
|
|
|
|
|
+ _crm_planorder= crm_planorder;
|
|
|
}
|
|
}
|
|
|
#endregion
|
|
#endregion
|
|
|
|
|
|
|
@@ -397,7 +419,12 @@ namespace Business.SaleForecastManagement
|
|
|
#endregion
|
|
#endregion
|
|
|
|
|
|
|
|
//生成月度产能共识
|
|
//生成月度产能共识
|
|
|
- List<MonthlyProdCapacity> capacities = CapacityAnalysis(input, updates, planMons);
|
|
|
|
|
|
|
+ var capacityDto = CapacityAnalysis(input, updates, planMons);
|
|
|
|
|
+
|
|
|
|
|
+ //生成下一个月的补货计划
|
|
|
|
|
+ var nextMonPFcsts = platformFcsts.Where(p => p.PlanMonth == strN2).ToList();
|
|
|
|
|
+ var nextMonDFcsts = domesticFcst.Where(p => p.PlanMonth == strN2).ToList();
|
|
|
|
|
+ var replenishs = MonthlyReplenish(input, nextMonPFcsts, nextMonDFcsts, standards, items, holidays);
|
|
|
|
|
|
|
|
//保存数据
|
|
//保存数据
|
|
|
using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
|
|
using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
|
|
@@ -421,9 +448,14 @@ namespace Business.SaleForecastManagement
|
|
|
}
|
|
}
|
|
|
//回写年度生产大纲
|
|
//回写年度生产大纲
|
|
|
await _yearDemandManagement.UpdateManyAsync(updates);
|
|
await _yearDemandManagement.UpdateManyAsync(updates);
|
|
|
- //先删除产能共识
|
|
|
|
|
|
|
+ //先删除产能共识、产能共识明细
|
|
|
await _monthlyProdCapacity.HardDeleteAsync(p=>p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id);
|
|
await _monthlyProdCapacity.HardDeleteAsync(p=>p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id);
|
|
|
- await _monthlyProdCapacity.InsertManyAsync(capacities);
|
|
|
|
|
|
|
+ await _monthlyProdCapacityDtl.HardDeleteAsync(p => p.Year == input.year && p.Month == input.month && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id);
|
|
|
|
|
+ await _monthlyProdCapacity.InsertManyAsync(capacityDto.mains);
|
|
|
|
|
+ await _monthlyProdCapacityDtl.InsertManyAsync(capacityDto.details);
|
|
|
|
|
+ //生成下一月的补货计划
|
|
|
|
|
+ await _crm_planorder.HardDeleteAsync(p=>p.PlanMonth == strN1 && p.Source =="系统运算" && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id);
|
|
|
|
|
+ await _crm_planorder.InsertManyAsync(replenishs);
|
|
|
|
|
|
|
|
await unitOfWork.CompleteAsync();
|
|
await unitOfWork.CompleteAsync();
|
|
|
}
|
|
}
|
|
@@ -442,7 +474,7 @@ namespace Business.SaleForecastManagement
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
/// <param name="input"></param>
|
|
/// <param name="input"></param>
|
|
|
/// <returns></returns>
|
|
/// <returns></returns>
|
|
|
- public List<MonthlyProdCapacity> CapacityAnalysis(InputDto input,List<YearDemandManagement> yearDemands, List<string> planMons)
|
|
|
|
|
|
|
+ public MonthlyCapacityDto CapacityAnalysis(InputDto input,List<YearDemandManagement> yearDemands, List<string> planMons)
|
|
|
{
|
|
{
|
|
|
//1、获取数据
|
|
//1、获取数据
|
|
|
//1.1 根据规格型号获取物料数据
|
|
//1.1 根据规格型号获取物料数据
|
|
@@ -458,6 +490,9 @@ namespace Business.SaleForecastManagement
|
|
|
|
|
|
|
|
//月度产能共识表
|
|
//月度产能共识表
|
|
|
List<MonthlyProdCapacity> capacities = new List<MonthlyProdCapacity>();
|
|
List<MonthlyProdCapacity> capacities = new List<MonthlyProdCapacity>();
|
|
|
|
|
+ //月度产能共识明细表
|
|
|
|
|
+ List<MonthlyProdCapacityDtl> capacityDtls = new List<MonthlyProdCapacityDtl>();
|
|
|
|
|
+
|
|
|
//产线
|
|
//产线
|
|
|
List<string> lines = lineDtls.Select(p => p.Line).Distinct().ToList();
|
|
List<string> lines = lineDtls.Select(p => p.Line).Distinct().ToList();
|
|
|
foreach (var item in lines)
|
|
foreach (var item in lines)
|
|
@@ -489,10 +524,46 @@ namespace Business.SaleForecastManagement
|
|
|
dtl.AvailableTimes = dtl.DailyWorks * dtl.MonthWorks;
|
|
dtl.AvailableTimes = dtl.DailyWorks * dtl.MonthWorks;
|
|
|
//计算产线耗时
|
|
//计算产线耗时
|
|
|
var curLines = lineDtls.Where(p => p.Line == item).ToList();
|
|
var curLines = lineDtls.Where(p => p.Line == item).ToList();
|
|
|
- var line = curLines.OrderByDescending(p => p.Op).First();
|
|
|
|
|
- var curStands = standards.Where(p=> curLines.Select(m=>m.Part).Contains(p.ItemNumber)).ToList();
|
|
|
|
|
- var curDemands = yearDemands.Where(p => curStands.Select(m => m.Model).Contains(p.Model) && p.PlanMonth == pm).ToList();
|
|
|
|
|
- dtl.NeedWorks = line.Rate == 0 ? 0 : (Math.Ceiling(curDemands.Sum(p=>p.Qty) / line.Rate));
|
|
|
|
|
|
|
+ decimal sumTimes = 0.00m;
|
|
|
|
|
+ List<ProdLineDto> lineDtos = new List<ProdLineDto>();
|
|
|
|
|
+ foreach (var ld in curLines)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (lineDtos.Exists(p=>p.Part == ld.Part && p.Line == ld.Line))
|
|
|
|
|
+ {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ var curStand = standards.FirstOrDefault(p => p.ItemNumber == ld.Part);
|
|
|
|
|
+ if (curStand == null)
|
|
|
|
|
+ {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ var curDemands = yearDemands.Where(p => p.Model == curStand.Model && p.PlanMonth == pm).ToList();
|
|
|
|
|
+ var line = curLines.Where(p=>p.Part == ld.Part && p.Line == ld.Line).OrderByDescending(p => p.Op).First();
|
|
|
|
|
+ sumTimes += line.Rate == 0 ? 0 : (Math.Ceiling(curDemands.Sum(p => p.Qty) / line.Rate));
|
|
|
|
|
+
|
|
|
|
|
+ MonthlyProdCapacityDtl capacityDtl = new MonthlyProdCapacityDtl();
|
|
|
|
|
+ capacityDtl.Year = input.year;
|
|
|
|
|
+ capacityDtl.Month = input.month;
|
|
|
|
|
+ capacityDtl.PlanMonth = pm;
|
|
|
|
|
+ capacityDtl.ProdLine = item;
|
|
|
|
|
+ capacityDtl.Model = curStand.Model;
|
|
|
|
|
+ capacityDtl.Qty = curDemands.Sum(p => p.Qty);
|
|
|
|
|
+ capacityDtl.tenant_id = input.tenant_id;
|
|
|
|
|
+ capacityDtl.company_id = input.company_id;
|
|
|
|
|
+ capacityDtl.factory_id = input.factory_id;
|
|
|
|
|
+ capacityDtl.org_id = input.org_id;
|
|
|
|
|
+ capacityDtl.create_by = input.create_by;
|
|
|
|
|
+ capacityDtl.create_by_name = input.create_by_name;
|
|
|
|
|
+ capacityDtl.create_time = DateTime.Now;
|
|
|
|
|
+ capacityDtls.Add(capacityDtl);
|
|
|
|
|
+
|
|
|
|
|
+ lineDtos.Add(new ProdLineDto {
|
|
|
|
|
+ Part = ld.Part,
|
|
|
|
|
+ Line= ld.Line
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ dtl.NeedWorks = sumTimes;
|
|
|
dtl.ProdRate = 100;
|
|
dtl.ProdRate = 100;
|
|
|
dtl.Rate = dtl.AvailableTimes == 0 ? 0 : Math.Floor(dtl.NeedWorks / dtl.AvailableTimes * 100);
|
|
dtl.Rate = dtl.AvailableTimes == 0 ? 0 : Math.Floor(dtl.NeedWorks / dtl.AvailableTimes * 100);
|
|
|
dtl.IsOverTime = dtl.NeedWorks > dtl.AvailableTimes ? "是" : "否";
|
|
dtl.IsOverTime = dtl.NeedWorks > dtl.AvailableTimes ? "是" : "否";
|
|
@@ -507,9 +578,96 @@ namespace Business.SaleForecastManagement
|
|
|
capacities.Add(dtl);
|
|
capacities.Add(dtl);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- return capacities;
|
|
|
|
|
|
|
+ return new MonthlyCapacityDto{
|
|
|
|
|
+ mains = capacities,
|
|
|
|
|
+ details = capacityDtls
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// T1、平台自动补货
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ /// <param name="input"></param>
|
|
|
|
|
+ /// <param name="platformFcsts">平台预测</param>
|
|
|
|
|
+ /// <param name="domesticFcsts">T1预测</param>
|
|
|
|
|
+ /// <param name="standards">标准SKU设置</param>
|
|
|
|
|
+ /// <param name="items">物料</param>
|
|
|
|
|
+ /// <param name="holidays">节假日</param>
|
|
|
|
|
+ /// <returns></returns>
|
|
|
|
|
+ public List<crm_planorder> MonthlyReplenish(InputDto input, List<PlatformFcstCollect> platformFcsts, List<DomesticTerminalFcst> domesticFcsts, List<StandardItemModelSet> standards, List<ic_item> items, List<HolidayMaster> holidays)
|
|
|
|
|
+ {
|
|
|
|
|
+ List<crm_planorder> planorders = new List<crm_planorder>();
|
|
|
|
|
+ //获取T1、平台预测数据中规格型号对应的不同版本的物料编码
|
|
|
|
|
+ var T1Models = domesticFcsts.Select(p => p.Model).Distinct().ToList();
|
|
|
|
|
+ var PModels = platformFcsts.Select(p => p.Model).Distinct().ToList();
|
|
|
|
|
+ List<string> models = T1Models;
|
|
|
|
|
+ models.AddRange(PModels);
|
|
|
|
|
+ models = models.Distinct().ToList();
|
|
|
|
|
+ List<SkuVersionSet> skus = _skuVersionSet.GetListAsync(p=>models.Contains(p.Model) && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id).Result;
|
|
|
|
|
+ //获取库存
|
|
|
|
|
+ List<string> itemNums = skus.Select(p=>p.ItemNum).Distinct().ToList();
|
|
|
|
|
+ List<LocationDetail> locationDetails = _locationDetail.Select(p=> itemNums.Contains(p.ItemNum) && p.Domain == input.factory_id.ToString() && p.IsActive);
|
|
|
|
|
+ //计算T1补货
|
|
|
|
|
+ foreach (var item in T1Models)
|
|
|
|
|
+ {
|
|
|
|
|
+ //获取当前规格型号对应的预测数据
|
|
|
|
|
+ var curFcsts = domesticFcsts.Where(p=>p.Model == item).ToList();
|
|
|
|
|
+ //当前规格型号对应的库存数量
|
|
|
|
|
+ decimal sumQty = 0.00m;
|
|
|
|
|
+ //当前的物料版本
|
|
|
|
|
+ var curSkus = skus.Where(p => p.Model == item).ToList();
|
|
|
|
|
+ if (curSkus.Any())
|
|
|
|
|
+ {
|
|
|
|
|
+ sumQty = locationDetails.Where(p => curSkus.Select(p => p.ItemNum).Contains(p.ItemNum)).Sum(p => p.QtyOnHand);
|
|
|
|
|
+ }
|
|
|
|
|
+ //计算Rop
|
|
|
|
|
+ //当前规格型号对应标准SKU的最小包装单位、补货周期
|
|
|
|
|
+ var curStd = standards.FirstOrDefault(p => p.Model == item);
|
|
|
|
|
+ decimal packQty = 1m;//最小包装单位
|
|
|
|
|
+ decimal cycle = 0m;//补货周期
|
|
|
|
|
+ if (curStd != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ var curItem = items.FirstOrDefault(p => p.number == curStd.ItemNumber);
|
|
|
|
|
+ packQty = curItem == null ? 1 : (curItem.minpackqty.GetValueOrDefault() == 0.0m ? 1 : curItem.minpackqty.Value);
|
|
|
|
|
+ cycle = curStd.ReplenishCycle;
|
|
|
|
|
+ }
|
|
|
|
|
+ //TODO:获取成品库存、在制库存、灭菌库存,参与计算
|
|
|
|
|
+ //N+1月使用N+2月的再订货点参与计算
|
|
|
|
|
+ decimal rop = CalcRop(curFcsts[0].PlanMonth + "-01", curFcsts.Sum(p=>p.Qty), packQty, holidays, cycle);
|
|
|
|
|
+ if(sumQty < rop)
|
|
|
|
|
+ {
|
|
|
|
|
+ planorders.Add(new crm_planorder {
|
|
|
|
|
+ PlanMonth = curFcsts[0].PlanMonth,
|
|
|
|
|
+ Model = curFcsts[0].Model,
|
|
|
|
|
+ ItemNum = curStd?.ItemNumber,
|
|
|
|
|
+ ProdLine = curFcsts[0].ProdLine,
|
|
|
|
|
+ ProdType = "",
|
|
|
|
|
+ Qty = rop,
|
|
|
|
|
+ Type = "计划单-T1直发补货",
|
|
|
|
|
+ Source = "系统运算",
|
|
|
|
|
+ tenant_id = input.tenant_id,
|
|
|
|
|
+ company_id= input.company_id,
|
|
|
|
|
+ factory_id= input.factory_id,
|
|
|
|
|
+ org_id= input.org_id,
|
|
|
|
|
+ create_by= input.create_by,
|
|
|
|
|
+ create_by_name= input.create_by_name,
|
|
|
|
|
+ create_time = DateTime.Now
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ //计算平台补货
|
|
|
|
|
+ foreach (var item in PModels)
|
|
|
|
|
+ {
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ return planorders;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// 计算再订货点
|
|
/// 计算再订货点
|
|
|
/// </summary>
|
|
/// </summary>
|