using HH.WMS.BLL; using HH.WMS.BLL.Algorithm; using HH.WMS.BLL.Basic; using HH.WMS.BLL.Common; using HH.WMS.BLL.CoreServer; using HH.WMS.BLL.MoveStock; using HH.WMS.BLL.OutStock; using HH.WMS.Common; using HH.WMS.Common.Algorithm; using HH.WMS.Entitys; using HH.WMS.Entitys.Ams; using HH.WMS.Entitys.Basic; using HH.WMS.Entitys.Common; using HH.WMS.Entitys.Entitys; using HH.WMS.WebApi.Areas.Common.Controllers; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; namespace HH.WMS.WebApi.Areas.OutStock.Controllers { public class SortingController : BaseController { #region (PDA)获取的分拣单 /// /// (PDA)获取的分拣单 /// /// [HttpGet] public OperateResult GetCurrentSorting(string tokenId, string sortingNo = "") { return ValidateToken(tokenId, t => { TN_WM_SORTING_LISTEntity sortingEntity = new TN_WM_SORTING_LISTEntity(); sortingEntity.SortingLocationList = new List(); if (!string.IsNullOrEmpty(sortingNo)) { sortingEntity = BLLCreator.Create>().GetSingleEntity(new { CN_S_SORTING_NO = sortingNo }); if (sortingEntity == null) return OperateResult.Error("未找到分拣单:" + sortingNo); } else { sortingEntity = BLLCreator.Create>().GetSingleEntity(new { CN_S_STATE = Constants.Sorting_Being }); if (sortingEntity == null) { sortingEntity = BLLCreator.Create>().GetSingleEntity(new { CN_S_STATE = new List() { Constants.Sorting_Stay, Constants.Sorting_Being } }, " ORDER BY CN_T_CREATE"); if (sortingEntity == null) { return OperateResult.Error(""); } } } var sortingLocation = BLLCreator.Create>().GetList(new { CN_S_SORTING_NO = sortingEntity.CN_S_SORTING_NO }); sortingLocation = sortingLocation.GroupBy(x => new { x.CN_S_LOCATION_CODE, x.CN_S_TRAY_CODE }) .Select(y => new TN_WM_SORTING_LOCATIONEntity { CN_S_TRAY_CODE = y.Key.CN_S_TRAY_CODE, CN_S_LOCATION_CODE = y.Key.CN_S_LOCATION_CODE, CN_F_QUANTITY = y.Sum(z => z.CN_F_QUANTITY) }).ToList(); var sortingResult = BLLCreator.Create>().GetList(new { CN_S_SORTING_NO = sortingEntity.CN_S_SORTING_NO }); var result = new { SortingNo = sortingEntity.CN_S_SORTING_NO, AreaCode = sortingEntity.CN_S_STOCK_AREA, SortingState = sortingEntity.CN_S_STATE, LocationItems = sortingLocation.Select(x => new { TrayCode = x.CN_S_TRAY_CODE, LocationCode = x.CN_S_LOCATION_CODE, PickNum = x.CN_F_QUANTITY, PickedNum = sortingResult.Where(y => y.CN_S_LOCATION_CODE.Equals(x.CN_S_LOCATION_CODE)).Sum(z => z.CN_F_QUANTITY), PickState = sortingResult.Where(y => y.CN_S_LOCATION_CODE.Equals(x.CN_S_LOCATION_CODE)).Sum(z => z.CN_F_QUANTITY) == x.CN_F_QUANTITY ? "已拣" : "未拣"//暂时赋值 }).Where(m => m.PickState != "已拣") }; return OperateResult.Succeed(null, result); }); } #endregion #region (PDA)分拣单列表 /// /// (PDA)分拣单列表 /// /// /// [HttpGet] public OperateResult GetSortings(string tokenId, string key = "", string isBig = "") { return ValidateToken(tokenId, t => { var allAreas = GetStockArea(); var filterArea = isBig == Constants.Y ? allAreas.FindAll(f => f.CN_C_IS_AUTO != Constants.Y && f.CN_S_AREA_CLASS != Constants.BigArea) : allAreas.FindAll(f => f.CN_S_AREA_CLASS == Constants.BigArea); var sortingList = BLLCreator.CreateDapper().GetList(new { CN_S_STATE = new List { Constants.Sorting_Stay, Constants.Sorting_Being }, CN_S_SORTING_NO = Util.ToLike(key), CN_S_STOCK_AREA = filterArea.Select(s => s.CN_S_AREA_CODE).ToList() }); return OperateResult.Succeed(null, sortingList.Select(x => new { SortingNo = x.CN_S_SORTING_NO, AreaCode = (allAreas.Find(f => f.CN_S_AREA_CODE.Equals(x.CN_S_STOCK_AREA)) ?? new AutoBomStockAreaEntity()).CN_S_AREA_NAME, CreateTime = x.CN_T_CREATE.ToString(), FromNo = x.CN_S_FROM_NO, SortingState = x.CN_S_STATE })); }); } #endregion #region (PDA杭叉)分拣指引 /// /// (PDA杭叉)分拣指引 /// /// /// [HttpGet] public OperateResult SortingGuide(string sortingNo) { return ValidateToken(t => { var sortingEntity = BLLCreator.Create>().GetSingleEntity(new { CN_S_SORTING_NO = sortingNo }); if (sortingEntity == null) return OperateResult.Error("未找到分拣单:" + sortingNo); var trayItem = new List(); //待分拣时生成分拣明细 if (sortingEntity.CN_S_STATE == Constants.Sorting_Stay) { #region 生成分拣明细 //调用算法获取分拣明细,分拣明细改到执行分拣单的时候生成 var sortingLocationResult = BLLCreator.Create().GetSortingLocation(sortingEntity, new UserRuleEntity() { LoginCode = t.CN_S_LOGIN, LoginName = t.CN_S_NAME }); if (!sortingLocationResult.Success) return sortingLocationResult; var sortingLocations = sortingLocationResult.GetData>(); sortingEntity.SortingLocationList.AddRange(sortingLocations); #endregion #region 生成托盘分配量 //批分托盘物料分配量,改到执行分拣单的时候分配 //组织批分实体 var batchesTrayItem = sortingLocations.Select(x => new BatchesEntity() { TrayCode = x.CN_S_TRAY_CODE, ItemCode = x.CN_S_ITEM_CODE, Qty = x.CN_F_QUANTITY }).ToList(); trayItem = BLLCreator.Create>().GetList(new { CN_S_ITEM_CODE = batchesTrayItem.Select(x => x.ItemCode).ToList() }); var or = trayItem.BatchesTrayItemQty(batchesTrayItem, BatchesType.ForwardBatch); if (!or.Success) return or; #endregion #region 执行分拣单 //执行分拣单 or = BLLCreator.Create().ExecuteSorting(sortingEntity, trayItem); if (!or.Success) return or; #endregion } var currentSortingLocation = BLLCreator.CreateDapper().GetList(new { CN_S_SORTING_NO = sortingNo }); var result = currentSortingLocation .Where(w => w.CN_F_QUANTITY > w.CN_F_PICKED_QTY) .Select(s => new { TrayCode = s.CN_S_TRAY_CODE, Location = s.CN_S_LOCATION_CODE, Qty = s.CN_F_QUANTITY, PickedQty = s.CN_F_PICKED_QTY }); return OperateResult.Succeed(null, result); }); } #endregion #region (PDA杭叉)先拣后播页面数据 /// /// (PDA杭叉)先拣后播页面数据 /// /// /// /// [HttpGet] public OperateResult GetPickData(string sortingNo, string location) { return ValidateToken(t => { if (string.IsNullOrEmpty(sortingNo) || string.IsNullOrEmpty(location)) return OperateResult.Error("分拣单号或货位号不可为空"); var sortingLocations = BLLCreator.CreateDapper().GetList(new { CN_S_SORTING_NO = sortingNo }); var result = sortingLocations .Where(w => w.CN_S_LOCATION_CODE == location) .Select(s => new { ItemName = s.CN_S_ITEM_NAME, ItemCode = s.CN_S_ITEM_CODE, ItemState = s.CN_S_ITEM_STATE, ItemLotNo = s.CN_S_LOT_NO, ItemProLotNo = s.CN_S_PRODUCTION_BATCH, ItemModel = s.CN_S_MODEL, ItemFigureNo = s.CN_S_FIGURE_NO, ItemUnit = s.CN_S_MEASURE_UNIT, TrayGrid = s.CN_S_TRAY_GRID, Owner = s.CN_S_OWNER, PickNum = s.CN_F_QUANTITY, PickedNum = s.CN_F_PICKED_QTY }); return OperateResult.Succeed(null, result); }); } #endregion #region (PDA)执行分拣单 /// /// (PDA)执行分拣单 /// /// /// [HttpGet] public OperateResult ExecuteSorting(string tokenId, string sortingNo, string area = "") { return ValidateToken(tokenId, t => { var sortingEntity = BLLCreator.Create>().GetSingleEntity(new { CN_S_SORTING_NO = sortingNo }); if (sortingEntity == null) return OperateResult.Error("未找到分拣单:" + sortingNo); if (sortingEntity.CN_S_STATE != Constants.Sorting_Stay) return OperateResult.Error("当前分拣单不是待分拣,请重新选择"); var trayItem = new List(); if (sortingEntity.CN_S_OP_FROM != Constants.MoveOrder) { #region 自动库需要生成出库任务 //生成任务 List endAreas = new List(); var outTaskResult = BLLCreator.Create(t).GetOutTask(ref sortingEntity, ref endAreas, area); if (!outTaskResult.Success) { return outTaskResult; } #endregion } var result = BLLCreator.Create().ExecuteSorting(sortingEntity, trayItem); if (!result.Success) return result; string isUseAms = GetStrategy(sortingEntity.CN_S_STOCK_CODE, StrategyKey.IsUseAms); if (isUseAms == Constants.Y) { //return WebApiManager.("api/BillRule/GenBillNo", postData); var sortingLocation = BLLCreator.Create>().GetList(new { CN_S_SORTING_NO = sortingNo }); var amsAddTaskList = new List(); amsAddTaskList = sortingLocation.GroupBy(p => p.CN_S_LOCATION_CODE).Select(x => new AmsAddTask { businessType = "拣货", sysName = "WMS", deviceName = "WMS", locationFrom = x.Key, locationTo = "SYS", priority = 0 }).ToList(); if (amsAddTaskList.Any()) { Log.Info("ExecuteSorting 调用ams AddTask 发送亮灯指令参数 分拣单:" + sortingNo, JsonConvert.SerializeObject(amsAddTaskList)); string amsResult = WebApiManager.HttpAms_Post("api/HHAms/AddTask", JsonConvert.SerializeObject(amsAddTaskList)); Log.Info("ExecuteSorting 调用ams AddTask 返回值:", amsResult); } } return result; }); } #endregion #region (PDA)获取分拣货位明细 /// /// (PDA)获取分拣货位明细 /// /// /// /// [HttpGet] public OperateResult GetSortingLocation(string tokenId, string sortingNo, string locationCode) { return ValidateToken(tokenId, t => { Log.Info("GetSortingLocation tokenId", tokenId); Log.Info("GetSortingLocation sortingNo", sortingNo); Log.Info("GetSortingLocation locationCode", locationCode); var sortingLocations = BLLCreator.Create>().GetList(new { CN_S_SORTING_NO = sortingNo, CN_S_LOCATION_CODE = locationCode }); Log.Info("sortingLocations sortingLocations", JsonConvert.SerializeObject(sortingLocations)); sortingLocations = sortingLocations.GroupBy(x => new { x.CN_S_ITEM_CODE, x.CN_S_ITEM_NAME, x.CN_S_ITEM_STATE, x.CN_S_LOT_NO, x.CN_S_TRAY_CODE, x.CN_S_TRAY_GRID, x.CN_S_PRODUCTION_BATCH, x.CN_S_MODEL, x.CN_S_FIGURE_NO, x.CN_S_MEASURE_UNIT, x.CN_S_OWNER, x.CN_S_LOCATION_CODE }).Select(y => new TN_WM_SORTING_LOCATIONEntity() { CN_S_ITEM_CODE = y.Key.CN_S_ITEM_CODE, CN_S_ITEM_NAME = y.Key.CN_S_ITEM_NAME, CN_S_ITEM_STATE = y.Key.CN_S_ITEM_STATE, CN_S_LOT_NO = y.Key.CN_S_LOT_NO, CN_S_TRAY_CODE = y.Key.CN_S_TRAY_CODE, CN_S_TRAY_GRID = y.Key.CN_S_TRAY_GRID, CN_S_PRODUCTION_BATCH = y.Key.CN_S_PRODUCTION_BATCH, CN_S_MODEL = y.Key.CN_S_MODEL, CN_S_FIGURE_NO = y.Key.CN_S_FIGURE_NO, CN_S_MEASURE_UNIT = y.Key.CN_S_MEASURE_UNIT, CN_S_OWNER = y.Key.CN_S_OWNER, CN_S_LOCATION_CODE = y.Key.CN_S_LOCATION_CODE, CN_F_QUANTITY = y.Sum(z => z.CN_F_QUANTITY) }).ToList(); var sortingResult = BLLCreator.Create>().GetList(new { CN_S_SORTING_NO = sortingNo }); Log.Info("sortingLocations sortingResult", JsonConvert.SerializeObject(sortingResult)); //CN_C_IS_SN List items = (BLLCreator.Create().GetItemList(sortingLocations.Select(x => x.CN_S_ITEM_CODE).ToList()) ?? new List()); var result = new { LocationCode = locationCode, TrayCode = sortingLocations[0].CN_S_TRAY_CODE, PickItems = sortingLocations.Select(x => { var currentItem = items.Find(m => m.CN_S_ITEM_CODE.Equals(x.CN_S_ITEM_CODE)) ?? new AutoBomItemEntity(); decimal PackNum = 0; //包装数量为0取最小包装数,最小包装数为0取1 if (x.CN_F_PACKING_QTY == 0) { x.CN_F_PACKING_QTY = currentItem.CN_F_MIN_PACK_QTY; if (x.CN_F_PACKING_QTY == 0) x.CN_F_PACKING_QTY = 1; } else { if (x.CN_F_PACKING_QTY > 1) { PackNum = x.CN_F_QUANTITY / x.CN_F_PACKING_QTY.Value; } } return new { ItemName = x.CN_S_ITEM_NAME, ItemCode = x.CN_S_ITEM_CODE, ItemState = x.CN_S_ITEM_STATE, ItemLotNo = x.CN_S_LOT_NO, ItemProLotNo = x.CN_S_PRODUCTION_BATCH, ItemModel = x.CN_S_MODEL, TrayGrid = x.CN_S_TRAY_GRID, ItemFigureNo = x.CN_S_FIGURE_NO, ItemUnit = x.CN_S_MEASURE_UNIT, PackUnit = x.CN_S_PACKING_UNIT, PackQty = x.CN_F_PACKING_QTY, Owner = x.CN_S_OWNER, PickNum = x.CN_F_QUANTITY, IsSn = string.IsNullOrEmpty(currentItem.CN_C_IS_SN) ? "N" : currentItem.CN_C_IS_SN, PickedNum = sortingResult.FindAll(s => { s.CN_S_LOT_NO = s.CN_S_LOT_NO ?? ""; s.CN_S_PRODUCTION_BATCH = s.CN_S_PRODUCTION_BATCH ?? ""; x.CN_S_LOT_NO = x.CN_S_LOT_NO ?? ""; x.CN_S_PRODUCTION_BATCH = x.CN_S_PRODUCTION_BATCH ?? ""; return s.CN_S_ITEM_CODE.Equals(x.CN_S_ITEM_CODE) && s.CN_S_ITEM_STATE.Equals(x.CN_S_ITEM_STATE) && s.CN_S_OWNER.Equals(x.CN_S_OWNER) && (!string.IsNullOrEmpty(s.CN_S_PRODUCTION_BATCH) || s.CN_S_PRODUCTION_BATCH.Equals(x.CN_S_PRODUCTION_BATCH)) && s.CN_S_LOCATION_CODE.Equals(x.CN_S_LOCATION_CODE); }).Sum(q => q.CN_F_QUANTITY) }; }) }; Log.Info("sortingLocations result", JsonConvert.SerializeObject(result)); return OperateResult.Succeed(null, result); }); } #endregion #region (PDA三生)获取分拣货位明细 /// ///(PDA三生)获取分拣货位明细 /// /// /// /// /// public OperateResult GetSortingLocations(string tokenId, string sortingNo, string locationCode) { return ValidateToken(tokenId, t => { Log.Info("GetSortingLocations tokenId", tokenId); Log.Info("GetSortingLocations sortingNo", sortingNo); Log.Info("GetSortingLocations locationCode", locationCode); var sortingLocations = BLLCreator.Create>().GetList(new { CN_S_SORTING_NO = sortingNo, CN_S_LOCATION_CODE = locationCode }); Log.Info("sortingLocations sortingLocations", JsonConvert.SerializeObject(sortingLocations)); var sortingResult = BLLCreator.Create>().GetList(new { CN_S_SORTING_NO = sortingNo }); Log.Info("sortingLocations sortingResult", JsonConvert.SerializeObject(sortingResult)); sortingLocations = sortingLocations.GroupBy(x => { if (x.CN_F_PACKING_QTY > x.CN_F_QUANTITY) { x.CN_F_PACKING_QTY = 1; x.CN_S_PACKING_UNIT = ""; } return new { x.CN_S_ITEM_CODE, x.CN_S_ITEM_NAME, x.CN_S_ITEM_STATE, x.CN_S_TRAY_CODE, x.CN_S_TRAY_GRID, x.CN_S_PRODUCTION_BATCH, x.CN_S_MODEL, x.CN_S_MEASURE_UNIT, x.CN_S_OWNER, x.CN_S_LOCATION_CODE, x.CN_S_PACKING_UNIT, x.CN_F_PACKING_QTY }; }).Select(y => { var currentItemLocationPicked = sortingResult.FindAll(s => { s.CN_S_PRODUCTION_BATCH = s.CN_S_PRODUCTION_BATCH ?? ""; s.CN_S_PACKING_UNIT = s.CN_S_PACKING_UNIT ?? ""; return s.CN_S_ITEM_CODE.Equals(y.Key.CN_S_ITEM_CODE) && s.CN_S_ITEM_STATE.Equals(y.Key.CN_S_ITEM_STATE) && s.CN_S_OWNER.Equals(y.Key.CN_S_OWNER) && (string.IsNullOrEmpty(s.CN_S_PRODUCTION_BATCH) || s.CN_S_PRODUCTION_BATCH == y.Key.CN_S_PRODUCTION_BATCH) && s.CN_S_LOCATION_CODE.Equals(y.Key.CN_S_LOCATION_CODE) && s.CN_S_PACKING_UNIT == y.Key.CN_S_PACKING_UNIT; }).Sum(q => q.CN_F_QUANTITY); bool isMinUnit = false; isMinUnit = (string.IsNullOrEmpty(y.Key.CN_S_PACKING_UNIT)) || (y.Key.CN_F_PACKING_QTY <= 1); return new TN_WM_SORTING_LOCATIONEntity() { CN_S_ITEM_CODE = y.Key.CN_S_ITEM_CODE, CN_S_ITEM_NAME = y.Key.CN_S_ITEM_NAME, CN_S_ITEM_STATE = y.Key.CN_S_ITEM_STATE, CN_S_TRAY_CODE = y.Key.CN_S_TRAY_CODE, CN_S_TRAY_GRID = y.Key.CN_S_TRAY_GRID, CN_S_PRODUCTION_BATCH = y.Key.CN_S_PRODUCTION_BATCH, CN_S_MODEL = y.Key.CN_S_MODEL, CN_S_MEASURE_UNIT = y.Key.CN_S_MEASURE_UNIT, CN_S_OWNER = y.Key.CN_S_OWNER, CN_S_LOCATION_CODE = y.Key.CN_S_LOCATION_CODE, CN_S_PACKING_UNIT = y.Key.CN_S_PACKING_UNIT, CN_F_PACKING_QTY = y.Key.CN_F_PACKING_QTY, CN_F_QUANTITY = y.Sum(z => z.CN_F_QUANTITY) - currentItemLocationPicked, IsMinUnit = isMinUnit }; }).Where(m => m.CN_F_QUANTITY > 0).ToList(); List items = (BLLCreator.Create().GetItemList(sortingLocations.Select(x => x.CN_S_ITEM_CODE).ToList()) ?? new List()); var results = sortingLocations.GroupBy(x => new { x.CN_S_ITEM_CODE, x.CN_S_ITEM_NAME, x.CN_S_ITEM_STATE, x.CN_S_PRODUCTION_BATCH, x.CN_S_MODEL, x.CN_S_OWNER }).Select(y => { var currentItem = items.Find(m => m.CN_S_ITEM_CODE.Equals(y.Key.CN_S_ITEM_CODE)) ?? new AutoBomItemEntity(); var currentItems = sortingLocations.Where(m => m.CN_S_ITEM_CODE.Equals(y.Key.CN_S_ITEM_CODE) && m.CN_S_ITEM_STATE.Equals(y.Key.CN_S_ITEM_STATE) && m.CN_S_OWNER.Equals(y.Key.CN_S_OWNER) && m.CN_S_PRODUCTION_BATCH == y.Key.CN_S_PRODUCTION_BATCH).ToList(); //不属于最小包装单位的数据 var currentItemPack = currentItems.Where(o => !o.IsMinUnit).GroupBy(n => new { n.CN_S_PACKING_UNIT, n.CN_F_PACKING_QTY, n.CN_S_MEASURE_UNIT, }).Select(m => new TN_WM_SORTING_LOCATIONEntity { CN_S_PACKING_UNIT = m.Key.CN_S_PACKING_UNIT, CN_F_PACKING_QTY = m.Key.CN_F_PACKING_QTY, CN_S_MEASURE_UNIT = m.Key.CN_S_MEASURE_UNIT, CN_F_QUANTITY = m.Sum(k => k.CN_F_QUANTITY) }).ToList(); //最小包装单位的数据 currentItemPack.AddRange(currentItems.Where(o => o.IsMinUnit).GroupBy(n => new { n.CN_S_MEASURE_UNIT }).Select(m => new TN_WM_SORTING_LOCATIONEntity { CN_S_MEASURE_UNIT = m.Key.CN_S_MEASURE_UNIT, CN_F_QUANTITY = m.Sum(k => k.CN_F_QUANTITY) }).ToList()); string packUnit = string.Empty; decimal numOfPack = 1; foreach (var _currentItemPack in currentItemPack) { if (string.IsNullOrEmpty(_currentItemPack.CN_S_PACKING_UNIT) || _currentItemPack.CN_F_PACKING_QTY <= 1) { if (_currentItemPack.CN_F_PACKING_QTY < 1) _currentItemPack.CN_F_PACKING_QTY = currentItem.CN_F_MIN_PACK_QTY; if (_currentItemPack.CN_F_PACKING_QTY < 1) _currentItemPack.CN_F_PACKING_QTY = 1; _currentItemPack.WaitPickDetail = _currentItemPack.CN_F_QUANTITY + _currentItemPack.CN_S_MEASURE_UNIT; TN_WM_B_UNIQUE_BARCODEEntity uniqueBig = BLLCreator.CreateDapper().GetSingleEntity(new { CN_S_ITEM_CODE = _currentItemPack.CN_S_ITEM_CODE, CN_S_PARENT_CODE = "" }); if (uniqueBig != null) { numOfPack = Math.Round(Convert.ToDecimal(uniqueBig.CN_F_PACKING_QTY), 0); //packUnit = "箱"; packUnit = _currentItemPack.CN_S_PACKING_UNIT; } } else { string _packingUnit = "箱"; //packUnit = _packingUnit;// _currentItemPack.CN_S_PACKING_UNIT; packUnit = _currentItemPack.CN_S_PACKING_UNIT; numOfPack = _currentItemPack.CN_F_PACKING_QTY != null ? _currentItemPack.CN_F_PACKING_QTY.Value : 1; _currentItemPack.WaitPickDetail = (_currentItemPack.CN_F_QUANTITY / _currentItemPack.CN_F_PACKING_QTY) + _packingUnit; } } return new { ItemName = y.Key.CN_S_ITEM_NAME, ItemCode = y.Key.CN_S_ITEM_CODE, ItemState = y.Key.CN_S_ITEM_STATE, WaitPickDetail = string.Join(",", currentItemPack.Select(o => o.WaitPickDetail)), TotalNum = currentItems.Sum(o => o.CN_F_QUANTITY), ItemUnit = currentItems[0].CN_S_MEASURE_UNIT, PackUnit = packUnit, NumOfPack = numOfPack, ItemProLotNo = currentItem.CN_C_IS_LOT_OUT == "Y" ? y.Key.CN_S_PRODUCTION_BATCH : "", ItemModel = y.Key.CN_S_MODEL, Owner = y.Key.CN_S_OWNER, AuxiliaryUnitList = currentItem.AuxiliaryUnitList ?? new List(), }; }); Log.Info("sortingLocations result", JsonConvert.SerializeObject(results)); return OperateResult.Succeed(null, results); }); } #endregion #region (PDA)确认分拣 /// /// (PDA)确认分拣 /// /// /// [HttpPost] public OperateResult ConfirmSorting(dynamic confirmSorting) { Log.Info("确认分拣", JsonConvert.SerializeObject(confirmSorting)); string tokenId = Util.ToString(confirmSorting.tokenId); return ValidateToken(tokenId, t => { //分拣单 string sortingNo = Util.ToString(confirmSorting.SortingNo); //托盘 string trayCode = Util.ToString(confirmSorting.TrayCode); //当前货位是否全部捡完 bool locationPickFinish = false;// Convert.ToBoolean(confirmSorting.LocationPickFinish ?? false); if (confirmSorting.SortingResult == null) return OperateResult.Error("分拣物料不可为空"); //周转箱号 string boxNo = Util.ToString(confirmSorting.BoxNo); //分拣单实体 TN_WM_SORTING_LISTEntity sortingEntity = new TN_WM_SORTING_LISTEntity(); List sortingResult = JsonConvert.DeserializeObject>(Util.ToString(confirmSorting.SortingResult)); sortingResult.ForEach(p => { p.CN_GUID = Guid.NewGuid().ToString(); p.CN_S_SERIAL_NO = p.CN_S_SERIAL_NO ?? ""; p.CN_S_TRAY_CODE = p.CN_S_TRAY_CODE ?? ""; p.CN_S_TURNOVERBOX_CODE = p.CN_S_TURNOVERBOX_CODE ?? boxNo; p.CN_S_CREATOR = t.CN_S_LOGIN; p.CN_S_CREATOR_BY = t.CN_S_NAME; p.CN_T_CREATE = DateTime.Now; p.CN_S_MODIFY = t.CN_S_LOGIN; p.CN_S_MODIFY_BY = t.CN_S_NAME; p.CN_T_MODIFY = DateTime.Now; }); bool sortingPicked = false; //若当前货位捡完了,判断分拣单是否已全部捡完 var sortingLocations = BLLCreator.Create>().GetList(new { CN_S_SORTING_NO = sortingNo }); var sortingResults = BLLCreator.Create>().GetList(new { CN_S_SORTING_NO = sortingNo }); if (sortingLocations.Where(x => x.CN_S_LOCATION_CODE == sortingResult[0].CN_S_LOCATION_CODE).Sum(y => y.CN_F_QUANTITY) == (sortingResults.Where(x => x.CN_S_LOCATION_CODE == sortingResult[0].CN_S_LOCATION_CODE).Sum(y => y.CN_F_QUANTITY) + sortingResult.Sum(x => x.CN_F_QUANTITY))) { locationPickFinish = true; } Log.Info("locationPickFinish", locationPickFinish.ToString()); Log.Info("确认分拣", "locationPickFinish"); sortingEntity = BLLCreator.Create>().GetSingleEntity(new { CN_S_SORTING_NO = sortingNo }); if (locationPickFinish) { //分拣单本次全部捡完 if (sortingLocations.Sum(x => x.CN_F_QUANTITY) == (sortingResults.Sum(x => x.CN_F_QUANTITY) + sortingResult.Sum(x => x.CN_F_QUANTITY))) { sortingPicked = true; //sortingEntity = BLLCreator.Create>().GetSingleEntity(new //{ // CN_S_SORTING_NO = sortingNo //}); Log.Info("确认分拣", "isNeedUniPak"); //如果需要合箱,要判断所有分拣数据是否都已合箱 string isNeedUniPak = GetStrategy(sortingEntity.CN_S_STOCK_CODE, StrategyKey.IsNeedUniPak); Log.Info("确认分拣", isNeedUniPak); if (isNeedUniPak.Equals("Y")) { if (!string.IsNullOrEmpty(boxNo)) { foreach (var s in sortingResults) { if (string.IsNullOrEmpty(s.CN_S_TURNOVERBOX_CODE)) { sortingPicked = false; break; } } } else { sortingPicked = false; } } Log.Info("确认分拣", "002"); } } bool wavePicked = false; string waveNo = string.Empty; //分拣单捡完了,判断波次是否捡完 if (sortingPicked) { wavePicked = true; waveNo = sortingEntity.CN_S_FROM_NO; var sortingList = BLLCreator.Create>().GetList(new { CN_S_FROM_NO = sortingEntity.CN_S_FROM_NO }); //找波次下其他分拣单是否为已分拣 foreach (var s in sortingList.Where(x => x.CN_S_SORTING_NO != sortingNo)) { if (s.CN_S_STATE != Constants.Sorting_Sorted) { wavePicked = false; break; } } } Log.Info("确认分拣", "ConfirmSorting"); var result = BLLCreator.Create().ConfirmSorting(sortingPicked, wavePicked, waveNo, sortingResult, boxNo); Log.Info("确认分拣", "result"); if (!result.Success) return result; Log.Info("确认分拣", "result"); //当前货位捡完了,发送灭灯指令 if (locationPickFinish) { Log.Info("locationPickFinish", "start"); //分拣单捡完,并且是移库单 if (sortingPicked && sortingEntity.CN_S_OP_FROM.Equals(Constants.MoveOrder)) { Log.Info("移库单分拣完成", JsonConvert.SerializeObject(sortingEntity)); var moveResult = BLLCreator.Create().MoveSortingComplete(sortingEntity.CN_S_FROM_NO, t.CN_S_LOGIN, t.CN_S_NAME, t.CN_S_ORG_GUID, t.CN_S_ORGFLAG); Log.Info("调用移库完成接口结果", JsonConvert.SerializeObject(moveResult)); if (!moveResult.Success) return OperateResult.Error("分拣单已捡完,调用移库完成接口错误:" + moveResult.Exception.Message); } string isUseAms = GetStrategy(sortingEntity.CN_S_STOCK_CODE, StrategyKey.IsUseAms); Log.Info("sortingEntity.CN_S_STOCK_CODE", sortingEntity.CN_S_STOCK_CODE); Log.Info("StrategyKey.IsUseAms", StrategyKey.IsUseAms); //Log.Info("sortingEntity", JsonConvert.SerializeObject(sortingEntity)); Log.Info("isUseAms", isUseAms); if (isUseAms.Equals("Y")) { var completeTaskParam = new { EndBit = sortingResult[0].CN_S_LOCATION_CODE, Status = "作业完成" }; Log.Info("ConfirmSorting 调用Ams发送灭灯指令参数 分拣单:" + sortingNo + " 货位:" + sortingResult[0].CN_S_LOCATION_CODE, JsonConvert.SerializeObject(completeTaskParam)); string amsResult = WebApiManager.HttpAms_Post("api/HHAms/CompleteTask", JsonConvert.SerializeObject(completeTaskParam)); Log.Info("ConfirmSorting 调用Ams发送灭灯指令返回值", amsResult); } } return result; }); } #endregion #region (PDA)扫描周转箱 /// /// (PDA)扫描周转箱 /// /// /// /// [HttpGet] public OperateResult ScanBox(string boxNo, string sortingNo) { return ValidateToken(t => { var trayInfoEntity = BLLCreator.Create>().GetSingleEntity(new { CN_S_TRAY_CODE = boxNo }); if (trayInfoEntity == null) return OperateResult.Error("未找到容器:" + boxNo); if (trayInfoEntity.CN_S_STATE.Equals(Constants.TrayState_InUse)) { if (!string.IsNullOrEmpty(trayInfoEntity.CN_S_SORTING_CODE) && !trayInfoEntity.CN_S_SORTING_CODE.Equals(sortingNo)) { return OperateResult.Error("周转箱:" + boxNo + "已绑定了分拣单:" + trayInfoEntity.CN_S_SORTING_CODE); } } return OperateResult.Succeed(null, trayInfoEntity); }); } #endregion #region (PDA)合箱 /// /// (PDA)合箱 /// /// /// /// [HttpGet] public OperateResult MergeBox(string sortingNo, string boxNo) { return ValidateToken(t => { var sortingEntity = BLLCreator.Create>().GetSingleEntity(new { CN_S_SORTING_NO = sortingNo }); if (sortingEntity == null) return OperateResult.Error("未找到分拣单:" + sortingNo); if (sortingEntity.CN_S_STATE.Equals(Constants.Sorting_Sorted)) { return OperateResult.Error("该分拣单已分拣完成,无需合箱"); } var sortingLocations = BLLCreator.Create>().GetList(new { CN_S_SORTING_NO = sortingNo }); var sortingResults = BLLCreator.Create>().GetList(new { CN_S_SORTING_NO = sortingNo }); bool sortingPicked = false; //分拣单全部捡完 if (sortingLocations.Sum(x => x.CN_F_QUANTITY) == (sortingResults.Sum(x => x.CN_F_QUANTITY))) { sortingPicked = true; } bool wavePicked = false; string waveNo = string.Empty; //分拣单捡完了,判断波次是否捡完 if (sortingPicked) { wavePicked = true; waveNo = sortingEntity.CN_S_FROM_NO; var sortingList = BLLCreator.Create>().GetList(new { CN_S_FROM_NO = sortingEntity.CN_S_FROM_NO }); //找波次下其他分拣单是否为已分拣 foreach (var s in sortingList.Where(x => x.CN_S_SORTING_NO != sortingNo)) { if (s.CN_S_STATE != Constants.Sorting_Sorted) { wavePicked = false; break; } } } List sortingResult = new List(); foreach (var s in sortingResults) { if (string.IsNullOrEmpty(s.CN_S_TURNOVERBOX_CODE)) { s.CN_S_TURNOVERBOX_CODE = boxNo; sortingResult.Add(s); } } if (!sortingResult.Any()) { return OperateResult.Error("未找到该分拣单需要合箱的数据!"); } return BLLCreator.Create().MergeBox(sortingResult, sortingPicked, wavePicked, waveNo); }); } #endregion #region (PDA汇聚)根据分拣单获取波次下所有发货通知单和分拣明细 /// /// (PDA汇聚)根据分拣单获取波次下所有发货通知单和分拣明细 /// /// /// /// [HttpGet] public OperateResult GetBJBBSortingData(string sortingNo, string locationCode) { return ValidateToken(t => { var sortingEntity = BLLCreator.CreateDapper().GetSingleEntity(new { CN_S_SORTING_NO = sortingNo }); if (sortingEntity == null) return OperateResult.Error("未找到分拣单:" + sortingNo); //当前分拣单当前货位 var currentSortingLocation = BLLCreator.CreateDapper().GetList(new { CN_S_SORTING_NO = sortingNo, CN_S_LOCATION_CODE = locationCode }); //当前分拣单波次下所有出库单 var currentWaveOut = BLLCreator.Create().GetOutListByWave(sortingEntity.CN_S_FROM_NO); //订单拣货数据 var orderSortingRels = BLLCreator.CreateDapper().GetList(new { CN_S_ORDER_NO = currentWaveOut.Select(s => s.CN_S_OP_NO).ToList() }); //批分每个出库单每个物料拣了多少个 foreach (var currentOut in currentWaveOut) { var curOrderSorting = orderSortingRels.Where(s => s.CN_S_ORDER_NO == currentOut.CN_S_OP_NO); foreach (var currentOutDtl in currentOut.OutDtlList) { var equalsCurOS = curOrderSorting.Where(w => w.CN_S_ITEM_CODE == currentOutDtl.CN_S_ITEM_CODE && w.CN_S_ITEM_STATE == currentOutDtl.CN_S_ITEM_STATE && w.CN_S_OWNER == currentOut.CN_S_OWNER && (w.CN_S_LOT_NO == currentOutDtl.CN_S_LOT_CODE || string.IsNullOrEmpty(currentOutDtl.CN_S_LOT_CODE))); foreach (var curOS in equalsCurOS) { var qty = currentOutDtl.CN_F_QUANTITY - currentOutDtl.CN_F_PICKED_QTY; if (qty == 0) break; if (curOS.CN_F_QUANTITY == 0) continue; if (curOS.CN_F_QUANTITY >= qty) { currentOutDtl.CN_F_PICKED_QTY += qty; curOS.CN_F_QUANTITY -= qty; } else { currentOutDtl.CN_F_PICKED_QTY += curOS.CN_F_QUANTITY; curOS.CN_F_QUANTITY = 0; } } } } var result = new { SortingLocations = currentSortingLocation, OutData = currentWaveOut, SortingBit = new string[] { "FJT01", "FJT02", "FJT03", "FJT04", } }; return OperateResult.Succeed(null, result); }); } #endregion public OperateResult SaveXJHB(dynamic saveData) { string tokenId = Util.ToString(saveData.tokenId); return ValidateToken(tokenId, t => { Log.Info("SaveXJHB", JsonConvert.SerializeObject(saveData)); //分拣结果 List sortingResult = JsonConvert.DeserializeObject>(Util.ToString(saveData.SortingResult)); if (!sortingResult.Any()) return OperateResult.Error("分拣结果数据不可为空"); string sortingNo = Util.ToString(saveData.SortingNo); if (string.IsNullOrEmpty(sortingNo)) return OperateResult.Error("分拣单号不可为空"); //周转箱号 string boxNo = Util.ToString(saveData.BoxNo); var sortingLocations = BLLCreator.CreateDapper().GetList(new { CN_S_SORTING_NO = sortingNo, }); //当前分拣明细的当前分拣物料 var pickedItemLocations = sortingLocations.Where(w => w.CN_S_TRAY_CODE == sortingResult[0].CN_S_TRAY_CODE && w.CN_S_LOCATION_CODE == sortingResult[0].CN_S_LOCATION_CODE && sortingResult.Exists(e => e.CN_S_ITEM_CODE == w.CN_S_ITEM_CODE)).ToList(); //批分分拣明细分拣数量 foreach (var sr in sortingResult) { foreach (var pickedItem in pickedItemLocations) { if (sr.CN_F_QUANTITY == 0) break; var stayQty = pickedItem.CN_F_QUANTITY - pickedItem.CN_F_PICKED_QTY; if (stayQty == 0) continue; if (sr.CN_F_QUANTITY >= stayQty) { pickedItem.CN_F_PICKED_QTY += stayQty; sr.CN_F_QUANTITY -= stayQty; } else { pickedItem.CN_F_PICKED_QTY += sr.CN_F_QUANTITY; sr.CN_F_QUANTITY = 0; } } } //分拣单,波次是否已分拣 bool sortingPicked = false; bool wavePicked = false; //分拣单是否全部分拣完 , 必须拣完并且全部合箱 if (sortingLocations.Sum(s => s.CN_F_QUANTITY) == sortingLocations.Sum(s => s.CN_F_PICKED_QTY)) { var allSortingResult = BLLCreator.CreateDapper().GetList(new { CN_S_SORTING_NO = sortingNo, }); if (!string.IsNullOrEmpty(boxNo) && !allSortingResult.Exists(e => string.IsNullOrEmpty(e.CN_S_TURNOVERBOX_CODE))) sortingPicked = true; } //当前分拣单实体 var currentSorting = BLLCreator.CreateDapper().GetSingleEntity(new { CN_S_SORTING_NO = sortingResult[0].CN_S_SORTING_NO }); #region 分拣单捡完了,判断波次有没有捡完 //分拣单捡完了,判断波次有没有捡完 if (sortingPicked) { var waveSortings = BLLCreator.CreateDapper().GetList(new { CN_S_FROM_NO = currentSorting.CN_S_FROM_NO }); if (!(waveSortings.Exists(e => e.CN_S_STATE != Constants.Sorting_Sorted))) wavePicked = true; } #endregion #region 如果分拣单拣完了,批分库区降库存 List areaQtyList = new List(); //算法策略 List lstStrate = BLLCreator.Create().GetStrateListByAreaOrStock("", "", Constants.Out) .OrderByDescending(a => a.CN_N_PRIORITY).Select(o => o.CN_S_CODE).ToList(); Log.Info("确认分拣", "lstStrate"); //分拣单都拣完了,批分库区降库存 if (sortingPicked) { Log.Info("确认分拣sortingResult", JsonConvert.SerializeObject(sortingResult)); if (currentSorting != null) { var currentSortingDtl = BLLCreator.CreateDapper() .GetList(new { CN_S_SORTING_NO = currentSorting.CN_S_SORTING_NO }); currentSorting.SortingDtlList = currentSortingDtl; areaQtyList = BLLCreator.CreateDapper().GetList(new { CN_S_ITEM_CODE = currentSortingDtl.Select(x => x.CN_S_ITEM_CODE).ToList() }); //反批分库区分配量 Log.Info("确认分拣反批分库区分配量", "BatchesAreaQty"); var result = areaQtyList.BatchesAreaQty(new List() { currentSorting }, lstStrate, true); Log.Info("确认分拣反批分库区分配量结果", JsonConvert.SerializeObject(result)); if (!result.Success) return result; } } #endregion #region 批分托盘物料关联,降分配量,删子表,解货位 //分拣结果的托盘物料关联数据 var trayItemMstList = BLLCreator.Create().BatchesTrayItemByResult(sortingResult); var currentTrayLocation = BLLCreator.CreateDapper().GetSingleEntity(new { CN_S_TRAY_CODE = sortingResult[0].CN_S_TRAY_CODE }); #endregion #region 初始化分拣结果 sortingResult.ForEach(p => { p.CN_GUID = Guid.NewGuid().ToString(); p.CN_S_SERIAL_NO = p.CN_S_SERIAL_NO ?? ""; p.CN_S_TRAY_CODE = p.CN_S_TRAY_CODE ?? ""; p.CN_S_TURNOVERBOX_CODE = p.CN_S_TURNOVERBOX_CODE ?? boxNo; p.CN_S_CREATOR = t.CN_S_LOGIN; p.CN_S_CREATOR_BY = t.CN_S_NAME; p.CN_T_CREATE = DateTime.Now; p.CN_S_MODIFY = t.CN_S_LOGIN; p.CN_S_MODIFY_BY = t.CN_S_NAME; p.CN_T_MODIFY = DateTime.Now; }); #endregion SavePickEntity savePickEntity = new SavePickEntity() { CurrentSorting = currentSorting, SortingPicked = sortingPicked, WavePicked = wavePicked, BoxNo = boxNo, WaveNo = currentSorting.CN_S_FROM_NO, SortingNo = currentSorting.CN_S_SORTING_NO, SortingResult = sortingResult, SortingLocation = pickedItemLocations, TrayItemList = trayItemMstList, TrayLocation = currentTrayLocation, AreaQtyList = areaQtyList }; return BLLCreator.Create().SaveXJHB(savePickEntity); }); } #region (PDA汇聚)保存边拣边播 /// /// (PDA汇聚)保存边拣边播 /// /// /// public OperateResult SaveBJBB(dynamic saveData) { string tokenId = Util.ToString(saveData.tokenId); return ValidateToken(tokenId, t => { Log.Info("保存边拣边播SaveBJBB", JsonConvert.SerializeObject(saveData)); //分拣结果 List sortingResult = JsonConvert.DeserializeObject>(Util.ToString(saveData.SortingResult)); if (!sortingResult.Any()) return OperateResult.Error("分拣结果数据不可为空"); List orderSortingRel = JsonConvert.DeserializeObject>(Util.ToString(saveData.OrderSortingRel)); if (!orderSortingRel.Any()) return OperateResult.Error("订单拣货明细不可为空"); //周转箱号 string boxNo = Util.ToString(saveData.BoxNo); if (string.IsNullOrEmpty(boxNo)) return OperateResult.Error("合箱容器号不可为空"); var sortingLocations = BLLCreator.CreateDapper().GetList(new { CN_S_SORTING_NO = sortingResult[0].CN_S_SORTING_NO, }); var pickedItemLocations = sortingLocations.Where(w => w.CN_S_TRAY_CODE == sortingResult[0].CN_S_TRAY_CODE && w.CN_S_LOCATION_CODE == sortingResult[0].CN_S_LOCATION_CODE && sortingResult.Exists(e => e.CN_S_ITEM_CODE == w.CN_S_ITEM_CODE)).ToList(); //批分分拣明细分拣数量 foreach (var sr in sortingResult) { foreach (var pickedItem in pickedItemLocations) { if (sr.CN_F_QUANTITY == 0) break; var stayQty = pickedItem.CN_F_QUANTITY - pickedItem.CN_F_PICKED_QTY; if (stayQty == 0) continue; if (sr.CN_F_QUANTITY >= stayQty) { pickedItem.CN_F_PICKED_QTY += stayQty; sr.CN_F_QUANTITY -= stayQty; } else { pickedItem.CN_F_PICKED_QTY += sr.CN_F_QUANTITY; sr.CN_F_QUANTITY = 0; } } } //分拣单,波次是否已分拣 bool sortingPicked = false; bool wavePicked = false; //分拣单是否全部分拣完 if (sortingLocations.Sum(s => s.CN_F_QUANTITY) == sortingLocations.Sum(s => s.CN_F_PICKED_QTY)) sortingPicked = true; //当前分拣单实体 var currentSorting = BLLCreator.CreateDapper().GetSingleEntity(new { CN_S_SORTING_NO = sortingResult[0].CN_S_SORTING_NO }); #region 分拣单捡完了,判断波次有没有捡完 //分拣单捡完了,判断波次有没有捡完 if (sortingPicked) { var waveSortings = BLLCreator.CreateDapper().GetList(new { CN_S_FROM_NO = currentSorting.CN_S_FROM_NO }); if (!(waveSortings.Exists(e => e.CN_S_STATE != Constants.Sorting_Sorted))) wavePicked = true; } #endregion #region 如果分拣单拣完了,批分库区降库存 List areaQtyList = new List(); //算法策略 List lstStrate = BLLCreator.Create().GetStrateListByAreaOrStock("", "", Constants.Out) .OrderByDescending(a => a.CN_N_PRIORITY).Select(o => o.CN_S_CODE).ToList(); Log.Info("确认分拣", "lstStrate"); //分拣单都拣完了,批分库区降库存 if (sortingPicked) { Log.Info("确认分拣sortingResult", JsonConvert.SerializeObject(sortingResult)); if (currentSorting != null) { var currentSortingDtl = BLLCreator.CreateDapper() .GetList(new { CN_S_SORTING_NO = currentSorting.CN_S_SORTING_NO }); currentSorting.SortingDtlList = currentSortingDtl; areaQtyList = BLLCreator.CreateDapper().GetList(new { CN_S_ITEM_CODE = currentSortingDtl.Select(x => x.CN_S_ITEM_CODE).ToList() }); //反批分库区分配量 Log.Info("确认分拣反批分库区分配量", "BatchesAreaQty"); var result = areaQtyList.BatchesAreaQty(new List() { currentSorting }, lstStrate, true); Log.Info("确认分拣反批分库区分配量结果", JsonConvert.SerializeObject(result)); if (!result.Success) return result; } } #endregion #region 批分托盘物料关联,降分配量,删子表,解货位 //分拣结果的托盘物料关联数据 var trayItemMstList = BLLCreator.Create().BatchesTrayItemByResult(sortingResult); var currentTrayLocation = BLLCreator.CreateDapper().GetSingleEntity(new { CN_S_TRAY_CODE = sortingResult[0].CN_S_TRAY_CODE }); #endregion #region 初始化分拣结果,订单拣货明细实体 sortingResult.ForEach(p => { p.CN_GUID = Guid.NewGuid().ToString(); p.CN_S_SERIAL_NO = p.CN_S_SERIAL_NO ?? ""; p.CN_S_TRAY_CODE = p.CN_S_TRAY_CODE ?? ""; p.CN_S_TURNOVERBOX_CODE = p.CN_S_TURNOVERBOX_CODE ?? boxNo; p.CN_S_CREATOR = t.CN_S_LOGIN; p.CN_S_CREATOR_BY = t.CN_S_NAME; p.CN_T_CREATE = DateTime.Now; p.CN_S_MODIFY = t.CN_S_LOGIN; p.CN_S_MODIFY_BY = t.CN_S_NAME; p.CN_T_MODIFY = DateTime.Now; }); orderSortingRel.ForEach(p => { p.CN_GUID = Guid.NewGuid().ToString(); p.CN_S_SERIAL_NO = p.CN_S_SERIAL_NO ?? ""; p.CN_S_CREATOR = t.CN_S_LOGIN; p.CN_S_CREATOR_BY = t.CN_S_NAME; p.CN_T_CREATE = DateTime.Now; p.CN_S_MODIFY = t.CN_S_LOGIN; p.CN_S_MODIFY_BY = t.CN_S_NAME; p.CN_T_MODIFY = DateTime.Now; }); #endregion SavePickEntity savePickEntity = new SavePickEntity() { CurrentSorting = currentSorting, SortingPicked = sortingPicked, WavePicked = wavePicked, BoxNo = boxNo, WaveNo = currentSorting.CN_S_FROM_NO, SortingNo = currentSorting.CN_S_SORTING_NO, SortingResult = sortingResult, SortingLocation = pickedItemLocations, OrderSortingRel = orderSortingRel, TrayItemList = trayItemMstList, TrayLocation = currentTrayLocation, AreaQtyList = areaQtyList }; return BLLCreator.Create().SaveBJBB(savePickEntity); }); } #endregion #region (PDA汇聚)分拣回和搬运 /// /// (PDA汇聚)分拣回和搬运 /// /// /// [HttpGet] public OperateResult Transport(string trayCode, string endArea, string sortingNo = "") { return ValidateToken(t => { //找是否已经存在该托盘未执行完的任务 var existsTask = BLLCreator.CreateDapper().GetSingleEntity(new { CN_S_TRAY_CODE = trayCode, CN_S_STATE = new List() { Constants.TaskState_NoExecuted, Constants.TaskState_Executing }, }); if (existsTask != null) return OperateResult.Error("托盘:" + trayCode + "存在未执行完的任务"); //当前托盘所在位置 var currentTrayLocation = BLLCreator.CreateDapper() .GetSingleEntity(new { CN_S_TRAY_CODE = trayCode }); //需要调作业区入库算法,算出货位给出库任务 var inAssignEntity = new InAssignEntity { objectType = InAssignEntity.ObjectType.托盘, objectCode = trayCode, lockLocation = false, lstAreaPrior = new List() { { new areaPriorClass{ areaCode = endArea, 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); //整托出库任务 string postData = "{\"appCode\":\"" + Constants.appCode + "\",\"ruleName\":\"" + Constants.Rule_TaskNo + "\",\"orgId\":\"\",\"orgFlag\":\"\"}"; string taskNo = WebApiManager.HttpAutoBom_Post("api/BillRule/GenBillNo", postData); string taskType = string.IsNullOrEmpty(sortingNo) ? Constants.TaskType_Transport : Constants.TaskType_SortingIn; TN_WM_TASKEntity taskEntity = new TN_WM_TASKEntity() { CN_S_TASK_NO = taskNo, CN_S_TASK_TYPE = taskType, CN_S_FROM_OP = Constants.Out, CN_S_FROM_NO = sortingNo, CN_S_TRAY_CODE = trayCode, CN_S_STOCK_CODE = currentTrayLocation.CN_S_STOCK_CODE, CN_S_START_AREA = currentTrayLocation.CN_S_STOCK_AREA, CN_S_START_BIT = currentTrayLocation.CN_S_LOCATION_CODE, CN_S_END_AREA = endArea, CN_S_END_BIT = inAssignResultEntity.locationCode, CN_S_STATE = Constants.TaskState_NoExecuted, CN_T_CREATE = DateTime.Now, CN_T_MODIFY = DateTime.Now }; return BLLCreator.Create().Transport(taskEntity); }); } #endregion #region 获取分拣明细 /// ///获取分拣明细 /// /// /// /// private OperateResult GetSortingLocation(TN_WM_SORTING_LISTEntity sortingEntity, UserRuleEntity user) { try { List sortingLocationList = new List(); //初始化调用算法数据 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(); Log.Info("调用OutNew参数 algorItems", JsonConvert.SerializeObject(algorItems)); var outResult = BLLCreator.Create().OutNew(new OutAlgorEnitty() { lstDevice = new List(), lstAreaPrior = lstAreaPrior, lstQueryItem = algorItems, lockLocation = false }); Log.Info("调用OutNew返回值 outResult", JsonConvert.SerializeObject(outResult)); 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().GetItem(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 = user.LoginCode, CN_S_CREATOR_BY = user.LoginName, 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 分拣单列表 /// /// 分拣单列表 /// /// /// [HttpPost] public string GetSortingList(SearchModel searchModel) { OperateResult result = new OperateResult(); try { long total = 0; DataTable dt = BLLCreator.Create>().GetPagingData(new List() { new SearchWhere(){ key="CN_S_SORTING_NO", sign= WhereSign.Like, value=Util.ToString(searchModel.SearchCondition.SortingNo)} }, searchModel.PageIndex, searchModel.PageSize, out total, true, new { CN_S_SORTING_NO = "%" + Util.ToString(searchModel.SearchCondition.SortingNo) + "%" }); dt.Columns["CN_S_STOCK_CODE"].ReadOnly = false; foreach (DataRow dr in dt.Rows) { dr["CN_S_STOCK_CODE"] = GetStock().Find(x => x.CN_S_STOCK_CODE.Equals(dr["CN_S_STOCK_CODE"].ToString().Trim())).CN_S_STOCK_NAME; dr["CN_S_STOCK_AREA"] = GetStockArea().Find(x => x.CN_S_AREA_CODE.Equals(dr["CN_S_STOCK_AREA"].ToString().Trim())).CN_S_AREA_NAME; } result = OperateResult.Succeed("", new { rows = dt, total = total }); } catch (Exception ex) { result = OperateResult.Error(ex.Message); } IsoDateTimeConverter timeFormat = new IsoDateTimeConverter(); timeFormat.DateTimeFormat = "yyyy-MM-dd HH:mm:ss"; return JsonConvert.SerializeObject(result, timeFormat); //return result; } #endregion #region 分拣数据 /// /// 分拣数据 /// /// /// [HttpGet] public OperateResult GetSortingDtl(string sortingNo) { try { var sortingDtl = BLLCreator.Create>().GetList(new { CN_S_SORTING_NO = sortingNo }); return OperateResult.Succeed(null, sortingDtl); } catch (Exception ex) { return OperateResult.Error(ex.Message); } } #endregion #region 分拣明细 /// /// 分拣明细 /// /// /// [HttpGet] public OperateResult GetCurrentSortingLocation(string sortingNo) { try { var sortingDtl = BLLCreator.Create>().GetList(new { CN_S_SORTING_NO = sortingNo }); return OperateResult.Succeed(null, sortingDtl); } catch (Exception ex) { return OperateResult.Error(ex.Message); } } #endregion #region 分拣结果 /// /// 分拣结果 /// /// /// [HttpGet] public OperateResult GetSortingResult(string sortingNo) { try { var sortingDtl = BLLCreator.Create>().GetList(new { CN_S_SORTING_NO = sortingNo }); return OperateResult.Succeed(null, sortingDtl); } catch (Exception ex) { return OperateResult.Error(ex.Message); } } #endregion #region 查询分拣单实体 /// /// 查询盘点单实体 /// /// 分拣单号 /// /// [Hanhe(dbs)] creater 2018/12/20 public OperateResult GetSortingModel(string sortingNo) { try { return ValidateToken(t => { TN_WM_SORTING_LISTEntity sorting = BLLCreator.Create>().GetSingleEntity(new { CN_S_SORTING_NO = sortingNo }); if (sorting != null) sorting.CN_S_STOCK_AREA = this.GetStockArea().Find(x => x.CN_S_AREA_CODE.Equals(sorting.CN_S_STOCK_AREA)).CN_S_AREA_NAME; return OperateResult.Succeed(null, sorting); }); } catch (Exception ex) { return OperateResult.Error(ex.Message); } } #endregion #region 订单拣货明细 /// /// 订单拣货明细 /// /// /// [HttpGet] public OperateResult GetOrderSortingRel(string opNo) { try { var sortingDtl = BLLCreator.Create>().GetList(new { CN_S_ORDER_NO = opNo }); return OperateResult.Succeed(null, sortingDtl); } catch (Exception ex) { return OperateResult.Error(ex.Message); } } #endregion #region 根据出库单号获取订单拣货明细 /// /// 根据出库单号获取订单拣货明细 /// /// /// [HttpGet] public OperateResult GetOrderSortingRelByOrderNo(string opNo) { try { var sortingDtl = BLLCreator.Create>().GetList(new { CN_S_ORDER_NO = opNo, CN_C_ISPACK = "Y" }); return OperateResult.Succeed(null, sortingDtl); } catch (Exception ex) { return OperateResult.Error(ex.Message); } } #endregion #region (cs端)先拣后播扫物料 /// /// ScanItem /// /// /// [HttpPost] public OperateResult ScanItem(PostEntity postEntity) { return ValidateToken(postEntity.TokenId, t => { var sortingResult = postEntity.GetPostData(); if (sortingResult == null) return OperateResult.Error("分拣结果数据不可为空"); //当前拣的分拣明细 var sortingLocation = BLLCreator.CreateDapper().GetSingleEntity(new { CN_S_SORTING_NO = sortingResult.CN_S_SORTING_NO, CN_S_TRAY_CODE = sortingResult.CN_S_TRAY_CODE, CN_S_ITEM_CODE = sortingResult.CN_S_ITEM_CODE }); //增加分拣明细分拣数 if (sortingLocation != null) { if (sortingResult.CN_F_QUANTITY > (sortingLocation.CN_F_QUANTITY - sortingLocation.CN_F_PACKING_QTY)) return OperateResult.Error("包装数大于分拣数"); sortingLocation.CN_F_PICKED_QTY += sortingResult.CN_F_QUANTITY; } #region 批分托盘物料关联,降分配量,删子表,解货位 //算法策略 List lstStrate = BLLCreator.Create().GetStrateListByAreaOrStock("", "", Constants.Out) .OrderByDescending(a => a.CN_N_PRIORITY).Select(o => o.CN_S_CODE).ToList(); //分拣结果的托盘物料关联数据 var trayItemMstList = BLLCreator.CreateDapper().GetList(new { CN_S_TRAY_CODE = sortingResult.CN_S_TRAY_CODE, CN_S_ITEM_CODE = sortingResult.CN_S_ITEM_CODE }); foreach (var trayItemMst in trayItemMstList) { trayItemMst.TrayItemDtlList = new List(); //属于当前托盘,当前物料的分拣明细 var currentSortingResult = sortingResult; decimal qty = currentSortingResult.CN_F_QUANTITY; if (trayItemMst.CN_F_QUANTITY >= qty && trayItemMst.CN_F_ALLOC_QTY >= qty) { trayItemMst.CN_F_QUANTITY -= qty; trayItemMst.CN_F_ALLOC_QTY -= qty; Log.Info("确认分拣", "0001"); trayItemMst.TrayItemDtlList = BLLCreator.CreateDapper().GetList(new { CN_PARENT_GUID = trayItemMst.CN_GUID }).OrderBy(x => x.CN_S_LOT_NO).ToList(); Log.Info("确认分拣", "0002"); Log.Info("确认分拣", "0003"); foreach (string stegy in lstStrate) { //逐个策略进行计算 switch (stegy) { case "FirstInFirstOut": trayItemMst.TrayItemDtlList = trayItemMst.TrayItemDtlList.OrderBy(o => o.CN_S_LOT_NO).ToList(); break; case "FirstWarrantFirstOut": trayItemMst.TrayItemDtlList = trayItemMst.TrayItemDtlList.Select(x => new { index = string.IsNullOrEmpty(x.CN_S_PRODUCTION_BATCH) ? 0 : 1, x }).OrderByDescending(y => y.index).ThenBy(z => z.x.CN_S_PRODUCTION_BATCH).Select(m => m.x).ToList(); break; } } Log.Info("确认分拣", "0004"); var csQty = currentSortingResult.CN_F_QUANTITY; foreach (var trayItemDtl in trayItemMst.TrayItemDtlList) { if (csQty == 0) break; if (trayItemDtl.CN_F_QUANTITY == 0) continue; if (trayItemDtl.CN_F_QUANTITY >= csQty) { trayItemDtl.CN_F_QUANTITY -= csQty; csQty = 0; } else { csQty -= trayItemDtl.CN_F_QUANTITY; trayItemDtl.CN_F_QUANTITY = 0; } } } } var currentTrayLocation = BLLCreator.CreateDapper().GetSingleEntity(new { CN_S_TRAY_CODE = sortingResult.CN_S_TRAY_CODE }); #endregion #region 初始化数据 sortingResult.CN_GUID = Guid.NewGuid().ToString(); sortingResult.CN_S_SERIAL_NO = sortingResult.CN_S_SERIAL_NO ?? ""; sortingResult.CN_S_TRAY_CODE = sortingResult.CN_S_TRAY_CODE ?? ""; sortingResult.CN_S_TURNOVERBOX_CODE = sortingResult.CN_S_TURNOVERBOX_CODE ?? ""; sortingResult.CN_S_CREATOR = t.CN_S_LOGIN; sortingResult.CN_S_CREATOR_BY = t.CN_S_NAME; sortingResult.CN_T_CREATE = DateTime.Now; sortingResult.CN_S_MODIFY = t.CN_S_LOGIN; sortingResult.CN_S_MODIFY_BY = t.CN_S_NAME; sortingResult.CN_T_MODIFY = DateTime.Now; var currentSorting = BLLCreator.CreateDapper().GetSingleEntity(new { CN_S_SORTING_NO = sortingResult.CN_S_SORTING_NO, }); #endregion SavePickEntity savePickEntity = new SavePickEntity { SortingResult = new List() { sortingResult }, TrayItemList = trayItemMstList, TrayLocation = currentTrayLocation, CurrentSorting = currentSorting }; return BLLCreator.Create().ScanItem(savePickEntity); }); } #endregion #region (cs端)先拣后播扫周转箱 /// /// (cs端)先拣后播扫周转箱 /// /// /// /// /// [HttpGet] public OperateResult ScanTurnoverBox(string sortingNo, string boxNo, string location) { return ValidateToken(t => { var trayEntity = BLLCreator.CreateDapper().GetSingleEntity(new { CN_S_TRAY_CODE = boxNo }); if (trayEntity == null) return OperateResult.Error("不存在周转箱:" + boxNo); var sortingEntity = BLLCreator.CreateDapper().GetSingleEntity(new { CN_S_SORTING_NO = sortingNo }); if (sortingEntity == null) return OperateResult.Error("未找到分拣单:" + sortingNo); var fromOutMst = BLLCreator.CreateDapper().GetSingleEntity(new { CN_S_WAVE_CODE = sortingEntity.CN_S_FROM_NO }); if (fromOutMst == null) return OperateResult.Error("未找到分拣单波次所属出库单"); //当前波次所有分拣单 var currentWaveSortings = BLLCreator.CreateDapper().GetList(new { CN_S_FROM_NO = sortingEntity.CN_S_FROM_NO }); //同一波次分拣单到同一个集散区 string boxBit = string.Empty; var existsBitSorting = currentWaveSortings.Find(w => !string.IsNullOrEmpty(w.CN_S_COLLECT_LOCATION)); if (existsBitSorting != null) boxBit = existsBitSorting.CN_S_COLLECT_LOCATION; if (string.IsNullOrEmpty(boxBit)) { var jsArea = BLLCreator.Create().GetSingle("CN_S_AREA_NAME", Constants.JSArea); if (jsArea == null) return OperateResult.Error("请维护集散区"); InAssignEntity aEntity = new InAssignEntity() { objectType = InAssignEntity.ObjectType.周转箱, objectCode = boxNo, lockLocation = false, lstAreaPrior = new List() { { new areaPriorClass() { areaCode = jsArea.CN_S_AREA_CODE, Prior = 1 } } }, logicAreaCode = Constants.FixedLogicArea_JS_FROM }; //根据库区获取货位 InAssignResultEntity resultEntity = BLLCreator.Create().InAssign(aEntity); if (!resultEntity.Success) return OperateResult.Error(resultEntity.Msg); boxBit = resultEntity.locationCode; } //当前分拣单分拣明细 var currentSortingLocation = BLLCreator.CreateDapper().GetList(new { CN_S_SORTING_NO = sortingNo }); //当前分拣单是否分拣完 bool sortingPicked = false; //当前波次是否捡完 bool wavePicked = false; //当前分拣单是否分拣完 if (currentSortingLocation.Sum(s => s.CN_F_QUANTITY) == currentSortingLocation.Sum(s => s.CN_F_PICKED_QTY)) sortingPicked = true; //当前波次是否捡完 var otherSortings = currentWaveSortings.Where(w => w.CN_S_SORTING_NO != sortingNo); if (sortingPicked && !otherSortings.Any() || (otherSortings.Count() == otherSortings.Where(w => w.CN_S_STATE == Constants.Sorting_Sorted).Count())) wavePicked = true; //当前分拣单未合箱的分拣结果 var staySortingResult = BLLCreator.CreateDapper().GetList(new { CN_S_SORTING_NO = sortingNo }).Where(w => string.IsNullOrEmpty(w.CN_S_TURNOVERBOX_CODE)).ToList(); SavePickEntity savePickEntity = new SavePickEntity() { SortingPicked = sortingPicked, WavePicked = wavePicked, CurrentSorting = sortingEntity, IsWx = fromOutMst.CN_S_SALES_STYLE == Constants.SalesStyle_WX, OutMst = fromOutMst, SortingResult = staySortingResult, SortingNo = sortingNo, BoxNo = boxNo, StartBit = location, EndBit = boxBit }; return OperateResult.Succeed(); }); } #endregion } }