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 System.Linq.Expressions;
using Furion.LinqBuilder;
using System.Linq;
using Admin.NET.Application.CommonHelper;
using DocumentFormat.OpenXml.Office.CustomUI;
namespace Admin.NET.Application;
///
/// 容器分拣信息服务
///
[ApiDescriptionSettings(ApplicationConst.WmsTaskGroupName, Order = 100)]
public class WmsPredetermineService : IDynamicApiController, ITransient
{
///
/// 是否正在执行预配方法
///
private static bool isRuning_Fun_Predetermine = false;
private static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 1);
private readonly SqlSugarRepository _wmsContainerSortRep;
private readonly SqlSugarRepository _v_wms_stock_quanRep;
private readonly SqlSugarRepository _wmsOrderSortDetailsRep;
//private readonly SqlSugarRepository _wmsStockQuanLockRep;
private readonly SqlSugarRepository _wmsOrderSortRep;
private readonly SqlSugarRepository _wmsOrderMovementDetailsRep;
private readonly SqlSugarRepository _v_wmsOrderMovementDetailsRep;
private readonly SqlSugarRepository _wmsOrderMovementRep;
private readonly SqlSugarRepository _wmsTaskRep;
private readonly SqlSugarRepository _wmsRecordPredDispHistoryRep;
private readonly SqlSugarRepository _v_wms_stock_quan_use_groupRep;
public WmsPredetermineService(
SqlSugarRepository v_wmsOrderMovementDetailsRep,
SqlSugarRepository wmsContainerSortRep,
SqlSugarRepository v_wms_stock_quanRep,
//SqlSugarRepository wmsStockQuanLockRep,
SqlSugarRepository wmsOrderSortDetailsRep,
SqlSugarRepository wmsOrderSortRep,
SqlSugarRepository wmsOrderMovementDetailsRep,
SqlSugarRepository wmsOrderMovementRep,
SqlSugarRepository wmsTaskRep,
SqlSugarRepository wmsRecordPredDispHistoryRep,
SqlSugarRepository v_wms_stock_quan_use_groupRep)
{
_wmsContainerSortRep = wmsContainerSortRep;
_v_wms_stock_quanRep = v_wms_stock_quanRep;
//_wmsStockQuanLockRep = wmsStockQuanLockRep;
_wmsOrderSortDetailsRep = wmsOrderSortDetailsRep;
_wmsOrderSortRep = wmsOrderSortRep;
_wmsOrderMovementDetailsRep = wmsOrderMovementDetailsRep;
_wmsOrderMovementRep = wmsOrderMovementRep;
_wmsTaskRep = wmsTaskRep;
_wmsRecordPredDispHistoryRep = wmsRecordPredDispHistoryRep;
_v_wms_stock_quan_use_groupRep = v_wms_stock_quan_use_groupRep;
_v_wmsOrderMovementDetailsRep = v_wmsOrderMovementDetailsRep;
}
///
/// 预配
///
///
///
[HttpPost]
[ApiDescriptionSettings(Name = "Predetermine")]
[Description("WmsPredetermine/Predetermine")]
public async Task Predetermine(List input)
{
try
{
if (isRuning_Fun_Predetermine)
{
throw Oops.Oh("程序正忙,请稍后再试");
}
await semaphoreSlim.WaitAsync();
isRuning_Fun_Predetermine = true;
return await PredetermineFaction(input);
}
catch (Exception ex)
{
throw Oops.Oh(ex.Message);
}
finally
{
semaphoreSlim.Release();
isRuning_Fun_Predetermine = false;
}
}
///
/// 取消预配
///
///
///
[HttpPost]
[ApiDescriptionSettings(Name = "CancelPredetermine")]
[Description("WmsPredetermine/CancelPredetermine")]
public async Task CancelPredetermine(List input)
{
try
{
if (isRuning_Fun_Predetermine)
{
throw Oops.Oh("程序正忙,请稍后再试");
}
await semaphoreSlim.WaitAsync();
isRuning_Fun_Predetermine = true;
return await PredetermineFaction(input, true);
}
catch (Exception ex)
{
throw Oops.Oh(ex.Message);
}
finally
{
semaphoreSlim.Release();
isRuning_Fun_Predetermine = false;
}
}
///
/// 预配/取消预配
///
///
///
///
private async Task PredetermineFaction(List input, bool isCancel = false)
{
/**
* 获取预配物料库存信息
* 获取当前预配锁定库存信息
* 校验可用库存-历史预配锁定库存 是否满足预配
* 新增预配锁定库存
* 修改下架单明细预配数
* 新增事务
* 新增操作日期
*/
List addWmsRecordPredDispHistoryList = new List();//新增的预配历史记录
//var addWmsStockQuanLockList = new List();//新增的锁定库存信息
//var updateWmsStockQuanLockList = new List();//更新的锁定库存信息
var updateWmsOrderMoveDetailsList = new List();//修改的移动单明细
//var updateWmsOrderMoveList = new List();//修改的移动单
List moveNoList = input.Select(s => s.MovementNo).ToList();
var allWmsOrderSortList = await _wmsOrderMovementRep.GetListAsync(u => moveNoList.Contains(u.OrderNo));
if (allWmsOrderSortList?.Count <= 0)
{
throw Oops.Oh("下架单不存在");
}
//获取下架单所有明细
var allOrderSortDetails = await _wmsOrderMovementDetailsRep.GetListAsync(u => moveNoList.Contains(u.MovementNo));
if (allOrderSortDetails?.Count <= 0)
{
throw Oops.Oh("下架单明细不存在");
}
// 查找物料库存
List materialCodeList = input.Select(x => x.MaterialCode).Distinct().ToList();
List allStockQuanGroupList = null;
if (!isCancel)
{
//根据物料编码获取物料汇总库存(同一个物料号分组汇总v_wms_stock_quan_for_use视图查询到细分到跟踪码的库存信息)
allStockQuanGroupList = await _v_wms_stock_quan_use_groupRep.GetListAsync(x => materialCodeList.Contains(x.MaterialCode) && x.UseQty > 0);
if (allStockQuanGroupList?.Count <= 0)
{
throw Oops.Oh("所有物料都没有库存");
}
}
////获取所有物料锁定库存
//var allStockQuanLockList = await _wmsStockQuanLockRep.GetListAsync(x => materialCodeList.Contains(x.MaterialCode));
////物料预配锁定库存
//var allStockQuanLockForPredetermineList = allStockQuanLockList.Where(x => x.LockType == LockTypeEnum.预配 && x.IsDelete == false).ToList();
//TODO 分配预配锁定库存
//获取本次操作的下架单和下架单明细
var currentMovementDetailsKeyList = input.Select(x => x.MovementNo + x.LineNumber).ToList();
var currentMovementDetailsList = await _wmsOrderMovementDetailsRep.GetListAsync(x => currentMovementDetailsKeyList.Contains(x.MovementNo + x.LineNumber));
var v_currentMovementDetailsList = await _v_wmsOrderMovementDetailsRep.GetListAsync(x => currentMovementDetailsKeyList.Contains(x.MovementNo + x.LineNumber));
var queryOrderIds = currentMovementDetailsList.Select(x => x.MovementId).Distinct().ToList();
var currentOrderMovementList = await _wmsOrderMovementRep.GetListAsync(x => queryOrderIds.Contains(x.Id));
foreach (var inputItem in input)
{
WmsOrderMovement movementOrder = currentOrderMovementList.FirstOrDefault(p => p.OrderNo == inputItem.MovementNo);
if (movementOrder == null)
{
throw Oops.Oh("本次分配的下架单不存在");
}
//TODO 校验下架单状态
var movementDetails = currentMovementDetailsList.FirstOrDefault(x => x.MovementNo == inputItem.MovementNo && x.LineNumber == inputItem.LineNumber);
if (movementDetails == null)
{
throw Oops.Oh("本次分配的下架单明细不存在");
}
var v_movementDetails = v_currentMovementDetailsList.FirstOrDefault(x => x.MovementNo == inputItem.MovementNo && x.LineNumber == inputItem.LineNumber);
if (v_movementDetails == null)
{
throw Oops.Oh("本次分配的下架单明细不存在");
}
var addWmsRecordPredDispHistory = new WmsRecordPredDispHistory()
{
PDRecordType = PDRecordTypeEnum.预配,
PDRecordTypeName = PDRecordTypeEnum.预配.ToString(),
Quantity = inputItem.SendQuantity,
MovementNo = movementDetails.MovementNo,
MovementLineNumber = movementDetails.LineNumber,
MaterialCode = movementDetails.MaterialCode,
MaterialName = movementDetails.MaterialName,
Remarks = "预配操作"
};
if (!isCancel)
{
#region 处理预配
decimal historyPredetermineQuantity = movementDetails.PredetermineQuantity;//下架单的历史预配数量
decimal allQuantity = movementDetails.Quantity - historyPredetermineQuantity;//下架单明细剩余可预配数量
decimal occQuantity = inputItem.SendQuantity;//当前实际预配数量
if ((occQuantity) <= 0)
{
throw Oops.Oh("下架单" + movementDetails.MovementNo + "行号" + movementDetails.LineNumber + "物料编号" + movementDetails.MaterialCode + $"(本次预配数{occQuantity})不能小于等于0");
}
if (allQuantity <= 0)
{
throw Oops.Oh("下架单" + movementDetails.MovementNo + "行号" + movementDetails.LineNumber + "物料编号" + movementDetails.MaterialCode + $"已全部预配");
}
if (occQuantity > allQuantity)
{
throw Oops.Oh("下架单" + movementDetails.MovementNo + "行号" + movementDetails.LineNumber + "物料编号" + movementDetails.MaterialCode + $"本次预配数量{occQuantity}大于剩余可预配数{allQuantity}");
}
// 根据物料找出库存列表中数量大于0的库存
var findStockQuanList = allStockQuanGroupList.Where(x => (x.UseQty) > 0 && x.MaterialCode == movementDetails.MaterialCode).ToList();
//寻找库存原则:按照先入先出原则 RecordInsertTime 排升序
//同一个物料尽量从同一个库位取
if (findStockQuanList.Count() <= 0)
{
//缺料
throw Oops.Oh("物料编号" + movementDetails.MaterialCode + $"库存数量不足,预配数量:{occQuantity},库存可用数量:0");
}
var sumQty = findStockQuanList.Sum(x => x.UseQty);
if (sumQty < occQuantity)
{
throw Oops.Oh("物料编号" + movementDetails.MaterialCode + $"库存数量不足,预配数量:{occQuantity},库存可用数量:{sumQty}");
}
//处理后未下发的数量,多个同一个物料多个库存数据的情况,循环处理下发
decimal currentIssueQuantity = occQuantity;
////创建锁定库存
//var addWmsStockQuanLock = LockStroreHelper.CommonCreateWmsStockQuanLockForPredetermine(movementDetails, occQuantity);
movementDetails.PredetermineQuantity += occQuantity;//累计预配数
//addWmsStockQuanLockList.Add(addWmsStockQuanLock);//添加预配锁定库存
updateWmsOrderMoveDetailsList.Add(movementDetails);//更新下架单明细
#endregion
}
else
{
addWmsRecordPredDispHistory.Remarks = "取消预配";
addWmsRecordPredDispHistory.Quantity = -inputItem.PredetermineQuantity;
#region 处理取消预配
decimal historyPredetermineQuantity = movementDetails.PredetermineQuantity;//下架单的历史预配数量
decimal occQuantity = inputItem.PredetermineQuantity;//当前实际取消预配数量
if ((occQuantity) <= 0)
{
throw Oops.Oh("下架单" + movementDetails.MovementNo + "行号" + movementDetails.LineNumber + "物料编号" + movementDetails.MaterialCode + $"(本次取消预配数{occQuantity})不能小于等于0");
}
if ((historyPredetermineQuantity - occQuantity) < 0)
{
throw Oops.Oh("下架单" + movementDetails.MovementNo + "行号" + movementDetails.LineNumber + "物料编号" + movementDetails.MaterialCode + $"(已预配数量{historyPredetermineQuantity}减去本次取消预配数{occQuantity})不能小于0");
}
if (v_movementDetails.DispenseQuantity > (historyPredetermineQuantity - occQuantity))
{
throw Oops.Oh("下架单" + movementDetails.MovementNo + "行号" + movementDetails.LineNumber + "物料编号" + movementDetails.MaterialCode + $"已分配数{v_movementDetails.DispenseQuantity}不能大于(已预配数量{historyPredetermineQuantity}减去本次取消预配数{occQuantity})");
}
//处理后未下发的数量,多个同一个物料多个库存数据的情况,循环处理下发
decimal currentIssueQuantity = occQuantity;
/*
//查询锁定库存
List wmsStockQuanLocks = await _wmsStockQuanLockRep.GetListAsync(x => x.IsDelete == false
&& x.MovementNo == inputItem.MovementNo && x.MovementLineNumber == inputItem.LineNumber
&& x.LockType == LockTypeEnum.预配
&& (x.Quantity) > 0
);
foreach (var stockQuanLock in wmsStockQuanLocks)
{
if (currentIssueQuantity <= 0) break;
if (currentIssueQuantity <= (stockQuanLock.Quantity))
{
stockQuanLock.Quantity = (stockQuanLock.Quantity) - currentIssueQuantity;
if (stockQuanLock.Quantity == 0)
{
stockQuanLock.IsDelete = true;
}
}
else
{//本次循环不够扣
currentIssueQuantity -= (stockQuanLock.Quantity);
stockQuanLock.IsDelete = true;
stockQuanLock.Quantity = 0;
}
updateWmsStockQuanLockList.Add(stockQuanLock);//添加预配锁定库存
}
//*/
movementDetails.PredetermineQuantity -= occQuantity;//累计预配数
updateWmsOrderMoveDetailsList.Add(movementDetails);//更新下架单明细
#endregion
}
addWmsRecordPredDispHistoryList.Add(addWmsRecordPredDispHistory);
}
var _tenant = _wmsOrderMovementDetailsRep.AsTenant();
try
{
#region 事务内执行操作
//await _wmsStockQuanLockRep.InsertRangeAsync(addWmsStockQuanLockList);
/*
foreach (var item in updateWmsStockQuanLockList)
{
if (item.IsDelete)
{
await _wmsStockQuanLockRep.DeleteAsync(item);//物理删除
}
else
{
await _wmsStockQuanLockRep.UpdateAsync(item);
}
}
//*/
await _wmsOrderMovementDetailsRep.UpdateRangeAsync(updateWmsOrderMoveDetailsList);
await _wmsRecordPredDispHistoryRep.InsertRangeAsync(addWmsRecordPredDispHistoryList);
#endregion
await _tenant.CommitTranAsync();
}
catch (Exception ex)
{
await _tenant.RollbackTranAsync();
throw;
}
return 1;
}
#region 私有方法
#endregion
}