pan
2025-11-27 1a1bc81ac1d9ad656e15b409122e23f7f3763293
提交
已修改11个文件
876 ■■■■ 文件已修改
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_AllocateService/AllocateService.cs 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_DTO/Stock/StockSelectViewDTO.cs 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IStockService/IStockInfoService.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Model/Models/Allocate/Dt_AllocateOrderDetail.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderDetailService.cs 248 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs 161 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/WIDESEA_OutboundService.csproj 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoService.cs 144 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs 195 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Allocate/AllocateOrderController.cs 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundOrderController.cs 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_AllocateService/AllocateService.cs
@@ -1,4 +1,5 @@
using MailKit.Search;
using Autofac.Core;
using MailKit.Search;
using Microsoft.Extensions.Logging;
using SqlSugar;
using SqlSugar.Extensions;
@@ -61,7 +62,7 @@
                {
                    1 => await AddAllocateOrder(allocateOrder),
                    2 => await UpdateAllocateOrder(allocateOrder),
                    3 => DeleteAllocateOrder(allocateOrder),
                    3 => await DeleteAllocateOrder(allocateOrder),
                    _ => WebResponseContent.Instance.OK(),
                };
@@ -82,33 +83,7 @@
                }
                allocateOrder.OrderNo = CreateCodeByRule(nameof(RuleCodeEnum.AllocateOrderCodeRule));
                Db.InsertNav(allocateOrder).Include(x => x.Details).ExecuteCommand();
                if (Enum.TryParse<BusinessTypeEnum>(allocateOrder.BusinessType, out var businessType))
                {
                    if (businessType == BusinessTypeEnum.智仓调外部仓库)
                    {
                        var inboundOrders = ConvertToInboundOrders(allocateOrder);
                        await _inboundService.InbounOrderService.ReceiveInboundOrder(inboundOrders, 1);
                    }
                    else if (businessType == BusinessTypeEnum.外部仓库调智仓 || businessType == BusinessTypeEnum.智仓调智仓)
                    {
                        if (businessType == BusinessTypeEnum.外部仓库调智仓)
                        {
                            allocateOrder.OrderType = InOrderTypeEnum.Allocat.ObjToInt();
                        }
                        else if (businessType == BusinessTypeEnum.智仓调智仓)
                        {
                            allocateOrder.OrderType = InOrderTypeEnum.InternalAllocat.ObjToInt();
                        }
                        var outboundOrders = ConvertToOutboundOrders(allocateOrder);
                        await _outboundService.OutboundOrderService.ReceiveOutboundOrder(outboundOrders, 1);
                    }
                    else
                    {
                        // å¤„理未定义的枚举值(如未来新增但未实现的类型)
                        throw new NotSupportedException($"不支持的业务类型枚举值: {businessType}");
                    }
                }
                await AddInOutData(allocateOrder);
                return WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
@@ -117,6 +92,39 @@
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        private async Task AddInOutData(Dt_AllocateOrder allocateOrder)
        {
            if (Enum.TryParse<BusinessTypeEnum>(allocateOrder.BusinessType, out var businessType))
            {
                if (businessType == BusinessTypeEnum.智仓调外部仓库)
                {
                    allocateOrder.OrderType = InOrderTypeEnum.Allocat.ObjToInt();
                    var inboundOrders = ConvertToInboundOrders(allocateOrder);
                    await _inboundService.InbounOrderService.ReceiveInboundOrder(inboundOrders, 1);
                }
                else if (businessType == BusinessTypeEnum.外部仓库调智仓 || businessType == BusinessTypeEnum.智仓调智仓)
                {
                    if (businessType == BusinessTypeEnum.外部仓库调智仓)
                    {
                        allocateOrder.OrderType = InOrderTypeEnum.Allocat.ObjToInt();
                    }
                    else if (businessType == BusinessTypeEnum.智仓调智仓)
                    {
                        allocateOrder.OrderType = InOrderTypeEnum.InternalAllocat.ObjToInt();
                    }
                    var outboundOrders = ConvertToOutboundOrders(allocateOrder);
                    await _outboundService.OutboundOrderService.ReceiveOutboundOrder(outboundOrders, 1);
                }
                else
                {
                    // å¤„理未定义的枚举值(如未来新增但未实现的类型)
                    throw new NotSupportedException($"不支持的业务类型枚举值: {businessType}");
                }
            }
        }
        public async Task<WebResponseContent> UpdateAllocateOrder(Dt_AllocateOrder model)
        {
            try
@@ -196,6 +204,10 @@
                _allocateOrderDetailRepository.AddData(allocateOrderDetails);
                BaseDal.UpdateData(allocateOrder);
                DeleteInOutData(model.UpperOrderNo, allocateOrder);
                await AddInOutData(allocateOrder);
                _unitOfWorkManage.CommitTran();
@@ -209,7 +221,7 @@
            }
        }
        public WebResponseContent DeleteAllocateOrder(Dt_AllocateOrder model)
        public async Task<WebResponseContent> DeleteAllocateOrder(Dt_AllocateOrder model)
        {
            try
            {
@@ -231,6 +243,9 @@
                    _allocateOrderDetailRepository.DeleteData(item);
                }
                BaseDal.DeleteData(allocateOrder);
                DeleteInOutData(model.UpperOrderNo, allocateOrder);
                _unitOfWorkManage.CommitTran();
                return WebResponseContent.Instance.OK();
            }
@@ -239,6 +254,26 @@
                _unitOfWorkManage.RollbackTran();
                _logger.LogInformation("AllocateService DeleteAllocateOrder  err:  " + ex.Message);
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        private void DeleteInOutData(string upperOrderNo, Dt_AllocateOrder allocateOrder)
        {
            if (Enum.TryParse<BusinessTypeEnum>(allocateOrder.BusinessType, out var businessType))
            {
                if (businessType == BusinessTypeEnum.智仓调外部仓库)
                {
                    _inboundService.InbounOrderService.Db.Deleteable<Dt_InboundOrder>().Where(x => x.UpperOrderNo == upperOrderNo).ExecuteCommand();
                    _inboundService.InboundOrderDetailService.Db.Deleteable<Dt_InboundOrderDetail>()
                     .Where(p => SqlFunc.Subqueryable<Dt_InboundOrder>().Where(s => s.Id == p.OrderId && s.UpperOrderNo == upperOrderNo).Any()).ExecuteCommand();
                }
                else if (businessType == BusinessTypeEnum.外部仓库调智仓 || businessType == BusinessTypeEnum.智仓调智仓)
                {
                    _outboundService.OutboundOrderService.Db.Deleteable<Dt_OutboundOrder>().Where(x => x.UpperOrderNo == upperOrderNo).ExecuteCommand();
                    _outboundService.OutboundOrderDetailService.Db.Deleteable<Dt_OutboundOrderDetail>()
                     .Where(p => SqlFunc.Subqueryable<Dt_OutboundOrder>().Where(s => s.Id == p.OrderId && s.UpperOrderNo == upperOrderNo).Any()).ExecuteCommand();
                }
            }
        }
