using Admin.NET.Application.CommonHelper;
using Admin.NET.Application.Entity;
using Furion.DatabaseAccessor;
namespace Admin.NET.Application;
///
/// pda组盘、解绑服务
///
[ApiDescriptionSettings(ApplicationConst.PdaOperationsGroup, Order = 100)]
public class WmsGroupDiskService : IDynamicApiController, ITransient
{
private readonly SqlSugarRepository _wmsPlaceRep;
private readonly SqlSugarRepository _v_wms_containerRep;
private readonly SqlSugarRepository _wmsStockQuanRep;
private readonly SqlSugarRepository _WmsContainerRep;
private readonly SqlSugarRepository _repWmsContainerPlaceRep;
private readonly SqlSugarRepository _wmsMaterialRep;
private readonly SqlSugarRepository _wmsContainerPackagingRep;
private readonly SqlSugarRepository _v_wms_stock_quanRep;
private readonly SqlSugarRepository _wmsLogActionRep;
private readonly SqlSugarRepository _wmsRecordTransRep;
private readonly SqlSugarRepository _wmsBaseBusinessTypeRep;
private readonly SqlSugarRepository _wmsAreaRep;
public WmsGroupDiskService(
SqlSugarRepository wmsPlaceRep,
SqlSugarRepository v_wms_containerRep,
SqlSugarRepository wmsStockQuanRep,
SqlSugarRepository wmsContainerRep,
SqlSugarRepository repWmsContainerPlaceRep,
SqlSugarRepository wmsMaterialRep,
SqlSugarRepository wmsContainerPackagingRep,
SqlSugarRepository v_wms_stock_quanRep,
SqlSugarRepository wmsLogActionRep,
SqlSugarRepository wmsRecordTransRep,
SqlSugarRepository wmsBaseBusinessTypeRep,
SqlSugarRepository wmsAreaRep
)
{
_wmsPlaceRep = wmsPlaceRep;
_v_wms_containerRep = v_wms_containerRep;
_wmsStockQuanRep = wmsStockQuanRep;
_WmsContainerRep = wmsContainerRep;
_repWmsContainerPlaceRep = repWmsContainerPlaceRep;
_wmsMaterialRep = wmsMaterialRep;
_wmsContainerPackagingRep = wmsContainerPackagingRep;
_v_wms_stock_quanRep = v_wms_stock_quanRep;
_wmsLogActionRep = wmsLogActionRep;
_wmsRecordTransRep = wmsRecordTransRep;
_wmsBaseBusinessTypeRep = wmsBaseBusinessTypeRep;
_wmsAreaRep = wmsAreaRep;
}
///
/// pda组盘查询-不分页查询容器上的物料-扫容器号
///
///
///
[HttpGet]
[ApiDescriptionSettings(Name = "PdaContainerWithMaterial")]
[Description("wmsGroupDisk/PdaContainerWithMaterial")]
public async Task> PdaContainerWithMaterial([FromQuery] DiyWmsGroupDiskInput input)
{
var WmsContainerItem = await _WmsContainerRep.GetFirstAsync(w => w.ContainerCode == input.ContainerCode &&
w.IsDelete == false);
if (WmsContainerItem == null)
{
throw Oops.Oh($"容器编号{input.ContainerCode}不存在!");
}
if (WmsContainerItem.IsDisabled == true)
{
throw Oops.Oh($"容器编号{input.ContainerCode}不可用!");
}
if (WmsContainerItem.IsVirtually == true)
{
throw Oops.Oh($"容器编号{input.ContainerCode}为虚拟状态!");
}
//容器必须有库位关系才能组盘 去pda库位绑定中 进行绑定
var entityWmsContainerPlace = await _repWmsContainerPlaceRep.GetFirstAsync(u => u.ContainerCode == input.ContainerCode);
ContainerPlaceHelper.ValidateContainerPlaceForGroupDisk(entityWmsContainerPlace, input.ContainerCode);
//组盘时,容器必须不在立体库上 有料容器
var StockContainer = await _wmsStockQuanRep.GetFirstAsync(w => w.ContainerCode == input.ContainerCode);
if (input.ActionType == 0)
{
////绑定
//if (StockContainer != null && StockContainer.StockStatus == StockStatusEnum.待上架)
//{
// throw Oops.Oh($"容器编号{input.ContainerCode}物料{StockContainer.MaterialCode}库存状态是{StockStatusEnum.待上架.GetDescription()}!");
//}
}
else
{
////解绑
//if (StockContainer != null && StockContainer.StockStatus != StockStatusEnum.待上架)
//{
// throw Oops.Oh($"容器编号{input.ContainerCode}物料{StockContainer.MaterialCode}库存状态不是{StockStatusEnum.待上架.GetDescription()}!");
//}
}
////主动适配 空容器垛查询的问题 【Editby shaocx,2024-07-27】
//var emptyContainer = "";
//var v_wms_stock_quan_emptyCointer = await _v_wms_stock_quanRep.GetFirstAsync(w => w.SNCode == input.ContainerCode);
//if (v_wms_stock_quan_emptyCointer != null)
//{//说明是 空容器物料
// emptyContainer = v_wms_stock_quan_emptyCointer.ContainerCode;
//}
var query = _wmsStockQuanRep.AsQueryable()
//.Where(u => u.ContainerCode.Contains(input.ContainerCode.Trim()) || (!string.IsNullOrEmpty(emptyContainer) && u.ContainerCode.Contains(emptyContainer)))
.Where(u => u.ContainerCode.Contains(input.ContainerCode.Trim()))
.WhereIF(!string.IsNullOrWhiteSpace(input.SNCode), u => u.SNCode == input.SNCode.Trim())
//.WhereIF(!string.IsNullOrWhiteSpace(input.MaterialCode), u => u.MaterialCode.Contains(input.MaterialCode.Trim()))
.Select();
var restList = await query.OrderBuilder(input, "", "Id").Select().ToListAsync();
//注意:要单独过滤掉 空容器物料 【Editby shaocx,2024-07-28】
restList = restList.Where(x => x.SNCode != input.ContainerCode).ToList();
return restList;
}
///
/// pda组盘查询-不分页查询跟踪码对应的物料-扫跟踪码
///
///
///
[HttpGet]
[ApiDescriptionSettings(Name = "PdaBindListForSNCode")]
[Description("wmsGroupDisk/PdaBindListForSNCode")]
public async Task PdaBindListForSNCode([FromQuery] DiyWmsGroupDiskBaseInput input)
{
PdaBindListForSNCodeOutput res = new PdaBindListForSNCodeOutput()
{
stockQuanOutput = null,
ValidateFailReason = "",
ValidateResult = true
};
if (input.SNCode == null)
{
throw Oops.Oh($"物料跟踪码不能为空!");
}
if (input.ContainerCode == null)
{
throw Oops.Oh($"容器号不能为空!");
}
var toContainerCode = await ContainerHelper.GetWmsContainer(_WmsContainerRep, input.ContainerCode);
if (toContainerCode.IsVirtually == true)
{
throw Oops.Oh($"容器号{input.ContainerCode}是虚拟容器,不允许操作!");
}
var query = _wmsStockQuanRep.AsQueryable()
.WhereIF(!string.IsNullOrWhiteSpace(input.SNCode), u => u.SNCode == input.SNCode.Trim())
.Select();
var allList = await query.Select().ToListAsync();
if (allList?.Count == 0)
{
throw Oops.Oh($"跟踪码{input.SNCode}没有找到库存!");
}
//检验库存的容器是否跟组盘的容器一致
if (allList.Count() > 1)
{
throw Oops.Oh($"该跟踪码{input.SNCode}存在多个库存!");
}
else if (allList.Count() == 1)
{
var dbObj = allList.First();
if (string.IsNullOrEmpty(dbObj.ContainerCode))
{
throw Oops.Oh($"跟踪码{dbObj.SNCode}绑定的容器号为空!");
}
var orgContainerCode = await ContainerHelper.GetWmsContainer(_WmsContainerRep, dbObj.ContainerCode);
if (orgContainerCode.IsVirtually != true && dbObj.ContainerCode != input.ContainerCode)
{
res.ValidateResult = false;
res.ValidateFailReason = $"跟踪码{input.SNCode}当前在容器{dbObj.ContainerCode}中,是否确认要将该物料继续组盘到新容器{input.ContainerCode}中";
}
}
res.stockQuanOutput = allList.First();
return res;
}
///
/// pda物料或空容器组盘
///
///
///
[HttpPost]
[ApiDescriptionSettings(Name = "PdaBindUpdate")]
[Description("wmsGroupDisk/PdaBindUpdate")]
[UnitOfWork]
public async Task PdaBindUpdate(WmsGroupDiskBaseInput input)
{
if (input is null)
{
throw Oops.Oh("输入参数不能为空");
}
if (input.Flag <= 0 || input.Flag > 3)
{
throw Oops.Oh("标记不正确");
}
if (input.orderDetails is null || input.orderDetails.Count == 0)
{
throw Oops.Oh("明细不能为空");
}
var errMsgPre = input.Flag == 1 ? "跟踪码" : "容器号";
foreach (var item in input.orderDetails)
{
if (string.IsNullOrWhiteSpace(item.SNCode))
{
throw Oops.Oh($"要组盘的{errMsgPre}不能为空");
}
}
if (input.orderDetails.Select(v => v.SNCode).Distinct().Count() != input.orderDetails.Count())
{
throw Oops.Oh($"要组盘的{errMsgPre}不能重复");
}
var toWmsContainer = await ContainerHelper.GetWmsContainer(_WmsContainerRep, input.ContainerCode);
if (toWmsContainer.IsDisabled == true)
{
throw Oops.Oh($"容器编号{input.ContainerCode}不可用!");
}
if (toWmsContainer.IsVirtually == true)
{
throw Oops.Oh($"容器编号{input.ContainerCode}为虚拟状态!");
}
#region 验证
if (input.Flag == 1)
{
}
else
{
var querySNCodeList = input.orderDetails.Select(x => x.SNCode).ToList();
var entityWmsContainerList = await _WmsContainerRep.GetListAsync(u => querySNCodeList.Contains(u.ContainerCode));
if (entityWmsContainerList.Count > 0 && entityWmsContainerList.Select(u => u.ContainerTypeName).Distinct().Count() > 1)
{
throw Oops.Oh($"不同容器类型的容器不能组盘!");
}
}
#endregion
//容器必须有库位关系才能组盘 去pda库位绑定中 进行绑定
var entityWmsContainerPlace = await _repWmsContainerPlaceRep.GetFirstAsync(u => u.ContainerCode == input.ContainerCode);
ContainerPlaceHelper.ValidateContainerPlaceForGroupDisk(entityWmsContainerPlace, input.ContainerCode);
//update by liuwq 20240729
//获取目标库位
var toPlace = await BaseInfoHelper.GetPlace(entityWmsContainerPlace.PlaceCode, _wmsPlaceRep);
List addWmsStockQuanList = new List();//新增库存列表
List updateWmsStockQuanList = new List();//更新库存列表
List deleteWmsStockQuanList = new List();//要删除的库存列表
//新增事务记录
List addWmsRecordTransList = new List();
//新增操作履历
List addWmsLogActionList = new List();
string recordTransRemarks = string.Empty;
BusinessTypeEnum businessTypeEnum = BusinessTypeEnum.物料组盘;
// 获取业务类型
var wmsBaseBusinessType = BusinessTypeHelper.GetBusinessTypeInfoFromDB((int)businessTypeEnum, _wmsBaseBusinessTypeRep);
//查询该容器中已有的库存和前端传过来的库存汇总
List allContainerStockQuanViewList = await _v_wms_stock_quanRep.AsQueryable()
.Where(x => x.ContainerCode == toWmsContainer.ContainerCode || input.orderDetails.Select(v => v.SNCode).Contains(x.SNCode))
.Where(u => u.IsDelete == false).Select()
.ToListAsync();
List dbStockQuanList = await _wmsStockQuanRep.AsQueryable().Where(x => allContainerStockQuanViewList.Select(v => v.Id).Contains(x.Id)).ToListAsync();
//寻找前端传过来,但是不在库存中的
var noStock_SnList = input.orderDetails.Where(x => !allContainerStockQuanViewList.Select(y => y.SNCode).ToList().Contains(x.SNCode)).ToList();
if (input.Flag == 1)
{
if (noStock_SnList?.Count > 0)
{
throw Oops.Oh($"跟踪码{noStock_SnList.First().SNCode}不在库存中,不可组盘");
}
//查询下,如果这个托盘有库存数据,就要清理下,因为可能在空容器组盘时会有遗留的 【Editby shaocx,2024-07-28】
var delObjList = dbStockQuanList.Where(x => x.SNCode == input.ContainerCode).ToList();
if (delObjList?.Count > 0)
{
deleteWmsStockQuanList.AddRange(delObjList);
}
}
else
{//空容器组盘,新增库存
foreach (var item in noStock_SnList)
{
//新增的组盘的物料一定是容器类型的物料
var itemAdd = item.Adapt();
StockQuanHelper.UpdateStockStatus(itemAdd, StockStatusEnum.待上架);
itemAdd.Quantity = 1;
itemAdd.QCStatus = StockQcStatusEnum.合格;
itemAdd.QCStatusName = StockQcStatusEnum.合格.ToString();
itemAdd.SNCode = item.SNCode;
itemAdd.MaterialCode = ApplicationConst.DefaultContinerMaterialCode;
itemAdd.MaterialName = ApplicationConst.DefaultContinerMaterialName;
itemAdd.ContainerCode = toWmsContainer.ContainerCode;
itemAdd.ContainerId = toWmsContainer.Id;
addWmsStockQuanList.Add(itemAdd);
#region 转移库存添加事务、操作日志
recordTransRemarks = $"容器{toWmsContainer.ContainerCode},空容器号{item.SNCode}";
WmsRecordTrans addWmsRecordTrans = await CreateRecordTransInfoForZP(true, wmsBaseBusinessType, null, itemAdd, toPlace, "");//备注暂时为空
addWmsRecordTransList.Add(addWmsRecordTrans);
//新增操作日志
WmsLogAction wareActionLog = LogActionHelper.CreateWmsLogAction(itemAdd.Id, recordTransRemarks, $"转移跟踪码{item.SNCode}库存");
addWmsLogActionList.Add(wareActionLog);
#endregion
}
}
// update by liuwq 20240717
//校验物料容器类型是否跟绑定的容器类型一致
if (input.Flag == 1)
{
await StockQuanHelper.CheckContainerType(_wmsMaterialRep, _wmsContainerPackagingRep, toWmsContainer, dbStockQuanList);
}
//更新容器编号
foreach (var item in dbStockQuanList)
{
if (item.ContainerCode != input.ContainerCode)
{
var itemAdd = item.Adapt();
itemAdd.ContainerCode = toWmsContainer.ContainerCode;
itemAdd.ContainerId = toWmsContainer.Id;
updateWmsStockQuanList.Add(itemAdd);
#region 转移库存添加事务、操作日志
recordTransRemarks = $"容器{toWmsContainer.ContainerCode}跟踪码{item.SNCode}";
//获取源库存信息
var sourceStockView = StockQuanHelper.GetVMmsStockQuan(allContainerStockQuanViewList, item.SNCode);
WmsRecordTrans addWmsRecordTrans = await CreateRecordTransInfoForZP(false, wmsBaseBusinessType, sourceStockView, itemAdd, toPlace, "");//备注暂时为空
addWmsRecordTransList.Add(addWmsRecordTrans);
//新增操作日志
WmsLogAction wareActionLog = LogActionHelper.CreateWmsLogAction(item.Id, recordTransRemarks, $"转移跟踪码{item.SNCode}库存");
addWmsLogActionList.Add(wareActionLog);
#endregion
}
}
if (updateWmsStockQuanList.Count == 0 && addWmsStockQuanList.Count == 0)
{
throw Oops.Oh("组盘没有可处理的数据!");
}
//累计容器使用次数,组盘一次,使用次数加1 update by liuwq 20240614
toWmsContainer.UsageCount++;
try
{
if (updateWmsStockQuanList.Count > 0)
{
await _wmsStockQuanRep.UpdateRangeAsync(updateWmsStockQuanList); //1更新库存
}
await _wmsStockQuanRep.InsertRangeAsync(addWmsStockQuanList);//新增库存
if (deleteWmsStockQuanList?.Count > 0)
{
await _wmsStockQuanRep.DeleteAsync(deleteWmsStockQuanList);//删除库存
}
await _WmsContainerRep.UpdateAsync(toWmsContainer); //更新容器 update by liuwq 20240614
//新增事务记录、收货记录、操作日志
await _wmsLogActionRep.InsertRangeAsync(addWmsLogActionList);
await _wmsRecordTransRep.InsertRangeAsync(addWmsRecordTransList);
List newStockQuans = new List();
newStockQuans.AddRange(dbStockQuanList);
newStockQuans.AddRange(addWmsStockQuanList);
return new PdaBindUpdateOutput()
{
StockQuans = newStockQuans
};
}
catch
{
throw;
}
}
///
/// pda物料或空容器解绑
///
///
///
[HttpPost]
[ApiDescriptionSettings(Name = "PdaUnBindUpdate")]
[Description("wmsGroupDisk/PdaUnBindUpdate")]
public async Task PdaUnBindUpdate(WmsGroupDiskBaseInput input)
{
//新增事务记录
List addWmsRecordTransList = new List();
string recordTransRemarks = string.Empty;
MoveTypeEnum moveType = MoveTypeEnum.其他;
BusinessTypeEnum businessTypeEnum = BusinessTypeEnum.物料解绑;
var WmsBaseBusinessType = BusinessTypeHelper.GetBusinessTypeInfoFromDB((int)businessTypeEnum, _wmsBaseBusinessTypeRep);
if (input is null)
{
throw Oops.Oh("输入参数不能为空");
}
if (input.orderDetails is null || input.orderDetails.Count == 0)
{
throw Oops.Oh("明细不能为空");
}
if (input.Flag != 3 && input.Flag != 4)
{
throw Oops.Oh("标记不正确");
}
if (input.Flag == 4)
{
businessTypeEnum = BusinessTypeEnum.空容器解绑;
}
var WmsContainerItem = await _WmsContainerRep.GetFirstAsync(w => w.ContainerCode == input.ContainerCode &&
w.IsDelete == false);
if (WmsContainerItem == null)
{
throw Oops.Oh($"容器编号{input.ContainerCode}不存在!");
}
if (WmsContainerItem.IsDisabled == true)
{
throw Oops.Oh($"容器编号{input.ContainerCode}不可用!");
}
if (WmsContainerItem.IsVirtually == true)
{
throw Oops.Oh($"容器编号{input.ContainerCode}为虚拟状态!");
}
//var dbOrder = await _wmsStockQuanRep.GetFirstAsync(w => w.ContainerCode == input.ContainerCode);
//if (dbOrder == null)
//{
// throw Oops.Oh($"容器编号{input.ContainerCode}的库存不存在");
//}
//update by liuwq 20240729
var all_v_wms_stock_quan = await _v_wms_stock_quanRep.GetListAsync(w => w.ContainerCode == input.ContainerCode || w.SNCode == input.ContainerCode);
if (all_v_wms_stock_quan?.Count <= 0)
{
throw Oops.Oh($"容器编号{input.ContainerCode}上没有库存!");
}
var v_wms_stock_quan = all_v_wms_stock_quan.FirstOrDefault(w => w.ContainerCode == input.ContainerCode || w.SNCode == input.ContainerCode);
if (v_wms_stock_quan == null)
{
throw Oops.Oh($"容器编号{input.ContainerCode}上没有库存!");
}
var dibu_ContainerCode = "";//底部容器号
if (input.Flag == 3)
{
dibu_ContainerCode = input.ContainerCode;
}
else
{
dibu_ContainerCode = v_wms_stock_quan.ContainerCode;
}
List db_wmsStockQuanList = null;
if (input.Flag == 3)
{
db_wmsStockQuanList = await _wmsStockQuanRep.AsQueryable()
.Where(x => x.ContainerCode == v_wms_stock_quan.ContainerCode)
.Where(u => u.IsDelete == false)
.Select()
.ToListAsync();
}
else
{
db_wmsStockQuanList = await _wmsStockQuanRep.AsQueryable()
.Where(x => x.ContainerCode == dibu_ContainerCode)
.Where(u => u.IsDelete == false)
.Select()
.ToListAsync();
//校验,如果把底部容器也移除了,就提示错误
if (input.orderDetails.Any(p => p.SNCode == dibu_ContainerCode))
{
throw Oops.Oh($"容器编号{dibu_ContainerCode}是该空容器垛的底部承载容器,不允许在空容器中解绑,如想解绑,需要操作【库位解绑】!");
}
}
ZtPlaceAndContainerOutput ztPlaceAndContainerOutput = await StockQuanHelper.VerifyZTPlaceAndContainerIsExist(_wmsPlaceRep, _WmsContainerRep, v_wms_stock_quan.AreaCode);
var toWmsContainer = ztPlaceAndContainerOutput.ZtContainer;
//寻找更新单据明细的物料
var updateList = db_wmsStockQuanList.Where(x => input.orderDetails.Any(p => p.SNCode == x.SNCode && p.ContainerCode == x.ContainerCode)).ToList();
//ly0814 空容器解绑 根据跟踪码寻找所有容器
var entityWmsContainerList = new List();
if (input.Flag == 4)
{
var querySNCodeList = input.orderDetails.Select(x => x.SNCode).ToList();
entityWmsContainerList = await _WmsContainerRep.GetListAsync(u => querySNCodeList.Contains(u.ContainerCode));
if (entityWmsContainerList.Count <= 0)
{
throw Oops.Oh($"传入的容器编号不存在!");
}
}
List addWmsContainerMaterial = new List();
foreach (var item in updateList)
{
var itemAdd = item.Adapt();
//解绑 - 解绑后的物料所在容器是该库区的在途容器 【Editby shaocx,2024-07-27】
itemAdd.ContainerCode = ztPlaceAndContainerOutput.ZtContainer.ContainerCode;
itemAdd.ContainerId = ztPlaceAndContainerOutput.ZtContainer.Id;
addWmsContainerMaterial.Add(itemAdd);
//记录事物日志
recordTransRemarks = $"容器{toWmsContainer.ContainerCode}跟踪码{item.SNCode}";
//获取源库存信息
var sourceStockView = StockQuanHelper.GetVMmsStockQuan(all_v_wms_stock_quan, item.SNCode);
WmsRecordTrans addWmsRecordTrans = await CreateRecordTransInfoForZP(false, WmsBaseBusinessType, sourceStockView, item, ztPlaceAndContainerOutput.ZtPlace, "");//备注暂时为空
//WmsRecordTrans addWmsRecordTrans = await CreateRecordTransInfoForZP(false, _v_wms_containerRep, item, moveType, businessTypeEnum, itemAdd, sourceContainer, toWmsContainer, recordTransRemarks);
addWmsRecordTransList.Add(addWmsRecordTrans);
}
if (addWmsContainerMaterial == null || addWmsContainerMaterial.Count == 0)
{
throw Oops.Oh("没有要更新的数据!");
}
try
{
await _wmsStockQuanRep.AsTenant().BeginTranAsync();
if (addWmsContainerMaterial.Count > 0)
{
await _wmsStockQuanRep.UpdateRangeAsync(addWmsContainerMaterial); //1更新库存表
}
// 1、事务日志
await _wmsRecordTransRep.InsertRangeAsync(addWmsRecordTransList);
//2、操作日志
await _wmsStockQuanRep.AsTenant().CommitTranAsync();
}
catch
{
await _wmsStockQuanRep.AsTenant().RollbackTranAsync();
throw;
}
}
///
/// PDA组盘创建事务记录入参方法
///
///
///
///
///
///
///
///
///
private static async Task CreateRecordTransInfoForZP(
bool isEmptyConinter,
WmsBaseBusinessType wmsBaseBusinessType,
v_wms_stock_quan sourceStockView,
WmsStockQuan toStockModel,
WmsBasePlace toPlace
, string remark)
{
//组盘 关联单号 行号 都是空值
TransferOtherDetail transferOtherDetail = new TransferOtherDetail()
{
RelationNo = string.Empty,
RelationNoLineNumber = string.Empty,
Remarks = remark
};
//源信息
//新增的库存源信息都是空
if (isEmptyConinter)
{
sourceStockView = null;
}
//新增事务记录
WmsRecordTrans addWmsRecordTrans = LogRecordHelper.CreateWmsRecordTrans(wmsBaseBusinessType, sourceStockView, toStockModel, toPlace, transferOtherDetail);
return addWmsRecordTrans;
}
}