using Admin.NET.Application.CommonHelper; using Admin.NET.Application.Entity; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Admin.NET.Application; /// /// 下架服务 /// [ApiDescriptionSettings(ApplicationConst.WmsOperationsGroupName, Order = 100)] public class WmsUnshelveService : IDynamicApiController, ITransient { private readonly SqlSugarRepository _wmsPlaceRep; private readonly SqlSugarRepository _wmsContainerRep; private readonly SqlSugarRepository _wmsContainerPlaceRep; private readonly SqlSugarRepository _wmsStockQuanRep; private readonly SqlSugarRepository _wmsTaskRep; private readonly SqlSugarRepository _wmsContainerTypeRep; private readonly SqlSugarRepository _wmsContainerPackagingRep; private readonly SqlSugarRepository _v_wms_stock_quanRep; private readonly SqlSugarRepository _wmsOrderMovementRep; private readonly SqlSugarRepository _wmsOrderMovementDetailsRep; private readonly SqlSugarRepository _repSNRep; private readonly SqlSugarRepository _WmsNoCreateRuleRep; private readonly SqlSugarRepository _wmsLogActionRep; private readonly SqlSugarRepository _wmsRecordTransRep; private readonly SqlSugarRepository _wmsBaseBusinessTypeRep; private readonly SqlSugarRepository _WmsAreaRep; /// /// 构造函数 /// public WmsUnshelveService(SqlSugarRepository wmsPlaceRep, SqlSugarRepository wmsContainerRep, SqlSugarRepository wmsContainerPlaceRep, SqlSugarRepository wmsStockQuanRep, SqlSugarRepository wmsTaskRep, SqlSugarRepository wmsContainerTypeRep, SqlSugarRepository wmsContainerPackagingRep, SqlSugarRepository v_wms_stock_quanRep, SqlSugarRepository wmsOrderMovementRep, SqlSugarRepository wmsOrderMovementDetailsRep, SqlSugarRepository repSNRep, SqlSugarRepository wmsNoCreateRuleRep, SqlSugarRepository wmsLogActionRep, SqlSugarRepository wmsRecordTransRep, SqlSugarRepository wmsBaseBusinessTypeRep, SqlSugarRepository wmsAreaRep) { this._wmsPlaceRep = wmsPlaceRep; this._wmsContainerRep = wmsContainerRep; this._wmsContainerPlaceRep = wmsContainerPlaceRep; this._wmsStockQuanRep = wmsStockQuanRep; this._wmsTaskRep = wmsTaskRep; this._wmsContainerTypeRep= wmsContainerTypeRep; this._wmsContainerPackagingRep= wmsContainerPackagingRep; this._v_wms_stock_quanRep = v_wms_stock_quanRep; this._wmsOrderMovementRep= wmsOrderMovementRep; this._wmsOrderMovementDetailsRep=wmsOrderMovementDetailsRep; this._repSNRep= repSNRep; this._WmsNoCreateRuleRep = wmsNoCreateRuleRep; this._wmsLogActionRep = wmsLogActionRep; this._wmsRecordTransRep = wmsRecordTransRep; this._wmsBaseBusinessTypeRep = wmsBaseBusinessTypeRep; this._WmsAreaRep = wmsAreaRep; } /// /// PDA容器下架判断目标库位是否异常 /// /// [HttpPost] [ApiDescriptionSettings(Name = "GetPlaceInfo", Description = "PDA容器下架判断目标库位是否异常")] [Description("/Unshelve/GetPlaceInfo")] public async Task GetPlaceInfo(GetPlaceInfoInput input) { var wmsPlace = await _wmsPlaceRep.GetFirstAsync(o => o.PlaceCode == input.PlaceCode && o.IsDelete==false); if(wmsPlace==null) throw Oops.Oh($"该地标/库位不存在,请检查库位基础数据!"); if (wmsPlace.PlaceStatus == PlaceStatusEnum.锁定) { var wmsTask = await _wmsTaskRep.GetFirstAsync(o => o.SourcePlaceCode == wmsPlace.PlaceCode&&o.TaskStatus== TaskStatusEnum.已下发); throw Oops.Oh($"该库位被任务号{wmsTask.TaskNo}锁定,不可使用!"); } if(wmsPlace.PlaceStatus== PlaceStatusEnum.封存) throw Oops.Oh($"该库位已冻结,不可使用!如需解冻,请先解冻该库位!"); } /// /// PDA下架查询-获取物料编号对应的容器类型 /// /// [HttpGet] [ApiDescriptionSettings(Name = "GetMaterialCodeByInfo", Description = "PDA容器下架查询-获取物料编号对应的容器类型")] [Description("/Unshelve/GetMaterialCodeByInfo")] public async Task GetMaterialCodeByInfo([FromQuery] GetMaterialCodeByInfoInput input) { if(string.IsNullOrEmpty(input.MaterialCode)) throw Oops.Oh($"物料编号不能为空!!"); var wmsMaterial = await _wmsContainerPackagingRep.AsQueryable(). WhereIF(!string.IsNullOrEmpty(input.MaterialCode), o => o.MaterialCode.Contains(input.MaterialCode.Trim())).FirstAsync(); if (wmsMaterial == null) throw Oops.Oh($"该物料编号{input.MaterialCode}在系统中没有关联容器类型,请先添加容器类型!"); var wmsContainerType = new GetContainerTypeOutPut() { ContainerTypeCode = wmsMaterial.ContainerTypeCode, ContainerTypeName = wmsMaterial.ContainerTypeName, }; return wmsContainerType; } /// /// 容器下架执行 /// /// [HttpPost] [ApiDescriptionSettings(Name = "ContainerUnshelveExecute", Description = "PDA容器下架确认-创建下架单、调度任务")] [Description("/Unshelve/ContainerUnshelveExecute")] public async Task ContainerUnshelveExecute(WmsUnshelveInput input) { //ly-0813 添加来源库区 //var AreaCodeItem = await _WmsAreaRep.GetFirstAsync(w => w.AreaCode == input.AreaCode && w.IsDelete == false); //if (AreaCodeItem==null) //{ // throw Oops.Oh($"来源库区{input.AreaCode}不存在!"); //} //获取库存中已上架的容器类型集合按时间排序 排除目标库位是自己的 var contaierList = await _v_wms_stock_quanRep.AsQueryable() .Where(o => o.PlaceCode != input.PlaceCode && o.ContainerTypeCode == input.ContainerTypeCode && o.MaterialTypeCode=="RQ" && o.IsDelete == false && o.StockStatus==StockStatusEnum.已上架) .OrderBy(o=>o.CreateTime).ToListAsync(); //判断当前容器类型是否有库存 if (contaierList.Count<=0) throw Oops.Oh($"当前容器类型{input.ContainerTypeCode}没有库存,请先上架该类型的容器!"); //查询第一个容器号的容器组盘集合 不能自己呼叫自己 var contaierInfoList = contaierList .Where(u => u.ContainerCode == contaierList[0].ContainerCode && u.ContainerCode != input.PlaceCode) .ToList(); //if (contaierInfoList.Count <= 0) //{ // throw Oops.Oh($"来源库区{input.AreaCode}没有找到已上架的容器!"); //} //源库位 string sourcePlaceCode = contaierInfoList[0].PlaceCode; string sourcePlaceName = contaierInfoList[0].PlaceName; //if (contaierInfoList[0].PlaceCode == input.PlaceCode) //{ // throw Oops.Oh($"来源库位{contaierInfoList[0].PlaceCode}和目标库位{input.PlaceCode}相同!"); //} //新增事务记录 List addWmsRecordTransList = new List(); //新增操作履历 List addWmsLogActionList = new List(); //新增下架单明细 List addWmsOrderMovementDetailsList = new List(); //获取目标库位信息 WmsBasePlace toPlace = null; if (!string.IsNullOrWhiteSpace(input.PlaceCode)) { toPlace = await _wmsPlaceRep.GetFirstAsync(w => w.PlaceCode == input.PlaceCode && w.IsDelete == false); if (toPlace == null) { throw Oops.Oh($"目标库位{input.PlaceCode}不存在!"); } if (toPlace.IsDisabled == true) { throw Oops.Oh($"目标库位{input.PlaceCode}已禁用!"); } if (toPlace.IsVirtually == true) { throw Oops.Oh($"目标库位{input.PlaceCode}是虚拟库位!"); } //库位属性 正常和禁出的可以组盘上架 if (toPlace.PlaceStatus != PlaceStatusEnum.正常 && toPlace.PlaceStatus != PlaceStatusEnum.禁出) { throw Oops.Oh($"目标库位{input.PlaceCode}库位属性是{toPlace.PlaceStatus.GetDescription()}!"); } } else { //用户必须指定一个 库位。 throw Oops.Oh($"目标库位不能为空!"); } BusinessTypeEnum businessTypeEnum = BusinessTypeEnum.容器下架; // 获取业务类型 update by liuwq 2024 07 30 var wmsBaseBusinessType = BusinessTypeHelper.GetBusinessTypeInfoFromDB((int)businessTypeEnum, _wmsBaseBusinessTypeRep); int lineNumber = 0;//移动单明细行号 var hearId = Yitter.IdGenerator.YitIdHelper.NextId();//上架单ID //3.循环库存信息-创建上架单明细 foreach (var vstockQuan in contaierInfoList) { var wmsContainerItem = await _wmsContainerRep.GetFirstAsync(w => w.ContainerCode == vstockQuan.SNCode &&w.IsDelete == false); if (wmsContainerItem == null) throw Oops.Oh($"容器{vstockQuan.SNCode}不存在!"); if (wmsContainerItem.IsDisabled == true) throw Oops.Oh($"容器{vstockQuan.SNCode}已禁用!"); if (wmsContainerItem.IsVirtually == true) throw Oops.Oh($"容器{vstockQuan.SNCode}是虚拟容器!"); var stockQuan = await _wmsStockQuanRep.GetFirstAsync(w => w.Id==vstockQuan.Id); if(stockQuan==null) throw Oops.Oh($"容器{vstockQuan.SNCode}不存在!"); if (string.IsNullOrWhiteSpace(vstockQuan.ContainerCode)) { throw Oops.Oh($"库存{vstockQuan.SNCode}容器号不能为空!"); } lineNumber++; #region 创建下架单明细 //3.根据容器的库存创建下架单明细 var wmsOrderMovementDetails = new WmsOrderMovementDetails() { MovementId = hearId, LineNumber = OrderHelper.AutoCompleEBELP(lineNumber.ToString(), 4),//lineNumber.ToString(), SNCode = vstockQuan.SNCode, SupplierCode = vstockQuan.SupplierCode, SupplierName = vstockQuan.SupplierName, Batch = vstockQuan.Batch, ErpOrderNo = vstockQuan.ErpOrderNo, ErpCode = vstockQuan.ErpCode, Unit = vstockQuan.MaterialUnit, SupplierBatch = vstockQuan.SupplierBatch, OrderStatus = OrderStatusEnum.新建, OrderStatusName = OrderStatusEnum.新建.GetDescription(), //ToAreaCode = input.ToAreaCode, //ToPlaceCode = input.ToPlaceCode, ContainerCode = vstockQuan.ContainerCode, ContainerName = vstockQuan.ContainerName, SourceWarehouseCode = vstockQuan.WarehouseCode, SourceWarehouseName = vstockQuan.WarehouseName, SourceAreaCode = vstockQuan.AreaCode, SourceAreaName = vstockQuan.AreaName, SourcePlaceCode = vstockQuan.PlaceCode, SourcePlaceName = vstockQuan.PlaceName, ToPlaceCode = toPlace.PlaceCode, ToPlaceName = toPlace.PlaceName, ToAreaCode = toPlace.AreaCode, ToAreaName = toPlace.AreaName, MaterialCode = vstockQuan.MaterialCode, MaterialName = vstockQuan.MaterialName, Quantity = vstockQuan.Quantity, ActionRemark = "PDA下架架创建下架单", ActionTime = DateTime.Now }; addWmsOrderMovementDetailsList.Add(wmsOrderMovementDetails); #endregion #region 转移库存操作日志 string recordTransRemarks = string.Empty; //新增操作日志 WmsLogAction wareActionLog = LogActionHelper.CreateWmsLogAction(vstockQuan.Id, businessTypeEnum.GetDescription(), recordTransRemarks); addWmsLogActionList.Add(wareActionLog); #endregion } // 获取当前时间 DateTime currentTime = DateTime.Now; // 格式化为年月日字符串 string formattedDate = currentTime.ToString("yyyyMMdd"); //按照单号规则生成单号 - 查找最新的创建的一条单据记录 var newestOrder = await _wmsOrderMovementRep.AsQueryable().Where(p => p.OrderType == OrderTypeEnum.下架单).Where(p => p.OrderNo.Contains(formattedDate)).OrderBy(it => it.CreateTime, OrderByType.Desc) .FirstAsync(); //按照单号规则生成单号-ly var OrderNoSjd = await SerialUtilOrder.GetSerialOrder(OrderTypeEnum.下架单, _WmsNoCreateRuleRep, _repSNRep, (int)businessTypeEnum, newestOrder == null ? null : newestOrder.OrderNo); if (OrderNoSjd == null || OrderNoSjd == "") { var OrderNoSjdRQ = await SerialUtilOrder.GetSerialOrder(OrderTypeEnum.下架单, _WmsNoCreateRuleRep, _repSNRep, (int)businessTypeEnum, newestOrder == null ? null : newestOrder.OrderNo); if (OrderNoSjdRQ != null || OrderNoSjdRQ != "") { OrderNoSjd = OrderNoSjdRQ; } else { OrderNoSjd = Yitter.IdGenerator.YitIdHelper.NextId().ToString(); } } var businessTypeInfo = BusinessTypeHelper.GetBusinessTypeInfoFromDB((int)businessTypeEnum, _wmsBaseBusinessTypeRep); //4 创建下架单 var addWmsOrderMovement = new WmsOrderMovement() { Id = hearId, OrderNo = OrderNoSjd, //按照单号规则生成单号-ly OrderType = OrderTypeEnum.下架单, OrderTypeName = OrderTypeEnum.下架单.GetDescription(), BusinessType = (int)businessTypeEnum, BusinessTypeName = businessTypeEnum.GetDescription(), OrderStatus = OrderStatusEnum.新建, OrderStatusName = OrderStatusEnum.新建.GetDescription(), OrderSocure = SourceByEnum.系统 }; BusinessTypeEnum wmsTaskBusinessTypeEnum = BusinessTypeEnum.容器下架; //5.创建调度任务 var wmsTask = new WmsTask() { MoveType = businessTypeInfo.MoveType, MoveTypeName = businessTypeInfo.MoveTypeName, BusinessType = businessTypeInfo.BusinessTypeValue, BusinessTypeName = businessTypeInfo.BusinessTypeName, ContainerCode = contaierList.FirstOrDefault().ContainerCode, IsFlagFinish = false, OrderNo = addWmsOrderMovement.OrderNo, TaskDescribe = "PDA容器下架", TaskStatus = TaskStatusEnum.新建, TaskStatusName = TaskStatusEnum.新建.GetDescription(), TaskNo = Yitter.IdGenerator.YitIdHelper.NextId().ToString(), TaskPriority = 0, TaskName = wmsTaskBusinessTypeEnum.GetDescription(), ToAreaCode = toPlace.AreaCode, SourcePlaceCode = sourcePlaceCode, ToPlaceCode = input.PlaceCode }; var _tenant = _wmsOrderMovementRep.AsTenant(); try { await _tenant.BeginTranAsync(); #region 事务内执行操作 //新增操作日志 await _wmsLogActionRep.InsertRangeAsync(addWmsLogActionList); if (addWmsOrderMovementDetailsList?.Count > 0) { //新增下架单 await _wmsOrderMovementRep.InsertAsync(addWmsOrderMovement); await _wmsOrderMovementDetailsRep.InsertRangeAsync(addWmsOrderMovementDetailsList); //新增任务调度 await _wmsTaskRep.InsertAsync(wmsTask); } else { throw Oops.Oh($"下架单明细为空!"); } #endregion await _tenant.CommitTranAsync(); } catch { await _tenant.RollbackTranAsync(); throw; } } }