namespace WIDESEA_StorageOutBasicServices; public class Dt_LocationService : ServiceBase, IDt_LocationService { private readonly IUnitOfWorkManage _unitOfWorkManage; private readonly IDt_OutOrderService _outOrderService; private readonly IDt_TaskService _taskService; private readonly IDt_BillGroupStockService _BillGroupStockService; public Dt_LocationService(IDt_LocationRepository BaseDal, IUnitOfWorkManage unitOfWorkManage, IDt_OutOrderService outOrderService, IDt_TaskService taskService, IDt_BillGroupStockService billGroupStockService) : base(BaseDal) { _unitOfWorkManage = unitOfWorkManage; _outOrderService = outOrderService; _taskService = taskService; _BillGroupStockService = billGroupStockService; } /// /// 检查并生成移库任务或返回出库任务 /// /// 库位ID /// 任务对象 public virtual async Task TransferCheck(string locationID) { try { // 获取指定库位的任务 var outboundTask = await _taskService.GetByLocation(locationID); if (outboundTask == null) return null; // 检查是否需要进行移库 if (CheckForInternalTransfer(locationID)) { // 计算对应位置的相对库位 (奇数行的下一行或者偶数行的上一行) var newLocationID = GetRelativeLocationID(locationID); // 获取新的库位的任务 var internalTransferTask = await _taskService.GetByLocation(newLocationID); // 如果新的库位没有找到对应的任务 if (internalTransferTask == null) { return await HandleNoTaskAtLocation(locationID, newLocationID, outboundTask); } // 直接返回一深位出库任务 return internalTransferTask; } // 返回当前库位的出库任务 return outboundTask; } catch (Exception) { return null; } } #region 内部方法 /// /// 计算相对的库位ID /// /// 当前库位ID /// 相对的库位ID private string GetRelativeLocationID(string locationID) { string[] parts = locationID.Split('-'); int line = int.Parse(parts[0]); // 计算相对的货位行值,奇数行的下一行或者偶数行的上一行 int relativeLine = line % 2 == 1 ? line + 1 : line - 1; // 构建新的库位ID string[] newLocationParts = new string[] { relativeLine.ToString().PadLeft(3, '0'), parts[1], parts[2] }; return string.Join("-", newLocationParts); } /// /// 处理没有任务的库位情况 /// /// 原始库位ID /// 新的库位ID /// 出库任务 /// 生成的移库任务或原始出库任务 private async Task HandleNoTaskAtLocation(string originalLocationID, string newLocationID, Dt_Task outboundTask) { // 判断该位置是否有库存 var stockInfo = await _BillGroupStockService.GetStocks(locationID: newLocationID); if (stockInfo == null) { // 如果没有库存,直接返回当前出库任务 return outboundTask; } else { // 如果有库存,生成移库任务 var emptyLocation = GetTransferLocationEmpty(outboundTask.Roadway); Dt_Task newTransferTask = new Dt_Task() { CreateDate = DateTime.Now, Creater = "System", CurrentAddress = originalLocationID, Grade = 99, MaterialNo = stockInfo.MaterialNo, NextAddress = emptyLocation.LocationID, PalletCode = stockInfo.PalletCode, Remark = "移库", Roadway = stockInfo.LocationInfo.Roadway, SourceAddress = originalLocationID, TaskNum = 0, TargetAddress = emptyLocation.LocationID, TaskState = TaskStateConst.PendingDispatch.ToString(), TaskType = TaskTypeConst.InternalTransfer.ToString(), }; return await _taskService.Create(newTransferTask); } } /// /// 根据货位检查一深位是否需要移库 /// /// 货位ID /// 是否需要移库 private bool CheckForInternalTransfer(string locationID) { // 根据 "-" 截取字符串并获取第一位数字 string[] parts = locationID.Split('-'); if (parts.Length > 0 && int.TryParse(parts[0], out int row)) { // 获取二深位的行号列表,表示需要移库 List transfertRows = AppSettings.app("TransfertRows").Split(',').ToList().ConvertAll(x => int.Parse(x)); // 判断行号是否在目标行号列表中 return transfertRows.Contains(row); } return false; } /// /// 根据巷道获取二深位的空库位 /// /// 巷道 /// 货位对象 private Dt_LocationInfo GetTransferLocationEmpty(string roadway) { return Db.Queryable() .Where(x => x.Status == LocationStateConst.LocationState_Empty) .Where(x => x.Depth == 2.ToString()) .Where(x => x.Roadway == roadway) .First(); } #endregion 内部方法 }