SyncDOPAppService.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. using Business.Core.Utilities;
  2. using Business.Domain;
  3. using Business.Dto;
  4. using Business.EntityFrameworkCore.SqlRepositories;
  5. using Business.StructuredDB.WMS;
  6. using Newtonsoft.Json;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Threading.Tasks;
  11. using Volo.Abp.Application.Services;
  12. using Volo.Abp.DependencyInjection;
  13. using Volo.Abp.Domain.Repositories;
  14. using Volo.Abp.MultiTenancy;
  15. using Volo.Abp.Uow;
  16. using IUnitOfWorkManager = Volo.Abp.Uow.IUnitOfWorkManager;
  17. namespace Business.DOP
  18. {
  19. //DOP
  20. public class SyncDOPAppService : ApplicationService, ISyncDOPAppService, ITransientDependency
  21. {
  22. #region 服务
  23. /// <summary>
  24. /// 平台规格型号对照表
  25. /// </summary>
  26. private readonly IRepository<WMS_PlatformSpecificationComparison, long> _PlatformSpecificationComparison;
  27. /// <summary>
  28. /// 平台库存表
  29. /// </summary>
  30. private readonly IRepository<WMS_PlatformInventory, long> _PlatformInventory;
  31. /// <summary>
  32. /// SAP库存表
  33. /// </summary>
  34. private readonly ISqlRepository<SAPInv> _sapInvRepository;
  35. /// <summary>
  36. /// SAP库存表
  37. /// </summary>
  38. private readonly ISqlRepository<ItemMaster> _itemMasterRepository;
  39. /// <summary>
  40. /// 国内终端预测
  41. /// </summary>
  42. private IRepository<DomesticTerminalFcst, long> _domesticTerminalFcst;
  43. /// <summary>
  44. /// 海外销售预测
  45. /// </summary>
  46. private IRepository<OverseasSaleFcst, long> _overseasSaleFcst;
  47. /// <summary>
  48. /// 标准物料规格型号设置表
  49. /// </summary>
  50. private IRepository<StandardItemModelSet, long> _standardItemModelSet;
  51. private IRepository<PlatStockMonitorSetting, long> _platStockMonitorSetting;
  52. private IRepository<YearDemandManagement, long> _yearDemandManagement;
  53. private IRepository<ic_item, long> _ic_item;
  54. /// <summary>
  55. /// 平台预测收集
  56. /// </summary>
  57. private IRepository<PlatformFcstCollect, long> _platformFcstCollect;
  58. /// <summary>
  59. /// 节假日记录表
  60. /// </summary>
  61. private ISqlRepository<HolidayMaster> _holidayMaster;
  62. /// <summary>
  63. /// 雪花算法
  64. /// </summary>
  65. SnowFlake snowFlake = new SnowFlake();
  66. /// <summary>
  67. /// 事务
  68. /// </summary>
  69. private readonly IUnitOfWorkManager _unitOfWorkManager;
  70. private readonly ICurrentTenant _currentTenant;
  71. #endregion
  72. #region 构造函数
  73. /// <summary>
  74. /// 构造函数
  75. /// </summary>
  76. public SyncDOPAppService(
  77. IRepository<WMS_PlatformSpecificationComparison, long> PlatformSpecificationComparison,
  78. IRepository<WMS_PlatformInventory, long> PlatformInventory,
  79. ISqlRepository<SAPInv> sapInvRepository,
  80. IRepository<DomesticTerminalFcst, long> domesticTerminalFcst,
  81. IRepository<OverseasSaleFcst, long> overseasSaleFcst,
  82. IRepository<StandardItemModelSet, long> standardItemModelSet,
  83. ISqlRepository<ItemMaster> itemMasterRepository,
  84. IRepository<PlatStockMonitorSetting, long> platStockMonitorSetting,
  85. IRepository<YearDemandManagement, long> yearDemandManagement,
  86. IRepository<PlatformFcstCollect, long> platformFcstCollect,
  87. ISqlRepository<HolidayMaster> holidayMaster,
  88. IRepository<ic_item, long> ic_item,
  89. IUnitOfWorkManager unitOfWorkManager,
  90. ICurrentTenant currentTenant
  91. )
  92. {
  93. _PlatformSpecificationComparison = PlatformSpecificationComparison;
  94. _PlatformInventory = PlatformInventory;
  95. _sapInvRepository = sapInvRepository;
  96. _domesticTerminalFcst = domesticTerminalFcst;
  97. _overseasSaleFcst = overseasSaleFcst;
  98. _standardItemModelSet = standardItemModelSet;
  99. _itemMasterRepository = itemMasterRepository;
  100. _platStockMonitorSetting = platStockMonitorSetting;
  101. _yearDemandManagement=yearDemandManagement;
  102. _holidayMaster = holidayMaster;
  103. _platformFcstCollect = platformFcstCollect;
  104. _ic_item = ic_item;
  105. _currentTenant = currentTenant;
  106. _unitOfWorkManager = unitOfWorkManager;
  107. }
  108. #endregion
  109. /// <summary>
  110. /// 海王平台成品监控
  111. /// </summary>
  112. /// <returns></returns>
  113. /// <exception cref="NotImplementedException"></exception>
  114. public async Task<string> SyncPlatformFinishedProductMonitoringHW(List<PlatformInventoryDto> platformInventoryDtoList)
  115. {
  116. var ret = SavePlatformFinishedProductMonitoringAsync(platformInventoryDtoList, 1);
  117. return await ret;
  118. }
  119. /// <summary>
  120. /// 国科平台成品监控
  121. /// </summary>
  122. /// <returns></returns>
  123. /// <exception cref="NotImplementedException"></exception>
  124. public async Task<string> SyncPlatformFinishedProductMonitoringGK(List<PlatformInventoryDto> platformInventoryDtoList)
  125. {
  126. var ret = SavePlatformFinishedProductMonitoringAsync(platformInventoryDtoList, 2);
  127. return await ret;
  128. }
  129. /// <summary>
  130. /// 保存库存信息
  131. /// </summary>
  132. /// <param name="platformInventoryDtoList"></param>
  133. /// <param name="type">1海王,2国科</param>
  134. public async Task<string> SavePlatformFinishedProductMonitoringAsync(List<PlatformInventoryDto> platformInventoryDtoList, int type)
  135. {
  136. if (platformInventoryDtoList.Count == 0)
  137. {
  138. return JsonConvert.SerializeObject("成品库存为空!");
  139. }
  140. List<WMS_PlatformInventory> platformInventoryInsert = new List<WMS_PlatformInventory>();
  141. List<WMS_PlatformInventory> platformInventoryDel;
  142. if (type == 1)
  143. {
  144. platformInventoryDel = _PlatformInventory.GetListAsync(x => x.Code == "HW0001").Result;
  145. }
  146. else
  147. {
  148. platformInventoryDel = _PlatformInventory.GetListAsync(x => x.Code == "HW0002").Result;
  149. }
  150. foreach (var item in platformInventoryDtoList)
  151. {
  152. WMS_PlatformInventory platformInventory = new WMS_PlatformInventory();
  153. platformInventory.GenerateNewId(snowFlake.NextId());
  154. platformInventory.Location = item.Location;
  155. platformInventory.SpecificationModel = item.SpecificationModel;
  156. platformInventory.BatchNumber = item.BatchNumber;
  157. platformInventory.InventoryQuantity = item.InventoryQuantity.GetValueOrDefault();
  158. platformInventory.PeriodOfValidity = item.PeriodOfValidity.GetValueOrDefault();
  159. if (type == 1)
  160. {
  161. platformInventory.Code = "HW0001";
  162. }
  163. else
  164. {
  165. platformInventory.Code = "GK0001";
  166. }
  167. platformInventoryInsert.Add(platformInventory);
  168. }
  169. using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
  170. {
  171. try
  172. {
  173. //先删后插
  174. await _PlatformInventory.DeleteManyAsync(platformInventoryDel);
  175. await _PlatformInventory.InsertManyAsync(platformInventoryInsert);
  176. await unitOfWork.CompleteAsync();
  177. }
  178. catch (Exception e)
  179. {
  180. new NLogHelper("SyncDOPAppService").WriteLog("PlatformFinishedProductMonitoringAsyncMerge", "接口异常:" + e.Message);
  181. unitOfWork.Dispose();
  182. return JsonConvert.SerializeObject(e.Message);
  183. }
  184. }
  185. return JsonConvert.SerializeObject("ok");
  186. }
  187. /// <summary>
  188. /// 库存监控数据报表接口
  189. /// </summary>
  190. /// <returns></returns>
  191. public async Task<string> InventoryMonitoring(InputDto input)
  192. {
  193. List<InventoryMonitoringDto> inventoryMonitoringDtos= new List<InventoryMonitoringDto>();
  194. var ItemModelSetList = _standardItemModelSet.GetListAsync(a => a.tenant_id == input.tenant_id && a.company_id == input.company_id && !a.IsDeleted).Result;
  195. if (ItemModelSetList == null)
  196. {
  197. new NLogHelper("SyncDOPAppService").WriteLog("InventoryMonitoring", "库存数据不存在", _currentTenant.Id.ToString());
  198. //throw new NotImplementedException("订单数据不存在!");
  199. return "库存数据不存在";
  200. }
  201. ItemModelSetList.ForEach(a =>
  202. {
  203. inventoryMonitoringDtos.Add(new InventoryMonitoringDto { Model=a.Model, ItemNumber=a.ItemNumber, FactoryInv=0,GKInv=0,HWInv=0, ReplenishCycle=a.ReplenishCycle });
  204. });
  205. var ItemList = ItemModelSetList.Select(a => a.ItemNumber);
  206. var modelList = ItemModelSetList.Select(a => a.Model);
  207. var ItemInvList = _sapInvRepository.Select(a => ItemList.Contains(a.MATNR) && a.WERKS == input.factory_id.ToString());
  208. int year = DateTime.Now.AddMonths(1).Year;
  209. int month = DateTime.Now.AddMonths(1).Month;
  210. string planMonth = $"{year}-01";
  211. string planMonthCurrent = $"{year}-{DateTime.Now.AddMonths(1).ToString("MM")}";
  212. var platformInvList = _PlatformInventory.GetListAsync(a => modelList.Contains(a.SpecificationModel) && a.tenant_id == input.tenant_id && a.factory_id == input.factory_id).Result;
  213. var yearDemandList= _yearDemandManagement.GetListAsync(a=>a.Year== year && a.PlanMonth == planMonth && a.tenant_id== input.tenant_id && a.company_id == input.company_id && !a.IsDeleted).Result;
  214. List<HolidayMaster> holidays = _holidayMaster.Select(p => (p.Dated.Value.Year == year || p.Dated.Value.Year == (year + 1)) && p.Domain == input.factory_id.ToString() && p.IsActive);
  215. List<ic_item> items = _ic_item.GetListAsync(p => ItemList.Contains(p.number) && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
  216. var platformFcstCollectList= _platformFcstCollect.GetListAsync(p=>p.PlanMonth== planMonthCurrent && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
  217. var platStockMonitorSettingList = _platStockMonitorSetting.GetListAsync(p => p.PlanMonth == planMonthCurrent && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
  218. var domesticTerminalFcstList = _domesticTerminalFcst.GetListAsync(p => p.PlanMonth == planMonthCurrent && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
  219. inventoryMonitoringDtos.ForEach(a =>
  220. {
  221. //产品线和系列
  222. var itemProdRange = yearDemandList.Find(b => b.Model == a.Model);
  223. if (itemProdRange != null)
  224. a.ProLine = itemProdRange.ProdLine;
  225. a.Series= itemProdRange.ProdRange;
  226. //工厂库存
  227. var itemSap = ItemInvList.Find(b => b.MATNR == a.ItemNumber);
  228. if(itemSap!=null)
  229. a.FactoryInv = itemSap.LABST.ToDecimal();
  230. //国科库存
  231. var platformInventoryGK= platformInvList.Find(b => b.SpecificationModel == a.Model && b.Code== "HW0002");
  232. if (platformInventoryGK != null)
  233. a.GKInv = platformInventoryGK.InventoryQuantity;
  234. //海王库存
  235. var platformInventoryHW = platformInvList.Find(b => b.SpecificationModel == a.Model && b.Code == "HW0001");
  236. if (platformInventoryHW != null)
  237. a.HWInv = platformInventoryHW.InventoryQuantity;
  238. //全域库存
  239. a.TotalInv = a.FactoryInv + a.GKInv + a.HWInv;
  240. //T1月需求
  241. var t1 = domesticTerminalFcstList.Find(a => a.TypeEnum == 2);
  242. if (t1 != null)
  243. {
  244. a.T1MonthlyDemand = t1.Qty;
  245. }
  246. //T1补货点
  247. decimal rop = 0.0m;
  248. //获取当月天数
  249. int days = DateTime.DaysInMonth(year, month);
  250. //计算当前月的周末天数
  251. int weeks = CalcWeekDays(days, DateTime.Now.AddDays(1 - DateTime.Now.Day).AddMonths(1));
  252. //获取当前年月的节假日设置
  253. var curHolidays = holidays.Where(p => p.Dated.Value.Year == DateTime.Now.AddMonths(1).Year && p.Dated.Value.Month == DateTime.Now.AddMonths(1).Month).ToList();
  254. //当月工作天数
  255. int workDays = days - weeks - curHolidays.Where(p => p.Ufld1 == "休假").Count() + curHolidays.Where(p => p.Ufld1 == "调班").Count();
  256. decimal packQty = 1m;//最小包装单位
  257. var curItem = items.FirstOrDefault(p => p.number == a.ItemNumber);
  258. packQty = curItem == null ? 1 : (curItem.minpackqty.GetValueOrDefault() == 0.0m ? 1 : curItem.minpackqty.Value);
  259. //rop = (需求量/月工作天数*补货周期)=>按照最小包装单位元整
  260. rop = Math.Ceiling(a.T1MonthlyDemand / workDays * a.ReplenishCycle / packQty) * packQty;
  261. a.ReplenishmentPoint = rop;
  262. //国科预估需求
  263. var gk = domesticTerminalFcstList.Find(a => a.TypeEnum == 5);
  264. if (gk != null)
  265. {
  266. a.GKEstimatedDemand = gk.Qty;
  267. }
  268. //海王预估需求
  269. var hw = domesticTerminalFcstList.Find(a => a.TypeEnum == 4);
  270. if (hw != null)
  271. {
  272. a.HWEstimatedDemand = hw.Qty;
  273. }
  274. //T2总体需求
  275. //a.TotalDemand = a.GKEstimatedDemand + a.HWEstimatedDemand;
  276. var t2 = domesticTerminalFcstList.Find(a => a.TypeEnum == 3);
  277. if (t2 != null)
  278. {
  279. a.T2TotalDemand = t2.Qty;
  280. }
  281. //总终端需求
  282. a.TotalTerminalDemand = a.T1MonthlyDemand + a.ReplenishmentPoint + a.GKEstimatedDemand + a.HWEstimatedDemand + a.T2TotalDemand;
  283. //工厂平台覆盖月
  284. a.FactoryCoveragePlatformMonth = a.FactoryInv / a.T1MonthlyDemand;
  285. //国科库存最高最低覆盖月
  286. var prodTypeGK=platformFcstCollectList?.Find(a => a.Model == a.Model && a.Platform == "国科");
  287. if(prodTypeGK!=null)
  288. {
  289. var prodTypeSettingGK = platStockMonitorSettingList?.Find(a => a.ProdType == prodTypeGK.ProdType && a.Platform == "国科");
  290. if(prodTypeSettingGK!=null)
  291. {
  292. a.GKCoverageMaxMonth = prodTypeSettingGK.MaxTimes;
  293. a.GKCoverageMinMonth = prodTypeSettingGK.MinTimes;
  294. }else
  295. {
  296. a.GKCoverageMaxMonth = 0;
  297. a.GKCoverageMinMonth = 0;
  298. }
  299. }
  300. //国科库存覆盖月
  301. a.GKCoverageMonth = a.GKInv / a.GKEstimatedDemand;
  302. //海王库存最高最低覆盖月
  303. var prodTypeHW = platformFcstCollectList?.Find(a => a.Model == a.Model && a.Platform == "海王");
  304. if (prodTypeHW != null)
  305. {
  306. var prodTypeSettingHW = platStockMonitorSettingList?.Find(a => a.ProdType == prodTypeHW.ProdType && a.Platform == "海王");
  307. if(prodTypeSettingHW != null)
  308. {
  309. a.GKCoverageMaxMonth = prodTypeSettingHW.MaxTimes;
  310. a.GKCoverageMinMonth = prodTypeSettingHW.MinTimes;
  311. }else
  312. {
  313. a.GKCoverageMaxMonth = 0;
  314. a.GKCoverageMinMonth = 0;
  315. }
  316. }
  317. //海王库存覆盖月
  318. a.HWCoverageMonth = a.HWInv / a.HWEstimatedDemand;
  319. //全域覆盖
  320. a.TotalCoverageMonth = a.TotalInv / a.TotalTerminalDemand;
  321. //T1库存监控
  322. if (a.FactoryInv < a.ReplenishmentPoint)
  323. {
  324. a.T1MonitoringResult = "按照补货点补货";
  325. }
  326. else
  327. {
  328. a.T1MonitoringResult = a.FactoryCoveragePlatformMonth > 6 ? "库存超出6个月阈值" : "正常覆盖范围";
  329. }
  330. //国科库存监控
  331. a.GKMonitoringResult = a.GKCoverageMonth > a.GKCoverageMaxMonth ? "库存高于最高库存水位警戒" : a.GKCoverageMonth < a.GKCoverageMinMonth ? "库存低于最低库存水位,紧急补货" : "正常周转";
  332. //海王库存监控
  333. a.HWMonitoringResult = a.HWCoverageMonth > a.HWCoverageMaxMonth ? "库存高于最高库存水位警戒" : a.HWCoverageMonth < a.HWCoverageMinMonth ? "库存低于最低库存水位,紧急补货" : "正常周转";
  334. //推荐决策
  335. if (a.TotalCoverageMonth < 3)
  336. {
  337. a.RecommendDecision = "紧急补货";
  338. }
  339. else
  340. if (a.TotalCoverageMonth < 6)
  341. {
  342. a.RecommendDecision = "需要补货";
  343. }
  344. else
  345. if (a.TotalCoverageMonth < 9)
  346. {
  347. a.RecommendDecision = "正常库存";
  348. }
  349. else
  350. if (a.TotalCoverageMonth < 24)
  351. {
  352. a.RecommendDecision = "关注库存";
  353. }
  354. else
  355. {
  356. a.RecommendDecision = "呆滞";
  357. }
  358. });
  359. return JsonConvert.SerializeObject(inventoryMonitoringDtos);
  360. }
  361. /// <summary>
  362. /// 计算当月有多少个周末
  363. /// </summary>
  364. /// <param name="days"></param>
  365. /// <param name="startDay"></param>
  366. /// <returns></returns>
  367. private int CalcWeekDays(int days, DateTime startDay)
  368. {
  369. int sumDays = 0;
  370. for (int i = 0; i < days; i++)
  371. {
  372. int weekDays = (int)startDay.AddDays(i).DayOfWeek;
  373. if (weekDays == 0 || weekDays == 6)
  374. {
  375. sumDays++;
  376. }
  377. }
  378. return sumDays;
  379. }
  380. }
  381. }