From 68628c6cc163cddfcc745c225a9f3f34767261ef Mon Sep 17 00:00:00 2001
From: 647556386 <647556386@qq.com>
Date: 星期六, 22 十一月 2025 20:44:40 +0800
Subject: [PATCH] Merge branch 'master' of http://115.159.85.185:8098/r/ZhongRui/ALDbanyunxiangmu
---
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs | 169 ++++++++++++++++++++++++++++++++++++++++++--------------
1 files changed, 127 insertions(+), 42 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 b1b0548..eddd986 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"
@@ -160,28 +160,33 @@
try
{
_unitOfWorkManage.BeginTran();
-
- // 1. 鍓嶇疆楠岃瘉鍜屼笟鍔℃鏌�
+
var validationResult = await ValidatePickingRequest(orderNo, palletCode, barcode);
if (!validationResult.IsValid)
return WebResponseContent.Instance.Error(validationResult.ErrorMessage);
var (lockInfo, orderDetail, stockDetail) = validationResult.Data;
- // 2. 璁$畻瀹為檯鎷i�夋暟閲�
+ // 璁$畻瀹為檯鎷i�夋暟閲�
var quantityResult = await CalculateActualPickingQuantity(lockInfo, orderDetail, stockDetail);
if (!quantityResult.IsValid)
return WebResponseContent.Instance.Error(quantityResult.ErrorMessage);
var (actualQty, adjustedReason) = quantityResult.Data;
- // 3. 鎵ц鍒嗘嫞閫昏緫
+ var overPickingValidation = await ValidateOverPicking(orderDetail.Id, actualQty);
+ if (!overPickingValidation.IsValid)
+ {
+ return WebResponseContent.Instance.Error(overPickingValidation.ErrorMessage);
+ }
+
+ // 鎵ц鍒嗘嫞閫昏緫
var pickingResult = await ExecutePickingLogic(lockInfo, orderDetail, stockDetail, orderNo, palletCode, barcode, actualQty);
- // 4. 鏇存柊鐩稿叧鏁版嵁
+ // 鏇存柊鐩稿叧鏁版嵁
await UpdateOrderRelatedData(orderDetail.Id, pickingResult.ActualPickedQty, orderNo);
- // 5. 璁板綍鎿嶄綔鍘嗗彶
+ // 璁板綍鎿嶄綔鍘嗗彶
await RecordPickingHistory(pickingResult, orderNo, palletCode);
_unitOfWorkManage.CommitTran();
@@ -388,18 +393,29 @@
decimal remainingOrderQty = orderDetail.NeedOutQuantity - orderDetail.OverOutQuantity;
decimal stockQuantity = stockDetail.StockQuantity;
+ if (plannedQty <= 0)
+ {
+ return ValidationResult<(decimal, string)>.Error($"璁″垝鎷i�夋暟閲忓繀椤诲ぇ浜�0锛屽綋鍓�: {plannedQty}");
+ }
+
+ if (remainingOrderQty <= 0)
+ {
+ return ValidationResult<(decimal, string)>.Error($"璁㈠崟鍓╀綑闇�姹傛暟閲忓繀椤诲ぇ浜�0锛屽綋鍓�: {remainingOrderQty}");
+ }
+
+ if (stockQuantity <= 0)
+ {
+ return ValidationResult<(decimal, string)>.Error($"搴撳瓨鏁伴噺蹇呴』澶т簬0锛屽綋鍓�: {stockQuantity}");
+ }
// 涓夐噸妫�鏌ワ細鍙栨渶灏忓��
decimal actualQty = plannedQty;
string adjustedReason = null;
- // 妫�鏌�1锛氳鍗曟暟閲忛檺鍒�
- if (plannedQty > remainingOrderQty && remainingOrderQty > 0)
+ if (plannedQty > remainingOrderQty)
{
actualQty = remainingOrderQty;
adjustedReason = $"璁㈠崟鏁伴噺闄愬埗锛氫粠{plannedQty}璋冩暣涓簕actualQty}";
}
-
- // 妫�鏌�2锛氬簱瀛樻暟閲忛檺鍒�
if (actualQty > stockQuantity)
{
actualQty = stockQuantity;
@@ -407,12 +423,19 @@
? $"{adjustedReason}锛屽簱瀛樻暟閲忛檺鍒讹細杩涗竴姝ヨ皟鏁翠负{actualQty}"
: $"搴撳瓨鏁伴噺闄愬埗锛氫粠{plannedQty}璋冩暣涓簕actualQty}";
}
-
- // 妫�鏌�3锛氬疄闄呭彲鎷i�夋暟閲忓繀椤诲ぇ浜�0
if (actualQty <= 0)
{
- return ValidationResult<(decimal, string)>.Error($"鏃犳硶鍒嗘嫞锛氳鍒掓暟閲弡plannedQty}锛屽墿浣欒鍗晎remainingOrderQty}锛屽簱瀛榹stockQuantity}");
+ return ValidationResult<(decimal, string)>.Error($"鏃犳硶鍒嗘嫞锛氳绠楀悗鐨勫疄闄呮暟閲忎负{actualQty}");
}
+ decimal projectedOverOut = orderDetail.OverOutQuantity + actualQty;
+ if (projectedOverOut > orderDetail.NeedOutQuantity)
+ {
+ // 濡傛灉浼氳秴鎷o紝璋冩暣涓哄垰濂芥弧瓒抽渶姹傜殑鏁伴噺
+ actualQty = orderDetail.NeedOutQuantity - orderDetail.OverOutQuantity;
+ adjustedReason = adjustedReason != null
+ ? $"{adjustedReason}锛岄槻瓒呮嫞闄愬埗锛氭渶缁堣皟鏁翠负{actualQty}"
+ : $"闃茶秴鎷i檺鍒讹細浠巤plannedQty}璋冩暣涓簕actualQty}";
+ }
if (adjustedReason != null)
{
@@ -422,6 +445,27 @@
return ValidationResult<(decimal, string)>.Success((actualQty, adjustedReason));
}
+ /// <summary>
+ /// 涓撻棬楠岃瘉鏄惁浼氬彂鐢熻秴鎷�
+ /// </summary>
+ private async Task<ValidationResult<bool>> ValidateOverPicking(int orderDetailId, decimal pickingQty)
+ {
+ var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+ .FirstAsync(x => x.Id == orderDetailId);
+
+ if (orderDetail == null)
+ return ValidationResult<bool>.Error("鏈壘鍒拌鍗曟槑缁�");
+
+ decimal projectedOverOut = orderDetail.OverOutQuantity + pickingQty;
+
+ if (projectedOverOut > orderDetail.NeedOutQuantity)
+ {
+ return ValidationResult<bool>.Error(
+ $"鍒嗘嫞鍚庡皢瀵艰嚧瓒呮嫞锛氬綋鍓嶅凡鍑哄簱{orderDetail.OverOutQuantity}锛屾湰娆″垎鎷pickingQty}锛屽悎璁projectedOverOut}锛岃秴杩囬渶姹倇orderDetail.NeedOutQuantity}");
+ }
+
+ return ValidationResult<bool>.Success(true);
+ }
private async Task<PickingResult> ExecutePickingLogic(
Dt_OutStockLockInfo lockInfo, Dt_OutboundOrderDetail orderDetail, Dt_StockInfoDetail stockDetail,
string orderNo, string palletCode, string barcode, decimal actualQty)
@@ -473,6 +517,7 @@
// 5. 鏇存柊鍘熼攣瀹氫俊鎭�
lockInfo.AssignQuantity = remainingStockQty;
lockInfo.PickedQty = 0;
+ lockInfo.Operator = App.User.UserName;
await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
// 6. 璁剧疆缁撴灉
@@ -493,6 +538,7 @@
// 2. 鏇存柊閿佸畾淇℃伅
lockInfo.PickedQty += actualQty;
lockInfo.Status = (int)OutLockStockStatusEnum.鎷i�夊畬鎴�;
+ lockInfo.Operator = App.User.UserName;
await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
}
@@ -511,6 +557,7 @@
// 2. 鏇存柊閿佸畾淇℃伅
lockInfo.PickedQty += stockOutQty;
lockInfo.AssignQuantity = remainingAssignQty;
+ lockInfo.Operator = App.User.UserName;
await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
// 3. 鏇存柊鎷嗗寘璁板綍鐘舵��
@@ -528,10 +575,24 @@
decimal newOverOutQuantity = currentOrderDetail.OverOutQuantity + pickedQty;
decimal newPickedQty = currentOrderDetail.PickedQty + pickedQty;
- // 鏈�缁堟鏌ワ細纭繚涓嶄細瓒呰繃璁㈠崟闇�姹傛暟閲�
if (newOverOutQuantity > currentOrderDetail.NeedOutQuantity)
{
- throw new Exception($"鍒嗘嫞鍚庡皢瀵艰嚧宸插嚭搴撴暟閲�({newOverOutQuantity})瓒呰繃璁㈠崟闇�姹傛暟閲�({currentOrderDetail.NeedOutQuantity})");
+
+ _logger.LogError($"闃茶秴鎷f鏌ュけ璐� - OrderDetailId: {orderDetailId}, 宸插嚭搴�: {newOverOutQuantity}, 闇�姹�: {currentOrderDetail.NeedOutQuantity}, 鏈鍒嗘嫞: {pickedQty}");
+
+
+ decimal adjustedQty = currentOrderDetail.NeedOutQuantity - currentOrderDetail.OverOutQuantity;
+
+ if (adjustedQty > 0)
+ {
+ _logger.LogWarning($"鑷姩璋冩暣鍒嗘嫞鏁伴噺闃叉瓒呮嫞锛氫粠{pickedQty}璋冩暣涓簕adjustedQty}");
+ newOverOutQuantity = currentOrderDetail.NeedOutQuantity;
+ newPickedQty = currentOrderDetail.PickedQty + adjustedQty;
+ }
+ else
+ {
+ throw new Exception($"鍒嗘嫞鍚庡皢瀵艰嚧宸插嚭搴撴暟閲�({newOverOutQuantity})瓒呰繃璁㈠崟闇�姹傛暟閲�({currentOrderDetail.NeedOutQuantity})锛屼笖鏃犳硶鑷姩璋冩暣");
+ }
}
// 鏇存柊璁㈠崟鏄庣粏
@@ -600,6 +661,10 @@
if (pickingRecord == null)
return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error("鏈壘鍒板搴旂殑鎷i�夎褰�");
+ if (pickingRecord.PickQuantity <= 0)
+ {
+ return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error($"鎷i�夎褰曟暟閲忔棤鏁�: {pickingRecord.PickQuantity}");
+ }
// 鏌ユ壘閿佸畾淇℃伅
var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
.Where(it => it.Id == pickingRecord.OutStockLockId)
@@ -607,14 +672,39 @@
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(
+ $"鍙栨秷鏁伴噺({pickingRecord.PickQuantity})瓒呰繃閿佸畾淇℃伅鐨勫凡鎷i�夋暟閲�({lockInfo.PickedQty})");
+ }
// 妫�鏌ョ姸鎬佹槸鍚﹀厑璁稿彇娑�
if (lockInfo.Status != (int)OutLockStockStatusEnum.鎷i�夊畬鎴�)
return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error("褰撳墠鐘舵�佷笉鍏佽鍙栨秷鍒嗘嫞");
- var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
- .Where(it => it.Barcode == barcode && it.StockId == pickingRecord.StockId)
- .FirstAsync();
+ var order = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>().FirstAsync(x => x.OrderNo == orderNo);
+
+ if (order?.OrderStatus == (int)OutOrderStatusEnum.鍑哄簱瀹屾垚)
+ return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error("璁㈠崟宸插嚭搴撳畬鎴愶紝涓嶅厑璁稿彇娑堝垎鎷�");
+
+ var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>().FirstAsync(x => x.Id == pickingRecord.OrderDetailId);
+
+ if (orderDetail == null)
+ return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error($"鏈壘鍒拌鍗曟槑缁嗭紝ID: {pickingRecord.OrderDetailId}");
+
+ // 妫�鏌ヨ鍗曟槑缁嗙殑宸叉嫞閫夋暟閲忔槸鍚﹁冻澶熷彇娑�
+ if (orderDetail.PickedQty < pickingRecord.PickQuantity)
+ {
+ return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error($"鍙栨秷鏁伴噺({pickingRecord.PickQuantity})瓒呰繃璁㈠崟鏄庣粏鐨勫凡鎷i�夋暟閲�({orderDetail.PickedQty})");
+ }
+
+ // 妫�鏌ヨ鍗曟槑缁嗙殑宸插嚭搴撴暟閲忔槸鍚﹁冻澶熷彇娑�
+ if (orderDetail.OverOutQuantity < pickingRecord.PickQuantity)
+ {
+ return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error($"鍙栨秷鏁伴噺({pickingRecord.PickQuantity})瓒呰繃璁㈠崟鏄庣粏鐨勫凡鍑哄簱鏁伴噺({orderDetail.OverOutQuantity})");
+ }
+
+ var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>().FirstAsync(it => it.Barcode == barcode && it.StockId == pickingRecord.StockId);
if (stockDetail != null)
{
@@ -624,23 +714,8 @@
{
return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error($"鏉$爜{barcode}宸茬粡鍥炲簱锛屼笉鑳藉彇娑堝垎鎷�");
}
- }
-
- // 妫�鏌ヨ鍗曠姸鎬�
- var order = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>()
- .Where(x => x.OrderNo == orderNo)
- .FirstAsync();
-
- if (order?.OrderStatus == (int)OutOrderStatusEnum.鍑哄簱瀹屾垚)
- return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error("璁㈠崟宸插嚭搴撳畬鎴愶紝涓嶅厑璁稿彇娑堝垎鎷�");
-
- // 鑾峰彇璁㈠崟鏄庣粏
- var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
- .FirstAsync(x => x.Id == pickingRecord.OrderDetailId);
-
- if (orderDetail == null)
- return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error($"鏈壘鍒拌鍗曟槑缁嗭紝ID: {pickingRecord.OrderDetailId}");
-
+ }
+
return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Success((pickingRecord, lockInfo, orderDetail));
}
/// <summary>
@@ -993,13 +1068,13 @@
await UpdateOrderDetailsOnReturn(analysis.RemainingLocks);
}
- // 鎯呭喌2锛氬鐞嗘墭鐩樹笂鍏朵粬搴撳瓨璐х墿
+ // 澶勭悊鎵樼洏涓婂叾浠栧簱瀛樿揣鐗�
if (analysis.HasPalletStockGoods)
{
await HandlePalletStockGoodsReturn(analysis.PalletStockGoods);
}
- // 鎯呭喌3锛氬鐞嗘媶鍖呰褰�
+ // 澶勭悊鎷嗗寘璁板綍
if (analysis.HasSplitRecords)
{
await HandleSplitRecordsReturn(analysis.SplitRecords, orderNo, palletCode);
@@ -1097,10 +1172,13 @@
private async Task HandlePalletStockGoodsReturn(List<Dt_StockInfoDetail> palletStockGoods)
{
+ _logger.LogInformation($"鍥炲簱鎿嶄綔锛氬彂鐜皗palletStockGoods.Count}涓簱瀛樻槑缁嗛渶瑕佸洖搴擄紝绛夊緟AGV鎼繍");
foreach (var stockGood in palletStockGoods)
{
- // 鎭㈠搴撳瓨鐘舵��
- stockGood.OutboundQuantity = 0;
+ _logger.LogInformation($"寰呭洖搴撹揣鐗� - 鏉$爜: {stockGood.Barcode}, 鏁伴噺: {stockGood.StockQuantity}, 褰撳墠鐘舵��: {stockGood.Status}");
+
+ // 鎭㈠搴撳瓨鐘舵��
+ stockGood.OutboundQuantity = 0;
stockGood.Status = StockStatusEmun.鍏ュ簱纭.ObjToInt();
await _stockInfoDetailService.Db.Updateable(stockGood).ExecuteCommandAsync();
@@ -1121,6 +1199,7 @@
private async Task UpdateStockInfoStatus(Dt_StockInfo stockInfo)
{
+ _logger.LogInformation($"鍥炲簱鎿嶄綔锛氭墭鐩榹stockInfo.PalletCode}绛夊緟AGV鍥炲簱鎼繍");
// 鏇存柊搴撳瓨涓昏〃鐘舵��
stockInfo.StockStatus = StockStatusEmun.鍏ュ簱纭.ObjToInt();
await _stockInfoService.Db.Updateable(stockInfo).ExecuteCommandAsync();
@@ -1337,7 +1416,7 @@
business_type = outboundOrder.BusinessType,
factoryArea = outboundOrder.FactoryArea,
operationType = 1,
- Operator = outboundOrder.Operator,
+ Operator = App.User.UserName,
orderNo = outboundOrder.UpperOrderNo,
status = outboundOrder.OrderStatus,
details = new List<FeedbackOutboundDetailsModel>()
@@ -1354,6 +1433,7 @@
materialCode = group.Key.MaterielCode,
lineNo = group.Key.lineNo,
warehouseCode = group.Key.WarehouseCode,
+ qty = group.Sum(x => x.PickedQty),
currentDeliveryQty = group.Sum(x => x.PickedQty),
unit = group.Key.Unit,
barcodes = group.Select(row => new WIDESEA_DTO.Outbound.BarcodesModel
@@ -1422,7 +1502,12 @@
CurrentBarcode = newBarcode,
OriginalLockQuantity = quantity,
IsSplitted = 1,
- ParentLockId = originalLock.Id
+ ParentLockId = originalLock.Id,
+ Operator= App.User.UserName,
+ FactoryArea=originalLock.FactoryArea,
+ lineNo=originalLock.lineNo,
+ WarehouseCode=originalLock.WarehouseCode,
+
};
var newLockId = await _outStockLockInfoService.Db.Insertable(newLockInfo).ExecuteReturnIdentityAsync();
--
Gitblit v1.9.3