@@ -288,7 +323,7 @@
                WarehouseId = allocateOrder.WarehouseId,
                OrderNo = allocateOrder.OrderNo,
                UpperOrderNo = allocateOrder.UpperOrderNo,
                OrderType = OutOrderTypeEnum.Allocate.ObjToInt(),
                OrderType = allocateOrder.OrderType,
                OrderStatus = allocateOrder.OrderStatus,
                CreateType = allocateOrder.CreateType,
                BusinessType = allocateOrder.BusinessType,
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_DTO/Stock/StockSelectViewDTO.cs
@@ -21,5 +21,12 @@
        public string Barcode { get; set; }
        public string BatchNo { get; set; }
        public string SupplyCode { get; set; }
        public DateTime StockCreateDate { get; set; }
        public int StockId { get; set; }
        public int? OrderDetailId { get; set; }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_IStockService/IStockInfoService.cs
@@ -13,7 +13,8 @@
        List<Dt_StockInfo> GetStockInfos(string materielCode, string lotNo, string supplyCode, List<string> locationCodes);
        List<Dt_StockInfo> GetUseableStocks(string materielCode, string batchNo,string supplyCode);
        Dt_StockInfo GetStockInfoByPalletCode(string palletCode);
        void AddMaterielGroup(Dt_StockInfo stockInfo);
        (List<Dt_StockInfo>, Dictionary<int, decimal>) GetOutboundStocks(List<Dt_StockInfo> stockInfos, string materielCode, decimal needQuantity, out decimal residueQuantity);
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Model/Models/Allocate/Dt_AllocateOrderDetail.cs
@@ -120,5 +120,7 @@
        /// </summary>
        [SugarColumn(IsNullable = true, ColumnDescription = "回传MES")]
        public int ReturnToMESStatus { get; set; } = 0;
        [SugarColumn(IsNullable = true, ColumnDescription = "过期日期")]
        public DateTime ValidDate { get; set; }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderDetailService.cs
