Browse Source

产销协同、月度销售预测回写年度大纲

heteng 2 years ago
parent
commit
5586825add

+ 4 - 0
MicroServices/Business/Business.Application/BusinessApplicationAutoMapperProfile.cs

@@ -95,6 +95,10 @@ namespace Business
                .ForMember(d => d.Id, map => map.MapFrom(o => o.mysql_id));
             #endregion
 
+            #region 销售预测
+            CreateMap<YearDemandManagement, YearDemandManagementHistory>();
+            #endregion
+
             #region Bang
             CreateMap<BomChildExamineDto, b_bom_child_examine>();
 

+ 280 - 57
MicroServices/Business/Business.Application/SaleForecastManagement/MonthlyCapacityLoadAppService.cs

@@ -1,11 +1,16 @@
-using Business.Core.Utilities;
+using Azure.Identity;
+using Business.Core.Utilities;
 using Business.Domain;
 using Business.Dto;
 using Business.EntityFrameworkCore.SqlRepositories;
+using Business.ResourceExamineManagement.Dto;
 using Business.SaleForecast;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Spire.Pdf.General.Render.Decode.Jpeg2000.j2k.quantization;
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Runtime.CompilerServices;
 using System.Threading.Tasks;
 using Volo.Abp.Application.Services;
 using Volo.Abp.DependencyInjection;
@@ -76,6 +81,11 @@ namespace Business.SaleForecastManagement
         /// </summary>
         private IRepository<YearDemandManagement, long> _yearDemandManagement;
 
+        /// <summary>
+        /// 年度生产需求大纲历史记录
+        /// </summary>
+        private IRepository<YearDemandManagementHistory, long> _yearDemandManagementHistory;
+
         /// <summary>
         /// 国内终端预测
         /// </summary>
@@ -121,7 +131,8 @@ namespace Business.SaleForecastManagement
             IRepository<YearDemandManagement, long> yearDemandManagement,
             IRepository<DomesticTerminalFcst, long> domesticTerminalFcst,
             IRepository<OverseasSaleFcst, long> overseasSaleFcst,
-            IRepository<PlatformFcstCollect, long> platformFcstCollect
+            IRepository<PlatformFcstCollect, long> platformFcstCollect,
+            IRepository<YearDemandManagementHistory, long> yearDemandManagementHistory
             )
         {
             _ic_item = ic_item;
@@ -137,8 +148,9 @@ namespace Business.SaleForecastManagement
             _standardItemModelSet = standardItemModelSet;
             _yearDemandManagement= yearDemandManagement;
             _domesticTerminalFcst= domesticTerminalFcst;
-            _overallDemandPlanDtl= overallDemandPlanDtl;
+            _overseasSaleFcst = overseasSaleFcst;
             _platformFcstCollect= platformFcstCollect;
+            _yearDemandManagementHistory= yearDemandManagementHistory;
         }
         #endregion
 
@@ -263,25 +275,25 @@ namespace Business.SaleForecastManagement
         //    return "OK|发布成功!";
         //}
 
-        ///// <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;
-        //}
+        /// <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;
+        }
 
         /// <summary>
         /// 月度需求预测更新
@@ -291,66 +303,277 @@ namespace Business.SaleForecastManagement
         /// <exception cref="NotImplementedException"></exception>
         public async Task<string> DemandAnalysis(InputDto input)
         {
-            //1.0 获取年度生产需求大纲
-            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;
-            if (yearDemands.Count() == 0)
-            {
-                new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入" + input.year + "年年度生产需求数据后再操作!", _currentTenant.Id.ToString());
-                return "NO|请导入" + input.year + "年年度生产需求数据后再操作!";
-            }
+            //1.0 获取当前年年度生产需求大纲
+            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).ToList();
+            //1.0 获取下一年年度生产大纲
+            List<YearDemandManagement> nextYearDemands = _yearDemandManagement.GetListAsync(p => p.Year == (input.year+1) && 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).ToList();
+            //记录历史版本:当前年+下一年
+            var updateMonth = input.year.ToString() + "-" + input.month.ToString("00");
+            var histories = ObjectMapper.Map<List<YearDemandManagement>, List<YearDemandManagementHistory>>(yearDemands);
+            histories.ForEach(p => {
+                p.UpdateMonth = updateMonth;
+            });
+            var nextHistories = ObjectMapper.Map<List<YearDemandManagement>, List<YearDemandManagementHistory>>(nextYearDemands);
+            nextHistories.ForEach(p => {
+                p.UpdateMonth = updateMonth;
+            });
             //1.1、获取海外销售预测数据
             List<OverseasSaleFcst> overseasSales = _overseasSaleFcst.GetListAsync(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 && !p.IsDeleted).Result;
