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;
///
/// 容器分拣信息服务
///
[ApiDescriptionSettings(ApplicationConst.WmsOperationsGroupName, Order = 100)]
public class WmsSortService : IDynamicApiController, ITransient
{
///
/// 是否正在执行确认分拣方法
///
private static bool isRuning_Fun_SortConfirm = false;
private static SemaphoreSlim semaphoreSlimSortConfirm = new SemaphoreSlim(1, 1);
private readonly SqlSugarRepository _WmsBaseBusinessTypeRep;
private readonly SqlSugarRepository _WmsSortRep;
private readonly SqlSugarRepository _wmsStockQuanRep;
private readonly SqlSugarRepository _v_wms_stock_quanRep;
private readonly SqlSugarRepository _wmsOrderSortDetailsRep;
private readonly SqlSugarRepository _wmsOrderSortRep;
private readonly SqlSugarRepository _wmsOrderMovementDetailsRep;
private readonly SqlSugarRepository _wmsOrderMovementRep;
private readonly SqlSugarRepository _wmsTaskRep;
private readonly SqlSugarRepository _wmsContainerRep;
private readonly SqlSugarRepository _wmsPlaceRep;
private readonly SqlSugarRepository _wmsLogActionRep;
private readonly SqlSugarRepository _wmsRecordTransRep;
private readonly SqlSugarRepository _wmsContainerPlaceRep;
private readonly SqlSugarRepository _wmsRecordSncodePrintrep;
private readonly UserManager _userManager;
private readonly SqlSugarRepository _wmsStockQuanOutRep;
private readonly SqlSugarRepository _wmsRecordReceivingDeliveryRep;
private readonly SqlSugarRepository _wmsStockQuanZeroRep;
private readonly SqlSugarRepository _WmsOrderDeliverDetailsRep;
private readonly SqlSugarRepository _WmsOrderDeliverRep;
public WmsSortService(
UserManager userManager,
SqlSugarRepository wmsRecordSncodePrintrep,
SqlSugarRepository WmsBaseBusinessTypeRep,
SqlSugarRepository WmsSortRep,
SqlSugarRepository wmsStockQuanRep,
SqlSugarRepository wmsOrderSortDetailsRep,
SqlSugarRepository wmsOrderSortRep,
SqlSugarRepository wmsOrderMovementDetailsRep,
SqlSugarRepository wmsOrderMovementRep,
SqlSugarRepository wmsTaskRep,
SqlSugarRepository wmsContainerRep,
SqlSugarRepository wmsPlaceRep,
SqlSugarRepository wmsLogActionRep,
SqlSugarRepository wmsRecordTransRep,
SqlSugarRepository wmsContainerPlaceRep,
SqlSugarRepository v_wms_stock_quanRep,
SqlSugarRepository wmsStockQuanOutRep,
SqlSugarRepository wmsRecordReceivingDeliveryRep,
SqlSugarRepository wmsStockQuanZeroRep,
SqlSugarRepository wmsOrderDeliverDetailsRep,
SqlSugarRepository 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;
}
///
/// 分页查询容器分拣信息
///
///
///
[HttpPost]
[ApiDescriptionSettings(Name = "GetSortListPage")]
[Description("WmsSort/GetSortListPage")]
public async Task> GetSortListPage(WmsSortInput input)
{
var query = CommonPageFilter(input);
return await query.OrderBuilder(input, "", "Id").ToPagedListAsync(input.Page, input.PageSize);
}
///
/// 不分页查询容器分拣信息--pda分拣用 ly-0607
///
///
///
[HttpPost]
[ApiDescriptionSettings(Name = "GetSortList")]
[Description("wmsSort/GetSortList")]
public async Task> List(WmsSortInput input)
{
var query = CommonPageFilter(input);
return await query.OrderBuilder(input, "", "Id").Select().ToListAsync();
}
///
/// 分拣确认
///
///
///
[HttpPost]
[ApiDescriptionSettings(Name = "SortConfirm")]
[Description("WmsSort/SortConfirm")]
public async Task 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;
}
}
///
/// 分拣异常标记
///
///
///
[HttpPost]
[ApiDescriptionSettings(Name = "SortExceptionFlagConfirm")]
[Description("WmsSort/SortExceptionFlagConfirm")]
public async Task 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 _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 updatePlaceList = new List();//变更库位集合
List updateWmsStockQuanList = new List();//变更库存集合
List addWmsStockQuanOutList = new List();//转移库存集合
List deleteWmsStockQuanList = new List();//删除库存集合
List updateOrderMovementList = new List();//变更下架单集合
List updateOrderMovementDetailsList = new List();//变更下架单集合
List updateWmsOrderDeliverList = new List();//DO主单集合
List updateOrderDeliverDetailsList = new List();//DO明细集合
List updateOrderSortList = new List();//变更波次单集合
List updateOrderSortDetailsList = new List();//变更波次单明细集合
List updateContainerSortList = new List();//变更容器分拣信息集合
List addWmsRecordSncodePrintList = new List();//新增分拣打印信息
List addWmsRecordReceivingDeliveryList = new List();// 新增发货记录信息
List addWmsStockQuanZeroList = new List();// 库存为0集合
//新增事务记录
List addWmsRecordTransList = new List();
//新增操作履历
List addWmsLogActionList = new List();
//分拣容器
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 sortIdList = input.SortDetailsConfirmList.Select(x => x.ContainerSortId).ToList();
//获取已下发的分拣信息
List sortList = await _WmsSortRep.GetListAsync(x => sortIdList.Contains(x.Id));
if (sortIdList?.Count <= 0)
{
throw Oops.Oh("分拣物料不能为空!");
}
List moveOrderNoList = sortList.Select(x => x.RelationNo).ToList();
//获取下架单
List allOrderMovementList = await _wmsOrderMovementRep.GetListAsync(x => moveOrderNoList.Contains(x.OrderNo) && x.IsDelete == false);
if (allOrderMovementList?.Count <= 0)
{
throw Oops.Oh("未获取到下架单!");
}
List moveIdList = allOrderMovementList.Select(x => x.Id).ToList();
//获取下架单全部明细
List allOrderMovementDetailsList = await _wmsOrderMovementDetailsRep.GetListAsync(x => moveIdList.Contains(x.MovementId) && x.IsDelete == false);
//-----ly-获取Do单全部明细
List allWmsOrderDeliverList = new List();
List allWmsOrderDeliverDetailsList = new List();
List 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 orderSortNoList = sortList.Select(x => x.SortNo).ToList();
List allOrderSortList = await _wmsOrderSortRep.GetListAsync(x => orderSortNoList.Contains(x.SortNo) && x.IsDelete == false);
//获取波次单所有明细
List orderSortIdList = allOrderSortList.Select(x => x.Id).ToList();
List allOrderSortDetailsList = await _wmsOrderSortDetailsRep.GetListAsync(x => orderSortIdList.Contains(x.SortId) && x.IsDelete == false);
//获取容器的所有库存信息
List allContainerStockQuans = await _wmsStockQuanRep.GetListAsync(x => x.ContainerCode == currentContainer.ContainerCode);
//获取所有库存视图信息 添加事务记录用
List 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();
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();
//获取线边库区容器 //根据下架单的目标库区转移,原材料库只能选择 线边库区的线边库位。
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();
addWmsRecordSncodePrintList.Add(RecordSncodePrintHelper.AddWmsRecordSncodePrintEntity(newWmsStockQuan, PrintTypeEnum.物料跟踪码, PrintSourceEnum.物料分拣打印));
// 添加发货记录
if (item.OccQuality > 0)
{
var wmsRecordReceivingDelivery = currentContainerStockQuans.Adapt();
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;
}
///
/// 分拣标记异常内部方法
///
///
///
private async Task _SortExceptionFlagConfirm(SortExceptionFlagConfirmInput input)
{
List updateWmsStockQuanList = new List();//变更库存集合
List addWmsStockQuanList_ExceptionFlag = new List();//标记异常的库存集合
List updateOrderMovementList = new List();//变更下架单集合
List updateOrderMovementDetailsList = new List();//变更下架单集合
List updateOrderSortList = new List();//变更波次单集合
List updateOrderSortDetailsList = new List();//变更波次单明细集合
List updateContainerSortList = new List();//变更容器分拣信息集合
List deleteContainerSortList = new List();//移除容器分拣信息集合
List addWmsRecordSncodePrintList = new List();//新增分拣打印信息
//新增事务记录
List addWmsRecordTransList = new List();
//新增操作履历
List addWmsLogActionList = new List();
//分拣容器
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 sortIdList = input.SortExceptionFlagDetailsConfirmList.Select(x => x.ContainerSortId).ToList();
//获取已下发的分拣信息
List sortList = await _WmsSortRep.GetListAsync(x => sortIdList.Contains(x.Id));
if (sortIdList?.Count <= 0)
{
throw Oops.Oh("分拣物料不能为空!");
}
List moveOrderNoList = sortList.Select(x => x.RelationNo).ToList();
//获取下架单
List allOrderMovementList = await _wmsOrderMovementRep.GetListAsync(x => moveOrderNoList.Contains(x.OrderNo) && x.IsDelete == false);
if (allOrderMovementList?.Count <= 0)
{
throw Oops.Oh("未获取到下架单!");
}
List moveIdList = allOrderMovementList.Select(x => x.Id).ToList();
//获取下架单全部明细
List allOrderMovementDetailsList = await _wmsOrderMovementDetailsRep.GetListAsync(x => moveIdList.Contains(x.MovementId) && x.IsDelete == false);
//-----ly-获取Do单全部明细
List allWmsOrderDeliverList = new List();
List allWmsOrderDeliverDetailsList = new List();
List 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 orderSortNoList = sortList.Select(x => x.SortNo).ToList();
List allOrderSortList = await _wmsOrderSortRep.GetListAsync(x => orderSortNoList.Contains(x.SortNo) && x.IsDelete == false);
//获取波次单所有明细
List orderSortIdList = allOrderSortList.Select(x => x.Id).ToList();
List allOrderSortDetailsList = await _wmsOrderSortDetailsRep.GetListAsync(x => orderSortIdList.Contains(x.SortId) && x.IsDelete == false);
//获取容器的所有库存信息
List allContainerStockQuans = await _wmsStockQuanRep.GetListAsync(x => x.ContainerCode == currentContainer.ContainerCode);
//获取所有库存视图信息 添加事务记录用
List 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();
//获取线边库区容器 //根据下架单的目标库区转移,原材料库只能选择 线边库区的线边库位。
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();
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();
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 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;
}
///
/// PDA拣货创建事务记录入参方法
///
///
///
///
///
///
///
///
///
private WmsRecordTrans CreateRecordTransInfoForJH(decimal sotQty, WmsOrderSortDetails orderSortDetails, List allPlaeList, List allStockQuanView, WmsBaseBusinessType businessTypeInfo, WmsStockQuan StockModel, string recordTransRemarks)
{
TransferOtherDetail transferOtherDetail = new TransferOtherDetail()
{
RelationNo = orderSortDetails.SortNo,//波次单号
RelationNoLineNumber = orderSortDetails.LineNumber,//波次单行号
Remarks = recordTransRemarks,
};
var toStockQuan = StockModel.Adapt();
//根据库存跟踪码视图可以查询到信息
//获取源库存信息
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;
}
///
/// 分拣验证
///
///
///
///
private async Task ValidateInput(SortConfirmInput input,
WmsBaseContainer currentContainer,
List sortList,
List allContainerStockQuans,
List allOrderMovementList,
List allOrderMovementDetailsList,
List allOrderSortDetailsList,
List 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}");
}
}
}
///
/// 分拣异常标记验证
///
///
///
///
///
///
///
///
///
///
private async Task ValidateInputForSortExceptionFlagConfirm(SortExceptionFlagConfirmInput input,
WmsBaseContainer currentContainer,
List sortList,
List allContainerStockQuans,
List allOrderMovementList,
List allOrderMovementDetailsList,
List allOrderSortDetailsList,
List 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}");
}
}
}
///
/// 公共查询容器分拣信息条件
///
///
///
private ISugarQueryable 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();
return query;
}
#endregion
}