From 0b0899370f271793f7156144b4b912438aebdf73 Mon Sep 17 00:00:00 2001
From: heshaofeng <heshaofeng@hnkhzn.com>
Date: 星期一, 24 十一月 2025 08:41:56 +0800
Subject: [PATCH] Merge branch 'master' of http://115.159.85.185:8098/r/ZhongRui/ALDbanyunxiangmu
---
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs | 647 ++++++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 531 insertions(+), 116 deletions(-)
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs"
index 02d76b3..8e030a2 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs"
@@ -10,6 +10,7 @@
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
+using WIDESEA_Common.CommonEnum;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.OrderEnum;
using WIDESEA_Common.StockEnum;
@@ -17,6 +18,7 @@
using WIDESEA_Core;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
+using WIDESEA_Core.Enums;
using WIDESEA_Core.Helper;
using WIDESEA_DTO.Basic;
using WIDESEA_DTO.Inbound;
@@ -86,6 +88,8 @@
_dailySequenceService = dailySequenceService;
}
+
+ #region 鏌ヨ鏂规硶
// 鑾峰彇鏈嫞閫夊垪琛�
public async Task<List<Dt_OutStockLockInfo>> GetUnpickedList(string orderNo, string palletCode)
{
@@ -148,6 +152,8 @@
return summary;
}
+ #endregion
+
#region 鏍稿績涓氬姟娴佺▼
/// <summary>
/// 鎷i��
@@ -161,7 +167,7 @@
try
{
_unitOfWorkManage.BeginTran();
-
+
var validationResult = await ValidatePickingRequest(orderNo, palletCode, barcode);
if (!validationResult.IsValid)
return WebResponseContent.Instance.Error(validationResult.ErrorMessage);
@@ -252,11 +258,11 @@
{
_unitOfWorkManage.BeginTran();
- // 1. 鍩虹楠岃瘉
+
if (string.IsNullOrEmpty(orderNo) || string.IsNullOrEmpty(palletCode))
return WebResponseContent.Instance.Error("璁㈠崟鍙峰拰鎵樼洏鐮佷笉鑳戒负绌�");
- // 2. 鑾峰彇搴撳瓨鍜屼换鍔′俊鎭�
+ // 鑾峰彇搴撳瓨鍜屼换鍔′俊鎭�
var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>().FirstAsync(x => x.PalletCode == palletCode);
if (stockInfo == null)
@@ -266,23 +272,34 @@
if (task == null)
return WebResponseContent.Instance.Error("鏈壘鍒板搴旂殑浠诲姟淇℃伅");
- // 3. 鍒嗘瀽闇�瑕佸洖搴撶殑璐х墿
- var returnAnalysis = await AnalyzeReturnItems(orderNo, palletCode, stockInfo.Id);
- if (!returnAnalysis.HasItemsToReturn)
- return await HandleNoReturnItems(orderNo, palletCode,task);
+ //鍒嗘瀽闇�瑕佸洖搴撶殑璐х墿
+ //var returnAnalysis = await AnalyzeReturnItems(orderNo, palletCode, stockInfo.Id);
+ //if (!returnAnalysis.HasItemsToReturn)
+ // return await HandleNoReturnItems(orderNo, palletCode, task);
- // 4. 鎵ц鍥炲簱鎿嶄綔
- await ExecuteReturnOperations(orderNo, palletCode, stockInfo, task, returnAnalysis);
+ var statusAnalysis = await AnalyzePalletStatus(orderNo, palletCode, stockInfo.Id);
+ if (!statusAnalysis.HasItemsToReturn)
+ return await HandleNoReturnItems(orderNo, palletCode, task, stockInfo.Id);
- // 5. 鍒涘缓鍥炲簱浠诲姟
- await CreateReturnTaskAndHandleESS(orderNo, palletCode, task, returnAnalysis);
+ // 4. 妫�鏌ユ槸鍚︽湁杩涜涓殑浠诲姟
+ if (statusAnalysis.HasActiveTasks)
+ {
+ return WebResponseContent.Instance.Error($"鎵樼洏 {palletCode} 鏈夎繘琛屼腑鐨勪换鍔★紝涓嶈兘鎵ц鍥炲簱鎿嶄綔");
+ }
+
+ //鎵ц鍥炲簱鎿嶄綔
+ await ExecuteReturnOperations(orderNo, palletCode, stockInfo, task, statusAnalysis);
_unitOfWorkManage.CommitTran();
- // 6. 鏇存柊璁㈠崟鐘舵�侊紙涓嶈Е鍙慚ES鍥炰紶锛�
+
+ // 鍒涘缓鍥炲簱浠诲姟
+ await CreateReturnTaskAndHandleESS(orderNo, palletCode, task, TaskTypeEnum.InPick);
+
+ // 鏇存柊璁㈠崟鐘舵�侊紙涓嶈Е鍙慚ES鍥炰紶锛�
await UpdateOrderStatusForReturn(orderNo);
- return WebResponseContent.Instance.OK($"鍥炲簱鎿嶄綔鎴愬姛锛屽叡鍥炲簱鏁伴噺锛歿returnAnalysis.TotalReturnQty}");
+ return WebResponseContent.Instance.OK($"鍥炲簱鎿嶄綔鎴愬姛锛屽叡鍥炲簱鏁伴噺锛歿statusAnalysis.TotalReturnQty}");
}
catch (Exception ex)
{
@@ -292,6 +309,71 @@
}
}
+ /// <summary>
+ /// 绌烘墭鐩樺彇璧版帴鍙o紙甯﹁鍗曞彿锛�
+ /// 楠岃瘉鎵樼洏鏄惁鐪熺殑涓虹┖锛屾竻鐞嗘暟鎹紝鏇存柊璁㈠崟鐘舵�侊紝鍒涘缓鍙栨墭鐩樹换鍔�
+ /// </summary>
+ public async Task<WebResponseContent> RemoveEmptyPallet(string orderNo, string palletCode)
+ {
+ try
+ {
+ _unitOfWorkManage.BeginTran();
+
+ if (string.IsNullOrEmpty(orderNo) || string.IsNullOrEmpty(palletCode))
+ return WebResponseContent.Instance.Error("璁㈠崟鍙峰拰鎵樼洏鐮佷笉鑳戒负绌�");
+
+ // 妫�鏌ヨ鍗曟槸鍚﹀瓨鍦�
+ var order = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>()
+ .Where(x => x.OrderNo == orderNo)
+ .FirstAsync();
+
+ if (order == null)
+ return WebResponseContent.Instance.Error($"鏈壘鍒拌鍗� {orderNo}");
+
+ //妫�鏌ユ墭鐩樻槸鍚﹀瓨鍦ㄤ笖灞炰簬璇ヨ鍗�
+ var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>()
+ .Where(x => x.PalletCode == palletCode)
+ .FirstAsync();
+
+ if (stockInfo == null)
+ return WebResponseContent.Instance.Error($"鏈壘鍒版墭鐩� {palletCode} 瀵瑰簲鐨勫簱瀛樹俊鎭�");
+
+ var statusAnalysis = await AnalyzePalletStatus(orderNo, palletCode, stockInfo.Id);
+
+ if (!statusAnalysis.CanRemove)
+ {
+ if (!statusAnalysis.IsEmptyPallet)
+ {
+ return WebResponseContent.Instance.Error($"鎵樼洏 {palletCode} 涓婅繕鏈夎揣鐗╋紝涓嶈兘鍙栬蛋");
+ }
+ if (statusAnalysis.HasActiveTasks)
+ {
+ return WebResponseContent.Instance.Error($"鎵樼洏 {palletCode} 杩樻湁杩涜涓殑浠诲姟锛屼笉鑳藉彇璧�");
+ }
+ }
+ // 娓呯悊闆跺簱瀛樻暟鎹�
+ await CleanupZeroStockData(stockInfo.Id);
+
+ // 鍒犻櫎鎴栧彇娑堢浉鍏充换鍔�
+ await HandleTaskCleanup(orderNo, palletCode);
+
+ // 鏇存柊璁㈠崟鐩稿叧鏁版嵁
+ await UpdateOrderData(orderNo, palletCode);
+
+
+ _unitOfWorkManage.CommitTran();
+
+ _logger.LogInformation($"绌烘墭鐩樺彇璧版搷浣滄垚鍔� - 璁㈠崟: {orderNo}, 鎵樼洏: {palletCode}, 鎿嶄綔浜�: {App.User.UserName}");
+
+ return WebResponseContent.Instance.OK("绌烘墭鐩樺彇璧版搷浣滄垚鍔�");
+ }
+ catch (Exception ex)
+ {
+ _unitOfWorkManage.RollbackTran();
+ _logger.LogError($"RemoveEmptyPallet澶辫触 - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}");
+ return WebResponseContent.Instance.Error($"绌烘墭鐩樺彇璧板け璐�: {ex.Message}");
+ }
+ }
#endregion
#region 鍒嗘嫞纭绉佹湁鏂规硶
@@ -367,7 +449,7 @@
{
// 鏌ユ壘鍚屼竴璁㈠崟涓嬬殑璁板綍
lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
- .Where(it => it.OrderNo == orderNo && it.CurrentBarcode == barcode && it.Status == (int)OutLockStockStatusEnum.鍑哄簱涓� && it.AssignQuantity > it.PickedQty).FirstAsync();
+ .Where(it => it.OrderNo == orderNo && it.CurrentBarcode == barcode && it.Status == (int)OutLockStockStatusEnum.鍑哄簱涓� && it.AssignQuantity > it.PickedQty).FirstAsync();
if (lockInfo == null)
{
@@ -436,7 +518,7 @@
adjustedReason = adjustedReason != null
? $"{adjustedReason}锛岄槻瓒呮嫞闄愬埗锛氭渶缁堣皟鏁翠负{actualQty}"
: $"闃茶秴鎷i檺鍒讹細浠巤plannedQty}璋冩暣涓簕actualQty}";
- }
+ }
if (adjustedReason != null)
{
@@ -501,30 +583,34 @@
{
decimal remainingStockQty = stockQuantity - actualQty;
- // 1. 鏇存柊鍘熸潯鐮佸簱瀛�
+ // 鏇存柊鍘熸潯鐮佸簱瀛�
stockDetail.StockQuantity = remainingStockQty;
stockDetail.OutboundQuantity = remainingStockQty;
await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
- // 2. 鐢熸垚鏂版潯鐮�
+ //鐢熸垚鏂版潯鐮�
string newBarcode = await GenerateNewBarcode();
- // 3. 鍒涘缓鏂伴攣瀹氫俊鎭�
+ //鍒涘缓鏂伴攣瀹氫俊鎭�
var newLockInfo = await CreateSplitLockInfo(lockInfo, actualQty, newBarcode);
- // 4. 璁板綍鎷嗗寘鍘嗗彶
+ // 璁板綍鎷嗗寘鍘嗗彶
await RecordSplitHistory(lockInfo, stockDetail, actualQty, remainingStockQty, newBarcode);
- // 5. 鏇存柊鍘熼攣瀹氫俊鎭�
+ // 鏇存柊鍘熼攣瀹氫俊鎭�
lockInfo.AssignQuantity = remainingStockQty;
lockInfo.PickedQty = 0;
lockInfo.Operator = App.User.UserName;
await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
- // 6. 璁剧疆缁撴灉
+ // 璁剧疆缁撴灉
result.FinalLockInfo = newLockInfo;
result.FinalBarcode = newBarcode;
result.SplitResults.AddRange(CreateSplitResults(lockInfo, actualQty, remainingStockQty, newBarcode, stockDetail.Barcode));
+
+ await UpdateOrderRelatedData(lockInfo.OrderDetailId, actualQty, lockInfo.OrderNo);
+
+ _logger.LogInformation($"鎷嗗寘鍒嗘嫞鏇存柊璁㈠崟鏄庣粏 - OrderDetailId: {lockInfo.OrderDetailId}, 鍒嗘嫞鏁伴噺: {actualQty}");
}
private async Task HandleFullPicking(Dt_OutStockLockInfo lockInfo, Dt_StockInfoDetail stockDetail,
@@ -578,10 +664,10 @@
if (newOverOutQuantity > currentOrderDetail.NeedOutQuantity)
{
-
+
_logger.LogError($"闃茶秴鎷f鏌ュけ璐� - OrderDetailId: {orderDetailId}, 宸插嚭搴�: {newOverOutQuantity}, 闇�姹�: {currentOrderDetail.NeedOutQuantity}, 鏈鍒嗘嫞: {pickedQty}");
-
+
decimal adjustedQty = currentOrderDetail.NeedOutQuantity - currentOrderDetail.OverOutQuantity;
if (adjustedQty > 0)
@@ -673,7 +759,7 @@
if (lockInfo == null)
return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error("鏈壘鍒板搴旂殑鍑哄簱閿佸畾淇℃伅");
-
+
if (lockInfo.PickedQty < pickingRecord.PickQuantity)
{
return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error(
@@ -715,8 +801,8 @@
{
return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error($"鏉$爜{barcode}宸茬粡鍥炲簱锛屼笉鑳藉彇娑堝垎鎷�");
}
- }
-
+ }
+
return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Success((pickingRecord, lockInfo, orderDetail));
}
/// <summary>
@@ -846,6 +932,8 @@
await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>()
.Where(x => x.Id == lockInfo.Id)
.ExecuteCommandAsync();
+
+ await UpdateOrderDetailOnCancel(pickingRecord.OrderDetailId, cancelQty);
}
private async Task HandleNormalBarcodeCancel(Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord, decimal cancelQty)
@@ -942,59 +1030,7 @@
return task;
}
-
- private async Task<ReturnAnalysisResult> AnalyzeReturnItems(string orderNo, string palletCode, int stockId)
- {
- var result = new ReturnAnalysisResult();
-
- // 鎯呭喌1锛氳幏鍙栨湭鍒嗘嫞鐨勫嚭搴撻攣瀹氳褰�
- var remainingLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
- .Where(it => it.OrderNo == orderNo &&
- it.PalletCode == palletCode &&
- it.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
- .ToListAsync();
-
- if (remainingLocks.Any())
- {
- result.HasRemainingLocks = true;
- result.RemainingLocks = remainingLocks;
- result.RemainingLocksReturnQty = remainingLocks.Sum(x => x.AssignQuantity - x.PickedQty);
- }
-
- // 鎯呭喌2锛氭鏌ユ墭鐩樹笂鏄惁鏈夊叾浠栧簱瀛樿揣鐗�
- var palletStockGoods = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
- .Where(it => it.StockId == stockId &&
- (it.Status == StockStatusEmun.鍏ュ簱纭.ObjToInt() ||
- it.Status == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt() ||
- it.Status == StockStatusEmun.鍑哄簱閿佸畾.ObjToInt()))
- .Where(it => it.StockQuantity > 0)
- .ToListAsync();
-
- if (palletStockGoods.Any())
- {
- result.HasPalletStockGoods = true;
- result.PalletStockGoods = palletStockGoods;
- result.PalletStockReturnQty = palletStockGoods.Sum(x => x.StockQuantity);
- }
-
- // 鎯呭喌3锛氭鏌ユ媶鍖呰褰�
- var splitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
- .Where(it => it.OrderNo == orderNo && it.PalletCode == palletCode && !it.IsReverted && it.Status != (int)SplitPackageStatusEnum.宸插洖搴�)
- .ToListAsync();
-
- if (splitRecords.Any())
- {
- result.HasSplitRecords = true;
- result.SplitRecords = splitRecords;
- result.SplitReturnQty = await CalculateSplitReturnQuantity(splitRecords, stockId);
- }
-
- result.TotalReturnQty = result.RemainingLocksReturnQty + result.PalletStockReturnQty + result.SplitReturnQty;
- result.HasItemsToReturn = result.TotalReturnQty > 0;
-
- return result;
- }
-
+
private async Task<decimal> CalculateSplitReturnQuantity(List<Dt_SplitPackageRecord> splitRecords, int stockId)
{
decimal totalQty = 0;
@@ -1034,40 +1070,74 @@
return totalQty;
}
- private async Task<WebResponseContent> HandleNoReturnItems(string orderNo, string palletCode,Dt_Task originalTask)
+ private async Task<WebResponseContent> HandleNoReturnItems(string orderNo, string palletCode, Dt_Task originalTask, int stockInfoId)
{
// 妫�鏌ユ槸鍚︽墍鏈夎揣鐗╅兘宸叉嫞閫夊畬鎴�
- var allPicked = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
- .Where(it => it.OrderNo == orderNo && it.PalletCode == palletCode)
- .AnyAsync(it => it.Status == (int)OutLockStockStatusEnum.鎷i�夊畬鎴�);
+ //var allPicked = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ // .Where(it => it.OrderNo == orderNo && it.PalletCode == palletCode)
+ // .AnyAsync(it => it.Status == (int)OutLockStockStatusEnum.鎷i�夊畬鎴�);
- if (allPicked)
+ //if (allPicked)
+ //{
+ // // 鍒犻櫎鍘熷鍑哄簱浠诲姟 缁勭┖鐩� 绌虹洏鍥炲簱
+ // //await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync();
+ // return WebResponseContent.Instance.OK("鎵�鏈夎揣鐗╁凡鎷i�夊畬鎴愶紝鎵樼洏涓虹┖");
+ //}
+ //else
+ //{
+ // // 鍒犻櫎鍘熷鍑哄簱浠诲姟
+ // //await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync();
+ // return WebResponseContent.Instance.Error("娌℃湁闇�瑕佸洖搴撶殑鍓╀綑璐х墿");
+ //}
+ try
{
- // 鍒犻櫎鍘熷鍑哄簱浠诲姟
- await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync();
- return WebResponseContent.Instance.OK("鎵�鏈夎揣鐗╁凡鎷i�夊畬鎴愶紝鎵樼洏涓虹┖");
+ var locationtype = 0;
+ var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>()
+ .Where(x => x.PalletCode == palletCode)
+ .FirstAsync();
+
+ if (stockInfo == null)
+ {
+ var firstLocation = await _locationInfoService.Db.Queryable<Dt_LocationInfo>().FirstAsync(x => x.LocationCode == originalTask.SourceAddress);
+ locationtype = firstLocation?.LocationType ?? 1;
+ }
+ else
+ {
+ locationtype = stockInfo.LocationType;
+ }
+
+ var targetAddress = originalTask.TargetAddress;
+
+ await CleanupZeroStockData(stockInfoId);
+
+ var emptystockInfo = new Dt_StockInfo() { PalletType = PalletTypeEnum.Empty.ObjToInt(), StockStatus = StockStatusEmun.缁勭洏鏆傚瓨.ObjToInt(), PalletCode = palletCode, LocationType = locationtype };
+ emptystockInfo.Details = new List<Dt_StockInfoDetail>();
+ _stockInfoService.AddMaterielGroup(emptystockInfo);
+ //绌烘墭鐩樺浣曞鐞� 杩樻湁涓�涓嚭搴撲换鍔¤澶勭悊銆�
+ originalTask.PalletType = PalletTypeEnum.Empty.ObjToInt();
+
+ await CreateReturnTaskAndHandleESS(orderNo, palletCode, originalTask, TaskTypeEnum.InEmpty);
+
}
- else
+ catch (Exception ex)
{
- // 鍒犻櫎鍘熷鍑哄簱浠诲姟
- await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync();
- return WebResponseContent.Instance.Error("娌℃湁闇�瑕佸洖搴撶殑鍓╀綑璐х墿");
+ _logger.LogError($" HandleNoReturnItems 澶辫触: {ex.Message}");
+ return WebResponseContent.Instance.Error($" 鍥炲簱绌烘墭鐩樺け璐ワ紒");
}
- //绌烘墭鐩樺浣曞鐞� 杩樻湁涓�涓嚭搴撲换鍔¤澶勭悊銆�
-
+ return WebResponseContent.Instance.OK("绌烘墭鐩樺洖搴撲换鍔″垱寤烘垚鍔�");
+
}
private async Task ExecuteReturnOperations(string orderNo, string palletCode, Dt_StockInfo stockInfo,
- Dt_Task task, ReturnAnalysisResult analysis)
+ Dt_Task task, PalletStatusAnalysis analysis)
{
// 鎯呭喌1锛氬鐞嗘湭鍒嗘嫞鐨勫嚭搴撻攣瀹氳褰�
if (analysis.HasRemainingLocks)
{
await HandleRemainingLocksReturn(analysis.RemainingLocks, stockInfo.Id);
- // 鍏抽敭锛氭洿鏂拌鍗曟槑缁嗙殑宸叉嫞閫夋暟閲�
- await UpdateOrderDetailsOnReturn(analysis.RemainingLocks);
- }
+ // await UpdateOrderDetailsOnReturn(analysis.RemainingLocks);
+ }
// 澶勭悊鎵樼洏涓婂叾浠栧簱瀛樿揣鐗�
if (analysis.HasPalletStockGoods)
@@ -1177,9 +1247,9 @@
foreach (var stockGood in palletStockGoods)
{
_logger.LogInformation($"寰呭洖搴撹揣鐗� - 鏉$爜: {stockGood.Barcode}, 鏁伴噺: {stockGood.StockQuantity}, 褰撳墠鐘舵��: {stockGood.Status}");
-
- // 鎭㈠搴撳瓨鐘舵��
- stockGood.OutboundQuantity = 0;
+
+ // 鎭㈠搴撳瓨鐘舵��
+ stockGood.OutboundQuantity = 0;
stockGood.Status = StockStatusEmun.鍏ュ簱纭.ObjToInt();
await _stockInfoDetailService.Db.Updateable(stockGood).ExecuteCommandAsync();
@@ -1213,7 +1283,7 @@
/// <param name="originalTask"></param>
/// <param name="analysis"></param>
/// <returns></returns>
- private async Task CreateReturnTaskAndHandleESS(string orderNo, string palletCode, Dt_Task originalTask, ReturnAnalysisResult analysis)
+ private async Task CreateReturnTaskAndHandleESS(string orderNo, string palletCode, Dt_Task originalTask, TaskTypeEnum taskTypeEnum)
{
var firstLocation = await _locationInfoService.Db.Queryable<Dt_LocationInfo>()
.FirstAsync(x => x.LocationCode == originalTask.SourceAddress);
@@ -1232,17 +1302,20 @@
SourceAddress = stations[originalTask.TargetAddress],
TargetAddress = newLocation.LocationCode,
TaskStatus = TaskStatusEnum.New.ObjToInt(),
- TaskType = TaskTypeEnum.InPick.ObjToInt(),
+ TaskType = taskTypeEnum.ObjToInt(),
PalletType = originalTask.PalletType,
WarehouseId = originalTask.WarehouseId
};
// 淇濆瓨鍥炲簱浠诲姟
await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync();
- var targetAddress = originalTask.TargetAddress;
-
+ var targetAddress = originalTask.TargetAddress;
+
// 鍒犻櫎鍘熷鍑哄簱浠诲姟
- await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync();
+ _taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.鑷姩瀹屾垚);
+ // await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync();
+
+
// 缁� ESS 鍙戦�佹祦鍔ㄤ俊鍙峰拰鍒涘缓浠诲姟
await SendESSCommands(palletCode, targetAddress, returnTask);
@@ -1274,10 +1347,7 @@
taskType = "putaway",
taskGroupCode = "",
groupPriority = 0,
- tasks = new List<TasksType>
- {
- new()
- {
+ tasks = new List<TasksType>{ new() {
taskCode = returnTask.TaskNum.ToString(),
taskPriority = 0,
taskDescribe = new TaskDescribeType
@@ -1290,8 +1360,7 @@
deadline = 0,
storageTag = ""
}
- }
- }
+ } }
};
var resultTask = await _eSSApiService.CreateTaskAsync(essTask);
@@ -1356,6 +1425,8 @@
}
}
+
+
private async Task UpdateOrderStatusForReturn(string orderNo)
{
try
@@ -1419,6 +1490,7 @@
operationType = 1,
Operator = App.User.UserName,
orderNo = outboundOrder.UpperOrderNo,
+ documentsNO = outboundOrder.OrderNo,
status = outboundOrder.OrderStatus,
details = new List<FeedbackOutboundDetailsModel>()
};
@@ -1473,7 +1545,324 @@
#endregion
+ #region 绌烘墭鐩�
+
+ /// <summary>
+ /// 娓呯悊闆跺簱瀛樻暟鎹�
+ /// </summary>
+ private async Task CleanupZeroStockData(int stockId)
+ {
+ try
+ {
+ // 1. 鍒犻櫎搴撳瓨鏁伴噺涓�0鐨勬槑缁嗚褰�
+ var deleteDetailCount = await _stockInfoDetailService.Db.Deleteable<Dt_StockInfoDetail>()
+ .Where(x => x.StockId == stockId && x.StockQuantity == 0 && (x.Status == StockStatusEmun.鍑哄簱瀹屾垚.ObjToInt() || x.Status ==
+ StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt()))
+ .ExecuteCommandAsync();
+
+ await _stockInfoService.Db.Deleteable<Dt_StockInfo>()
+ .Where(x => x.Id == stockId).ExecuteCommandAsync();
+
+ _logger.LogInformation($"娓呯悊闆跺簱瀛樻槑缁嗚褰� - StockId: {stockId}, 鍒犻櫎璁板綍鏁�: {deleteDetailCount}");
+
+
+
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning($"娓呯悊闆跺簱瀛樻暟鎹け璐� - StockId: {stockId}, Error: {ex.Message}");
+ // 娉ㄦ剰锛氭竻鐞嗗け璐ヤ笉搴旇褰卞搷涓绘祦绋�
+ }
+ }
+ /// <summary>
+ /// 澶勭悊浠诲姟娓呯悊锛堟寜璁㈠崟鍜屾墭鐩橈級
+ /// </summary>
+ private async Task HandleTaskCleanup(string orderNo, string palletCode)
+ {
+ try
+ {
+ // 1. 鏌ユ壘鎵�鏈変笌璇ヨ鍗曞拰鎵樼洏鐩稿叧鐨勪换鍔�
+ var tasks = await _taskRepository.Db.Queryable<Dt_Task>().Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode).ToListAsync();
+
+ if (tasks.Any())
+ {
+ foreach (var task in tasks)
+ {
+ task.TaskStatus = (int)TaskStatusEnum.Finish;
+ }
+ // await _taskRepository.Db.Updateable(tasks).ExecuteCommandAsync();
+
+ _taskRepository.DeleteAndMoveIntoHty(tasks, OperateTypeEnum.鑷姩瀹屾垚);
+ _logger.LogInformation($"瀹屾垚{tasks.Count}涓墭鐩樹换鍔� - 璁㈠崟: {orderNo}, 鎵樼洏: {palletCode}");
+ }
+
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning($"澶勭悊浠诲姟娓呯悊澶辫触 - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}");
+ throw new Exception($"浠诲姟娓呯悊澶辫触: {ex.Message}");
+ }
+ }
+ /// <summary>
+ /// 鏇存柊璁㈠崟鐩稿叧鏁版嵁
+ /// </summary>
+ private async Task UpdateOrderData(string orderNo, string palletCode)
+ {
+ try
+ {
+ // 妫�鏌ヨ鍗曟槸鍚﹁繕鏈夊叾浠栨墭鐩樺湪澶勭悊涓�
+ var otherActivePallets = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(x => x.OrderNo == orderNo &&
+ x.PalletCode != palletCode &&
+ (x.Status == (int)OutLockStockStatusEnum.鍑哄簱涓� || x.Status == (int)OutLockStockStatusEnum.鍥炲簱涓�))
+ .AnyAsync();
+
+ var otherActiveTasks = await _taskRepository.Db.Queryable<Dt_Task>()
+ .Where(x => x.OrderNo == orderNo &&
+ x.PalletCode != palletCode
+ // && x.TaskStatus.In((int)TaskStatusEnum.寰呮墽琛�, (int)TaskStatusEnum.鎵ц涓�)
+ )
+ .AnyAsync();
+
+ // 濡傛灉娌℃湁鍏朵粬鎵樼洏鍦ㄥ鐞嗭紝妫�鏌ヨ鍗曟槸鍚﹀簲璇ュ畬鎴�
+ if (!otherActivePallets && !otherActiveTasks)
+ {
+ await CheckAndUpdateOrderCompletion(orderNo);
+ }
+ else
+ {
+ _logger.LogInformation($"璁㈠崟 {orderNo} 杩樻湁鍏朵粬鎵樼洏鍦ㄥ鐞嗭紝涓嶆洿鏂拌鍗曠姸鎬�");
+ }
+
+ // 3. 鏇存柊鎷i�夎褰曠姸鎬侊紙鍙�夛級
+ await UpdatePickingRecordsStatus(orderNo, palletCode);
+
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning($"鏇存柊璁㈠崟鏁版嵁澶辫触 - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}");
+ throw new Exception($"鏇存柊璁㈠崟鏁版嵁澶辫触: {ex.Message}");
+ }
+ }
+
+ /// <summary>
+ /// 妫�鏌ュ苟鏇存柊璁㈠崟瀹屾垚鐘舵��
+ /// </summary>
+ private async Task CheckAndUpdateOrderCompletion(string orderNo)
+ {
+ var orderDetails = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+ .LeftJoin<Dt_OutboundOrder>((o, item) => o.OrderId == item.Id)
+ .Where((o, item) => item.OrderNo == orderNo)
+ .Select((o, item) => o)
+ .ToListAsync();
+
+ bool allCompleted = true;
+ foreach (var detail in orderDetails)
+ {
+ if (detail.OverOutQuantity < detail.NeedOutQuantity)
+ {
+ allCompleted = false;
+ break;
+ }
+ }
+
+ var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>()
+ .FirstAsync(x => x.OrderNo == orderNo);
+
+ if (outboundOrder != null && allCompleted && outboundOrder.OrderStatus != (int)OutOrderStatusEnum.鍑哄簱瀹屾垚)
+ {
+ outboundOrder.OrderStatus = (int)OutOrderStatusEnum.鍑哄簱瀹屾垚;
+ await _outboundOrderService.Db.Updateable(outboundOrder).ExecuteCommandAsync();
+
+ _logger.LogInformation($"璁㈠崟 {orderNo} 宸叉爣璁颁负鍑哄簱瀹屾垚");
+
+ // 鍚慚ES鍙嶉璁㈠崟瀹屾垚锛堝鏋滈渶瑕侊級
+ await HandleOrderCompletion(outboundOrder, orderNo);
+ }
+ }
+
+ /// <summary>
+ /// 鏇存柊鎷i�夎褰曠姸鎬�
+ /// </summary>
+ private async Task UpdatePickingRecordsStatus(string orderNo, string palletCode)
+ {
+ try
+ {
+ // 鍙互灏嗙浉鍏崇殑鎷i�夎褰曟爣璁颁负宸插畬鎴�
+ var pickingRecords = await Db.Queryable<Dt_PickingRecord>()
+ .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode)
+ .ToListAsync();
+
+ // 杩欓噷鍙互鏍规嵁闇�瑕佹洿鏂版嫞閫夎褰曠殑鐘舵�佸瓧娈�
+ // 渚嬪锛歱ickingRecord.Status = (int)PickingStatusEnum.宸插畬鎴�;
+
+ _logger.LogInformation($"鎵惧埌{pickingRecords.Count}鏉℃嫞閫夎褰� - 璁㈠崟: {orderNo}, 鎵樼洏: {palletCode}");
+
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning($"鏇存柊鎷i�夎褰曠姸鎬佸け璐�: {ex.Message}");
+ }
+ }
+ #endregion
+
+
+
#region 杈呭姪鏂规硶
+ /// <summary>
+ /// 缁熶竴鍒嗘瀽鎵樼洏鐘舵�� - 杩斿洖鎵樼洏鐨勫畬鏁寸姸鎬佷俊鎭�
+ /// </summary>
+ private async Task<PalletStatusAnalysis> AnalyzePalletStatus(string orderNo, string palletCode, int stockId)
+ {
+ var result = new PalletStatusAnalysis
+ {
+ OrderNo = orderNo,
+ PalletCode = palletCode,
+ StockId = stockId
+ };
+
+ // 1. 鍒嗘瀽鏈垎鎷g殑鍑哄簱閿佸畾璁板綍
+ var remainingLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(it => it.OrderNo == orderNo &&
+ it.PalletCode == palletCode &&
+ it.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
+ .ToListAsync();
+
+ if (remainingLocks.Any())
+ {
+ result.HasRemainingLocks = true;
+ result.RemainingLocks = remainingLocks;
+ result.RemainingLocksReturnQty = remainingLocks.Sum(x => x.AssignQuantity - x.PickedQty);
+ }
+
+ // 2. 鍒嗘瀽鎵樼洏涓婄殑搴撳瓨璐х墿
+ var palletStockGoods = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ .Where(it => it.StockId == stockId &&
+ (it.Status == StockStatusEmun.鍏ュ簱纭.ObjToInt() ||
+ it.Status == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt() ||
+ it.Status == StockStatusEmun.鍑哄簱閿佸畾.ObjToInt()))
+ .Where(it => it.StockQuantity > 0)
+ .ToListAsync();
+
+ if (palletStockGoods.Any())
+ {
+ result.HasPalletStockGoods = true;
+ result.PalletStockGoods = palletStockGoods;
+ result.PalletStockReturnQty = palletStockGoods.Sum(x => x.StockQuantity);
+ }
+
+ // 3. 鍒嗘瀽鎷嗗寘璁板綍
+ var splitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
+ .Where(it => it.OrderNo == orderNo &&
+ it.PalletCode == palletCode &&
+ !it.IsReverted &&
+ it.Status != (int)SplitPackageStatusEnum.宸插洖搴�)
+ .ToListAsync();
+
+ if (splitRecords.Any())
+ {
+ result.HasSplitRecords = true;
+ result.SplitRecords = splitRecords;
+ result.SplitReturnQty = await CalculateSplitReturnQuantity(splitRecords, stockId);
+ }
+
+ // 4. 璁$畻鎬诲洖搴撴暟閲忓拰绌烘墭鐩樼姸鎬�
+ result.TotalReturnQty = result.RemainingLocksReturnQty + result.PalletStockReturnQty + result.SplitReturnQty;
+ result.HasItemsToReturn = result.TotalReturnQty > 0;
+ result.IsEmptyPallet = !result.HasItemsToReturn;
+
+ // 5. 妫�鏌ユ槸鍚︽湁杩涜涓殑浠诲姟
+ result.HasActiveTasks = await _taskRepository.Db.Queryable<Dt_Task>()
+ .Where(x => x.OrderNo == orderNo && x.TaskType == TaskTypeEnum.InPick.ObjToInt() &&
+ x.PalletCode == palletCode &&
+ x.TaskStatus == (int)TaskStatusEnum.New)
+ .AnyAsync();
+
+ return result;
+ }
+
+ /// <summary>
+ /// 妫�鏌ユ墭鐩樻槸鍚︿负绌�
+ /// </summary>
+ private async Task<bool> IsPalletEmpty(string orderNo, string palletCode)
+ {
+ try
+ {
+ // 鑾峰彇搴撳瓨淇℃伅
+ var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>()
+ .Where(x => x.PalletCode == palletCode)
+ .FirstAsync();
+
+ if (stockInfo == null)
+ return false;
+
+ // 浣跨敤缁熶竴鐨勭姸鎬佸垎鏋�
+ var statusAnalysis = await AnalyzePalletStatus(orderNo, palletCode, stockInfo.Id);
+ return statusAnalysis.IsEmptyPallet;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning($"妫�鏌ユ墭鐩樻槸鍚︿负绌哄け璐� - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}");
+ return false;
+ }
+ }
+ /// <summary>
+ /// 妫�鏌ュ苟澶勭悊绌烘墭鐩�
+ /// </summary>
+ private async Task<bool> CheckAndHandleEmptyPallet(string orderNo, string palletCode)
+ {
+ try
+ {
+ // 1. 鑾峰彇搴撳瓨淇℃伅
+ var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>()
+ .Where(x => x.PalletCode == palletCode)
+ .FirstAsync();
+
+ if (stockInfo == null)
+ {
+ _logger.LogWarning($"鏈壘鍒版墭鐩� {palletCode} 鐨勫簱瀛樹俊鎭�");
+ return false;
+ }
+
+ // 2. 浣跨敤缁熶竴鐨勭姸鎬佸垎鏋�
+ var statusAnalysis = await AnalyzePalletStatus(orderNo, palletCode, stockInfo.Id);
+
+ // 3. 妫�鏌ユ槸鍚︿负绌烘墭鐩樹笖娌℃湁杩涜涓殑浠诲姟
+ if (!statusAnalysis.IsEmptyPallet || statusAnalysis.HasActiveTasks)
+ {
+ return false;
+ }
+
+ _logger.LogInformation($"妫�娴嬪埌绌烘墭鐩橈紝寮�濮嬭嚜鍔ㄥ鐞� - 璁㈠崟: {orderNo}, 鎵樼洏: {palletCode}");
+
+ //// 娓呯悊闆跺簱瀛樻暟鎹�
+ //await CleanupZeroStockData(stockInfo.Id);
+
+ //// 鏇存柊搴撳瓨涓昏〃鐘舵�佷负绌烘墭鐩�
+ //await UpdateStockInfoAsEmpty(stockInfo);
+
+ //// 澶勭悊鍑哄簱閿佸畾璁板綍
+ //await HandleOutStockLockRecords(orderNo, palletCode);
+
+ //// 澶勭悊浠诲姟鐘舵��
+ //await HandleTaskStatusForEmptyPallet(orderNo, palletCode);
+
+ //// 鏇存柊璁㈠崟鏁版嵁
+ //await UpdateOrderDataForEmptyPallet(orderNo, palletCode);
+
+ ////璁板綍鎿嶄綔鍘嗗彶
+ //await RecordAutoEmptyPalletOperation(orderNo, palletCode);
+
+ _logger.LogInformation($"绌烘墭鐩樿嚜鍔ㄥ鐞嗗畬鎴� - 璁㈠崟: {orderNo}, 鎵樼洏: {palletCode}");
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError($"鑷姩澶勭悊绌烘墭鐩樺け璐� - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}");
+ return false;
+ }
+ }
private async Task<string> GenerateNewBarcode()
{
@@ -1506,10 +1895,10 @@
OriginalLockQuantity = quantity,
IsSplitted = 1,
ParentLockId = originalLock.Id,
- Operator= App.User.UserName,
- FactoryArea=originalLock.FactoryArea,
- lineNo=originalLock.lineNo,
- WarehouseCode=originalLock.WarehouseCode,
+ Operator = App.User.UserName,
+ FactoryArea = originalLock.FactoryArea,
+ lineNo = originalLock.lineNo,
+ WarehouseCode = originalLock.WarehouseCode,
};
@@ -1614,7 +2003,7 @@
}
return WebResponseContent.Instance.OK("鎷i�夌‘璁ゆ垚鍔�", new { SplitResults = new List<SplitResult>() });
}
-
+
#endregion
}
@@ -1668,6 +2057,32 @@
public List<Dt_StockInfoDetail> PalletStockGoods { get; set; } = new List<Dt_StockInfoDetail>();
public List<Dt_SplitPackageRecord> SplitRecords { get; set; } = new List<Dt_SplitPackageRecord>();
}
+ public class PalletStatusAnalysis
+ {
+ public string OrderNo { get; set; }
+ public string PalletCode { get; set; }
+ public int StockId { get; set; }
+ // 鍥炲簱鐩稿叧灞炴��
+ public bool HasItemsToReturn { get; set; }
+ public bool HasRemainingLocks { get; set; }
+ public bool HasPalletStockGoods { get; set; }
+ public bool HasSplitRecords { get; set; }
+ public decimal RemainingLocksReturnQty { get; set; }
+ public decimal PalletStockReturnQty { get; set; }
+ public decimal SplitReturnQty { get; set; }
+ public decimal TotalReturnQty { get; set; }
+ public List<Dt_OutStockLockInfo> RemainingLocks { get; set; } = new List<Dt_OutStockLockInfo>();
+ public List<Dt_StockInfoDetail> PalletStockGoods { get; set; } = new List<Dt_StockInfoDetail>();
+ public List<Dt_SplitPackageRecord> SplitRecords { get; set; } = new List<Dt_SplitPackageRecord>();
+
+ // 绌烘墭鐩樼浉鍏冲睘鎬�
+ public bool IsEmptyPallet { get; set; }
+ public bool HasActiveTasks { get; set; }
+
+ // 渚垮埄鏂规硶
+ public bool CanReturn => HasItemsToReturn && !HasActiveTasks;
+ public bool CanRemove => IsEmptyPallet && !HasActiveTasks;
+ }
#endregion
}
--
Gitblit v1.9.3