|
|
@@ -0,0 +1,198 @@
|
|
|
+using Business.Core.Enum;
|
|
|
+using Business.Core.Utilities;
|
|
|
+using Business.Domain;
|
|
|
+using Business.Dto;
|
|
|
+using Business.EntityFrameworkCore.SqlRepositories;
|
|
|
+using Business.SaleForecast;
|
|
|
+using Business.StructuredDB.SaleFcst;
|
|
|
+using Business.StructuredDB.WMS;
|
|
|
+using NetTopologySuite.Algorithm;
|
|
|
+using RazorEngine;
|
|
|
+using Spire.Pdf.General.Render.Decode.Jpeg2000.j2k.wavelet.synthesis;
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Linq;
|
|
|
+using System.Text;
|
|
|
+using System.Threading.Tasks;
|
|
|
+using Volo.Abp.Application.Dtos;
|
|
|
+using Volo.Abp.Application.Services;
|
|
|
+using Volo.Abp.DependencyInjection;
|
|
|
+using Volo.Abp.Domain.Repositories;
|
|
|
+using Volo.Abp.MultiTenancy;
|
|
|
+using Volo.Abp.Uow;
|
|
|
+using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
|
|
|
+
|
|
|
+namespace Business.SaleForecastManagement
|
|
|
+{
|
|
|
+ public class AnnualProductionOutlineAppService : ApplicationService, ITransientDependency, IAnnualProductionOutlineAppService
|
|
|
+ {
|
|
|
+ #region 服务
|
|
|
+ /// <summary>
|
|
|
+ /// 工作单元
|
|
|
+ /// </summary>
|
|
|
+ private readonly IUnitOfWorkManager _unitOfWorkManager;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 日志
|
|
|
+ /// </summary>
|
|
|
+ private readonly ICurrentTenant _currentTenant;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 年度销售预测
|
|
|
+ /// </summary>
|
|
|
+ private IRepository<YearDemandManagement, long> _yearDemandManagement;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 年度销售预测历史记录
|
|
|
+ /// </summary>
|
|
|
+ private IRepository<YearDemandManagementHistory, long> _yearDemandManagementHistory;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 年度生产大纲
|
|
|
+ /// </summary>
|
|
|
+ private IRepository<AnnualProductionOutline, long> _annualProductionOutline;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 生产线明细
|
|
|
+ /// </summary>
|
|
|
+ private ISqlRepository<ProdLineDetail> _prodLineDetail;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 标准工艺流程表
|
|
|
+ /// </summary>
|
|
|
+ private ISqlRepository<RoutingOpDetail> _routingOpDetail;
|
|
|
+ /// <summary>
|
|
|
+ /// 库存表
|
|
|
+ /// </summary>
|
|
|
+ private ISqlRepository<LocationDetail> _locationDetail;
|
|
|
+ /// <summary>
|
|
|
+ /// 平台库存表
|
|
|
+ /// </summary>
|
|
|
+ private readonly IRepository<WMS_PlatformInventory, long> _PlatformInventory;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 雪花算法
|
|
|
+ /// </summary>
|
|
|
+ SnowFlake help = new SnowFlake();
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region 构造函数
|
|
|
+ /// <summary>
|
|
|
+ /// 构造函数
|
|
|
+ /// </summary>
|
|
|
+ public AnnualProductionOutlineAppService(
|
|
|
+
|
|
|
+ IUnitOfWorkManager unitOfWorkManager,
|
|
|
+ ICurrentTenant currentTenant,
|
|
|
+ IRepository<YearDemandManagement, long> yearDemandManagement,
|
|
|
+ IRepository<AnnualProductionOutline, long> annualProductionOutline,
|
|
|
+ IRepository<YearDemandManagementHistory, long> yearDemandManagementHistory,
|
|
|
+ ISqlRepository<ProdLineDetail> prodLineDetail,
|
|
|
+ IRepository<WMS_PlatformInventory, long> PlatformInventory,
|
|
|
+ ISqlRepository<RoutingOpDetail> routingOpDetail,
|
|
|
+ ISqlRepository<LocationDetail> locationDetail
|
|
|
+ )
|
|
|
+ {
|
|
|
+ _unitOfWorkManager = unitOfWorkManager;
|
|
|
+ _currentTenant = currentTenant;
|
|
|
+ _PlatformInventory = PlatformInventory;
|
|
|
+ _prodLineDetail = prodLineDetail;
|
|
|
+ _routingOpDetail = routingOpDetail;
|
|
|
+ _locationDetail = locationDetail;
|
|
|
+ _yearDemandManagement = yearDemandManagement;
|
|
|
+ _yearDemandManagementHistory = yearDemandManagementHistory;
|
|
|
+ _annualProductionOutline = annualProductionOutline;
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ /// <summary>
|
|
|
+ /// 生成年度生产大纲
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="input"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ /// <exception cref="NotImplementedException"></exception>
|
|
|
+ public async Task<string> SaveAnnualProductionOutline(InputDto input)
|
|
|
+ {
|
|
|
+ //获取当前导入或修改数据
|
|
|
+ List<YearDemandManagement> yearDemands = _yearDemandManagement.GetListAsync(p => p.Year == input.year && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result.OrderBy(p => p.OrderNum).ThenBy(o => o.PlanMonth).ToList();
|
|
|
+ //标准工艺路径表
|
|
|
+ List<RoutingOpDetail> routingOps = _routingOpDetail.Select(p => yearDemands.Select(m => m.SAPItemNumber).Contains(p.RoutingCode) && p.Domain == input.factory_id.ToString() && p.IsActive);
|
|
|
+ var routingOpList = routingOps.Where(x => x.Descr == "组装").ToList();
|
|
|
+ //生产线明细表
|
|
|
+ List<ProdLineDetail> prodLines = _prodLineDetail.Select(p => yearDemands.Select(m => m.SAPItemNumber).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<LocationDetail> locations = _locationDetail.Select(x => yearDemands.Select(m => m.SAPItemNumber).Contains(x.ItemNum) && x.Domain == input.factory_id.ToString() && x.IsActive).ToList();
|
|
|
+ //平台库存
|
|
|
+ var platformInvList = _PlatformInventory.GetListAsync(a => yearDemands.Select(m => m.SAPItemNumber).Contains(a.SAPItemNumber) && a.tenant_id == input.tenant_id && a.factory_id == input.factory_id).Result;
|
|
|
+ //取上一个月发货出库记录
|
|
|
+ //IEnumerable<ASNBOLShipperDetail> shipList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.RealQty > 0 && planItemList.Contains(a.ContainerItem)).Where(s => s.ShipDate >= getMonthStartTime(-1) && s.ShipDate <= getMonthEndTime(-1));
|
|
|
+ //在制 -- 工单计划中的数量 工单数量-完成数=生产中的在制
|
|
|
+ //年度生产大纲实体
|
|
|
+ List<AnnualProductionOutline> annualProductionOutlines = new List<AnnualProductionOutline>();
|
|
|
+ List<YearDemandManagement> frontYearDemand = new List<YearDemandManagement>();
|
|
|
+ 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();
|
|
|
+ var QtySum = yearDemands.Where(x => x.SAPItemNumber == item.SAPItemNumber).ToList();
|
|
|
+ //排产批量:(AVG(1 - 12月销售预测)/ 100 )=(0.45 = 1 小数向上取整) *100 = 100
|
|
|
+ var pcpl = Math.Ceiling(QtySum.Sum(p => p.Qty) / QtySum.Count()) * 100;
|
|
|
+ //库存合计 + 在制+已发货
|
|
|
+ var locationSum = (locationList.Count == 0 ? 0 : locationList.Sum(x => x.QtyOnHand)) + (platformInvs.Count == 0 ? 0 : platformInvs.Sum(x => x.InventoryQuantity));
|
|
|
+ //if (annualProductionOutlines.Count > 0)
|
|
|
+ //{
|
|
|
+ //前面N个月的生产数量
|
|
|
+ var frontQtySum = annualProductionOutlines.Sum(x => x.Qty);
|
|
|
+ var num = (locationSum + frontQtySum) - frontYearDemand.Sum(m => m.Qty) - item.Qty / 2;
|
|
|
+ if (num < 0)
|
|
|
+ {
|
|
|
+ num = pcpl * Math.Ceiling((-(locationSum + frontQtySum)) + frontYearDemand.Sum(m => m.Qty) + item.Qty / 2);
|
|
|
+ }
|
|
|
+ // }
|
|
|
+ //生产数量:3月为例子,(库存和前2月生产数量)-(前2个月销售预测数据)-当月销售预测数据 / 2 < 0 else 排产批量 *((-库存合计数量 + 前2个月销售预测数量 + 当月销售预测数量 / 2)/ 批量排产)
|
|
|
+ //生成年度生产大纲
|
|
|
+ AnnualProductionOutline annualProductionOutline = new AnnualProductionOutline();
|
|
|
+ //TODO:取值
|
|
|
+ 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 = num;
|
|
|
+ annualProductionOutline.StandardHours = (Assembly == null ? 0 : Assembly.RunTime) + (HeatSealing == null ? 0 : HeatSealing.RunTime) + (Packaging == null ? 0 : Packaging.RunTime);
|
|
|
+ //组装热封包装工时乘以数量 =单月工时
|
|
|
+ annualProductionOutline.AssemblyHours = Assembly == null ? 0 : Assembly.RunTime * num;
|
|
|
+ annualProductionOutline.HeatSealingHours = HeatSealing == null ? 0 : HeatSealing.RunTime * num;
|
|
|
+ annualProductionOutline.PackagingHours = Packaging == null ? 0 : Packaging.RunTime * num;
|
|
|
+ annualProductionOutline.Totalhours = annualProductionOutline.AssemblyHours + annualProductionOutline.HeatSealingHours + annualProductionOutline.Totalhours;
|
|
|
+ annualProductionOutline.OrderNum = item.OrderNum;
|
|
|
+ annualProductionOutlines.Add(annualProductionOutline);
|
|
|
+ frontYearDemand.Add(item);
|
|
|
+ }
|
|
|
+ //保存数据
|
|
|
+ using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ await _annualProductionOutline.InsertManyAsync(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";
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|