-            if (overseasSales.Count() == 0)
-            {
-                new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入"+input.year+"年"+input.month+"月海外预测数据后再操作!", _currentTenant.Id.ToString());
-                return "NO|请导入"+input.year+"年"+input.month+"月海外预测数据后再操作!";
-            }
             //1.2、获取平台预测收集数据
             List<PlatformFcstCollect> platformFcsts = _platformFcstCollect.GetListAsync(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 && !p.IsDeleted).Result;
-            if (platformFcsts.Count() == 0)
-            {
-                new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入" + input.year + "年" + input.month + "月平台需求预测数据后再操作!", _currentTenant.Id.ToString());
-                return "NO|请导入" + input.year + "年" + input.month + "月平台需求预测数据后再操作!";
-            }
             //1.3、获取国内终端预测-T1汇总数据
-            List<DomesticTerminalFcst> domesticFcst = _domesticTerminalFcst.GetListAsync(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 && !p.IsDeleted).Result;
-            if (domesticFcst.Count() == 0)
+            List<DomesticTerminalFcst> domesticFcst = _domesticTerminalFcst.GetListAsync(p =>p.TypeEnum == 2 && 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 && !p.IsDeleted).Result;
+            //1.4、根据年度生产大纲,获取规格型号对应的补货周期
+            List<string> allModels = yearDemands.Select(p=>p.Model).Distinct().ToList();
+            if (nextYearDemands.Any())
             {
-                new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入" + input.year + "年" + input.month + "月国内终端预测数据后再操作!", _currentTenant.Id.ToString());
-                return "NO|请导入" + input.year + "年" + input.month + "月国内终端预测数据后再操作!";
+                allModels.AddRange(nextYearDemands.Select(p => p.Model).ToList());
+                allModels = allModels.Distinct().ToList();
             }
