|
|
@@ -7,6 +7,7 @@ using Business.EntityFrameworkCore;
|
|
|
using Business.EntityFrameworkCore.SqlRepositories;
|
|
|
using Business.PriorityManagement;
|
|
|
using Business.ResourceExamineManagement.Dto;
|
|
|
+using Business.StructuredDB.SaleFcst;
|
|
|
using Business.StructuredDB.WMS;
|
|
|
using EFCore.BulkExtensions;
|
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
@@ -347,6 +348,18 @@ namespace Business.ResourceExamineManagement
|
|
|
/// </summary>
|
|
|
public List<HolidayMaster> holidays = new List<HolidayMaster>();
|
|
|
private readonly IUnitOfWorkManager _unitOfWorkManager;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 补货模型
|
|
|
+ /// </summary>
|
|
|
+ private IRepository<ReplenishmentModel, long> _replenishmentModel;
|
|
|
+ private IRepository<DomesticTerminalFcst, long> _domesticTerminalFcst;
|
|
|
+ private ISqlRepository<ASNBOLShipperDetail> _ASNBOLShipperDetail;
|
|
|
+ private IRepository<StandardItemModelSet, long> _standardItemModelSet;
|
|
|
+ private ISqlRepository<InvTransHist> _invTransHist;
|
|
|
+ private ISqlRepository<SAPInv> _SAPInv;
|
|
|
+ private IRepository<srm_purchase, long> _srmPurchase;
|
|
|
+ private ISqlRepository<MonthlyShipmentPlan> _monthlyShipmentPlan;
|
|
|
#endregion
|
|
|
|
|
|
#region 构造函数
|
|
|
@@ -440,6 +453,14 @@ namespace Business.ResourceExamineManagement
|
|
|
ISqlRepository<ItemPackMaster> itemPackMaster,
|
|
|
ISqlRepository<GeneralizedCodeMaster> generalizedCodeMaster,
|
|
|
ISqlRepository<ScheduleResultOpMaster> scheduleResultOpMaster,
|
|
|
+ IRepository<ReplenishmentModel, long> replenishmentModel,
|
|
|
+ IRepository<DomesticTerminalFcst, long> domesticTerminalFcst,
|
|
|
+ ISqlRepository<ASNBOLShipperDetail> ASNBOLShipperDetail,
|
|
|
+ IRepository<StandardItemModelSet, long> standardItemModelSet,
|
|
|
+ ISqlRepository<InvTransHist> invTransHist,
|
|
|
+ ISqlRepository<SAPInv> SAPInv,
|
|
|
+ ISqlRepository<MonthlyShipmentPlan> monthlyShipmentPlan,
|
|
|
+ IRepository<srm_purchase, long> srmPurchase,
|
|
|
IUnitOfWorkManager unitOfWorkManager
|
|
|
)
|
|
|
{
|
|
|
@@ -525,6 +546,14 @@ namespace Business.ResourceExamineManagement
|
|
|
_generalizedCodeMaster = generalizedCodeMaster;
|
|
|
_unitOfWorkManager = unitOfWorkManager;
|
|
|
_scheduleResultOpMaster = scheduleResultOpMaster;
|
|
|
+ _replenishmentModel = replenishmentModel;
|
|
|
+ _domesticTerminalFcst = domesticTerminalFcst;
|
|
|
+ _standardItemModelSet = standardItemModelSet;
|
|
|
+ _invTransHist = invTransHist;
|
|
|
+ _SAPInv = SAPInv;
|
|
|
+ _monthlyShipmentPlan = monthlyShipmentPlan;
|
|
|
+ _srmPurchase = srmPurchase;
|
|
|
+ _businessDbContext = businessDbContext;
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
@@ -3864,5 +3893,695 @@ namespace Business.ResourceExamineManagement
|
|
|
}
|
|
|
_productExamineAppService.CalcSuggestTime(sentrys, kittingTimes, icitemlist);
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ public async Task<string> WeekPlan(InputDto input)
|
|
|
+ {
|
|
|
+
|
|
|
+ //1.获取补货模型全局参数
|
|
|
+ ReplenishmentDto replenishmentDto = GetROPParam();
|
|
|
+
|
|
|
+ //到了配置的更新时间才更新
|
|
|
+ if (DateTime.Now.Day != replenishmentDto.SaleFcstEntryDate)
|
|
|
+ return "不在更新时间日期";
|
|
|
+
|
|
|
+
|
|
|
+ //获取月度发货计划
|
|
|
+ string planMonth = $"{DateTime.Now.AddMonths(1).Year}-{DateTime.Now.AddMonths(months: 1).Month}";
|
|
|
+ var planList = _monthlyShipmentPlan.Select(a => a.PlanMonth == planMonth && !a.IsDeleted);
|
|
|
+ var monthPlanList = ObjectMapper.Map<List<MonthlyShipmentPlan>, List<MonthlyShipmentPlanDto>>(planList);
|
|
|
+ var itemList = _ic_item.GetListAsync(a => planList.Select(p => p.SAPItemNumber).Contains(a.number) && a.tenant_id == input.tenant_id && a.company_id == input.company_id && !a.IsDeleted).Result;
|
|
|
+ var mesItemList = _itemMaster.Select(a => planList.Select(p => p.SAPItemNumber).Contains(a.ItemNum) && a.Domain == input.factory_id.ToString() && a.IsActive);
|
|
|
+ var srm_purchaseList = _srmPurchase.GetListAsync(a => planList.Select(p => p.SAPItemNumber).Contains(a.number) && a.tenant_id == input.tenant_id && a.company_id == input.company_id && !a.IsDeleted).Result;
|
|
|
+ //获取补货模型前一个周期和未来N个周期的数据
|
|
|
+ var ropModelList = _replenishmentModel.GetListAsync(a => a.zero_based_seqno >= 0 && a.zero_based_seqno <= replenishmentDto.UpdateWeeks).Result;
|
|
|
+ //发货计划物料列表
|
|
|
+ List<string> planItemList = planList?.Select(a => a.SAPItemNumber).ToList();
|
|
|
+ //补货模型物料列表
|
|
|
+ List<string> ropItemList = ropModelList?.Where(c => c.zero_based_seqno == 0).Select(a => a.number).ToList();
|
|
|
+ //第一次算或者新品物料列表
|
|
|
+ List<string> nohistoryItemList = planItemList.Except(ropItemList).ToList();
|
|
|
+ var sapItemInv = _SAPInv.Select(a => nohistoryItemList.Contains(a.MATNR) && a.WERKS == input.factory_id.ToString());
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ //取上一个月发货出库记录
|
|
|
+ var shipList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.ShipDate >= getMonthStartTime(-1) && a.ShipDate <= getMonthEndTime(-1) && a.RealQty > 0 && planItemList.Contains(a.ContainerItem));
|
|
|
+
|
|
|
+ //按照物料分组统计出货金额
|
|
|
+ var itemGroup = shipList.GroupBy(p => p.ContainerItem)
|
|
|
+ .Select(p => new ASNBOLShipperDetail
|
|
|
+ {
|
|
|
+ QtyToShip = p.Sum(a => a.QtyToShip),
|
|
|
+ ContainerItem = p.Key
|
|
|
+ }).ToList();
|
|
|
+
|
|
|
+ monthPlanList?.ForEach(a =>
|
|
|
+ {
|
|
|
+ //物料属性:0.配置类 1.自制 2.委外加工 3.外购 4.虚拟件
|
|
|
+ a.erp_cls = itemList.Find(s => s.number == a.SAPItemNumber)?.erp_cls;
|
|
|
+ if (mesItemList.Find(s => s.ItemNum == a.SAPItemNumber) != null)
|
|
|
+ {
|
|
|
+ a.stock_turnover = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber).StockTurnOver;
|
|
|
+ a.PLT = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber)?.PurLT;
|
|
|
+ a.IsLongPeriod = a.PLT >= replenishmentDto.LongPeriodDay;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ a.stock_turnover = 4;
|
|
|
+ }
|
|
|
+ if (srm_purchaseList.Find(s => s.number == a.SAPItemNumber) != null)
|
|
|
+ {
|
|
|
+ a.PLT = srm_purchaseList.Find(s => s.number == a.SAPItemNumber).lead_time;
|
|
|
+ a.IsLongPeriod = a.PLT >= replenishmentDto.LongPeriodDay;
|
|
|
+ }
|
|
|
+ //存在物料该物料编码表示之前算过,否则表示第一次算或者是新品
|
|
|
+ //之前算过,取算法模型数据,不存在表示第一次算要取默认值
|
|
|
+ if (ropModelList != null && ropModelList.Any(a => a.zero_based_seqno == 0))
|
|
|
+ {
|
|
|
+ a.actual_period_start_instock = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (sapItemInv.Find(s => s.MATNR == a.SAPItemNumber) != null)
|
|
|
+ {
|
|
|
+ a.actual_period_start_instock = Convert.ToDecimal(sapItemInv.Find(s => s.MATNR == a.SAPItemNumber).LABST);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ a.actual_period_start_instock = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+ //第一周需要更新参数,其他周不要更新
|
|
|
+ if (WeekOfMonth(DateTime.Now, 1) == 1)
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+ //每算一次都要把所有zero_based_seqno减去1
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ var modelList = domesticFcst?.Select(a => a.Model);
|
|
|
+ var ItemModelSetList = _standardItemModelSet.GetListAsync(a => a.tenant_id == input.tenant_id && a.company_id == input.company_id && modelList.Contains(a.Model) && !a.IsDeleted).Result;
|
|
|
+ if (ItemModelSetList == null)
|
|
|
+ {
|
|
|
+ return "库存数据不存在";
|
|
|
+ }
|
|
|
+ var itemNumList = ItemModelSetList?.Select(a => a.ItemNumber).ToList();
|
|
|
+ List<mo_ic_bom> boms = _ic_bom.GetListAsync(p => itemNumList.Contains(p.item_number) && p.factory_id == input.factory_id && p.company_id == input.company_id && !p.IsDeleted).Result.ToList();
|
|
|
+ var pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
|
|
|
+ List<mo_ic_bom> autoCreates = new List<mo_ic_bom>();
|
|
|
+ boms.ForEach(p =>
|
|
|
+ {
|
|
|
+ if (!pretreatments.Where(s => s.sourceid == p.mysql_id).Any())
|
|
|
+ {
|
|
|
+ autoCreates.Add(p);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (autoCreates.Any())
|
|
|
+ {
|
|
|
+ AutoCreateBomBill(input.company_id.ToString(), autoCreates);
|
|
|
+ pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return "OK";
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 每月15号更新周计划参数(考虑多次执行的情况)
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="input"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public async Task<string> WeekPlanParms(InputDto input)
|
|
|
+ {
|
|
|
+ //1.获取补货模型全局参数
|
|
|
+ ReplenishmentDto replenishmentDto = GetROPParam();
|
|
|
+
|
|
|
+ //到了配置的更新时间才更新
|
|
|
+ if (DateTime.Now.Day != replenishmentDto.SaleFcstEntryDate)
|
|
|
+ return "不在更新时间日期";
|
|
|
+
|
|
|
+ //Step1:按照瑞奇、两大平台分别根据历史出库数据和预测出货数据计算ROP
|
|
|
+ //Step2:计算瑞奇的M-M+2共12周补货(每次补EOP/4),计算海王的M-M+2共12周补货(每次补EOP/4),计算国科的M-M+2共12周补货(每次补EOP/4)
|
|
|
+ //Step3:汇总Step2所有补货,为工厂的制造需求
|
|
|
+ //Step4:按照Step3制造需求做资源检查,按月统计各物料消耗预测
|
|
|
+ //Step5:按照各SKU的历史出库数据和Step4里计算的预测消耗数量计算参数
|
|
|
+ //Step6:计算各SKU的12周采购补货
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ //获取月度发货计划(一次导入三个月的销售预测),因为是固定格式yyyy-MM所以可以用字符串比较,避免写很多字符串判断相等
|
|
|
+ string planMonth = $"{DateTime.Now.Year}-{DateTime.Now.Month.ToString("00")}";
|
|
|
+ string planMonthMax = $"{DateTime.Now.AddMonths(replenishmentDto.SaleFcstMonth).Year}-{DateTime.Now.AddMonths(replenishmentDto.SaleFcstMonth).Month.ToString("00")}";
|
|
|
+ var planList = _monthlyShipmentPlan.Select(a => a.PlanMonth.CompareTo(planMonth) >= 0 && a.PlanMonth.CompareTo(planMonthMax) <= 0 && !a.IsDeleted).ToList();
|
|
|
+
|
|
|
+ var itemList = _ic_item.GetListAsync(a => planList.Select(p => p.SAPItemNumber).Contains(a.number) && a.tenant_id == input.tenant_id && a.company_id == input.company_id && !a.IsDeleted).Result;
|
|
|
+ var mesItemList = _itemMaster.Select(a => planList.Select(p => p.SAPItemNumber).Contains(a.ItemNum) && a.Domain == input.factory_id.ToString() && a.IsActive);
|
|
|
+ var srm_purchaseList = _srmPurchase.GetListAsync(a => planList.Select(p => p.SAPItemNumber).Contains(a.number) && a.tenant_id == input.tenant_id && a.company_id == input.company_id && !a.IsDeleted).Result;
|
|
|
+
|
|
|
+ //获取补货模型前H周期和未来F个周期的数据
|
|
|
+ var ropModelList = _replenishmentModel.GetListAsync(a => a.zero_based_seqno >= -1 * replenishmentDto.HistoryOutStockMonth && a.zero_based_seqno <= replenishmentDto.SaleFcstMonth).Result;
|
|
|
+ //发货计划物料列表
|
|
|
+ List<string> planItemList = planList?.Select(a => a.SAPItemNumber).ToList();
|
|
|
+ //获取成品库存、灭菌库存、在制库存(会从SAP同步的库存表更新到LocationDetail、ic_item表中)
|
|
|
+ //List<SAPInv> sAPInvs = _SAPInv.Select(p => p.WERKS == input.factory_id.ToString() && itemNums.Contains(p.MATNR));
|
|
|
+ var locations = _locationDetail.Select(p => p.Domain == input.factory_id.ToString() && planList.Select(a => a.SAPItemNumber).Contains(p.ItemNum) && p.IsActive);
|
|
|
+ var sapItemInv = _SAPInv.Select(a => planItemList.Contains(a.MATNR) && a.WERKS == input.factory_id.ToString());
|
|
|
+
|
|
|
+ //取上一个月发货出库记录
|
|
|
+ var 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));
|
|
|
+
|
|
|
+ //取本月发货出库记录
|
|
|
+ var shipMList = _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.Value >= getMonthStartTime(0) && s.ShipDate <= DateTime.Now);
|
|
|
+ //按照物料分组统计出货金额
|
|
|
+ var itemGroup = shipList.GroupBy(p => p.ContainerItem)
|
|
|
+ .Select(p => new ASNBOLShipperDetail
|
|
|
+ {
|
|
|
+ QtyToShip = p.Sum(a => a.QtyToShip),
|
|
|
+ ContainerItem = p.Key
|
|
|
+ }).ToList();
|
|
|
+ //按照物料分组统计出货金额
|
|
|
+ var itemMGroup = shipMList.GroupBy(p => p.ContainerItem)
|
|
|
+ .Select(p => new ASNBOLShipperDetail
|
|
|
+ {
|
|
|
+ QtyToShip = p.Sum(a => a.QtyToShip),
|
|
|
+ ContainerItem = p.Key
|
|
|
+ }).ToList();
|
|
|
+ List<ReplenishmentModel> addList = new List<ReplenishmentModel>();
|
|
|
+ List<ReplenishmentModel> updateList = new List<ReplenishmentModel>();//更新上一个月的实际出库数量
|
|
|
+ var mathtool = new MathNet.Numerics.Distributions.Normal();
|
|
|
+ ropModelList?.Where(r => r.isparam && r.seqno == DateTime.Now.AddMonths(-1).Month && r.year == DateTime.Now.AddMonths(-1).Year).ToList()?.ForEach
|
|
|
+ (m =>
|
|
|
+ {
|
|
|
+ if (itemGroup.Any(a => a.ContainerItem == m.number))
|
|
|
+ {
|
|
|
+ m.actual_out_qty = itemGroup.Find(a => a.ContainerItem == m.number)?.QtyToShip;
|
|
|
+ updateList.Add(m);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ //需要按照成品资源检查计算原材料
|
|
|
+ planList?.Where(s => s.PlanMonth == planMonth).ToList()?.ForEach(a =>
|
|
|
+ {
|
|
|
+ ReplenishmentModel rop = new ReplenishmentModel();
|
|
|
+ rop.number = a.SAPItemNumber;
|
|
|
+ var icItem = itemList.Find(s => s.number == a.SAPItemNumber);
|
|
|
+ if (icItem != null)
|
|
|
+ {
|
|
|
+ rop.name = icItem.name;
|
|
|
+ rop.model = a.Model;
|
|
|
+ rop.erp_cls = icItem.erp_cls; //物料属性: 0.配置类 1.自制 2.委外加工 3.外购 4.虚拟件
|
|
|
+ rop.fversion = icItem.fversion;
|
|
|
+ rop.min_pack_qty = icItem.minpackqty;
|
|
|
+ rop.moq = icItem.moq;
|
|
|
+ }
|
|
|
+ rop.actual_period_start_instock = 0;
|
|
|
+ if (rop.distributionchannel == "海王" || rop.distributionchannel == "国科")
|
|
|
+ {
|
|
|
+ rop.actual_period_start_instock = locations.Find(l => l.ItemNum == a.SAPItemNumber)?.QtyOnHand;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ rop.actual_period_start_instock = sapItemInv.Find(s => s.MATNR == a.SAPItemNumber)?.LABST.ToDecimal();
|
|
|
+ }
|
|
|
+ rop.distributionchannel = a.DistributionChannel;
|
|
|
+ rop.lifecycle = a.LifeCycle;
|
|
|
+ rop.area = a.Area;
|
|
|
+ rop.plan_out_qty = Math.Ceiling(a.Qty);
|
|
|
+ rop.actual_out_qty = 0;
|
|
|
+ if (itemMGroup.Any(m => m.ContainerItem == a.SAPItemNumber))
|
|
|
+ {
|
|
|
+ rop.actual_out_qty = itemMGroup.Find(m => m.ContainerItem == a.SAPItemNumber)?.QtyToShip;
|
|
|
+ }
|
|
|
+ rop.year = DateTime.Now.Year;
|
|
|
+ rop.long_period = "Y";
|
|
|
+ rop.short_period = "M";
|
|
|
+ rop.seqno = DateTime.Now.Month;
|
|
|
+ rop.zero_based_seqno = 0;
|
|
|
+ rop.period_start_date = getMonthStartTime(0);
|
|
|
+ rop.period_end_date = getMonthEndTime(0);
|
|
|
+ rop.monthl_avg_demand = CalcAvgDemand(planList, a.SAPItemNumber);
|
|
|
+ rop.monthl_avg_demand_variance = Math.Ceiling(Convert.ToDecimal(CalcVariance(planList, a.SAPItemNumber)));
|
|
|
+ rop.monthl_avg_outstock = CalcAvgOutStock(ropModelList, replenishmentDto, rop.actual_out_qty.Value, a.SAPItemNumber);
|
|
|
+ if (mesItemList.Find(s => s.ItemNum == a.SAPItemNumber) != null)
|
|
|
+ {
|
|
|
+ rop.stock_turnover = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber).StockTurnOver;
|
|
|
+ rop.supply_leadtime = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber)?.PurLT;
|
|
|
+ rop.stock_turnover = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber)?.StockTurnOver;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ rop.stock_turnover = 4;
|
|
|
+ }
|
|
|
+ if (srm_purchaseList.Find(s => s.number == a.SAPItemNumber) != null)
|
|
|
+ {
|
|
|
+ rop.supply_leadtime = srm_purchaseList.Find(s => s.number == a.SAPItemNumber).lead_time;
|
|
|
+ }
|
|
|
+ CalcFMRAndABC(rop, replenishmentDto, input);
|
|
|
+ rop.security_stock = Math.Ceiling((decimal)(mathtool.InverseCumulativeDistribution((double)rop.service_level_pct.Value) * (double)rop.monthl_avg_demand_variance));
|
|
|
+ rop.eop = Math.Ceiling(rop.monthl_avg_demand.Value * rop.supply_leadtime.Value / DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month));
|
|
|
+ rop.rop_computed = rop.security_stock + rop.eop;
|
|
|
+ rop.max_stock_level = rop.monthl_avg_outstock * (12 / rop.stock_turnover);
|
|
|
+ rop.rop_revised = Math.Min(rop.rop_computed.Value, rop.max_stock_level.Value);
|
|
|
+ rop.isparam = true;
|
|
|
+ rop.tenant_id = input.tenant_id;
|
|
|
+ rop.factory_id = input.factory_id;
|
|
|
+ rop.create_time = DateTime.Now;
|
|
|
+ rop.org_id = input.org_id;
|
|
|
+ addList.Add(rop);
|
|
|
+ });
|
|
|
+ addList?.ForEach(item => { item.GenerateNewId(help.NextId()); });
|
|
|
+
|
|
|
+ await _replenishmentModel.InsertManyAsync(addList);
|
|
|
+ await _replenishmentModel.UpdateManyAsync(updateList);
|
|
|
+ var ropModeAllList = _replenishmentModel.GetListAsync(a => a.year != DateTime.Now.Year && a.seqno != DateTime.Now.Month && a.isparam).Result;
|
|
|
+ ropModeAllList?.ForEach(item => { item.seqno = item.seqno - 1; });
|
|
|
+ await _replenishmentModel.UpdateManyAsync(ropModeAllList);
|
|
|
+ return "OK";
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// GK和HW平台成品周计划
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="planDtos"></param>
|
|
|
+ /// <param name="input"></param>
|
|
|
+ /// <param name="nohistoryItemList"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public string PlatformWeekPlan(InputDto input)
|
|
|
+ {
|
|
|
+ //1.获取补货模型全局参数
|
|
|
+ ReplenishmentDto replenishmentDto = GetROPParam();
|
|
|
+
|
|
|
+ //到了配置的更新时间才更新
|
|
|
+ if (DateTime.Now.Day != replenishmentDto.SaleFcstEntryDate)
|
|
|
+ return "不在更新时间日期";
|
|
|
+
|
|
|
+
|
|
|
+ //获取月度发货计划
|
|
|
+ string planMonth = $"{DateTime.Now.AddMonths(1).Year}-{DateTime.Now.AddMonths(months: 1).Month}";
|
|
|
+ var planList = _monthlyShipmentPlan.Select(a => a.PlanMonth == planMonth && !a.IsDeleted);
|
|
|
+ var monthPlanList = ObjectMapper.Map<List<MonthlyShipmentPlan>, List<MonthlyShipmentPlanDto>>(planList);
|
|
|
+ var itemList = _ic_item.GetListAsync(a => planList.Select(p => p.SAPItemNumber).Contains(a.number) && a.tenant_id == input.tenant_id && a.company_id == input.company_id && !a.IsDeleted).Result;
|
|
|
+ var mesItemList = _itemMaster.Select(a => planList.Select(p => p.SAPItemNumber).Contains(a.ItemNum) && a.Domain == input.factory_id.ToString() && a.IsActive);
|
|
|
+ var srm_purchaseList = _srmPurchase.GetListAsync(a => planList.Select(p => p.SAPItemNumber).Contains(a.number) && a.tenant_id == input.tenant_id && a.company_id == input.company_id && !a.IsDeleted).Result;
|
|
|
+ //获取补货模型前一个周期和未来N个周期的数据
|
|
|
+ var ropModelList = _replenishmentModel.GetListAsync(a => a.zero_based_seqno >= 0 && a.zero_based_seqno <= replenishmentDto.UpdateWeeks).Result;
|
|
|
+ //发货计划物料列表
|
|
|
+ List<string> planItemList = planList?.Select(a => a.SAPItemNumber).ToList();
|
|
|
+ //补货模型物料列表
|
|
|
+ List<string> ropItemList = ropModelList?.Where(c => c.zero_based_seqno == 0).Select(a => a.number).ToList();
|
|
|
+ //第一次算或者新品物料列表
|
|
|
+ List<string> nohistoryItemList = planItemList.Except(ropItemList).ToList();
|
|
|
+ var sapItemInv = _SAPInv.Select(a => nohistoryItemList.Contains(a.MATNR) && a.WERKS == input.factory_id.ToString());
|
|
|
+
|
|
|
+ //1.6、获取成品库存、灭菌库存、在制库存(会从SAP同步的库存表更新到LocationDetail、ic_item表中)
|
|
|
+ //List<SAPInv> sAPInvs = _SAPInv.Select(p => p.WERKS == input.factory_id.ToString() && itemNums.Contains(p.MATNR));
|
|
|
+ var locations = _locationDetail.Select(p => p.Domain == input.factory_id.ToString() && planList.Select(a => a.SAPItemNumber).Contains(p.ItemNum) && p.IsActive);
|
|
|
+
|
|
|
+
|
|
|
+ //取上一个月发货出库记录
|
|
|
+ var shipList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.ShipDate >= getMonthStartTime(-1) && a.ShipDate <= getMonthEndTime(-1) && a.RealQty > 0 && planItemList.Contains(a.ContainerItem));
|
|
|
+
|
|
|
+ //按照物料分组统计出货金额
|
|
|
+ var itemGroup = shipList.GroupBy(p => p.ContainerItem)
|
|
|
+ .Select(p => new ASNBOLShipperDetail
|
|
|
+ {
|
|
|
+ Price = p.Sum(a => a.QtyToShip),
|
|
|
+ ContainerItem = p.Key
|
|
|
+ }).ToList();
|
|
|
+
|
|
|
+ monthPlanList?.ForEach(a =>
|
|
|
+ {
|
|
|
+ //物料属性:0.配置类 1.自制 2.委外加工 3.外购 4.虚拟件
|
|
|
+ a.erp_cls = itemList.Find(s => s.number == a.SAPItemNumber)?.erp_cls;
|
|
|
+ if (mesItemList.Find(s => s.ItemNum == a.SAPItemNumber) != null)
|
|
|
+ {
|
|
|
+ a.stock_turnover = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber).StockTurnOver;
|
|
|
+ a.PLT = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber)?.PurLT;
|
|
|
+ a.IsLongPeriod = a.PLT >= replenishmentDto.LongPeriodDay;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ a.stock_turnover = 4;
|
|
|
+ }
|
|
|
+ if (srm_purchaseList.Find(s => s.number == a.SAPItemNumber) != null)
|
|
|
+ {
|
|
|
+ a.PLT = srm_purchaseList.Find(s => s.number == a.SAPItemNumber).lead_time;
|
|
|
+ a.IsLongPeriod = a.PLT >= replenishmentDto.LongPeriodDay;
|
|
|
+ }
|
|
|
+ //存在物料该物料编码表示之前算过,否则表示第一次算或者是新品
|
|
|
+ //之前算过,取算法模型数据,不存在表示第一次算要取默认值
|
|
|
+ if (ropModelList != null && ropModelList.Any(a => a.zero_based_seqno == 0))
|
|
|
+ {
|
|
|
+ a.actual_period_start_instock = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (sapItemInv.Find(s => s.MATNR == a.SAPItemNumber) != null)
|
|
|
+ {
|
|
|
+ a.actual_period_start_instock = Convert.ToDecimal(sapItemInv.Find(s => s.MATNR == a.SAPItemNumber).LABST);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ a.actual_period_start_instock = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+ //第一周需要更新参数,其他周不要更新
|
|
|
+ if (WeekOfMonth(DateTime.Now, 1) == 1)
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+ //每算一次都要把所有zero_based_seqno减去1
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ var modelList = domesticFcst?.Select(a => a.Model);
|
|
|
+ var ItemModelSetList = _standardItemModelSet.GetListAsync(a => a.tenant_id == input.tenant_id && a.company_id == input.company_id && modelList.Contains(a.Model) && !a.IsDeleted).Result;
|
|
|
+ if (ItemModelSetList == null)
|
|
|
+ {
|
|
|
+ return "库存数据不存在";
|
|
|
+ }
|
|
|
+ var itemNumList = ItemModelSetList?.Select(a => a.ItemNumber).ToList();
|
|
|
+ List<mo_ic_bom> boms = _ic_bom.GetListAsync(p => itemNumList.Contains(p.item_number) && p.factory_id == input.factory_id && p.company_id == input.company_id && !p.IsDeleted).Result.ToList();
|
|
|
+ var pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
|
|
|
+ List<mo_ic_bom> autoCreates = new List<mo_ic_bom>();
|
|
|
+ boms.ForEach(p =>
|
|
|
+ {
|
|
|
+ if (!pretreatments.Where(s => s.sourceid == p.mysql_id).Any())
|
|
|
+ {
|
|
|
+ autoCreates.Add(p);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (autoCreates.Any())
|
|
|
+ {
|
|
|
+ AutoCreateBomBill(input.company_id.ToString(), autoCreates);
|
|
|
+ pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return "OK";
|
|
|
+ }
|
|
|
+
|
|
|
+ public ReplenishmentDto GetROPParam()
|
|
|
+ {
|
|
|
+ ReplenishmentDto replenishmentDto = new ReplenishmentDto();
|
|
|
+ replenishmentDto.ReplenishmentCalcPeriod = "W";
|
|
|
+ replenishmentDto.HistoryOutStockMonth = 2;
|
|
|
+ replenishmentDto.SaleFcstMonth = 2;
|
|
|
+ replenishmentDto.SaleFcstEntryDate = 27;
|
|
|
+ replenishmentDto.UpdateWeeks = 12;
|
|
|
+ replenishmentDto.WeekPlanUpdateDay = 7;//每周日更新
|
|
|
+ replenishmentDto.LongPeriodDay = 60;
|
|
|
+ return replenishmentDto;
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 计算ABC分类和FMR分类
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="replenishmentModels"></param>
|
|
|
+ public void CalcFMRAndABC(List<ReplenishmentModel> replenishmentModels, ReplenishmentDto replenishmentDto, InputDto input)
|
|
|
+ {
|
|
|
+ var itemNumList = replenishmentModels?.Select(a => a.number).ToList();
|
|
|
+ //发货出库记录
|
|
|
+ var shipList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.ShipDate >= DateTime.Now.AddMonths(replenishmentDto.HistoryOutStockMonth * -1) && a.RealQty > 0 && itemNumList.Contains(a.ContainerItem));
|
|
|
+ //领料出库记录
|
|
|
+ //var pickbilllist = _NbrDetail.Select(a => a.Domain == input.factory_id.ToString() && a.Type == "SM" && a.IsActive && a.UpdateTime >= DateTime.Now.AddMonths(replenishmentDto.HistoryOutStockMonth * -1) && itemNumList.Contains(a.ItemNum));
|
|
|
+ var pickbilllist = _invTransHist.Select(a => a.Domain == input.factory_id.ToString() && a.TransType == "iss-wo" && a.IsActive && a.CreateTime >= DateTime.Now.AddMonths(replenishmentDto.HistoryOutStockMonth * -1) && itemNumList.Contains(a.ItemNum));
|
|
|
+ //总的移库次数
|
|
|
+ int totalCount = shipList.Count() + pickbilllist.Count();
|
|
|
+ //平均出库次数
|
|
|
+ decimal avgOutStock = totalCount / replenishmentDto.HistoryOutStockMonth;
|
|
|
+
|
|
|
+ //总出货金额
|
|
|
+ decimal? totalPrice = shipList.Sum(a => a.Price * a.QtyToShip);
|
|
|
+ //按照物料分组统计出货金额
|
|
|
+ var itemGroup = shipList.GroupBy(p => p.ContainerItem)
|
|
|
+ .Select(p => new ASNBOLShipperDetail
|
|
|
+ {
|
|
|
+ Price = p.Sum(a => a.Price * a.QtyToShip) * 100 / totalPrice,
|
|
|
+ ContainerItem = p.Key
|
|
|
+ }).ToList().OrderByDescending(c => c.Price).ThenByDescending(c => c.ContainerItem);
|
|
|
+ var AIndex = (int)Math.Ceiling(itemGroup.Count() * 0.75);//A类:0-75%
|
|
|
+ var BIndex = (int)Math.Ceiling(itemGroup.Count() * 0.9) - AIndex;//A类:75%-90%
|
|
|
+ var CIndex = itemGroup.Count() - AIndex - BIndex;//A类:90%-100%
|
|
|
+ var AItem = itemGroup.Take(AIndex);
|
|
|
+ var BItem = itemGroup.Skip(AIndex).Take(BIndex);
|
|
|
+ var CItem = itemGroup.Skip(AIndex + BIndex).Take(CIndex);
|
|
|
+ replenishmentModels?.ForEach(replenishmentModel =>
|
|
|
+ {
|
|
|
+ if (AItem.Any(a => a.ContainerItem == replenishmentModel.number))
|
|
|
+ {
|
|
|
+ replenishmentModel.abc = "A";//金额占比前75%的物料划为A类
|
|
|
+ }
|
|
|
+ else if (BItem.Any(a => a.ContainerItem == replenishmentModel.number))
|
|
|
+ {
|
|
|
+ replenishmentModel.abc = "B";//金额占比前75%-90%的物料划为A类
|
|
|
+ }
|
|
|
+ else if (CItem.Any(a => a.ContainerItem == replenishmentModel.number))
|
|
|
+ {
|
|
|
+ replenishmentModel.abc = "C";//金额占比后10%的物料划为A类
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ replenishmentModel.abc = "B";//原材料默认为B
|
|
|
+ }
|
|
|
+ int itemMoveCount = shipList.Count(a => a.ContainerItem == replenishmentModel.number) + pickbilllist.Count(a => a.ItemNum == replenishmentModel.number);
|
|
|
+ if (itemMoveCount >= avgOutStock)
|
|
|
+ {
|
|
|
+ replenishmentModel.fmr = "F";
|
|
|
+ }
|
|
|
+ else if (itemMoveCount >= avgOutStock / 2 && itemMoveCount < avgOutStock || itemMoveCount == 0)
|
|
|
+ {
|
|
|
+ replenishmentModel.fmr = "M";//没有出库移库记录的默认为M
|
|
|
+ }
|
|
|
+ else if (itemMoveCount < avgOutStock / 2)
|
|
|
+ {
|
|
|
+ replenishmentModel.fmr = "R";
|
|
|
+ }
|
|
|
+
|
|
|
+ if (replenishmentModel.abc == "A" && replenishmentModel.fmr == "R")
|
|
|
+ {
|
|
|
+ replenishmentModel.service_level_pct = (decimal?)0.8;
|
|
|
+ }
|
|
|
+ if (replenishmentModel.abc != "C" && replenishmentModel.fmr != "R")
|
|
|
+ {
|
|
|
+ replenishmentModel.service_level_pct = (decimal?)0.96;
|
|
|
+ }
|
|
|
+ if (replenishmentModel.abc == "C" || (replenishmentModel.abc == "B" && replenishmentModel.fmr == "R"))
|
|
|
+ {
|
|
|
+ replenishmentModel.service_level_pct = (decimal?)0.9;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 计算ABC分类和FMR分类
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="replenishmentModels"></param>
|
|
|
+ public void CalcFMRAndABC(ReplenishmentModel replenishmentModel, ReplenishmentDto replenishmentDto, InputDto input)
|
|
|
+ {
|
|
|
+ //发货出库记录
|
|
|
+ var shipList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.ShipDate >= DateTime.Now.AddMonths(replenishmentDto.HistoryOutStockMonth * -1) && a.RealQty > 0 && replenishmentModel.number == a.ContainerItem);
|
|
|
+ //领料出库记录
|
|
|
+ //var pickbilllist = _NbrDetail.Select(a => a.Domain == input.factory_id.ToString() && a.Type == "SM" && a.IsActive && a.UpdateTime >= DateTime.Now.AddMonths(replenishmentDto.HistoryOutStockMonth * -1) && itemNumList.Contains(a.ItemNum));
|
|
|
+ var pickbilllist = _invTransHist.Select(a => a.Domain == input.factory_id.ToString() && a.TransType == "iss-wo" && a.IsActive && a.CreateTime >= DateTime.Now.AddMonths(replenishmentDto.HistoryOutStockMonth * -1) && replenishmentModel.number == a.ItemNum);
|
|
|
+ //总的移库次数
|
|
|
+ int totalCount = shipList.Count() + pickbilllist.Count();
|
|
|
+ //平均出库次数
|
|
|
+ decimal avgOutStock = totalCount / replenishmentDto.HistoryOutStockMonth;
|
|
|
+
|
|
|
+ //总出货金额
|
|
|
+ decimal? totalPrice = shipList.Sum(a => a.Price * a.QtyToShip);
|
|
|
+ //按照物料分组统计出货金额
|
|
|
+ var itemGroup = shipList.GroupBy(p => p.ContainerItem)
|
|
|
+ .Select(p => new ASNBOLShipperDetail
|
|
|
+ {
|
|
|
+ Price = p.Sum(a => a.Price * a.QtyToShip) * 100 / totalPrice,
|
|
|
+ ContainerItem = p.Key
|
|
|
+ }).ToList().OrderByDescending(c => c.Price).ThenByDescending(c => c.ContainerItem);
|
|
|
+ var AIndex = (int)Math.Ceiling(itemGroup.Count() * 0.75);//A类:0-75%
|
|
|
+ var BIndex = (int)Math.Ceiling(itemGroup.Count() * 0.9) - AIndex;//A类:75%-90%
|
|
|
+ var CIndex = itemGroup.Count() - AIndex - BIndex;//A类:90%-100%
|
|
|
+ var AItem = itemGroup.Take(AIndex);
|
|
|
+ var BItem = itemGroup.Skip(AIndex).Take(BIndex);
|
|
|
+ var CItem = itemGroup.Skip(AIndex + BIndex).Take(CIndex);
|
|
|
+ if (AItem.Any(a => a.ContainerItem == replenishmentModel.number))
|
|
|
+ {
|
|
|
+ replenishmentModel.abc = "A";//金额占比前75%的物料划为A类
|
|
|
+ }
|
|
|
+ else if (BItem.Any(a => a.ContainerItem == replenishmentModel.number))
|
|
|
+ {
|
|
|
+ replenishmentModel.abc = "B";//金额占比前75%-90%的物料划为B类
|
|
|
+ }
|
|
|
+ else if (CItem.Any(a => a.ContainerItem == replenishmentModel.number))
|
|
|
+ {
|
|
|
+ replenishmentModel.abc = "C";//金额占比后10%的物料划为C类
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ replenishmentModel.abc = "B";//原材料默认为B
|
|
|
+ }
|
|
|
+ int itemMoveCount = shipList.Count(a => a.ContainerItem == replenishmentModel.number) + pickbilllist.Count(a => a.ItemNum == replenishmentModel.number);
|
|
|
+ if (itemMoveCount >= avgOutStock)
|
|
|
+ {
|
|
|
+ replenishmentModel.fmr = "F";
|
|
|
+ }
|
|
|
+ else if (itemMoveCount >= avgOutStock / 2 && itemMoveCount < avgOutStock || itemMoveCount == 0)
|
|
|
+ {
|
|
|
+ replenishmentModel.fmr = "M";//没有出库移库记录的默认为M
|
|
|
+ }
|
|
|
+ else if (itemMoveCount < avgOutStock / 2)
|
|
|
+ {
|
|
|
+ replenishmentModel.fmr = "R";
|
|
|
+ }
|
|
|
+
|
|
|
+ if (replenishmentModel.abc == "A" && replenishmentModel.fmr == "R")
|
|
|
+ {
|
|
|
+ replenishmentModel.service_level_pct = (decimal?)0.8;
|
|
|
+ }
|
|
|
+ if (replenishmentModel.fmr != "R")
|
|
|
+ {
|
|
|
+ replenishmentModel.service_level_pct = (decimal?)0.96;
|
|
|
+ }
|
|
|
+ if (replenishmentModel.abc != "A"&& replenishmentModel.fmr == "R")
|
|
|
+ {
|
|
|
+ replenishmentModel.service_level_pct = (decimal?)0.9;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 算平均月需求数量
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="planList">发货计划</param>
|
|
|
+ /// <param name="itemGroup"></param>
|
|
|
+ /// <param name="itemNum"></param>
|
|
|
+ /// <param name="month"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public decimal CalcAvgDemand(List<MonthlyShipmentPlan> list, string itemNum)
|
|
|
+ {
|
|
|
+ return list.Where(i => i.SAPItemNumber == itemNum).Select(a => a.Qty).Average();
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ ///
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="list">补货模型</param>
|
|
|
+ /// <param name="MQty">本月实际出库</param>
|
|
|
+ /// <param name="replenishmentDto">全局参数</param>
|
|
|
+ /// <param name="itemNum">物料编码</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public decimal CalcAvgOutStock(List<ReplenishmentModel> list, ReplenishmentDto replenishmentDto, decimal MQty, string itemNum)
|
|
|
+ {
|
|
|
+ return (list.Where(i => i.number == itemNum && i.zero_based_seqno > 1 - replenishmentDto.HistoryOutStockMonth && i.zero_based_seqno <= 0).Select(a => a.actual_out_qty.Value).Sum() + MQty) / (replenishmentDto.HistoryOutStockMonth + 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ public double CalcVariance(List<MonthlyShipmentPlan> list, string itemNum)
|
|
|
+ {
|
|
|
+ var avg = CalcAvgDemand(list, itemNum);
|
|
|
+ var nums = list.Where(i => i.SAPItemNumber == itemNum).Select(a => a.Qty);
|
|
|
+ if (nums.Count() <= 1)
|
|
|
+ return 0;
|
|
|
+ return Math.Sqrt(nums.Sum(x => Math.Pow(Convert.ToDouble(x) - Convert.ToDouble(avg), 2)) / (nums.Count() - 1));
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取指定日期在为一年中为第几周
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="dt">指定时间</param>
|
|
|
+ /// <reutrn>返回第几周</reutrn>
|
|
|
+ public static int GetWeekOfYear(DateTime dt)
|
|
|
+ {
|
|
|
+
|
|
|
+ System.Globalization.GregorianCalendar gc = new System.Globalization.GregorianCalendar();
|
|
|
+ int weekOfYear = gc.GetWeekOfYear(dt, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Monday);
|
|
|
+ return weekOfYear;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取指定日期在该月的第几周
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="day"></param>
|
|
|
+ /// <param name="WeekStart">1表示周一至周日为一周,2表示周日至周六为一周</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static int WeekOfMonth(DateTime day, int WeekStart)
|
|
|
+ {
|
|
|
+ DateTime FirstofMonth = Convert.ToDateTime(day.Date.Year + "-" + day.Date.Month + "-" + 1);
|
|
|
+
|
|
|
+ int i = (int)FirstofMonth.Date.DayOfWeek;
|
|
|
+ if (i == 0)
|
|
|
+ {
|
|
|
+ i = 7;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (WeekStart == 1)
|
|
|
+ {
|
|
|
+ return (day.Date.Day + i - 2) / 7 + 1;
|
|
|
+ }
|
|
|
+ if (WeekStart == 2)
|
|
|
+ {
|
|
|
+ return (day.Date.Day + i - 1) / 7;
|
|
|
+
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ //获取上周开始时间
|
|
|
+ public static DateTime getPreWeekStartTime()
|
|
|
+ {
|
|
|
+ var weekday = (int)DateTime.Now.DayOfWeek;
|
|
|
+ return Convert.ToDateTime(DateTime.Now.AddDays(-7 - weekday + 1).ToString("yyyy-MM-dd 00:00:00.000"));
|
|
|
+ }
|
|
|
+ //获取上周结束时间
|
|
|
+ public static DateTime getPreWeekEndTime()
|
|
|
+ {
|
|
|
+ int weekday = (int)DateTime.Now.DayOfWeek;
|
|
|
+ return Convert.ToDateTime(DateTime.Now.AddDays(weekday - 7 + 1).ToString("yyyy-MM-dd 23:59:59.000"));
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 获取上个月开始时间
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="months"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static DateTime getPreMonthStartTime()
|
|
|
+ {
|
|
|
+ return Convert.ToDateTime(DateTime.Now.AddMonths(-1).AddDays(1 - DateTime.Now.Day).ToString("yyyy-MM-dd 00:00:00.000"));
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 获取上月结束时间
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="months"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static DateTime getPreMonthEndTime()
|
|
|
+ {
|
|
|
+ return Convert.ToDateTime(DateTime.Now.AddDays(-DateTime.Now.Day).ToString("yyyy-MM-dd 23:59:59.000"));
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取前后某个,整数月开始时间
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="months">正数表示后多少个月的第一天,负数为前多少个月第一天</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static DateTime getMonthStartTime(int months)
|
|
|
+ {
|
|
|
+ return getPreMonthStartTime().AddMonths(months + 1);
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 获取前后某个,整数月结束时间
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="months">正数表示后多少个月的第一天,负数为前多少个月第一天</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static DateTime getMonthEndTime(int months)
|
|
|
+ {
|
|
|
+ return getPreMonthEndTime().AddMonths(months + 1);
|
|
|
+ }
|
|
|
}
|
|
|
}
|