From 95c92db3c831c73b05068b09221c13ad4a250322 Mon Sep 17 00:00:00 2001
From: 647556386 <647556386@qq.com>
Date: 星期一, 02 二月 2026 20:07:00 +0800
Subject: [PATCH] 条码扫描成功音频播放功能,代码优化
---
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs | 2093 ++++++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 1,706 insertions(+), 387 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 01a0644..6d656bb 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"
@@ -1,17 +1,11 @@
-锘縰sing Dm.filter;
-using MailKit.Search;
-using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Mvc;
+锘縰sing MailKit.Search;
using Microsoft.Extensions.Logging;
+using Microsoft.IdentityModel.Tokens;
+using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json;
using SqlSugar;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Text.Json;
-using System.Threading.Tasks;
+using WIDESEA_BasicService;
using WIDESEA_Common.CommonEnum;
-using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.OrderEnum;
using WIDESEA_Common.StockEnum;
using WIDESEA_Common.TaskEnum;
@@ -20,13 +14,28 @@
using WIDESEA_Core.BaseServices;
using WIDESEA_Core.Enums;
using WIDESEA_Core.Helper;
+using WIDESEA_Core.Utilities;
using WIDESEA_DTO.Basic;
using WIDESEA_DTO.Inbound;
using WIDESEA_DTO.Outbound;
+using WIDESEA_DTO.ReturnMES;
+using WIDESEA_IAllocateService;
using WIDESEA_IBasicService;
+using WIDESEA_ICheckService;
+using WIDESEA_IInboundService;
using WIDESEA_IOutboundService;
using WIDESEA_IStockService;
+using WIDESEA_ITaskInfoService;
using WIDESEA_Model.Models;
+using WIDESEA_Model.Models.Basic;
+using WIDESEA_Model.Models.Check;
+using WIDESEA_Model.Models.Outbound;
+using Org.BouncyCastle.Asn1.Ocsp;
+using WIDESEA_BasicService.MESOperation;
+using WIDESEA_Core.Util;
+using WIDESEA_DTO.Allocate;
+using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
+using WIDESEA_IRecordService;
namespace WIDESEA_OutboundService
{
@@ -35,6 +44,7 @@
/// </summary>
public class OutboundPickingService : ServiceBase<Dt_PickingRecord, IRepository<Dt_PickingRecord>>, IOutboundPickingService
{
+ #region 鏋勯�犲嚱鏁�
private readonly IUnitOfWorkManage _unitOfWorkManage;
public IRepository<Dt_PickingRecord> Repository => BaseDal;
@@ -50,8 +60,20 @@
private readonly IESSApiService _eSSApiService;
private readonly IInvokeMESService _invokeMESService;
private readonly IDailySequenceService _dailySequenceService;
-
+ private readonly IAllocateService _allocateService;
+ private readonly IRepository<Dt_InboundOrder> _inboundOrderRepository;
+ private readonly IInboundOrderDetailService _inboundOrderDetailService;
+ private readonly IRepository<Dt_WarehouseArea> _warehouseAreaRepository;
+ private readonly IReCheckOrderService _reCheckOrderService;
+ private readonly ITask_HtyService _task_HtyService;
private readonly ILogger<OutboundPickingService> _logger;
+ private readonly IRepository<Dt_InterfaceLog> _interfaceLog;
+ private readonly IInboundService _inboundService;
+ private readonly IFeedbackMesService _feedbackMesService;
+ private readonly HttpClientHelper _httpClientHelper;
+ private readonly IRepository<Dt_MesReturnRecord> _mesReturnRecord;
+ private readonly IStockQuantityChangeRecordService _stockQuantityChangeRecordService;
+ private readonly IInboundOrderService _inboundOrderService;
private Dictionary<string, string> stations = new Dictionary<string, string>
{
@@ -70,7 +92,7 @@
public OutboundPickingService(IRepository<Dt_PickingRecord> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IStockService stockService,
IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService, ILocationInfoService locationInfoService,
IOutboundOrderDetailService outboundOrderDetailService, ISplitPackageService splitPackageService, IOutboundOrderService outboundOrderService,
- IRepository<Dt_Task> taskRepository, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger, IInvokeMESService invokeMESService, IDailySequenceService dailySequenceService) : base(BaseDal)
+ IRepository<Dt_Task> taskRepository, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger, IInvokeMESService invokeMESService, IDailySequenceService dailySequenceService, IAllocateService allocateService, IRepository<Dt_InboundOrder> inboundOrderRepository, IInboundOrderDetailService inboundOrderDetailService, IRepository<Dt_WarehouseArea> warehouseAreaRepository, IReCheckOrderService reCheckOrderService, ITask_HtyService task_HtyService, IRepository<Dt_InterfaceLog> interfaceLog, IInboundService inboundService, IFeedbackMesService feedbackMesService, HttpClientHelper httpClientHelper, IRepository<Dt_MesReturnRecord> mesReturnRecord,IStockQuantityChangeRecordService stockQuantityChangeRecordService,IInboundOrderService inboundOrderService) : base(BaseDal)
{
_unitOfWorkManage = unitOfWorkManage;
_stockInfoService = stockInfoService;
@@ -86,8 +108,23 @@
_logger = logger;
_invokeMESService = invokeMESService;
_dailySequenceService = dailySequenceService;
+ _allocateService = allocateService;
+ _inboundOrderRepository = inboundOrderRepository;
+ _inboundOrderDetailService = inboundOrderDetailService;
+ _warehouseAreaRepository = warehouseAreaRepository;
+ _reCheckOrderService = reCheckOrderService;
+ _task_HtyService = task_HtyService;
+ _interfaceLog = interfaceLog;
+ _inboundService = inboundService;
+ _feedbackMesService = feedbackMesService;
+ _httpClientHelper = httpClientHelper;
+ _mesReturnRecord = mesReturnRecord;
+ _stockQuantityChangeRecordService = stockQuantityChangeRecordService;
+ _inboundOrderService = inboundOrderService;
+
}
+ #endregion
#region 鏌ヨ鏂规硶
// 鑾峰彇鏈嫞閫夊垪琛�
@@ -225,19 +262,19 @@
}
_unitOfWorkManage.BeginTran();
- // 1. 鍓嶇疆楠岃瘉
+ // 鍓嶇疆楠岃瘉
var validationResult = await ValidateCancelRequest(orderNo, palletCode, barcode);
if (!validationResult.IsValid)
return WebResponseContent.Instance.Error(validationResult.ErrorMessage);
var (pickingRecord, lockInfo, orderDetail) = validationResult.Data;
- // 2. 鎵ц鍙栨秷閫昏緫
+ //鎵ц鍙栨秷閫昏緫
await ExecuteCancelLogic(lockInfo, pickingRecord, orderDetail, orderNo);
_unitOfWorkManage.CommitTran();
- return WebResponseContent.Instance.OK($"鍙栨秷鍒嗘嫞鎴愬姛锛屾仮澶嶆暟閲忥細{pickingRecord.PickQuantity}");
+ return WebResponseContent.Instance.OK($"鍙栨秷鍒嗘嫞鎴愬姛");
}
catch (Exception ex)
{
@@ -274,15 +311,31 @@
return WebResponseContent.Instance.Error("鏈壘鍒板搴旂殑浠诲姟淇℃伅");
//鍒嗘瀽闇�瑕佸洖搴撶殑璐х墿
- //var returnAnalysis = await AnalyzeReturnItems(orderNo, palletCode, stockInfo.Id);
- //if (!returnAnalysis.HasItemsToReturn)
- // return await HandleNoReturnItems(orderNo, palletCode, task);
-
var statusAnalysis = await AnalyzePalletStatus(orderNo, palletCode, stockInfo.Id);
if (!statusAnalysis.HasItemsToReturn)
- return await HandleNoReturnItems(orderNo, palletCode, task, stockInfo.Id);
+ {
+ try
+ {
+ var result = await HandleNoReturnItems(orderNo, palletCode, task, stockInfo.Id);
+ _unitOfWorkManage.CommitTran();
+ if (result.Status)
+ {
+ task.PalletType = PalletTypeEnum.Empty.ObjToInt();
+ await CreateReturnTaskAndHandleESS(orderNo, palletCode, task, TaskTypeEnum.InEmpty, PalletTypeEnum.Empty.ObjToInt());
+ }
+ return result;
+ }
+ catch (Exception ex)
+ {
+ _unitOfWorkManage.RollbackTran();
+ _logger.LogError($"ReturnRemaining 鍥炲簱绌虹澶辫触 - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}");
+ return WebResponseContent.Instance.Error($"鍥炲簱绌虹鎿嶄綔澶辫触: {ex.Message}");
+ }
- // 4. 妫�鏌ユ槸鍚︽湁杩涜涓殑浠诲姟
+
+ }
+
+ // 妫�鏌ユ槸鍚︽湁杩涜涓殑浠诲姟
if (statusAnalysis.HasActiveTasks)
{
return WebResponseContent.Instance.Error($"鎵樼洏 {palletCode} 鏈夎繘琛屼腑鐨勪换鍔★紝涓嶈兘鎵ц鍥炲簱鎿嶄綔");
@@ -291,11 +344,13 @@
//鎵ц鍥炲簱鎿嶄綔
await ExecuteReturnOperations(orderNo, palletCode, stockInfo, task, statusAnalysis);
+ await ReleaseAllLocksForReallocation(orderNo, palletCode, statusAnalysis);
+
_unitOfWorkManage.CommitTran();
// 鍒涘缓鍥炲簱浠诲姟
- await CreateReturnTaskAndHandleESS(orderNo, palletCode, task, TaskTypeEnum.InPick,task.PalletType);
+ await CreateReturnTaskAndHandleESS(orderNo, palletCode, task, TaskTypeEnum.InPick, task.PalletType);
// 鏇存柊璁㈠崟鐘舵�侊紙涓嶈Е鍙慚ES鍥炰紶锛�
await UpdateOrderStatusForReturn(orderNo);
@@ -382,16 +437,16 @@
private async Task<ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>> ValidatePickingRequest(string orderNo, string palletCode, string barcode)
{
- // 1. 鍩虹鍙傛暟楠岃瘉
+ // 鍩虹鍙傛暟楠岃瘉
if (string.IsNullOrEmpty(orderNo) || string.IsNullOrEmpty(palletCode) || string.IsNullOrEmpty(barcode))
return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error("璁㈠崟鍙枫�佹墭鐩樼爜鍜屾潯鐮佷笉鑳戒负绌�");
- // 2. 鏌ユ壘鏈夋晥鐨勯攣瀹氫俊鎭�
+ // 鏌ユ壘鏈夋晥鐨勯攣瀹氫俊鎭�
var lockInfo = await FindValidLockInfo(orderNo, palletCode, barcode);
if (lockInfo == null)
return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error($"鏈壘鍒版湁鏁堢殑閿佸畾淇℃伅");
- // 3. 妫�鏌ヨ鍗曠姸鎬�
+ // 妫�鏌ヨ鍗曠姸鎬�
var order = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>()
.Where(x => x.OrderNo == orderNo)
.FirstAsync();
@@ -399,18 +454,18 @@
if (order?.OrderStatus == (int)OutOrderStatusEnum.鍑哄簱瀹屾垚)
return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error($"璁㈠崟{orderNo}宸插畬鎴愶紝涓嶈兘缁х画鍒嗘嫞");
- // 4. 鑾峰彇璁㈠崟鏄庣粏
+ // 鑾峰彇璁㈠崟鏄庣粏
var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
.FirstAsync(x => x.Id == lockInfo.OrderDetailId);
if (orderDetail == null)
return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error($"鏈壘鍒拌鍗曟槑缁�");
- // 5. 妫�鏌ヨ鍗曟槑缁嗘暟閲�
+ // 妫�鏌ヨ鍗曟槑缁嗘暟閲�
if (orderDetail.OverOutQuantity >= orderDetail.NeedOutQuantity)
return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error($"璁㈠崟鏄庣粏闇�姹傛暟閲忓凡婊¤冻");
- // 6. 鑾峰彇搴撳瓨鏄庣粏
+ // 鑾峰彇搴撳瓨鏄庣粏
var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
.Where(x => x.Barcode == barcode && x.StockId == lockInfo.StockId &&
x.Status != StockStatusEmun.鍏ュ簱纭.ObjToInt())
@@ -419,14 +474,14 @@
if (stockDetail == null)
return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error($"鏃犳晥鐨勬潯鐮佹垨鐗╂枡缂栫爜");
- // 7. 妫�鏌ュ簱瀛樼姸鎬佸拰鏁伴噺
+ // 妫�鏌ュ簱瀛樼姸鎬佸拰鏁伴噺
if (stockDetail.StockQuantity <= 0)
return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error($"鏉$爜{barcode}搴撳瓨涓嶈冻");
if (stockDetail.Status != StockStatusEmun.鍑哄簱閿佸畾.ObjToInt())
return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error($"鏉$爜{barcode}鐘舵�佷笉姝g‘锛屾棤娉曞垎鎷�");
- // 8. 妫�鏌ユ槸鍚﹂噸澶嶅垎鎷�
+ //妫�鏌ユ槸鍚﹂噸澶嶅垎鎷�
var existingPicking = await Db.Queryable<Dt_PickingRecord>()
.Where(x => x.Barcode == barcode && x.OrderNo == orderNo && x.PalletCode == palletCode && x.OutStockLockId == lockInfo.Id)
.FirstAsync();
@@ -459,10 +514,21 @@
var completedLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
.Where(it => it.CurrentBarcode == barcode &&
(it.Status == (int)OutLockStockStatusEnum.鎷i�夊畬鎴� ||
+ it.Status == (int)OutLockStockStatusEnum.宸查噴鏀� ||
+ it.Status == (int)OutLockStockStatusEnum.宸插彇璧� ||
it.PickedQty >= it.AssignQuantity)).FirstAsync();
if (completedLockInfo != null)
- throw new Exception($"鏉$爜{barcode}宸茬粡瀹屾垚鍒嗘嫞锛屼笉鑳介噸澶嶅垎鎷�");
+ {
+ string statusMsg = completedLockInfo.Status switch
+ {
+ (int)OutLockStockStatusEnum.鎷i�夊畬鎴� => "宸茬粡瀹屾垚鍒嗘嫞",
+ (int)OutLockStockStatusEnum.宸查噴鏀� => "宸茬粡閲婃斁",
+ (int)OutLockStockStatusEnum.宸插彇璧� => "宸茬粡鍙栬蛋",
+ _ => "宸茬粡瀹屾垚鍒嗘嫞"
+ };
+ throw new Exception($"鏉$爜{barcode}{statusMsg}锛屼笉鑳介噸澶嶅垎鎷�");
+ }
else
return null;
}
@@ -624,13 +690,13 @@
private async Task HandleFullPicking(Dt_OutStockLockInfo lockInfo, Dt_StockInfoDetail stockDetail,
decimal actualQty, PickingResult result)
{
- // 1. 鏇存柊搴撳瓨
+ // 鏇存柊搴撳瓨
stockDetail.StockQuantity = 0;
stockDetail.OutboundQuantity = 0;
stockDetail.Status = StockStatusEmun.鍑哄簱瀹屾垚.ObjToInt();
await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
- // 2. 鏇存柊閿佸畾淇℃伅
+ // 鏇存柊閿佸畾淇℃伅
lockInfo.PickedQty += actualQty;
lockInfo.Status = (int)OutLockStockStatusEnum.鎷i�夊畬鎴�;
lockInfo.Operator = App.User.UserName;
@@ -643,19 +709,19 @@
decimal stockOutQty = stockQuantity;
decimal remainingAssignQty = actualQty - stockQuantity;
- // 1. 鏇存柊搴撳瓨
+ // 鏇存柊搴撳瓨
stockDetail.StockQuantity = 0;
stockDetail.OutboundQuantity = 0;
stockDetail.Status = StockStatusEmun.鍑哄簱瀹屾垚.ObjToInt();
await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
- // 2. 鏇存柊閿佸畾淇℃伅
+ // 鏇存柊閿佸畾淇℃伅
lockInfo.PickedQty += stockOutQty;
lockInfo.AssignQuantity = remainingAssignQty;
lockInfo.Operator = App.User.UserName;
await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
- // 3. 鏇存柊鎷嗗寘璁板綍鐘舵��
+ // 鏇存柊鎷嗗寘璁板綍鐘舵��
await UpdateSplitRecordsStatus(stockDetail.Barcode);
result.ActualPickedQty = stockOutQty;
@@ -672,9 +738,7 @@
if (newOverOutQuantity > currentOrderDetail.NeedOutQuantity)
{
-
_logger.LogError($"闃茶秴鎷f鏌ュけ璐� - OrderDetailId: {orderDetailId}, 宸插嚭搴�: {newOverOutQuantity}, 闇�姹�: {currentOrderDetail.NeedOutQuantity}, 鏈鍒嗘嫞: {pickedQty}");
-
decimal adjustedQty = currentOrderDetail.NeedOutQuantity - currentOrderDetail.OverOutQuantity;
@@ -683,6 +747,7 @@
_logger.LogWarning($"鑷姩璋冩暣鍒嗘嫞鏁伴噺闃叉瓒呮嫞锛氫粠{pickedQty}璋冩暣涓簕adjustedQty}");
newOverOutQuantity = currentOrderDetail.NeedOutQuantity;
newPickedQty = currentOrderDetail.PickedQty + adjustedQty;
+ pickedQty = adjustedQty; // 鏇存柊瀹為檯鎷i�夋暟閲�
}
else
{
@@ -690,15 +755,21 @@
}
}
- // 鏇存柊璁㈠崟鏄庣粏
+ // 鏇存柊璁㈠崟鏄庣粏鏁伴噺鍜岀姸鎬�
await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
.SetColumns(it => new Dt_OutboundOrderDetail
{
PickedQty = newPickedQty,
OverOutQuantity = newOverOutQuantity,
+ OrderDetailStatus = newOverOutQuantity >= currentOrderDetail.NeedOutQuantity ?
+ OrderDetailStatusEnum.Over.ObjToInt() :
+ OrderDetailStatusEnum.Outbound.ObjToInt()
})
.Where(it => it.Id == orderDetailId)
.ExecuteCommandAsync();
+
+ // 鏇存柊閿佸畾鏁伴噺
+ await UpdateOrderDetailLockQuantity(orderDetailId);
// 妫�鏌ュ苟鏇存柊璁㈠崟鐘舵��
await CheckAndUpdateOrderStatus(orderNo);
@@ -729,7 +800,15 @@
PickQuantity = result.ActualPickedQty,
PickTime = DateTime.Now,
Operator = App.User.UserName,
- OutStockLockId = result.FinalLockInfo.Id
+ OutStockLockId = result.FinalLockInfo.Id,
+ BarcodeUnit = result.FinalLockInfo.BarcodeUnit,
+ BarcodeQty = result.FinalLockInfo.BarcodeQty,
+ BatchNo = result.FinalLockInfo.BatchNo,
+ lineNo = result.FinalLockInfo.lineNo,
+ SupplyCode = result.FinalLockInfo.SupplyCode,
+ WarehouseCode = result.FinalLockInfo.WarehouseCode,
+
+
};
await Db.Insertable(pickingHistory).ExecuteCommandAsync();
@@ -738,7 +817,75 @@
#endregion
#region 鍙栨秷鍒嗘嫞绉佹湁鏂规硶
+ private async Task<ValidationResult<bool>> ValidateDataConsistencyBeforeCancel(CancelPickingContext context)
+ {
+ try
+ {
+ // 楠岃瘉璁㈠崟鏄庣粏鏁版嵁
+ var currentOrderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+ .FirstAsync(x => x.Id == context.OrderDetail.Id);
+ if (currentOrderDetail.OverOutQuantity < context.PickingRecord.PickQuantity)
+ return ValidationResult<bool>.Error($"璁㈠崟鏄庣粏宸插嚭搴撴暟閲�({currentOrderDetail.OverOutQuantity})灏忎簬鍙栨秷鏁伴噺({context.PickingRecord.PickQuantity})");
+
+ if (currentOrderDetail.PickedQty < context.PickingRecord.PickQuantity)
+ return ValidationResult<bool>.Error($"璁㈠崟鏄庣粏宸叉嫞閫夋暟閲�({currentOrderDetail.PickedQty})灏忎簬鍙栨秷鏁伴噺({context.PickingRecord.PickQuantity})");
+
+ // 楠岃瘉閿佸畾淇℃伅鏁版嵁
+ var currentLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .FirstAsync(x => x.Id == context.LockInfo.Id);
+
+ if (currentLockInfo.PickedQty < context.PickingRecord.PickQuantity)
+ return ValidationResult<bool>.Error($"閿佸畾淇℃伅宸叉嫞閫夋暟閲�({currentLockInfo.PickedQty})灏忎簬鍙栨秷鏁伴噺({context.PickingRecord.PickQuantity})");
+
+ ////// 楠岃瘉搴撳瓨鏁版嵁
+ ////var currentStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ //// .FirstAsync(x => x.Barcode == context.PickingRecord.Barcode && x.StockId == context.PickingRecord.StockId);
+
+ ////if (currentStockDetail == null)
+ //// return ValidationResult<bool>.Error($"鏈壘鍒板搴旂殑搴撳瓨鏄庣粏璁板綍");
+
+ ////if (currentStockDetail.Status == StockStatusEmun.鍏ュ簱纭.ObjToInt() ||
+ //// currentStockDetail.Status == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt())
+ //// return ValidationResult<bool>.Error($"鏉$爜{context.PickingRecord.Barcode}宸茬粡鍥炲簱锛屾棤娉曞彇娑堝垎鎷�");
+
+ // 楠岃瘉鐘舵�佹祦杞殑鍚堟硶鎬�
+ if (!await CanCancelPicking(currentLockInfo, null))
+ return ValidationResult<bool>.Error($"褰撳墠鐘舵�佷笉鍏佽鍙栨秷鍒嗘嫞");
+
+ return ValidationResult<bool>.Success(true);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError($"鍙栨秷鍒嗘嫞鏁版嵁涓�鑷存�ч獙璇佸け璐�: {ex.Message}");
+ return ValidationResult<bool>.Error($"鏁版嵁楠岃瘉澶辫触: {ex.Message}");
+ }
+ }
+
+ private async Task<bool> CanCancelPicking(Dt_OutStockLockInfo lockInfo, Dt_StockInfoDetail stockDetail)
+ {
+ if (lockInfo.Status == (int)OutLockStockStatusEnum.宸查噴鏀� || lockInfo.Status == (int)OutLockStockStatusEnum.宸插彇璧�)
+ return false;
+ // 閿佸畾淇℃伅鐘舵�佹鏌�
+ if (lockInfo.Status != (int)OutLockStockStatusEnum.鎷i�夊畬鎴�)
+ return false;
+
+
+
+ // 濡傛灉鏄媶鍖呰褰曪紝杩橀渶瑕佹鏌ョ埗閿佸畾淇℃伅鐘舵��
+ if (lockInfo.IsSplitted == 1 && lockInfo.ParentLockId.HasValue)
+ {
+ var parentLock = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .FirstAsync(x => x.Id == lockInfo.ParentLockId.Value);
+
+ if (parentLock == null || parentLock.Status == (int)OutLockStockStatusEnum.鍥炲簱涓� ||
+ parentLock.Status == (int)OutLockStockStatusEnum.宸查噴鏀� ||
+ parentLock.Status == (int)OutLockStockStatusEnum.宸插彇璧�)
+ return false;
+ }
+
+ return true;
+ }
private async Task<ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>> ValidateCancelRequest(string orderNo, string palletCode, string barcode)
{
// 鍩虹鍙傛暟楠岃瘉
@@ -813,22 +960,7 @@
return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Success((pickingRecord, lockInfo, orderDetail));
}
- /// <summary>
- /// 妫�鏌ユ潯鐮佹槸鍚﹀凡缁忓洖搴�
- /// </summary>
- private async Task<bool> IsBarcodeReturned(string barcode, int stockId)
- {
- var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
- .Where(it => it.Barcode == barcode && it.StockId == stockId)
- .FirstAsync();
- if (stockDetail == null)
- return false;
-
- // 濡傛灉鐘舵�佹槸鍏ュ簱纭鎴栧叆搴撳畬鎴愶紝璇存槑宸茬粡鍥炲簱
- return stockDetail.Status == StockStatusEmun.鍏ュ簱纭.ObjToInt() ||
- stockDetail.Status == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt();
- }
/// <summary>
/// 妫�鏌ラ攣瀹氫俊鎭搴旂殑鏉$爜鏄惁宸茬粡鍥炲簱
@@ -846,30 +978,25 @@
stockDetail.Status == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt();
}
private async Task ExecuteCancelLogic(Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord,
- Dt_OutboundOrderDetail orderDetail, string orderNo)
+ Dt_OutboundOrderDetail orderDetail, string orderNo)
{
decimal cancelQty = pickingRecord.PickQuantity;
- var currentStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
- .Where(it => it.Barcode == pickingRecord.Barcode && it.StockId == pickingRecord.StockId)
- .FirstAsync();
-
- if (currentStockDetail != null &&
- (currentStockDetail.Status == StockStatusEmun.鍏ュ簱纭.ObjToInt() ||
- currentStockDetail.Status == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt()))
+ // 鏁版嵁涓�鑷存�ч獙璇�
+ var context = new CancelPickingContext
{
- throw new Exception($"鏉$爜{pickingRecord.Barcode}宸茬粡鍥炲簱锛屾棤娉曞彇娑堝垎鎷�");
- }
- // 妫�鏌ュ彇娑堝悗鏁伴噺涓嶄細涓鸿礋鏁�
- decimal newOverOutQuantity = orderDetail.OverOutQuantity - cancelQty;
- decimal newPickedQty = orderDetail.PickedQty - cancelQty;
+ LockInfo = lockInfo,
+ PickingRecord = pickingRecord,
+ OrderDetail = orderDetail,
+ OrderNo = orderNo,
+ CancelQuantity = cancelQty
+ };
- if (newOverOutQuantity < 0 || newPickedQty < 0)
- {
- throw new Exception($"鍙栨秷鍒嗘嫞灏嗗鑷存暟鎹紓甯革細宸插嚭搴搟newOverOutQuantity}锛屽凡鎷i�墈newPickedQty}");
- }
+ var validationResult = await ValidateDataConsistencyBeforeCancel(context);
+ if (!validationResult.IsValid)
+ throw new Exception(validationResult.ErrorMessage);
- // 澶勭悊涓嶅悓绫诲瀷鐨勫彇娑�
+ // 澶勭悊涓嶅悓绫诲瀷鐨勫彇娑�
if (lockInfo.IsSplitted == 1 && lockInfo.ParentLockId.HasValue)
{
await HandleSplitBarcodeCancel(lockInfo, pickingRecord, cancelQty);
@@ -879,16 +1006,23 @@
await HandleNormalBarcodeCancel(lockInfo, pickingRecord, cancelQty);
}
- // 鏇存柊璁㈠崟鏄庣粏
+ // 鏇存柊璁㈠崟鏄庣粏
await UpdateOrderDetailOnCancel(pickingRecord.OrderDetailId, cancelQty);
// 鍒犻櫎鎷i�夎褰�
- await Db.Deleteable<Dt_PickingRecord>()
+ var deleteResult = await Db.Deleteable<Dt_PickingRecord>()
.Where(x => x.Id == pickingRecord.Id)
.ExecuteCommandAsync();
- // 閲嶆柊妫�鏌ヨ鍗曠姸鎬�
+ if (deleteResult <= 0)
+ throw new Exception("鍒犻櫎鎷i�夎褰曞け璐�");
+
+ _logger.LogInformation($"鍒犻櫎鎷i�夎褰� - 璁板綍ID: {pickingRecord.Id}, 鏉$爜: {pickingRecord.Barcode}");
+
+ // 閲嶆柊妫�鏌ヨ鍗曠姸鎬�
await UpdateOrderStatusForReturn(orderNo);
+
+
}
private async Task HandleSplitBarcodeCancel(Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord, decimal cancelQty)
@@ -901,61 +1035,85 @@
if (parentLockInfo == null)
throw new Exception("鏈壘鍒扮埗閿佸畾淇℃伅锛屾棤娉曞彇娑堟媶鍖呭垎鎷�");
+ // 妫�鏌ョ埗鏉$爜鍜屾媶鍖呮潯鐮佺殑鐘舵��
if (await IsLockInfoReturned(parentLockInfo))
- {
throw new Exception($"鐖舵潯鐮亄parentLockInfo.CurrentBarcode}宸茬粡鍥炲簱锛屾棤娉曞彇娑堟媶鍖呭垎鎷�");
- }
+
if (await IsLockInfoReturned(lockInfo))
- {
throw new Exception($"鎷嗗寘鏉$爜{lockInfo.CurrentBarcode}宸茬粡鍥炲簱锛屾棤娉曞彇娑堟媶鍖呭垎鎷�");
- }
+
// 鎭㈠鐖堕攣瀹氫俊鎭殑鍒嗛厤鏁伴噺
parentLockInfo.AssignQuantity += cancelQty;
+ parentLockInfo.Status = (int)OutLockStockStatusEnum.鍑哄簱涓�; // 鎭㈠涓哄嚭搴撲腑鐘舵��
await _outStockLockInfoService.Db.Updateable(parentLockInfo).ExecuteCommandAsync();
- // 鎭㈠搴撳瓨
- var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ // 鎭㈠鐖舵潯鐮佸簱瀛�
+ var parentStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
.Where(x => x.Barcode == parentLockInfo.CurrentBarcode && x.StockId == parentLockInfo.StockId)
.FirstAsync();
- if (stockDetail != null)
+ if (parentStockDetail != null)
{
- stockDetail.StockQuantity += cancelQty;
- stockDetail.OutboundQuantity = stockDetail.StockQuantity;
- stockDetail.Status = StockStatusEmun.鍑哄簱閿佸畾.ObjToInt();
- await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
+ parentStockDetail.StockQuantity += cancelQty;
+ parentStockDetail.OutboundQuantity = parentStockDetail.StockQuantity;
+ parentStockDetail.Status = StockStatusEmun.鍑哄簱閿佸畾.ObjToInt();
+ await _stockInfoDetailService.Db.Updateable(parentStockDetail).ExecuteCommandAsync();
+
+ _logger.LogInformation($"鎭㈠鐖舵潯鐮佸簱瀛� - 鏉$爜: {parentStockDetail.Barcode}, 鎭㈠鏁伴噺: {cancelQty}, 鏂板簱瀛�: {parentStockDetail.StockQuantity}");
+ }
+
+ // 澶勭悊鎷嗗寘浜х敓鐨勬柊鏉$爜搴撳瓨
+ var splitStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ .Where(x => x.Barcode == lockInfo.CurrentBarcode && x.StockId == lockInfo.StockId)
+ .FirstAsync();
+
+ if (splitStockDetail != null)
+ {
+ // 鍒犻櫎鎷嗗寘浜х敓鐨勬柊鏉$爜搴撳瓨璁板綍
+ await _stockInfoDetailService.Db.Deleteable(splitStockDetail).ExecuteCommandAsync();
+ _logger.LogInformation($"鍒犻櫎鎷嗗寘鏂版潯鐮佸簱瀛� - 鏉$爜: {splitStockDetail.Barcode}");
}
// 鏇存柊鎷嗗寘璁板綍鐘舵��
- await _splitPackageService.Db.Updateable<Dt_SplitPackageRecord>()
+ var updateCount = await _splitPackageService.Db.Updateable<Dt_SplitPackageRecord>()
.SetColumns(x => new Dt_SplitPackageRecord
{
Status = (int)SplitPackageStatusEnum.宸叉挙閿�,
IsReverted = true,
+ Operator = App.User.UserName,
+ RevertTime = DateTime.Now
})
.Where(x => x.NewBarcode == lockInfo.CurrentBarcode && !x.IsReverted)
.ExecuteCommandAsync();
+
+ _logger.LogInformation($"鏇存柊鎷嗗寘璁板綍鐘舵�� - 鏇存柊璁板綍鏁�: {updateCount}");
// 鍒犻櫎鎷嗗寘浜х敓鐨勯攣瀹氫俊鎭�
await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>()
.Where(x => x.Id == lockInfo.Id)
.ExecuteCommandAsync();
- await UpdateOrderDetailOnCancel(pickingRecord.OrderDetailId, cancelQty);
+ _logger.LogInformation($"鍒犻櫎鎷嗗寘閿佸畾淇℃伅 - 閿佸畾ID: {lockInfo.Id}, 鏉$爜: {lockInfo.CurrentBarcode}");
}
-
private async Task HandleNormalBarcodeCancel(Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord, decimal cancelQty)
{
if (await IsLockInfoReturned(lockInfo))
- {
throw new Exception($"鏉$爜{lockInfo.CurrentBarcode}宸茬粡鍥炲簱锛屾棤娉曞彇娑堝垎鎷�");
- }
+
// 鎭㈠閿佸畾淇℃伅
lockInfo.PickedQty -= cancelQty;
if (lockInfo.PickedQty < 0) lockInfo.PickedQty = 0;
- lockInfo.Status = (int)OutLockStockStatusEnum.鍑哄簱涓�;
+ // 鍙湁褰撴嫞閫夋暟閲忓畬鍏ㄥ彇娑堟椂鎵嶆仮澶嶇姸鎬�
+ if (lockInfo.PickedQty == 0)
+ {
+ lockInfo.Status = (int)OutLockStockStatusEnum.鍑哄簱涓�;
+ }
+
+ lockInfo.Operator = App.User.UserName;
await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
+
+ _logger.LogInformation($"鎭㈠閿佸畾淇℃伅 - 閿佸畾ID: {lockInfo.Id}, 鎵e噺鎷i�夋暟閲�: {cancelQty}, 鏂板凡鎷i�夋暟閲�: {lockInfo.PickedQty}");
// 鎭㈠搴撳瓨
var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
@@ -966,45 +1124,81 @@
{
stockDetail.StockQuantity += cancelQty;
stockDetail.OutboundQuantity = stockDetail.StockQuantity;
- stockDetail.Status = StockStatusEmun.鍑哄簱閿佸畾.ObjToInt();
+
+ // 鎭㈠搴撳瓨鐘舵��
+ if (stockDetail.Status == StockStatusEmun.鍑哄簱瀹屾垚.ObjToInt())
+ {
+ stockDetail.Status = StockStatusEmun.鍑哄簱閿佸畾.ObjToInt();
+ }
+
await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
+
+ _logger.LogInformation($"鎭㈠搴撳瓨 - 鏉$爜: {stockDetail.Barcode}, 鎭㈠鏁伴噺: {cancelQty}, " +
+ $"鏂板簱瀛�: {stockDetail.StockQuantity}, 鏂扮姸鎬�: {stockDetail.Status}");
+ }
+ else
+ {
+ _logger.LogWarning($"鏈壘鍒板簱瀛樿褰� - 鏉$爜: {pickingRecord.Barcode}, 搴撳瓨ID: {pickingRecord.StockId}");
}
}
-
private async Task UpdateOrderDetailOnCancel(int orderDetailId, decimal cancelQty)
{
- // 鑾峰彇鏈�鏂扮殑璁㈠崟鏄庣粏鏁版嵁
+ // 鑾峰彇鏈�鏂扮殑璁㈠崟鏄庣粏鏁版嵁锛堝甫閿侊級
var currentOrderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+ //.With(SqlWith.RowLock)
.FirstAsync(x => x.Id == orderDetailId);
decimal newOverOutQuantity = currentOrderDetail.OverOutQuantity - cancelQty;
decimal newPickedQty = currentOrderDetail.PickedQty - cancelQty;
- // 妫�鏌ュ彇娑堝悗鏁伴噺涓嶄細涓鸿礋鏁�
- if (newOverOutQuantity < 0 || newPickedQty < 0)
+ // 涓ユ牸妫�鏌ュ彇娑堝悗鏁伴噺涓嶄細涓鸿礋鏁�
+ if (newOverOutQuantity < 0)
+ throw new Exception($"鍙栨秷鍒嗘嫞灏嗗鑷村凡鍑哄簱鏁伴噺({newOverOutQuantity})涓鸿礋鏁�");
+
+ if (newPickedQty < 0)
+ throw new Exception($"鍙栨秷鍒嗘嫞灏嗗鑷村凡鎷i�夋暟閲�({newPickedQty})涓鸿礋鏁�");
+
+ // 纭畾鏂扮殑鐘舵��
+ int newStatus;
+ if (newOverOutQuantity >= currentOrderDetail.NeedOutQuantity)
{
- throw new Exception($"鍙栨秷鍒嗘嫞灏嗗鑷村凡鍑哄簱鏁伴噺({newOverOutQuantity})鎴栧凡鎷i�夋暟閲�({newPickedQty})涓鸿礋鏁�");
+ newStatus = OrderDetailStatusEnum.Over.ObjToInt();
+ }
+ else if (newOverOutQuantity > 0)
+ {
+ newStatus = OrderDetailStatusEnum.Outbound.ObjToInt();
+ }
+ else
+ {
+ newStatus = OrderDetailStatusEnum.New.ObjToInt();
}
- await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+ // 鏇存柊璁㈠崟鏄庣粏
+ var updateResult = await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
.SetColumns(it => new Dt_OutboundOrderDetail
{
PickedQty = newPickedQty,
OverOutQuantity = newOverOutQuantity,
+ OrderDetailStatus = newStatus
})
.Where(it => it.Id == orderDetailId)
.ExecuteCommandAsync();
- }
+ if (updateResult <= 0)
+ throw new Exception("鏇存柊璁㈠崟鏄庣粏澶辫触");
+
+ // 鏇存柊閿佸畾鏁伴噺
+ await UpdateOrderDetailLockQuantity(orderDetailId);
+
+ _logger.LogInformation($"鏇存柊璁㈠崟鏄庣粏 - OrderDetailId: {orderDetailId}, " +
+ $"鎵e噺宸插嚭搴�: {cancelQty}, 鏂板凡鍑哄簱: {newOverOutQuantity}, " +
+ $"鎵e噺宸叉嫞閫�: {cancelQty}, 鏂板凡鎷i��: {newPickedQty}, " +
+ $"鏂扮姸鎬�: {newStatus}");
+ }
#endregion
#region 鍥炲簱鎿嶄綔绉佹湁鏂规硶
- private async Task<Dt_StockInfo> GetStockInfo(string palletCode)
- {
- return await _stockInfoService.Db.Queryable<Dt_StockInfo>()
- .FirstAsync(x => x.PalletCode == palletCode);
- }
/// <summary>
/// 妫�鏌ユ暣涓墭鐩樻槸鍚﹀凡缁忓洖搴�
/// </summary>
@@ -1083,23 +1277,6 @@
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�夊畬鎴�);
-
- //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
{
var locationtype = 0;
@@ -1121,15 +1298,13 @@
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,PalletTypeEnum.Empty.ObjToInt());
}
catch (Exception ex)
@@ -1190,6 +1365,116 @@
await UpdateStockInfoStatus(stockInfo);
}
+ /// <summary>
+ /// 瀹屽叏閲婃斁閿佸畾锛屽厑璁搁噸鏂板垎閰嶅簱瀛�
+ /// </summary>
+ private async Task ReleaseAllLocksForReallocation(string orderNo, string palletCode, PalletStatusAnalysis analysis)
+ {
+ _logger.LogInformation($"寮�濮嬮噴鏀鹃攣瀹氫互渚块噸鏂板垎閰� - 璁㈠崟: {orderNo}, 鎵樼洏: {palletCode}");
+
+ // 澶勭悊鏈垎鎷g殑鍑哄簱閿佸畾璁板綍 - 瀹屽叏閲婃斁
+ if (analysis.HasRemainingLocks)
+ {
+ await ReleaseRemainingLocks(analysis.RemainingLocks);
+ }
+
+ // 澶勭悊宸插洖搴撶殑閿佸畾璁板綍 - 鍒犻櫎鎴栨爣璁颁负鏃犳晥
+ await CleanupReturnedLocks(orderNo, palletCode);
+
+ // 閲嶇疆璁㈠崟鏄庣粏鐨勯攣瀹氭暟閲�
+ await ResetOrderDetailLockQuantities(analysis);
+
+ _logger.LogInformation($"閿佸畾閲婃斁瀹屾垚 - 璁㈠崟: {orderNo}, 鎵樼洏: {palletCode}");
+ }
+
+ /// <summary>
+ /// 閲婃斁鏈垎鎷g殑閿佸畾璁板綍
+ /// </summary>
+ private async Task ReleaseRemainingLocks(List<Dt_OutStockLockInfo> remainingLocks)
+ {
+ var lockIds = remainingLocks.Select(x => x.Id).ToList();
+
+ // 灏嗛攣瀹氳褰曠姸鎬佹敼涓�"宸查噴鏀�"锛屾垨鑰呯洿鎺ュ垹闄�
+ // 鏍囪涓哄凡閲婃斁
+ await _outStockLockInfoService.Db.Updateable<Dt_OutStockLockInfo>()
+ .SetColumns(it => new Dt_OutStockLockInfo
+ {
+ Status = (int)OutLockStockStatusEnum.宸查噴鏀�,
+
+ Operator = App.User.UserName
+ })
+ .Where(it => lockIds.Contains(it.Id))
+ .ExecuteCommandAsync();
+
+ // 鐩存帴鍒犻櫎锛堟洿褰诲簳锛�
+ // await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>()
+ // .Where(it => lockIds.Contains(it.Id))
+ // .ExecuteCommandAsync();
+
+ _logger.LogInformation($"閲婃斁{remainingLocks.Count}鏉℃湭鍒嗘嫞閿佸畾璁板綍");
+ }
+
+ /// <summary>
+ /// 娓呯悊宸插洖搴撶殑閿佸畾璁板綍
+ /// </summary>
+ private async Task CleanupReturnedLocks(string orderNo, string palletCode)
+ {
+ // 鏌ユ壘鎵�鏈夌姸鎬佷负鍥炲簱涓殑閿佸畾璁板綍骞堕噴鏀�
+ var returnedLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(it => it.OrderNo == orderNo &&
+ it.PalletCode == palletCode &&
+ it.Status == (int)OutLockStockStatusEnum.鍥炲簱涓�)
+ .ToListAsync();
+
+ if (returnedLocks.Any())
+ {
+ var returnedLockIds = returnedLocks.Select(x => x.Id).ToList();
+
+ await _outStockLockInfoService.Db.Updateable<Dt_OutStockLockInfo>()
+ .SetColumns(it => new Dt_OutStockLockInfo
+ {
+ Status = (int)OutLockStockStatusEnum.宸查噴鏀�,
+ //ReleaseTime = DateTime.Now,
+ Operator = App.User.UserName
+ })
+ .Where(it => returnedLockIds.Contains(it.Id))
+ .ExecuteCommandAsync();
+
+ _logger.LogInformation($"娓呯悊{returnedLocks.Count}鏉″洖搴撲腑閿佸畾璁板綍");
+ }
+ }
+
+ /// <summary>
+ /// 閲嶇疆璁㈠崟鏄庣粏鐨勯攣瀹氭暟閲�
+ /// </summary>
+ private async Task ResetOrderDetailLockQuantities(PalletStatusAnalysis analysis)
+ {
+ // 鏀堕泦鎵�鏈夊彈褰卞搷鐨勮鍗曟槑缁咺D
+ var affectedOrderDetailIds = new HashSet<int>();
+
+ if (analysis.HasRemainingLocks)
+ {
+ foreach (var lockInfo in analysis.RemainingLocks)
+ {
+ affectedOrderDetailIds.Add(lockInfo.OrderDetailId);
+ }
+ }
+
+ // 閲嶇疆杩欎簺璁㈠崟鏄庣粏鐨勯攣瀹氭暟閲�
+ foreach (var orderDetailId in affectedOrderDetailIds)
+ {
+ await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+ .SetColumns(it => new Dt_OutboundOrderDetail
+ {
+ LockQuantity = 0, // 閲嶇疆閿佸畾鏁伴噺
+ OrderDetailStatus = OrderDetailStatusEnum.New.ObjToInt() // 閲嶇疆鐘舵�佷负鏂板缓
+ })
+ .Where(it => it.Id == orderDetailId)
+ .ExecuteCommandAsync();
+ }
+
+ _logger.LogInformation($"閲嶇疆{affectedOrderDetailIds.Count}涓鍗曟槑缁嗙殑閿佸畾鏁伴噺");
+ }
private async Task HandleRemainingLocksReturn(List<Dt_OutStockLockInfo> remainingLocks, int stockId)
{
var lockIds = remainingLocks.Select(x => x.Id).ToList();
@@ -1221,6 +1506,7 @@
if (stockDetail != null)
{
+ stockDetail.StockQuantity += returnQty;
// 鎭㈠搴撳瓨鐘舵��
stockDetail.OutboundQuantity = Math.Max(0, stockDetail.OutboundQuantity - returnQty);
stockDetail.Status = StockStatusEmun.鍏ュ簱纭.ObjToInt();
@@ -1228,6 +1514,7 @@
}
else
{
+ _logger.LogWarning($"鏈壘鍒板搴旂殑搴撳瓨鏄庣粏 - 鏉$爜: {lockInfo.CurrentBarcode}, 搴撳瓨ID: {lockInfo.StockId}");
// 鍒涘缓鏂扮殑搴撳瓨璁板綍
//var newStockDetail = new Dt_StockInfoDetail
//{
@@ -1247,40 +1534,36 @@
//};
//await _stockInfoDetailService.Db.Insertable(newStockDetail).ExecuteCommandAsync();
}
- }
- }
-
- private async Task UpdateOrderDetailsOnReturn(List<Dt_OutStockLockInfo> remainingLocks)
- {
- // 鎸夎鍗曟槑缁嗗垎缁�
- var orderDetailGroups = remainingLocks.GroupBy(x => x.OrderDetailId);
-
- foreach (var group in orderDetailGroups)
- {
- var orderDetailId = group.Key;
- var totalReturnQty = group.Sum(x => x.AssignQuantity - x.PickedQty);
-
- // 鑾峰彇褰撳墠璁㈠崟鏄庣粏
- var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
- .FirstAsync(x => x.Id == orderDetailId);
-
- if (orderDetail != null)
+ try
{
- // 璋冩暣宸叉嫞閫夋暟閲忓拰宸插嚭搴撴暟閲�
- decimal newPickedQty = Math.Max(0, orderDetail.PickedQty - totalReturnQty);
- decimal newOverOutQuantity = Math.Max(0, orderDetail.OverOutQuantity - totalReturnQty);
+ var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+ .FirstAsync(x => x.Id == lockInfo.OrderDetailId);
- await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
- .SetColumns(it => new Dt_OutboundOrderDetail
- {
- PickedQty = newPickedQty,
- OverOutQuantity = newOverOutQuantity,
- })
- .Where(it => it.Id == orderDetailId)
- .ExecuteCommandAsync();
+ if (orderDetail != null)
+ {
+ decimal newLockQuantity = Math.Max(0, orderDetail.LockQuantity - returnQty);
+
+ await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+ .SetColumns(it => new Dt_OutboundOrderDetail
+ {
+ LockQuantity = newLockQuantity
+ })
+ .Where(it => it.Id == lockInfo.OrderDetailId)
+ .ExecuteCommandAsync();
+
+ _logger.LogInformation($"鏇存柊璁㈠崟鏄庣粏閿佸畾鏁伴噺 - OrderDetailId: {lockInfo.OrderDetailId}, " +
+ $"鎵e噺閿佸畾: {returnQty}, 鏂伴攣瀹氭暟閲�: {newLockQuantity}");
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError($"鏇存柊璁㈠崟鏄庣粏閿佸畾鏁伴噺澶辫触 - OrderDetailId: {lockInfo.OrderDetailId}, Error: {ex.Message}");
}
}
+
+
}
+
private async Task HandlePalletStockGoodsReturn(List<Dt_StockInfoDetail> palletStockGoods)
{
@@ -1342,7 +1625,7 @@
/// <param name="originalTask"></param>
/// <param name="analysis"></param>
/// <returns></returns>
- private async Task CreateReturnTaskAndHandleESS(string orderNo, string palletCode, Dt_Task originalTask, TaskTypeEnum taskTypeEnum,int palletType)
+ private async Task CreateReturnTaskAndHandleESS(string orderNo, string palletCode, Dt_Task originalTask, TaskTypeEnum taskTypeEnum, int palletType)
{
var firstLocation = await _locationInfoService.Db.Queryable<Dt_LocationInfo>()
.FirstAsync(x => x.LocationCode == originalTask.SourceAddress);
@@ -1365,17 +1648,33 @@
TaskType = taskTypeEnum.ObjToInt(),
PalletType = palletType,
WarehouseId = originalTask.WarehouseId
-
+
};
- // 淇濆瓨鍥炲簱浠诲姟
- await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync();
+ try
+ {
+ // 淇濆瓨鍥炲簱浠诲姟
+ var insertcount = await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync();
+ if (insertcount <= 0)
+ {
+ throw new Exception("鍒涘缓浠诲姟澶辫触锛�");
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogInformation($"CreateReturnTaskAndHandleESS 鍒涘缓浠诲姟澶辫触: {orderNo} 锛� {palletCode}");
+ throw new Exception("鍒涘缓浠诲姟澶辫触锛�");
+ }
var targetAddress = originalTask.TargetAddress;
+ _logger.LogInformation($"CreateReturnTaskAndHandleESS 鍒犻櫎鍘嗗彶浠诲姟: {orderNo} 锛� {originalTask.TaskNum}");
// 鍒犻櫎鍘熷鍑哄簱浠诲姟
- _taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.鑷姩瀹屾垚);
- // await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync();
-
-
+ // _taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.鑷姩瀹屾垚);
+ var result = _task_HtyService.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.浜哄伐鍒犻櫎);
+ if (!result)
+ {
+ await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync();
+ }
+ _logger.LogInformation($"CreateReturnTaskAndHandleESS 鍒犻櫎鍘嗗彶浠诲姟: {orderNo} 锛� {originalTask.TaskNum},褰卞搷琛� {result}");
// 缁� ESS 鍙戦�佹祦鍔ㄤ俊鍙峰拰鍒涘缓浠诲姟
await SendESSCommands(palletCode, targetAddress, returnTask);
@@ -1392,40 +1691,40 @@
{
try
{
- // 1. 鍙戦�佹祦鍔ㄤ俊鍙�
+ // 鍙戦�佹祦鍔ㄤ俊鍙�
var moveResult = await _eSSApiService.MoveContainerAsync(new WIDESEA_DTO.Basic.MoveContainerRequest
{
slotCode = movestations[targetAddress],
containerCode = palletCode
});
- if (moveResult)
- {
- // 2. 鍒涘缓鍥炲簱浠诲姟
- var essTask = new TaskModel()
- {
- taskType = "putaway",
- taskGroupCode = "",
- groupPriority = 0,
- tasks = new List<TasksType>{ new() {
- taskCode = returnTask.TaskNum.ToString(),
- taskPriority = 0,
- taskDescribe = new TaskDescribeType
- {
- containerCode = palletCode,
- containerType = "CT_KUBOT_STANDARD",
- fromLocationCode = stations.GetValueOrDefault(targetAddress) ?? "",
- toStationCode = "",
- toLocationCode = returnTask.TargetAddress,
- deadline = 0,
- storageTag = ""
- }
- } }
- };
+ //if (moveResult)
+ //{
+ // 鍒涘缓鍥炲簱浠诲姟
+ //var essTask = new TaskModel()
+ //{
+ // taskType = "putaway",
+ // taskGroupCode = "",
+ // groupPriority = 0,
+ // tasks = new List<TasksType>{ new() {
+ // taskCode = returnTask.TaskNum.ToString(),
+ // taskPriority = 0,
+ // taskDescribe = new TaskDescribeType
+ // {
+ // containerCode = palletCode,
+ // containerType = "CT_KUBOT_STANDARD",
+ // fromLocationCode = stations.GetValueOrDefault(targetAddress) ?? "",
+ // toStationCode = "",
+ // toLocationCode = returnTask.TargetAddress,
+ // deadline = 0,
+ // storageTag = ""
+ // }
+ // } }
+ //};
- var resultTask = await _eSSApiService.CreateTaskAsync(essTask);
- _logger.LogInformation($"ReturnRemaining 鍒涘缓浠诲姟鎴愬姛: {resultTask}");
- }
+ //var resultTask = await _eSSApiService.CreateTaskAsync(essTask);
+ //_logger.LogInformation($"ReturnRemaining 鍒涘缓浠诲姟鎴愬姛: {resultTask}");
+ //}
}
catch (Exception ex)
{
@@ -1449,13 +1748,25 @@
.ToListAsync();
bool allCompleted = true;
+ bool hasPartial = false;
+ bool hasLocked = false;
+
foreach (var detail in orderDetails)
{
if (detail.OverOutQuantity < detail.NeedOutQuantity)
{
allCompleted = false;
- break;
}
+
+ if (detail.OrderDetailStatus == OrderDetailStatusEnum.Outbound.ObjToInt())
+ {
+ hasPartial = true;
+ }
+
+ //if (detail.OrderDetailStatus == OrderDetailStatusEnum.Locked.ObjToInt())
+ //{
+ // hasLocked = true;
+ //}
}
var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>()
@@ -1463,20 +1774,34 @@
if (outboundOrder == null) return;
- int newStatus = allCompleted ? (int)OutOrderStatusEnum.鍑哄簱瀹屾垚 : (int)OutOrderStatusEnum.鍑哄簱涓�;
+ int newStatus;
+ if (allCompleted)
+ {
+ newStatus = (int)OutOrderStatusEnum.鍑哄簱瀹屾垚;
+ }
+ else if (hasPartial)
+ {
+ newStatus = (int)OutOrderStatusEnum.鍑哄簱涓�;
+ }
+ else
+ {
+ newStatus = (int)OutOrderStatusEnum.鏈紑濮�;
+ }
if (outboundOrder.OrderStatus != newStatus)
{
await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
- .SetColumns(x => x.OrderStatus == newStatus)
+ .SetColumns(x => new Dt_OutboundOrder
+ {
+ OrderStatus = newStatus,
+ Operator = App.User.UserName,
+ })
.Where(x => x.OrderNo == orderNo)
.ExecuteCommandAsync();
- // 鍙湁姝e父鍒嗘嫞瀹屾垚鏃舵墠鍚慚ES鍙嶉
- //if (allCompleted && newStatus == (int)OutOrderStatusEnum.鍑哄簱瀹屾垚)
- //{
- // await HandleOrderCompletion(outboundOrder, orderNo);
- //}
+ _logger.LogInformation($"璁㈠崟鐘舵�佹洿鏂� - OrderNo: {orderNo}, 鏃х姸鎬�: {outboundOrder.OrderStatus}, 鏂扮姸鎬�: {newStatus}");
+
+
}
}
catch (Exception ex)
@@ -1485,8 +1810,70 @@
}
}
+ /// <summary>
+ /// 鏇存柊璁㈠崟鏄庣粏鐘舵�侊紙鍩轰簬宸插嚭搴撴暟閲忥級
+ /// </summary>
+ private async Task UpdateOrderDetailStatus(int orderDetailId)
+ {
+ var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+ .FirstAsync(x => x.Id == orderDetailId);
+ if (orderDetail == null) return;
+ int newStatus = orderDetail.OrderDetailStatus;
+
+ if (orderDetail.OverOutQuantity >= orderDetail.NeedOutQuantity)
+ {
+ // 宸插嚭搴撴暟閲� >= 闇�姹傛暟閲忥紝鏍囪涓哄畬鎴�
+ newStatus = OrderDetailStatusEnum.Over.ObjToInt();
+ }
+ else if (orderDetail.OverOutQuantity > 0)
+ {
+ // 鏈夐儴鍒嗗嚭搴擄紝浣嗘湭瀹屾垚
+ newStatus = OrderDetailStatusEnum.Outbound.ObjToInt();
+ }
+ else if (orderDetail.LockQuantity > 0)
+ {
+ // 鏈夐攣瀹氭暟閲忥紝浣嗘湭鍑哄簱
+ //newStatus = OrderDetailStatusEnum.Locked.ObjToInt();
+ }
+ else
+ {
+ // 鏂板缓鐘舵��
+ newStatus = OrderDetailStatusEnum.New.ObjToInt();
+ }
+
+ // 鍙湁鐘舵�佸彂鐢熷彉鍖栨椂鎵嶆洿鏂�
+ if (orderDetail.OrderDetailStatus != newStatus)
+ {
+ await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+ .SetColumns(it => new Dt_OutboundOrderDetail
+ {
+ OrderDetailStatus = newStatus,
+
+ })
+ .Where(it => it.Id == orderDetailId)
+ .ExecuteCommandAsync();
+ }
+ }
+ /// <summary>
+ /// 鏇存柊璁㈠崟鏄庣粏閿佸畾鏁伴噺
+ /// </summary>
+ private async Task UpdateOrderDetailLockQuantity(int orderDetailId)
+ {
+ var totalLockedQty = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(x => x.OrderDetailId == orderDetailId &&
+ x.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
+ .SumAsync(x => x.AssignQuantity - x.PickedQty);
+
+ await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+ .SetColumns(it => new Dt_OutboundOrderDetail
+ {
+ LockQuantity = totalLockedQty
+ })
+ .Where(it => it.Id == orderDetailId)
+ .ExecuteCommandAsync();
+ }
private async Task UpdateOrderStatusForReturn(string orderNo)
{
try
@@ -1517,7 +1904,11 @@
if (outboundOrder.OrderStatus != newStatus)
{
await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
- .SetColumns(x => x.OrderStatus == newStatus)
+ .SetColumns(x => new Dt_OutboundOrder
+ {
+ OrderStatus = newStatus,
+ Operator = App.User.UserName,
+ })
.Where(x => x.OrderNo == orderNo)
.ExecuteCommandAsync();
@@ -1527,79 +1918,6 @@
catch (Exception ex)
{
_logger.LogError($"UpdateOrderStatusForReturn澶辫触 - OrderNo: {orderNo}, Error: {ex.Message}");
- }
- }
-
- private async Task HandleOrderCompletion(Dt_OutboundOrder outboundOrder, string orderNo)
- {
- // 璋冩嫧鍑哄簱鍜岄噸妫�鍑哄簱涓嶉渶瑕佸弽棣圡ES
- if (outboundOrder.OrderType == OutOrderTypeEnum.Allocate.ObjToInt() ||
- outboundOrder.OrderType == OutOrderTypeEnum.ReCheck.ObjToInt())
- {
- return;
- }
-
- try
- {
- var feedmodel = new FeedbackOutboundRequestModel
- {
- reqCode = Guid.NewGuid().ToString(),
- reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
- business_type = outboundOrder.BusinessType,
- factoryArea = outboundOrder.FactoryArea,
- operationType = 1,
- Operator = App.User.UserName,
- orderNo = outboundOrder.UpperOrderNo,
- documentsNO = outboundOrder.OrderNo,
- status = outboundOrder.OrderStatus,
- details = new List<FeedbackOutboundDetailsModel>()
- };
-
- // 鍙幏鍙栧凡鎷i�夊畬鎴愮殑閿佸畾璁板綍
- var lists = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
- .Where(x => x.OrderNo == orderNo && x.Status == (int)OutLockStockStatusEnum.鎷i�夊畬鎴�)
- .ToListAsync();
-
- var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.lineNo, item.Unit, item.WarehouseCode })
- .Select(group => new FeedbackOutboundDetailsModel
- {
- 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
- {
- barcode = row.CurrentBarcode,
- supplyCode = row.SupplyCode,
- batchNo = row.BatchNo,
- unit = row.Unit,
- qty = row.PickedQty
- }).ToList()
- }).ToList();
-
- feedmodel.details = groupedData;
-
- var result = await _invokeMESService.FeedbackOutbound(feedmodel);
- if (result != null && result.code == 200)
- {
- await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
- .SetColumns(x => x.ReturnToMESStatus == 1)
- .Where(x => x.OrderId == outboundOrder.Id)
- .ExecuteCommandAsync();
-
- await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
- .SetColumns(x => x.ReturnToMESStatus == 1)
- .Where(x => x.OrderNo == orderNo)
- .ExecuteCommandAsync();
- }
-
- _logger.LogError($"FeedbackOutbound鎴愬姛 - OrderNo: {orderNo}, {JsonSerializer.Serialize(result)}");
- }
- catch (Exception ex)
- {
- _logger.LogError($"FeedbackOutbound澶辫触 - OrderNo: {orderNo}, Error: {ex.Message}");
}
}
@@ -1616,12 +1934,10 @@
{
// 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()))
+ .Where(x => x.StockId == stockId && x.StockQuantity == 0)
.ExecuteCommandAsync();
- await _stockInfoService.Db.Deleteable<Dt_StockInfo>()
- .Where(x => x.Id == stockId).ExecuteCommandAsync();
+ _stockInfoService.DeleteData(stockId);
_logger.LogInformation($"娓呯悊闆跺簱瀛樻槑缁嗚褰� - StockId: {stockId}, 鍒犻櫎璁板綍鏁�: {deleteDetailCount}");
@@ -1641,7 +1957,7 @@
{
try
{
- // 1. 鏌ユ壘鎵�鏈変笌璇ヨ鍗曞拰鎵樼洏鐩稿叧鐨勪换鍔�
+ // 鏌ユ壘鎵�鏈変笌璇ヨ鍗曞拰鎵樼洏鐩稿叧鐨勪换鍔�
var tasks = await _taskRepository.Db.Queryable<Dt_Task>().Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode).ToListAsync();
if (tasks.Any())
@@ -1694,7 +2010,7 @@
_logger.LogInformation($"璁㈠崟 {orderNo} 杩樻湁鍏朵粬鎵樼洏鍦ㄥ鐞嗭紝涓嶆洿鏂拌鍗曠姸鎬�");
}
- // 3. 鏇存柊鎷i�夎褰曠姸鎬侊紙鍙�夛級
+ // 鏇存柊鎷i�夎褰曠姸鎬侊紙鍙�夛級
await UpdatePickingRecordsStatus(orderNo, palletCode);
}
@@ -1732,12 +2048,11 @@
if (outboundOrder != null && allCompleted && outboundOrder.OrderStatus != (int)OutOrderStatusEnum.鍑哄簱瀹屾垚)
{
outboundOrder.OrderStatus = (int)OutOrderStatusEnum.鍑哄簱瀹屾垚;
+ outboundOrder.Operator = App.User.UserName;
await _outboundOrderService.Db.Updateable(outboundOrder).ExecuteCommandAsync();
_logger.LogInformation($"璁㈠崟 {orderNo} 宸叉爣璁颁负鍑哄簱瀹屾垚");
- // 鍚慚ES鍙嶉璁㈠崟瀹屾垚锛堝鏋滈渶瑕侊級
- await HandleOrderCompletion(outboundOrder, orderNo);
}
}
@@ -1755,7 +2070,6 @@
// 杩欓噷鍙互鏍规嵁闇�瑕佹洿鏂版嫞閫夎褰曠殑鐘舵�佸瓧娈�
// 渚嬪锛歱ickingRecord.Status = (int)PickingStatusEnum.宸插畬鎴�;
-
_logger.LogInformation($"鎵惧埌{pickingRecords.Count}鏉℃嫞閫夎褰� - 璁㈠崟: {orderNo}, 鎵樼洏: {palletCode}");
}
@@ -1765,8 +2079,6 @@
}
}
#endregion
-
-
#region 杈呭姪鏂规硶
/// <summary>
@@ -1856,89 +2168,6 @@
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()
{
var seq = await _dailySequenceService.GetNextSequenceAsync();
@@ -1974,6 +2203,8 @@
FactoryArea = originalLock.FactoryArea,
lineNo = originalLock.lineNo,
WarehouseCode = originalLock.WarehouseCode,
+ BarcodeQty = originalLock.BarcodeQty,
+ BarcodeUnit = originalLock.BarcodeUnit,
};
@@ -2048,11 +2279,6 @@
}
}
- private async Task<int> GenerateTaskNumber()
- {
- return await _dailySequenceService.GetNextSequenceAsync();
- }
-
private WebResponseContent CreatePickingResponse(PickingResult result, string adjustedReason)
{
//if (result.SplitResults.Any())
@@ -2078,8 +2304,1092 @@
}
return WebResponseContent.Instance.OK("鎷i�夌‘璁ゆ垚鍔�", new { SplitResults = new List<SplitResult>() });
}
-
#endregion
+
+
+ #region 铏氭嫙鍑哄叆搴�
+ public WebResponseContent GetAvailablePurchaseOrders()
+ {
+ List<Dt_InboundOrder> InOders = _inboundOrderRepository.QueryData().Where(x => x.OrderStatus != InOrderStatusEnum.鍏ュ簱瀹屾垚.ObjToInt()).ToList();
+ List<string> InOderCodes = InOders.Select(x => x.UpperOrderNo).ToList();
+ return WebResponseContent.Instance.OK("鎴愬姛", data: InOderCodes);
+ }
+
+ public WebResponseContent GetAvailablePickingOrders(string outOrder)
+ {
+ Dt_OutboundOrder outboundOrder = Db.Queryable<Dt_OutboundOrder>().Where(x => x.UpperOrderNo == outOrder && x.OrderStatus != OutOrderStatusEnum.鍑哄簱瀹屾垚.ObjToInt()).Includes(x=>x.Details).First();
+ if(outboundOrder == null)
+ {
+ return WebResponseContent.Instance.Error("鏈壘鍒版弧瓒冲嚭搴撴潯浠剁殑鍑哄簱鍗�");
+ }
+ if(outboundOrder.IsBatch == 0)
+ {
+ return WebResponseContent.Instance.Error("璇ュ崟鎹笉灞炰簬鍒嗘壒鍥炰紶鍗曟嵁锛屼笉鍏佽铏氭嫙鍑哄叆搴�");
+ }
+ //鍏堟竻绌哄崟鎹櫄鎷熷嚭鍏ュ簱鏁伴噺杩涜璁$畻
+ foreach (var item in outboundOrder.Details)
+ {
+ item.NoStockOutQty = 0;
+ item.documentsNO = "";
+ }
+ _outboundOrderDetailService.UpdateData(outboundOrder.Details);
+ return WebResponseContent.Instance.OK("鎴愬姛");
+
+ }
+
+ public WebResponseContent BarcodeValidate(NoStockOutModel noStockOut)
+ {
+ try
+ {
+ Dt_InboundOrder inboundOrder = Db.Queryable<Dt_InboundOrder>()
+ .Where(x => x.UpperOrderNo == noStockOut.inOder && x.OrderStatus != InOrderStatusEnum.鍏ュ簱瀹屾垚.ObjToInt())
+ .Includes(x => x.Details)
+ .First();
+ if (inboundOrder == null)
+ {
+ return WebResponseContent.Instance.Error($"鏈壘鍒伴噰璐崟锛歿noStockOut.inOder}");
+ }
+
+ Dt_OutboundOrder outboundOrder = Db.Queryable<Dt_OutboundOrder>()
+ .Where(x => x.UpperOrderNo == noStockOut.outOder && x.OrderStatus != OutOrderStatusEnum.鍑哄簱瀹屾垚.ObjToInt())
+ .Includes(x => x.Details)
+ .First();
+ if (outboundOrder == null)
+ {
+ return WebResponseContent.Instance.Error($"鏈壘鍒板嚭搴撳崟锛歿noStockOut.outOder}");
+ }
+
+ var detailLists = new List<Dt_InboundOrderDetail>();
+ var matchedDetail = inboundOrder.Details.FirstOrDefault(detail =>
+ detail.Barcode == noStockOut.barCode &&
+ detail.OrderDetailStatus != OrderDetailStatusEnum.Over.ObjToInt());
+
+ if (matchedDetail == null)
+ {
+ matchedDetail = inboundOrder.Details.FirstOrDefault(detail =>
+ detail.OutBoxbarcodes == noStockOut.barCode &&
+ detail.OrderDetailStatus != OrderDetailStatusEnum.Over.ObjToInt());
+
+ if (matchedDetail == null)
+ {
+ return WebResponseContent.Instance.Error($"鍦ㄩ噰璐崟 {noStockOut.inOder} 涓湭鎵惧埌鏉$爜涓� {noStockOut.barCode} 鐨勬槑缁嗐��");
+ }
+ else
+ {
+ // 娣诲姞鎵�鏈夊尮閰嶅绠辩爜涓旈潪瀹屾垚鐘舵�佺殑鏄庣粏
+ foreach (var detail in inboundOrder.Details)
+ {
+ if (detail.OrderDetailStatus != OrderDetailStatusEnum.Over.ObjToInt() &&
+ !string.IsNullOrEmpty(detail.Barcode) &&
+ detail.OutBoxbarcodes == noStockOut.barCode)
+ {
+ detailLists.Add(detail);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!string.IsNullOrEmpty(noStockOut.barCode))
+ {
+ detailLists.Add(matchedDetail);
+ }
+ }
+ var outDetails = new List<Dt_OutboundOrderDetail>();
+ // 閬嶅巻姣忎釜鍏ュ簱鏄庣粏
+ foreach (var item in detailLists)
+ {
+ // 閲嶇疆褰撳墠鍏ュ簱鏄庣粏鐨勬棤搴撳瓨鍑哄簱鏁伴噺
+ item.NoStockOutQty = 0;
+
+ // 褰撳墠鏉$爜闇�瑕佸嚭搴撶殑鎬绘暟閲忥紙鍏ュ簱鍗曞墿浣欏彲鍑烘暟閲忥級
+ decimal remainingBarcodeQty = item.OrderQuantity - item.ReceiptQuantity;
+ if (remainingBarcodeQty <= 0)
+ {
+ return WebResponseContent.Instance.Error($"璇ラ噰璐崟涓殑鏉$爜{item.Barcode}瀵瑰簲鐨勫彲鍑烘暟閲忎负0");
+ }
+
+ // 绛涢�夊嚭搴撳崟涓鍚堟潯浠剁殑鏄庣粏锛堝悓鐗╂枡銆侀潪瀹屾垚銆佹湁鍓╀綑鍙嚭鏁伴噺锛�
+ var eligibleOutDetails = outboundOrder.Details.Where(detail =>
+ detail.MaterielCode == item.MaterielCode &&
+ detail.OrderDetailStatus != OrderDetailStatusEnum.Over.ObjToInt() &&
+ (detail.OrderQuantity - detail.LockQuantity - detail.MoveQty - detail.NoStockOutQty) > 0).ToList();
+
+ if (!eligibleOutDetails.Any())
+ {
+ return WebResponseContent.Instance.Error($"鍦ㄥ嚭搴撳崟涓湭鎵惧埌鐗╂枡{item.MaterielCode}鐨勫彲鍑哄簱鏄庣粏");
+ }
+
+ // 閬嶅巻绗﹀悎鏉′欢鐨勫嚭搴撴槑缁嗭紝閫愯鍒嗛厤鏁伴噺
+ foreach (var outDetail in eligibleOutDetails)
+ {
+ // 璁$畻褰撳墠鍑哄簱琛岀殑鍓╀綑鍙嚭鏁伴噺
+ decimal rowRemainingQty = outDetail.OrderQuantity - outDetail.LockQuantity - outDetail.MoveQty - outDetail.NoStockOutQty;
+ if (rowRemainingQty <= 0) continue;
+
+ if (!outDetail.BatchNo.IsNullOrEmpty())
+ {
+ if (outDetail.BatchNo != item.BatchNo)
+ {
+ return WebResponseContent.Instance.Error($"鍑哄簱鍗曡鎵规{outDetail.BatchNo}涓庨噰璐崟鎵规{item.BatchNo}涓嶅尮閰�");
+ }
+ }
+ if (!outDetail.SupplyCode.IsNullOrEmpty())
+ {
+ if (outDetail.SupplyCode != item.SupplyCode)
+ {
+ return WebResponseContent.Instance.Error($"鍑哄簱鍗曡渚涘簲鍟唟outDetail.SupplyCode}涓庨噰璐崟渚涘簲鍟唟item.SupplyCode}涓嶅尮閰�");
+ }
+ }
+ if (!string.IsNullOrEmpty(outboundOrder.FactoryArea) && !string.IsNullOrEmpty(inboundOrder.FactoryArea))
+ {
+ if (inboundOrder.FactoryArea != outboundOrder.FactoryArea)
+ {
+ return WebResponseContent.Instance.Error($"璇ユ潯鐮亄item.Barcode}瀵瑰簲鐨勫崟鎹巶鍖轰笌鍑哄簱鍗曟嵁涓嶄竴鑷达紒涓嶅厑璁稿嚭搴撱��");
+ }
+ }
+ if (inboundOrder.BusinessType != "11" && !outDetail.WarehouseCode.IsNullOrEmpty())
+ {
+ if (outDetail.WarehouseCode != item.WarehouseCode)
+ {
+ return WebResponseContent.Instance.Error($"浠撳簱涓嶄竴鑷达紒鍑哄簱鍗曡浠撳簱{outDetail.WarehouseCode}涓庨噰璐崟浠撳簱{item.WarehouseCode}涓嶅尮閰�");
+ }
+ }
+ else
+ {
+ item.WarehouseCode = outDetail.WarehouseCode;
+ }
+
+ // 璁$畻鏈鍒嗛厤鐨勬暟閲忥紙鍙栧墿浣欐潯鐮佹暟閲忓拰褰撳墠琛屽墿浣欐暟閲忕殑杈冨皬鍊硷級
+ decimal assignQty = Math.Min(remainingBarcodeQty, rowRemainingQty);
+
+ // 鏇存柊鍏ュ簱鏄庣粏鍜屽嚭搴撴槑缁嗙殑鏃犲簱瀛樺嚭搴撴暟閲�
+ item.NoStockOutQty += assignQty;
+ outDetail.NoStockOutQty += assignQty;
+
+ // 鏇存柊鍓╀綑闇�瑕佸垎閰嶇殑鏉$爜鏁伴噺
+ remainingBarcodeQty -= assignQty;
+
+ // 璁板綍宸叉洿鏂扮殑鍑哄簱鏄庣粏锛堝幓閲嶏級
+ if (!outDetails.Contains(outDetail))
+ {
+ outDetails.Add(outDetail);
+ }
+
+ // 楠岃瘉褰撳墠琛屾槸鍚︽孩鍑�
+ if ((outDetail.LockQuantity + outDetail.NoStockOutQty + outDetail.MoveQty) > outDetail.OrderQuantity)
+ {
+ return WebResponseContent.Instance.Error($"鍑哄簱鍗曟槑缁唟outDetail.Id}鏁伴噺婧㈠嚭锛岃秴鍑烘暟閲忥細{(outDetail.LockQuantity + outDetail.NoStockOutQty + outDetail.MoveQty) - outDetail.OrderQuantity}");
+ }
+
+ // 澶勭悊MES鍙傛暟鍥炰紶锛氳褰曞綋鍓嶆潯鐮佸垎閰嶅埌璇ヨ鐨勫疄闄呮暟閲�
+ List<Barcodes> barcodesList = new List<Barcodes>();
+ Barcodes barcodes = new Barcodes
+ {
+ Barcode = item.Barcode,
+ Qty = assignQty,
+ SupplyCode = item?.SupplyCode ?? "",
+ BatchNo = item?.BatchNo ?? "",
+ Unit = item?.Unit ?? ""
+ };
+ // 鍙嶅簭鍒楀寲璇ヨ宸叉湁鐨勬潯鐮佽褰�
+ if (!string.IsNullOrEmpty(outDetail.documentsNO))
+ {
+ try
+ {
+ barcodesList = JsonConvert.DeserializeObject<List<Barcodes>>(outDetail.documentsNO) ?? new List<Barcodes>();
+ }
+ catch (JsonException ex)
+ {
+ return WebResponseContent.Instance.Error($"鍑哄簱鍗曟槑缁唟outDetail.Id}鐨刣ocumentsNO瀛楁鏍煎紡閿欒锛歿ex.Message}");
+ }
+ }
+ // 娣诲姞鏈鍒嗛厤鐨勮褰�
+ barcodesList.Add(barcodes);
+ // 搴忓垪鍖栧洖瀛�
+ JsonSerializerSettings settings = new JsonSerializerSettings
+ {
+ ContractResolver = new CamelCasePropertyNamesContractResolver()
+ };
+ outDetail.documentsNO = JsonConvert.SerializeObject(barcodesList, settings);
+
+ // 鏉$爜鏁伴噺鍒嗛厤瀹屾瘯锛岄��鍑哄綋鍓嶈寰幆
+ if (remainingBarcodeQty <= 0)
+ {
+ break;
+ }
+ }
+
+ // 鎵�鏈夌鍚堟潯浠剁殑鍑哄簱琛岄亶鍘嗗畬鍚庯紝鏉$爜鏁伴噺浠嶆湁鍓╀綑
+ if (remainingBarcodeQty > 0)
+ {
+ return WebResponseContent.Instance.Error($"鏉$爜{item.Barcode}闇�鍑哄簱鏁伴噺{item.OrderQuantity - item.ReceiptQuantity}锛屼絾鍑哄簱鍗曚腑鐗╂枡{item.MaterielCode}鍓╀綑鍙嚭鎬婚噺涓嶈冻锛屼粛鍓╀綑{remainingBarcodeQty}鏁伴噺鏈垎閰�");
+ }
+ }
+
+ _unitOfWorkManage.BeginTran();
+ _inboundOrderDetailService.UpdateData(detailLists);
+ _outboundOrderDetailService.UpdateData(outDetails);
+ _unitOfWorkManage.CommitTran();
+
+ return WebResponseContent.Instance.OK("鎴愬姛", data: detailLists);
+ }
+ catch (Exception ex)
+ {
+ _unitOfWorkManage.RollbackTran();
+ return WebResponseContent.Instance.Error(ex.Message);
+ }
+ }
+
+
+ public WebResponseContent DeleteBarcode(NoStockOutModel noStockOut)
+ {
+ try
+ {
+ Dt_InboundOrder inboundOrder = Db.Queryable<Dt_InboundOrder>()
+ .Where(x => x.UpperOrderNo == noStockOut.inOder && x.OrderStatus != InOrderStatusEnum.鍏ュ簱瀹屾垚.ObjToInt())
+ .Includes(x => x.Details)
+ .First();
+ if (inboundOrder == null)
+ {
+ return WebResponseContent.Instance.Error($"鏈壘鍒伴噰璐崟锛歿noStockOut.inOder}");
+ }
+
+ var matchedDetail = inboundOrder.Details.FirstOrDefault(detail =>
+ detail.Barcode == noStockOut.barCode &&
+ detail.OrderDetailStatus != OrderDetailStatusEnum.Over.ObjToInt());
+
+ if (matchedDetail == null)
+ {
+ return WebResponseContent.Instance.Error($"鍦ㄩ噰璐崟 {noStockOut.inOder} 涓湭鎵惧埌鏉$爜涓� {noStockOut.barCode} 鐨勬槑缁嗐��");
+ }
+
+ // 閲嶇疆鍏ュ簱鏄庣粏鐨勬棤搴撳瓨鍑哄簱鏁伴噺
+ decimal revokedTotalQty = matchedDetail.NoStockOutQty; // 璁板綍闇�瑕佹挙閿�鐨勬�绘暟閲忥紙鍏ュ簱鍗曚腑宸插垎閰嶇殑鏁伴噺锛�
+ matchedDetail.NoStockOutQty = 0;
+ if(inboundOrder.BusinessType == "11")
+ {
+ matchedDetail.WarehouseCode ="";
+ }
+
+ // 閲嶇疆鍏ュ簱鏄庣粏鐘舵��
+ if (matchedDetail.ReceiptQuantity == 0 && matchedDetail.OverInQuantity == 0)
+ {
+ matchedDetail.OrderDetailStatus = OrderDetailStatusEnum.New.ObjToInt();
+ }
+
+ Dt_OutboundOrder outboundOrder = Db.Queryable<Dt_OutboundOrder>()
+ .Where(x => x.UpperOrderNo == noStockOut.outOder && x.OrderStatus != OutOrderStatusEnum.鍑哄簱瀹屾垚.ObjToInt())
+ .Includes(x => x.Details)
+ .First();
+ if (outboundOrder == null)
+ {
+ return WebResponseContent.Instance.Error($"鏈壘鍒板嚭搴撳崟锛歿noStockOut.outOder}");
+ }
+
+ // 鎵惧埌鎵�鏈夊叧鑱旇鏉$爜鐨勫嚭搴撴槑缁嗚
+ // 鍚岀墿鏂欍�侀潪瀹屾垚鐘舵�併�乨ocumentsNO鍖呭惈璇ユ潯鐮�
+ var matchedCodeList = outboundOrder.Details.Where(detail =>
+ detail.MaterielCode == matchedDetail.MaterielCode && // 纭繚鐗╂枡鍖归厤
+ detail.OrderDetailStatus != OrderDetailStatusEnum.Over.ObjToInt() &&
+ !string.IsNullOrEmpty(detail.documentsNO) &&
+ detail.documentsNO.Contains(noStockOut.barCode) // 鍖呭惈褰撳墠鏉$爜
+ ).ToList();
+
+ if (!matchedCodeList.Any())
+ {
+ return WebResponseContent.Instance.Error($"鍦ㄥ嚭搴撳崟涓湭鎵惧埌鍏宠仈鏉$爜{noStockOut.barCode}鐨勭墿鏂檣matchedDetail.MaterielCode}鏄庣粏銆�");
+ }
+
+ //閫愯澶勭悊鍑哄簱鏄庣粏鐨勬挙閿�閫昏緫
+ decimal remainingRevokeQty = revokedTotalQty; // 鍓╀綑闇�瑕佹挙閿�鐨勬暟閲�
+ foreach (var matchedCode in matchedCodeList)
+ {
+ if (remainingRevokeQty <= 0) break; // 鎵�鏈夋暟閲忓凡鎾ら攢锛岄��鍑哄惊鐜�
+
+ // 澶勭悊MES鍙傛暟鎾ら攢
+ List<Barcodes> barcodesList = new List<Barcodes>();
+ if (!string.IsNullOrEmpty(matchedCode.documentsNO))
+ {
+ try
+ {
+ barcodesList = JsonConvert.DeserializeObject<List<Barcodes>>(matchedCode.documentsNO) ?? new List<Barcodes>();
+ }
+ catch (JsonException ex)
+ {
+ return WebResponseContent.Instance.Error($"鍑哄簱鍗曟槑缁唟matchedCode.Id}鐨刣ocumentsNO瀛楁鏍煎紡閿欒锛歿ex.Message}");
+ }
+ }
+
+ // 绛涢�夊嚭褰撳墠鏉$爜鐨勬墍鏈夎褰�
+ var barcodeRecords = barcodesList.Where(b =>
+ string.Equals(b.Barcode, noStockOut.barCode, StringComparison.OrdinalIgnoreCase)).ToList();
+ if (!barcodeRecords.Any()) continue;
+
+ // 璁$畻璇ヨ闇�瑕佹挙閿�鐨勬暟閲忥紙绱姞璇ユ潯鐮佸湪璇ヨ鐨勬墍鏈夊垎閰嶆暟閲忥級
+ decimal rowRevokeQty = barcodeRecords.Sum(b => b.Qty);
+ // 瀹為檯鎾ら攢鏁伴噺锛氬彇璇ヨ鍙挙閿�鏁伴噺鍜屽墿浣欓渶瑕佹挙閿�鏁伴噺鐨勮緝灏忓��
+ decimal actualRevokeQty = Math.Min(rowRevokeQty, remainingRevokeQty);
+
+ // 绉婚櫎璇ヨ涓鏉$爜鐨勮褰曪紙鎴栭儴鍒嗚褰曪紝鑻ュ墿浣欐挙閿�鏁伴噺涓嶈冻锛�
+ if (actualRevokeQty < rowRevokeQty)
+ {
+ // 鍓╀綑鎾ら攢鏁伴噺涓嶈冻锛屽彧绉婚櫎閮ㄥ垎璁板綍锛堟寜鏁伴噺鎵e噺锛�
+ decimal tempQty = actualRevokeQty;
+ var removeList = new List<Barcodes>();
+ foreach (var record in barcodeRecords)
+ {
+ if (tempQty <= 0) break;
+ if (record.Qty <= tempQty)
+ {
+ removeList.Add(record);
+ tempQty -= record.Qty;
+ }
+ else
+ {
+ // 璁板綍鏁伴噺鎷嗗垎锛屾墸鍑忛儴鍒嗘暟閲�
+ record.Qty -= tempQty;
+ tempQty = 0;
+ }
+ }
+ barcodesList.RemoveAll(b => removeList.Contains(b));
+ }
+ else
+ {
+ // 绉婚櫎璇ヨ涓鏉$爜鐨勬墍鏈夎褰�
+ barcodesList.RemoveAll(b =>
+ string.Equals(b.Barcode, noStockOut.barCode, StringComparison.OrdinalIgnoreCase));
+ }
+
+ //閲嶆柊搴忓垪鍖朚ES鍙傛暟
+ JsonSerializerSettings settings = new JsonSerializerSettings
+ {
+ ContractResolver = new CamelCasePropertyNamesContractResolver()
+ };
+ matchedCode.documentsNO = JsonConvert.SerializeObject(barcodesList, settings);
+
+ //鎵e噺鍑哄簱鏄庣粏鐨勬棤搴撳瓨鍑哄簱鏁伴噺
+ matchedCode.NoStockOutQty = Math.Max(0, matchedCode.NoStockOutQty - actualRevokeQty);
+ remainingRevokeQty -= actualRevokeQty;
+
+ //閲嶇疆鍑哄簱鏄庣粏鐘舵��
+ if (matchedCode.LockQuantity == 0 && matchedCode.OverOutQuantity == 0)
+ {
+ matchedCode.OrderDetailStatus = OrderDetailStatusEnum.New.ObjToInt();
+ }
+ }
+
+ //鑻ヤ粛鏈夋湭鎾ら攢鐨勬暟閲忥紝璇存槑鏁版嵁涓嶄竴鑷�
+ if (remainingRevokeQty > 0)
+ {
+ return WebResponseContent.Instance.Error($"鎾ら攢鏉$爜{noStockOut.barCode}鏃讹紝鍑哄簱鍗曚腑鍙挙閿�鏁伴噺涓嶈冻锛屼粛鏈墈remainingRevokeQty}鏁伴噺鏈挙閿�");
+ }
+
+ _unitOfWorkManage.BeginTran();
+ _inboundOrderDetailService.UpdateData(matchedDetail);
+ _outboundOrderDetailService.UpdateData(matchedCodeList);
+ _unitOfWorkManage.CommitTran();
+
+ return WebResponseContent.Instance.OK("鏉$爜鎾ら攢鎴愬姛", data: new { RevokedQty = revokedTotalQty });
+ }
+ catch (Exception ex)
+ {
+ _unitOfWorkManage.RollbackTran();
+ return WebResponseContent.Instance.Error(ex.Message);
+ }
+ }
+
+ public async Task<WebResponseContent> NoStockOutSubmit(NoStockOutSubmit noStockOutSubmit)
+ {
+ try
+ {
+ Dt_OutboundOrder outboundOrder = _inboundOrderRepository.Db.Queryable<Dt_OutboundOrder>().Where(x => x.UpperOrderNo == noStockOutSubmit.OutOderSubmit && x.OrderStatus != OutOrderStatusEnum.鍑哄簱瀹屾垚.ObjToInt()).Includes(x => x.Details).First();
+ if (outboundOrder == null)
+ {
+ return WebResponseContent.Instance.Error($"鏈壘鍒板嚭搴撳崟锛歿noStockOutSubmit.OutOderSubmit}");
+ }
+
+ List<Dt_OutboundOrderDetail> outboundOrderDetails = new List<Dt_OutboundOrderDetail>();
+
+ Dictionary<int, List<string>> orderIdBarCodeDict = new Dictionary<int, List<string>>();
+
+ List<Dt_InboundOrderDetail> updateInboundDetails = new List<Dt_InboundOrderDetail>();
+
+ Dictionary<int, Dt_InboundOrder> updateInboundOrders = new Dictionary<int, Dt_InboundOrder>();
+
+ List<Dt_StockQuantityChangeRecord> changeRecords = new List<Dt_StockQuantityChangeRecord>();
+ _unitOfWorkManage.BeginTran();
+
+ List<Dt_InboundOrderDetail> allInboundDetails = _inboundOrderDetailService.Db
+ .Queryable<Dt_InboundOrderDetail>()
+ .Where(detail => noStockOutSubmit.BarCodeSubmit.Contains(detail.Barcode)
+ && detail.OrderDetailStatus != OrderDetailStatusEnum.Over.ObjToInt())
+ .ToList();
+
+ var detailGroupByOrderId = allInboundDetails.GroupBy(d => d.OrderId).ToList();
+ foreach (var group in detailGroupByOrderId)
+ {
+ int orderId = group.Key;
+ List<Dt_InboundOrderDetail> groupDetails = group.ToList();
+ List<string> groupBarCodes = groupDetails.Select(d => d.Barcode).ToList();
+
+ orderIdBarCodeDict[orderId] = groupBarCodes;
+
+ Dt_InboundOrder currentInboundOrder = null;
+ if (!updateInboundOrders.TryGetValue(orderId, out currentInboundOrder))
+ {
+ currentInboundOrder = _inboundOrderRepository.Db
+ .Queryable<Dt_InboundOrder>()
+ .Where(x => x.Id == orderId)
+ .Includes(x => x.Details)
+ .First();
+
+ if (currentInboundOrder == null)
+ {
+ _unitOfWorkManage.RollbackTran();
+ return WebResponseContent.Instance.Error($"鏈壘鍒板叆搴撳崟ID涓� {orderId} 鐨勫崟鎹�");
+ }
+ updateInboundOrders[orderId] = currentInboundOrder;
+ }
+
+ foreach (var detail in groupDetails)
+ {
+ detail.ReceiptQuantity = detail.NoStockOutQty;
+ detail.OverInQuantity = detail.NoStockOutQty;
+
+ if (detail.OrderQuantity == detail.OverInQuantity)
+ {
+ detail.OrderDetailStatus = OrderDetailStatusEnum.Over.ObjToInt();
+ }
+ updateInboundDetails.Add(detail);
+
+ //娣诲姞搴撳瓨鍙樺姩璁板綍
+ Dt_StockQuantityChangeRecord changeRecord = new Dt_StockQuantityChangeRecord
+ {
+ StockDetailId = detail.Id,
+ PalleCode = DateTime.Now.ToString(),
+ MaterielCode = detail.MaterielCode,
+ MaterielName = detail.MaterielName ?? "",
+ BatchNo = detail.BatchNo ?? "",
+ OriginalSerilNumber = detail.Barcode,
+ NewSerilNumber = "",
+ OrderNo = currentInboundOrder.InboundOrderNo,
+ TaskNum = 0,
+ ChangeType = (int)StockChangeTypeEnum.Inbound,
+ ChangeQuantity = detail.NoStockOutQty,
+ BeforeQuantity = detail.OverInQuantity - detail.NoStockOutQty,
+ AfterQuantity = detail.OverInQuantity,
+ SupplyCode = detail.SupplyCode ?? "",
+ WarehouseCode = detail.WarehouseCode ?? "",
+ Remark = $"铏氭嫙鍏ュ簱"
+ };
+ changeRecords.Add(changeRecord);
+ }
+
+ var inboundOrder = updateInboundOrders[orderId];
+ int totalDetailCount = inboundOrder.Details.Count;
+
+ int finishedDetailCount = inboundOrder.Details.Count(x => x.OrderDetailStatus == OrderDetailStatusEnum.Over.ObjToInt())
+ + groupDetails.Count(x => x.OrderDetailStatus == OrderDetailStatusEnum.Over.ObjToInt());
+
+ inboundOrder.OrderStatus = totalDetailCount == finishedDetailCount
+ ? InOrderStatusEnum.鍏ュ簱瀹屾垚.ObjToInt()
+ : InOrderStatusEnum.鍏ュ簱涓�.ObjToInt();
+ }
+
+ if (updateInboundDetails.Any())
+ {
+ _inboundOrderDetailService.Db.Updateable(updateInboundDetails).ExecuteCommand();
+ }
+ if (updateInboundOrders.Any())
+ {
+ // 鎵归噺鏇存柊鍏ュ簱涓诲崟
+ _inboundOrderService.Db.Updateable(updateInboundOrders.Values.ToList()).ExecuteCommand();
+ }
+
+ // 7. 寰幆鍒嗙粍缁撴灉锛岃皟鐢∕ES鍥炰紶鏂规硶锛堟寜鍏ュ簱鍗曞垎缁勫洖浼狅級
+ foreach (var kvp in orderIdBarCodeDict)
+ {
+ int orderId = kvp.Key;
+ List<string> barCodeList = kvp.Value;
+ //鍏ュ簱鍥炰紶MES
+ NoStockOutBatchInOrderFeedbackToMes(orderId, barCodeList);
+ }
+
+ //鍙鍑哄簱鏉$爜鐨勫嚭搴撳崟鏄庣粏杩涜璁$畻鍥炰紶
+ List<Dt_OutboundOrderDetail> outboundOrderDetail = outboundOrder.Details
+ .Where(x => !string.IsNullOrWhiteSpace(x.documentsNO)
+ && noStockOutSubmit.BarCodeSubmit.Any(barcode =>
+ x.documentsNO.IndexOf(barcode, StringComparison.OrdinalIgnoreCase) >= 0))
+ .ToList();
+
+ foreach (var item in outboundOrderDetail)
+ {
+ item.LockQuantity += item.NoStockOutQty;
+ item.OverOutQuantity += item.NoStockOutQty;
+ item.CurrentDeliveryQty += item.NoStockOutQty;
+ //娣诲姞鍥炰紶MES鍙傛暟
+ List<Barcodes> barcodesList = new List<Barcodes>();
+ List<Barcodes> documentsNOList = new List<Barcodes>();
+ if (!string.IsNullOrEmpty(item.ReturnJsonData))
+ {
+ barcodesList = JsonConvert.DeserializeObject<List<Barcodes>>(item.ReturnJsonData) ?? new List<Barcodes>();
+ }
+ if (!string.IsNullOrEmpty(item.documentsNO) && item.documentsNO!="")
+ {
+ documentsNOList = JsonConvert.DeserializeObject<List<Barcodes>>(item.documentsNO) ?? new List<Barcodes>();
+ }
+ foreach (var documentsNO in documentsNOList)
+ {
+ barcodesList.Add(documentsNO);
+ }
+ JsonSerializerSettings settings = new JsonSerializerSettings
+ {
+ ContractResolver = new CamelCasePropertyNamesContractResolver()
+ };
+ item.ReturnJsonData = JsonConvert.SerializeObject(barcodesList, settings);
+ //娣诲姞搴撳瓨鍙樺姩璁板綍
+ Dt_StockQuantityChangeRecord changeRecord = new Dt_StockQuantityChangeRecord
+ {
+ StockDetailId = item.Id,
+ PalleCode = DateTime.Now.ToString(),
+ MaterielCode = item.MaterielCode,
+ MaterielName = item.MaterielName ?? "",
+ BatchNo = item.BatchNo ?? "",
+ OriginalSerilNumber = item.ReturnJsonData,
+ NewSerilNumber = "",
+ OrderNo = outboundOrder.OrderNo,
+ TaskNum = 0,
+ ChangeType = (int)StockChangeTypeEnum.Inbound,
+ ChangeQuantity = -item.NoStockOutQty,
+ BeforeQuantity = item.OrderQuantity,
+ AfterQuantity = item.OrderQuantity - item.OverOutQuantity,
+ SupplyCode = item.SupplyCode ?? "",
+ WarehouseCode = item.WarehouseCode ?? "",
+ Remark = $"铏氭嫙鍑哄簱"
+ };
+ changeRecords.Add(changeRecord);
+ outboundOrderDetails.Add(item);
+ }
+
+ _outboundOrderDetailService.UpdateData(outboundOrderDetails);
+ //鎵归噺娣诲姞搴撳瓨鍙樺姩璁板綍
+ if (changeRecords.Any())
+ {
+ _stockQuantityChangeRecordService.Db.Insertable(changeRecords).ExecuteCommand();
+ }
+ // 妫�鏌ュ嚭搴撳崟鏄惁瀹屾垚
+ if (CheckOutboundOrderCompleted(outboundOrder.OrderNo))
+ {
+ outboundOrder.OrderStatus = OutOrderStatusEnum.鍑哄簱瀹屾垚.ObjToInt();
+
+ }
+ else
+ {
+ outboundOrder.OrderStatus = OutOrderStatusEnum.鍑哄簱涓�.ObjToInt();
+ }
+ _outboundOrderService.UpdateData(outboundOrder);
+ _unitOfWorkManage.CommitTran();
+ //鍑哄簱鍥炰紶MES
+ _feedbackMesService.OutboundFeedback(outboundOrder.OrderNo);
+
+ return WebResponseContent.Instance.OK();
+ }
+ catch (Exception ex)
+ {
+ _unitOfWorkManage.RollbackTran();
+ return WebResponseContent.Instance.Error(ex.Message);
+ }
+ }
+
+
+ public WebResponseContent NoStockOutBatchInOrderFeedbackToMes(int id,List<string> barCodeList)
+ {
+ WebResponseContent content = new WebResponseContent();
+ try
+ {
+ var inboundOrder = _inboundOrderRepository.Db.Queryable<Dt_InboundOrder>()
+ .Where(x => x.Id == id)
+ .First();
+
+ List<Dt_MesReturnRecord> returnRecords = _mesReturnRecord.QueryData(x => x.OrderNo == inboundOrder.InboundOrderNo && x.OrderId == inboundOrder.Id && x.ReturnStatus == 2);
+ foreach (var item in returnRecords)
+ {
+ HttpResponseResult<MesResponseDTO> httpResponse = _httpClientHelper.Post<MesResponseDTO>(item.ApiUrl, item.RequestData);
+ item.ReturnCount += 1;
+ bool success = httpResponse.IsSuccess && httpResponse.Data.Code == "200";
+ item.ReturnStatus = success ? 1 : 2;
+ item.HttpStatusCode = httpResponse.StatusCode.ObjToInt();
+ item.LastReturnTime = DateTime.Now;
+ item.ResponseData = httpResponse.Content;
+ item.SuccessTime = httpResponse.IsSuccess ? DateTime.Now : null;
+
+ //List<Dt_InboundOrderDetail> details=new List<Dt_InboundOrderDetail>();
+ //foreach (var y in item.DetailsId.Split(','))
+ //{
+ // details.Add( _inboundOrderDetailRepository.QueryFirst(x => x.Id == Convert.ToInt32(y)));
+ //}
+ }
+ _mesReturnRecord.UpdateData(returnRecords);
+
+ var inboundOrderDetail = _inboundOrderRepository.Db.Queryable<Dt_InboundOrderDetail>()
+ .Where(x => x.OrderId == inboundOrder.Id && x.OrderDetailStatus == (int)OrderDetailStatusEnum.Over && x.ReturnToMESStatus == 0)
+ .ToList();
+
+ var detail = inboundOrderDetail.Where(x => barCodeList.Contains(x.Barcode)).ToList();
+
+ if (inboundOrder.OrderType == (int)InOrderTypeEnum.AllocatInbound)//璋冩嫧鍏ュ簱
+ {
+ var allocate = _inboundOrderRepository.Db.Queryable<Dt_AllocateOrder>().Where(x => x.OrderNo == inboundOrder.InboundOrderNo).First();
+ var allocatefeedmodel = new AllocateDto
+ {
+ ReqCode = Guid.NewGuid().ToString(),
+ ReqTime = DateTime.Now.ToString(),
+ BusinessType = "3",
+ FactoryArea = inboundOrder.FactoryArea,
+ OperationType = 1,
+ Operator = App.User.UserName,
+ OrderNo = inboundOrder.UpperOrderNo,
+ fromWarehouse = allocate?.FromWarehouse ?? "",
+ toWarehouse = allocate?.ToWarehouse ?? "",
+ Details = NoStockOutGetAllocateDtoDetails(detail)
+ };
+
+ if (allocatefeedmodel.Details.Count <= 0)
+ {
+ throw new Exception("鏈壘鍒伴渶瑕佸洖浼犵殑鏁版嵁");
+ }
+
+ var response = NoStockOutresponseModel(inboundOrder, 3, null, allocatefeedmodel);
+
+ if (response != null && response.IsSuccess)
+ {
+ _inboundOrderRepository.Db.Updateable<Dt_InboundOrderDetail>().SetColumns(it => new Dt_InboundOrderDetail { ReturnToMESStatus = 1 })
+ .Where(it => it.OrderId == inboundOrder.Id && barCodeList.Contains(it.Barcode)).ExecuteCommand();
+ _inboundOrderRepository.Db.Updateable<Dt_InboundOrder>().SetColumns(it => new Dt_InboundOrder { ReturnToMESStatus = 1 })
+ .Where(it => it.Id == inboundOrder.Id).ExecuteCommand();
+ }
+ else
+ {
+ _inboundOrderRepository.Db.Updateable<Dt_InboundOrderDetail>().SetColumns(it => new Dt_InboundOrderDetail { ReturnToMESStatus = 2 })
+ .Where(it => it.OrderId == inboundOrder.Id && barCodeList.Contains(it.Barcode)).ExecuteCommand();
+ _inboundOrderRepository.Db.Updateable<Dt_InboundOrder>().SetColumns(it => new Dt_InboundOrder { ReturnToMESStatus =2})
+ .Where(it => it.Id == inboundOrder.Id).ExecuteCommand();
+ return content.Error("鍥炰紶MES澶辫触");
+ }
+ }
+ else
+ {
+ var feedmodel = new FeedbackInboundRequestModel
+ {
+ reqCode = Guid.NewGuid().ToString(),
+ reqTime = DateTime.Now.ToString(),
+ business_type = inboundOrder.BusinessType,
+ factoryArea = inboundOrder.FactoryArea,
+ operationType = 1,
+ Operator = App.User.UserName,
+ orderNo = inboundOrder.UpperOrderNo,
+ status = inboundOrder.OrderStatus,
+ details = NoStockOutFeedbackInboundDetailsModelDto(detail)
+ };
+
+ if (feedmodel.details.Count <= 0)
+ {
+ throw new Exception("鏈壘鍒伴渶瑕佸洖浼犵殑鏁版嵁");
+ }
+ var response = NoStockOutresponseModel(inboundOrder, 3, feedmodel);
+
+ if (response != null && response.IsSuccess)
+ {
+ _inboundOrderRepository.Db.Updateable<Dt_InboundOrderDetail>().SetColumns(it => new Dt_InboundOrderDetail { ReturnToMESStatus = 1 })
+ .Where(it => it.OrderId == inboundOrder.Id && barCodeList.Contains(it.Barcode)).ExecuteCommand();
+ _inboundOrderRepository.Db.Updateable<Dt_InboundOrder>().SetColumns(it => new Dt_InboundOrder { ReturnToMESStatus = 1 })
+ .Where(it => it.Id == inboundOrder.Id).ExecuteCommand();
+ }
+ else
+ {
+ _inboundOrderRepository.Db.Updateable<Dt_InboundOrderDetail>().SetColumns(it => new Dt_InboundOrderDetail { ReturnToMESStatus = 2 }).Where(it => it.OrderId == inboundOrder.Id && barCodeList.Contains(it.Barcode)).ExecuteCommand();
+ _inboundOrderRepository.Db.Updateable<Dt_InboundOrder>().SetColumns(it => new Dt_InboundOrder { ReturnToMESStatus = 2 })
+ .Where(it => it.Id == inboundOrder.Id).ExecuteCommand();
+ return content.Error("鍥炰紶MES澶辫触");
+ }
+ }
+
+ return content.OK("鍥炰紶MES鎴愬姛");
+ }
+ catch (Exception ex)
+ {
+ return content.Error(ex.Message);
+ }
+ }
+
+ public List<AllocateDtoDetail> NoStockOutGetAllocateDtoDetails(List<Dt_InboundOrderDetail> inboundOrderDetails)
+ {
+ var groupedData = inboundOrderDetails.GroupBy(item => new { item.MaterielCode, item.lineNo, item.BarcodeUnit, item.WarehouseCode })
+ .Select(group => new AllocateDtoDetail
+ {
+ MaterialCode = group.Key.MaterielCode,
+ LineNo = group.Key.lineNo,
+ WarehouseCode = group.Key.WarehouseCode,
+ Qty = group.Sum(x => x.BarcodeQty),
+ Unit = group.Key.BarcodeUnit,
+ Barcodes = group.Select(row => new BarcodeInfo
+ {
+ Barcode = row.Barcode,
+ Qty = row.BarcodeQty,
+ BatchNo = row.BatchNo,
+ SupplyCode = row.SupplyCode,
+ Unit = row.BarcodeUnit
+ }).ToList()
+ }).ToList();
+ return groupedData;
+ }
+ public List<FeedbackInboundDetailsModel> NoStockOutFeedbackInboundDetailsModelDto(List<Dt_InboundOrderDetail> inboundOrderDetails )
+ {
+ var groupedData = inboundOrderDetails.GroupBy(item => new { item.MaterielCode, item.lineNo, item.BarcodeUnit, item.WarehouseCode })
+ .Select(group => new FeedbackInboundDetailsModel
+ {
+ materialCode = group.Key.MaterielCode,
+ lineNo = group.Key.lineNo,
+ warehouseCode = group.Key.WarehouseCode,
+ qty = group.Sum(x => x.BarcodeQty),
+ unit = group.Key.BarcodeUnit,
+ barcodes = group.Select(row => new FeedbackBarcodesModel
+ {
+ barcode = row.Barcode,
+ qty = row.BarcodeQty
+ }).ToList()
+ }).ToList();
+ return groupedData;
+ }
+
+ public HttpResponseResult<MesResponseDTO> NoStockOutresponseModel(Dt_InboundOrder order, int InterfaceType, FeedbackInboundRequestModel model = null, AllocateDto allocateDto = null)
+ {
+ HttpResponseResult<MesResponseDTO> httpResponseResult = new HttpResponseResult<MesResponseDTO>();
+ string reqCode = Guid.NewGuid().ToString();
+ string reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
+ string requestData = string.Empty;
+ string apiUrl = string.Empty;
+ if (model != null)
+ {
+ apiUrl = AppSettings.GetValue("AldMaterialWarehousing");
+ httpResponseResult = _httpClientHelper.Post<MesResponseDTO>(apiUrl, model.Serialize());
+ requestData = model.Serialize();
+ }
+ else
+ {
+ apiUrl = AppSettings.GetValue("AldAllocationOperation");
+ httpResponseResult = _httpClientHelper.Post<MesResponseDTO>(apiUrl, allocateDto.Serialize());
+ requestData = allocateDto.Serialize();
+ }
+ httpResponseResult.ApiUrl = apiUrl;
+ bool isSuccess = httpResponseResult.IsSuccess && httpResponseResult.Data.Code == "200";
+ string message = "鎴愬姛";
+ if (!isSuccess)
+ {
+ if (!httpResponseResult.IsSuccess)
+ {
+ message = $"MES鎺ュ彛杩斿洖閿欒锛孒TTP浠g爜锛歿httpResponseResult.StatusCode}锛屼俊鎭細{httpResponseResult.ErrorMessage}";
+ }
+ else if (httpResponseResult?.Data?.Code != "200")
+ {
+ message = $"璋冪敤MES鎺ュ彛澶辫触锛屼唬鐮侊細{httpResponseResult?.Data?.Code}锛屼俊鎭細{httpResponseResult?.Data?.Message}";
+ }
+ }
+ Dt_MesReturnRecord mesReturnRecord = new Dt_MesReturnRecord()
+ {
+ ApiUrl = httpResponseResult.ApiUrl,
+ InterfaceType = InterfaceType,
+ OrderId = order.Id,
+ OrderNo = order.InboundOrderNo,
+ RequestCode = reqCode,
+ RequestData = requestData,
+ FailureReason = message,
+ LastReturnTime = DateTime.Now,
+ HttpStatusCode = httpResponseResult.StatusCode.ObjToInt(),
+ ResponseData = httpResponseResult.Content,
+ ReturnType = 0,
+ ReturnCount = 1,
+ ReturnStatus = httpResponseResult.IsSuccess ? 1 : 2,
+ SuccessTime = httpResponseResult.IsSuccess ? DateTime.Now : null
+ };
+ _unitOfWorkManage.Db.Insertable(mesReturnRecord).ExecuteCommand();
+
+ return httpResponseResult;
+ }
+ public bool CheckOutboundOrderCompleted(string orderNo)
+ {
+ Dt_OutboundOrder outboundOrder = _outboundOrderService.Db.Queryable<Dt_OutboundOrder>().Where(x => x.OrderNo == orderNo).First();
+ if (outboundOrder == null) return false;
+
+ List<Dt_OutboundOrderDetail> details = _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>().Where(x => x.OrderId == outboundOrder.Id).ToList();
+
+ // 妫�鏌ユ墍鏈夋槑缁嗙殑宸插嚭鏁伴噺鏄惁閮界瓑浜庡崟鎹暟閲�
+ return details.All(x => x.OverOutQuantity >= x.OrderQuantity - x.MoveQty);
+ }
+
+ public WebResponseContent GetPurchaseOrderByBarcode(string barcode)
+ {
+ try
+ {
+ Dt_InboundOrderDetail inboundOrderDetail = _stockInfoDetailService.Db.Queryable<Dt_InboundOrderDetail>().Where(x => x.Barcode == barcode && x.OrderDetailStatus != OrderDetailStatusEnum.Over.ObjToInt()).First();
+ if (inboundOrderDetail == null)
+ {
+ inboundOrderDetail = _stockInfoDetailService.Db.Queryable<Dt_InboundOrderDetail>().Where(x => x.OutBoxbarcodes == barcode && x.OrderDetailStatus != OrderDetailStatusEnum.Over.ObjToInt()).First();
+
+ if(inboundOrderDetail == null)
+ {
+ return WebResponseContent.Instance.Error($"鏈壘鍒拌鏉$爜{barcode}鐨勫叆搴撴槑缁嗘垨鑰呮槑缁嗙姸鎬佸凡鍏ユ櫤浠撳畬鎴�");
+ }
+ }
+ Dt_InboundOrder inboundOrder = _inboundOrderRepository.QueryFirst(x => x.Id == inboundOrderDetail.OrderId && x.OrderStatus != InOrderStatusEnum.鍏ュ簱瀹屾垚.ObjToInt());
+ if (inboundOrder == null)
+ {
+ return WebResponseContent.Instance.Error($"璇ュ叆搴撳崟{inboundOrder}鐘舵�佸凡鍏ユ櫤浠撳畬鎴�");
+ }
+ var resultData = new { purchaseOrderNo = inboundOrder.UpperOrderNo };
+
+ return WebResponseContent.Instance.OK("鏌ヨ閲囪喘鍗曟垚鍔�", data: resultData);
+ }
+ catch (Exception ex)
+ {
+ return WebResponseContent.Instance.Error(ex.Message);
+ }
+ }
+ #endregion
+
+ public WebResponseContent UnPalletQuantity(string orderNo)
+ {
+ // 鍒濆鍖栬繑鍥濪TO锛堥粯璁ゅ�奸兘涓�0锛岄伩鍏峮ull锛�
+ var resultDTO = new PalletSumQuantityDTO
+ {
+ StockSumQuantity = 0,
+ StockCount = 0,
+ UniqueUnit = ""
+ };
+ WebResponseContent content = new WebResponseContent();
+ try
+ {
+ if (string.IsNullOrWhiteSpace(orderNo))
+ {
+ return content.Error("浼犲叆鐨勮鍗曞彿orderNo涓虹┖鎴栫┖鐧�");
+ }
+ var orderDetail = Db.Queryable<Dt_PickingRecord>().Where(s => s.OrderNo == orderNo).ToList();
+ if (orderDetail == null)
+ {
+ return content.Error("鏈壘鍒板崟鎹�");
+ }
+ var unitGroups = orderDetail.GroupBy(d => d.BarcodeUnit).ToList();
+ if (unitGroups.Count == 1)
+ {
+ resultDTO.UniqueUnit = unitGroups.First().Key;
+ }
+ else
+ {
+ resultDTO.UniqueUnit = "";
+ }
+ var validDetails = _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>().Where(s => s.OrderNo == orderNo).ToList();
+ resultDTO.StockSumQuantity = orderDetail.Sum(d => d.PickQuantity);
+ resultDTO.StockCount = orderDetail.Count;
+ if (validDetails.Any())
+ {
+ resultDTO.StockSumQuantity -= validDetails.Sum(d => d.StockQuantity);
+ // 鏄庣粏璁板綍鏁帮細绗﹀悎鏉′欢鐨勬湁鏁堣褰曟潯鏁�
+ resultDTO.StockCount -= validDetails.Count;
+ }
+ return content.OK("", resultDTO);
+ }
+ catch (Exception ex)
+ {
+ return content.Error("SumQuantity 缁熻搴撳瓨鏁伴噺澶辫触锛岃鍗曞彿锛歿OrderNo}");
+ }
+ }
+
+ public WebResponseContent BarcodeMaterielGroup(BarcodeMaterielGroupDTO materielGroupDTO)
+ {
+
+ WebResponseContent content = new WebResponseContent();
+ try
+ {
+ (bool, string, object?) result2 = ModelValidate.ValidateModelData(materielGroupDTO);
+ if (!result2.Item1) return content = WebResponseContent.Instance.Error(result2.Item2);
+
+ // materielGroupDTO.WarehouseCode
+ var code = _warehouseAreaRepository.Db.Queryable<Dt_WarehouseArea>().Where(x => x.Code == materielGroupDTO.WarehouseType).Select(x => x.Code).First();
+ if (string.IsNullOrEmpty(code))
+ {
+ return content = WebResponseContent.Instance.Error($"浠撳簱涓病鏈夎{materielGroupDTO.WarehouseType}缂栧彿銆�");
+ }
+
+ if (materielGroupDTO.orderTypes == InOrderTypeEnum.ReCheck.ObjToInt())
+ {
+ var dborder = _reCheckOrderService.Db.Queryable<Dt_ReCheckOrder>().First(x => x.OrderNo == materielGroupDTO.OrderNo);
+ if (dborder != null && (dborder.SignSeq == 0 || dborder.SignSeq == 1))
+ {
+ return content.Error("鍙湁鎷垮埌閲嶆缁撴灉鎵嶈兘鍏ュ簱锛�");
+ }
+
+
+ }
+ // Dt_InboundOrder inboundOrder = GetInboundOrder(materielGroupDTO.OrderNo);
+
+ var dbinboundOrderDetails = Db.Queryable<Dt_PickingRecord>().Where(x => x.OrderNo == materielGroupDTO.OrderNo && !x.IsCancelled && x.Barcode == materielGroupDTO.Barcodes).ToList();
+
+ if (dbinboundOrderDetails != null && !dbinboundOrderDetails.Any())
+ {
+ return content = WebResponseContent.Instance.Error($"鍗曟嵁涓病鏈夎{materielGroupDTO.Barcodes}鏉$爜鏁版嵁銆�");
+ }
+
+ List<string?> materielCodes = dbinboundOrderDetails.GroupBy(x => x.Barcode).Select(x => x.Key).ToList();
+
+ Dt_StockInfo? stockInfo = _stockService.StockInfoService.GetStockByPalletCode(materielGroupDTO.PalletCode);
+
+
+
+ (bool, string, object?) result = CheckMaterielGroupParam(materielGroupDTO, materielCodes, stockInfo);
+ if (!result.Item1) return content = WebResponseContent.Instance.Error(result.Item2);
+
+ if (stockInfo == null)
+ {
+ stockInfo = new Dt_StockInfo() { PalletType = (int)PalletTypeEnum.None, LocationType = materielGroupDTO.locationType.ObjToInt() };
+ stockInfo.Details = new List<Dt_StockInfoDetail>();
+ }
+ var inboindId = 0; Dt_InboundOrder dt_InboundOrder = null;
+ var orderno = dbinboundOrderDetails.First().OrderNo;
+ var dbinbound = _inboundOrderRepository.QueryData(x => x.InboundOrderNo == orderno).FirstOrDefault();
+ if (dbinbound == null)
+ {
+ dt_InboundOrder = new Dt_InboundOrder
+ {
+ WarehouseId = 0,
+ InboundOrderNo = dbinboundOrderDetails.First()?.OrderNo,
+ UpperOrderNo = dbinboundOrderDetails.First()?.OrderNo,
+ SupplierId = dbinboundOrderDetails.First()?.SupplyCode,
+ OrderType = materielGroupDTO.orderTypes,
+
+ BusinessType = materielGroupDTO.orderTypes.ToString(),
+
+ FactoryArea = dbinboundOrderDetails.First()?.FactoryArea,
+ Remark = "",
+ Details = new List<Dt_InboundOrderDetail>()
+ };
+ inboindId = _inboundOrderRepository.AddData(dt_InboundOrder);
+ }
+ else
+ {
+ dt_InboundOrder = new Dt_InboundOrder { Details = new List<Dt_InboundOrderDetail>() };
+ inboindId = dbinbound.Id;
+ }
+
+ foreach (var item in dbinboundOrderDetails)
+ {
+ stockInfo.Details.Add(new Dt_StockInfoDetail
+ {
+ StockId = stockInfo == null ? 0 : stockInfo.Id,
+ Barcode = item.Barcode,
+ MaterielCode = item.MaterielCode,
+ BatchNo = item.BatchNo,
+ Unit = item.BarcodeUnit,
+ InboundOrderRowNo = item.lineNo,
+ SupplyCode = item.SupplyCode,
+ WarehouseCode = materielGroupDTO.WarehouseType,
+ StockQuantity = item.PickQuantity,
+ BarcodeQty = item.BarcodeQty,
+ BarcodeUnit = item.BarcodeUnit,
+ FactoryArea = item.FactoryArea,
+ Status = 0,
+ OrderNo = item.OrderNo,
+ BusinessType = materielGroupDTO.orderTypes.ToString(),
+
+
+ });
+ item.WarehouseCode = item.WarehouseCode;
+
+ dt_InboundOrder.Details.Add(new Dt_InboundOrderDetail
+ {
+ OrderId = inboindId,
+ MaterielCode = item.MaterielCode,
+ MaterielName = "",
+ BatchNo = item.BatchNo,
+ OrderQuantity = item.PickQuantity,
+ ReceiptQuantity = 0,
+ OverInQuantity = 0,
+ Unit = item.BarcodeUnit,
+ RowNo = 0,
+ lineNo = item.lineNo,
+ SupplyCode = item.SupplyCode,
+ WarehouseCode = item.WarehouseCode,
+ Barcode = item.Barcode,
+ OutBoxbarcodes = "",
+ BarcodeQty = (decimal)item.BarcodeQty,
+ BarcodeUnit = item.BarcodeUnit
+ });
+ }
+
+ _inboundOrderDetailService.Db.Insertable<Dt_InboundOrderDetail>(dt_InboundOrder.Details);
+ if (stockInfo.Id == 0)
+ {
+ stockInfo.PalletCode = materielGroupDTO.PalletCode;
+ stockInfo.StockStatus = StockStatusEmun.缁勭洏鏆傚瓨.ObjToInt();
+ }
+ stockInfo.PalletType = (int)PalletTypeEnum.None;
+
+ List<int> updateDetailIds = dbinboundOrderDetails.Select(x => x.Id).ToList();
+
+ try
+ {
+ _unitOfWorkManage.BeginTran();
+
+ _stockService.StockInfoService.AddMaterielGroup(stockInfo);
+ _unitOfWorkManage.CommitTran();
+ return WebResponseContent.Instance.OK();
+ }
+ catch (Exception ex)
+ {
+ _unitOfWorkManage.RollbackTran();
+ return WebResponseContent.Instance.Error(ex.Message);
+ }
+ }
+ catch (Exception ex)
+ {
+ content = WebResponseContent.Instance.Error(ex.Message);
+ }
+ finally
+ {
+
+ }
+ return content;
+
+ }
+
+
+ public (bool, string, object?) CheckMaterielGroupParam(BarcodeMaterielGroupDTO materielGroupDTO, List<string> barcodeCodes, Dt_StockInfo stockInfo)
+ {
+ (bool, string, object?) result = ModelValidate.ValidateModelData(materielGroupDTO);
+ if (!result.Item1) return result;
+
+ if (_taskRepository.QueryFirst(x => x.PalletCode == materielGroupDTO.PalletCode) != null)
+ {
+ return (false, "璇ユ墭鐩樺彿宸叉湁浠诲姟", materielGroupDTO);
+ }
+
+ if (stockInfo != null && !string.IsNullOrEmpty(stockInfo.LocationCode) && stockInfo.StockStatus != StockStatusEmun.缁勭洏鏆傚瓨.ObjToInt())
+ {
+ return (false, "宸蹭笂鏋剁殑鎵樼洏涓嶈兘鍐嶆缁勭洏", materielGroupDTO);
+ }
+
+ if (_stockService.StockInfoDetailService.ExistBarcodes(barcodeCodes))
+ {
+ return (false, $"{barcodeCodes[0]} 鏉$爜鍦ㄥ簱瀛樹腑宸插瓨鍦�", materielGroupDTO);
+ }
+
+
+
+ return (true, "鎴愬姛", materielGroupDTO);
+ }
+
+
+
}
#region 鏀寔绫诲畾涔�
@@ -2118,20 +3428,6 @@
public List<SplitResult> SplitResults { get; set; } = new List<SplitResult>();
}
- public class ReturnAnalysisResult
- {
- 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 class PalletStatusAnalysis
{
public string OrderNo { get; set; }
@@ -2145,12 +3441,22 @@
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 bool HasUnallocatedLocks { get; set; }
+ public List<Dt_OutStockLockInfo> UnallocatedLocks { get; set; } = new List<Dt_OutStockLockInfo>();
+ public decimal UnallocatedLocksReturnQty { 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 HashSet<string> ProcessedBarcodes { get; set; } = new HashSet<string>();
+ public List<string> AllBarcodes { get; set; } = new List<string>();
// 绌烘墭鐩樼浉鍏冲睘鎬�
public bool IsEmptyPallet { get; set; }
public bool HasActiveTasks { get; set; }
@@ -2159,5 +3465,18 @@
public bool CanReturn => HasItemsToReturn && !HasActiveTasks;
public bool CanRemove => IsEmptyPallet && !HasActiveTasks;
}
+
+ public class CancelPickingContext
+ {
+ public string OrderNo { get; set; }
+ public string PalletCode { get; set; }
+ public string Barcode { get; set; }
+ public string Operator { get; set; }
+
+ public decimal CancelQuantity { get; set; }
+ public Dt_PickingRecord PickingRecord { get; set; }
+ public Dt_OutStockLockInfo LockInfo { get; set; }
+ public Dt_OutboundOrderDetail OrderDetail { get; set; }
+ }
#endregion
}
--
Gitblit v1.9.3