-            //1.4、根据年度生产大纲,获取规格型号对应的补货周期
-            List<string> models = yearDemands.Select(p=>p.Model).Distinct().ToList();  
-            List<StandardItemModelSet> standards = _standardItemModelSet.GetListAsync(p=>models.Contains(p.Model) && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
-            //1.5、获取规格型号对应的标准SKU数据
+            List<StandardItemModelSet> standards = _standardItemModelSet.GetListAsync(p => allModels.Contains(p.Model) && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
+            //1.5、获取规格型号对应的标准SKU数据:获取最小包装单位
             List<string> itemNums = standards.Select(p=>p.ItemNumber).Distinct().ToList();
             List<ic_item> items = _ic_item.GetListAsync(p=> itemNums.Contains(p.number) && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id && !p.IsDeleted).Result;
+            //1.6、获取成品库存
+            //1.7、获取在制库存
+            //1.8、获取灭菌库存
+            //1.9、获取节假日设置
+            List<HolidayMaster> holidays = _holidayMaster.Select(p => (p.Dated.Value.Year == input.year || p.Dated.Value.Year == (input.year + 1)) && p.Domain == input.factory_id.ToString() && p.IsActive);
+
+            #region 数据校验
+            //1、校验当前年的年度生产大纲是否导入
+            if (!yearDemands.Any())
+            {
+                new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入" + input.year + "年的年度生产需求后再操作!", _currentTenant.Id.ToString());
+                return "NO|请导入" + input.year + "年的年度生产需求后再操作!";
+            }
+            //2、如果当前月份大于10,则需校验下一年的年度生产大纲
+            if (input.month > 10 && !nextYearDemands.Any())
+            {
+                new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入" + (input.year+1) + "年的年度生产需求后再操作!", _currentTenant.Id.ToString());
+                return "NO|请导入" + (input.year + 1) + "年的年度生产需求后再操作!";
+            }
+            //3、校验当前月份的海外销售预测是否导入
+            if (!overseasSales.Any())
+            {
+                new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入" + input.year + "年" + input.month + "月海外销售预测后再操作!", _currentTenant.Id.ToString());
+                return "NO|请导入" + input.year + "年" + input.month + "月海外销售预测后再操作!";
+            }
+            //4、校验当前月份的平台预测收集是否导入
+            if (!platformFcsts.Any())
+            {
+                new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入" + input.year + "年" + input.month + "月平台需求收集后再操作!", _currentTenant.Id.ToString());
+                return "NO|请导入" + input.year + "年" + input.month + "月平台需求收集后再操作!";
+            }
+            //5、校验当前月份的国内终端预测是否导入
+            if (!domesticFcst.Any())
+            {
+                new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "请导入" + input.year + "年" + input.month + "月国内终端预测后再操作!", _currentTenant.Id.ToString());
+                return "NO|请导入" + input.year + "年" + input.month + "月国内终端预测后再操作!";
+            }
+            //6、校验终端+平台导入的规格型号是否已维护标准SKU
+            if (allModels.Count() != standards.Count())
+            {
+                allModels.RemoveAll(standards.Select(p=>p.Model).ToList());
+                new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "规格型号【" + string.Join(",",allModels) + "】没有维护标准SKU,请维护后再操作!", _currentTenant.Id.ToString());
+                return "NO|规格型号【" + string.Join(",", allModels) + "】没有维护标准SKU,请维护后再操作!";
+            }
+            //7、校验是否已维护补货周期
+            var zeros = standards.Where(p => p.ReplenishCycle == 0).ToList();
+            if (zeros.Any())
+            {
+                new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "规格型号【" + string.Join(",", zeros.Select(p=>p.Model).ToList()) + "】没有维护补货周期,请维护后再操作!", _currentTenant.Id.ToString());
+                return "NO|规格型号【" + string.Join(",", zeros.Select(p => p.Model).ToList()) + "】没有维护补货周期,请维护后再操作!";
+            }
+            #endregion
 
-            //计算海外预测
+            //计算当前年月的N+1,N+2
+            int newYear = input.month == 12 ? input.year + 1 : input.year;
+            int newMonth = input.month == 12 ? 1 : input.month + 1;
+            string strN1 = newYear.ToString() + "-" + newMonth.ToString("00");
+            newYear = newMonth == 12 ? newYear + 1 : newYear;
+            newMonth = newMonth == 12 ? 1 : newMonth + 1;
+            string strN2 = newYear.ToString() + "-" + newMonth.ToString("00");
 
