瀏覽代碼

库存监控报表接口

Murphy 2 年之前
父節點
當前提交
bd3d1e4f60

+ 6 - 0
MicroServices/Business/Business.Application.Contracts/DOP/ISyncDOPAppService.cs

@@ -22,5 +22,11 @@ namespace Business.DOP
         /// <param name="id"></param>
         /// <returns></returns>
         Task<string> SyncPlatformFinishedProductMonitoringGK(List<PlatformInventoryDto> platformInventoryDtoList);
+
+        /// <summary>
+        /// 库存监控
+        /// </summary>
+        /// <returns></returns>
+        Task<string> InventoryMonitoring(InputDto input);
     }
 }

+ 150 - 0
MicroServices/Business/Business.Application.Contracts/Dto/InventoryMonitoringDto.cs

@@ -0,0 +1,150 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Business.Dto
+{
+    /// <summary>
+    /// 库存监控结果
+    /// </summary>
+    public class InventoryMonitoringDto
+    {
+        /// <summary>
+        /// 物料编码
+        /// </summary>
+        public string ItemNumber { get; set; }
+
+        /// <summary>
+        /// 补货周期
+        /// </summary>
+        public decimal ReplenishCycle { get; set; }
+
+        /// <summary>
+        /// 产品线
+        /// </summary>
+        public string ProLine { get; set; }
+
+        /// <summary>
+        /// 系列
+        /// </summary>
+        public string Series { get; set; }
+
+        /// <summary>
+        /// 规格型号
+        /// </summary>
+        public string Model { get; set; }
+
+        /// <summary>
+        /// 工厂库存
+        /// </summary>
+        public decimal FactoryInv { get; set; }
+
+        /// <summary>
+        /// 国科库存
+        /// </summary>
+        public decimal GKInv { get; set; }
+
+        /// <summary>
+        /// 海王库存
+        /// </summary>
+        public decimal HWInv { get; set; }
+
+        /// <summary>
+        /// 全域库存
+        /// </summary>
+        public decimal TotalInv { get; set; }
+
+        /// <summary>
+        /// T1月需求
+        /// </summary>
+        public decimal T1MonthlyDemand { get; set; }
+
+        /// <summary>
+        /// T1补货点
+        /// </summary>
+        public decimal ReplenishmentPoint { get; set; }
+
+        /// <summary>
+        /// 国科预估需求
+        /// </summary>
+        public decimal GKEstimatedDemand { get; set; }
+
+        /// <summary>
+        ///  海王预估需求
+        /// </summary>
+        public decimal HWEstimatedDemand { get; set; }
+
+        /// <summary>
+        /// T2总体需求
+        /// </summary>
+        public decimal T2TotalDemand { get; set; }
+
+        /// <summary>
+        /// 总终端需求
+        /// </summary>
+        public decimal TotalTerminalDemand { get; set; }
+
+        /// <summary>
+        /// 工厂覆盖平台月
+        /// </summary>
+        public decimal FactoryCoveragePlatformMonth { get; set; }
+
+        /// <summary>
+        /// 国科库存最高覆盖月
+        /// </summary>
+        public decimal GKCoverageMaxMonth { get; set; }
+
+        /// <summary>
+        /// 国科库存最低覆盖月
+        /// </summary>
+        public decimal GKCoverageMinMonth { get; set; }
+
+        /// <summary>
+        /// 国科库存覆盖月
+        /// </summary>
+        public decimal GKCoverageMonth { get; set; }
+
+        /// <summary>
+        /// 海王最高库存范围
+        /// </summary>
+        public decimal HWCoverageMaxMonth { get; set; }
+
+        /// <summary>
+        /// 海王最低库存范围
+        /// </summary>
+        public decimal HWCoverageMinMonth { get; set; }
+
+
+        /// <summary>
+        /// 海王库存覆盖月
+        /// </summary>
+        public decimal HWCoverageMonth { get; set; }
+
+        /// <summary>
+        /// 全域覆盖
+        /// </summary>
+        public decimal TotalCoverageMonth { get; set; }
+
+        /// <summary>
+        ///T1库存监控
+        /// </summary>
+        public string T1MonitoringResult { get; set; }
+
+        /// <summary>
+        ///国科库存监控
+        /// </summary>
+        public string GKMonitoringResult { get; set; }
+
+        /// <summary>
+        ///海王库存监控
+        /// </summary>
+        public string HWMonitoringResult { get; set; }
+
+        /// <summary>
+        ///推荐决策
+        /// </summary>
+        public string RecommendDecision { get; set; }
+    }
+}

