|
|
using Admin.NET.Core.Service;
|
using Admin.NET.Application.Entity;
|
using Microsoft.AspNetCore.Http;
|
using System.Data;
|
using System.Web;
|
using System.Text;
|
using static SKIT.FlurlHttpClient.Wechat.Api.Models.ChannelsECLeagueHeadSupplierOrderGetResponse.Types.CommssionOrder.Types;
|
using Microsoft.AspNetCore.Razor.TagHelpers;
|
using Furion.LinqBuilder;
|
using Admin.NET.Application.CommonHelper;
|
namespace Admin.NET.Application;
|
/// <summary>
|
/// 容器分拣信息服务
|
/// </summary>
|
[ApiDescriptionSettings(ApplicationConst.WmsOperationsGroupName, Order = 100)]
|
public class WmsSortService : IDynamicApiController, ITransient
|
{
|
/// <summary>
|
/// 是否正在执行确认分拣方法
|
/// </summary>
|
private static bool isRuning_Fun_SortConfirm = false;
|
private static SemaphoreSlim semaphoreSlimSortConfirm = new SemaphoreSlim(1, 1);
|
|
private readonly SqlSugarRepository<WmsBaseBusinessType> _WmsBaseBusinessTypeRep;
|
private readonly SqlSugarRepository<WmsContainerSort> _WmsSortRep;
|
private readonly SqlSugarRepository<WmsStockQuan> _wmsStockQuanRep;
|
private readonly SqlSugarRepository<v_wms_stock_quan> _v_wms_stock_quanRep;
|
private readonly SqlSugarRepository<WmsOrderSortDetails> _wmsOrderSortDetailsRep;
|
private readonly SqlSugarRepository<WmsOrderSort> _wmsOrderSortRep;
|
private readonly SqlSugarRepository<WmsOrderMovementDetails> _wmsOrderMovementDetailsRep;
|
private readonly SqlSugarRepository<WmsOrderMovement> _wmsOrderMovementRep;
|
private readonly SqlSugarRepository<WmsTask> _wmsTaskRep;
|
private readonly SqlSugarRepository<WmsBaseContainer> _wmsContainerRep;
|
private readonly SqlSugarRepository<WmsBasePlace> _wmsPlaceRep;
|
|
private readonly SqlSugarRepository<WmsLogAction> _wmsLogActionRep;
|
private readonly SqlSugarRepository<WmsRecordTrans> _wmsRecordTransRep;
|
private readonly SqlSugarRepository<WmsContainerPlace> _wmsContainerPlaceRep;
|
private readonly SqlSugarRepository<WmsRecordSncodePrint> _wmsRecordSncodePrintrep;
|
private readonly UserManager _userManager;
|
private readonly SqlSugarRepository<WmsStockQuanOut> _wmsStockQuanOutRep;
|
private readonly SqlSugarRepository<WmsRecordReceivingDelivery> _wmsRecordReceivingDeliveryRep;
|
private readonly SqlSugarRepository<WmsStockQuanZero> _wmsStockQuanZeroRep;
|
private readonly SqlSugarRepository<WmsOrderDeliverDetails> _WmsOrderDeliverDetailsRep;
|
private readonly SqlSugarRepository<WmsOrderDeliver> _WmsOrderDeliverRep;
|
public WmsSortService(
|
UserManager userManager,
|
SqlSugarRepository<WmsRecordSncodePrint> wmsRecordSncodePrintrep,
|
SqlSugarRepository<WmsBaseBusinessType> WmsBaseBusinessTypeRep,
|
SqlSugarRepository<WmsContainerSort> WmsSortRep,
|
SqlSugarRepository<WmsStockQuan> wmsStockQuanRep,
|
SqlSugarRepository<WmsOrderSortDetails> wmsOrderSortDetailsRep,
|
SqlSugarRepository<WmsOrderSort> wmsOrderSortRep,
|
SqlSugarRepository<WmsOrderMovementDetails> wmsOrderMovementDetailsRep,
|
SqlSugarRepository<WmsOrderMovement> wmsOrderMovementRep,
|
SqlSugarRepository<WmsTask> wmsTaskRep,
|
SqlSugarRepository<WmsBaseContainer> wmsContainerRep,
|
SqlSugarRepository<WmsBasePlace> wmsPlaceRep,
|
SqlSugarRepository<WmsLogAction> wmsLogActionRep,
|
SqlSugarRepository<WmsRecordTrans> wmsRecordTransRep,
|
SqlSugarRepository<WmsContainerPlace> wmsContainerPlaceRep,
|
SqlSugarRepository<v_wms_stock_quan> v_wms_stock_quanRep,
|
SqlSugarRepository<WmsStockQuanOut> wmsStockQuanOutRep,
|
SqlSugarRepository<WmsRecordReceivingDelivery> wmsRecordReceivingDeliveryRep,
|
SqlSugarRepository<WmsStockQuanZero> wmsStockQuanZeroRep,
|
SqlSugarRepository<WmsOrderDeliverDetails> wmsOrderDeliverDetailsRep,
|
SqlSugarRepository<WmsOrderDeliver> wmsOrderDeliverRep
|
)
|
{
|
_userManager = userManager;
|
_wmsRecordSncodePrintrep = wmsRecordSncodePrintrep;
|
_WmsBaseBusinessTypeRep = WmsBaseBusinessTypeRep;
|
_WmsSortRep = WmsSortRep;
|
_wmsStockQuanRep = wmsStockQuanRep;
|
_wmsOrderSortDetailsRep = wmsOrderSortDetailsRep;
|
_wmsOrderSortRep = wmsOrderSortRep;
|
_wmsOrderMovementDetailsRep = wmsOrderMovementDetailsRep;
|
_wmsOrderMovementRep = wmsOrderMovementRep;
|
_wmsTaskRep = wmsTaskRep;
|
_wmsContainerRep = wmsContainerRep;
|
_wmsPlaceRep = wmsPlaceRep;
|
_wmsLogActionRep = wmsLogActionRep;
|
_wmsRecordTransRep = wmsRecordTransRep;
|
_wmsContainerPlaceRep = wmsContainerPlaceRep;
|
_v_wms_stock_quanRep = v_wms_stock_quanRep;
|
_wmsStockQuanOutRep = wmsStockQuanOutRep;
|
_wmsRecordReceivingDeliveryRep = wmsRecordReceivingDeliveryRep;
|
_wmsStockQuanZeroRep = wmsStockQuanZeroRep;
|
_WmsOrderDeliverDetailsRep = wmsOrderDeliverDetailsRep;
|
_WmsOrderDeliverRep = wmsOrderDeliverRep;
|
}
|
|
|
|
/// <summary>
|
/// 分页查询容器分拣信息
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
[HttpPost]
|
[ApiDescriptionSettings(Name = "GetSortListPage")]
|
[Description("WmsSort/GetSortListPage")]
|
public async Task<SqlSugarPagedList<WmsSortOutput>> GetSortListPage(WmsSortInput input)
|
{
|
var query = CommonPageFilter(input);
|
return await query.OrderBuilder(input, "", "Id").ToPagedListAsync(input.Page, input.PageSize);
|
}
|
|
|
|
/// <summary>
|
/// 不分页查询容器分拣信息--pda分拣用 ly-0607
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
[HttpPost]
|
[ApiDescriptionSettings(Name = "GetSortList")]
|
[Description("wmsSort/GetSortList")]
|
public async Task<List<WmsSortOutput>> List(WmsSortInput input)
|
{
|
var query = CommonPageFilter(input);
|
return await query.OrderBuilder(input, "", "Id").Select<WmsSortOutput>().ToListAsync();
|
}
|
|
|
/// <summary>
|
/// 分拣确认
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
[HttpPost]
|
[ApiDescriptionSettings(Name = "SortConfirm")]
|
[Description("WmsSort/SortConfirm")]
|
public async Task<int> SortConfirm(SortConfirmInput input)
|
{
|
try
|
{
|
if (isRuning_Fun_SortConfirm)
|
{
|
throw Oops.Oh("程序正忙,请稍后再试");
|
}
|
await semaphoreSlimSortConfirm.WaitAsync();
|
|
isRuning_Fun_SortConfirm = true;
|
|
//TODO 确认分拣
|
await _SortConfirm(input);
|
|
return 1;
|
}
|
catch (Exception ex)
|
{
|
throw Oops.Oh(ex.Message);
|
}
|
finally
|
{
|
semaphoreSlimSortConfirm.Release();
|
isRuning_Fun_SortConfirm = false;
|
}
|
}
|
|
/// <summary>
|
/// 分拣异常标记
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
[HttpPost]
|
[ApiDescriptionSettings(Name = "SortExceptionFlagConfirm")]
|
[Description("WmsSort/SortExceptionFlagConfirm")]
|
public async Task<int> SortExceptionFlagConfirm(SortExceptionFlagConfirmInput input)
|
{
|
try
|
{
|
if (isRuning_Fun_SortConfirm)
|
{
|
throw Oops.Oh("程序正忙,请稍后再试");
|
}
|
await semaphoreSlimSortConfirm.WaitAsync();
|
|
isRuning_Fun_SortConfirm = true;
|
|
await _SortExceptionFlagConfirm(input);
|
|
return 1;
|
}
|
catch (Exception ex)
|
{
|
throw Oops.Oh(ex.Message);
|
}
|
finally
|
{
|
semaphoreSlimSortConfirm.Release();
|
isRuning_Fun_SortConfirm = false;
|
}
|
}
|
|
#region 私有方法
|
|
|
private async Task<int> _SortConfirm(SortConfirmInput input)
|
{
|
/*
|
* 1.获取已下发的分拣信息
|
* 2.校验分拣信息状态和分拣数
|
* 3.校验出库任务未完成不能分拣
|
* 4.校验下架单、波次单状态、已分拣数和需求数
|
* 4.校验容器是否存在未完成的调度任务,存在就不能下发
|
* 4.逻辑删除波次锁定库存
|
* 5.更新分拣信息状态
|
* 6.更新上架单状态、分拣数
|
* 6.1 一步法的情况,整托出到线边,大部分情况,即使下架单需求数小于容器上的实际库存数,也是全出。
|
* 比如需求数是10,容器实际库存是20,应当更新单据的分拣数=20(实际20个库存全去了线边)
|
*
|
* 6.2 二步法的情况,实际分拣数不能大于需求数
|
*
|
* 7.更新波次单状态、分拣数
|
* 7.1 一步法的情况,整托出到线边,大部分情况,即使下架单需求数小于容器上的实际库存数,也是
|
* 比如需求数是10,容器实际库存是20,应当更新单据的分拣数=20(实际20个库存全去了线边)
|
* (尚未实现)
|
* 7.2 二步法的情况,实际分拣数不能大于需求数
|
*
|
* 8.库存状态变更
|
* 9.库存库位转移
|
* 9.1 下架单指定目标库位 =》库存转移到该目标库位
|
* 9.2 下架单指定目标库区(线边库区),没有指定库位=》库存转移到 线边库区的虚拟库位“接驳位”。
|
* 说明:原材料库区的下架单目标库区只能选择 线边库区。
|
*
|
* 10.添加事务记录
|
* 11.添加操作履历
|
*
|
* 12 如果绑定do单 更新do状态 发货数
|
*
|
*
|
*/
|
|
//当前分拣容器
|
|
|
List<WmsBasePlace> updatePlaceList = new List<WmsBasePlace>();//变更库位集合
|
List<WmsStockQuan> updateWmsStockQuanList = new List<WmsStockQuan>();//变更库存集合
|
List<WmsStockQuanOut> addWmsStockQuanOutList = new List<WmsStockQuanOut>();//转移库存集合
|
List<WmsStockQuan> deleteWmsStockQuanList = new List<WmsStockQuan>();//删除库存集合
|
List<WmsOrderMovement> updateOrderMovementList = new List<WmsOrderMovement>();//变更下架单集合
|
List<WmsOrderMovementDetails> updateOrderMovementDetailsList = new List<WmsOrderMovementDetails>();//变更下架单集合
|
|
List<WmsOrderDeliver> updateWmsOrderDeliverList = new List<WmsOrderDeliver>();//DO主单集合
|
List<WmsOrderDeliverDetails> updateOrderDeliverDetailsList = new List<WmsOrderDeliverDetails>();//DO明细集合
|
|
List<WmsOrderSort> updateOrderSortList = new List<WmsOrderSort>();//变更波次单集合
|
List<WmsOrderSortDetails> updateOrderSortDetailsList = new List<WmsOrderSortDetails>();//变更波次单明细集合
|
List<WmsContainerSort> updateContainerSortList = new List<WmsContainerSort>();//变更容器分拣信息集合
|
List<WmsRecordSncodePrint> addWmsRecordSncodePrintList = new List<WmsRecordSncodePrint>();//新增分拣打印信息
|
List<WmsRecordReceivingDelivery> addWmsRecordReceivingDeliveryList = new List<WmsRecordReceivingDelivery>();// 新增发货记录信息
|
List<WmsStockQuanZero> addWmsStockQuanZeroList = new List<WmsStockQuanZero>();// 库存为0集合
|
|
//新增事务记录
|
List<WmsRecordTrans> addWmsRecordTransList = new List<WmsRecordTrans>();
|
//新增操作履历
|
List<WmsLogAction> addWmsLogActionList = new List<WmsLogAction>();
|
|
//分拣容器
|
WmsBaseContainer currentContainer = await _wmsContainerRep.GetFirstAsync(x => x.ContainerCode.Equals(input.ContainerCode));
|
if (currentContainer == null)
|
{
|
throw Oops.Oh($"容器{input.ContainerCode}不能存在!");
|
}
|
if (currentContainer.IsDisabled == true)
|
{
|
throw Oops.Oh($"容器{input.ContainerCode}已禁用!");
|
}
|
if (currentContainer.IsVirtually == true)
|
{
|
throw Oops.Oh($"容器{input.ContainerCode}是虚拟容器!");
|
}
|
|
//获取库存未完成的调度任务
|
var allTaskList = await _wmsTaskRep.GetListAsync(x => x.TaskStatus != TaskStatusEnum.已完成 && x.TaskStatus != TaskStatusEnum.已取消 && x.IsDelete == false && currentContainer.ContainerCode.Equals(x.ContainerCode));
|
|
if (allTaskList?.Count > 0)
|
{
|
throw Oops.Oh($"容器{currentContainer.ContainerCode}存在未完成的调用任务");
|
}
|
|
|
List<long> sortIdList = input.SortDetailsConfirmList.Select(x => x.ContainerSortId).ToList();
|
//获取已下发的分拣信息
|
List<WmsContainerSort> sortList = await _WmsSortRep.GetListAsync(x => sortIdList.Contains(x.Id));
|
if (sortIdList?.Count <= 0)
|
{
|
throw Oops.Oh("分拣物料不能为空!");
|
}
|
List<string> moveOrderNoList = sortList.Select(x => x.RelationNo).ToList();
|
//获取下架单
|
List<WmsOrderMovement> allOrderMovementList = await _wmsOrderMovementRep.GetListAsync(x => moveOrderNoList.Contains(x.OrderNo) && x.IsDelete == false);
|
if (allOrderMovementList?.Count <= 0)
|
{
|
throw Oops.Oh("未获取到下架单!");
|
}
|
|
|
|
List<long> moveIdList = allOrderMovementList.Select(x => x.Id).ToList();
|
//获取下架单全部明细
|
List<WmsOrderMovementDetails> allOrderMovementDetailsList = await _wmsOrderMovementDetailsRep.GetListAsync(x => moveIdList.Contains(x.MovementId) && x.IsDelete == false);
|
|
//-----ly-获取Do单全部明细
|
List<WmsOrderDeliver> allWmsOrderDeliverList = new List<WmsOrderDeliver>();
|
List<WmsOrderDeliverDetails> allWmsOrderDeliverDetailsList = new List<WmsOrderDeliverDetails>();
|
List<string> doNoList = allOrderMovementDetailsList.Select(x => x.RelationNo).ToList();
|
if (doNoList.Count > 0)
|
{
|
allWmsOrderDeliverList = await _WmsOrderDeliverRep.GetListAsync(x => doNoList.Contains(x.DeliverNo) && x.IsDelete == false);
|
allWmsOrderDeliverDetailsList = await _WmsOrderDeliverDetailsRep.GetListAsync(x => doNoList.Contains(x.DoNo) && x.IsDelete == false);
|
if (doNoList?.Count <= 0)
|
{
|
throw Oops.Oh("未获取到Do单!");
|
}
|
}
|
//----ly-获取Do单全部明细
|
|
//获取波次单
|
List<string> orderSortNoList = sortList.Select(x => x.SortNo).ToList();
|
List<WmsOrderSort> allOrderSortList = await _wmsOrderSortRep.GetListAsync(x => orderSortNoList.Contains(x.SortNo) && x.IsDelete == false);
|
|
//获取波次单所有明细
|
List<long> orderSortIdList = allOrderSortList.Select(x => x.Id).ToList();
|
List<WmsOrderSortDetails> allOrderSortDetailsList = await _wmsOrderSortDetailsRep.GetListAsync(x => orderSortIdList.Contains(x.SortId) && x.IsDelete == false);
|
|
|
|
//获取容器的所有库存信息
|
List<WmsStockQuan> allContainerStockQuans = await _wmsStockQuanRep.GetListAsync(x => x.ContainerCode == currentContainer.ContainerCode);
|
//获取所有库存视图信息 添加事务记录用
|
List<v_wms_stock_quan> allStockQuanViewList = await _v_wms_stock_quanRep.GetListAsync(x => allContainerStockQuans.Select(s => s.SNCode).ToList().Contains(x.SNCode));
|
|
//获取库存库位相信
|
var placeCodeList = allStockQuanViewList.Select(s => s.PlaceCode).Distinct().ToList();
|
var allPlaeList = await _wmsPlaceRep.GetListAsync(u => placeCodeList.Contains(u.PlaceCode) && u.IsDelete == false);
|
|
//验证
|
await ValidateInput(input, currentContainer, sortList, allContainerStockQuans, allOrderMovementList, allOrderMovementDetailsList, allOrderSortDetailsList, allOrderSortList);
|
|
|
//处理分拣信息
|
foreach (var item in input.SortDetailsConfirmList)
|
{
|
//当前要处理的分拣信息
|
var sortItem = sortList.FirstOrDefault(x => x.Id == item.ContainerSortId);
|
sortItem.PickQuantity += item.OccQuality;//更新分拣信息实际分拣数量
|
|
OrderHelper.UpdateContainerSortStatus(sortItem);
|
updateContainerSortList.Add(sortItem);
|
|
//当前处理的波次单明细
|
var currentOrderSortDetails = allOrderSortDetailsList.FirstOrDefault(x => x.Id == sortItem.SortDetailsId && x.IsDelete == false);
|
currentOrderSortDetails.PickQuantity += item.OccQuality; //更新波次单明细实际分拣数量
|
OrderHelper.updateOrderSortDetailsStatus(currentOrderSortDetails);
|
updateOrderSortDetailsList.Add(currentOrderSortDetails);
|
|
//当前处理的下架单单明细
|
var currentOrderMovementDetails = allOrderMovementDetailsList.FirstOrDefault(x => x.MovementNo == currentOrderSortDetails.RelationNo && x.LineNumber == currentOrderSortDetails.RelationNoLineNumber && x.IsDelete == false);
|
currentOrderMovementDetails.PickQuantity += item.OccQuality;//更新下架单明细实际分拣数量
|
OrderHelper.UpdateOrderMovementDetailsStatus(currentOrderMovementDetails);
|
updateOrderMovementDetailsList.Add(currentOrderMovementDetails);
|
|
//ly-当前处理的Do单明细
|
if (currentOrderMovementDetails.RelationNo != null)
|
{
|
var currentOrderDeliverDetails = allWmsOrderDeliverDetailsList.FirstOrDefault(x => x.DoNo == currentOrderMovementDetails.RelationNo && x.DoLineNumber == currentOrderMovementDetails.RelationNoLineNumber && x.IsDelete == false);
|
if (currentOrderDeliverDetails != null)
|
{
|
currentOrderDeliverDetails.DeliverQuantity += item.OccQuality;
|
OrderHelper.UpdateOrderDeliverDetailsStatus(currentOrderDeliverDetails);
|
updateOrderDeliverDetailsList.Add(currentOrderDeliverDetails);
|
}
|
}
|
|
|
//update by liuwq 20240720 查询库存视图
|
#region 事务入参
|
BusinessTypeEnum businessTypeEnum = BusinessTypeEnum.拣货;
|
// 获取业务类型
|
var wmsBaseBusinessType = BusinessTypeHelper.GetBusinessTypeInfoFromDB((int)businessTypeEnum, _WmsBaseBusinessTypeRep);
|
string recordTransRemarks = string.Empty;
|
|
#endregion
|
|
|
|
//根据锁定库存跟踪码 获取库存信息
|
var currentContainerStockQuans = allContainerStockQuans.FirstOrDefault(x => x.SNCode == sortItem.SNCode && x.IsDelete == false);
|
currentContainerStockQuans.Quantity -= item.OccQuality;//更新库存数量
|
if (currentContainerStockQuans.Quantity < 0)
|
{
|
throw Oops.Oh($"跟踪码{currentContainerStockQuans.SNCode}库存扣减后数量为{currentContainerStockQuans.Quantity},库存不足");
|
}
|
|
currentContainerStockQuans.MaxIndex = currentContainerStockQuans.MaxIndex ?? 0;
|
|
|
//TODO 是否需要删除用完的库存
|
if (currentContainerStockQuans.Quantity == 0)
|
{
|
|
|
//库存分拣完,全部转移到 线边区域,将库存为0的转到库存为0表中
|
//currentContainerStockQuans.IsDelete = true;
|
deleteWmsStockQuanList.Add(currentContainerStockQuans);//update by liuwq 20240801 删除0库存
|
var wmsStockQuanZero = currentContainerStockQuans.Adapt<WmsStockQuanZero>();
|
addWmsStockQuanZeroList.Add(wmsStockQuanZero);
|
}
|
//分拣完成需要解冻库存 【Editby shaocx,2024-07-28】
|
StockQuanHelper.UpdateStockLockStatus(currentContainerStockQuans, new LockInfo()
|
{
|
LockStatus = LockStatusEnum.未锁定,
|
LockReason = "分拣完成解冻",
|
LockTime = DateTime.Now,
|
LockUser = _userManager.RealName,//登录人的真实姓名
|
});
|
|
updateWmsStockQuanList.Add(currentContainerStockQuans);
|
|
addWmsRecordSncodePrintList.Add(RecordSncodePrintHelper.AddWmsRecordSncodePrintEntity(currentContainerStockQuans, PrintTypeEnum.物料跟踪码, PrintSourceEnum.物料分拣打印));
|
|
|
#region 转移库存添加事务、操作日志
|
recordTransRemarks = $"拣货转移库存";
|
WmsRecordTrans addWmsRecordTrans = CreateRecordTransInfoForJH(item.OccQuality, currentOrderSortDetails, allPlaeList, allStockQuanViewList, wmsBaseBusinessType, currentContainerStockQuans, recordTransRemarks);
|
addWmsRecordTransList.Add(addWmsRecordTrans);
|
|
//新增操作日志
|
WmsLogAction wareActionLog = LogActionHelper.CreateWmsLogAction(currentContainerStockQuans.Id, recordTransRemarks, $"更新库存跟踪码{currentContainerStockQuans.SNCode}");
|
addWmsLogActionList.Add(wareActionLog);
|
#endregion
|
|
|
//TODO 变更库位属性=禁入,是否应该在调度任务执行
|
//var currentPlace = allPlaceList.FirstOrDefault(f => f.PlaceCode.Equals(currentContainerStockQuansLock.PlaceCode));
|
//currentPlace.PlaceStatus = PlaceStatusEnum.封存;//PDA分拣操作后库位属性变更为封存
|
//updatePlaceList.Add(currentPlace);
|
|
|
|
//分拣的库存转移到线边区域
|
var newWmsStockQuanOut = currentContainerStockQuans.Adapt<WmsStockQuanOut>();
|
//获取线边库区容器 //根据下架单的目标库区转移,原材料库只能选择 线边库区的线边库位。
|
newWmsStockQuanOut.Id = Yitter.IdGenerator.YitIdHelper.NextId();//TODO
|
//newWmsStockQuanOut.SN_1d = string.Empty;//TODO
|
//newWmsStockQuanOut.SN_2d = string.Empty;//TODO
|
newWmsStockQuanOut.SourceSNCode = currentContainerStockQuans.SNCode;//分拣拆分创建的新库存记录
|
newWmsStockQuanOut.SNCode = currentContainerStockQuans.SNCode;
|
|
currentContainerStockQuans.MaxIndex++;//累计拆分次数,作为跟踪码的最大索引,用于产生新的库存跟踪码
|
|
//但是业务上库存信息实际已经转移到线边区了, 数据也转移到WmsStockQuanOut表了
|
//newWmsStockQuanOut.ContainerCode = OperationsContainerEnum.LS.ToString();
|
|
//TODO 系统增加一个配置 ,是否支持分拣
|
//工厂没有分拣操作的,容器是整个运到线边库区,容器不变,全部库存都出掉,下架单的下架数更新为全部库存。(此种场景 一定是一个物料只有一件的放在容器里)
|
|
newWmsStockQuanOut.Quantity = item.OccQuality;
|
newWmsStockQuanOut.StockStatus = StockStatusEnum.已下架;
|
newWmsStockQuanOut.StockStatusName = StockStatusEnum.已下架.GetDescription();
|
//StockQuanHelper.UpdateStockStatus(newWmsStockQuan, StockStatusEnum.已下架, BusinessTypeEnum.拣货.GetDescription());
|
addWmsStockQuanOutList.Add(newWmsStockQuanOut);
|
|
var newWmsStockQuan = newWmsStockQuanOut.Adapt<WmsStockQuan>();
|
addWmsRecordSncodePrintList.Add(RecordSncodePrintHelper.AddWmsRecordSncodePrintEntity(newWmsStockQuan, PrintTypeEnum.物料跟踪码, PrintSourceEnum.物料分拣打印));
|
|
// 添加发货记录
|
if (item.OccQuality > 0)
|
{
|
var wmsRecordReceivingDelivery = currentContainerStockQuans.Adapt<WmsRecordReceivingDelivery>();
|
wmsRecordReceivingDelivery.Images = "";
|
wmsRecordReceivingDelivery.Quantity = item.OccQuality;
|
wmsRecordReceivingDelivery.RelationNo = currentOrderSortDetails.RelationNo;
|
wmsRecordReceivingDelivery.RelationNoLineNumber = currentOrderSortDetails.RelationNoLineNumber;
|
wmsRecordReceivingDelivery.OrderNo = currentOrderSortDetails.SortNo;
|
wmsRecordReceivingDelivery.OrderNoLineNumber = currentOrderSortDetails.LineNumber;
|
wmsRecordReceivingDelivery.CustCode = currentOrderSortDetails.CustCode;
|
wmsRecordReceivingDelivery.ErpCode = currentOrderMovementDetails.ErpCode;
|
wmsRecordReceivingDelivery.ErpOrderNo = currentOrderMovementDetails.ErpOrderNo;
|
wmsRecordReceivingDelivery.ErpVoucher = newWmsStockQuan.ErpVoucher;
|
wmsRecordReceivingDelivery.Id = Yitter.IdGenerator.YitIdHelper.NextId();//TODO
|
wmsRecordReceivingDelivery.InOutFlag = InOutFlagEnum.出;
|
wmsRecordReceivingDelivery.MoveType = wmsBaseBusinessType.MoveType;
|
wmsRecordReceivingDelivery.MoveTypeName = wmsBaseBusinessType.MoveTypeName;
|
wmsRecordReceivingDelivery.BusinessType = wmsBaseBusinessType.BusinessTypeValue;
|
wmsRecordReceivingDelivery.BusinessTypeName = wmsBaseBusinessType.BusinessTypeName;
|
wmsRecordReceivingDelivery.OrderType = OrderTypeEnum.波次单;
|
wmsRecordReceivingDelivery.OrderTypeName = OrderTypeEnum.波次单.GetDescription();
|
wmsRecordReceivingDelivery.Remarks = "分拣";
|
addWmsRecordReceivingDeliveryList.Add(wmsRecordReceivingDelivery);
|
}
|
|
|
|
#region 新增下架库存 操作日志
|
|
|
|
recordTransRemarks = $"拣货转移库存到线边";
|
|
|
//新增操作日志
|
wareActionLog = LogActionHelper.CreateWmsLogAction(currentContainerStockQuans.Id, recordTransRemarks, $"新增跟踪码{newWmsStockQuanOut.SNCode}库存");
|
addWmsLogActionList.Add(wareActionLog);
|
#endregion
|
|
}
|
|
//更新下架单状态
|
foreach (var item in allOrderMovementList)
|
{
|
var updateOrderMovementDetails = allOrderMovementDetailsList.Where(w => w.MovementId == item.Id).ToList();
|
////计算 下架单的状态
|
OrderHelper.UpdatOrderMovementStatus(updateOrderMovementDetails, item);
|
updateOrderMovementList.Add(item);
|
}
|
|
//ly0802 DO单存在 更新DO主单
|
if (allWmsOrderDeliverList.Count > 0)
|
{
|
foreach (var item in allWmsOrderDeliverList)
|
{
|
var updateOrderDeliverDetails = allWmsOrderDeliverDetailsList.Where(w => w.DoId == item.Id).ToList();
|
OrderHelper.UpdatOrderDeliverStatus(updateOrderDeliverDetails, item);
|
updateWmsOrderDeliverList.Add(item);
|
}
|
}
|
|
//更新波次单状态
|
foreach (var item in allOrderSortList)
|
{
|
var updateOrderSortDetails = allOrderSortDetailsList.Where(w => w.SortId == item.Id).ToList();
|
////计算 波次单单的状态
|
OrderHelper.UpdatOrderSortStatus(updateOrderSortDetails, item);
|
updateOrderSortList.Add(item);
|
}
|
|
|
var _tenant = _WmsSortRep.AsTenant();
|
try
|
{
|
await _tenant.BeginTranAsync();
|
|
#region 事务内执行操作
|
//处理库存
|
await _wmsStockQuanOutRep.InsertRangeAsync(addWmsStockQuanOutList); // 添加库存出库表
|
await _wmsRecordReceivingDeliveryRep.InsertRangeAsync(addWmsRecordReceivingDeliveryList);// 添加库存出库记录
|
await _wmsStockQuanZeroRep.InsertRangeAsync(addWmsStockQuanZeroList);// 添加库存为0的表中
|
|
await _wmsStockQuanRep.UpdateRangeAsync(updateWmsStockQuanList);
|
|
if (deleteWmsStockQuanList?.Count > 0)
|
{
|
await _wmsStockQuanRep.DeleteAsync(deleteWmsStockQuanList);
|
}
|
|
//处理库区
|
//TODO 变更库位属性=禁入,是否应该在调度任务执行
|
// await _wmsPlaceRep.UpdateRangeAsync(updatePlaceList);
|
|
//处理单据
|
await _wmsOrderMovementDetailsRep.UpdateRangeAsync(updateOrderMovementDetailsList);
|
await _wmsOrderMovementRep.UpdateRangeAsync(updateOrderMovementList);
|
|
//更新DO单主表
|
if (updateWmsOrderDeliverList.Count > 0)
|
{
|
await _WmsOrderDeliverRep.UpdateRangeAsync(updateWmsOrderDeliverList);
|
}
|
//更新DO单明细表
|
if (updateOrderDeliverDetailsList.Count > 0)
|
{
|
await _WmsOrderDeliverDetailsRep.UpdateRangeAsync(updateOrderDeliverDetailsList);
|
}
|
|
await _wmsOrderSortDetailsRep.UpdateRangeAsync(updateOrderSortDetailsList);
|
await _wmsOrderSortRep.UpdateRangeAsync(updateOrderSortList);
|
|
//处理容器分拣信息
|
await _WmsSortRep.UpdateRangeAsync(updateContainerSortList);
|
|
//新增事务记录、收货记录、操作日志
|
await _wmsLogActionRep.InsertRangeAsync(addWmsLogActionList);
|
await _wmsRecordTransRep.InsertRangeAsync(addWmsRecordTransList);
|
|
//新增打印记录
|
await _wmsRecordSncodePrintrep.InsertRangeAsync(addWmsRecordSncodePrintList);
|
|
|
#endregion
|
|
await _tenant.CommitTranAsync();
|
}
|
catch
|
{
|
await _tenant.RollbackTranAsync();
|
throw;
|
}
|
|
|
return 1;
|
}
|
|
|
/// <summary>
|
/// 分拣标记异常内部方法
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
private async Task<int> _SortExceptionFlagConfirm(SortExceptionFlagConfirmInput input)
|
{
|
List<WmsStockQuan> updateWmsStockQuanList = new List<WmsStockQuan>();//变更库存集合
|
List<WmsStockQuan> addWmsStockQuanList_ExceptionFlag = new List<WmsStockQuan>();//标记异常的库存集合
|
|
List<WmsOrderMovement> updateOrderMovementList = new List<WmsOrderMovement>();//变更下架单集合
|
List<WmsOrderMovementDetails> updateOrderMovementDetailsList = new List<WmsOrderMovementDetails>();//变更下架单集合
|
|
|
|
List<WmsOrderSort> updateOrderSortList = new List<WmsOrderSort>();//变更波次单集合
|
List<WmsOrderSortDetails> updateOrderSortDetailsList = new List<WmsOrderSortDetails>();//变更波次单明细集合
|
List<WmsContainerSort> updateContainerSortList = new List<WmsContainerSort>();//变更容器分拣信息集合
|
List<WmsContainerSort> deleteContainerSortList = new List<WmsContainerSort>();//移除容器分拣信息集合
|
List<WmsRecordSncodePrint> addWmsRecordSncodePrintList = new List<WmsRecordSncodePrint>();//新增分拣打印信息
|
|
|
|
//新增事务记录
|
List<WmsRecordTrans> addWmsRecordTransList = new List<WmsRecordTrans>();
|
//新增操作履历
|
List<WmsLogAction> addWmsLogActionList = new List<WmsLogAction>();
|
|
//分拣容器
|
WmsBaseContainer currentContainer = await _wmsContainerRep.GetFirstAsync(x => x.ContainerCode.Equals(input.ContainerCode));
|
if (currentContainer == null)
|
{
|
throw Oops.Oh($"容器{input.ContainerCode}不能存在!");
|
}
|
if (currentContainer.IsDisabled == true)
|
{
|
throw Oops.Oh($"容器{input.ContainerCode}已禁用!");
|
}
|
if (currentContainer.IsVirtually == true)
|
{
|
throw Oops.Oh($"容器{input.ContainerCode}是虚拟容器!");
|
}
|
|
//获取库存未完成的调度任务
|
var allTaskList = await _wmsTaskRep.GetListAsync(x => x.TaskStatus != TaskStatusEnum.已完成 && x.TaskStatus != TaskStatusEnum.已取消 && x.IsDelete == false && currentContainer.ContainerCode.Equals(x.ContainerCode));
|
|
if (allTaskList?.Count > 0)
|
{
|
throw Oops.Oh($"容器{currentContainer.ContainerCode}存在未完成的调用任务");
|
}
|
|
|
List<long> sortIdList = input.SortExceptionFlagDetailsConfirmList.Select(x => x.ContainerSortId).ToList();
|
//获取已下发的分拣信息
|
List<WmsContainerSort> sortList = await _WmsSortRep.GetListAsync(x => sortIdList.Contains(x.Id));
|
if (sortIdList?.Count <= 0)
|
{
|
throw Oops.Oh("分拣物料不能为空!");
|
}
|
List<string> moveOrderNoList = sortList.Select(x => x.RelationNo).ToList();
|
//获取下架单
|
List<WmsOrderMovement> allOrderMovementList = await _wmsOrderMovementRep.GetListAsync(x => moveOrderNoList.Contains(x.OrderNo) && x.IsDelete == false);
|
if (allOrderMovementList?.Count <= 0)
|
{
|
throw Oops.Oh("未获取到下架单!");
|
}
|
|
|
|
List<long> moveIdList = allOrderMovementList.Select(x => x.Id).ToList();
|
//获取下架单全部明细
|
List<WmsOrderMovementDetails> allOrderMovementDetailsList = await _wmsOrderMovementDetailsRep.GetListAsync(x => moveIdList.Contains(x.MovementId) && x.IsDelete == false);
|
|
//-----ly-获取Do单全部明细
|
List<WmsOrderDeliver> allWmsOrderDeliverList = new List<WmsOrderDeliver>();
|
List<WmsOrderDeliverDetails> allWmsOrderDeliverDetailsList = new List<WmsOrderDeliverDetails>();
|
List<string> doNoList = allOrderMovementDetailsList.Select(x => x.RelationNo).ToList();
|
if (doNoList.Count > 0)
|
{
|
allWmsOrderDeliverList = await _WmsOrderDeliverRep.GetListAsync(x => doNoList.Contains(x.DeliverNo) && x.IsDelete == false);
|
allWmsOrderDeliverDetailsList = await _WmsOrderDeliverDetailsRep.GetListAsync(x => doNoList.Contains(x.DoNo) && x.IsDelete == false);
|
if (doNoList?.Count <= 0)
|
{
|
throw Oops.Oh("未获取到Do单!");
|
}
|
}
|
//----ly-获取Do单全部明细
|
|
//获取波次单
|
List<string> orderSortNoList = sortList.Select(x => x.SortNo).ToList();
|
List<WmsOrderSort> allOrderSortList = await _wmsOrderSortRep.GetListAsync(x => orderSortNoList.Contains(x.SortNo) && x.IsDelete == false);
|
|
//获取波次单所有明细
|
List<long> orderSortIdList = allOrderSortList.Select(x => x.Id).ToList();
|
List<WmsOrderSortDetails> allOrderSortDetailsList = await _wmsOrderSortDetailsRep.GetListAsync(x => orderSortIdList.Contains(x.SortId) && x.IsDelete == false);
|
|
|
|
//获取容器的所有库存信息
|
List<WmsStockQuan> allContainerStockQuans = await _wmsStockQuanRep.GetListAsync(x => x.ContainerCode == currentContainer.ContainerCode);
|
//获取所有库存视图信息 添加事务记录用
|
List<v_wms_stock_quan> allStockQuanViewList = await _v_wms_stock_quanRep.GetListAsync(x => allContainerStockQuans.Select(s => s.SNCode).ToList().Contains(x.SNCode));
|
|
//获取库存库位相信
|
var placeCodeList = allStockQuanViewList.Select(s => s.PlaceCode).Distinct().ToList();
|
var allPlaeList = await _wmsPlaceRep.GetListAsync(u => placeCodeList.Contains(u.PlaceCode) && u.IsDelete == false);
|
|
//验证
|
await ValidateInputForSortExceptionFlagConfirm(input, currentContainer, sortList, allContainerStockQuans, allOrderMovementList, allOrderMovementDetailsList, allOrderSortDetailsList, allOrderSortList);
|
|
|
|
//处理分拣信息
|
foreach (var item in input.SortExceptionFlagDetailsConfirmList)
|
{
|
var doReason = BusinessTypeEnum.拣货.GetDescription() + ",标记异常数量" + item.ExceptionQuality + ",原因:" + input.ExceptionReason;
|
//当前要处理的分拣信息
|
var sortItem = sortList.FirstOrDefault(x => x.Id == item.ContainerSortId);
|
if ((sortItem.Quantity - sortItem.PickQuantity) < item.ExceptionQuality)
|
{
|
throw Oops.Oh($"物料{sortItem.MaterialCode}的需求分拣数量{sortItem.Quantity},已分拣数量{sortItem.PickQuantity},两者相差不能小于本次标记异常数量{item.ExceptionQuality}");
|
}
|
if ((sortItem.Quantity) < item.ExceptionQuality)
|
{
|
throw Oops.Oh($"物料{sortItem.MaterialCode}的需求分拣数量{sortItem.Quantity}不能小于本次标记异常数量{item.ExceptionQuality}");
|
}
|
sortItem.Quantity -= item.ExceptionQuality;//回滚数量
|
OrderHelper.UpdateContainerSortStatus(sortItem);
|
if (sortItem.Quantity == 0)
|
{
|
deleteContainerSortList.Add(sortItem);
|
}
|
else
|
{
|
updateContainerSortList.Add(sortItem);
|
}
|
|
//当前处理的波次单明细
|
var currentOrderSortDetails = allOrderSortDetailsList.FirstOrDefault(x => x.Id == sortItem.SortDetailsId && x.IsDelete == false);
|
currentOrderSortDetails.IssueQuantity -= item.ExceptionQuality; //回滚下发数
|
currentOrderSortDetails.OffShelvesQuantity -= item.ExceptionQuality; //回滚下架数
|
OrderHelper.updateOrderSortDetailsStatus(currentOrderSortDetails);
|
updateOrderSortDetailsList.Add(currentOrderSortDetails);
|
|
//当前处理的下架单单明细
|
var currentOrderMovementDetails = allOrderMovementDetailsList.FirstOrDefault(x => x.MovementNo == currentOrderSortDetails.RelationNo && x.LineNumber == currentOrderSortDetails.RelationNoLineNumber && x.IsDelete == false);
|
currentOrderMovementDetails.OffShelvesQuantity -= item.ExceptionQuality;//回滚下架数
|
OrderHelper.UpdateOrderMovementDetailsStatus(currentOrderMovementDetails);
|
updateOrderMovementDetailsList.Add(currentOrderMovementDetails);
|
|
|
|
//update by liuwq 20240720 查询库存视图
|
#region 事务入参
|
BusinessTypeEnum businessTypeEnum = BusinessTypeEnum.拣货;
|
// 获取业务类型
|
var wmsBaseBusinessType = BusinessTypeHelper.GetBusinessTypeInfoFromDB((int)businessTypeEnum, _WmsBaseBusinessTypeRep);
|
string recordTransRemarks = string.Empty;
|
|
#endregion
|
|
|
|
//根据锁定库存跟踪码 获取库存信息
|
var currentContainerStockQuans = allContainerStockQuans.FirstOrDefault(x => x.SNCode == sortItem.SNCode && x.IsDelete == false);
|
currentContainerStockQuans.Quantity -= item.ExceptionQuality;//更新库存数量
|
if (currentContainerStockQuans.Quantity < 0)
|
{
|
throw Oops.Oh($"跟踪码{currentContainerStockQuans.SNCode}库存扣减后数量为{currentContainerStockQuans.Quantity},库存不足");
|
}
|
|
currentContainerStockQuans.MaxIndex = currentContainerStockQuans.MaxIndex ?? 0;
|
|
|
|
//分拣完成需要解冻库存 【Editby shaocx,2024-07-28】
|
StockQuanHelper.UpdateStockLockStatus(currentContainerStockQuans, new LockInfo()
|
{
|
LockStatus = LockStatusEnum.未锁定,
|
LockReason = "分拣完成解冻",
|
LockTime = DateTime.Now,
|
LockUser = _userManager.RealName,//登录人的真实姓名
|
});
|
|
updateWmsStockQuanList.Add(currentContainerStockQuans);
|
|
addWmsRecordSncodePrintList.Add(RecordSncodePrintHelper.AddWmsRecordSncodePrintEntity(currentContainerStockQuans, PrintTypeEnum.物料跟踪码, PrintSourceEnum.物料分拣打印));
|
|
|
|
|
|
//TODO 变更库位属性=禁入,是否应该在调度任务执行
|
//var currentPlace = allPlaceList.FirstOrDefault(f => f.PlaceCode.Equals(currentContainerStockQuansLock.PlaceCode));
|
//currentPlace.PlaceStatus = PlaceStatusEnum.封存;//PDA分拣操作后库位属性变更为封存
|
//updatePlaceList.Add(currentPlace);
|
|
|
|
//分拣的库存转移到线边区域
|
var newWmsStockQuan__ExceptionFlag = currentContainerStockQuans.Adapt<WmsStockQuan>();
|
//获取线边库区容器 //根据下架单的目标库区转移,原材料库只能选择 线边库区的线边库位。
|
newWmsStockQuan__ExceptionFlag.Id = Yitter.IdGenerator.YitIdHelper.NextId();//TODO
|
newWmsStockQuan__ExceptionFlag.SNCode = SnCodeHelper.ReturnNewSNCode(currentContainerStockQuans);
|
|
currentContainerStockQuans.MaxIndex++;//累计拆分次数,作为跟踪码的最大索引,用于产生新的库存跟踪码
|
|
//但是业务上库存信息实际已经转移到线边区了, 数据也转移到WmsStockQuanOut表了
|
//newWmsStockQuanOut.ContainerCode = OperationsContainerEnum.LS.ToString();
|
|
//TODO 系统增加一个配置 ,是否支持分拣
|
//工厂没有分拣操作的,容器是整个运到线边库区,容器不变,全部库存都出掉,下架单的下架数更新为全部库存。(此种场景 一定是一个物料只有一件的放在容器里)
|
|
newWmsStockQuan__ExceptionFlag.Quantity = item.ExceptionQuality;
|
StockQuanHelper.UpdateStockStatus(newWmsStockQuan__ExceptionFlag, StockStatusEnum.已冻结,
|
doReason, _userManager.RealName);
|
addWmsStockQuanList_ExceptionFlag.Add(newWmsStockQuan__ExceptionFlag);
|
|
var newWmsStockQuan = newWmsStockQuan__ExceptionFlag.Adapt<WmsStockQuan>();
|
addWmsRecordSncodePrintList.Add(RecordSncodePrintHelper.AddWmsRecordSncodePrintEntity(newWmsStockQuan, PrintTypeEnum.物料跟踪码, PrintSourceEnum.物料分拣打印));
|
|
|
#region 转移库存添加事务、操作日志
|
recordTransRemarks = $"拣货转移库存";
|
var sourceStockView = StockQuanHelper.GetVMmsStockQuan(allStockQuanViewList, currentContainerStockQuans.SNCode);
|
WmsRecordTrans addWmsRecordTrans = await AddWmsRecordTransForSortExceptionFlagConfirm(wmsBaseBusinessType, sourceStockView, currentContainerStockQuans);
|
addWmsRecordTransList.Add(addWmsRecordTrans);
|
|
v_wms_stock_quan new_sourceStockView = sourceStockView.Adapt<v_wms_stock_quan>();
|
new_sourceStockView.SNCode = sourceStockView.SNCode; //源跟踪码是被拆分的库存的跟踪码
|
new_sourceStockView.Quantity = 0;//拆分新增的库存源库存数是0
|
addWmsRecordTrans = await AddWmsRecordTransForSortExceptionFlagConfirm(wmsBaseBusinessType, new_sourceStockView, newWmsStockQuan__ExceptionFlag);
|
addWmsRecordTransList.Add(addWmsRecordTrans);
|
|
//新增操作日志
|
WmsLogAction wareActionLog = LogActionHelper.CreateWmsLogAction(currentContainerStockQuans.Id, recordTransRemarks, $"更新库存跟踪码{currentContainerStockQuans.SNCode}");
|
addWmsLogActionList.Add(wareActionLog);
|
#endregion
|
|
#region 新增下架库存 操作日志
|
|
|
|
recordTransRemarks = $"拣货,标记异常数量";
|
|
|
//新增操作日志
|
wareActionLog = LogActionHelper.CreateWmsLogAction(currentContainerStockQuans.Id, recordTransRemarks, $"新增跟踪码{newWmsStockQuan__ExceptionFlag.SNCode}库存," + doReason);
|
addWmsLogActionList.Add(wareActionLog);
|
#endregion
|
|
}
|
|
//更新下架单状态
|
foreach (var item in allOrderMovementList)
|
{
|
var updateOrderMovementDetails = allOrderMovementDetailsList.Where(w => w.MovementId == item.Id).ToList();
|
////计算 下架单的状态
|
OrderHelper.UpdatOrderMovementStatus(updateOrderMovementDetails, item);
|
updateOrderMovementList.Add(item);
|
}
|
|
|
|
//更新波次单状态
|
foreach (var item in allOrderSortList)
|
{
|
var updateOrderSortDetails = allOrderSortDetailsList.Where(w => w.SortId == item.Id).ToList();
|
////计算 波次单单的状态
|
OrderHelper.UpdatOrderSortStatus(updateOrderSortDetails, item);
|
updateOrderSortList.Add(item);
|
}
|
|
|
var _tenant = _WmsSortRep.AsTenant();
|
try
|
{
|
await _tenant.BeginTranAsync();
|
|
#region 事务内执行操作
|
|
|
//处理库存
|
await _wmsStockQuanRep.InsertRangeAsync(addWmsStockQuanList_ExceptionFlag); // 添加异常标记库存
|
await _wmsStockQuanRep.UpdateRangeAsync(updateWmsStockQuanList);
|
|
|
//处理库区
|
//TODO 变更库位属性=禁入,是否应该在调度任务执行
|
// await _wmsPlaceRep.UpdateRangeAsync(updatePlaceList);
|
|
//处理单据
|
await _wmsOrderMovementDetailsRep.UpdateRangeAsync(updateOrderMovementDetailsList);
|
await _wmsOrderMovementRep.UpdateRangeAsync(updateOrderMovementList);
|
|
|
await _wmsOrderSortDetailsRep.UpdateRangeAsync(updateOrderSortDetailsList);
|
await _wmsOrderSortRep.UpdateRangeAsync(updateOrderSortList);
|
|
//处理容器分拣信息
|
await _WmsSortRep.UpdateRangeAsync(updateContainerSortList);
|
await _WmsSortRep.DeleteAsync(deleteContainerSortList);
|
|
//新增事务记录、收货记录、操作日志
|
await _wmsLogActionRep.InsertRangeAsync(addWmsLogActionList);
|
await _wmsRecordTransRep.InsertRangeAsync(addWmsRecordTransList);
|
|
//新增打印记录
|
await _wmsRecordSncodePrintrep.InsertRangeAsync(addWmsRecordSncodePrintList);
|
|
|
#endregion
|
|
await _tenant.CommitTranAsync();
|
}
|
catch
|
{
|
await _tenant.RollbackTranAsync();
|
throw;
|
}
|
|
|
return 1;
|
}
|
|
|
private async Task<WmsRecordTrans> AddWmsRecordTransForSortExceptionFlagConfirm(WmsBaseBusinessType wmsBaseBusinessType, v_wms_stock_quan sourceStockView, WmsStockQuan toStockQuan)
|
{
|
|
var toPlace = await BaseInfoHelper.GetPlace(sourceStockView.PlaceCode, _wmsPlaceRep);
|
// 其他参数对象
|
TransferOtherDetail transferOtherDetail = new TransferOtherDetail()
|
{
|
RelationNo = "",
|
RelationNoLineNumber = "",
|
Remarks = "",
|
|
};
|
|
//新增事务记录
|
//目标库存 仅变更库存数
|
var ret = LogRecordHelper.CreateWmsRecordTrans(wmsBaseBusinessType, sourceStockView, toStockQuan, toPlace, transferOtherDetail);
|
return ret;
|
}
|
|
|
/// <summary>
|
/// PDA拣货创建事务记录入参方法
|
/// </summary>
|
/// <param name="sotQty"></param>
|
/// <param name="orderSortDetails"></param>
|
/// <param name="allPlaeList"></param>
|
/// <param name="allStockQuanView"></param>
|
/// <param name="businessTypeInfo"></param>
|
/// <param name="StockModel"></param>
|
/// <param name="recordTransRemarks"></param>
|
/// <returns></returns>
|
private WmsRecordTrans CreateRecordTransInfoForJH(decimal sotQty, WmsOrderSortDetails orderSortDetails, List<WmsBasePlace> allPlaeList, List<v_wms_stock_quan> allStockQuanView, WmsBaseBusinessType businessTypeInfo, WmsStockQuan StockModel, string recordTransRemarks)
|
{
|
|
TransferOtherDetail transferOtherDetail = new TransferOtherDetail()
|
{
|
RelationNo = orderSortDetails.SortNo,//波次单号
|
RelationNoLineNumber = orderSortDetails.LineNumber,//波次单行号
|
Remarks = recordTransRemarks,
|
|
};
|
|
var toStockQuan = StockModel.Adapt<WmsStockQuan>();
|
|
//根据库存跟踪码视图可以查询到信息
|
//获取源库存信息
|
var sourceStockView = StockQuanHelper.GetVMmsStockQuan(allStockQuanView, toStockQuan.SNCode);
|
sourceStockView.Quantity = toStockQuan.Quantity + sotQty;//源库存数 (此时库存已经减掉分拣数,计算源库存再加回去)
|
|
|
//拣货库存库存不在原来的地方了,目标库位为空和目标容器为空
|
|
WmsBasePlace toPlace = null;
|
toStockQuan.ContainerCode = string.Empty;
|
|
|
|
//新增事务记录
|
WmsRecordTrans addWmsRecordTrans = LogRecordHelper.CreateWmsRecordTrans(businessTypeInfo, sourceStockView, toStockQuan, toPlace, transferOtherDetail);
|
|
//分拣新增的库存不在记录事务,转移走了
|
|
return addWmsRecordTrans;
|
}
|
|
/// <summary>
|
/// 分拣验证
|
/// </summary>
|
/// <param name="input"></param>
|
/// <param name="currentContainer"></param>
|
/// <returns></returns>
|
private async Task ValidateInput(SortConfirmInput input,
|
WmsBaseContainer currentContainer,
|
List<WmsContainerSort> sortList,
|
List<WmsStockQuan> allContainerStockQuans,
|
List<WmsOrderMovement> allOrderMovementList,
|
List<WmsOrderMovementDetails> allOrderMovementDetailsList,
|
List<WmsOrderSortDetails> allOrderSortDetailsList,
|
List<WmsOrderSort> allSrderSortList
|
)
|
{
|
if (input.SortDetailsConfirmList?.Count() == 0)
|
{
|
throw Oops.Oh("分拣信息不能为空!");
|
}
|
var exist = input.SortDetailsConfirmList.Exists(x => x.ContainerSortId == 0);
|
if (exist)
|
{
|
throw Oops.Oh("分拣信息ID不能为0!");
|
}
|
exist = input.SortDetailsConfirmList.Exists(x => x.OccQuality <= 0);
|
if (exist)
|
{
|
throw Oops.Oh("实际分拣数量不能小于等于0!");
|
}
|
|
if (string.IsNullOrEmpty(input.ContainerCode))
|
{
|
throw Oops.Oh("容器号不能为空!");
|
}
|
exist = input.SortDetailsConfirmList.Exists(x => string.IsNullOrWhiteSpace(x.ContainerCode));
|
if (exist)
|
{
|
throw Oops.Oh("容器号不能为空!");
|
}
|
|
//exist = input.SortDetailsConfirmList.Exists(x => string.IsNullOrWhiteSpace(x.RelationNo));
|
//if (exist)
|
//{
|
// throw Oops.Oh("关联单号不能为空!");
|
//}
|
|
string sortContainerCode = input.ContainerCode.Trim();
|
//获取容器活跃的调度任务
|
var queryParam = ExpressionHelper.GetActiveTask();
|
queryParam.And(x => x.ContainerCode.Equals(sortContainerCode));
|
var taskList = await _wmsTaskRep.GetListAsync(queryParam);
|
if (taskList?.Count > 0)
|
{
|
throw Oops.Oh($"容器编号{input.ContainerCode}出库任务未完成不能分拣");
|
}
|
|
currentContainer = await _wmsContainerRep.GetFirstAsync(x => x.ContainerCode == sortContainerCode);
|
if (currentContainer == null)
|
{
|
throw Oops.Oh($"容器编号{input.ContainerCode}基础信息不存在");
|
}
|
if (currentContainer.IsDisabled == true)
|
{
|
throw Oops.Oh($"容器编号{input.ContainerCode}基础信息已禁用");
|
}
|
|
foreach (var item in input.SortDetailsConfirmList)
|
{
|
var sortItem = sortList.FirstOrDefault(x => x.Id == item.ContainerSortId);
|
if (sortItem == null)
|
{
|
throw Oops.Oh($"ID{item.ContainerSortId}分拣信息不存在");
|
}
|
|
if (sortItem.SortStatus != OrderStatusEnum.新建 && sortItem.SortStatus != OrderStatusEnum.处理中)
|
{
|
throw Oops.Oh($"物料{sortItem.MaterialCode}跟踪码{sortItem.SNCode}分拣信息状态是{sortItem.SortStatus.GetDescription()}");
|
}
|
//容器分拣信息剩余可分拣数
|
var lastSortQty = sortItem.Quantity - sortItem.PickQuantity;
|
if (item.OccQuality > lastSortQty)
|
{
|
throw Oops.Oh($"物料{sortItem.MaterialCode}跟踪码{sortItem.SNCode}分拣数{item.OccQuality}大于可分拣数{lastSortQty}");
|
}
|
|
|
|
//当前处理的波次单明细
|
var currentOrderSortDetails = allOrderSortDetailsList.FirstOrDefault(x => x.Id == sortItem.SortDetailsId && x.IsDelete == false);
|
if (currentOrderSortDetails == null)
|
{
|
throw Oops.Oh($"物料{sortItem.MaterialCode}跟踪码{sortItem.SNCode}波次单明细不存在");
|
}
|
|
if (currentOrderSortDetails.SortDetailStatus != OrderStatusEnum.新建 && currentOrderSortDetails.SortDetailStatus != OrderStatusEnum.处理中)
|
{
|
throw Oops.Oh($"波次单号{currentOrderSortDetails.SortNo}行号{currentOrderSortDetails.LineNumber}明细状态是{currentOrderSortDetails.SortDetailStatus.GetDescription()}");
|
}
|
|
//波次单明细剩余可分拣数校验
|
var lastOrderSortQty = currentOrderSortDetails.Quantity - currentOrderSortDetails.PickQuantity;
|
if (item.OccQuality > lastOrderSortQty)
|
{
|
throw Oops.Oh($"波次单号{currentOrderSortDetails.SortNo}行号{currentOrderSortDetails.LineNumber}物料{currentOrderSortDetails.MaterialCode}可分拣数{lastOrderSortQty}小于本次分拣数{item.OccQuality}");
|
}
|
|
|
//当前处理的下架单单明细
|
var currentOrderMovementDetails = allOrderMovementDetailsList.FirstOrDefault(x => x.MovementNo == currentOrderSortDetails.RelationNo && x.LineNumber == currentOrderSortDetails.RelationNoLineNumber && x.IsDelete == false);
|
if (currentOrderMovementDetails == null)
|
{
|
throw Oops.Oh($"物料{sortItem.MaterialCode}跟踪码{sortItem.SNCode}下架单明细不存在");
|
}
|
|
if (currentOrderMovementDetails.OrderStatus != OrderStatusEnum.新建 && currentOrderMovementDetails.OrderStatus != OrderStatusEnum.处理中)
|
{
|
throw Oops.Oh($"下架单号{currentOrderMovementDetails.MovementNo}行号{currentOrderMovementDetails.LineNumber}明细状态是{currentOrderMovementDetails.OrderStatus.GetDescription()}");
|
}
|
|
//下架单单明细剩余可分拣数
|
var lastOrderSortOrderMovementQty = currentOrderMovementDetails.Quantity - currentOrderMovementDetails.PickQuantity;
|
lastOrderSortOrderMovementQty = lastOrderSortOrderMovementQty < 0 ? 0 : lastOrderSortOrderMovementQty;
|
if (item.OccQuality > lastOrderSortOrderMovementQty)
|
{
|
throw Oops.Oh($"下架单号{currentOrderMovementDetails.MovementNo}行号{currentOrderMovementDetails.LineNumber}物料{currentOrderMovementDetails.MaterialCode}可分拣数{lastOrderSortOrderMovementQty}小于本次分拣数{item.OccQuality}");
|
}
|
|
|
|
|
|
|
}
|
|
}
|
|
/// <summary>
|
/// 分拣异常标记验证
|
/// </summary>
|
/// <param name="input"></param>
|
/// <param name="currentContainer"></param>
|
/// <param name="sortList"></param>
|
/// <param name="allContainerStockQuans"></param>
|
/// <param name="allOrderMovementList"></param>
|
/// <param name="allOrderMovementDetailsList"></param>
|
/// <param name="allOrderSortDetailsList"></param>
|
/// <param name="allSrderSortList"></param>
|
/// <returns></returns>
|
private async Task ValidateInputForSortExceptionFlagConfirm(SortExceptionFlagConfirmInput input,
|
WmsBaseContainer currentContainer,
|
List<WmsContainerSort> sortList,
|
List<WmsStockQuan> allContainerStockQuans,
|
List<WmsOrderMovement> allOrderMovementList,
|
List<WmsOrderMovementDetails> allOrderMovementDetailsList,
|
List<WmsOrderSortDetails> allOrderSortDetailsList,
|
List<WmsOrderSort> allSrderSortList
|
)
|
{
|
if (input.SortExceptionFlagDetailsConfirmList?.Count() == 0)
|
{
|
throw Oops.Oh("分拣信息不能为空!");
|
}
|
var exist = input.SortExceptionFlagDetailsConfirmList.Exists(x => x.ContainerSortId == 0);
|
if (exist)
|
{
|
throw Oops.Oh("分拣信息ID不能为0!");
|
}
|
exist = input.SortExceptionFlagDetailsConfirmList.Exists(x => x.ExceptionQuality <= 0);
|
if (exist)
|
{
|
throw Oops.Oh("实际分拣数量不能小于等于0!");
|
}
|
|
if (string.IsNullOrEmpty(input.ContainerCode))
|
{
|
throw Oops.Oh("容器号不能为空!");
|
}
|
if (string.IsNullOrEmpty(input.ExceptionReason))
|
{
|
throw Oops.Oh("异常原因不能为空!");
|
}
|
exist = input.SortExceptionFlagDetailsConfirmList.Exists(x => string.IsNullOrWhiteSpace(x.ContainerCode));
|
if (exist)
|
{
|
throw Oops.Oh("容器号不能为空!");
|
}
|
|
//exist = input.SortDetailsConfirmList.Exists(x => string.IsNullOrWhiteSpace(x.RelationNo));
|
//if (exist)
|
//{
|
// throw Oops.Oh("关联单号不能为空!");
|
//}
|
|
string sortContainerCode = input.ContainerCode.Trim();
|
//获取容器活跃的调度任务
|
var queryParam = ExpressionHelper.GetActiveTask();
|
queryParam.And(x => x.ContainerCode.Equals(sortContainerCode));
|
var taskList = await _wmsTaskRep.GetListAsync(queryParam);
|
if (taskList?.Count > 0)
|
{
|
throw Oops.Oh($"容器编号{input.ContainerCode}出库任务未完成不能分拣");
|
}
|
|
currentContainer = await _wmsContainerRep.GetFirstAsync(x => x.ContainerCode == sortContainerCode);
|
if (currentContainer == null)
|
{
|
throw Oops.Oh($"容器编号{input.ContainerCode}基础信息不存在");
|
}
|
if (currentContainer.IsDisabled == true)
|
{
|
throw Oops.Oh($"容器编号{input.ContainerCode}基础信息已禁用");
|
}
|
|
foreach (var item in input.SortExceptionFlagDetailsConfirmList)
|
{
|
var sortItem = sortList.FirstOrDefault(x => x.Id == item.ContainerSortId);
|
if (sortItem == null)
|
{
|
throw Oops.Oh($"ID{item.ContainerSortId}分拣信息不存在");
|
}
|
|
if (sortItem.SortStatus != OrderStatusEnum.新建 && sortItem.SortStatus != OrderStatusEnum.处理中)
|
{
|
throw Oops.Oh($"物料{sortItem.MaterialCode}跟踪码{sortItem.SNCode}分拣信息状态是{sortItem.SortStatus.GetDescription()}");
|
}
|
//容器分拣信息剩余可分拣数
|
var lastSortQty = sortItem.Quantity - sortItem.PickQuantity;
|
if (item.ExceptionQuality > lastSortQty)
|
{
|
throw Oops.Oh($"物料{sortItem.MaterialCode}跟踪码{sortItem.SNCode}分拣数{item.ExceptionQuality}大于可分拣数{lastSortQty}");
|
}
|
|
|
|
//当前处理的波次单明细
|
var currentOrderSortDetails = allOrderSortDetailsList.FirstOrDefault(x => x.Id == sortItem.SortDetailsId && x.IsDelete == false);
|
if (currentOrderSortDetails == null)
|
{
|
throw Oops.Oh($"物料{sortItem.MaterialCode}跟踪码{sortItem.SNCode}波次单明细不存在");
|
}
|
|
if (currentOrderSortDetails.SortDetailStatus != OrderStatusEnum.新建 && currentOrderSortDetails.SortDetailStatus != OrderStatusEnum.处理中)
|
{
|
throw Oops.Oh($"波次单号{currentOrderSortDetails.SortNo}行号{currentOrderSortDetails.LineNumber}明细状态是{currentOrderSortDetails.SortDetailStatus.GetDescription()}");
|
}
|
|
//波次单明细剩余可分拣数校验
|
var lastOrderSortQty = currentOrderSortDetails.Quantity - currentOrderSortDetails.PickQuantity;
|
if (item.ExceptionQuality > lastOrderSortQty)
|
{
|
throw Oops.Oh($"波次单号{currentOrderSortDetails.SortNo}行号{currentOrderSortDetails.LineNumber}物料{currentOrderSortDetails.MaterialCode}可分拣数{lastOrderSortQty}小于本次分拣数{item.ExceptionQuality}");
|
}
|
|
|
//当前处理的下架单单明细
|
var currentOrderMovementDetails = allOrderMovementDetailsList.FirstOrDefault(x => x.MovementNo == currentOrderSortDetails.RelationNo && x.LineNumber == currentOrderSortDetails.RelationNoLineNumber && x.IsDelete == false);
|
if (currentOrderMovementDetails == null)
|
{
|
throw Oops.Oh($"物料{sortItem.MaterialCode}跟踪码{sortItem.SNCode}下架单明细不存在");
|
}
|
|
if (currentOrderMovementDetails.OrderStatus != OrderStatusEnum.新建 && currentOrderMovementDetails.OrderStatus != OrderStatusEnum.处理中)
|
{
|
throw Oops.Oh($"下架单号{currentOrderMovementDetails.MovementNo}行号{currentOrderMovementDetails.LineNumber}明细状态是{currentOrderMovementDetails.OrderStatus.GetDescription()}");
|
}
|
|
//下架单单明细剩余可分拣数
|
var lastOrderSortOrderMovementQty = currentOrderMovementDetails.Quantity - currentOrderMovementDetails.PickQuantity;
|
lastOrderSortOrderMovementQty = lastOrderSortOrderMovementQty < 0 ? 0 : lastOrderSortOrderMovementQty;
|
if (item.ExceptionQuality > lastOrderSortOrderMovementQty)
|
{
|
throw Oops.Oh($"下架单号{currentOrderMovementDetails.MovementNo}行号{currentOrderMovementDetails.LineNumber}物料{currentOrderMovementDetails.MaterialCode}可分拣数{lastOrderSortOrderMovementQty}小于本次分拣数{item.ExceptionQuality}");
|
}
|
|
|
|
|
|
|
}
|
|
}
|
|
/// <summary>
|
/// 公共查询容器分拣信息条件
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
private ISugarQueryable<WmsSortOutput> CommonPageFilter(WmsSortInput input)
|
{
|
//if (string.IsNullOrWhiteSpace(input.ContainerCode))
|
//{
|
// throw Oops.Oh("请输入容器号");
|
//}
|
|
var query = _WmsSortRep.AsQueryable()
|
.WhereIF(!string.IsNullOrWhiteSpace(input.SearchKey), u =>
|
u.MaterialCode.Contains(input.SearchKey.Trim())
|
|| u.MaterialName.Contains(input.SearchKey.Trim())
|
|| u.SNCode.Contains(input.SearchKey.Trim())
|
|| u.Batch.Contains(input.SearchKey.Trim())
|
|| u.SupplierBatch.Contains(input.SearchKey.Trim())
|
|| u.ErpCode.Contains(input.SearchKey.Trim())
|
|| u.SortNo.Contains(input.SearchKey.Trim())
|
|| u.RelationNo.Contains(input.SearchKey.Trim())
|
)
|
.WhereIF(!string.IsNullOrWhiteSpace(input.ContainerCode), u => u.ContainerCode == input.ContainerCode)
|
.WhereIF(!string.IsNullOrWhiteSpace(input.MaterialCode), u => u.MaterialCode.Contains(input.MaterialCode.Trim()))
|
.WhereIF(!string.IsNullOrWhiteSpace(input.MaterialName), u => u.MaterialName.Contains(input.MaterialName.Trim()))
|
.WhereIF(!string.IsNullOrWhiteSpace(input.SNCode), u => u.SNCode.Contains(input.SNCode.Trim()))
|
.WhereIF(!string.IsNullOrWhiteSpace(input.SNCode), u => u.SNCode == input.SNCode)
|
.WhereIF(input.SortStatus.HasValue, u => u.SortStatus == input.SortStatus)
|
.WhereIF(!string.IsNullOrWhiteSpace(input.Batch), u => u.Batch.Contains(input.Batch.Trim()))
|
.WhereIF(!string.IsNullOrWhiteSpace(input.SupplierBatch), u => u.SupplierBatch.Contains(input.SupplierBatch.Trim()))
|
.WhereIF(!string.IsNullOrWhiteSpace(input.ErpCode), u => u.ErpCode.Contains(input.ErpCode.Trim()))
|
.WhereIF(!string.IsNullOrWhiteSpace(input.SortNo), u => u.SortNo.Contains(input.SortNo.Trim()))
|
.WhereIF(!string.IsNullOrWhiteSpace(input.RelationNo), u => u.RelationNo == input.RelationNo)
|
.WhereIF(input.RelationOrderType.HasValue, u => u.RelationOrderType == input.RelationOrderType)
|
.Where(u => u.Quantity > u.PickQuantity) //--ly0703 - pda过滤已经分拣完成的数据
|
.Select<WmsSortOutput>();
|
return query;
|
}
|
|
#endregion
|
|
|
|
|
}
|