AnnualProductionOutlineAppService.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. using Business.Core.Enum;
  2. using Business.Core.Utilities;
  3. using Business.Domain;
  4. using Business.Dto;
  5. using Business.EntityFrameworkCore.SqlRepositories;
  6. using Business.SaleForecast;
  7. using Business.StructuredDB.SaleFcst;
  8. using Business.StructuredDB.WMS;
  9. using NetTopologySuite.Algorithm;
  10. using RazorEngine;
  11. using Spire.Pdf.General.Render.Decode.Jpeg2000.j2k.wavelet.synthesis;
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Linq;
  15. using System.Text;
  16. using System.Threading.Tasks;
  17. using Volo.Abp.Application.Dtos;
  18. using Volo.Abp.Application.Services;
  19. using Volo.Abp.DependencyInjection;
  20. using Volo.Abp.Domain.Repositories;
  21. using Volo.Abp.MultiTenancy;
  22. using Volo.Abp.Uow;
  23. using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
  24. namespace Business.SaleForecastManagement
  25. {
  26. public class AnnualProductionOutlineAppService : ApplicationService, ITransientDependency, IAnnualProductionOutlineAppService
  27. {
  28. #region 服务
  29. /// <summary>
  30. /// 工作单元
  31. /// </summary>
  32. private readonly IUnitOfWorkManager _unitOfWorkManager;
  33. /// <summary>
  34. /// 日志
  35. /// </summary>
  36. private readonly ICurrentTenant _currentTenant;
  37. /// <summary>
  38. /// 年度销售预测
  39. /// </summary>
  40. private IRepository<YearDemandManagement, long> _yearDemandManagement;
  41. /// <summary>
  42. /// 年度销售预测历史记录
  43. /// </summary>
  44. private IRepository<YearDemandManagementHistory, long> _yearDemandManagementHistory;
  45. /// <summary>
  46. /// 年度生产大纲
  47. /// </summary>
  48. private IRepository<AnnualProductionOutline, long> _annualProductionOutline;
  49. /// <summary>
  50. /// 生产线明细
  51. /// </summary>
  52. private ISqlRepository<ProdLineDetail> _prodLineDetail;
  53. /// <summary>
  54. /// 标准工艺流程表
  55. /// </summary>
  56. private ISqlRepository<RoutingOpDetail> _routingOpDetail;
  57. /// <summary>
  58. /// 库存表
  59. /// </summary>
  60. private ISqlRepository<LocationDetail> _locationDetail;
  61. /// <summary>
  62. /// 平台库存表
  63. /// </summary>
  64. private readonly IRepository<WMS_PlatformInventory, long> _PlatformInventory;
  65. /// <summary>
  66. /// 雪花算法
  67. /// </summary>
  68. SnowFlake help = new SnowFlake();
  69. #endregion
  70. #region 构造函数
  71. /// <summary>
  72. /// 构造函数
  73. /// </summary>
  74. public AnnualProductionOutlineAppService(
  75. IUnitOfWorkManager unitOfWorkManager,
  76. ICurrentTenant currentTenant,
  77. IRepository<YearDemandManagement, long> yearDemandManagement,
  78. IRepository<AnnualProductionOutline, long> annualProductionOutline,
  79. IRepository<YearDemandManagementHistory, long> yearDemandManagementHistory,
  80. ISqlRepository<ProdLineDetail> prodLineDetail,
  81. IRepository<WMS_PlatformInventory, long> PlatformInventory,
  82. ISqlRepository<RoutingOpDetail> routingOpDetail,
  83. ISqlRepository<LocationDetail> locationDetail
  84. )
  85. {
  86. _unitOfWorkManager = unitOfWorkManager;
  87. _currentTenant = currentTenant;
  88. _PlatformInventory = PlatformInventory;
  89. _prodLineDetail = prodLineDetail;
  90. _routingOpDetail = routingOpDetail;
  91. _locationDetail = locationDetail;
  92. _yearDemandManagement = yearDemandManagement;
  93. _yearDemandManagementHistory = yearDemandManagementHistory;
  94. _annualProductionOutline = annualProductionOutline;
  95. }
  96. #endregion
  97. /// <summary>
  98. /// 生成年度生产大纲
  99. /// </summary>
  100. /// <param name="input"></param>
  101. /// <returns></returns>
  102. /// <exception cref="NotImplementedException"></exception>
  103. public async Task<string> SaveAnnualProductionOutline(InputDto input)
  104. {
  105. //获取当前导入或修改数据
  106. 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();
  107. //标准工艺路径表
  108. List<RoutingOpDetail> routingOps = _routingOpDetail.Select(p => yearDemands.Select(m => m.SAPItemNumber).Contains(p.RoutingCode) && p.Domain == input.factory_id.ToString() && p.IsActive);
  109. var routingOpList = routingOps.Where(x => x.Descr == "组装").ToList();
  110. //生产线明细表
  111. 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();
  112. List<LocationDetail> locations = _locationDetail.Select(x => yearDemands.Select(m => m.SAPItemNumber).Contains(x.ItemNum) && x.Domain == input.factory_id.ToString() && x.IsActive).ToList();
  113. //平台库存
  114. 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;
  115. //取上一个月发货出库记录
  116. //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));
  117. //在制 -- 工单计划中的数量 工单数量-完成数=生产中的在制
  118. //年度生产大纲实体
  119. List<AnnualProductionOutline> annualProductionOutlines = new List<AnnualProductionOutline>();
  120. List<YearDemandManagement> frontYearDemand = new List<YearDemandManagement>();
  121. foreach (var item in yearDemands)
  122. {
  123. var routingOp = routingOps.Where(x => x.RoutingCode == item.SAPItemNumber).ToList();
  124. var Assembly = routingOp.Where(x => x.Descr == "组装").FirstOrDefault();
  125. var HeatSealing = routingOp.Where(x => x.Descr == "热封").FirstOrDefault();
  126. var Packaging = routingOp.Where(x => x.Descr == "包装").FirstOrDefault();
  127. var prodLine = prodLines.Where(x => x.Part == item.SAPItemNumber).OrderBy(x => x.Sequence).FirstOrDefault();
  128. //不同库位库存数量
  129. var locationList = locations.Where(x => x.ItemNum == item.SAPItemNumber).ToList();
  130. var platformInvs = platformInvList.Where(x => x.SAPItemNumber == item.SAPItemNumber).ToList();
  131. var QtySum = yearDemands.Where(x => x.SAPItemNumber == item.SAPItemNumber).ToList();
  132. //排产批量:(AVG(1 - 12月销售预测)/ 100 )=(0.45 = 1 小数向上取整) *100 = 100
  133. var pcpl = Math.Ceiling(QtySum.Sum(p => p.Qty) / QtySum.Count()) * 100;
  134. //库存合计 + 在制+已发货
  135. var locationSum = (locationList.Count == 0 ? 0 : locationList.Sum(x => x.QtyOnHand)) + (platformInvs.Count == 0 ? 0 : platformInvs.Sum(x => x.InventoryQuantity));
  136. //if (annualProductionOutlines.Count > 0)
  137. //{
  138. //前面N个月的生产数量
  139. var frontQtySum = annualProductionOutlines.Sum(x => x.Qty);
  140. var num = (locationSum + frontQtySum) - frontYearDemand.Sum(m => m.Qty) - item.Qty / 2;
  141. if (num < 0)
  142. {
  143. num = pcpl * Math.Ceiling((-(locationSum + frontQtySum)) + frontYearDemand.Sum(m => m.Qty) + item.Qty / 2);
  144. }
  145. // }
  146. //生产数量:3月为例子,(库存和前2月生产数量)-(前2个月销售预测数据)-当月销售预测数据 / 2 < 0 else 排产批量 *((-库存合计数量 + 前2个月销售预测数量 + 当月销售预测数量 / 2)/ 批量排产)
  147. //生成年度生产大纲
  148. AnnualProductionOutline annualProductionOutline = new AnnualProductionOutline();
  149. //TODO:取值
  150. annualProductionOutline.Year = item.Year;
  151. annualProductionOutline.Area = item.Area;
  152. annualProductionOutline.ProdLine = item.ProdLine;
  153. annualProductionOutline.ProdRange = item.ProdRange;
  154. annualProductionOutline.WorkshopLine = prodLine == null ? "" : prodLine.Line;
  155. annualProductionOutline.SAPItemNumber = item.SAPItemNumber;
  156. annualProductionOutline.Model = item.Model;
  157. annualProductionOutline.Languages = item.Languages;
  158. annualProductionOutline.PlanMonth = item.PlanMonth;
  159. annualProductionOutline.Qty = num;
  160. annualProductionOutline.StandardHours = (Assembly == null ? 0 : Assembly.RunTime) + (HeatSealing == null ? 0 : HeatSealing.RunTime) + (Packaging == null ? 0 : Packaging.RunTime);
  161. //组装热封包装工时乘以数量 =单月工时
  162. annualProductionOutline.AssemblyHours = Assembly == null ? 0 : Assembly.RunTime * num;
  163. annualProductionOutline.HeatSealingHours = HeatSealing == null ? 0 : HeatSealing.RunTime * num;
  164. annualProductionOutline.PackagingHours = Packaging == null ? 0 : Packaging.RunTime * num;
  165. annualProductionOutline.Totalhours = annualProductionOutline.AssemblyHours + annualProductionOutline.HeatSealingHours + annualProductionOutline.Totalhours;
  166. annualProductionOutline.OrderNum = item.OrderNum;
  167. annualProductionOutlines.Add(annualProductionOutline);
  168. frontYearDemand.Add(item);
  169. }
  170. //保存数据
  171. using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
  172. {
  173. try
  174. {
  175. await _annualProductionOutline.InsertManyAsync(annualProductionOutlines);
  176. await unitOfWork.CompleteAsync();
  177. }
  178. catch (Exception e)
  179. {
  180. unitOfWork.Dispose();
  181. new NLogHelper("AnnualProductionOutlineAppService").WriteLog("SaveAnnualProductionOutline", "【" + input.year + "年" + "】月度需求预测更新失败:" + e.Message, _currentTenant.Id.ToString());
  182. return "NO|" + e.Message;
  183. };
  184. }
  185. return "OK";
  186. }
  187. }
  188. }