+ 275 - 2
MicroServices/Business/Business.Application/DOP/SyncDOPAppService.cs

@@ -1,9 +1,12 @@
 using Business.Core.Utilities;
+using Business.Domain;
 using Business.Dto;
+using Business.EntityFrameworkCore.SqlRepositories;
 using Business.StructuredDB.WMS;
 using Newtonsoft.Json;
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Threading.Tasks;
 using Volo.Abp.Application.Services;
 using Volo.Abp.DependencyInjection;
@@ -26,6 +29,47 @@ namespace Business.DOP
         /// 平台库存表
         /// </summary>
         private readonly IRepository<WMS_PlatformInventory, long> _PlatformInventory;
+
+        /// <summary>
+        /// SAP库存表
+        /// </summary>
+        private readonly ISqlRepository<SAPInv> _sapInvRepository;
+
+        /// <summary>
+        /// SAP库存表
+        /// </summary>
+        private readonly ISqlRepository<ItemMaster> _itemMasterRepository;
+
+        /// <summary>
+        /// 国内终端预测
+        /// </summary>
+        private IRepository<DomesticTerminalFcst, long> _domesticTerminalFcst;
+
+        /// <summary>
+        /// 海外销售预测
+        /// </summary>
+        private IRepository<OverseasSaleFcst, long> _overseasSaleFcst;
+
+        /// <summary>
+        /// 标准物料规格型号设置表
+        /// </summary>
+        private IRepository<StandardItemModelSet, long> _standardItemModelSet;
+
+        private IRepository<PlatStockMonitorSetting, long> _platStockMonitorSetting;
+
+        private IRepository<YearDemandManagement, long> _yearDemandManagement;
+
+        private IRepository<ic_item, long> _ic_item;
+
+        /// <summary>
+        /// 平台预测收集
+        /// </summary>
+        private IRepository<PlatformFcstCollect, long> _platformFcstCollect;
+        /// <summary>
+        /// 节假日记录表
+        /// </summary>
+        private ISqlRepository<HolidayMaster> _holidayMaster;
+
         /// <summary>
         ///  雪花算法
         /// </summary>
@@ -34,6 +78,8 @@ namespace Business.DOP
         /// 事务
         /// </summary>
         private readonly IUnitOfWorkManager _unitOfWorkManager;
+
+        private readonly ICurrentTenant _currentTenant;
         #endregion
         #region 构造函数
         /// <summary>
@@ -42,12 +88,33 @@ namespace Business.DOP
         public SyncDOPAppService(
             IRepository<WMS_PlatformSpecificationComparison, long> PlatformSpecificationComparison,
             IRepository<WMS_PlatformInventory, long> PlatformInventory,
-             IUnitOfWorkManager unitOfWorkManager,
-        ICurrentTenant currentTenant
+            ISqlRepository<SAPInv> sapInvRepository,
+            IRepository<DomesticTerminalFcst, long> domesticTerminalFcst,
+            IRepository<OverseasSaleFcst, long> overseasSaleFcst,
+            IRepository<StandardItemModelSet, long> standardItemModelSet,
+            ISqlRepository<ItemMaster> itemMasterRepository,
+            IRepository<PlatStockMonitorSetting, long> platStockMonitorSetting,
+            IRepository<YearDemandManagement, long> yearDemandManagement,
+            IRepository<PlatformFcstCollect, long> platformFcstCollect,
+            ISqlRepository<HolidayMaster> holidayMaster,
+            IRepository<ic_item, long> ic_item,
+            IUnitOfWorkManager unitOfWorkManager,
+            ICurrentTenant currentTenant
             )
         {
             _PlatformSpecificationComparison = PlatformSpecificationComparison;
             _PlatformInventory = PlatformInventory;
+            _sapInvRepository = sapInvRepository;
+            _domesticTerminalFcst = domesticTerminalFcst;
+            _overseasSaleFcst = overseasSaleFcst;
+            _standardItemModelSet = standardItemModelSet;
+            _itemMasterRepository = itemMasterRepository;
+            _platStockMonitorSetting = platStockMonitorSetting;
+            _yearDemandManagement=yearDemandManagement;
+            _holidayMaster = holidayMaster;
+            _platformFcstCollect = platformFcstCollect;
+            _ic_item = ic_item;
+            _currentTenant = currentTenant;
             _unitOfWorkManager = unitOfWorkManager;
         }
         #endregion
