From e62ab9b29a574191e29d27893ee82316fa6e6c14 Mon Sep 17 00:00:00 2001
From: pan <antony1029@163.com>
Date: 星期五, 21 十一月 2025 19:04:02 +0800
Subject: [PATCH] tj
---
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs | 1945 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 1,781 insertions(+), 164 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 a47f4b8..4deb21d 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,4 +1,10 @@
-锘縰sing System;
+锘縰sing Dm.filter;
+using MailKit.Search;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
+using SqlSugar;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -6,9 +12,13 @@
using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.OrderEnum;
using WIDESEA_Common.StockEnum;
+using WIDESEA_Common.TaskEnum;
using WIDESEA_Core;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
+using WIDESEA_Core.Helper;
+using WIDESEA_DTO.Basic;
+using WIDESEA_DTO.Inbound;
using WIDESEA_DTO.Outbound;
using WIDESEA_IBasicService;
using WIDESEA_IOutboundService;
@@ -31,10 +41,33 @@
private readonly IStockInfoDetailService _stockInfoDetailService;
private readonly ILocationInfoService _locationInfoService;
private readonly IOutboundOrderDetailService _outboundOrderDetailService;
+ private readonly IOutboundOrderService _outboundOrderService;
private readonly ISplitPackageService _splitPackageService;
-
+ private readonly IRepository<Dt_Task> _taskRepository;
+ private readonly IESSApiService _eSSApiService;
+ private readonly IInvokeMESService _invokeMESService;
+ private readonly IDailySequenceService _dailySequenceService;
- public OutboundPickingService(IRepository<Dt_PickingRecord> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IStockService stockService, IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService, ILocationInfoService locationInfoService, IOutboundOrderDetailService outboundOrderDetailService, ISplitPackageService splitPackageService) : base(BaseDal)
+ private readonly ILogger<OutboundPickingService> _logger;
+
+ private Dictionary<string, string> stations = new Dictionary<string, string>
+ {
+ {"2-1","2-9" },
+ {"3-1","3-9" },
+
+ };
+
+ private Dictionary<string, string> movestations = new Dictionary<string, string>
+ {
+ {"2-1","2-5" },
+ {"3-1","3-5" },
+
+ };
+
+ 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)
{
_unitOfWorkManage = unitOfWorkManage;
_stockInfoService = stockInfoService;
@@ -44,117 +77,1718 @@
_locationInfoService = locationInfoService;
_outboundOrderDetailService = outboundOrderDetailService;
_splitPackageService = splitPackageService;
+ _outboundOrderService = outboundOrderService;
+ _taskRepository = taskRepository;
+ _eSSApiService = eSSApiService;
+ _logger = logger;
+ _invokeMESService = invokeMESService;
+ _dailySequenceService = dailySequenceService;
}
- /// <summary>
- /// 鎵爜鎷i�夌‘璁� - 绠�鍖栫増鏈�
- /// 鍙鐞嗗疄闄呮嫞閫夌殑搴撳瓨鎵e噺
- /// </summary>
- public async Task<WebResponseContent> ConfirmPicking(PickingConfirmRequest request)
+
+ #region 鏌ヨ鍑哄簱璇︽儏鍒楄〃
+ public async Task<List<OutStockLockListResp>> GetOutStockLockListAsync(string orderNo)
+ {
+ var locks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(t => t.OrderNo == orderNo)
+ .ToListAsync();
+
+ return locks.Select(t => new OutStockLockListResp
+ {
+ Id = t.Id,
+ // TaskNum = t.TaskNum,
+ PalletCode = t.PalletCode,
+ CurrentBarcode = t.CurrentBarcode,
+ AssignQuantity = t.AssignQuantity,
+ PickedQty = t.PickedQty,
+ Status = t.Status,
+ // IsSplitted = t.IsSplitted
+ }).ToList();
+ }
+ #endregion
+ public async Task<WebResponseContent> ValidateBarcode(string barcode)
+ {
+ try
+ {
+ if (string.IsNullOrEmpty(barcode))
+ {
+ return WebResponseContent.Instance.Error("鏉$爜涓嶈兘涓虹┖");
+ }
+
+ // 鏍规嵁鏉$爜鏌ヨ搴撳瓨鏄庣粏
+ var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ .Includes(x => x.StockInfo)
+ .Where(x => x.Barcode == barcode)
+ .FirstAsync();
+
+ if (stockDetail == null)
+ {
+ return WebResponseContent.Instance.Error("鏉$爜涓嶅瓨鍦�");
+ }
+
+
+
+ var result = new
+ {
+ Barcode = barcode,
+ MaterielCode = stockDetail.MaterielCode,
+
+ BatchNo = stockDetail.BatchNo,
+ AvailableQuantity = stockDetail.StockQuantity - stockDetail.OutboundQuantity,
+ LocationCode = stockDetail.StockInfo?.LocationCode,
+ PalletCode = stockDetail.StockInfo?.PalletCode
+ };
+
+ return WebResponseContent.Instance.OK(null, result);
+ }
+ catch (Exception ex)
+ {
+ return WebResponseContent.Instance.Error($"鏉$爜楠岃瘉澶辫触: {ex.Message}");
+ }
+ }
+
+ // 妫�鏌ュ苟鏇存柊璁㈠崟鐘舵��
+ private async Task CheckAndUpdateOrderStatus(string orderNo)
+ {
+
+ var orderDetails = _stockInfoDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+ .LeftJoin<Dt_OutboundOrder>((o, item) => o.OrderId == item.Id) // 鍏宠仈鏉′欢锛氱埗琛� Id = 瀛愯〃 OrderId
+ .Where((o, item) => item.OrderNo == orderNo) // 杩囨护鐖惰〃 OrderNo
+ .Select((o, item) => o) // 鍙繑鍥炲瓙琛ㄦ暟鎹�
+ .ToList();
+
+ //var orderDetails = await _stockInfoDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+ // .Where(x => x.OrderId == orderNo.ObjToInt())
+ // .ToListAsync();
+
+ bool allCompleted = true;
+ foreach (var detail in orderDetails)
+ {
+ if (detail.OverOutQuantity < detail.NeedOutQuantity)
+ {
+ allCompleted = false;
+ break;
+ }
+ }
+
+ if (allCompleted)
+ {
+ try
+ {
+ await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
+ .SetColumns(x => x.OrderStatus == 2) // 宸插畬鎴�
+ .Where(x => x.OrderNo == orderNo)
+ .ExecuteCommandAsync();
+
+ var outboundOrder = _stockInfoService.Db.Queryable<Dt_OutboundOrder>().First(x => x.OrderNo == orderNo);
+
+
+ if (outboundOrder != null && outboundOrder.OrderStatus == OutOrderStatusEnum.鍑哄簱瀹屾垚.ObjToInt())
+ {
+
+ if (outboundOrder.OrderType == OutOrderTypeEnum.Allocate.ObjToInt().ObjToInt())//璋冩嫧鍑哄簱
+ {
+
+ }
+ else if (outboundOrder.OrderType == OutOrderTypeEnum.ReCheck.ObjToInt()) //閲嶆鍑哄簱
+ {
+
+ }
+ else
+ {
+ var feedmodel = new FeedbackOutboundRequestModel
+ {
+ reqCode = Guid.NewGuid().ToString(),
+ reqTime = DateTime.Now.ToString(),
+ business_type = outboundOrder.BusinessType,
+ factoryArea = outboundOrder.FactoryArea,
+ operationType = 1,
+ Operator = outboundOrder.Operator,
+ orderNo = outboundOrder.UpperOrderNo,
+ status = outboundOrder.OrderStatus,
+ details = new List<FeedbackOutboundDetailsModel>()
+
+ };
+ var lists = _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>().Where(x => x.OrderNo == orderNo && x.Status == (int)OutLockStockStatusEnum.鎷i�夊畬鎴�).ToList();
+
+ 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,
+ currentDeliveryQty = group.Sum(x => x.OrderQuantity),
+ // warehouseCode= "1072",
+ 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();
+ }
+ }
+
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(" OutboundPickingService FeedbackOutbound : " + ex.Message);
+ }
+
+ }
+ }
+
+ public async Task<WebResponseContent> ConfirmPicking(string orderNo, string palletCode, string barcode)
{
try
{
_unitOfWorkManage.BeginTran();
- // 1. 楠岃瘉鏉$爜鏈夋晥鎬�
+ // 1. 楠岃瘉杈撳叆鍙傛暟
+ if (string.IsNullOrEmpty(orderNo) || string.IsNullOrEmpty(palletCode) || string.IsNullOrEmpty(barcode))
+ {
+ throw new Exception("璁㈠崟鍙枫�佹墭鐩樼爜鍜屾潯鐮佷笉鑳戒负绌�");
+ }
+
+ // 2. 鏌ユ壘鍑哄簱閿佸畾淇℃伅
+ var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(it => it.OrderNo == orderNo &&
+ it.Status == (int)OutLockStockStatusEnum.鍑哄簱涓� &&
+ it.PalletCode == palletCode &&
+ it.CurrentBarcode == barcode &&
+ it.AssignQuantity > it.PickedQty)
+ .FirstAsync();
+
+ if (lockInfo == null)
+ {
+ lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(it => it.CurrentBarcode == barcode &&
+ it.Status == (int)OutLockStockStatusEnum.鍑哄簱涓� &&
+ it.AssignQuantity > it.PickedQty)
+ .FirstAsync();
+
+ if (lockInfo == null)
+ {
+ var completedLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(it => it.CurrentBarcode == barcode &&
+ (it.Status == (int)OutLockStockStatusEnum.鎷i�夊畬鎴� ||
+ it.PickedQty >= it.AssignQuantity))
+ .FirstAsync();
+
+ if (completedLockInfo != null)
+ throw new Exception($"鏉$爜{barcode}宸茬粡瀹屾垚鍒嗘嫞锛屼笉鑳介噸澶嶅垎鎷�");
+ else
+ throw new Exception($"鏉$爜{barcode}涓嶅睘浜庢墭鐩榹palletCode}鎴栦笉瀛樺湪寰呭垎鎷h褰�");
+ }
+ }
+
+ if (lockInfo.PalletCode != palletCode)
+ throw new Exception($"鏉$爜{barcode}涓嶅睘浜庢墭鐩榹palletCode}");
+
+ // 妫�鏌ユ嫞閫夊巻鍙诧紝闃叉閲嶅鍒嗘嫞
+ var existingPicking = await Db.Queryable<Dt_PickingRecord>()
+ .Where(x => x.Barcode == barcode &&
+ x.OrderNo == orderNo &&
+ x.PalletCode == palletCode &&
+ x.OutStockLockId == lockInfo.Id)
+ .FirstAsync();
+
+ if (existingPicking != null)
+ {
+ throw new Exception($"鏉$爜{barcode}宸茬粡鍒嗘嫞杩囷紝涓嶈兘閲嶅鍒嗘嫞");
+ }
+
+ // 鑾峰彇璁㈠崟鏄庣粏骞舵鏌ユ暟閲忛檺鍒�
+ var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+ .FirstAsync(x => x.Id == lockInfo.OrderDetailId);
+
+ if (orderDetail == null)
+ throw new Exception($"鏈壘鍒拌鍗曟槑缁嗭紝ID: {lockInfo.OrderDetailId}");
+
+ // 鍏抽敭淇锛氭鏌ョ疮璁℃嫞閫夋暟閲忔槸鍚︿細瓒呰繃璁㈠崟鏁伴噺
+ decimal actualQty = lockInfo.AssignQuantity - lockInfo.PickedQty;
+ decimal remainingOrderQty = orderDetail.NeedOutQuantity - orderDetail.OverOutQuantity;
+
+ if (actualQty > remainingOrderQty)
+ {
+ // 濡傛灉鍒嗛厤鏁伴噺澶т簬鍓╀綑璁㈠崟鏁伴噺锛岃皟鏁村疄闄呮嫞閫夋暟閲�
+ actualQty = remainingOrderQty;
+
+ if (actualQty <= 0)
+ {
+ throw new Exception($"璁㈠崟{orderNo}鐨勯渶姹傛暟閲忓凡婊¤冻锛屾棤娉曠户缁垎鎷�");
+ }
+
+ _logger.LogWarning($"璋冩暣鍒嗘嫞鏁伴噺锛氬師鍒嗛厤{lockInfo.AssignQuantity - lockInfo.PickedQty}锛岃皟鏁翠负{actualQty}锛岃鍗曢渶姹倇orderDetail.NeedOutQuantity}锛屽凡鍑哄簱{orderDetail.OverOutQuantity}");
+ }
+
var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
- .Where(x => x.Barcode == request.Barcode && x.MaterielCode == request.MaterielCode)
+ .Where(x => x.Barcode == barcode && x.StockId == lockInfo.StockId)
.FirstAsync();
if (stockDetail == null)
return WebResponseContent.Instance.Error("鏃犳晥鐨勬潯鐮佹垨鐗╂枡缂栫爜");
- // 2. 妫�鏌ュ簱瀛樺彲鐢ㄦ暟閲�
- decimal availableQuantity = stockDetail.StockQuantity - stockDetail.OutboundQuantity;
- if (request.PickQuantity > availableQuantity)
- return WebResponseContent.Instance.Error($"鎷i�夋暟閲忚秴杩囧彲鐢ㄥ簱瀛橈紝鍙敤鏁伴噺锛歿availableQuantity}");
+ decimal stockQuantity = stockDetail.StockQuantity;
- // 3. 鏌ユ壘鐩稿叧鐨勫嚭搴撻攣瀹氫俊鎭紙鏀寔鎷嗗寘鍚庣殑鏂版潯鐮侊級
- var lockInfo = await FindLockInfoByBarcode(request.OrderDetailId, request.Barcode, request.MaterielCode);
+ List<SplitResult> splitResults = new List<SplitResult>();
+ Dt_OutStockLockInfo finalLockInfo = lockInfo;
+ var finalBarcode = barcode;
+ var finalStockId = stockDetail.Id;
+ decimal actualPickedQty = actualQty;
- if (lockInfo == null)
- return WebResponseContent.Instance.Error("鏈壘鍒扮浉鍏崇殑鍑哄簱閿佸畾淇℃伅");
-
- // 4. 妫�鏌ラ攣瀹氭暟閲�
- decimal remainingLockQuantity = lockInfo.AssignQuantity - lockInfo.PickedQty;
- if (request.PickQuantity > remainingLockQuantity)
- return WebResponseContent.Instance.Error($"鎷i�夋暟閲忚秴杩囬攣瀹氭暟閲忥紝鍓╀綑鍙嫞閫夛細{remainingLockQuantity}");
-
- // 5. 鏇存柊閿佸畾淇℃伅鐨勫凡鎷i�夋暟閲�
- lockInfo.PickedQty += request.PickQuantity;
- await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
-
- // 6. 鏇存柊搴撳瓨鍑哄簱鏁伴噺 - 瀹為檯鍑忓皯搴撳瓨
- stockDetail.OutboundQuantity += request.PickQuantity;
- await _stockInfoService.Db.Updateable(stockDetail).ExecuteCommandAsync();
-
- // 7. 鏇存柊鍑哄簱鍗曟槑缁�
- var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
- .Where(x => x.Id == request.OrderDetailId)
- .FirstAsync();
-
- orderDetail.OverOutQuantity += request.PickQuantity;
- orderDetail.LockQuantity -= request.PickQuantity;
-
- // 妫�鏌ユ槸鍚﹀畬鎴愬嚭搴�
- if (Math.Abs(orderDetail.OverOutQuantity - orderDetail.OrderQuantity) < 0.001m)
+ if (actualQty < stockQuantity)
{
- orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.Over;
- orderDetail.LockQuantity = 0;
+ // 鎯呭喌1: 鍒嗛厤鏁伴噺灏忎簬搴撳瓨鏁伴噺锛岄渶瑕佽嚜鍔ㄦ媶鍖�
+ decimal remainingStockQty = stockQuantity - actualQty;
- // 鏇存柊鐩稿叧鐨勯攣瀹氫俊鎭姸鎬佷负宸插嚭搴�
- var relatedLockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
- .Where(x => x.OrderDetailId == request.OrderDetailId &&
- x.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
+ // 鏇存柊鍘熸潯鐮佸簱瀛樹负鍓╀綑鏁伴噺
+ stockDetail.StockQuantity = remainingStockQty;
+ stockDetail.OutboundQuantity = remainingStockQty;
+ await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
+
+ // 鐢熸垚鏂版潯鐮佺敤浜庤褰曟嫞閫夋暟閲�
+ var seq = await _dailySequenceService.GetNextSequenceAsync();
+ string newBarcode = "WSLOT" + DateTime.Now.ToString("yyyyMMdd") + seq.ToString()?.PadLeft(5, '0');
+
+ // 涓烘柊鏉$爜鍒涘缓鍑哄簱閿佸畾淇℃伅
+ var newLockInfo = new Dt_OutStockLockInfo
+ {
+ OrderNo = lockInfo.OrderNo,
+ OrderDetailId = lockInfo.OrderDetailId,
+ BatchNo = lockInfo.BatchNo,
+ MaterielCode = lockInfo.MaterielCode,
+ MaterielName = lockInfo.MaterielName,
+ StockId = lockInfo.StockId,
+ OrderQuantity = actualQty,
+ OriginalQuantity = actualQty,
+ AssignQuantity = actualQty,
+ PickedQty = actualQty,
+ LocationCode = lockInfo.LocationCode,
+ PalletCode = lockInfo.PalletCode,
+ TaskNum = lockInfo.TaskNum,
+ Status = (int)OutLockStockStatusEnum.鎷i�夊畬鎴�,
+ Unit = lockInfo.Unit,
+ SupplyCode = lockInfo.SupplyCode,
+ OrderType = lockInfo.OrderType,
+ CurrentBarcode = newBarcode,
+ OriginalLockQuantity = actualQty,
+ IsSplitted = 1,
+ ParentLockId = lockInfo.Id
+ };
+
+ var newLockId = await _outStockLockInfoService.Db.Insertable(newLockInfo).ExecuteReturnIdentityAsync();
+ newLockInfo.Id = newLockId;
+
+ // 璁板綍鎷嗗寘鍘嗗彶
+ var splitHistory = new Dt_SplitPackageRecord
+ {
+ FactoryArea = lockInfo.FactoryArea,
+ TaskNum = lockInfo.TaskNum,
+ OutStockLockInfoId = lockInfo.Id,
+ StockId = stockDetail.StockId,
+ Operator = App.User.UserName,
+ IsReverted = false,
+ OriginalBarcode = barcode,
+ NewBarcode = newBarcode,
+ SplitQty = actualQty,
+ RemainQuantity = remainingStockQty,
+ MaterielCode = lockInfo.MaterielCode,
+ SplitTime = DateTime.Now,
+ OrderNo = lockInfo.OrderNo,
+ PalletCode = lockInfo.PalletCode,
+ Status = (int)SplitPackageStatusEnum.宸叉嫞閫�
+ };
+ await _splitPackageService.Db.Insertable(splitHistory).ExecuteCommandAsync();
+
+ // 鏇存柊鍘熼攣瀹氫俊鎭负鍓╀綑搴撳瓨鏁伴噺
+ lockInfo.AssignQuantity = remainingStockQty;
+ lockInfo.PickedQty = 0;
+ await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
+
+ splitResults.Add(new SplitResult
+ {
+ materialCode = lockInfo.MaterielCode,
+ supplierCode = lockInfo.SupplyCode,
+ quantityTotal = actualQty.ToString("F2"),
+ batchNumber = newBarcode,
+ batch = lockInfo.BatchNo,
+ factory = lockInfo.FactoryArea,
+ date = DateTime.Now.ToString("yyyy-MM-dd"),
+ });
+
+ splitResults.Add(new SplitResult
+ {
+ materialCode = lockInfo.MaterielCode,
+ supplierCode = lockInfo.SupplyCode,
+ quantityTotal = remainingStockQty.ToString("F2"),
+ batchNumber = barcode,
+ batch = lockInfo.BatchNo,
+ factory = lockInfo.FactoryArea,
+ date = DateTime.Now.ToString("yyyy-MM-dd"),
+ });
+
+ finalLockInfo = newLockInfo;
+ finalBarcode = newBarcode;
+ }
+ else if (actualQty == stockQuantity)
+ {
+ // 鎯呭喌2: 鍒嗛厤鏁伴噺绛変簬搴撳瓨鏁伴噺锛屾暣鍖呭嚭搴�
+ stockDetail.StockQuantity = 0;
+ stockDetail.OutboundQuantity = 0;
+ await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
+
+ lockInfo.PickedQty += actualQty;
+ lockInfo.Status = (int)OutLockStockStatusEnum.鎷i�夊畬鎴�;
+ await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
+ }
+ else
+ {
+ // 鎯呭喌3: 鍒嗛厤鏁伴噺澶т簬搴撳瓨鏁伴噺锛屽簱瀛樻暣鍖呭嚭搴�
+ decimal stockOutQty = stockQuantity;
+ stockDetail.StockQuantity = 0;
+ stockDetail.OutboundQuantity = 0;
+ await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
+
+ decimal remainingAssignQty = actualQty - stockQuantity;
+ lockInfo.PickedQty += stockOutQty;
+ lockInfo.AssignQuantity = remainingAssignQty;
+ await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
+
+ var relatedSplitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
+ .Where(it => it.OriginalBarcode == barcode || it.NewBarcode == barcode)
+ .Where(it => !it.IsReverted)
.ToListAsync();
- foreach (var relatedLock in relatedLockInfos)
+ foreach (var record in relatedSplitRecords)
{
- relatedLock.Status = (int)OutLockStockStatusEnum.宸插嚭搴�;
+ record.Status = (int)SplitPackageStatusEnum.宸叉嫞閫�;
+ await _splitPackageService.Db.Updateable(record).ExecuteCommandAsync();
}
- await _outStockLockInfoService.Db.Updateable(relatedLockInfos).ExecuteCommandAsync();
+
+ actualPickedQty = stockOutQty;
}
- await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
+ // 鍏抽敭淇锛氬啀娆℃鏌ヨ鍗曟暟閲忛檺鍒�
+ decimal newOverOutQuantity = orderDetail.OverOutQuantity + actualPickedQty;
+ decimal newPickedQty = orderDetail.PickedQty + actualPickedQty;
- // 8. 璁板綍鎷i�夊巻鍙�
- var pickHistory = new Dt_PickingRecord
+ if (newOverOutQuantity > orderDetail.NeedOutQuantity)
{
- OrderDetailId = request.OrderDetailId,
- Barcode = request.Barcode,
- PickQuantity = request.PickQuantity,
- PickTime = DateTime.Now,
+ throw new Exception($"鍒嗘嫞鍚庡皢瀵艰嚧宸插嚭搴撴暟閲�({newOverOutQuantity})瓒呰繃璁㈠崟闇�姹傛暟閲�({orderDetail.NeedOutQuantity})");
+ }
- LocationCode = request.LocationCode,
- StockId = stockDetail.StockId
+ // 鏇存柊璁㈠崟鏄庣粏
+ await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+ .SetColumns(it => new Dt_OutboundOrderDetail
+ {
+ PickedQty = newPickedQty,
+ OverOutQuantity = newOverOutQuantity
+ })
+ .Where(it => it.Id == lockInfo.OrderDetailId)
+ .ExecuteCommandAsync();
+
+ await CheckAndUpdateOrderStatus(orderNo);
+
+ // 鏌ヨ浠诲姟琛�
+ var task = _taskRepository.QueryData(x => x.OrderNo == orderNo && x.PalletCode == palletCode).FirstOrDefault();
+
+ if (finalLockInfo.Id <= 0)
+ {
+ throw new Exception($"閿佸畾淇℃伅ID鏃犳晥: {finalLockInfo.Id}锛屾棤娉曡褰曟嫞閫夊巻鍙�");
+ }
+
+ // 璁板綍鎷i�夊巻鍙�
+ var pickingHistory = new Dt_PickingRecord
+ {
+ FactoryArea = finalLockInfo.FactoryArea,
+ TaskNo = task?.TaskNum ?? 0,
+ LocationCode = task?.SourceAddress ?? "",
+ StockId = finalStockId,
+ OrderNo = orderNo,
+ OrderDetailId = finalLockInfo.OrderDetailId,
+ PalletCode = palletCode,
+ Barcode = finalBarcode,
+ MaterielCode = finalLockInfo.MaterielCode,
+ PickQuantity = actualPickedQty,
+ PickTime = DateTime.Now,
+ Operator = App.User.UserName,
+ OutStockLockId = finalLockInfo.Id
};
- await Db.Insertable(pickHistory).ExecuteCommandAsync();
+ await Db.Insertable(pickingHistory).ExecuteCommandAsync();
_unitOfWorkManage.CommitTran();
- return WebResponseContent.Instance.OK("鎷i�夌‘璁ゆ垚鍔�");
+ if (splitResults.Any())
+ {
+ return WebResponseContent.Instance.OK("鎷i�夌‘璁ゆ垚鍔燂紝宸茶嚜鍔ㄦ媶鍖�", new { SplitResults = splitResults });
+ }
+
+ return WebResponseContent.Instance.OK("鎷i�夌‘璁ゆ垚鍔�", new { SplitResults = new List<SplitResult>() });
+
}
catch (Exception ex)
{
_unitOfWorkManage.RollbackTran();
- return WebResponseContent.Instance.Error($"鎷i�夌‘璁ゅけ璐�: {ex.Message}");
+ _logger.LogError($"ConfirmPicking澶辫触 - OrderNo: {orderNo}, PalletCode: {palletCode}, Barcode: {barcode}, Error: {ex.Message}");
+ return WebResponseContent.Instance.Error($"鎷i�夌‘璁ゅけ璐ワ細{ex.Message}");
}
}
- /// <summary>
- /// 鏍规嵁鏉$爜鏌ユ壘閿佸畾淇℃伅
- /// </summary>
- private async Task<Dt_OutStockLockInfo> FindLockInfoByBarcode(int orderDetailId, string barcode, string materielCode)
+ public async Task<WebResponseContent> CancelPicking(string orderNo, string palletCode, string barcode)
{
- return await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
- .Where(x => x.OrderDetailId == orderDetailId &&
- x.MaterielCode == materielCode &&
- x.CurrentBarcode == barcode &&
- x.Status == (int)OutLockStockStatusEnum.鍑哄簱涓� &&
- x.AssignQuantity > x.PickedQty)
- .FirstAsync();
+ try
+ {
+ _unitOfWorkManage.BeginTran();
+
+ // 鏌ユ壘鎷i�夎褰�
+ var pickingRecord = await Db.Queryable<Dt_PickingRecord>()
+ .Where(it => it.OrderNo == orderNo &&
+ it.PalletCode == palletCode &&
+ it.Barcode == barcode)
+ .OrderByDescending(it => it.PickTime)
+ .FirstAsync();
+
+ if (pickingRecord == null)
+ return WebResponseContent.Instance.Error("鏈壘鍒板搴旂殑鎷i�夎褰�");
+
+ // 鏌ユ壘鍑哄簱閿佸畾淇℃伅
+ var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(it => it.Id == pickingRecord.OutStockLockId)
+ .FirstAsync();
+
+ if (lockInfo == null)
+ return WebResponseContent.Instance.Error("鏈壘鍒板搴旂殑鍑哄簱閿佸畾淇℃伅");
+
+ // 妫�鏌ユ槸鍚﹀彲浠ュ彇娑�
+ if (lockInfo.Status != (int)OutLockStockStatusEnum.鎷i�夊畬鎴�)
+ return WebResponseContent.Instance.Error("褰撳墠鐘舵�佷笉鍏佽鍙栨秷鍒嗘嫞");
+
+ decimal cancelQty = pickingRecord.PickQuantity;
+
+ // 鑾峰彇璁㈠崟鏄庣粏
+ var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+ .FirstAsync(x => x.Id == pickingRecord.OrderDetailId);
+
+ if (orderDetail == null)
+ throw new Exception($"鏈壘鍒拌鍗曟槑缁嗭紝ID: {pickingRecord.OrderDetailId}");
+
+ // 鍏抽敭淇锛氭鏌ュ彇娑堝悗鏁伴噺涓嶄細涓鸿礋鏁�
+ decimal newOverOutQuantity = orderDetail.OverOutQuantity - cancelQty;
+ decimal newPickedQty = orderDetail.PickedQty - cancelQty;
+
+ if (newOverOutQuantity < 0 || newPickedQty < 0)
+ {
+ throw new Exception($"鍙栨秷鍒嗘嫞灏嗗鑷村凡鍑哄簱鏁伴噺鎴栧凡鎷i�夋暟閲忎负璐熸暟");
+ }
+
+ // 澶勭悊鍙栨秷閫昏緫
+ if (lockInfo.IsSplitted == 1 && lockInfo.ParentLockId.HasValue)
+ {
+ await HandleSplitBarcodeCancel(lockInfo, pickingRecord, cancelQty);
+ }
+ else
+ {
+ await HandleNormalBarcodeCancel(lockInfo, pickingRecord, cancelQty);
+ }
+
+ // 鏇存柊璁㈠崟鏄庣粏
+ await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+ .SetColumns(it => new Dt_OutboundOrderDetail
+ {
+ PickedQty = newPickedQty,
+ OverOutQuantity = newOverOutQuantity
+ })
+ .Where(it => it.Id == pickingRecord.OrderDetailId)
+ .ExecuteCommandAsync();
+
+ // 鍒犻櫎鎷i�夎褰�
+ await Db.Deleteable<Dt_PickingRecord>()
+ .Where(x => x.Id == pickingRecord.Id)
+ .ExecuteCommandAsync();
+
+ // 閲嶆柊妫�鏌ヨ鍗曠姸鎬�
+ await CheckAndUpdateOrderStatus(orderNo);
+
+ _unitOfWorkManage.CommitTran();
+ return WebResponseContent.Instance.OK($"鍙栨秷鍒嗘嫞鎴愬姛锛屾仮澶嶆暟閲忥細{cancelQty}");
+ }
+ catch (Exception ex)
+ {
+ _unitOfWorkManage.RollbackTran();
+ _logger.LogError($"CancelPicking澶辫触 - OrderNo: {orderNo}, PalletCode: {palletCode}, Barcode: {barcode}, Error: {ex.Message}");
+ return WebResponseContent.Instance.Error($"鍙栨秷鍒嗘嫞澶辫触锛歿ex.Message}");
+ }
}
+ private async Task HandleSplitBarcodeCancel(Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord, decimal cancelQty)
+ {
+ // 鏌ユ壘鐖堕攣瀹氫俊鎭�
+ var parentLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(x => x.Id == lockInfo.ParentLockId.Value)
+ .FirstAsync();
+
+ if (parentLockInfo == null)
+ {
+ throw new Exception("鏈壘鍒扮埗閿佸畾淇℃伅锛屾棤娉曞彇娑堟媶鍖呭垎鎷�");
+ }
+
+ // 鎭㈠鐖堕攣瀹氫俊鎭殑鍒嗛厤鏁伴噺
+ parentLockInfo.AssignQuantity += cancelQty;
+ await _outStockLockInfoService.Db.Updateable(parentLockInfo).ExecuteCommandAsync();
+
+ // 鎭㈠搴撳瓨
+ var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ .Where(x => x.Barcode == parentLockInfo.CurrentBarcode && x.StockId == parentLockInfo.StockId)
+ .FirstAsync();
+
+ if (stockDetail != null)
+ {
+ stockDetail.StockQuantity += cancelQty;
+ stockDetail.OutboundQuantity += cancelQty;
+ await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
+ }
+
+ // 鏇存柊鎷嗗寘璁板綍鐘舵��
+ await _splitPackageService.Db.Updateable<Dt_SplitPackageRecord>()
+ .SetColumns(x => new Dt_SplitPackageRecord
+ {
+ Status = (int)SplitPackageStatusEnum.宸叉挙閿�,
+ IsReverted = true
+ })
+ .Where(x => x.NewBarcode == lockInfo.CurrentBarcode && !x.IsReverted)
+ .ExecuteCommandAsync();
+
+ // 鍒犻櫎鎷嗗寘浜х敓鐨勯攣瀹氫俊鎭�
+ await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>()
+ .Where(x => x.Id == lockInfo.Id)
+ .ExecuteCommandAsync();
+ }
+
+ private async Task HandleNormalBarcodeCancel(Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord, decimal cancelQty)
+ {
+ // 鎭㈠閿佸畾淇℃伅
+ lockInfo.PickedQty -= cancelQty;
+ if (lockInfo.PickedQty < 0) lockInfo.PickedQty = 0;
+
+ lockInfo.Status = (int)OutLockStockStatusEnum.鍑哄簱涓�;
+ await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
+
+ // 鎭㈠搴撳瓨
+ var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ .Where(x => x.Barcode == pickingRecord.Barcode && x.StockId == pickingRecord.StockId)
+ .FirstAsync();
+
+ if (stockDetail != null)
+ {
+ stockDetail.StockQuantity += cancelQty;
+ stockDetail.OutboundQuantity += cancelQty;
+ await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
+ }
+ }
+
+ public async Task<WebResponseContent> ReturnRemaining(string orderNo, string palletCode, string reason)
+ {
+ try
+ {
+ _unitOfWorkManage.BeginTran();
+
+ if (string.IsNullOrEmpty(orderNo) || string.IsNullOrEmpty(palletCode))
+ {
+ return WebResponseContent.Instance.Error("璁㈠崟鍙峰拰鎵樼洏鐮佷笉鑳戒负绌�");
+ }
+ var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>()
+ .FirstAsync(x => x.PalletCode == palletCode);
+
+ if (stockInfo == null)
+ {
+ return WebResponseContent.Instance.Error($"鏈壘鍒版墭鐩� {palletCode} 瀵瑰簲鐨勫簱瀛樹俊鎭�");
+ }
+ var task = await GetCurrentTask(orderNo, palletCode);
+ if (task == null)
+ {
+ return WebResponseContent.Instance.Error("鏈壘鍒板搴旂殑浠诲姟淇℃伅");
+ }
+
+ // 鍒嗘瀽闇�瑕佸洖搴撶殑璐х墿
+ var returnAnalysis = await AnalyzeReturnItems(orderNo, palletCode, stockInfo.Id);
+
+ if (!returnAnalysis.HasItemsToReturn)
+ {
+ return await HandleNoReturnItems(orderNo, palletCode);
+ }
+
+ // 鎵ц鍥炲簱鎿嶄綔
+ await ExecuteReturnOperations(orderNo, palletCode, stockInfo, task, returnAnalysis);
+
+ //鍒涘缓鍥炲簱浠诲姟骞跺鐞咵SS
+ await CreateReturnTaskAndHandleESS(orderNo, palletCode, task, returnAnalysis);
+
+ _unitOfWorkManage.CommitTran();
+
+ // 鏇存柊璁㈠崟鐘舵��
+ await UpdateOrderStatusForReturn(orderNo);
+
+ return WebResponseContent.Instance.OK($"鍥炲簱鎿嶄綔鎴愬姛锛屽叡鍥炲簱鏁伴噺锛歿returnAnalysis.TotalReturnQty}");
+
+ }
+ catch (Exception ex)
+ {
+ _unitOfWorkManage.RollbackTran();
+ _logger.LogError($"ReturnRemaining澶辫触 - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}");
+ return WebResponseContent.Instance.Error($"鍥炲簱鎿嶄綔澶辫触: {ex.Message}");
+ }
+ }
+
+ #region 璁㈠崟鐘舵��
+
+ private async Task UpdateOrderStatusForReturn(string orderNo)
+ {
+ try
+ {
+ var orderDetails = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+ .LeftJoin<Dt_OutboundOrder>((o, item) => o.OrderId == item.Id)
+ .Where((o, item) => item.OrderNo == orderNo)
+ .Select((o, item) => o)
+ .ToListAsync();
+
+ bool allCompleted = true;
+ foreach (var detail in orderDetails)
+ {
+ if (detail.OverOutQuantity < detail.NeedOutQuantity)
+ {
+ allCompleted = false;
+ break;
+ }
+ }
+
+ var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>()
+ .FirstAsync(x => x.OrderNo == orderNo);
+
+ if (outboundOrder == null) return;
+
+ // 鍙湁褰撶姸鎬佺‘瀹炲彂鐢熷彉鍖栨椂鎵嶆洿鏂�
+ int newStatus = allCompleted ? (int)OutOrderStatusEnum.鍑哄簱瀹屾垚 : (int)OutOrderStatusEnum.鍑哄簱涓�;
+
+ if (outboundOrder.OrderStatus != newStatus)
+ {
+ await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
+ .SetColumns(x => x.OrderStatus == newStatus)
+ .Where(x => x.OrderNo == orderNo)
+ .ExecuteCommandAsync();
+
+ _logger.LogInformation($"鍥炲簱鎿嶄綔鏇存柊璁㈠崟鐘舵�� - OrderNo: {orderNo}, 鏂扮姸鎬�: {newStatus}");
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError($"UpdateOrderStatusForReturn澶辫触 - OrderNo: {orderNo}, Error: {ex.Message}");
+
+ }
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ private async Task<Dt_Task> GetCurrentTask(string orderNo, string palletCode)
+ {
+ // 鍏堝皾璇曢�氳繃璁㈠崟鍙峰拰鎵樼洏鍙锋煡鎵句换鍔�
+ var task = await _taskRepository.Db.Queryable<Dt_Task>()
+ .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode)
+ .FirstAsync();
+
+ if (task == null)
+ {
+ // 濡傛灉鎵句笉鍒帮紝鍐嶉�氳繃鎵樼洏鍙锋煡鎵�
+ task = await _taskRepository.Db.Queryable<Dt_Task>()
+ .Where(x => x.PalletCode == palletCode)
+ .FirstAsync();
+ }
+
+ return task;
+ }
+
+ private async Task<ReturnAnalysisResult> AnalyzeReturnItems(string orderNo, string palletCode, int stockId)
+ {
+ var result = new ReturnAnalysisResult();
+
+ // 鑾峰彇鏈垎鎷g殑鍑哄簱閿佸畾璁板綍
+ var remainingLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(it => it.OrderNo == orderNo &&
+ it.PalletCode == palletCode &&
+ it.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
+ .ToListAsync();
+
+ if (remainingLocks.Any())
+ {
+ result.HasRemainingLocks = true;
+ result.RemainingLocks = remainingLocks;
+ result.RemainingLocksReturnQty = remainingLocks.Sum(x => x.AssignQuantity - x.PickedQty);
+ }
+
+ // 妫�鏌ユ墭鐩樹笂鏄惁鏈夊叾浠栧簱瀛樿揣鐗�
+ var palletStockGoods = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ .Where(it => it.StockId == stockId &&
+ (it.Status == StockStatusEmun.鍏ュ簱纭.ObjToInt() ||
+ it.Status == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt() ||
+ it.Status == StockStatusEmun.鍑哄簱閿佸畾.ObjToInt()))
+ .Where(it => it.StockQuantity > 0) // 鏈夊簱瀛樼殑
+ .ToListAsync();
+
+
+ if (palletStockGoods.Any())
+ {
+ result.HasPalletStockGoods = true;
+ result.PalletStockGoods = palletStockGoods;
+ result.PalletStockReturnQty = palletStockGoods.Sum(x => x.StockQuantity);
+ }
+
+ // 妫�鏌ユ媶鍖呰褰�
+ var splitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
+ .Where(it => it.OrderNo == orderNo && it.PalletCode == palletCode && !it.IsReverted)
+ .ToListAsync();
+
+ if (splitRecords.Any())
+ {
+ result.HasSplitRecords = true;
+ result.SplitRecords = splitRecords;
+ result.SplitReturnQty = await CalculateSplitReturnQuantity(splitRecords, stockId);
+ }
+
+ result.TotalReturnQty = result.RemainingLocksReturnQty + result.PalletStockReturnQty + result.SplitReturnQty;
+ result.HasItemsToReturn = result.TotalReturnQty > 0;
+
+ return result;
+ }
+
+ private async Task<decimal> CalculateSplitReturnQuantity(List<Dt_SplitPackageRecord> splitRecords, int stockId)
+ {
+ decimal totalQty = 0;
+ var processedBarcodes = new HashSet<string>();
+
+ foreach (var splitRecord in splitRecords)
+ {
+ // 妫�鏌ュ師鏉$爜
+ if (!processedBarcodes.Contains(splitRecord.OriginalBarcode))
+ {
+ var originalStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ .Where(it => it.Barcode == splitRecord.OriginalBarcode && it.StockId == stockId)
+ .FirstAsync();
+
+ if (originalStock != null && originalStock.StockQuantity > 0)
+ {
+ totalQty += originalStock.StockQuantity;
+ processedBarcodes.Add(splitRecord.OriginalBarcode);
+ }
+ }
+
+ // 妫�鏌ユ柊鏉$爜
+ if (!processedBarcodes.Contains(splitRecord.NewBarcode))
+ {
+ var newStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ .Where(it => it.Barcode == splitRecord.NewBarcode && it.StockId == stockId)
+ .FirstAsync();
+
+ if (newStock != null && newStock.StockQuantity > 0)
+ {
+ totalQty += newStock.StockQuantity;
+ processedBarcodes.Add(splitRecord.NewBarcode);
+ }
+ }
+ }
+
+ return totalQty;
+ }
+
+ private async Task<WebResponseContent> HandleNoReturnItems(string orderNo, string palletCode)
+ {
+ // 妫�鏌ユ槸鍚︽墍鏈夎揣鐗╅兘宸叉嫞閫夊畬鎴�
+ 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)
+ {
+ return WebResponseContent.Instance.OK("鎵�鏈夎揣鐗╁凡鎷i�夊畬鎴愶紝鎵樼洏涓虹┖");
+ }
+ else
+ {
+ return WebResponseContent.Instance.Error("娌℃湁闇�瑕佸洖搴撶殑鍓╀綑璐х墿");
+ }
+ }
+
+ private async Task ExecuteReturnOperations(string orderNo, string palletCode, Dt_StockInfo stockInfo,
+ Dt_Task task, ReturnAnalysisResult analysis)
+ {
+ // 鎯呭喌1锛氬鐞嗘湭鍒嗘嫞鐨勫嚭搴撻攣瀹氳褰�
+ if (analysis.HasRemainingLocks)
+ {
+ await HandleRemainingLocksReturn(analysis.RemainingLocks, stockInfo.Id);
+
+ // 鍏抽敭锛氭洿鏂拌鍗曟槑缁嗙殑宸叉嫞閫夋暟閲�
+ await UpdateOrderDetailsOnReturn(analysis.RemainingLocks);
+ }
+
+ // 鎯呭喌2锛氬鐞嗘墭鐩樹笂鍏朵粬搴撳瓨璐х墿
+ if (analysis.HasPalletStockGoods)
+ {
+ await HandlePalletStockGoodsReturn(analysis.PalletStockGoods);
+ }
+
+ // 鎯呭喌3锛氬鐞嗘媶鍖呰褰�
+ if (analysis.HasSplitRecords)
+ {
+ await HandleSplitRecordsReturn(analysis.SplitRecords, orderNo, palletCode);
+ }
+
+ // 鏇存柊搴撳瓨涓昏〃鐘舵��
+ await UpdateStockInfoStatus(stockInfo);
+ }
+
+ private async Task HandleRemainingLocksReturn(List<Dt_OutStockLockInfo> remainingLocks, int stockId)
+ {
+ var lockIds = remainingLocks.Select(x => x.Id).ToList();
+
+ // 鏇存柊鍑哄簱閿佸畾璁板綍鐘舵�佷负鍥炲簱涓�
+ await _outStockLockInfoService.Db.Updateable<Dt_OutStockLockInfo>()
+ .SetColumns(it => new Dt_OutStockLockInfo
+ {
+ Status = (int)OutLockStockStatusEnum.鍥炲簱涓�
+ })
+ .Where(it => lockIds.Contains(it.Id))
+ .ExecuteCommandAsync();
+
+ // 澶勭悊搴撳瓨璁板綍
+ foreach (var lockInfo in remainingLocks)
+ {
+ decimal returnQty = lockInfo.AssignQuantity - lockInfo.PickedQty;
+
+ // 鏌ユ壘瀵瑰簲鐨勫簱瀛樻槑缁�
+ var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ .Where(it => it.Barcode == lockInfo.CurrentBarcode && it.StockId == lockInfo.StockId)
+ .FirstAsync();
+
+ if (stockDetail != null)
+ {
+ // 鎭㈠搴撳瓨鐘舵��
+ stockDetail.OutboundQuantity = Math.Max(0, stockDetail.OutboundQuantity - returnQty);
+ stockDetail.Status = StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt();
+ await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
+ }
+ else
+ {
+ // 鍒涘缓鏂扮殑搴撳瓨璁板綍锛堟媶鍖呬骇鐢熺殑鏂版潯鐮侊級
+ var newStockDetail = new Dt_StockInfoDetail
+ {
+ StockId = lockInfo.StockId,
+ MaterielCode = lockInfo.MaterielCode,
+ MaterielName = lockInfo.MaterielName,
+ OrderNo = lockInfo.OrderNo,
+ BatchNo = lockInfo.BatchNo,
+ StockQuantity = returnQty,
+ OutboundQuantity = 0,
+ Barcode = lockInfo.CurrentBarcode,
+ InboundOrderRowNo = "",
+ Status = StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt(),
+ SupplyCode = lockInfo.SupplyCode,
+ WarehouseCode = lockInfo.WarehouseCode,
+ Unit = lockInfo.Unit
+ };
+ 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)
+ {
+ // 璋冩暣宸叉嫞閫夋暟閲忓拰宸插嚭搴撴暟閲�
+ decimal newPickedQty = Math.Max(0, orderDetail.PickedQty - totalReturnQty);
+ decimal newOverOutQuantity = Math.Max(0, orderDetail.OverOutQuantity - totalReturnQty);
+
+ await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+ .SetColumns(it => new Dt_OutboundOrderDetail
+ {
+ PickedQty = newPickedQty,
+ OverOutQuantity = newOverOutQuantity
+ })
+ .Where(it => it.Id == orderDetailId)
+ .ExecuteCommandAsync();
+ }
+ }
+ }
+
+ private async Task HandlePalletStockGoodsReturn(List<Dt_StockInfoDetail> palletStockGoods)
+ {
+ foreach (var stockGood in palletStockGoods)
+ {
+ // 鎭㈠搴撳瓨鐘舵��
+ stockGood.OutboundQuantity = 0;
+ stockGood.Status = StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt();
+ await _stockInfoDetailService.Db.Updateable(stockGood).ExecuteCommandAsync();
+ }
+ }
+
+ private async Task HandleSplitRecordsReturn(List<Dt_SplitPackageRecord> splitRecords, string orderNo, string palletCode)
+ {
+ // 鏇存柊鎷嗗寘璁板綍鐘舵��
+ await _splitPackageService.Db.Updateable<Dt_SplitPackageRecord>()
+ .SetColumns(x => new Dt_SplitPackageRecord
+ {
+ Status = (int)SplitPackageStatusEnum.宸插洖搴�
+ })
+ .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode && !x.IsReverted)
+ .ExecuteCommandAsync();
+ }
+
+ private async Task UpdateStockInfoStatus(Dt_StockInfo stockInfo)
+ {
+ // 鏇存柊搴撳瓨涓昏〃鐘舵��
+ stockInfo.StockStatus = StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt();
+ await _stockInfoService.Db.Updateable(stockInfo).ExecuteCommandAsync();
+ }
+
+ private async Task CreateReturnTaskAndHandleESS(string orderNo, string palletCode, Dt_Task originalTask, ReturnAnalysisResult analysis)
+ {
+ var firstLocation = await _locationInfoService.Db.Queryable<Dt_LocationInfo>()
+ .FirstAsync(x => x.LocationCode == originalTask.SourceAddress);
+
+ // 鍒嗛厤鏂拌揣浣嶏紙鍥炲簱鍒板瓨鍌ㄤ綅锛�
+ var newLocation = _locationInfoService.AssignLocation(firstLocation.LocationType);
+
+ Dt_Task returnTask = new()
+ {
+ CurrentAddress = stations[originalTask.TargetAddress],
+ Grade = 0,
+ PalletCode = palletCode,
+ NextAddress = "",
+ OrderNo = originalTask.OrderNo,
+ Roadway = newLocation.RoadwayNo,
+ SourceAddress = stations[originalTask.TargetAddress],
+ TargetAddress = newLocation.LocationCode,
+ TaskStatus = TaskStatusEnum.New.ObjToInt(),
+ TaskType = TaskTypeEnum.InPick.ObjToInt(),
+ PalletType = originalTask.PalletType,
+ WarehouseId = originalTask.WarehouseId,
+
+ };
+
+ // 淇濆瓨鍥炲簱浠诲姟
+ await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync();
+
+ // 鍒犻櫎鍘熷鍑哄簱浠诲姟
+ _taskRepository.Db.Deleteable(originalTask);
+
+ // 缁� ESS 鍙戦�佹祦鍔ㄤ俊鍙峰拰鍒涘缓浠诲姟
+ await SendESSCommands(palletCode, originalTask, returnTask);
+ }
+ private async Task SendESSCommands(string palletCode, Dt_Task originalTask, Dt_Task returnTask)
+ {
+ try
+ {
+ // 1. 鍙戦�佹祦鍔ㄤ俊鍙�
+ var moveResult = await _eSSApiService.MoveContainerAsync(new WIDESEA_DTO.Basic.MoveContainerRequest
+ {
+ slotCode = movestations[originalTask.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(originalTask.TargetAddress) ?? "",
+ toStationCode = "",
+ toLocationCode = returnTask.TargetAddress,
+ deadline = 0,
+ storageTag = ""
+ }
+ }
+ }
+ };
+
+ var resultTask = await _eSSApiService.CreateTaskAsync(essTask);
+ _logger.LogInformation($"ReturnRemaining 鍒涘缓浠诲姟鎴愬姛: {resultTask}");
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError($"ReturnRemaining ESS鍛戒护鍙戦�佸け璐�: {ex.Message}");
+ throw new Exception($"ESS绯荤粺閫氫俊澶辫触: {ex.Message}");
+ }
+ }
+
+ #endregion
+
+
+
+ /// <summary>
+ /// 鍥炲簱鎿嶄綔
+ /// </summary>
+
+ //public async Task<WebResponseContent> ReturnRemaining(string orderNo, string palletCode, string reason)
+ //{
+ // try
+ // {
+ // _unitOfWorkManage.BeginTran();
+
+ // // 鑾峰彇鎵�鏈夋湭鍒嗘嫞鐨勫嚭搴撻攣瀹氳褰曪紝鍖呮嫭鎷嗗寘浜х敓鐨勮褰�
+ // var remainingLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ // .Where(it => it.OrderNo == orderNo && it.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
+ // .ToListAsync();
+
+ // var stockinfo = _stockInfoService.Db.Queryable<Dt_StockInfo>().First(x => x.PalletCode == palletCode);
+
+ // var tasks = new List<Dt_Task>();
+
+ // // 鏌ヨ浠诲姟琛�
+ // var task = remainingLocks.Any()
+ // ? _taskRepository.QueryData(x => x.TaskNum == remainingLocks.First().TaskNum).FirstOrDefault()
+ // : _taskRepository.QueryData(x => x.PalletCode == palletCode).FirstOrDefault();
+
+ // if (task == null)
+ // {
+ // return WebResponseContent.Instance.Error("鏈壘鍒板搴旂殑浠诲姟淇℃伅");
+ // }
+
+ // // 妫�鏌ユ墭鐩樹笂鏄惁鏈夊叾浠栭潪鍑哄簱璐х墿锛堝簱瀛樿揣鐗╋級
+ // var palletStockGoods = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ // .Where(it => it.StockId == stockinfo.Id &&
+ // (it.Status == StockStatusEmun.鍏ュ簱纭.ObjToInt() ||
+ // it.Status == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt() ||
+ // it.Status == StockStatusEmun.鍑哄簱閿佸畾.ObjToInt()))
+ // .Where(it => it.OutboundQuantity == 0 || it.OutboundQuantity < it.StockQuantity) // 鏈畬鍏ㄥ嚭搴撶殑
+ // .ToListAsync();
+
+ // // 妫�鏌ユ媶鍖呰褰曪紝鎵惧嚭闇�瑕佸洖搴撶殑鏉$爜
+ // var splitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
+ // .Where(it => it.OrderNo == orderNo && it.PalletCode == palletCode && !it.IsReverted)
+ // .ToListAsync();
+
+ // // 璁$畻闇�瑕佸洖搴撶殑鎷嗗寘鏉$爜
+ // var splitBarcodesToReturn = new List<string>();
+ // foreach (var splitRecord in splitRecords)
+ // {
+ // // 妫�鏌ュ師鏉$爜鏄惁杩樻湁搴撳瓨闇�瑕佸洖搴�
+ // var originalStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ // .Where(it => it.Barcode == splitRecord.OriginalBarcode && it.StockId == stockinfo.Id)
+ // .FirstAsync();
+
+ // if (originalStock != null && originalStock.StockQuantity > 0)
+ // {
+ // splitBarcodesToReturn.Add(splitRecord.OriginalBarcode);
+ // }
+
+ // // 妫�鏌ユ柊鏉$爜鏄惁杩樻湁搴撳瓨闇�瑕佸洖搴�
+ // var newStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ // .Where(it => it.Barcode == splitRecord.NewBarcode && it.StockId == stockinfo.Id)
+ // .FirstAsync();
+
+ // if (newStock != null && newStock.StockQuantity > 0)
+ // {
+ // splitBarcodesToReturn.Add(splitRecord.NewBarcode);
+ // }
+ // }
+
+ // // 濡傛灉娌℃湁闇�瑕佸洖搴撶殑璐х墿锛堟棦鏃犳湭鍒嗘嫞鍑哄簱璐х墿锛屼篃鏃犲叾浠栧簱瀛樿揣鐗╋紝涔熸棤鎷嗗寘鍓╀綑璐х墿锛�
+ // if (!remainingLocks.Any() && !palletStockGoods.Any() && !splitBarcodesToReturn.Any())
+ // {
+ // // 妫�鏌ユ槸鍚︽墍鏈夎揣鐗╅兘宸叉嫞閫夊畬鎴�
+ // 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)
+ // {
+ // return WebResponseContent.Instance.OK("鎵�鏈夎揣鐗╁凡鎷i�夊畬鎴愶紝鎵樼洏涓虹┖");
+ // }
+ // else
+ // {
+ // return WebResponseContent.Instance.Error("娌℃湁闇�瑕佸洖搴撶殑鍓╀綑璐х墿");
+ // }
+ // }
+
+ // var firstlocation = _locationInfoService.Db.Queryable<Dt_LocationInfo>().First(x => x.LocationCode == task.SourceAddress);
+ // decimal totalReturnQty = 0;
+
+ // // 鎯呭喌1锛氬鐞嗘湭鍒嗘嫞鐨勫嚭搴撻攣瀹氳褰�
+ // if (remainingLocks.Any(x => x.PalletCode == palletCode))
+ // {
+ // var palletLocks = remainingLocks.Where(x => x.PalletCode == palletCode).ToList();
+ // totalReturnQty = palletLocks.Sum(x => x.AssignQuantity - x.PickedQty);
+
+ // if (totalReturnQty > 0)
+ // {
+ // // 鍒嗛厤鏂拌揣浣�
+ // var newLocation = _locationInfoService.AssignLocation(firstlocation.LocationType);
+
+ // // 鏇存柊鍑哄簱閿佸畾璁板綍鐘舵��
+ // var lockIds = palletLocks.Select(x => x.Id).ToList();
+ // await _outStockLockInfoService.Db.Updateable<Dt_OutStockLockInfo>()
+ // .SetColumns(it => new Dt_OutStockLockInfo { Status = (int)OutLockStockStatusEnum.鍥炲簱涓� })
+ // .Where(it => lockIds.Contains(it.Id))
+ // .ExecuteCommandAsync();
+
+
+
+ // // 澶勭悊搴撳瓨璁板綍
+ // foreach (var lockInfo in palletLocks)
+ // {
+ // decimal returnQty = lockInfo.AssignQuantity - lockInfo.PickedQty;
+
+ // // 妫�鏌ュ簱瀛樿褰曟槸鍚﹀瓨鍦�
+ // var existingStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ // .Where(it => it.Barcode == lockInfo.CurrentBarcode && it.StockId == lockInfo.StockId)
+ // .FirstAsync();
+
+ // if (existingStock != null)
+ // {
+ // // 搴撳瓨璁板綍瀛樺湪锛屾仮澶嶉攣瀹氭暟閲�
+ // existingStock.OutboundQuantity = 0;
+
+ // await _stockInfoDetailService.Db.Updateable(existingStock).ExecuteCommandAsync();
+ // }
+ // else
+ // {
+ // // 搴撳瓨璁板綍涓嶅瓨鍦紙鍙兘鏄媶鍖呬骇鐢熺殑鏂版潯鐮侊級锛屽垱寤烘柊鐨勫簱瀛樿褰�
+ // var newStockDetail = new Dt_StockInfoDetail
+ // {
+ // StockId = lockInfo.StockId,
+ // MaterielCode = lockInfo.MaterielCode,
+ // MaterielName = lockInfo.MaterielName,
+ // OrderNo = lockInfo.OrderNo,
+ // BatchNo = lockInfo.BatchNo,
+ // StockQuantity = returnQty,
+ // OutboundQuantity = 0,
+ // Barcode = lockInfo.CurrentBarcode,
+ // InboundOrderRowNo = "",
+ // Status = StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt(),
+ // SupplyCode = lockInfo.SupplyCode,
+ // WarehouseCode = lockInfo.WarehouseCode,
+ // Unit = lockInfo.Unit
+ // };
+ // await _stockInfoDetailService.Db.Insertable(newStockDetail).ExecuteCommandAsync();
+ // }
+ // }
+
+ // // 鍒涘缓鍥炲簱浠诲姟
+ // CreateReturnTask(tasks, task, palletCode, newLocation);
+ // }
+ // }
+
+ // // 鎯呭喌2锛氬鐞嗘媶鍖呭墿浣欑殑搴撳瓨璐х墿
+ // if (splitBarcodesToReturn.Any())
+ // {
+ // decimal splitReturnQty = 0;
+
+ // foreach (var barcode in splitBarcodesToReturn)
+ // {
+ // var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ // .Where(it => it.Barcode == barcode && it.StockId == stockinfo.Id)
+ // .FirstAsync();
+
+ // if (stockDetail != null && stockDetail.StockQuantity > 0)
+ // {
+ // splitReturnQty += stockDetail.StockQuantity;
+
+ // // 鎭㈠搴撳瓨鐘舵�佷负鍏ュ簱瀹屾垚
+ // stockDetail.OutboundQuantity = 0;
+
+ // await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
+ // }
+ // }
+
+ // totalReturnQty += splitReturnQty;
+
+ // // 濡傛灉娌℃湁鍒涘缓浠诲姟锛屽垱寤哄洖搴撲换鍔�
+ // if (!tasks.Any())
+ // {
+ // var newLocation = _locationInfoService.AssignLocation(firstlocation.LocationType);
+ // CreateReturnTask(tasks, task, palletCode, newLocation);
+ // }
+ // }
+
+ // // 鎯呭喌3锛氬嚭搴撹揣鐗╁凡鍒嗘嫞瀹岋紝浣嗘墭鐩樹笂杩樻湁鍏朵粬搴撳瓨璐х墿闇�瑕佸洖搴�
+ // if (palletStockGoods.Any() && !remainingLocks.Any(x => x.PalletCode == palletCode))
+ // {
+ // decimal otherReturnQty = palletStockGoods.Sum(x => x.StockQuantity - x.OutboundQuantity);
+ // totalReturnQty += otherReturnQty;
+ // // 鏇存柊杩欎簺搴撳瓨璐х墿鐨勭姸鎬�
+ // foreach (var stockGood in palletStockGoods)
+ // {
+ // stockGood.OutboundQuantity = 0;
+
+ // await _stockInfoDetailService.Db.Updateable(stockGood).ExecuteCommandAsync();
+ // }
+ // // 濡傛灉娌℃湁鍒涘缓浠诲姟锛屽垱寤哄洖搴撲换鍔�
+ // if (!tasks.Any())
+ // {
+ // var newLocation = _locationInfoService.AssignLocation(firstlocation.LocationType);
+ // CreateReturnTask(tasks, task, palletCode, newLocation);
+ // }
+
+
+ // }
+
+ // var allSplitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
+ // .Where(it => it.OrderNo == orderNo && it.PalletCode == palletCode && !it.IsReverted)
+ // .ToListAsync();
+
+ // foreach (var record in allSplitRecords)
+ // {
+ // record.Status = (int)SplitPackageStatusEnum.宸插洖搴�;
+ // await _splitPackageService.Db.Updateable(record).ExecuteCommandAsync();
+ // }
+ // // 淇濆瓨浠诲姟 缁橢SS涓嬪彂浠诲姟
+ // if (tasks.Any())
+ // {
+ // try
+ // {
+ // await _taskRepository.Db.Insertable(tasks).ExecuteCommandAsync();
+ // var targetAddress = task.TargetAddress;
+ // _taskRepository.DeleteData(task);
+
+ // // 缁� ESS 娴佸姩淇″彿鍜屽垱寤轰换鍔�
+ // try
+ // {
+ // var result = await _eSSApiService.MoveContainerAsync(new WIDESEA_DTO.Basic.MoveContainerRequest
+ // {
+ // slotCode = movestations[targetAddress],
+ // containerCode = palletCode
+ // });
+
+ // if (result)
+ // {
+ // TaskModel esstask = new TaskModel()
+ // {
+ // taskType = "putaway",
+ // taskGroupCode = "",
+ // groupPriority = 0,
+ // tasks = new List<TasksType>
+ // {
+ // new()
+ // {
+ // taskCode = tasks.First().TaskNum.ToString(),
+ // taskPriority = 0,
+ // taskDescribe = new TaskDescribeType {
+ // containerCode = palletCode,
+ // containerType = "CT_KUBOT_STANDARD",
+ // fromLocationCode = stations.GetValueOrDefault(targetAddress) ?? "",
+ // toStationCode = "",
+ // toLocationCode = tasks.First().TargetAddress,
+ // deadline = 0, storageTag = ""
+ // }
+ // }
+ // }
+ // };
+
+ // var resulttask = await _eSSApiService.CreateTaskAsync(esstask);
+ // _logger.LogInformation("ReturnRemaining 鍒涘缓浠诲姟杩斿洖: " + resulttask);
+ // }
+ // }
+ // catch (Exception ex)
+ // {
+ // _logger.LogInformation("ReturnRemaining 鍒涘缓浠诲姟杩斿洖 catch err: " + ex.Message);
+ // }
+
+ // _unitOfWorkManage.CommitTran();
+ // return WebResponseContent.Instance.OK($"鍥炲簱鎿嶄綔鎴愬姛锛屽叡鍥炲簱鏁伴噺锛歿totalReturnQty}");
+ // }
+ // catch (Exception ex)
+ // {
+ // _unitOfWorkManage.RollbackTran();
+ // return WebResponseContent.Instance.Error($"鍒涘缓鍥炲簱浠诲姟澶辫触: {ex.Message}");
+ // }
+ // }
+
+ // _unitOfWorkManage.RollbackTran();
+ // return WebResponseContent.Instance.Error("鏈垱寤轰换浣曞洖搴撲换鍔�");
+ // }
+ // catch (Exception ex)
+ // {
+ // _unitOfWorkManage.RollbackTran();
+ // return WebResponseContent.Instance.Error($"鍥炲簱鎿嶄綔澶辫触: {ex.Message}");
+ // }
+ //}
+
+
+ /// <summary>
+ /// 鍒涘缓鍥炲簱浠诲姟
+ /// </summary>
+ private void CreateReturnTask(List<Dt_Task> tasks, Dt_Task originalTask, string palletCode, Dt_LocationInfo newLocation)
+ {
+ Dt_Task newTask = new()
+ {
+ CurrentAddress = stations[originalTask.TargetAddress],
+ Grade = 0,
+ PalletCode = palletCode,
+ NextAddress = "",
+ OrderNo = originalTask.OrderNo,
+ Roadway = newLocation.RoadwayNo,
+ SourceAddress = stations[originalTask.TargetAddress],
+ TargetAddress = newLocation.LocationCode,
+ TaskStatus = TaskStatusEnum.New.ObjToInt(),
+ TaskType = TaskTypeEnum.InPick.ObjToInt(),
+ PalletType = originalTask.PalletType,
+ WarehouseId = originalTask.WarehouseId,
+
+ };
+ tasks.Add(newTask);
+ }
+
+ /// <summary>
+ /// 妫�鏌ユ墭鐩樻槸鍚﹂渶瑕佸洖搴撶殑杈呭姪鏂规硶
+ /// </summary>
+ public async Task<bool> CheckPalletNeedReturn(string orderNo, string palletCode)
+ {
+ // 1. 妫�鏌ユ槸鍚︽湁鏈垎鎷g殑鍑哄簱璁板綍
+ var hasUnpickedLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(it => it.OrderNo == orderNo && it.PalletCode == palletCode && it.Status == 1)
+ .AnyAsync();
+
+ if (hasUnpickedLocks)
+ return true;
+
+ // 2. 妫�鏌ュ嚭搴撴槸鍚﹀凡瀹屾垚浣嗘墭鐩樿繕鏈夊簱瀛樿揣鐗�
+ var outboundFinished = !await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(it => it.PalletCode == palletCode && it.Status == 1)
+ .AnyAsync();
+
+ var stockinfo = _stockInfoService.Db.Queryable<Dt_StockInfo>().First(x => x.PalletCode == palletCode);
+
+
+ var hasRemainingGoods = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ .Where(it => it.StockId == stockinfo.Id && it.Status == StockStatusEmun.鍏ュ簱纭.ObjToInt())
+ .Where(it => it.OutboundQuantity == 0 || it.OutboundQuantity < it.StockQuantity)
+ .AnyAsync();
+
+ return outboundFinished && hasRemainingGoods;
+ }
+
+
+ /// <summary>
+ /// 鑾峰彇鎷嗗寘閾撅紙浠庡綋鍓嶆潯鐮佽拷婧埌鍘熷鏉$爜锛�
+ /// </summary>
+ // 鍦� GetSplitChain 鏂规硶涓坊鍔犳洿涓ユ牸鐨勯獙璇�
+ private async Task<List<SplitChainItem>> GetSplitChain(string currentBarcode)
+ {
+ var chain = new List<SplitChainItem>();
+ var visited = new HashSet<string>();
+
+ string current = currentBarcode;
+ int maxDepth = 10; // 闃叉鏃犻檺寰幆
+
+ while (!string.IsNullOrEmpty(current) && maxDepth > 0)
+ {
+ maxDepth--;
+
+ if (visited.Contains(current))
+ {
+ _logger.LogWarning($"妫�娴嬪埌寰幆寮曠敤鍦ㄦ媶鍖呴摼涓�: {current}");
+ break;
+ }
+
+ visited.Add(current);
+
+ var splitRecord = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
+ .Where(it => it.NewBarcode == current && !it.IsReverted)
+ .FirstAsync();
+
+ if (splitRecord == null)
+ break;
+
+ // 楠岃瘉鎷嗗寘璁板綍鐨勫畬鏁存��
+ if (string.IsNullOrEmpty(splitRecord.OriginalBarcode))
+ {
+ _logger.LogError($"鎷嗗寘璁板綍 {splitRecord.Id} 缂哄皯鍘熷鏉$爜");
+ break;
+ }
+
+ var item = new SplitChainItem
+ {
+ SplitRecord = splitRecord,
+ OriginalBarcode = splitRecord.OriginalBarcode,
+ NewBarcode = splitRecord.NewBarcode,
+ SplitQuantity = splitRecord.SplitQty
+ };
+
+ chain.Add(item);
+
+ current = splitRecord.OriginalBarcode;
+ }
+
+ if (maxDepth <= 0)
+ {
+ _logger.LogWarning($"鎷嗗寘閾捐拷婧揪鍒版渶澶ф繁搴�: {currentBarcode}");
+ }
+
+ chain.Reverse();
+ return chain;
+ }
+ /// <summary>
+ /// 澶勭悊鎷嗗寘閾剧殑鍙栨秷鍒嗘嫞
+ /// </summary>
+ private async Task HandleSplitChainCancel(string orderNo, string palletCode, string barcode,
+ decimal cancelQty, Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord, List<SplitChainItem> splitChain)
+ {
+ if (!splitChain.Any())
+ return;
+
+ // 鎵惧埌鍘熷鏉$爜锛堥摼鐨勭涓�涓級
+ var originalSplitItem = splitChain.First();
+ var originalBarcode = originalSplitItem.OriginalBarcode;
+
+ // 鏌ユ壘鍘熷鏉$爜鐨勯攣瀹氫俊鎭拰搴撳瓨
+ var originalLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(it => it.CurrentBarcode == originalBarcode && it.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
+ .FirstAsync();
+
+ var originalStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ .Where(it => it.Barcode == originalBarcode && it.StockId == originalLockInfo.StockId)
+ .FirstAsync();
+
+ if (originalLockInfo == null || originalStockDetail == null)
+ throw new Exception("鏈壘鍒板師濮嬫潯鐮佺殑閿佸畾淇℃伅鎴栧簱瀛樹俊鎭�");
+
+ // 鎭㈠鍘熷鏉$爜搴撳瓨锛堝皢鍙栨秷鐨勬暟閲忓姞鍥炲幓锛�
+ originalStockDetail.StockQuantity += cancelQty;
+ originalStockDetail.OutboundQuantity += cancelQty;
+ await _stockInfoDetailService.Db.Updateable(originalStockDetail).ExecuteCommandAsync();
+
+ // 鎭㈠鍘熷鏉$爜閿佸畾淇℃伅
+ originalLockInfo.AssignQuantity += cancelQty;
+ await _outStockLockInfoService.Db.Updateable(originalLockInfo).ExecuteCommandAsync();
+
+ // 鍒犻櫎鎷嗗寘閾句腑鎵�鏈夋柊鏉$爜鐨勯攣瀹氫俊鎭拰搴撳瓨璁板綍
+ var allNewBarcodes = splitChain.Select(x => x.NewBarcode).ToList();
+
+ // 鍒犻櫎閿佸畾淇℃伅
+ await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>()
+ .Where(it => allNewBarcodes.Contains(it.CurrentBarcode))
+ .ExecuteCommandAsync();
+
+ // 鍒犻櫎搴撳瓨璁板綍锛堝彧鍒犻櫎鎷嗗寘浜х敓鐨勬柊鏉$爜搴撳瓨锛屼繚鐣欏師濮嬫潯鐮侊級
+ await _stockInfoDetailService.Db.Deleteable<Dt_StockInfoDetail>()
+ .Where(it => allNewBarcodes.Contains(it.Barcode) && it.Barcode != originalBarcode)
+ .ExecuteCommandAsync();
+
+ // 鏇存柊鎷嗗寘閾句腑鎵�鏈夋媶鍖呰褰曠姸鎬佷负宸叉媶鍖�
+ foreach (var chainItem in splitChain)
+ {
+ chainItem.SplitRecord.Status = (int)SplitPackageStatusEnum.宸叉媶鍖�;
+ await _splitPackageService.Db.Updateable(chainItem.SplitRecord).ExecuteCommandAsync();
+ }
+
+ // 鎭㈠璁㈠崟鏄庣粏鎷i�夋暟閲忥紙浣跨敤鍘熷閿佸畾淇℃伅鐨勮鍗曟槑缁咺D锛�
+ await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+ .SetColumns(it => it.PickedQty == it.PickedQty - cancelQty)
+ .Where(it => it.Id == originalLockInfo.OrderDetailId)
+ .ExecuteCommandAsync();
+
+ // 鎭㈠璁㈠崟鐘舵��
+ await CheckAndRevertOrderStatus(orderNo);
+
+ // 鍒犻櫎鎷i�夎褰�
+ await Db.Deleteable<Dt_PickingRecord>()
+ .Where(it => it.Id == pickingRecord.Id)
+ .ExecuteCommandAsync();
+
+ //// 璁板綍鍙栨秷鎿嶄綔鍘嗗彶
+ //await RecordCancelHistory(orderNo, palletCode, barcode, cancelQty, pickingRecord.Id,
+ // lockInfo.MaterielCode, "鍙栨秷鎷嗗寘閾惧垎鎷�");
+ }
+
+ /// <summary>
+ /// 澶勭悊鏅�氭潯鐮佺殑鍙栨秷鍒嗘嫞
+ /// </summary>
+ private async Task HandleNormalBarcodeCancel(string orderNo, string palletCode, string barcode,
+ decimal cancelQty, Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord)
+ {
+ // 1. 鏌ユ壘搴撳瓨淇℃伅
+ var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+ .Where(it => it.Barcode == barcode && it.StockId == lockInfo.StockId)
+ .FirstAsync();
+
+ if (stockDetail == null)
+ throw new Exception("鏈壘鍒板搴旂殑搴撳瓨淇℃伅");
+
+ // 2. 鎭㈠搴撳瓨鏁伴噺
+ if (stockDetail.StockQuantity == 0)
+ {
+ // 鏁村寘鍑哄簱鐨勬儏鍐�
+ stockDetail.StockQuantity = cancelQty;
+ stockDetail.OutboundQuantity = cancelQty;
+ }
+ else
+ {
+ // 閮ㄥ垎鍑哄簱鐨勬儏鍐�
+ stockDetail.StockQuantity += cancelQty;
+ stockDetail.OutboundQuantity += cancelQty;
+ }
+ await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
+
+ // 3. 鎭㈠閿佸畾淇℃伅鐘舵��
+ lockInfo.AssignQuantity += cancelQty;
+ lockInfo.PickedQty -= cancelQty;
+
+ if (lockInfo.PickedQty == 0)
+ {
+ lockInfo.Status = (int)OutLockStockStatusEnum.鍑哄簱涓�;
+ }
+ await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
+
+ // 4. 澶勭悊鐩稿叧鐨勬媶鍖呰褰曠姸鎬佹仮澶�
+ var relatedSplitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
+ .Where(it => it.OriginalBarcode == barcode &&
+ it.Status == (int)SplitPackageStatusEnum.宸叉嫞閫�)
+ .ToListAsync();
+
+ foreach (var record in relatedSplitRecords)
+ {
+ record.Status = (int)SplitPackageStatusEnum.宸叉媶鍖�;
+ await _splitPackageService.Db.Updateable(record).ExecuteCommandAsync();
+ }
+
+ // 5. 鎭㈠璁㈠崟鏄庣粏鐨勬嫞閫夋暟閲�
+ await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+ .SetColumns(it => it.PickedQty == it.PickedQty - cancelQty)
+ .Where(it => it.Id == lockInfo.OrderDetailId)
+ .ExecuteCommandAsync();
+
+ // 6. 鎭㈠璁㈠崟鐘舵��
+ await CheckAndRevertOrderStatus(orderNo);
+
+ // 7. 鍒犻櫎鎷i�夎褰�
+ await Db.Deleteable<Dt_PickingRecord>().Where(it => it.Id == pickingRecord.Id).ExecuteCommandAsync();
+
+ //// 8. 璁板綍鍙栨秷鎿嶄綔鍘嗗彶
+ //await RecordCancelHistory(orderNo, palletCode, barcode, cancelQty, pickingRecord.Id,
+ // lockInfo.MaterielCode, "鍙栨秷鍒嗘嫞");
+ }
+
+ /// <summary>
+ /// 妫�鏌ュ苟鎭㈠璁㈠崟鐘舵��
+ /// </summary>
+ private async Task CheckAndRevertOrderStatus(string orderNo)
+ {
+ var order = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>()
+ .Where(x => x.OrderNo == orderNo)
+ .FirstAsync();
+
+ if (order != null && order.OrderStatus == OutOrderStatusEnum.鍑哄簱瀹屾垚.ObjToInt())
+ {
+ await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
+ .SetColumns(x => x.OrderStatus == OutOrderStatusEnum.鍑哄簱涓�.ObjToInt())
+ .Where(x => x.OrderNo == orderNo)
+ .ExecuteCommandAsync();
+ }
+ }
+
+
+
+
+ // 鑾峰彇鏈嫞閫夊垪琛�
+ public async Task<List<Dt_OutStockLockInfo>> GetUnpickedList(string orderNo, string palletCode)
+ {
+ var list = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(x => x.OrderNo == orderNo &&
+ x.PalletCode == palletCode &&
+ x.Status == 1)
+ .ToListAsync();
+ return list.Where(x => x.RemainQuantity > 0).ToList();
+ }
+
+ // 鑾峰彇宸叉嫞閫夊垪琛�
+ public async Task<List<Dt_OutStockLockInfo>> GetPickedList(string orderNo, string palletCode)
+ {
+ var list = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .Where(x => x.OrderNo == orderNo &&
+ x.PalletCode == palletCode &&
+ x.Status == 6)
+ .ToListAsync();
+ return list;
+ }
+ // 鑾峰彇鎷i�夋眹鎬�
+ public async Task<object> GetPickingSummary(ConfirmPickingDto dto)
+ {
+ var picked = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .WhereIF(!string.IsNullOrEmpty(dto.OrderNo), x => x.OrderNo == dto.OrderNo)
+ .WhereIF(!string.IsNullOrEmpty(dto.PalletCode), x => x.PalletCode == dto.PalletCode)
+ .Where(x => x.Status == 6)
+ .GroupBy(x => new { x.PalletCode, x.MaterielCode })
+ .Select(x => new SummaryPickingDto
+ {
+ PalletCode = x.PalletCode,
+ MaterielCode = x.MaterielCode,
+ pickedCount = SqlFunc.AggregateCount(x.Id)
+ }).FirstAsync();
+ if (picked == null)
+ {
+ picked = new SummaryPickingDto { pickedCount = 0 };
+ }
+
+ var summary = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+ .WhereIF(!string.IsNullOrEmpty(dto.OrderNo), x => x.OrderNo == dto.OrderNo)
+ .WhereIF(!string.IsNullOrEmpty(dto.PalletCode), x => x.PalletCode == dto.PalletCode)
+ .Where(x => x.Status == 1)
+ .GroupBy(x => new { x.PalletCode, x.MaterielCode })
+ .Select(x => new SummaryPickingDto
+ {
+ PalletCode = x.PalletCode,
+ MaterielCode = x.MaterielCode,
+ UnpickedCount = SqlFunc.AggregateCount(x.Id),
+ UnpickedQuantity = SqlFunc.AggregateSum(x.AssignQuantity) - SqlFunc.AggregateSum(x.PickedQty),
+
+ }).FirstAsync();
+ if (summary == null)
+ {
+ summary = new SummaryPickingDto { pickedCount = 0 };
+ }
+ summary.pickedCount = picked.pickedCount;
+
+ return summary;
+ }
/// <summary>
/// 鑾峰彇鎷i�夊巻鍙�
/// </summary>
@@ -173,69 +1807,6 @@
.ToListAsync();
}
- /// <summary>
- /// 鎾ら攢鎷i��
- /// </summary>
- public async Task<WebResponseContent> CancelPicking(CancelPickingRequest request)
- {
- // 瀹炵幇鎾ら攢鎷i�夌殑閫昏緫锛岄渶瑕侊細
- // 1. 鎭㈠搴撳瓨鍑哄簱鏁伴噺
- // 2. 鎭㈠閿佸畾淇℃伅鐨勫凡鎷i�夋暟閲�
- // 3. 鎭㈠鍑哄簱鍗曟槑缁嗙殑宸插嚭鏁伴噺鍜岄攣瀹氭暟閲�
- // 4. 鍒犻櫎鎴栨爣璁版嫞閫夊巻鍙茶褰�
- // 娉ㄦ剰锛氳繖閲岄渶瑕佷簨鍔″鐞�
- try
- {
- _unitOfWorkManage.BeginTran();
-
- var pickHistory = await Db.Queryable<Dt_PickingRecord>()
- .Where(x => x.Id == request.PickingHistoryId)
- .FirstAsync();
-
- if (pickHistory == null)
- return WebResponseContent.Instance.Error("鏈壘鍒版嫞閫夎褰�");
-
- // 鎭㈠搴撳瓨
- var stockDetail = await _stockInfoService.Db.Queryable<Dt_StockInfoDetail>()
- .Where(x => x.Barcode == pickHistory.Barcode && x.StockId == pickHistory.StockId)
- .FirstAsync();
- if (stockDetail != null)
- {
- stockDetail.OutboundQuantity -= pickHistory.PickQuantity;
- await _stockInfoService.Db.Updateable(stockDetail).ExecuteCommandAsync();
- }
- // 鎭㈠閿佸畾淇℃伅
- var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
- .Where(x => x.OrderDetailId == pickHistory.OrderDetailId && x.StockId == pickHistory.StockId)
- .FirstAsync();
- lockInfo.PickedQty -= pickHistory.PickQuantity;
- await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
-
- // 鎭㈠鍑哄簱鍗曟槑缁�
- var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
- .Where(x => x.Id == pickHistory.OrderDetailId)
- .FirstAsync();
- orderDetail.OverOutQuantity -= pickHistory.PickQuantity;
- orderDetail.LockQuantity += pickHistory.PickQuantity;
- if (orderDetail.OverOutQuantity < orderDetail.OrderQuantity)
- {
- orderDetail.OrderDetailStatus = orderDetail.LockQuantity > 0 ?
- (int)OrderDetailStatusEnum.Outbound : (int)OrderDetailStatusEnum.AssignOverPartial;
- }
- await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
-
- // 鍒犻櫎鎷i�夊巻鍙茶褰�
- await Db.Deleteable<Dt_PickingRecord>().Where(x => x.Id == request.PickingHistoryId).ExecuteCommandAsync();
-
- _unitOfWorkManage.CommitTran();
- return WebResponseContent.Instance.OK("鎾ら攢鎴愬姛");
- }
- catch (Exception ex)
- {
- _unitOfWorkManage.RollbackTran();
- return WebResponseContent.Instance.Error($"鎾ら攢澶辫触: {ex.Message}");
- }
- }
/// <summary>
/// 鑾峰彇鎵樼洏鐨勫嚭搴撶姸鎬佷俊鎭�
@@ -306,50 +1877,59 @@
{
_unitOfWorkManage.BeginTran();
- // 1. 鑾峰彇鎵樼洏搴撳瓨淇℃伅
var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>()
.Includes(x => x.Details)
- .Where(x => x.PalletCode == request.PalletCode)
- .FirstAsync();
+ .Where(x => x.PalletCode == request.PalletCode).FirstAsync();
if (stockInfo == null)
return WebResponseContent.Instance.Error("鏈壘鍒版墭鐩樺簱瀛樹俊鎭�");
- // 2. 鑾峰彇鐩稿叧鐨勫嚭搴撻攣瀹氫俊鎭�
+
var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
- .Where(x => x.PalletCode == request.PalletCode &&
- x.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
+ .Where(x => x.OrderNo == request.OrderNo && x.PalletCode == request.PalletCode)
.ToListAsync();
- // 3. 鏁翠釜鎵樼洏鍑哄簱 - 璁剧疆鍑哄簱鏁伴噺绛変簬搴撳瓨鏁伴噺
- foreach (var detail in stockInfo.Details)
- {
- decimal outboundQuantity = detail.StockQuantity - detail.OutboundQuantity;
- detail.OutboundQuantity = detail.StockQuantity; // 鍏ㄩ儴鍑哄簱
- await _stockInfoDetailService.Db.Updateable(detail).ExecuteCommandAsync();
- }
- // 4. 鏇存柊鍑哄簱閿佸畾淇℃伅
foreach (var lockInfo in lockInfos)
{
- decimal unpicked = lockInfo.AssignQuantity - lockInfo.PickedQty;
- lockInfo.PickedQty += unpicked; // 鏍囪涓哄叏閮ㄦ嫞閫�
+ if (lockInfo.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
+ {
+ lockInfo.PickedQty = lockInfo.AssignQuantity;
+ }
lockInfo.Status = (int)OutLockStockStatusEnum.宸插嚭搴�;
await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
- // 鏇存柊鍑哄簱鍗曟槑缁�
var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
- .Where(x => x.Id == lockInfo.OrderDetailId)
- .FirstAsync();
- orderDetail.OverOutQuantity += unpicked;
- orderDetail.LockQuantity -= unpicked;
- orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.Over;
- orderDetail.LockQuantity = 0;
-
- await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
+ .Where(x => x.Id == lockInfo.OrderDetailId)
+ .FirstAsync();
+ if (orderDetail != null)
+ {
+ orderDetail.OverOutQuantity += lockInfo.PickedQty;
+ orderDetail.LockQuantity -= lockInfo.PickedQty;
+ orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.Over;
+ orderDetail.LockQuantity = 0;
+ await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
+ }
+ }
+ var groupDetails = lockInfos.GroupBy(x => x.OrderDetailId).Select(x => new
+ {
+ OrderDetailId = x.Key,
+ TotalQuantity = x.Sum(o => o.PickedQty)
+ }).ToList();
+ foreach (var item in groupDetails)
+ {
+ var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>().Where(x => x.Id == item.OrderDetailId).FirstAsync();
+ if (orderDetail != null)
+ {
+ orderDetail.OverOutQuantity = item.TotalQuantity;
+ orderDetail.LockQuantity = 0;
+ orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.Over;
+ await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
+ }
}
- // 5. 鏇存柊鎷嗗寘璁板綍鐘舵��
+ await CheckAndUpdateOrderStatus(request.OrderNo);
+
var lockInfoIds = lockInfos.Select(x => x.Id).ToList();
var splitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
.Where(x => lockInfoIds.Contains(x.OutStockLockInfoId) &&
@@ -362,7 +1942,7 @@
await _splitPackageService.Db.Updateable(record).ExecuteCommandAsync();
}
- // 6. 娓呯┖璐т綅
+
var location = await _locationInfoService.Db.Queryable<Dt_LocationInfo>()
.Where(x => x.LocationCode == stockInfo.LocationCode)
.FirstAsync();
@@ -371,6 +1951,14 @@
location.LocationStatus = (int)LocationStatusEnum.Free;
await _locationInfoService.Db.Updateable(location).ExecuteCommandAsync();
}
+
+ foreach (var detail in stockInfo.Details)
+ {
+ await _stockInfoDetailService.Db.Deleteable(detail).ExecuteCommandAsync();
+ }
+ await _stockInfoService.Db.Deleteable(stockInfo).ExecuteCommandAsync();
+
+
_unitOfWorkManage.CommitTran();
return WebResponseContent.Instance.OK("鐩存帴鍑哄簱鎴愬姛");
@@ -383,4 +1971,33 @@
}
}
+
+ #region 杩斿洖
+ /// <summary>
+ /// 鎷嗗寘閾鹃」
+ /// </summary>
+ public class SplitChainItem
+ {
+ public Dt_SplitPackageRecord SplitRecord { get; set; }
+ public string OriginalBarcode { get; set; }
+ public string NewBarcode { get; set; }
+ public decimal SplitQuantity { get; set; }
+ }
+ 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>();
+ }
+
+ #endregion
+
}
--
Gitblit v1.9.3