+            //需要回写的数据
+            List<YearDemandManagement> updates = new List<YearDemandManagement>();
+            #region 计算国内终端预测,回写年度生产大纲
+            //获取导入的T1、平台数据
+            List<string> gnModels = new List<string>();
+            if (domesticFcst.Any())
+            {
+                gnModels.AddRange(domesticFcst.Select(p => p.Model).ToList());
+            }
+            if (platformFcsts.Any())
+            {
+                gnModels.AddRange(platformFcsts.Select(p => p.Model).ToList());
+            }
+            gnModels = gnModels.Distinct().ToList();
+            foreach (var gnModel in gnModels)
+            {
+                //N+1月
+                YearDemandManagement monthN1 = new YearDemandManagement();
+                //N+2月
+                YearDemandManagement monthN2 = new YearDemandManagement();
+                //获取需要回写的数据
+                if (input.month < 11)
+                {
+                    monthN1 = yearDemands.FirstOrDefault(p => p.Area == "国内" && p.Model == gnModel && p.PlanMonth == strN1);
+                    monthN2 = yearDemands.FirstOrDefault(p => p.Area == "国内" && p.Model == gnModel && p.PlanMonth == strN2);
+                }
+                if (input.month == 11)
+                {
+                    monthN1 = yearDemands.FirstOrDefault(p => p.Area == "国内" && p.Model == gnModel && p.PlanMonth == strN1);
+                    monthN2 = nextYearDemands.FirstOrDefault(p => p.Area == "国内" && p.Model == gnModel && p.PlanMonth == strN2);
+                }
+                if (input.month == 12)
+                {
+                    monthN1 = nextYearDemands.FirstOrDefault(p => p.Area == "国内" && p.Model == gnModel && p.PlanMonth == strN1);
+                    monthN2 = nextYearDemands.FirstOrDefault(p => p.Area == "国内" && p.Model == gnModel && p.PlanMonth == strN2);
+                }
+                if (monthN1 == null || monthN2 == null)
+                {
+                    continue;
+                }
+                //T1
+                var sumT1N1 = domesticFcst.Where(p => p.Model == gnModel && p.PlanMonth == strN1).Sum(p=>p.Qty);
+                var sumT1N2 = domesticFcst.Where(p => p.Model == gnModel && p.PlanMonth == strN2).Sum(p => p.Qty);
+                //平台
+                var sumPN1 = platformFcsts.Where(p => p.Model == gnModel && p.PlanMonth == strN1).Sum(p => p.Qty);
+                var sumPN2 = platformFcsts.Where(p => p.Model == gnModel && p.PlanMonth == strN2).Sum(p => p.Qty);
+                //合计
+                var sumN1 = sumT1N1+ sumPN1;
+                var sumN2 = sumT1N2 + sumPN2;
+
+                //当前规格型号对应标准SKU的最小包装单位、补货周期
+                var curStd = standards.FirstOrDefault(p => p.Model == gnModel);
+                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(strN2+"-01", sumN2, packQty, holidays, cycle);
+                monthN1.Qty = sumN1 / 2 + sumN2 / 2 + rop - 0 - 0 - 0;
+                //N+2月使用本月的需求量,下一月的工作天数
+                rop = CalcRop(Convert.ToDateTime(strN2 + "-01").AddMonths(1).ToString("yyyy-MM-dd"), sumN2, packQty, holidays, cycle);
+                monthN2.Qty = sumN2 + rop - 0 - 0 - 0;
+                //负数置0
+                monthN1.Qty = monthN1.Qty < 0 ? 0m : monthN1.Qty;
+                monthN2.Qty = monthN2.Qty < 0 ? 0m : monthN2.Qty;
+                //记录需要回写的数据
+                updates.Add(monthN1);
+                updates.Add(monthN2);
+            }
+            #endregion
+
+            #region 海外销售预测,回写年度生产大纲
+            List<string> hwModels = overseasSales.Select(p => p.Model).Distinct().ToList();
+            foreach (var hwModel in hwModels)
+            {
+                //N+1月
+                YearDemandManagement monthN1 = new YearDemandManagement();
+                //N+2月
+                YearDemandManagement monthN2 = new YearDemandManagement();
+                //获取需要回写的数据
+                if (input.month < 11)
+                {
+                    monthN1 = yearDemands.FirstOrDefault(p => p.Area == "海外" && p.Model == hwModel && p.PlanMonth == strN1);
+                    monthN2 = yearDemands.FirstOrDefault(p => p.Area == "海外" && p.Model == hwModel && p.PlanMonth == strN2);
+                }
+                if (input.month == 11)
+                {
+                    monthN1 = yearDemands.FirstOrDefault(p => p.Area == "海外" && p.Model == hwModel && p.PlanMonth == strN1);
+                    monthN2 = nextYearDemands.FirstOrDefault(p => p.Area == "海外" && p.Model == hwModel && p.PlanMonth == strN2);
+                }
+                if (input.month == 12)
+                {
+                    monthN1 = nextYearDemands.FirstOrDefault(p => p.Area == "海外" && p.Model == hwModel && p.PlanMonth == strN1);
+                    monthN2 = nextYearDemands.FirstOrDefault(p => p.Area == "海外" && p.Model == hwModel && p.PlanMonth == strN2);
+                }
+                if (monthN1 == null || monthN2 == null) {
+                    continue;
+                }
+                var sumN1 = overseasSales.Where(p => p.Model == hwModel && p.PlanMonth == strN1).Sum(p => p.Qty);
+                var sumN2 = overseasSales.Where(p => p.Model == hwModel && p.PlanMonth == strN2).Sum(p => p.Qty);
+
+                //海外生产需求量=当月的50%+下一月的50%-成品库存-在制库存-灭菌库存
+                //TODO:获取成品库存、在制库存、灭菌库存,参与运算
+                //计算N+1月,N+2月
+                monthN1.Qty = sumN1 / 2 + sumN2 / 2 - 0 - 0 - 0;
+                monthN2.Qty = sumN2 - 0 - 0 - 0;
+                //负数置0
+                monthN1.Qty = monthN1.Qty < 0 ? 0m : monthN1.Qty;
+                monthN2.Qty = monthN2.Qty < 0 ? 0m : monthN2.Qty;
+                //记录需要回写的数据
+                updates.Add(monthN1);
+                updates.Add(monthN2);
+            }
+            #endregion
 
             //保存数据
             using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
             {
                 try
                 {
-                    ////先删除数据
-                    //_monthlyProdCapacityMain.Delete(p => p.tenant_id == input.tenant_id && p.factory_id == input.factory_id && p.Version.Contains(input.version.Substring(0, 7)));
-                    //_monthlyProdCapacityDtl.Delete(p => p.tenant_id == input.tenant_id && p.factory_id == input.factory_id && p.Version.Contains(input.version.Substring(0, 7)));
-
-                    ////插入数据
-                    //_monthlyProdCapacityMain.Insert(capacityMains);
-                    //_monthlyProdCapacityDtl.Insert(capacityDtls);
-                    //await unitOfWork.CompleteAsync();
+                    //判断是否存在当前年月的历史版本,不存在则插入
+                    var dbHistory =  _yearDemandManagementHistory.GetListAsync(p=>p.UpdateMonth == updateMonth && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id).Result;
+                    if (!dbHistory.Any())
+                    {
+                        await _yearDemandManagementHistory.InsertManyAsync(histories);
+                    }
+                    if (input.month > 10)
+                    {
+                        //判断是否存在下一年月的历史版本,不存在则插入
+                        dbHistory = _yearDemandManagementHistory.GetListAsync(p => p.UpdateMonth == updateMonth && p.tenant_id == input.tenant_id && p.company_id == input.company_id && p.factory_id == input.factory_id).Result;
+                        if (!dbHistory.Any())
+                        {
+                            await _yearDemandManagementHistory.InsertManyAsync(nextHistories);
+                        }
+                    }
+                    //回写年度生产大纲
+                    await _yearDemandManagement.UpdateManyAsync(updates);
+                    await unitOfWork.CompleteAsync();
                 }
                 catch (Exception e)
                 {
                     unitOfWork.Dispose();
-                    new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("CapacityAnalysis", "生成【" + input.year + "年" + input.month + "月】月度产能共识失败:" + e.Message, _currentTenant.Id.ToString());
+                    new NLogHelper("MonthlyCapacityLoadAppService").WriteLog("DemandAnalysis", "【" + input.year + "年" + input.month + "月】月度需求预测更新失败:" + e.Message, _currentTenant.Id.ToString());
                     return "NO|" + e.Message;
                 };
             }
             return "OK|发布成功!";
         }