@@ -130,5 +197,211 @@ namespace Business.DOP
             }
             return JsonConvert.SerializeObject("ok");
         }
+
+        /// <summary>
+        /// 库存监控数据报表接口
+        /// </summary>
+        /// <returns></returns>
+        public async Task<string> InventoryMonitoring(InputDto input)
+        {
+            List<InventoryMonitoringDto> inventoryMonitoringDtos= new List<InventoryMonitoringDto>();
+            var ItemModelSetList = _standardItemModelSet.GetListAsync(a => a.tenant_id == input.tenant_id && a.company_id == input.company_id && !a.IsDeleted).Result;
+            if (ItemModelSetList == null)
+            {
+                new NLogHelper("SyncDOPAppService").WriteLog("InventoryMonitoring", "库存数据不存在", _currentTenant.Id.ToString());
+                //throw new NotImplementedException("订单数据不存在!");
+                return "库存数据不存在";
+            }
+            ItemModelSetList.ForEach(a => 
+            {
+                inventoryMonitoringDtos.Add(new InventoryMonitoringDto { Model=a.Model, ItemNumber=a.ItemNumber, FactoryInv=0,GKInv=0,HWInv=0, ReplenishCycle=a.ReplenishCycle });
+            });
+            var ItemList = ItemModelSetList.Select(a => a.ItemNumber);
+            var modelList = ItemModelSetList.Select(a => a.Model);
+            var ItemInvList = _sapInvRepository.Select(a => ItemList.Contains(a.MATNR) && a.WERKS == input.factory_id.ToString());
+            int year = DateTime.Now.AddMonths(1).Year;
+            int month = DateTime.Now.AddMonths(1).Month;
+            string planMonth = $"{year}-01";
+            string planMonthCurrent = $"{year}-{DateTime.Now.AddMonths(1).ToString("MM")}";
+            var platformInvList = _PlatformInventory.GetListAsync(a => modelList.Contains(a.SpecificationModel) && a.tenant_id == input.tenant_id && a.factory_id == input.factory_id).Result;
+            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;
+            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);
+            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;
+            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;
+            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;
+            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;
+            inventoryMonitoringDtos.ForEach(a =>
+            {
+                //产品线和系列
+                var itemProdRange = yearDemandList.Find(b => b.Model == a.Model);
+                if (itemProdRange != null)
+                    a.ProLine = itemProdRange.ProdLine;
+                    a.Series= itemProdRange.ProdRange;
+
+                //工厂库存
+                var itemSap = ItemInvList.Find(b => b.MATNR == a.ItemNumber);
+                if(itemSap!=null)
+                    a.FactoryInv = itemSap.LABST.ToDecimal();
+                //国科库存
+                var platformInventoryGK=  platformInvList.Find(b => b.SpecificationModel == a.Model && b.Code== "HW0002");
+                if (platformInventoryGK != null)
+                    a.GKInv = platformInventoryGK.InventoryQuantity;
+                //海王库存
+                var platformInventoryHW = platformInvList.Find(b => b.SpecificationModel == a.Model && b.Code == "HW0001");
+                if (platformInventoryHW != null)
+                    a.HWInv = platformInventoryHW.InventoryQuantity;
+
+                //全域库存
+                a.TotalInv = a.FactoryInv + a.GKInv + a.HWInv;
+
+                //T1月需求
+                var t1 = domesticTerminalFcstList.Find(a => a.TypeEnum == 2);
+                if (t1 != null)
+                {
+                    a.T1MonthlyDemand = t1.Qty;
+                }
+                //T1补货点
+                decimal rop = 0.0m;
+                //获取当月天数
+                int days = DateTime.DaysInMonth(year, month);
+                //计算当前月的周末天数
+                int weeks = CalcWeekDays(days, DateTime.Now.AddDays(1 - DateTime.Now.Day).AddMonths(1));
+                //获取当前年月的节假日设置
+                var curHolidays = holidays.Where(p => p.Dated.Value.Year == DateTime.Now.AddMonths(1).Year && p.Dated.Value.Month == DateTime.Now.AddMonths(1).Month).ToList();
+                //当月工作天数
+                int workDays = days - weeks - curHolidays.Where(p => p.Ufld1 == "休假").Count() + curHolidays.Where(p => p.Ufld1 == "调班").Count();
+                decimal packQty = 1m;//最小包装单位
+                var curItem = items.FirstOrDefault(p => p.number == a.ItemNumber);
+                packQty = curItem == null ? 1 : (curItem.minpackqty.GetValueOrDefault() == 0.0m ? 1 : curItem.minpackqty.Value);
+                //rop = (需求量/月工作天数*补货周期)=>按照最小包装单位元整
+                rop = Math.Ceiling(a.T1MonthlyDemand / workDays * a.ReplenishCycle / packQty) * packQty;
+                a.ReplenishmentPoint = rop;
+
+                //国科预估需求
+                var gk = domesticTerminalFcstList.Find(a => a.TypeEnum == 5);
+                if (gk != null)
+                {
+                    a.GKEstimatedDemand = gk.Qty;
+                }
+                //海王预估需求
+                var hw = domesticTerminalFcstList.Find(a => a.TypeEnum == 4);
+                if (hw != null)
+                {
+                    a.HWEstimatedDemand = hw.Qty;
+                }
+                //T2总体需求
+                //a.TotalDemand = a.GKEstimatedDemand + a.HWEstimatedDemand;
+                var t2 = domesticTerminalFcstList.Find(a => a.TypeEnum == 3);
+                if (t2 != null)
+                {
+                    a.T2TotalDemand = t2.Qty;
+                }
+                //总终端需求
+                a.TotalTerminalDemand = a.T1MonthlyDemand + a.ReplenishmentPoint + a.GKEstimatedDemand + a.HWEstimatedDemand + a.T2TotalDemand;
+                //工厂平台覆盖月
+                a.FactoryCoveragePlatformMonth = a.FactoryInv / a.T1MonthlyDemand;
+                //国科库存最高最低覆盖月
+                var prodTypeGK=platformFcstCollectList?.Find(a => a.Model == a.Model && a.Platform == "国科");
+                if(prodTypeGK!=null)
+                {
+                    var prodTypeSettingGK = platStockMonitorSettingList?.Find(a => a.ProdType == prodTypeGK.ProdType && a.Platform == "国科");
+                    if(prodTypeSettingGK!=null)
+                    {
+                        a.GKCoverageMaxMonth = prodTypeSettingGK.MaxTimes;
+                        a.GKCoverageMinMonth = prodTypeSettingGK.MinTimes;
+                    }else
+                    {
+                        a.GKCoverageMaxMonth = 0;
+                        a.GKCoverageMinMonth = 0;
+                    }
+                }
+
+                //国科库存覆盖月
+                a.GKCoverageMonth = a.GKInv / a.GKEstimatedDemand;
+
+
+                //海王库存最高最低覆盖月
+                var prodTypeHW = platformFcstCollectList?.Find(a => a.Model == a.Model && a.Platform == "海王");
+                if (prodTypeHW != null)
+                {
+                    var prodTypeSettingHW = platStockMonitorSettingList?.Find(a => a.ProdType == prodTypeHW.ProdType && a.Platform == "海王");
+                    if(prodTypeSettingHW != null)
+                    {
+                        a.GKCoverageMaxMonth = prodTypeSettingHW.MaxTimes;
+                        a.GKCoverageMinMonth = prodTypeSettingHW.MinTimes;
+                    }else
+                    {
+                        a.GKCoverageMaxMonth = 0;
+                        a.GKCoverageMinMonth = 0;
+                    }
+                }
+
+
+                //海王库存覆盖月
+                a.HWCoverageMonth = a.HWInv / a.HWEstimatedDemand;
+                //全域覆盖
+                a.TotalCoverageMonth = a.TotalInv / a.TotalTerminalDemand;
+
+                //T1库存监控
+                if (a.FactoryInv < a.ReplenishmentPoint)
+                {
+                    a.T1MonitoringResult = "按照补货点补货";
+                }
+                else
+                {
+                    a.T1MonitoringResult = a.FactoryCoveragePlatformMonth > 6 ? "库存超出6个月阈值" : "正常覆盖范围";
+                }
+                //国科库存监控
+                a.GKMonitoringResult = a.GKCoverageMonth > a.GKCoverageMaxMonth ? "库存高于最高库存水位警戒" : a.GKCoverageMonth < a.GKCoverageMinMonth ? "库存低于最低库存水位,紧急补货" : "正常周转";
+                //海王库存监控
+                a.HWMonitoringResult = a.HWCoverageMonth > a.HWCoverageMaxMonth ? "库存高于最高库存水位警戒" : a.HWCoverageMonth < a.HWCoverageMinMonth ? "库存低于最低库存水位,紧急补货" : "正常周转";
+
+                //推荐决策
+                if (a.TotalCoverageMonth < 3)
+                {
+                    a.RecommendDecision = "紧急补货";
+                }
+                else 
+                if (a.TotalCoverageMonth < 6)
+                {
+                    a.RecommendDecision = "需要补货";
+                }
+                else 
+                if (a.TotalCoverageMonth < 9)
+                {
+                    a.RecommendDecision = "正常库存";
+                }
+                else 
+                if (a.TotalCoverageMonth < 24)
+                {
+                    a.RecommendDecision = "关注库存";
+                }
+                else
+                {
+                    a.RecommendDecision = "呆滞";
+                }
+            });
+            return JsonConvert.SerializeObject(inventoryMonitoringDtos);
+        }
+
+        /// <summary>
+        /// 计算当月有多少个周末
+        /// </summary>
+        /// <param name="days"></param>
+        /// <param name="startDay"></param>
+        /// <returns></returns>
+        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;
+        }
     }
 }