@@ -336,71 +336,231 @@
        }
        public (List<Dt_StockInfo>, Dt_OutboundOrderDetail, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) AssignStockOutbound(Dt_OutboundOrderDetail outboundOrderDetail, List<StockSelectViewDTO> stockSelectViews)
        public (List<Dt_StockInfo>, Dt_OutboundOrderDetail, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>)
       AssignStockOutbound(Dt_OutboundOrderDetail outboundOrderDetail, List<StockSelectViewDTO> stockSelectViews)
        {
            // éªŒè¯ç”¨æˆ·é€‰æ‹©
            (bool, string) checkResult = CheckSelectStockDeital(outboundOrderDetail, stockSelectViews);
            if (!checkResult.Item1) throw new Exception(checkResult.Item2);
            Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == outboundOrderDetail.OrderId);
            var originalNeedQuantity = outboundOrderDetail.OrderQuantity - outboundOrderDetail.LockQuantity - outboundOrderDetail.MoveQty;
            var needQuantity = originalNeedQuantity;
            List<Dt_StockInfo> outStocks = new List<Dt_StockInfo>();
            List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>();
            List<Dt_StockInfo> outStocks = _stockService.StockInfoService.GetStockInfosByPalletCodes(stockSelectViews.Select(x => x.PalletCode).ToList());
            var assignQuantity = 0m;
            outStocks.ForEach(x =>
            {
                x.Details.ForEach(v =>
                {
                    assignQuantity += v.StockQuantity - v.OutboundQuantity;
                });
            });
            decimal remainingNeedQuantity = originalNeedQuantity;
            decimal totalAssignedFromUserSelection = 0;
            outboundOrderDetail.LockQuantity += assignQuantity;
            outStocks.ForEach(x =>
            // æŒ‰å…ˆè¿›å…ˆå‡ºæŽ’序用户选择的库存
            var userSelectedStocks = _stockService.StockInfoService.GetStockInfosByPalletCodes(
                stockSelectViews.Select(x => x.PalletCode).ToList());
            var sortedUserSelectedStocks = userSelectedStocks
                .OrderBy(x => x.CreateDate)
                .ToList();
            // åˆ†é…ç”¨æˆ·é€‰æ‹©çš„库存
            foreach (var stock in sortedUserSelectedStocks)
            {
                x.Details.ForEach(v =>
                if (remainingNeedQuantity <= 0) break;
                // èŽ·å–ç”¨æˆ·å¯¹è¯¥æ‰˜ç›˜çš„é€‰æ‹©æ•°é‡
                var userSelection = stockSelectViews.FirstOrDefault(x => x.PalletCode == stock.PalletCode);
                if (userSelection == null) continue;
                // è®¡ç®—该托盘实际可用数量
                var availableQuantity = CalculateAvailableQuantity(stock, outboundOrderDetail.MaterielCode,
                    outboundOrderDetail.BatchNo, outboundOrderDetail.SupplyCode);
                // ç¡®å®šåˆ†é…æ•°é‡ï¼šå–用户选择数量、可用数量和剩余需求的最小值
                var assignQuantity = Math.Min(
                    Math.Min(userSelection.UseableQuantity, availableQuantity),
                    remainingNeedQuantity);
                if (assignQuantity <= 0) continue;
                // æ‰§è¡Œåˆ†é…
                var actualAssigned = AssignStockQuantity(stock, outboundOrderDetail, assignQuantity);
                if (actualAssigned > 0)
                {
                    v.OutboundQuantity = v.StockQuantity;
                });
            });
            needQuantity -= assignQuantity;
            if (outboundOrderDetail.OrderQuantity > outboundOrderDetail.LockQuantity)
            {
                List<Dt_StockInfo> stockInfos = _stockService.StockInfoService.GetUseableStocks(outboundOrderDetail.MaterielCode, outboundOrderDetail.BatchNo, "");
                stockInfos = stockInfos.Where(x => !stockSelectViews.Select(v => v.PalletCode).Contains(x.PalletCode)).ToList();
                var (autoAssignStocks, stockAllocations) = _stockService.StockInfoService.GetOutboundStocks(stockInfos, outboundOrderDetail.MaterielCode, needQuantity, out decimal residueQuantity);
                outboundOrderDetail.LockQuantity += needQuantity - residueQuantity;
                outStocks.AddRange(autoAssignStocks);
                outboundOrderDetail.OrderDetailStatus = OrderDetailStatusEnum.AssignOver.ObjToInt();
                if (residueQuantity > 0)
                {
                    outboundOrderDetail.OrderDetailStatus = OrderDetailStatusEnum.AssignOverPartial.ObjToInt();
                    outStocks.Add(stock);
                    totalAssignedFromUserSelection += actualAssigned;
                    remainingNeedQuantity -= actualAssigned;
                    // åˆ›å»ºé”å®šè®°å½•
                    var lockInfo = CreateOutStockLockInfo(outboundOrder, outboundOrderDetail, stock, actualAssigned);
                    outStockLockInfos.Add(lockInfo);
                }
            }
            List<Dt_OutStockLockInfo> outStockLockInfos = _outStockLockInfoService.GetOutStockLockInfos(outboundOrder, outboundOrderDetail, outStocks);
            // æ£€æŸ¥ç”¨æˆ·é€‰æ‹©æ˜¯å¦è‡³å°‘分配了一部分
            if (totalAssignedFromUserSelection <= 0)
            {
                throw new Exception("用户选择的库存无法分配任何数量");
            }
            // å¦‚果用户选择的库存不够,自动分配剩余部分
            decimal autoAssignedQuantity = 0;
            if (remainingNeedQuantity > 0)
            {
                List<Dt_StockInfo> autoStocks = _stockService.StockInfoService.GetUseableStocks(
                    outboundOrderDetail.MaterielCode, outboundOrderDetail.BatchNo, "");
                // æŽ’除用户已选择的托盘
                autoStocks = autoStocks
                    .Where(x => !stockSelectViews.Select(v => v.PalletCode).Contains(x.PalletCode))
                    .ToList();
                var (autoAssignStocks, stockAllocations) = _stockService.StockInfoService.GetOutboundStocks(
                    autoStocks, outboundOrderDetail.MaterielCode, remainingNeedQuantity, out decimal residueQuantity);
                // æ£€æŸ¥è‡ªåŠ¨åˆ†é…ç»“æžœ
                autoAssignedQuantity = remainingNeedQuantity - residueQuantity;
                if (autoAssignedQuantity <= 0 && remainingNeedQuantity > 0)
                {
                    // éƒ¨åˆ†åˆ†é…æ˜¯å¯ä»¥æŽ¥å—的,记录警告但不报错
                    _logger.LogWarning($"自动分配失败,剩余需求{remainingNeedQuantity}无法满足");
                }
                else if (autoAssignedQuantity > 0)
                {
                    outStocks.AddRange(autoAssignStocks);
                    // ä¸ºè‡ªåŠ¨åˆ†é…çš„åº“å­˜åˆ›å»ºé”å®šè®°å½•
                    var autoLockInfos = CreateLockInfosForAutoAssign(outboundOrder, outboundOrderDetail, autoAssignStocks, stockAllocations);
                    outStockLockInfos.AddRange(autoLockInfos);
                }
            }
            // æ›´æ–°é”å®šæ•°é‡
            outboundOrderDetail.LockQuantity += totalAssignedFromUserSelection + autoAssignedQuantity;
            // æ›´æ–°çŠ¶æ€
            UpdateOrderDetailStatus(outboundOrderDetail, remainingNeedQuantity - autoAssignedQuantity);
            List<Dt_LocationInfo> locationInfos = _locationInfoService.GetLocationInfos(outStocks.Select(x => x.LocationCode).ToList());
            return (outStocks, outboundOrderDetail, outStockLockInfos, locationInfos);
        }
        private (bool, string) CheckSelectStockDeital(Dt_OutboundOrderDetail outboundOrderDetail, List<StockSelectViewDTO> stockSelectViews)
        // è¾…助方法
        private decimal CalculateAvailableQuantity(Dt_StockInfo stock, string materielCode, string batchNo, string supplyCode)
        {
            if (outboundOrderDetail == null)
            {
                return (false, "未找到出库单明细信息");
            }
            if (outboundOrderDetail.OrderDetailStatus != OrderDetailStatusEnum.New.ObjToInt() && outboundOrderDetail.OrderDetailStatus != OrderDetailStatusEnum.AssignOverPartial.ObjToInt())
            {
                return (false, "该明细不可操作");
            }
            //if (stockSelectViews.Sum(x => x.UseableQuantity) > outboundOrderDetail.OrderQuantity - outboundOrderDetail.LockQuantity - outboundOrderDetail.MoveQty)
            //{
            //    return (false, "选择数量超出单据数量");
            //}
            return (true, "成功");
            var relevantDetails = stock.Details
                .Where(d => d.MaterielCode == materielCode &&
                           (string.IsNullOrEmpty(batchNo) || d.BatchNo == batchNo) &&
                           (string.IsNullOrEmpty(supplyCode) || d.SupplyCode == supplyCode))
                .ToList();
            return relevantDetails.Sum(d => d.StockQuantity - d.OutboundQuantity);
        }
        private decimal AssignStockQuantity(Dt_StockInfo stock, Dt_OutboundOrderDetail detail, decimal assignQuantity)
        {
            decimal remainingAssign = assignQuantity;
            // æŒ‰å…ˆè¿›å…ˆå‡ºåˆ†é…åº“存明细
            var sortedDetails = stock.Details
                .Where(d => d.MaterielCode == detail.MaterielCode &&
                           d.BatchNo == detail.BatchNo &&
                           (d.StockQuantity - d.OutboundQuantity) > 0)
                .OrderBy(d => d.CreateDate)
                .ToList();
            foreach (var stockDetail in sortedDetails)
            {
                if (remainingAssign <= 0) break;
                var available = stockDetail.StockQuantity - stockDetail.OutboundQuantity;
                var assign = Math.Min(available, remainingAssign);
                stockDetail.OutboundQuantity += assign;
                remainingAssign -= assign;
            }
            return assignQuantity - remainingAssign; // è¿”回实际分配数量
        }
        private Dt_OutStockLockInfo CreateOutStockLockInfo(Dt_OutboundOrder outboundOrder, Dt_OutboundOrderDetail detail,
            Dt_StockInfo stock, decimal quantity)
        {
            var barcode = stock.Details
                .Where(d => !string.IsNullOrEmpty(d.Barcode))
                .Select(d => d.Barcode)
                .FirstOrDefault();
            return _outStockLockInfoService.GetOutStockLockInfo(outboundOrder, detail, stock, quantity, barcode);
        }
        private List<Dt_OutStockLockInfo> CreateLockInfosForAutoAssign(Dt_OutboundOrder outboundOrder,
            Dt_OutboundOrderDetail detail, List<Dt_StockInfo> stocks, Dictionary<int, decimal> allocations)
        {
            var lockInfos = new List<Dt_OutStockLockInfo>();
            foreach (var stock in stocks.OrderBy(x => x.CreateDate))
            {
                if (allocations.TryGetValue(stock.Id, out decimal quantity) && quantity > 0)
                {
                    var lockInfo = CreateOutStockLockInfo(outboundOrder, detail, stock, quantity);
                    lockInfos.Add(lockInfo);
                }
            }
            return lockInfos;
        }
        private void UpdateOrderDetailStatus(Dt_OutboundOrderDetail detail, decimal remainingQuantity)
        {
            if (remainingQuantity <= 0)
            {
                detail.OrderDetailStatus = OrderDetailStatusEnum.AssignOver.ObjToInt();
            }
            else
            {
                detail.OrderDetailStatus = OrderDetailStatusEnum.AssignOverPartial.ObjToInt();
            }
        }
        private (bool, string) CheckSelectStockDeital(Dt_OutboundOrderDetail outboundOrderDetail, List<StockSelectViewDTO> stockSelectViews)
        {
            var needQuantity = outboundOrderDetail.OrderQuantity - outboundOrderDetail.LockQuantity - outboundOrderDetail.MoveQty;
            if (needQuantity <= 0)
            {
                return (false, "出库单明细无需分配库存");
            }
            // æ£€æŸ¥æ€»é€‰æ‹©æ•°é‡æ˜¯å¦å¤§äºŽ0
            var totalSelected = stockSelectViews.Sum(x => x.UseableQuantity);
            if (totalSelected <= 0)
            {
                return (false, "用户选择的库存数量必须大于0");
            }
            // æ£€æŸ¥æ¯ä¸ªæ‰˜ç›˜çš„可用数量
            foreach (var selection in stockSelectViews)
            {
                if (selection.UseableQuantity <= 0)
                {
                    return (false, $"托盘[{selection.PalletCode}]的选择数量必须大于0");
                }
                var stock = _stockService.StockInfoService.GetStockInfoByPalletCode(selection.PalletCode);
                if (stock == null)
                {
                    return (false, $"托盘[{selection.PalletCode}]不存在");
                }
                var available = CalculateAvailableQuantity(stock, outboundOrderDetail.MaterielCode,
                    outboundOrderDetail.BatchNo, outboundOrderDetail.SupplyCode);
                if (available <= 0)
                {
                    return (false, $"托盘[{selection.PalletCode}]没有可用库存");
                }
            }
            return (true, "验证通过");
        }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs
@@ -20,9 +20,11 @@
using WIDESEA_Core.BaseServices;
using WIDESEA_Core.Enums;
using WIDESEA_Core.Helper;
using WIDESEA_DTO.Allocate;
using WIDESEA_DTO.Basic;
using WIDESEA_DTO.Inbound;
using WIDESEA_DTO.Outbound;
using WIDESEA_IAllocateService;
using WIDESEA_IBasicService;
using WIDESEA_IOutboundService;
using WIDESEA_IStockService;
@@ -50,6 +52,7 @@
        private readonly IESSApiService _eSSApiService;
        private readonly IInvokeMESService _invokeMESService;
        private readonly IDailySequenceService _dailySequenceService;
        private readonly IAllocateService _allocateService;
        private readonly ILogger<OutboundPickingService> _logger;
@@ -70,7 +73,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) : base(BaseDal)
        {
            _unitOfWorkManage = unitOfWorkManage;
            _stockInfoService = stockInfoService;
@@ -86,6 +89,7 @@
            _logger = logger;
            _invokeMESService = invokeMESService;
            _dailySequenceService = dailySequenceService;
            _allocateService = allocateService;
        }
@@ -1654,78 +1658,141 @@
        private async Task HandleOrderCompletion(Dt_OutboundOrder outboundOrder, string orderNo)
        {
            // è°ƒæ‹¨å‡ºåº“和重检出库不需要反馈MES
            if (outboundOrder.OrderType == OutOrderTypeEnum.Allocate.ObjToInt() ||
                outboundOrder.OrderType == OutOrderTypeEnum.ReCheck.ObjToInt())
            if (outboundOrder.OrderType == OutOrderTypeEnum.Allocate.ObjToInt())
            {
                return;
            }
            try
            {
                var feedmodel = new FeedbackOutboundRequestModel
                var allocate = _allocateService.Repository.QueryData(x => x.UpperOrderNo == outboundOrder.UpperOrderNo).First();
                var feedmodel = new AllocateDto
                {
                    reqCode = Guid.NewGuid().ToString(),
                    reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                    business_type = outboundOrder.BusinessType,
                    factoryArea = outboundOrder.FactoryArea,
                    operationType = 1,
                    ReqCode = Guid.NewGuid().ToString(),
                    ReqTime = DateTime.Now.ToString(),
                    BusinessType = "3",
                    FactoryArea = outboundOrder.FactoryArea,
                    OperationType = 1,
                    Operator = App.User.UserName,
                    orderNo = outboundOrder.UpperOrderNo,
                    documentsNO = outboundOrder.OrderNo,
                    status = outboundOrder.OrderStatus,
                    details = new List<FeedbackOutboundDetailsModel>()
                };
                    OrderNo = outboundOrder.UpperOrderNo,
                   // documentsNO = outboundOrder.OrderNo,
                   // status = outboundOrder.OrderStatus,
                    fromWarehouse = allocate?.FromWarehouse ?? "",
                    toWarehouse = allocate?.ToWarehouse ?? "",
                    Details = new List<AllocateDtoDetail>()
                };
                // åªèŽ·å–å·²æ‹£é€‰å®Œæˆçš„é”å®šè®°å½•
                var lists = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                    .Where(x => x.OrderNo == orderNo && x.Status == (int)OutLockStockStatusEnum.拣选完成)
                    .ToListAsync();
                var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.lineNo, item.Unit, item.WarehouseCode })
                   .Select(group => new FeedbackOutboundDetailsModel
                   .Select(group => new AllocateDtoDetail
                   {
                       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
                       MaterialCode = group.Key.MaterielCode,
                       LineNo = group.Key.lineNo,
                       WarehouseCode = group.Key.WarehouseCode,
                       Qty = group.Sum(x => x.PickedQty),
                       Unit = group.Key.Unit,
                       Barcodes = group.Select(row => new BarcodeInfo
                       {
                           barcode = row.CurrentBarcode,
                           supplyCode = row.SupplyCode,
                           batchNo = row.BatchNo,
                           unit = row.Unit,
                           qty = row.PickedQty
                           Barcode = row.CurrentBarcode,
                           SupplyCode = row.SupplyCode,
                           BatchNo = row.BatchNo,
                           Unit = row.Unit,
                           Qty = row.PickedQty
                       }).ToList()
                   }).ToList();
                feedmodel.Details = groupedData;
                feedmodel.details = groupedData;
                var result = await _invokeMESService.FeedbackOutbound(feedmodel);
                var result = await _invokeMESService.FeedbackAllocate(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();
                           .SetColumns(x => x.ReturnToMESStatus == 1)
                           .Where(x => x.OrderId == outboundOrder.Id).ExecuteCommandAsync();
                    await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
                          .SetColumns(x => new Dt_OutboundOrder
                          {
                              ReturnToMESStatus = 1,
                              Operator = App.User.UserName,
                          })
                        .Where(x => x.OrderNo == orderNo)
                        .ExecuteCommandAsync();
                          }).Where(x => x.OrderNo == orderNo).ExecuteCommandAsync();
                }
                _logger.LogError($"FeedbackOutbound成功 - OrderNo: {orderNo}, {JsonSerializer.Serialize(result)}");
            }
            catch (Exception ex)
            else if (outboundOrder.OrderType == OutOrderTypeEnum.ReCheck.ObjToInt())
            {
                _logger.LogError($"FeedbackOutbound失败 - OrderNo: {orderNo}, Error: {ex.Message}");
            }
            else
            {
                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>()
                    };
                    // åªèŽ·å–å·²æ‹£é€‰å®Œæˆçš„é”å®šè®°å½•
                    var lists = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                        .Where(x => x.OrderNo == orderNo && x.Status == (int)OutLockStockStatusEnum.拣选完成)
                        .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 => new Dt_OutboundOrder
                              {
                                  ReturnToMESStatus = 1,
                                  Operator = App.User.UserName,
                              })
                            .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}");
                }
            }
        }
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/WIDESEA_OutboundService.csproj
@@ -7,6 +7,7 @@
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="..\WIDESEA_IAllocateService\WIDESEA_IAllocateService.csproj" />
    <ProjectReference Include="..\WIDESEA_IBasicService\WIDESEA_IBasicService.csproj" />
    <ProjectReference Include="..\WIDESEA_IOutboundService\WIDESEA_IOutboundService.csproj" />
    <ProjectReference Include="..\WIDESEA_IRecordService\WIDESEA_IRecordService.csproj" />
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoService.cs
@@ -22,14 +22,16 @@
        public IRepository<Dt_StockInfo> Repository => BaseDal;
        private readonly IRepository<Dt_StockInfoDetail> _stockInfoDetailRepository;
        private readonly IOutboundOrderService _outboundOrderService;
        private readonly IOutboundOrderDetailService _outboundOrderDetailService;
        private readonly ILocationInfoService _locationInfoService;
        public StockInfoService(IRepository<Dt_StockInfo> BaseDal, IMapper mapper, IRepository<Dt_StockInfoDetail> stockInfoDetailRepository, IRecordService recordService, ILocationInfoService locationInfoService, IOutboundOrderService outboundOrderService) : base(BaseDal)
        public StockInfoService(IRepository<Dt_StockInfo> BaseDal, IMapper mapper, IRepository<Dt_StockInfoDetail> stockInfoDetailRepository, IRecordService recordService, ILocationInfoService locationInfoService, IOutboundOrderService outboundOrderService, IOutboundOrderDetailService outboundOrderDetailService) : base(BaseDal)
        {
            _mapper = mapper;
            _stockInfoDetailRepository = stockInfoDetailRepository;
            _recordService = recordService;
            _locationInfoService = locationInfoService;
            _outboundOrderService = outboundOrderService;
            _outboundOrderDetailService = outboundOrderDetailService;
        }
        /// <summary>