+
+        /// <summary>
+        /// 计算再订货点
+        /// </summary>
+        /// <param name="planMonth">计划年月(yyyy-MM-dd)</param>
+        /// <param name="qty">需求量</param>
+        /// <param name="qty">最小包装数量</param>
+        /// <param name="holidays">节假日</param>
+        /// <param name="replenishCycle">补货周期</param>
+        /// <returns></returns>
+        private decimal CalcRop(string planMonth,decimal qty,decimal packQty,List<HolidayMaster> holidays,decimal replenishCycle)
+        {
+            decimal rop = 0.0m;
+            //获取当月天数
+            int year = Convert.ToInt16(planMonth.Substring(0, 4));
+            int month = Convert.ToInt16(planMonth.Substring(5, 2));
+            int days = DateTime.DaysInMonth(year, month);
+            //计算当前月的周末天数
+            int weeks = CalcWeekDays(days, Convert.ToDateTime(planMonth));
+            //获取当前年月的节假日设置
+            var curHolidays = holidays.Where(p => p.Dated.Value.Year == year && p.Dated.Value.Month == month).ToList();
+            //当月工作天数
+            int workDays = days - weeks - curHolidays.Where(p => p.Ufld1 == "休假").Count() + curHolidays.Where(p => p.Ufld1 == "调班").Count();
+            //rop = (需求量/月工作天数*补货周期)=>按照最小包装单位元整
+            rop = Math.Ceiling(qty / workDays * replenishCycle / packQty) * packQty;
+            return rop;
+        }
     }
 }

