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;
|
|
/// <summary>
|
/// 下架服务
|
/// </summary>
|
[ApiDescriptionSettings(ApplicationConst.WmsOperationsGroupName, Order = 100)]
|
public class WmsUnshelveService : IDynamicApiController, ITransient
|
{
|
private readonly SqlSugarRepository<WmsBasePlace> _wmsPlaceRep;
|
private readonly SqlSugarRepository<WmsBaseContainer> _wmsContainerRep;
|
private readonly SqlSugarRepository<WmsContainerPlace> _wmsContainerPlaceRep;
|
private readonly SqlSugarRepository<WmsStockQuan> _wmsStockQuanRep;
|
private readonly SqlSugarRepository<WmsTask> _wmsTaskRep;
|
private readonly SqlSugarRepository<WmsBaseContainerType> _wmsContainerTypeRep;
|
private readonly SqlSugarRepository<WmsBaseContainerPackaging> _wmsContainerPackagingRep;
|
private readonly SqlSugarRepository<v_wms_stock_quan> _v_wms_stock_quanRep;
|
private readonly SqlSugarRepository<WmsOrderMovement> _wmsOrderMovementRep;
|
private readonly SqlSugarRepository<WmsOrderMovementDetails> _wmsOrderMovementDetailsRep;
|
private readonly SqlSugarRepository<WmsConfigSerialSN> _repSNRep;
|
private readonly SqlSugarRepository<WmsConfigNoRule> _WmsNoCreateRuleRep;
|
private readonly SqlSugarRepository<WmsLogAction> _wmsLogActionRep;
|
private readonly SqlSugarRepository<WmsRecordTrans> _wmsRecordTransRep;
|
private readonly SqlSugarRepository<WmsBaseBusinessType> _wmsBaseBusinessTypeRep;
|
private readonly SqlSugarRepository<WmsBaseArea> _WmsAreaRep;
|
/// <summary>
|
/// 构造函数
|
/// </summary>
|
public WmsUnshelveService(SqlSugarRepository<WmsBasePlace> wmsPlaceRep,
|
SqlSugarRepository<WmsBaseContainer> wmsContainerRep,
|
SqlSugarRepository<WmsContainerPlace> wmsContainerPlaceRep,
|
SqlSugarRepository<WmsStockQuan> wmsStockQuanRep,
|
SqlSugarRepository<WmsTask> wmsTaskRep,
|
SqlSugarRepository<WmsBaseContainerType> wmsContainerTypeRep,
|
SqlSugarRepository<WmsBaseContainerPackaging> wmsContainerPackagingRep,
|
SqlSugarRepository<v_wms_stock_quan> v_wms_stock_quanRep,
|
SqlSugarRepository<WmsOrderMovement> wmsOrderMovementRep,
|
SqlSugarRepository<WmsOrderMovementDetails> wmsOrderMovementDetailsRep,
|
SqlSugarRepository<WmsConfigSerialSN> repSNRep,
|
SqlSugarRepository<WmsConfigNoRule> wmsNoCreateRuleRep,
|
SqlSugarRepository<WmsLogAction> wmsLogActionRep,
|
SqlSugarRepository<WmsRecordTrans> wmsRecordTransRep,
|
SqlSugarRepository<WmsBaseBusinessType> wmsBaseBusinessTypeRep,
|
SqlSugarRepository<WmsBaseArea> 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;
|
}
|
|
/// <summary>
|
/// PDA容器下架判断目标库位是否异常
|
/// </summary>
|
/// <returns></returns>
|
[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($"该库位已冻结,不可使用!如需解冻,请先解冻该库位!");
|
}
|
|
/// <summary>
|
/// PDA下架查询-获取物料编号对应的容器类型
|
/// </summary>
|
/// <returns></returns>
|
[HttpGet]
|
[ApiDescriptionSettings(Name = "GetMaterialCodeByInfo", Description = "PDA容器下架查询-获取物料编号对应的容器类型")]
|
[Description("/Unshelve/GetMaterialCodeByInfo")]
|
public async Task<GetContainerTypeOutPut> 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;
|
}
|
|
/// <summary>
|
/// 容器下架执行
|
/// </summary>
|
/// <returns></returns>
|
[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<WmsRecordTrans> addWmsRecordTransList = new List<WmsRecordTrans>();
|
//新增操作履历
|
List<WmsLogAction> addWmsLogActionList = new List<WmsLogAction>();
|
//新增下架单明细
|
List<WmsOrderMovementDetails> addWmsOrderMovementDetailsList = new List<WmsOrderMovementDetails>();
|
|
//获取目标库位信息
|
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;
|
}
|
}
|
|
}
|