@@ -226,49 +228,131 @@
        {
            return Db.Queryable<Dt_StockInfo>().Where(x => palletCodes.Contains(x.PalletCode)).Includes(x => x.Details).OrderBy(x => x.CreateDate).ToList();
        }
        // æ·»åŠ èŽ·å–å•ä¸ªæ‰˜ç›˜åº“å­˜çš„æ–¹æ³•ï¼ˆå¦‚æžœä¸å­˜åœ¨ï¼‰
        public Dt_StockInfo GetStockInfoByPalletCode(string palletCode)
        {
            return Db.Queryable<Dt_StockInfo>()
                .Where(x => x.PalletCode == palletCode)
                .Includes(x => x.Details)
                .First();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="materielCode"></param>
        /// <returns></returns>
        //public List<StockSelectViewDTO> GetStockSelectViews(int orderId, string materielCode)
        //{
        //    try
        //    {
        //        Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == orderId);
        //        if (outboundOrder == null)
        //        {
        //            throw new Exception($"未找到出库单信息");
        //        }
        //        List<string> locationCodes = _locationInfoService.GetCanOutLocationCodes();
        //        return BaseDal.QueryTabs<Dt_StockInfo, Dt_StockInfoDetail, StockSelectViewDTO>((a, b) => a.Id == b.StockId, (a, b) => new StockSelectViewDTO
        //        {
        //            LocationCode = a.LocationCode,
        //            MaterielCode = b.MaterielCode,
        //            MaterielName = b.MaterielName,
        //            Barcode=b.Barcode,
        //            PalletCode = a.PalletCode,
        //            UseableQuantity = b.StockQuantity - b.OutboundQuantity
        //        }, a => locationCodes.Contains(a.LocationCode), b => b.StockQuantity > b.OutboundQuantity && b.MaterielCode == materielCode, x => true).GroupBy(x => x.PalletCode).Select(x => new StockSelectViewDTO
        //        {
        //            LocationCode = x.FirstOrDefault()?.LocationCode ?? "",
        //            MaterielCode = x.FirstOrDefault()?.MaterielCode ?? "",
        //            MaterielName = x.FirstOrDefault()?.MaterielName ?? "",
        //            Barcode=x.FirstOrDefault()?.Barcode??"",
        //            PalletCode = x.Key,
        //            UseableQuantity = x.Sum(x => x.UseableQuantity)
        //        }).ToList();
        //    }
        //    catch (Exception ex)
        //    {
        //        return null;
        //    }
        //}
        public List<StockSelectViewDTO> GetStockSelectViews(int orderId, string materielCode)
        {
            try
            Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == orderId);
            if (outboundOrder == null)
            {
                Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == orderId);
                if (outboundOrder == null)
                throw new Exception($"未找到ID为{orderId}的出库单信息");
            }
            // èŽ·å–å‡ºåº“å•æ˜Žç»†ï¼Œç”¨äºŽç¡®å®šéœ€è¦çš„æ‰¹æ¬¡å’Œä¾›åº”å•†
            var orderDetails = _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>().Where(x => x.OrderId == orderId && x.MaterielCode == materielCode).ToList();
            if (!orderDetails.Any())
            {
                throw new Exception($"出库单{orderId}中未找到物料{materielCode}的明细信息");
            }
            List<string> locationCodes = _locationInfoService.GetCanOutLocationCodes();
            var result = new List<StockSelectViewDTO>();
            // ä¸ºæ¯ä¸ªå‡ºåº“单明细查询对应的库存
            foreach (var orderDetail in orderDetails)
            {
                // æž„建查询条件
                var stockQuery = Db.Queryable<Dt_StockInfo>()
                    .Where(x => locationCodes.Contains(x.LocationCode))
                    .Where(x => x.StockStatus == (int)StockStatusEmun.入库完成)
                    .Includes(x => x.Details);
                // æ‰§è¡ŒæŸ¥è¯¢å¹¶æŒ‰å…ˆè¿›å…ˆå‡ºæŽ’序
                var stocks = stockQuery.ToList()
                    .Where(x => x.Details.Any(d =>
                        d.MaterielCode == materielCode &&
                        d.BatchNo == orderDetail.BatchNo &&
                        d.SupplyCode == orderDetail.SupplyCode &&
                        d.StockQuantity > d.OutboundQuantity
                    ))
                    .OrderBy(x => x.CreateDate)
                    .ToList();
                foreach (var stock in stocks)
                {
                    throw new Exception($"未找到出库单信息");
                    var relevantDetails = stock.Details
                        .Where(d => d.MaterielCode == materielCode &&
                                   d.BatchNo == orderDetail.BatchNo &&
                                   d.SupplyCode == orderDetail.SupplyCode &&
                                   d.StockQuantity > d.OutboundQuantity)
                        .ToList();
                    if (relevantDetails.Any())
                    {
                        var firstDetail = relevantDetails.First();
                        var useableQuantity = relevantDetails.Sum(d => d.StockQuantity - d.OutboundQuantity);
                        result.Add(new StockSelectViewDTO
                        {
                            LocationCode = stock.LocationCode,
                            MaterielCode = materielCode,
                            MaterielName = firstDetail.MaterielName,
                            BatchNo = orderDetail.BatchNo,
                            SupplyCode = orderDetail.SupplyCode,
                            Barcode = firstDetail.Barcode,
                            PalletCode = stock.PalletCode,
                            UseableQuantity = useableQuantity,
                            StockCreateDate = stock.CreateDate,
                            StockId = stock.Id,
                            OrderDetailId = orderDetail.Id // å…³è”到具体的出库单明细
                        });
                    }
                }
                List<string> locationCodes = _locationInfoService.GetCanOutLocationCodes();
                return BaseDal.QueryTabs<Dt_StockInfo, Dt_StockInfoDetail, StockSelectViewDTO>((a, b) => a.Id == b.StockId, (a, b) => new StockSelectViewDTO
                {
                    LocationCode = a.LocationCode,
                    MaterielCode = b.MaterielCode,
                    MaterielName = b.MaterielName,
                    Barcode=b.Barcode,
                    PalletCode = a.PalletCode,
                    UseableQuantity = b.StockQuantity - b.OutboundQuantity
                }, a => locationCodes.Contains(a.LocationCode), b => b.StockQuantity > b.OutboundQuantity && b.MaterielCode == materielCode, x => true).GroupBy(x => x.PalletCode).Select(x => new StockSelectViewDTO
                {
                    LocationCode = x.FirstOrDefault()?.LocationCode ?? "",
                    MaterielCode = x.FirstOrDefault()?.MaterielCode ?? "",
                    MaterielName = x.FirstOrDefault()?.MaterielName ?? "",
                    Barcode=x.FirstOrDefault()?.Barcode??"",
                    PalletCode = x.Key,
                    UseableQuantity = x.Sum(x => x.UseableQuantity)
                }).ToList();
            }
            catch (Exception ex)
            {
                return null;
            }
            return result;
        }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs
@@ -127,7 +127,7 @@
                if (int.TryParse(taskNum, out var newTaskNum))
                {
                    task =await BaseDal.QueryFirstAsync(x => x.TaskNum == newTaskNum);
                    task = await BaseDal.QueryFirstAsync(x => x.TaskNum == newTaskNum);
                    if (task == null)
                    {
                        return WebResponseContent.Instance.Error("未找到任务信息");
@@ -154,12 +154,12 @@
                                return responseContent;
                            }
                        }
                        catch (AggregateException ex)
                        catch (AggregateException ex)
                        {
                            _logger.LogError($"TaskService TaskCompleted  taskResult:   {ex.Message} ");
                            return WebResponseContent.Instance.Error(ex.Message);
                        }
                        catch(Exception ex)
                        catch (Exception ex)
                        {
                            _logger.LogError(ex, $"Unexpected error in {task.TaskType}");
                            return WebResponseContent.Instance.Error(ex.Message);
@@ -394,7 +394,7 @@
            locationInfo.LocationStatus = LocationStatusEnum.Free.ObjToInt();
            _locationInfoService.Repository.UpdateData(locationInfo);
            var outloks =await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>().Where(x => x.TaskNum == task.TaskNum).ToListAsync();
            var outloks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>().Where(x => x.TaskNum == task.TaskNum).ToListAsync();
            var stockids = outloks.Select(x => x.StockId).ToList();
@@ -489,7 +489,7 @@
            try
            {
                //查库存
                Dt_StockInfo stockInfo =await _stockRepository.Db.Queryable<Dt_StockInfo>().Includes(x => x.Details).Where(x => x.PalletCode == task.PalletCode).FirstAsync();
                Dt_StockInfo stockInfo = await _stockRepository.Db.Queryable<Dt_StockInfo>().Includes(x => x.Details).Where(x => x.PalletCode == task.PalletCode).FirstAsync();
                if (stockInfo == null)
                {
                    _logger.LogInformation($"TaskService  InPickTaskCompleted: æœªæ‰¾åˆ°æ‰˜ç›˜å¯¹åº”的组盘信息.{task.TaskNum}");
@@ -510,7 +510,7 @@
                var beforelocationStatus = locationInfo.LocationStatus;
                // èŽ·å–æ‰€æœ‰å›žåº“ä¸­çš„å‡ºåº“é”å®šè®°å½•
                var returnLocks =await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                var returnLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                    .Where(it => it.OrderNo == task.OrderNo && it.PalletCode == task.PalletCode && it.Status == (int)OutLockStockStatusEnum.回库中)
                    .ToListAsync();
                // æ›´æ–°å‡ºåº“锁定记录状态为回库完成
@@ -518,7 +518,7 @@
                {
                    lockInfo.Status = (int)OutLockStockStatusEnum.已回库;
                }
                _outStockLockInfoService.Db.Updateable(returnLocks).ExecuteCommand();
                _outStockLockInfoService.Db.Updateable(returnLocks).ExecuteCommand();
                stockInfo.LocationCode = task.TargetAddress;
                stockInfo.StockStatus = StockStatusEmun.入库完成.ObjToInt();
@@ -532,7 +532,7 @@
                }
                _stockService.StockInfoService.Repository.UpdateData(stockInfo);
                await ProcessStockDetailsForReturn(task, stockInfo.Id);
                await DeleteZeroQuantityStockDetails(stockInfo.Id);
@@ -572,14 +572,13 @@
        private async Task HandleOutboundOrderToMESCompletion(Dt_OutboundOrder outboundOrder, 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();
                    .ToListAsync();
                bool allCompleted = true;
                foreach (var detail in orderDetails)
@@ -599,75 +598,147 @@
                        .SetColumns(x => x.OrderStatus == newStatus)
                        .Where(x => x.OrderNo == orderNo)
                        .ExecuteCommandAsync();
                }
                //只有正常分拣完成时才向MES反馈
                if (allCompleted && newStatus == (int)OutOrderStatusEnum.出库完成)
                {
                    var feedmodel = new FeedbackOutboundRequestModel
                    if (outboundOrder.OrderType == OutOrderTypeEnum.Allocate.ObjToInt())
                    {
                        reqCode = Guid.NewGuid().ToString(),
                        reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                        business_type = outboundOrder.BusinessType,
                        factoryArea = outboundOrder.FactoryArea,
                        operationType = 1,
                        Operator = outboundOrder.Operator,
                        orderNo = outboundOrder.UpperOrderNo,
                        documentsNO = outboundOrder.OrderNo,
                        status = outboundOrder.OrderStatus,
                        details = new List<FeedbackOutboundDetailsModel>()
                    };
                    foreach (var detail in orderDetails)
                    {
                        // èŽ·å–è¯¥æ˜Žç»†å¯¹åº”çš„æ¡ç ä¿¡æ¯ï¼ˆä»Žé”å®šè®°å½•ï¼‰
                        var detailLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                            .Where(x => x.OrderNo == orderNo &&
                                       x.OrderDetailId == detail.Id &&
                                       x.Status == (int)OutLockStockStatusEnum.拣选完成)
                            .ToListAsync();
                        var detailModel = new FeedbackOutboundDetailsModel
                        var allocate = _allocateService.Repository.QueryData(x => x.UpperOrderNo == outboundOrder.UpperOrderNo).First();
                        var feedmodel = new AllocateDto
                        {
                            materialCode = detail.MaterielCode,
                            lineNo = detail.lineNo, // æ³¨æ„ï¼šè¿™é‡Œå¯èƒ½éœ€è¦è°ƒæ•´å­—段名
                            warehouseCode = detail.WarehouseCode,
                            qty = detail.OverOutQuantity, // ä½¿ç”¨è®¢å•明细的已出库数量
                            currentDeliveryQty = detail.OverOutQuantity,
                            unit = detail.Unit,
                            barcodes = detailLocks.Select(lockInfo => new WIDESEA_DTO.Outbound.BarcodesModel
                            ReqCode = Guid.NewGuid().ToString(),
                            ReqTime = DateTime.Now.ToString(),
                            BusinessType = "3",
                            FactoryArea = outboundOrder.FactoryArea,
                            OperationType = 1,
                            Operator = outboundOrder.Operator,
                            OrderNo = outboundOrder.UpperOrderNo,
                            // documentsNO = outboundOrder.OrderNo,
                            // status = outboundOrder.OrderStatus,
                            fromWarehouse = allocate?.FromWarehouse ?? "",
                            toWarehouse = allocate?.ToWarehouse ?? "",
                            Details = new List<AllocateDtoDetail>()
                        };
                        foreach (var detail in orderDetails)
                        {
                            // èŽ·å–è¯¥æ˜Žç»†å¯¹åº”çš„æ¡ç ä¿¡æ¯ï¼ˆä»Žé”å®šè®°å½•ï¼‰
                            var detailLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                                .Where(x => x.OrderNo == orderNo &&
                                           x.OrderDetailId == detail.Id &&
                                           x.Status == (int)OutLockStockStatusEnum.拣选完成)
                                .ToListAsync();
                            var detailModel = new AllocateDtoDetail
                            {
                                barcode = lockInfo.CurrentBarcode,
                                supplyCode = lockInfo.SupplyCode,
                                batchNo = lockInfo.BatchNo,
                                unit = lockInfo.Unit,
                                qty = lockInfo.PickedQty // æ¡ç çº§åˆ«çš„æ•°é‡ä»ç”¨é”å®šè®°å½•
                            }).ToList()
                                MaterialCode = detail.MaterielCode,
                                LineNo = detail.lineNo, // æ³¨æ„ï¼šè¿™é‡Œå¯èƒ½éœ€è¦è°ƒæ•´å­—段名
                                WarehouseCode = detail.WarehouseCode,
                                Qty = detail.OverOutQuantity, // ä½¿ç”¨è®¢å•明细的已出库数量
                                //currentDeliveryQty = detail.OverOutQuantity,
                                Unit = detail.Unit,
                                Barcodes = detailLocks.Select(lockInfo => new BarcodeInfo
                                {
                                    Barcode = lockInfo.CurrentBarcode,
                                    SupplyCode = lockInfo.SupplyCode,
                                    BatchNo = lockInfo.BatchNo,
                                    Unit = lockInfo.Unit,
                                    Qty = lockInfo.PickedQty // æ¡ç çº§åˆ«çš„æ•°é‡ä»ç”¨é”å®šè®°å½•
                                }).ToList()
                            };
                            feedmodel.Details.Add(detailModel);
                        }
                        var result = await _invokeMESService.FeedbackAllocate(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 => new Dt_OutboundOrder
                                  {
                                      ReturnToMESStatus = 1,
                                      Operator = App.User.UserName,
                                  }).Where(x => x.OrderNo == orderNo).ExecuteCommandAsync();
                        }
                    }
                    else if (outboundOrder.OrderType == OutOrderTypeEnum.ReCheck.ObjToInt())
                    {
                    }
                    else
                    {
                        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 = outboundOrder.Operator,
                            orderNo = outboundOrder.UpperOrderNo,
                            documentsNO = outboundOrder.OrderNo,
                            status = outboundOrder.OrderStatus,
                            details = new List<FeedbackOutboundDetailsModel>()
                        };
                        feedmodel.details.Add(detailModel);
                    }
                    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();
                        foreach (var detail in orderDetails)
                        {
                            // èŽ·å–è¯¥æ˜Žç»†å¯¹åº”çš„æ¡ç ä¿¡æ¯ï¼ˆä»Žé”å®šè®°å½•ï¼‰
                            var detailLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                                .Where(x => x.OrderNo == orderNo &&
                                           x.OrderDetailId == detail.Id &&
                                           x.Status == (int)OutLockStockStatusEnum.拣选完成)
                                .ToListAsync();
                        await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
                            .SetColumns(x => x.ReturnToMESStatus == 1)
                            .Where(x => x.OrderNo == orderNo)
                            .ExecuteCommandAsync();
                            var detailModel = new FeedbackOutboundDetailsModel
                            {
                                materialCode = detail.MaterielCode,
                                lineNo = detail.lineNo, // æ³¨æ„ï¼šè¿™é‡Œå¯èƒ½éœ€è¦è°ƒæ•´å­—段名
                                warehouseCode = detail.WarehouseCode,
                                qty = detail.OverOutQuantity, // ä½¿ç”¨è®¢å•明细的已出库数量
                                currentDeliveryQty = detail.OverOutQuantity,
                                unit = detail.Unit,
                                barcodes = detailLocks.Select(lockInfo => new WIDESEA_DTO.Outbound.BarcodesModel
                                {
                                    barcode = lockInfo.CurrentBarcode,
                                    supplyCode = lockInfo.SupplyCode,
                                    batchNo = lockInfo.BatchNo,
                                    unit = lockInfo.Unit,
                                    qty = lockInfo.PickedQty // æ¡ç çº§åˆ«çš„æ•°é‡ä»ç”¨é”å®šè®°å½•
                                }).ToList()
                            };
                            feedmodel.details.Add(detailModel);
                        }
                        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($"CheckAndUpdateOrderStatus失败 - OrderNo: {orderNo}, Error: {ex.Message}");
            }
            }
        }
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Allocate/AllocateOrderController.cs
@@ -69,7 +69,9 @@
                            Barcode = barcodeDto.Barcode,
                            BatchNo = barcodeDto.BatchNo,
                            BarcodeQty = barcodeDto.Qty,
                            BarcodeUnit = barcodeDto.Unit
                            BarcodeUnit = barcodeDto.Unit,
                            ValidDate=barcodeDto.validDate,
                        };
                        allocateOrder.Details.Add(orderDetail);
                    }
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundOrderController.cs
@@ -30,13 +30,13 @@
        private readonly WIDESEA_IBasicService.IErpApiService erpApiService;
        private readonly WIDESEA_IBasicService.IInvokeMESService _invokeMESService;
        public readonly IInboundService _inboundService;
        private readonly IESSApiService _eSSApiService;
        private readonly ILocationInfoService _locationInfoService;
        private readonly IDailySequenceService _dailySequenceService;
        private readonly IMaterialUnitService _materialUnitService;
        private readonly ILogger<InboundOrderController> _logger;
        public InboundOrderController(IInboundOrderService service, WIDESEA_IBasicService.IErpApiService erpApiService, WIDESEA_IBasicService.IInvokeMESService invokeMESService, IESSApiService eSSApiService, IDailySequenceService dailySequenceService, ILocationInfoService locationInfoService, ILogger<InboundOrderController> logger, IMaterialUnitService materialUnitService) : base(service)
        public InboundOrderController(IInboundOrderService service, WIDESEA_IBasicService.IErpApiService erpApiService, WIDESEA_IBasicService.IInvokeMESService invokeMESService, IESSApiService eSSApiService, IDailySequenceService dailySequenceService, ILocationInfoService locationInfoService, ILogger<InboundOrderController> logger, IMaterialUnitService materialUnitService, IInboundService inboundService) : base(service)
        {
            this.erpApiService = erpApiService;
            _invokeMESService = invokeMESService;
@@ -45,14 +45,20 @@
            _locationInfoService = locationInfoService;
            _logger = logger;
            _materialUnitService = materialUnitService;
            _inboundService = inboundService;
        }
        [HttpPost, Route("Test"), AllowAnonymous, MethodParamsValidate]
        public async Task<WebResponseContent> Test()
        {
           // var purchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync("101001-00002", 10);
             Service.Db.Deleteable<Dt_InboundOrder>().Where(x=>x.UpperOrderNo== "12020251100040").ExecuteCommand();
            _inboundService.InboundOrderDetailService.Db.Deleteable<Dt_InboundOrderDetail>()
             .Where(p => SqlFunc.Subqueryable<Dt_InboundOrder>().Where(s => s.Id == p.OrderId && s.UpperOrderNo == "12020251100040").Any()).ExecuteCommand();
           // var pdddurchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync("100513-00210", 10);
            // var purchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync("101001-00002", 10);
            // var pdddurchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync("100513-00210", 10);
            //var sddd = _locationInfoService.AssignLocation();
            //var code = sddd.LocationCode;