+ 1 - 1
MicroServices/Business/Business.Domain/StructuredDB/SaleFcst/DomesticTerminalFcst.cs

@@ -62,7 +62,7 @@ namespace Business.Domain
         /// 产品数量
         /// </summary>
         [Comment("产品数量")]
-        public decimal? Qty { get; set; }
+        public decimal Qty { get; set; }
 
         /// <summary>
         /// 排序编码

+ 1 - 1
MicroServices/Business/Business.Domain/StructuredDB/SaleFcst/OverseasSaleFcst.cs

@@ -56,7 +56,7 @@ namespace Business.Domain
         /// 产品数量
         /// </summary>
         [Comment("产品数量")]
-        public decimal? Qty { get; set; }
+        public decimal Qty { get; set; }
 
         /// <summary>
         /// 排序编码

+ 1 - 1
MicroServices/Business/Business.Domain/StructuredDB/SaleFcst/PlatformFcstCollect.cs

@@ -56,7 +56,7 @@ namespace Business.Domain
         /// 产品数量
         /// </summary>
         [Comment("产品数量")]
-        public decimal? Qty { get; set; }
+        public decimal Qty { get; set; }
 
         /// <summary>
         /// 排序编码

+ 7 - 1
MicroServices/Business/Business.Domain/StructuredDB/SaleFcst/YearDemandManagementHistory.cs

@@ -13,9 +13,15 @@ namespace Business.Domain
     /// 年度生产需求管理历史表
     /// </summary>
     [Comment("年度生产需求管理表")]
-    [Index(nameof(Year), nameof(Area), nameof(ProdLine),nameof(ProdRange), nameof(Line),nameof(Model),nameof(PlanMonth),nameof(tenant_id), nameof(company_id),nameof(factory_id), IsUnique = true)]
+    [Index(nameof(UpdateMonth),nameof(Year), nameof(Area), nameof(ProdLine),nameof(ProdRange), nameof(Line),nameof(Model),nameof(PlanMonth),nameof(tenant_id), nameof(company_id),nameof(factory_id), IsUnique = true)]
     public class YearDemandManagementHistory : BaseEntity
     {
+        /// <summary>
+        /// 更新年月
+        /// </summary>
+        [Comment("更新年月")]
+        public string UpdateMonth { get; set; }
+
         /// <summary>
         /// 年
         /// </summary>