+ 2 - 0
MicroServices/Business/Business.EntityFrameworkCore/EntityFrameworkCore/DOP/BusinessDbContext.cs

@@ -211,6 +211,8 @@ namespace Business.EntityFrameworkCore
         /// </summary>
         public DbSet<WMS_PlatformInventory> WMS_PlatformInventory { get; set; }
 
+        public DbSet<WMS_PlatformSpecificationComparison> WMS_PlatformSpecificationComparison { get; set; }
+
         /// <summary>
         /// SAP¿â´æ±í
         /// </summary>

+ 1 - 1
MicroServices/Business/Business.Host/nlog.config

@@ -105,6 +105,6 @@
 		<logger name="Microsoft.*" maxlevel="Info" final="true" />
 		<logger name="System.Net.Http.*" maxlevel="Info" final="true" />
 
-		<logger name="*" minlevel="Info" writeTo="allfile,database" />
+		<logger name="*" minlevel="Trace" writeTo="allfile,database" />
 	</rules>
 </nlog>

+ 14 - 0
MicroServices/Business/Business.HttpApi/Controllers/DOP/DOPController.cs

@@ -49,5 +49,19 @@ namespace Business.Controllers.DOP
         {
             return await _DopAppService.SyncPlatformFinishedProductMonitoringGK(platformInventoryDtoList);
         }
+
+
+        /// <summary>
+        /// 库存监控数据报表
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        [HttpGet]
+        [Route("InventoryMonitoring")]
+        public async Task<string> InventoryMonitoring(InputDto input)
+        {
+            return await _DopAppService.InventoryMonitoring(input);
+        }
+
     }
 }