using HH.WMS.Entitys; using HH.WMS.Entitys.Common; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; using HH.WMS.Entitys.Basic; using System.Threading; using HH.WMS.Common; using HH.WMS.BLL; using HH.WMS.BLL.CoreServer; using HH.WMS.Entitys.Sys; using HH.WMS.BLL.OutStock; using HH.WMS.BLL.Algorithm; using HH.WMS.Common.Algorithm; using HH.WMS.Common.Algorithm.Out; using HH.WMS.BLL.Common; namespace HH.WMS.CoreServer.Service { public class WaveService { #region 线程 //内销线程 public Thread thNxCreateWave = null; //外销线程 public Thread thWxCreateWave = null; //执行分拣单线程 public Thread thExecuteSorting = null; //执行分拣出,盘点出的任务 public Thread thExecuteTask = null; #endregion #region 开始 /// /// 开始 /// public void Start() { #region 执行分拣单 //执行分拣单 thExecuteSorting = thExecuteSorting ?? new Thread(() => { DoRepeatAction(ExecuteSorting); }); thExecuteSorting.IsBackground = true; thExecuteSorting.Start(); #endregion #region 执行任务 //执行任务 thExecuteTask = thExecuteTask ?? new Thread(() => { DoRepeatAction(ExecuteTask); }); thExecuteTask.IsBackground = true; thExecuteTask.Start(); #endregion } #endregion #region 重复执行一个action /// /// 重复执行一个action /// /// private void DoRepeatAction(Func func) { while (true) { try { var result = func(); if (!result.Success) { Log.Info("error", result.Msg); } } catch (Exception ex) { Log.Info("error", ex.Message); } finally { //每次执行完休眠2秒钟 Thread.Sleep(2000); } } } #endregion #region 执行分拣单,生成分拣明细 /// /// 执行分拣单,生成分拣明细 /// /// public OperateResult ExecuteSorting() { //获取待分拣分拣单 var staySortings = BLLCreator.CreateDapper().GetTopList(5, new { CN_S_STATE = Constants.Sorting_Stay }); //分拣单子表 var staySortingDtl = new List(); if (staySortings.Any()) { //获取分拣单子表 staySortingDtl = BLLCreator.CreateDapper().GetList(new { CN_S_SORTING_NO = staySortings.Select(s => s.CN_S_SORTING_NO).ToList() }); } //逐个执行,单个失败不会return foreach (var staySorting in staySortings) { staySorting.SortingDtlList = staySortingDtl.FindAll(f => f.CN_S_SORTING_NO == staySorting.CN_S_SORTING_NO); //调用算法获取分拣明细 var sortingLocationResult = GetSortingLocation(staySorting); if (!sortingLocationResult.Success) { //消息 Log.Info("分拣单获取分拣明细失败:", JsonConvert.SerializeObject(sortingLocationResult)); continue; } //分拣明细 var sortingLocations = sortingLocationResult.GetData>(); staySorting.SortingLocationList.AddRange(sortingLocations); var currentArea = BLLCreator.Create().GetArea(staySorting.CN_S_STOCK_AREA); //自动库时生成任务 if (currentArea.CN_C_IS_AUTO == Constants.Y) { //生成任务 List endAreas = new List(); var outTaskResult = GetOutTask(staySorting, ref endAreas); if (!outTaskResult.Success) { Log.Info("分拣单生成出库任务失败:", JsonConvert.SerializeObject(outTaskResult)); continue; } var tasks = outTaskResult.GetData>(); staySorting.Tasks = tasks; staySorting.EndBits = endAreas; } var executeResult = BLLCreator.Create().ExecuteSorting(staySorting); if (!executeResult.Success) { //消息 Log.Info("执行分拣executeResult失败:", JsonConvert.SerializeObject(executeResult)); continue; } } return OperateResult.Succeed(); } #endregion #region 执行任务 /// /// 执行任务 /// /// public OperateResult ExecuteTask() { var noExecuteTask = BLLCreator.CreateDapper().GetList(new { CN_B_SENDAMS = false, CN_S_TASK_TYPE = new List() { Constants.TaskType_SortingOut, Constants.TaskType_CheckOut }, }).OrderBy(o=>o.CN_T_CREATE); foreach (var task in noExecuteTask) { //需要调作业区入库算法,算出货位给出库任务 var inAssignEntity = new InAssignEntity { objectType = InAssignEntity.ObjectType.托盘, objectCode = task.CN_S_TRAY_CODE, lockLocation = false, lstAreaPrior = new List() { { new areaPriorClass{ areaCode = task.CN_S_END_AREA, Prior = 1 } } } }; Log.Info("ExecuteTask调用算法InAssign参数", JsonConvert.SerializeObject(inAssignEntity)); InAssignResultEntity inAssignResultEntity = BLLCreator.Create().InAssign(inAssignEntity); Log.Info("ExecuteTask调用算法InAssign结果", JsonConvert.SerializeObject(inAssignResultEntity)); if (!inAssignResultEntity.Success) continue; //当前分拣单库区 task.EndAreaEntity = BLLCreator.Create().GetArea(task.CN_S_END_AREA); task.CN_S_END_BIT = inAssignResultEntity.locationCode; var executeTaskResult = BLLCreator.Create().ExecuteTask(task); if (!executeTaskResult.Success) Log.Info("executeTaskResult Msg", executeTaskResult.Msg); } return OperateResult.Succeed(); } #endregion #region 获取任务 /// /// 获取任务 /// /// /// /// public OperateResult GetOutTask(TN_WM_SORTING_LISTEntity sortingEntity, ref List endAreas) { try { //当前分拣单库区 var currentArea = BLLCreator.Create().GetArea(sortingEntity.CN_S_STOCK_AREA); if (currentArea == null) return OperateResult.Error("未找到库区:" + sortingEntity.CN_S_STOCK_AREA); //托盘货位分组 var trayGroup = sortingEntity.SortingLocationList.GroupBy(g => new { g.CN_S_SORTING_NO, g.CN_S_TRAY_CODE, g.CN_S_LOCATION_CODE }).Select(s => new { s.Key.CN_S_SORTING_NO, s.Key.CN_S_TRAY_CODE, s.Key.CN_S_LOCATION_CODE, CN_F_QUANTITY = s.Sum(m => m.CN_F_QUANTITY) }); //整托托盘 List fullTrayCode = new List(); //托盘区的需要考虑整托 if (currentArea.CN_S_AREA_NAME == Constants.TrayArea) { //托盘数量汇总 var trayQtyGroup = trayGroup.GroupBy(g => g.CN_S_TRAY_CODE).Select(s => new { CN_S_TRAY_CODE = s.Key, CN_F_QUANTITY = s.Sum(m => m.CN_F_QUANTITY) }); //所有托盘物料关联明细 var trayItems = BLLCreator.CreateDapper().GetList(new { CN_S_TRAY_CODE = trayQtyGroup.Select(s => s.CN_S_TRAY_CODE).ToList() }); //比较算法返回的托盘物料数量与明细数量是否相等(整托) foreach (var tray in trayQtyGroup) { //整托 if (tray.CN_F_QUANTITY == trayItems.Where(s => s.CN_S_TRAY_CODE == tray.CN_S_TRAY_CODE) .Sum(m => m.CN_F_QUANTITY)) { fullTrayCode.Add(tray.CN_S_TRAY_CODE); } } } List taskList = new List(); //存在非整托货位托盘 var pickTrays = trayGroup.Where(s => !fullTrayCode.Contains(s.CN_S_TRAY_CODE)) .Select(e => new TN_WM_SORTING_LOCATIONEntity() { CN_S_SORTING_NO = e.CN_S_SORTING_NO, CN_S_TRAY_CODE = e.CN_S_TRAY_CODE, CN_S_LOCATION_CODE = e.CN_S_LOCATION_CODE, }).ToList(); if (pickTrays.Any()) { //非整托任务 WorkflowEntity workflowEntity = new WorkflowEntity(Constants.Workflow_Out) { CirObj = Constants.Tray, StartArea = currentArea.CN_S_AREA_CODE, ReturnList = true }; //找站点 GetWorkPosition var trayWorkflow = BLLCreator.Create().GetWorkPosition(workflowEntity); if (!trayWorkflow.Success) return trayWorkflow; var workAreaPro = trayWorkflow.GetData>(); //分拣出库任务 var pickTasks = GetTaskEntity(workAreaPro[0], pickTrays); endAreas.AddRange(workAreaPro.Select(s => s.CN_S_END_AREA_CODE).ToList()); taskList.AddRange(pickTasks); } //存在非整托货位托盘 var fullTrays = trayGroup.Where(s => fullTrayCode.Contains(s.CN_S_TRAY_CODE)) .Select(e => new TN_WM_SORTING_LOCATIONEntity() { CN_S_SORTING_NO = e.CN_S_SORTING_NO, CN_S_TRAY_CODE = e.CN_S_TRAY_CODE, CN_S_LOCATION_CODE = e.CN_S_LOCATION_CODE, }).ToList(); if (fullTrays.Any()) { //整托任务 WorkflowEntity workflowEntity = new WorkflowEntity(Constants.Workflow_Out) { CirObj = Constants.Tray, StartArea = currentArea.CN_S_AREA_CODE, IsFullTray = Constants.Y, }; //找站点 GetWorkPosition var trayWorkflow = BLLCreator.Create().GetWorkPosition(workflowEntity); if (!trayWorkflow.Success) return trayWorkflow; var workAreaPro = trayWorkflow.GetData(); //需要调作业区入库算法,算出货位给出库任务 var inAssignEntity = new InAssignEntity { objectType = InAssignEntity.ObjectType.托盘, objectCode = fullTrays[0].CN_S_TRAY_CODE, lockLocation = false, lstAreaPrior = new List() { { new areaPriorClass{ areaCode = workAreaPro.CN_S_END_AREA_CODE, Prior = 1 } } } }; Log.Info("调用算法InAssign参数", JsonConvert.SerializeObject(inAssignEntity)); InAssignResultEntity inAssignResultEntity = BLLCreator.Create().InAssign(inAssignEntity); Log.Info("调用算法InAssign结果", JsonConvert.SerializeObject(inAssignResultEntity)); if (!inAssignResultEntity.Success) return OperateResult.Error(inAssignResultEntity.Msg); //整托出库任务 var fullTasks = GetTaskEntity(workAreaPro, pickTrays, inAssignResultEntity.locationCode); taskList.AddRange(fullTasks); } return OperateResult.Succeed(null, taskList); } catch (Exception ex) { return OperateResult.Error(ex.Message); } } #endregion #region 获取任务实体 /// /// 获取任务实体 /// /// /// /// private List GetTaskEntity(TN_WM_WORK_AREA_PROEntity workArea, List sortingLocations, string endBit = "") { var trayLocationGroup = sortingLocations.GroupBy(g => new { g.CN_S_TRAY_CODE, g.CN_S_LOCATION_CODE, g.CN_S_SORTING_NO }).Select(s => new { s.Key.CN_S_TRAY_CODE, s.Key.CN_S_LOCATION_CODE, s.Key.CN_S_SORTING_NO }); List taskList = new List(); foreach (var task in trayLocationGroup) { string postData = "{\"appCode\":\"" + Constants.appCode + "\",\"ruleName\":\"" + Constants.Rule_TaskNo + "\",\"orgId\":\"\",\"orgFlag\":\"\"}"; string taskNo = WebApiManager.HttpAutoBom_Post("api/BillRule/GenBillNo", postData); TN_WM_TASKEntity taskEntity = new TN_WM_TASKEntity() { CN_S_TASK_NO = taskNo, CN_S_TASK_TYPE = Constants.TaskType_SortingOut, CN_S_FROM_OP = Constants.Out, CN_S_FROM_NO = task.CN_S_SORTING_NO, CN_S_TRAY_CODE = task.CN_S_TRAY_CODE, CN_S_STOCK_CODE = "", CN_S_START_AREA = workArea.CN_S_START_AREA_CODE, CN_S_START_BIT = task.CN_S_LOCATION_CODE, CN_S_END_AREA = workArea.CN_S_END_AREA_CODE, CN_S_END_BIT = endBit, CN_S_STATE = Constants.TaskState_NoExecuted, CN_T_CREATE = DateTime.Now, CN_T_MODIFY = DateTime.Now, EndAreaEntity = BLLCreator.Create().GetArea(workArea.CN_S_END_AREA_CODE) }; taskList.Add(taskEntity); } return taskList; } #endregion #region 是否在上班时间 /// /// 是否在上班时间 /// /// private WaveConfig WaveConfig() { //没加仓库条件 var waveStrategyValues = BLLCreator.CreateDapper().GetList(new { CN_S_CODE = new List { Constants.Strategy_StartTime, Constants.Strategy_EndTime, Constants.Strategy_SeveralMaxCreateWave, Constants.Strategy_LessMinute } }); WaveConfig waveConfig = new WaveConfig(); //上班时间 var startTime = waveStrategyValues.Find(f => f.CN_S_CODE == Constants.Strategy_StartTime); string _startTime = startTime != null ? startTime.CN_S_VALUE : Constants.WaveDefault_StartTime; _startTime = string.IsNullOrEmpty(_startTime) ? Constants.WaveDefault_StartTime : _startTime; waveConfig.StartTime = DateTime.Parse(_startTime); //下班时间 var endTime = waveStrategyValues.Find(f => f.CN_S_CODE == Constants.Strategy_EndTime); string _endTime = endTime != null ? endTime.CN_S_VALUE : Constants.WaveDefault_EndTime; _endTime = string.IsNullOrEmpty(_endTime) ? Constants.WaveDefault_EndTime : _endTime; waveConfig.EndTime = DateTime.Parse(_endTime); //内销几单一波 var severalMaxCreateWave = waveStrategyValues.Find(f => f.CN_S_CODE == Constants.Strategy_SeveralMaxCreateWave); string _severalMaxCreateWave = severalMaxCreateWave != null ? severalMaxCreateWave.CN_S_VALUE : Constants.WaveDefault_SeveralMaxCreateWave; _severalMaxCreateWave = string.IsNullOrEmpty(_severalMaxCreateWave) ? Constants.WaveDefault_SeveralMaxCreateWave : _severalMaxCreateWave; waveConfig.SeveralMaxCreateWave = int.Parse(_severalMaxCreateWave); //内销几分钟后生成 var lessMinute = waveStrategyValues.Find(f => f.CN_S_CODE == Constants.Strategy_LessMinute); string _lessMinute = lessMinute != null ? lessMinute.CN_S_VALUE : Constants.WaveDefault_LessMinute; _lessMinute = string.IsNullOrEmpty(_lessMinute) ? Constants.WaveDefault_LessMinute : _lessMinute; waveConfig.LessMinute = int.Parse(_lessMinute); //result return waveConfig; } #endregion #region 是否在上班时间 /// /// 是否在上班时间 /// /// /// private bool IsWorkTime(WaveConfig waveConfig) { try { TimeSpan dspWorkingDayAM = waveConfig.StartTime.TimeOfDay; TimeSpan dspWorkingDayPM = waveConfig.EndTime.TimeOfDay; TimeSpan dspNow = DateTime.Now.TimeOfDay; if (dspNow >= dspWorkingDayAM && dspNow <= dspWorkingDayPM) { return true; } return false; } catch { return false; } } #endregion #region 创建波次分拣单 /// /// 创建波次分拣单 /// /// /// 是否内销 /// public OperateResult WaveCreate(List outList) { //登陆信息&生成单号 UserRuleEntity user = new UserRuleEntity() { RuleCode = Constants.Rule_WaveNo }; //生成波次号 string waveNo = user.GenerateNo(); return ChangeOutOperate(outList, (outMstList, batchesList, stockList, lstStrate) => { //批分分配量 var bResult = stockList.BatchesStockAllocQty(batchesList, lstStrate); if (!bResult.Success) return bResult; //批分结果数据 var batchesResult = bResult.GetData(); if (batchesResult == null) return OperateResult.Error("生成打单数据异常"); //算库区 OperateResult outAreaResult = OutArea(batchesResult.OutMstList); if (!outAreaResult.Success) return outAreaResult; //算法库区返回结果 var algorResultEntity = outAreaResult.GetData(); Log.Info("WaveCreate 调用OutArea返回值algorResultEntity", JsonConvert.SerializeObject(algorResultEntity)); //算法库区返回结果 if (!algorResultEntity.Success) return OperateResult.Error("算法异常:" + algorResultEntity.Msg); //算法结果 var algorResult = algorResultEntity.itemOutAreaResult; //算法结果 if (algorResult == null) return OperateResult.Error("库存不足,请先完成来料区的上架"); //获取分拣单数据 var sortingDataResult = GetSortingData(algorResult, user, waveNo); if (!sortingDataResult.Success) return sortingDataResult; //生成的分拣单数据 var sortingList = sortingDataResult.GetData>(); List itemCodes = new List(); sortingList.ForEach(x => { if (x.SortingDtlList != null) x.SortingDtlList.ForEach(y => { itemCodes.Add(y.CN_S_ITEM_CODE); }); }); //分拣单的所有库区量表数据 var stockAreaList = BLLCreator.Create>().GetList(new { CN_S_STOCK_AREA = sortingList.Select(x => x.CN_S_STOCK_AREA).ToList(), CN_S_ITEM_CODE = itemCodes }); Log.Info("批分库区参数 sortingList:", JsonConvert.SerializeObject(sortingList)); Log.Info("批分库区参数 lstStrate:", JsonConvert.SerializeObject(lstStrate)); //批分库区量表 var batchesAreaResult = stockAreaList.BatchesAreaQty(sortingList, lstStrate); if (!batchesAreaResult.Success) return batchesAreaResult; Log.Info("批分库区结果 batchesAreaResult:", JsonConvert.SerializeObject(batchesAreaResult)); //波次实体 batchesResult.WaveMst = GetWaveEntity(batchesResult, waveNo); if (batchesResult.ShortageOutList.Any()) { //新的发货单赋值波次号 batchesResult.ShortageOutList.ForEach(f => { if (f.CN_S_STATE != Constants.State_Shortage) f.CN_S_WAVE_CODE = batchesResult.WaveMst.CN_S_WAVE_NO; }); } //分拣单实体 batchesResult.SortingList = sortingList; //库区量表实体 batchesResult.StockAreaList = stockAreaList; //创建波次分拣单 return BLLCreator.Create().WaveCreate(batchesResult); }); } #endregion #region 获取分拣单数据 /// /// 获取分拣单数据 /// /// /// /// /// public OperateResult GetSortingData(List outAreaResultList, UserRuleEntity user, string waveNo) { try { //分拣单 List sortingList = new List(); //分拣单组别 user.RuleCode = Constants.SortingGroup; string sortingGroup = user.GenerateNo(); //分拣单号 user.RuleCode = Constants.SortingNo; int sortingIndex = 1; IEnumerable> igOutAreaResult = outAreaResultList.GroupBy(x => new { x.stockCode, x.areaCode }); foreach (var _igOutAreaResult in igOutAreaResult) { //分拣单 TN_WM_SORTING_LISTEntity sortingEntity = new TN_WM_SORTING_LISTEntity() { CN_GUID = Guid.NewGuid().ToString(), CN_S_SORTING_NO = waveNo + "-" + sortingIndex++, CN_S_OP_FROM = Constants.Rule_WaveNo, CN_S_FROM_NO = waveNo, CN_T_OPERATE = DateTime.Now.ToString(),// "", //丢里咯木 CN_S_STOCK_CODE = _igOutAreaResult.Key.stockCode, CN_S_STOCK_AREA = _igOutAreaResult.Key.areaCode, CN_S_STATE = Constants.Sorting_Stay, CN_S_SEEDING_MODE = "", CN_S_GROUP = sortingGroup, CN_S_CREATOR = user.LoginCode, CN_S_CREATOR_BY = user.LoginName, CN_T_CREATE = DateTime.Now, CN_S_MODIFY = user.LoginCode, CN_S_MODIFY_BY = user.LoginName, CN_T_MODIFY = DateTime.Now }; //分拣单子表行索引 int sortingDtlindex = 1; //分拣单子表 sortingEntity.SortingDtlList = new List(); //分拣明细 sortingEntity.SortingLocationList = new List(); foreach (var outArea in _igOutAreaResult.AsEnumerable()) { foreach (var d in outArea.lstItem) { //物料详细 AutoBomItemEntity item = BLLCreator.Create().GetItemEntity(d.itemCode) ?? new AutoBomItemEntity(); //分拣单子行 TN_WM_SORTING_DTLEntity sortingDtlEntity = new TN_WM_SORTING_DTLEntity() { CN_GUID = Guid.NewGuid().ToString(), CN_S_SORTING_NO = sortingEntity.CN_S_SORTING_NO, CN_N_ROW_NO = sortingDtlindex++, CN_F_QUANTITY = d.itemQty, CN_S_ITEM_CODE = d.itemCode, CN_S_ITEM_NAME = item.CN_S_ITEM_NAME, CN_S_STATE = Constants.Sorting_Stay, CN_S_LOT_NO = outArea.batchCode, CN_S_PRODUCTION_BATCH = outArea.prodBatchCode, CN_S_ITEM_STATE = outArea.itemState, CN_S_OWNER = outArea.ownerName, CN_S_MODEL = item.CN_S_MODEL, CN_S_FIGURE_NO = item.CN_S_FIGURE_NO, CN_S_MEASURE_UNIT = item.CN_S_MEASURE_UNIT }; sortingEntity.SortingDtlList.Add(sortingDtlEntity); } } sortingList.Add(sortingEntity); } return OperateResult.Succeed(null, sortingList); } catch (Exception ex) { return OperateResult.Error(ex.Message); } } #endregion #region 获取波次实体 /// /// 获取波次实体 /// /// /// private TN_WM_WAVE_MSTEntity GetWaveEntity(BatchesResult bResult, string waveNo) { TN_WM_WAVE_MSTEntity waveMstEntity = new TN_WM_WAVE_MSTEntity() { CN_S_CREATE_TYPE = Constants.CreateType_Manual, CN_S_WAVE_NO = waveNo, CN_S_FROM = "WMS", CN_GUID = Guid.NewGuid().ToString(), CN_S_STATE = Constants.Sorting_Stay, CN_T_CREATE = DateTime.Now, CN_T_MODIFY = DateTime.Now, CN_T_OPERATE = DateTime.Now, CN_S_CREATOR = "自动", CN_S_CREATOR_BY = "auto", CN_S_MODIFY = "自动", CN_S_MODIFY_BY = "auto", CN_C_NEED_SEEDING = Constants.Y, CN_S_STATUS = Constants.State_New, CN_S_SEEDING_MODE = "", CN_S_STOCK_CODE = bResult.OutMstList[0].CN_S_STOCK_CODE }; waveMstEntity.WaveDtlList = new List(); int index = 1; foreach (var outDtl in bResult.OutMstList) { TN_WM_WAVE_DTLEntity waveDtlEntity = new TN_WM_WAVE_DTLEntity() { CN_GUID = Guid.NewGuid().ToString(), CN_S_WAVE_NO = waveNo, CN_S_ORDER_NO = outDtl.CN_S_OP_NO, CN_S_STATE = Constants.State_New, CN_T_CREATE = DateTime.Now, CN_T_MODIFY = DateTime.Now, CN_S_CREATOR = "自动", CN_S_CREATOR_BY = "auto", CN_S_MODIFY = "自动", CN_S_MODIFY_BY = "auto", CN_S_MSTGUID = waveMstEntity.CN_GUID, CN_N_ORDER = index++ }; waveMstEntity.WaveDtlList.Add(waveDtlEntity); } return waveMstEntity; } #endregion #region 获取分拣明细 /// ///获取分拣明细 /// /// /// /// private OperateResult GetSortingLocation(TN_WM_SORTING_LISTEntity sortingEntity) { try { //所有库区 var allAreas = BLLCreator.Create().GetArea(); //所有自动库区 var autoAreas = allAreas.FindAll(f => f.CN_C_IS_AUTO == Constants.Y); //当前库区 var currentArea = allAreas.Find(f => f.CN_S_AREA_CODE == sortingEntity.CN_S_STOCK_AREA); if (currentArea == null) { //未找到库区 string notFoundArea = "分拣单:{0}的库区:{1}在Mongo中未找到"; notFoundArea = string.Format(notFoundArea, sortingEntity.CN_S_SORTING_NO, sortingEntity.CN_S_STOCK_AREA); return OperateResult.Error(notFoundArea); } //自动库分拣处理 if (currentArea.CN_C_IS_AUTO == Constants.Y) { if (currentArea.CN_S_CURRENT_MODE != Constants.CurrentMode_Out) { //当前库区不为出库模式,不允许生成明细 string notOutMode = "库区:{0}的模式为:{1},不允许执行分拣,请切换到:{2}"; notOutMode = string.Format(notOutMode, currentArea.CN_S_AREA_CODE, currentArea.CN_S_CURRENT_MODE, Constants.CurrentMode_Out); return OperateResult.Error(notOutMode); } // if (currentArea.CN_N_PICK_MAX > 0) if(true) { //当前库区分拣中的分拣单 var beingSorting = BLLCreator.CreateDapper().GetList(new { CN_S_STOCK_AREA = sortingEntity.CN_S_STOCK_AREA, CN_S_STATE = Constants.Sorting_Being }); //当前库区分拣中的分拣单数达到最大数 //if (beingSorting.Count >= currentArea.CN_N_PICK_MAX) if (beingSorting.Count >=0) { //错误消息 string pickMaxError = "库区:{0}中正在分拣的分拣单数已达到可同时分拣的最大数:{1},请先分拣:{2}"; //pickMaxError = string.Format(pickMaxError, sortingEntity.CN_S_STOCK_AREA, // currentArea.CN_N_PICK_MAX, // string.Join(",", beingSorting.Select(s => s.CN_S_SORTING_NO)) // ); return OperateResult.Error(pickMaxError); } } //调算法获取明细 return AlgorithmLocation(sortingEntity); } else { //收货区和暂存区 if (currentArea.CN_S_AREA_CLASS == Constants.ReceivingArea || currentArea.CN_S_AREA_CLASS == Constants.TempStorageArea) { return OperateResult.Error("收货区和暂存区的分拣明细待开发"); } else//大件和平库的处理 { return OperateResult.Error("大件和平库的分拣明细待开发"); } } } catch (Exception ex) { return OperateResult.Error(ex.Message); } } #endregion #region 算法获取明细 /// /// 算法获取明细 /// /// /// private OperateResult AlgorithmLocation(TN_WM_SORTING_LISTEntity sortingEntity) { try { //分拣明细 List sortingLocationList = new List(); //调算法算货位 OperateResult outNewResult = OutNew(sortingEntity); if (!outNewResult.Success) return outNewResult; //算法结果 var outResult = outNewResult.GetData(); //算法结果 if (outResult.lstItemNotEnough.Any()) { outResult.lstItemNotEnough.ForEach(x => { var currentNotEnough = sortingEntity.SortingDtlList.Find(s => s.CN_S_ITEM_CODE.Equals(x.itemCode)); if (currentNotEnough != null) x.itemName = currentNotEnough.CN_S_ITEM_NAME; }); return OperateResult.Warning("物料:" + string.Join(";", outResult.lstItemNotEnough.Select(x => x.itemCode)) + "库存不足,请先完成来料区的上架", outResult.lstItemNotEnough); } if (!outResult.Success) return OperateResult.Error("算法异常:" + outResult.Msg); if (sortingEntity.SortingDtlList.Sum(x => x.CN_F_QUANTITY) != Convert.ToDecimal(outResult.itemLocations.Sum(x => x.itemQty))) { return OperateResult.Error("算法异常:返回的物料信息不完整!"); } var locations = outResult.itemLocations.Select(m => { AutoBomItemEntity mm = BLLCreator.Create().GetItemEntity(m.itemCode) ?? new AutoBomItemEntity(); return new TN_WM_SORTING_LOCATIONEntity() { CN_GUID = Guid.NewGuid().ToString(), CN_S_LOT_NO = m.batchCode, CN_S_ITEM_STATE = m.itemState, CN_S_OWNER = m.ownerName, CN_F_QUANTITY = m.itemQty, CN_F_PICKED_QTY = 0, CN_S_ITEM_CODE = m.itemCode, CN_S_LOCATION_CODE = m.locationCode, CN_S_TRAY_CODE = m.trayCode, CN_S_TRAY_GRID = m.trayGrid, CN_S_SORTING_NO = sortingEntity.CN_S_SORTING_NO, CN_S_STATE = sortingEntity.CN_S_STATE, CN_S_ORDER_NO = "", CN_S_CREATOR = "自动", CN_S_CREATOR_BY = "auto", CN_S_ITEM_NAME = mm.CN_S_ITEM_NAME, CN_S_MODEL = mm.CN_S_MODEL, CN_S_FIGURE_NO = mm.CN_S_FIGURE_NO, CN_S_MEASURE_UNIT = mm.CN_S_MEASURE_UNIT, CN_S_PACKING_UNIT = m.packUnit, CN_F_PACKING_QTY = m.packQty, CN_S_PRODUCTION_BATCH = m.prodBatchCode, CN_T_CREATE = DateTime.Now, CN_T_MODIFY = DateTime.Now }; }).ToList(); sortingLocationList.AddRange(locations); return OperateResult.Succeed(null, sortingLocationList); } catch (Exception ex) { return OperateResult.Error(ex.Message); } } #endregion #region 带出出库订单,批分,仓库实体 /// /// 带出出库订单实体 /// /// /// /// public OperateResult ChangeOutOperate(List outMst, Func, List, List, List, OperateResult> funcOut) { try { List batchesList = new List(); foreach (var _out in outMst) { _out.OutDtlList = BLLCreator.Create>().GetList(new { CN_S_OP_NO = _out.CN_S_OP_NO, CN_C_AUTO_INOUT = false }); //.FindAll(a => //{ // if (_out.CN_S_OUT_TYPE == Constants.OutType_BigOut) return true; // //物料详细 // AutoBomItemEntity item = BLLCreator.Create().GetItemEntity(a.CN_S_ITEM_CODE); // if (item == null) // throw new Exception("autobom中未找到物料:" + a.CN_S_ITEM_CODE); // if (item.CN_S_STORE_TYPE == Constants.BigArea) // a.CN_C_BIG = true; // return true; //}); batchesList.AddRange(_out.OutDtlList.Select(p => { return new BatchesEntity() { ItemCode = p.CN_S_ITEM_CODE, ItemState = p.CN_S_ITEM_STATE, ItemArrivalLot = p.CN_S_LOT_CODE, ItemProductionLot = p.CN_S_PRODUCTION_BATCH, Owner = _out.CN_S_OWNER, Qty = p.CN_F_QUANTITY, OpNo = _out.CN_S_OP_NO, OutMst = _out, IsFilter = p.CN_C_AUTO_INOUT }; }).ToList()); } //当前子表物料库存 var stockList = BLLCreator.Create>().GetList(new { CN_S_ITEM_CODE = batchesList.Select(p => p.ItemCode).ToList() }); //算法策略 List lstStrate = BLLCreator.Create().GetStrateListByAreaOrStock("", "", Constants.Out) .OrderByDescending(a => a.CN_N_PRIORITY).Select(o => o.CN_S_CODE).ToList(); return funcOut(outMst, batchesList, stockList, lstStrate); } catch (Exception ex) { return OperateResult.Error(ex.Message); } } #endregion #region 算库区 /// /// 算库区 /// /// /// private OperateResult OutArea(List outMstList) { try { //所有出库物料 var outItemList = new List(); outMstList.ForEach(p => { //子表货主赋值 p.OutDtlList.ForEach(q => q.CN_S_OWNER = p.CN_S_OWNER); outItemList.AddRange(p.OutDtlList); }); //初始化调用算法数据 List itemQuerys = outItemList.GroupBy(p => new { p.CN_S_ITEM_CODE, p.CN_S_ITEM_STATE, p.CN_S_OWNER, p.CN_S_LOT_CODE, p.CN_S_PRODUCTION_BATCH }).Select(x => new itemQueryClass() { itemCode = x.Key.CN_S_ITEM_CODE, batchCode = x.Key.CN_S_LOT_CODE, prodBatchCode = x.Key.CN_S_PRODUCTION_BATCH, itemState = x.Key.CN_S_ITEM_STATE, ownerName = x.Key.CN_S_OWNER, stockCode = outMstList[0].CN_S_STOCK_CODE, itemQty = x.Sum(y => y.CN_F_QUANTITY) }).ToList(); //初始化调用算法库区 var allArea = BLLCreator.Create().GetArea(); List lstAreaPrior = allArea.Select(p => new areaPriorClass() { areaCode = p.CN_S_AREA_CODE, Prior = p.CN_N_PRIORITY }).ToList(); Log.Info("调用OutArea参数 itemQuerys", JsonConvert.SerializeObject(itemQuerys)); Log.Info("调用OutArea参数 lstAreaPrior", JsonConvert.SerializeObject(lstAreaPrior)); //调用出库算法 string outAreaParams = JsonConvert.SerializeObject(new { itemQuerys = itemQuerys, lstAreaPrior = lstAreaPrior }); OutAreaResultAllEntity algorResultEntity = BLLCreator.Create().OutArea(itemQuerys, lstAreaPrior); Log.Info("algorResultEntity", JsonConvert.SerializeObject(algorResultEntity)); return OperateResult.Succeed(null, algorResultEntity); } catch (Exception ex) { return OperateResult.Error("WaveService-OutArea:" + ex.Message); } } #endregion #region 算货位 /// /// 算货位 /// /// /// private OperateResult OutNew(TN_WM_SORTING_LISTEntity sortingEntity) { try { //初始化调用算法数据 List algorItems = sortingEntity.SortingDtlList.GroupBy(x => new { x.CN_S_ITEM_CODE, x.CN_S_ITEM_STATE, x.CN_S_OWNER, x.CN_S_LOT_NO, x.CN_S_PRODUCTION_BATCH }).Select(y => new itemQueryClass() { stockCode = sortingEntity.CN_S_STOCK_CODE, areaCode = sortingEntity.CN_S_STOCK_AREA, itemCode = y.Key.CN_S_ITEM_CODE, batchCode = y.Key.CN_S_LOT_NO, prodBatchCode = y.Key.CN_S_PRODUCTION_BATCH, itemState = y.Key.CN_S_ITEM_STATE, ownerName = y.Key.CN_S_OWNER, itemQty = y.Sum(z => z.CN_F_QUANTITY) }).ToList(); var lstAreaPrior = algorItems.Select(x => new areaPriorClass() { areaCode = x.areaCode, Prior = 1 }).ToList(); OutAlgorEnitty outNewParams = new OutAlgorEnitty { lstDevice = new List(), lstAreaPrior = lstAreaPrior, lstQueryItem = algorItems, lockLocation = false }; Log.Info("调用OutNew参数 outNewParams", JsonConvert.SerializeObject(outNewParams)); OutResultEntityNew outResult = BLLCreator.Create().OutNew(outNewParams); Log.Info("调用OutNew返回值 outResult", JsonConvert.SerializeObject(outResult)); return OperateResult.Succeed(null, outResult); } catch (Exception ex) { return OperateResult.Error("WaveService-OutNew:" + ex.Message); } } #endregion } #region 波次配置 /// /// 波次配置 /// public class WaveConfig { public DateTime StartTime { get; set; } public DateTime EndTime { get; set; } public int SeveralMaxCreateWave { get; set; } public int LessMinute { get; set; } } #endregion }