647556386
2025-10-18 d01658c63cd541fe4ea5cec5c4bd7f23b9408cdb
WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/Service/OutboundOrderDetailService.cs
@@ -10,6 +10,7 @@
using WIDESEA_Core.BaseServices;
using WIDESEA_Core.Enums;
using WIDESEA_Core.Helper;
using WIDESEA_DTO.ERP;
using WIDESEA_DTO.Stock;
using WIDESEA_IBasicRepository;
using WIDESEA_IBasicService;
@@ -23,8 +24,11 @@
namespace WIDESEA_OutboundService
{
    public partial class OutboundOrderDetailService : ServiceBase<Dt_OutboundOrderDetail, IOutboundOrderDetailRepository>, IOutboundOrderDetailService
    {
        public WebResponseContent LockOutboundStock(int orderDetailId)
        {
            Dt_OutboundOrderDetail outboundOrderDetail = BaseDal.QueryFirst(x => x.Id == orderDetailId);
@@ -128,6 +132,7 @@
        public (List<Dt_StockInfo>, Dt_OutboundOrderDetail, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) AssignStockOutbound(Dt_OutboundOrderDetail outboundOrderDetail, List<StockSelectViewDTO> stockSelectViews)
        {
            #region
            (bool, string) checkResult = CheckSelectStockDeital(outboundOrderDetail, stockSelectViews);
            if (!checkResult.Item1) throw new Exception(checkResult.Item2);
@@ -136,7 +141,13 @@
            decimal needQuantity = originalNeedQuantity;
            List<Dt_StockInfo> outStocks = _stockService.StockInfoService.Repository.GetStockInfosByPalletCode(stockSelectViews.Select(x => x.BatchNo).ToList());
            List<Dt_StockInfo> outStocks = _stockService.StockInfoService.Repository.GetStockInfosByPalletCode(stockSelectViews.Select(x => x.PalletCode).ToList());
            //List<Dt_StockInfo> stockInfos = _stockService.StockInfoService.GetUseableStocks(outboundOrder.MaterialCode, "", outboundOrder.WarehouseId);
            if (!outStocks.Any())
            {
                throw new Exception($"未找到可分配库存");
            }
            decimal assignQuantity = 0;
            outStocks.ForEach(x =>
            {
@@ -158,7 +169,7 @@
            if (outboundOrderDetail.OrderQuantity > outboundOrderDetail.LockQuantity)
            {
                List<Dt_StockInfo> stockInfos = _stockService.StockInfoService.GetUseableStocks(outboundOrderDetail.MaterielCode);
                stockInfos = stockInfos.Where(x => !stockSelectViews.Select(v => v.BatchNo).Contains(x.BatchNo)).ToList();
                stockInfos = stockInfos.Where(x => !stockSelectViews.Select(v => v.PalletCode).Contains(x.PalletCode)).ToList();
                List<Dt_StockInfo> autoAssignStocks = _stockService.StockInfoService.GetOutboundStocks(stockInfos, outboundOrderDetail.MaterielCode, needQuantity, out decimal residueQuantity);
                outboundOrderDetail.LockQuantity += needQuantity - residueQuantity;
                outStocks.AddRange(autoAssignStocks);
@@ -173,6 +184,7 @@
            List<Dt_LocationInfo> locationInfos = _basicService.LocationInfoService.Repository.GetLocationInfos(outStocks.Select(x => x.LocationCode).ToList());
            #endregion
            return (outStocks, outboundOrderDetail, outStockLockInfos, locationInfos);
        }
@@ -265,6 +277,14 @@
                List<Dt_OutStockLockInfo> addOutStockLockInfos = outStockLockInfos.Where(x => x.Id == 0).ToList();
                if (addOutStockLockInfos != null && addOutStockLockInfos.Any())
                {
                    if (tasks != null)
                    {
                        addOutStockLockInfos.ForEach(x =>
                        {
                            x.TaskNum = tasks.FirstOrDefault(v => v.PalletCode == x.PalletCode)?.TaskNum;
                        });
                    }
                    _outStockLockInfoService.Repository.AddData(addOutStockLockInfos);
                }
                List<Dt_OutStockLockInfo> updateOutStockLockInfos = outStockLockInfos.Where(x => x.Id > 0).ToList();
@@ -283,6 +303,105 @@
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="outboundOrderDetails"></param>
        /// <returns></returns>
        public (List<Dt_StockInfo>, List<Dt_OutboundOrderDetail>, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) AssignStockOutbound(List<Dt_OutboundOrderDetail> outboundOrderDetails)
        {
            if (!outboundOrderDetails.Any())
            {
                throw new Exception($"未找到出库单明细信息");
            }
            if (outboundOrderDetails.GroupBy(x => x.OrderId).Count() > 1)
            {
                throw new Exception($"请勿同时操作多个单据明细");
            }
            Dt_OutboundOrder outboundOrder = _outboundRepository.OutboundOrderRepository.QueryFirst(x => x.Id == outboundOrderDetails.FirstOrDefault().OrderId);
            List<Dt_StockInfo> outStocks = new List<Dt_StockInfo>();
            List<Dt_OutboundOrderDetail> groupDetails = outboundOrderDetails.GroupBy(x => new { x.MaterielCode, x.BatchNo , x.LocationName}).Select(x => new Dt_OutboundOrderDetail { OrderQuantity = x.Sum(v => v.OrderQuantity) - x.Sum(v => v.LockQuantity), MaterielCode = x.Key.MaterielCode, BatchNo = x.Key.BatchNo,LocationName = x.Key.LocationName}).ToList();
            List<Dt_Warehouse> warehouse = new List<Dt_Warehouse>();
            if (outboundOrder.OutWareHouse == "SC01_BC")
            {
                warehouse = _basicService.WarehouseService.Repository.QueryData(x => x.WarehouseDes == outboundOrder.OutWareHouse || x.WarehouseDes =="SC02_BC");
            }
            else
            {
                warehouse = _basicService.WarehouseService.Repository.QueryData(x => x.WarehouseDes == outboundOrder.OutWareHouse);
            }
            List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>();
            List<Dt_LocationInfo> locationInfos = new List<Dt_LocationInfo>();
            foreach (var item in groupDetails)
            {
                decimal originalNeedQuantity = item.OrderQuantity;
                decimal needQuantity = originalNeedQuantity;
                List<Dt_StockInfo> stockInfos = new List<Dt_StockInfo>();
                ///出库指定库位出库判断
                if (item.LocationName != null && item.LocationName != "")
                {
                   stockInfos = _stockService.StockInfoService.GetUseableStocks(item.MaterielCode, item.BatchNo, warehouse).Where(x=>x.LocationCode == item.LocationName).ToList();
                }
                else
                {
                   stockInfos = _stockService.StockInfoService.GetUseableStocks(item.MaterielCode, item.BatchNo, warehouse);
                }
                if (!stockInfos.Any())
                {
                    throw new Exception($"未找到可分配库存");
                }
                List<Dt_StockInfo> autoAssignStocks = _stockService.StockInfoService.GetOutboundStocks(stockInfos, item.MaterielCode, needQuantity, out decimal residueQuantity);
                item.LockQuantity += needQuantity - residueQuantity;
                outStocks.AddRange(autoAssignStocks);
                decimal assignQuantity = needQuantity - residueQuantity;
                List<Dt_OutboundOrderDetail> details = outboundOrderDetails.Where(x => !string.IsNullOrEmpty(x.BatchNo) ? x.BatchNo == item.BatchNo : true && x.MaterielCode == item.MaterielCode).ToList();
                for (int i = 0; i < details.Count; i++)
                {
                    decimal orderQuantity = details[i].OrderQuantity;
                    for (int j = 0; j < autoAssignStocks.Count; j++)
                    {
                        decimal detailAssignQuantity = outStockLockInfos.Where(x => !string.IsNullOrEmpty(x.BatchNo) ? x.BatchNo == item.BatchNo : true && x.MaterielCode == item.MaterielCode && x.OrderDetailId == details[i].Id).Sum(x => x.AssignQuantity);//出库订单明细已分配数量
                        decimal palletAssignQuantity = outStockLockInfos.Where(x => x.BatchNo == item.BatchNo && x.MaterielCode == item.MaterielCode && x.PalletCode == autoAssignStocks[j].PalletCode).Sum(x => x.AssignQuantity);//出库详情已分配数量
                        if (string.IsNullOrEmpty(item.BatchNo))
                        {
                            palletAssignQuantity = outStockLockInfos.Where(x => x.MaterielCode == item.MaterielCode && x.PalletCode == autoAssignStocks[j].PalletCode).Sum(x => x.AssignQuantity);//出库详情已分配数量
                        }
                        decimal palletOutboundQuantity = autoAssignStocks[j].Details.Sum(x => x.OutboundQuantity);
                        if (palletAssignQuantity < palletOutboundQuantity)//如果出库详情已分配数量小于托盘已分配数量,则可以继续添加该托盘出库信息
                        {
                            decimal orderDetailNeedQuantity = details[i].OrderQuantity - detailAssignQuantity;
                            if (orderDetailNeedQuantity > autoAssignStocks[j].Details.Sum(x => x.OutboundQuantity) - palletAssignQuantity)
                            {
                                details[i].LockQuantity += autoAssignStocks[j].Details.Sum(x => x.OutboundQuantity) - palletAssignQuantity;
                                Dt_OutStockLockInfo outStockLockInfo = _outStockLockInfoService.GetOutStockLockInfo(outboundOrder, details[i], autoAssignStocks[j], autoAssignStocks[j].Details.Sum(x => x.OutboundQuantity) - palletAssignQuantity);
                                outStockLockInfos.Add(outStockLockInfo);
                            }
                            else
                            {
                                Dt_OutStockLockInfo outStockLockInfo = _outStockLockInfoService.GetOutStockLockInfo(outboundOrder, details[i], autoAssignStocks[j], details[i].OrderQuantity - details[i].LockQuantity);
                                outStockLockInfos.Add(outStockLockInfo);
                                details[i].LockQuantity = details[i].OrderQuantity;
                                break;
                            }
                        }
                    }
                }
                locationInfos.AddRange(_basicService.LocationInfoService.Repository.GetLocationInfos(outStocks.Select(x => x.LocationCode).ToList()));
            }
            return (outStocks, outboundOrderDetails, outStockLockInfos, locationInfos);
        }
        private (bool, string) CheckSelectStockDeital(Dt_OutboundOrderDetail outboundOrderDetail, List<StockSelectViewDTO> stockSelectViews)
        {
            if (outboundOrderDetail == null)
@@ -350,5 +469,87 @@
            }
            return (true, "成功");
        }
        public string ToCancelOutFeedbackERP = WIDESEA_Core.Helper.AppSettings.Configuration["CancelOutFeedbackERP"];
        public WebResponseContent CancelOutFeedbackERP(int[] keys)
        {
            List<Dt_OutboundOrderDetail> outboundOrderDetails = _outboundRepository.OutboundOrderDetailRepository.QueryData(x => keys.Contains(x.Id));
            if (outboundOrderDetails == null || outboundOrderDetails.Count == 0)
            {
                return WebResponseContent.Instance.Error("未找到出库单明细信息");
            }
            if (outboundOrderDetails.FirstOrDefault(x => x.OrderDetailStatus > OrderDetailStatusEnum.New.ObjToInt() && x.OrderDetailStatus != OrderDetailStatusEnum.AssignOverPartial.ObjToInt()) != null)
            {
                return WebResponseContent.Instance.Error("所选出库单明细存在出库中或已完成");
            }
            Dt_OutboundOrder outboundOrder = _outboundRepository.OutboundOrderRepository.QueryFirst(x => x.Id == outboundOrderDetails[0].OrderId);
            if(outboundOrder == null)
            {
                return WebResponseContent.Instance.Error("未通过该明细找到出库单信息");
            }
            if (!outboundOrder.System.Equals("ERP"))
            {
                return WebResponseContent.Instance.Error("该出库单据非ERP推送,无法取消");
            }
            string ids ="";
            foreach (var item in outboundOrderDetails)
            {
                ids = item.LinId;
                var postContent = new MultipartFormDataContent();
                postContent.Headers.Add("ContentType", $"multipart/form-data");
                postContent.Add(new StringContent(ids), "ids");
                string result = string.Empty;
                HttpClient client = null;
                try
                {
                    using (client = new HttpClient())
                    {
                        HttpResponseMessage response = client.PostAsync(ToCancelOutFeedbackERP, postContent)
                            .ConfigureAwait(false).GetAwaiter().GetResult();
                        // 确保响应成功
                        response.EnsureSuccessStatusCode();
                        result = response.Content.ReadAsStringAsync()
                            .ConfigureAwait(false).GetAwaiter().GetResult();
                    }
                    _unitOfWorkManage.BeginTran();
                    _outboundRepository.OutboundOrderDetailRepository.DeleteAndMoveIntoHty(outboundOrderDetails, OperateType.人工取消);
                    //检查该主订单是否还有剩余明细
                    int remainingDetailsCount = _outboundRepository.OutboundOrderDetailRepository
                        .Db.Queryable<Dt_OutboundOrderDetail>()
                        .Where(d => d.OrderId == outboundOrder.Id)
                        .Count();
                    // 如果没有剩余明细,再删除主订单
                    if (remainingDetailsCount == 0)
                    {
                        _outboundRepository.OutboundOrderRepository.DeleteAndMoveIntoHty(outboundOrder, OperateType.人工取消);
                    }
                    _unitOfWorkManage.CommitTran();
                    // 假设ERP返回成功时返回成功响应
                    return WebResponseContent.Instance.OK(result);
                }
                catch (HttpRequestException ex)
                {
                    _unitOfWorkManage.RollbackTran();
                    // 处理HTTP请求相关异常
                    return WebResponseContent.Instance.Error($"HTTP请求错误: {ex.Message}");
                }
                catch (Exception ex)
                {
                    _unitOfWorkManage.RollbackTran();
                    // 处理其他异常
                    return WebResponseContent.Instance.Error($"处理失败: {ex.Message}");
                }
            }
            return WebResponseContent.Instance.OK();
        }
    }
}