hutongqing
2024-12-14 e7cf443b37f8f4d8a1bc4fe4cd6f058f39e5c7f5
更新

添加出库单库存分配方法
添加物料码解析接口
已删除6个文件
已修改15个文件
已添加3个文件
已重命名5个文件
652 ■■■■ 文件已修改
代码管理/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/FileContentIndex/341739e1-48c0-452c-a5ea-3c213effa27e.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/FileContentIndex/412af394-9dac-4306-95f6-39fd60896df6.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/FileContentIndex/4cc8f357-fc0c-4940-a3b6-b8853a50c180.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/FileContentIndex/ce72d7b5-21c0-485a-b3a5-52df88bd7a47.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/FileContentIndex/ea02e79b-60fd-46cb-830c-ee3a3c992700.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/FileContentIndex/edabd823-9c10-4009-8e95-cb1d3217eb83.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_BasicRepository/LocationInfoRepository.cs 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_Common/StockEnum/StockChangeTypeEnum.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_Core/Helper/CodeAnalysisHelper.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_DTO/Stock/StockSelectViewDTO.cs 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_IBasicRepository/ILocationInfoRepository.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutStockLockInfoService.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutboundOrderDetailService.cs 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_IRecordService/ILocationStatusChangeRecordService.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_IStockService/IStockInfoService.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundLockInfo.cs 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/OutStockLockInfoService.cs 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderDetailService.cs 343 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderService.cs 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_RecordService/Service/LocationStatusChangeRecordService.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_StockService/Base/StockInfoDetailService.cs 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_StockService/Base/StockInfoService.cs 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_StockService/Service/StockViewService.cs 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoDetailService.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoDetail_HtyService.cs 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoService.cs 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfo_HtyService.cs 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockViewService.cs 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Basic/MaterielInfoController.cs 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/FileContentIndex/341739e1-48c0-452c-a5ea-3c213effa27e.vsidx
Binary files differ
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/FileContentIndex/412af394-9dac-4306-95f6-39fd60896df6.vsidx
Binary files differ
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/FileContentIndex/4cc8f357-fc0c-4940-a3b6-b8853a50c180.vsidx
Binary files differ
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/FileContentIndex/ce72d7b5-21c0-485a-b3a5-52df88bd7a47.vsidx
Binary files differ
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/FileContentIndex/ea02e79b-60fd-46cb-830c-ee3a3c992700.vsidx
Binary files differ
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/FileContentIndex/edabd823-9c10-4009-8e95-cb1d3217eb83.vsidx
Binary files differ
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_BasicRepository/LocationInfoRepository.cs
@@ -29,10 +29,10 @@
        public List<LocationGroupDTO> GetLocationGroups(string roadway, LocationStatusEnum locationAStatus, LocationStatusEnum locationBStatus)
        {
            return QueryTabs<Dt_LocationInfo, Dt_LocationInfo, LocationGroupDTO>(
                (a, b) => a.Column == b.Column && a.Layer == b.Layer && a.Row != b.Row && SqlFunc.Abs(a.Row - b.Row) == 1,
                (a, b) => new LocationGroupDTO { DepthA = a.Depth, DepthB = b.Depth, EnableStatusA = a.EnableStatus, EnableStatusB = b.EnableStatus, IdA = a.Id, IdB = b.Id, LocationCodeA = a.LocationCode, LocationCodeB = b.LocationCode, LocationStatusA = a.LocationStatus, LocationStatusB = b.LocationStatus, LocationTypeA = a.LocationType, LocationTypeB = b.LocationType },
                a => a.Depth == 1 && a.RoadwayNo == roadway && a.LocationStatus == locationAStatus.ObjToInt(),
                b => b.Depth == 2 && b.RoadwayNo == roadway && b.LocationStatus == locationBStatus.ObjToInt(),
                (a, b) => a.Column == b.Column && a.Layer == b.Layer && a.Row != b.Row && SqlFunc.Abs(a.Row - b.Row) == 1,
                (a, b) => new LocationGroupDTO { DepthA = a.Depth, DepthB = b.Depth, EnableStatusA = a.EnableStatus, EnableStatusB = b.EnableStatus, IdA = a.Id, IdB = b.Id, LocationCodeA = a.LocationCode, LocationCodeB = b.LocationCode, LocationStatusA = a.LocationStatus, LocationStatusB = b.LocationStatus, LocationTypeA = a.LocationType, LocationTypeB = b.LocationType },
                a => a.Depth == 1 && a.RoadwayNo == roadway && a.LocationStatus == locationAStatus.ObjToInt(),
                b => b.Depth == 2 && b.RoadwayNo == roadway && b.LocationStatus == locationBStatus.ObjToInt(),
                x => true);
        }
@@ -54,5 +54,10 @@
            });
            UpdateData(locationInfos);
        }
        public List<string> GetCanOutLocationCodes(int warehouseId)
        {
            return QueryData(x => x.LocationCode, x => x.WarehouseId == warehouseId && x.LocationStatus == LocationStatusEnum.InStock.ObjToInt() && (x.EnableStatus == EnableStatusEnum.OnlyOut.ObjToInt() || x.EnableStatus == EnableStatusEnum.Normal.ObjToInt())).Distinct().ToList();
        }
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_Common/StockEnum/StockChangeTypeEnum.cs
@@ -31,5 +31,11 @@
        /// </summary>
        [Description("移库")]
        Relocation,
        /// <summary>
        /// å‡ºåº“锁定
        /// </summary>
        [Description("出库锁定")]
        StockLock
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_Core/Helper/CodeAnalysisHelper.cs
@@ -99,7 +99,7 @@
            }
            catch (Exception ex)
            {
                throw new Exception($"解析错误,{ex.Message}");
            }
            (bool, string, object?) validateResult = ModelValidate.ValidateModelData(result, type);
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_DTO/Stock/StockSelectViewDTO.cs
@@ -9,14 +9,14 @@
    public class StockSelectViewDTO
    {
        public string MaterielCode {  get; set; }
        public string MaterielCode { get; set; }
        public string MaterielName { get; set; }
        public decimal UseableQuantity { get; set; }
        public float UseableQuantity { get; set; }
        public string PalletCode {  get; set; }
        public string PalletCode { get; set; }
        public string LocationCode {  get; set; }
        public string LocationCode { get; set; }
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_IBasicRepository/ILocationInfoRepository.cs
@@ -42,5 +42,7 @@
        /// <param name="locationInfos">货位实体集合</param>
        /// <param name="locationStatus">货位状态</param>
        void UpdateLocationStatus(List<Dt_LocationInfo> locationInfos, LocationStatusEnum locationStatus);
        List<string> GetCanOutLocationCodes(int warehouseId);
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutStockLockInfoService.cs
@@ -14,5 +14,9 @@
    public interface IOutStockLockInfoService : IService<Dt_OutStockLockInfo>
    {
        IOutStockLockInfoRepository Repository { get; }
        List<Dt_OutStockLockInfo> GetOutStockLockInfos(Dt_OutboundOrder outboundOrder, Dt_OutboundOrderDetail outboundOrderDetail, List<Dt_StockInfo> outStocks, int? taskNum = null);
        List<Dt_OutStockLockInfo> GetByOrderDetailId(int orderDetailId, OutLockStockStatusEnum outStockStatus);
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutboundOrderDetailService.cs
@@ -4,6 +4,7 @@
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Core;
using WIDESEA_Core.BaseServices;
using WIDESEA_Core.Enums;
@@ -17,5 +18,53 @@
    {
        IOutboundOrderDetailRepository Repository { get; }
        /// <summary>
        /// é”å®šå‡ºåº“库存
        /// </summary>
        /// <param name="orderDetailId">出库单明细Id</param>
        /// <returns></returns>
        WebResponseContent LockOutboundStock(int orderDetailId);
        /// <summary>
        /// åˆ†é…åº“存出库逻辑
        /// </summary>
        /// <param name="outboundOrderDetail">出库单明细</param>
        /// <param name="stockSelectViews">人工选择的库存</param>
        /// <returns></returns>
        (List<Dt_StockInfo>, Dt_OutboundOrderDetail, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) AssignStockOutbound(Dt_OutboundOrderDetail outboundOrderDetail, List<StockSelectViewDTO> stockSelectViews);
        /// <summary>
        /// é”å®šå‡ºåº“库存
        /// </summary>
        /// <param name="orderDetailId">出库单明细Id</param>
        /// <param name="stockSelectViews">人工选择的库存</param>
        /// <returns></returns>
        WebResponseContent LockOutboundStock(int orderDetailId, List<StockSelectViewDTO> stockSelectViews);
        /// <summary>
        /// é”å®šå‡ºåº“库存(多明细)
        /// </summary>
        /// <param name="keys"></param>
        /// <returns></returns>
        WebResponseContent LockOutboundStock(int[] keys);
        /// <summary>
        /// é”å®šå‡ºåº“库存(修改数据)
        /// </summary>
        /// <param name="stockInfos">库存明细集合</param>
        /// <param name="outboundOrderDetails">出库单明细集合</param>
        /// <param name="outStockLockInfos">出库锁定明细集合</param>
        /// <param name="locationInfos">货位结合</param>
        /// <param name="locationStatus">货位状态修改的值</param>
        /// <param name="tasks">任务信息</param>
        /// <returns></returns>
        WebResponseContent LockOutboundStockDataUpdate(List<Dt_StockInfo> stockInfos, List<Dt_OutboundOrderDetail> outboundOrderDetails, List<Dt_OutStockLockInfo> outStockLockInfos, List<Dt_LocationInfo> locationInfos, LocationStatusEnum locationStatus = LocationStatusEnum.Lock, List<Dt_Task>? tasks = null);
        /// <summary>
        /// æ’¤é”€é”å®šå‡ºåº“库存
        /// </summary>
        /// <param name="orderDetailId">出库单明细主键</param>
        /// <returns></returns>
        WebResponseContent RevokeLockOutboundStock(int orderDetailId);
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_IRecordService/ILocationStatusChangeRecordService.cs
@@ -17,7 +17,7 @@
        void AddLocationStatusChangeRecord(Dt_LocationInfo locationInfo, LocationStatusEnum lastStatus, LocationChangeType changeType, string? orderNo = null, int? taskNum = null);
        void AddLocationStatusChangeRecord(List<Dt_LocationInfo> locationInfos, LocationStatusEnum newStatus, LocationChangeType changeType, string? orderNo, List<int>? taskNums);
        void AddLocationStatusChangeRecord(List<Dt_LocationInfo> locationInfos, LocationStatusEnum newStatus, LocationChangeType changeType, string? orderNo = null, List<int>? taskNums = null);
        WebResponseContent GetLocationState(int id);
    }
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_IStockService/IStockInfoService.cs
@@ -13,5 +13,9 @@
    public interface IStockInfoService : IService<Dt_StockInfo>
    {
        IStockInfoRepository Repository { get; }
        List<Dt_StockInfo> GetOutboundStocks(List<Dt_StockInfo> stockInfos, string materielCode, float needQuantity, out float residueQuantity);
        List<Dt_StockInfo> GetUseableStocks(string materielCode, int warehoseId);
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_OutboundLockInfo.cs
@@ -36,14 +36,14 @@
        [SugarColumn(IsNullable = false, ColumnDescription = "库存主键")]
        public int StockId { get; set; }
        [SugarColumn(IsNullable = false, DecimalDigits = 2, ColumnDescription = "单据数量")]
        public decimal OrderQuantity { get; set; }
        [SugarColumn(IsNullable = false, ColumnDescription = "单据数量")]
        public float OrderQuantity { get; set; }
        [SugarColumn(IsNullable = false, DecimalDigits = 2, ColumnDescription = "原始库存量")]
        public decimal OriginalQuantity {  get; set; }
        [SugarColumn(IsNullable = false, ColumnDescription = "原始库存量")]
        public float OriginalQuantity {  get; set; }
        [SugarColumn(IsNullable = false, DecimalDigits = 2, ColumnDescription = "分配出库量")]
        public decimal AssignQuantity {  get; set; }
        [SugarColumn(IsNullable = false, ColumnDescription = "分配出库量")]
        public float AssignQuantity {  get; set; }
        [SugarColumn(IsNullable = true, Length = 20, ColumnDescription = "货位编号")]
        public string LocationCode { get; set; }
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/OutStockLockInfoService.cs
@@ -19,5 +19,38 @@
        public OutStockLockInfoService(IOutStockLockInfoRepository BaseDal) : base(BaseDal)
        {
        }
        public List<Dt_OutStockLockInfo> GetOutStockLockInfos(Dt_OutboundOrder outboundOrder, Dt_OutboundOrderDetail outboundOrderDetail, List<Dt_StockInfo> outStocks, int? taskNum = null)
        {
            List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>();
            foreach (var item in outStocks)
            {
                Dt_OutStockLockInfo outStockLockInfo = new Dt_OutStockLockInfo()
                {
                    PalletCode = item.PalletCode,
                    AssignQuantity = item.Details.Where(x => x.MaterielCode == outboundOrderDetail.MaterielCode).Sum(x => x.OutboundQuantity),
                    MaterielCode = outboundOrderDetail.MaterielCode,
                    BatchNo = outboundOrderDetail.BatchNo,
                    LocationCode = item.LocationCode,
                    MaterielName = outboundOrderDetail.MaterielName,
                    OrderDetailId = outboundOrderDetail.Id,
                    OrderNo = outboundOrder.OrderNo,
                    OrderType = outboundOrder.OrderType,
                    OriginalQuantity = item.Details.Where(x => x.MaterielCode == outboundOrderDetail.MaterielCode).Sum(x => x.StockQuantity),
                    Status = taskNum == null ? OutLockStockStatusEnum.已分配.ObjToInt() : OutLockStockStatusEnum.出库中.ObjToInt(),
                    StockId = item.Id,
                    TaskNum = taskNum
                };
                outStockLockInfos.Add(outStockLockInfo);
            }
            return outStockLockInfos;
        }
        public List<Dt_OutStockLockInfo> GetByOrderDetailId(int orderDetailId, OutLockStockStatusEnum outStockStatus)
        {
            return BaseDal.QueryData(x => x.OrderDetailId == orderDetailId && x.Status == outStockStatus.ObjToInt());
        }
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderDetailService.cs
@@ -5,6 +5,9 @@
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.OrderEnum;
using WIDESEA_Common.StockEnum;
using WIDESEA_Core;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
@@ -19,6 +22,7 @@
using WIDESEA_IStockRepository;
using WIDESEA_IStockService;
using WIDESEA_Model.Models;
using WIDESEA_OutboundRepository;
using WIDESEA_StockRepository;
namespace WIDESEA_OutboundService
@@ -26,12 +30,349 @@
    public partial class OutboundOrderDetailService : ServiceBase<Dt_OutboundOrderDetail, IOutboundOrderDetailRepository>, IOutboundOrderDetailService
    {
        private readonly IUnitOfWorkManage _unitOfWorkManage;
        private readonly IStockService _stockService;
        private readonly IOutboundRepository _outboundRepository;
        private readonly IOutStockLockInfoService _outStockLockInfoService;
        private readonly IBasicService _basicService;
        private readonly IRecordService _recordService;
        public IOutboundOrderDetailRepository Repository => BaseDal;
        public OutboundOrderDetailService(IOutboundOrderDetailRepository BaseDal, IUnitOfWorkManage unitOfWorkManage) : base(BaseDal)
        public OutboundOrderDetailService(IOutboundOrderDetailRepository BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockService stockService, IOutboundRepository outboundRepository, IOutStockLockInfoService outStockLockInfoService, IBasicService basicService, IRecordService recordService) : base(BaseDal)
        {
            _unitOfWorkManage = unitOfWorkManage;
            _stockService = stockService;
            _outboundRepository = outboundRepository;
            _outStockLockInfoService = outStockLockInfoService;
            _basicService = basicService;
            _recordService = recordService;
        }
        public WebResponseContent LockOutboundStock(int orderDetailId)
        {
            Dt_OutboundOrderDetail outboundOrderDetail = BaseDal.QueryFirst(x => x.Id == orderDetailId);
            (bool, string) result = CheckDeital(outboundOrderDetail);
            if (!result.Item1) return WebResponseContent.Instance.Error(result.Item2);
            Dt_OutboundOrder outboundOrder = _outboundRepository.OutboundOrderRepository.QueryFirst(x => x.Id == outboundOrderDetail.OrderId);
            float needQuantity = outboundOrderDetail.OrderQuantity - outboundOrderDetail.LockQuantity;
            List<Dt_StockInfo> outStock = new List<Dt_StockInfo>();
            List<Dt_StockInfo> stockInfos = _stockService.StockInfoService.GetUseableStocks(outboundOrderDetail.MaterielCode, outboundOrder.WarehouseId);
            float stockTotalQuantity = stockInfos.Select(x => x.Details.Sum(v => v.StockQuantity - v.OutboundQuantity)).Sum(x => x);
            if (stockTotalQuantity >= needQuantity)//库存够
            {
                int index = 0;
                while (needQuantity > 0)
                {
                    Dt_StockInfo stockInfo = stockInfos[index];
                    float useableStockQuantity = stockInfo.Details.Where(x => x.MaterielCode == outboundOrderDetail.MaterielCode).Sum(x => x.StockQuantity - x.OutboundQuantity);
                    if (useableStockQuantity < needQuantity)
                    {
                        outboundOrderDetail.LockQuantity += useableStockQuantity;
                        stockInfo.Details.ForEach(x => x.OutboundQuantity = x.StockQuantity);
                        needQuantity -= useableStockQuantity;
                    }
                    else
                    {
                        outboundOrderDetail.LockQuantity += needQuantity;
                        stockInfo.Details.ForEach(x =>
                        {
                            if (x.StockQuantity > x.OutboundQuantity && x.MaterielCode == outboundOrderDetail.MaterielCode)
                            {
                                if (x.StockQuantity - x.OutboundQuantity >= needQuantity)
                                {
                                    x.OutboundQuantity += needQuantity;
                                    needQuantity = 0;
                                }
                                else
                                {
                                    needQuantity -= (x.StockQuantity - x.OutboundQuantity);
                                    x.OutboundQuantity = x.StockQuantity;
                                }
                            }
                        });
                    }
                    outStock.Add(stockInfo);
                    index++;
                }
                return WebResponseContent.Instance.OK(data: new { stockInfos, outboundOrderDetail });
            }
            else
            {
                for (int i = 0; i < stockInfos.Count; i++)
                {
                    Dt_StockInfo stockInfo = stockInfos[i];
                    float useableStockQuantity = stockInfo.Details.Where(x => x.MaterielCode == outboundOrderDetail.MaterielCode).Sum(x => x.StockQuantity - x.OutboundQuantity);
                    if (useableStockQuantity < needQuantity)
                    {
                        outboundOrderDetail.LockQuantity += useableStockQuantity;
                        stockInfo.Details.ForEach(x => x.OutboundQuantity = x.StockQuantity);
                        needQuantity -= useableStockQuantity;
                    }
                    else
                    {
                        outboundOrderDetail.LockQuantity += needQuantity;
                        stockInfo.Details.ForEach(x =>
                        {
                            if (x.StockQuantity > x.OutboundQuantity && x.MaterielCode == outboundOrderDetail.MaterielCode)
                            {
                                if (x.StockQuantity - x.OutboundQuantity >= needQuantity)
                                {
                                    x.OutboundQuantity += needQuantity;
                                    needQuantity = 0;
                                }
                                else
                                {
                                    needQuantity -= (x.StockQuantity - x.OutboundQuantity);
                                    x.OutboundQuantity = x.StockQuantity;
                                }
                            }
                        });
                    }
                    outStock.Add(stockInfo);
                }
                return WebResponseContent.Instance.OK(data: new { stockInfos, outboundOrderDetail });
            }
        }
        private (bool, string) CheckDeital(Dt_OutboundOrderDetail outboundOrderDetail)
        {
            if (outboundOrderDetail == null)
            {
                return (false, "未找到出库单明细信息");
            }
            if (outboundOrderDetail.OrderDetailStatus != OrderDetailStatusEnum.New.ObjToInt())
            {
                return (false, "该明细不可操作");
            }
            return (true, "成功");
        }
        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 = _outboundRepository.OutboundOrderRepository.QueryFirst(x => x.Id == outboundOrderDetail.OrderId);
            float originalNeedQuantity = outboundOrderDetail.OrderQuantity - outboundOrderDetail.LockQuantity;
            float needQuantity = originalNeedQuantity;
            List<Dt_StockInfo> outStocks = _stockService.StockInfoService.Repository.GetStockInfosByPalletCodes(stockSelectViews.Select(x => x.PalletCode).ToList());
            float assignQuantity = 0;
            outStocks.ForEach(x =>
            {
                x.Details.ForEach(v =>
                {
                    assignQuantity += v.StockQuantity - v.OutboundQuantity;
                });
            });
            outboundOrderDetail.LockQuantity += assignQuantity;
            outStocks.ForEach(x =>
            {
                x.Details.ForEach(v =>
                {
                    v.OutboundQuantity = v.StockQuantity;
                });
            });
            needQuantity -= assignQuantity;
            if (outboundOrderDetail.OrderQuantity > outboundOrderDetail.LockQuantity)
            {
                List<Dt_StockInfo> stockInfos = _stockService.StockInfoService.GetUseableStocks(outboundOrderDetail.MaterielCode, outboundOrder.WarehouseId);
                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 float residueQuantity);
                outboundOrderDetail.LockQuantity += needQuantity - residueQuantity;
                outStocks.AddRange(autoAssignStocks);
                outboundOrderDetail.OrderDetailStatus = OrderDetailStatusEnum.AssignOver.ObjToInt();
                if (residueQuantity > 0)
                {
                    outboundOrderDetail.OrderDetailStatus = OrderDetailStatusEnum.AssignOverPartial.ObjToInt();
                }
            }
            List<Dt_OutStockLockInfo> outStockLockInfos = _outStockLockInfoService.GetOutStockLockInfos(outboundOrder, outboundOrderDetail, outStocks);
            List<Dt_LocationInfo> locationInfos = _basicService.LocationInfoService.Repository.GetLocationInfos(outStocks.Select(x => x.LocationCode).ToList());
            return (outStocks, outboundOrderDetail, outStockLockInfos, locationInfos);
        }
        public WebResponseContent LockOutboundStock(int orderDetailId, List<StockSelectViewDTO> stockSelectViews)
        {
            try
            {
                Dt_OutboundOrderDetail outboundOrderDetail = BaseDal.QueryFirst(x => x.Id == orderDetailId);
                (bool, string) checkResult = CheckSelectStockDeital(outboundOrderDetail, stockSelectViews);
                if (!checkResult.Item1) throw new Exception(checkResult.Item2);
                (List<Dt_StockInfo>, Dt_OutboundOrderDetail, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) result = AssignStockOutbound(outboundOrderDetail, stockSelectViews);
                _unitOfWorkManage.BeginTran();
                WebResponseContent content = LockOutboundStockDataUpdate(result.Item1, new List<Dt_OutboundOrderDetail> { result.Item2 }, result.Item3, result.Item4);
                if (content.Status)
                {
                    _unitOfWorkManage.CommitTran();
                }
                else
                {
                    _unitOfWorkManage.RollbackTran();
                }
                return content;
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        public WebResponseContent LockOutboundStock(int[] keys)
        {
            try
            {
                List<StockSelectViewDTO> stockSelectViews = new List<StockSelectViewDTO>();
                List<Dt_StockInfo> stockInfos = new List<Dt_StockInfo>();
                List<Dt_OutboundOrderDetail> outboundOrderDetails = new List<Dt_OutboundOrderDetail>();
                List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>();
                List<Dt_LocationInfo> locationInfos = new List<Dt_LocationInfo>();
                foreach (var item in keys)
                {
                    Dt_OutboundOrderDetail outboundOrderDetail = BaseDal.QueryFirst(x => x.Id == item);
                    (bool, string) checkResult = CheckSelectStockDeital(outboundOrderDetail, stockSelectViews);
                    if (!checkResult.Item1) throw new Exception(checkResult.Item2);
                    (List<Dt_StockInfo>, Dt_OutboundOrderDetail, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) result = AssignStockOutbound(outboundOrderDetail, stockSelectViews);
                    if (result.Item1.Count > 0)
                    {
                        stockInfos.AddRange(result.Item1);
                        outboundOrderDetails.Add(result.Item2);
                        outStockLockInfos.AddRange(result.Item3);
                        locationInfos.AddRange(result.Item4);
                    }
                }
                _unitOfWorkManage.BeginTran();
                WebResponseContent content = LockOutboundStockDataUpdate(stockInfos, outboundOrderDetails, outStockLockInfos, locationInfos);
                if (content.Status)
                {
                    _unitOfWorkManage.CommitTran();
                }
                else
                {
                    _unitOfWorkManage.RollbackTran();
                }
                return content;
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        public WebResponseContent LockOutboundStockDataUpdate(List<Dt_StockInfo> stockInfos, List<Dt_OutboundOrderDetail> outboundOrderDetails, List<Dt_OutStockLockInfo> outStockLockInfos, List<Dt_LocationInfo> locationInfos, LocationStatusEnum locationStatus = LocationStatusEnum.Lock, List<Dt_Task>? tasks = null)
        {
            try
            {
                _stockService.StockInfoService.Repository.UpdateData(stockInfos);
                List<Dt_StockInfoDetail> stockInfoDetails = new List<Dt_StockInfoDetail>();
                foreach (var item in stockInfos)
                {
                    stockInfoDetails.AddRange(item.Details);
                }
                _stockService.StockInfoDetailService.Repository.UpdateData(stockInfoDetails);
                BaseDal.UpdateData(outboundOrderDetails);
                List<Dt_OutStockLockInfo> addOutStockLockInfos = outStockLockInfos.Where(x => x.Id == 0).ToList();
                if (addOutStockLockInfos != null && addOutStockLockInfos.Any())
                {
                    _outStockLockInfoService.Repository.AddData(addOutStockLockInfos);
                }
                List<Dt_OutStockLockInfo> updateOutStockLockInfos = outStockLockInfos.Where(x => x.Id > 0).ToList();
                if (updateOutStockLockInfos != null && updateOutStockLockInfos.Any())
                {
                    _outStockLockInfoService.Repository.UpdateData(updateOutStockLockInfos);
                }
                _recordService.LocationStatusChangeRecordSetvice.AddLocationStatusChangeRecord(locationInfos, locationStatus, LocationChangeType.OutboundAssignLocation, "", tasks?.Select(x => x.TaskNum).ToList());
                _basicService.LocationInfoService.Repository.UpdateLocationStatus(locationInfos, locationStatus);
                return WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        private (bool, string) CheckSelectStockDeital(Dt_OutboundOrderDetail outboundOrderDetail, List<StockSelectViewDTO> stockSelectViews)
        {
            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)
            {
                return (false, "选择数量超出单据数量");
            }
            return (true, "成功");
        }
        public WebResponseContent RevokeLockOutboundStock(int orderDetailId)
        {
            Dt_OutboundOrderDetail outboundOrderDetail = BaseDal.QueryFirst(x => x.Id == orderDetailId);
            (bool, string) result = CheckRevoke(outboundOrderDetail);
            if (!result.Item1) return WebResponseContent.Instance.Error(result.Item2);
            List<Dt_OutStockLockInfo> outStockLockInfos = _outStockLockInfoService.GetByOrderDetailId(orderDetailId, OutLockStockStatusEnum.已分配);
            if (outStockLockInfos.Count > 0)
            {
                List<Dt_StockInfo> stocks = _stockService.StockInfoService.Repository.GetStockInfosByPalletCodes(outStockLockInfos.Select(x => x.PalletCode).ToList());
                if (stocks.Count > 0)
                {
                    stocks.ForEach(x =>
                    {
                        x.Details.ForEach(v =>
                        {
                            v.OutboundQuantity = 0;
                        });
                    });
                    outboundOrderDetail.OrderDetailStatus = OrderDetailStatusEnum.New.ObjToInt();
                    outboundOrderDetail.LockQuantity = outboundOrderDetail.OverOutQuantity;
                    outStockLockInfos.ForEach(x =>
                    {
                        x.Status = OutLockStockStatusEnum.撤销.ObjToInt();
                    });
                    List<Dt_LocationInfo> locationInfos = _basicService.LocationInfoService.Repository.GetLocationInfos(stocks.Select(x => x.LocationCode).ToList());
                    return LockOutboundStockDataUpdate(stocks, new List<Dt_OutboundOrderDetail> { outboundOrderDetail }, outStockLockInfos, locationInfos, LocationStatusEnum.InStock);
                }
                return WebResponseContent.Instance.Error("未找到库存信息");
            }
            return WebResponseContent.Instance.Error("未找到已分配的出库信息");
        }
        private (bool, string) CheckRevoke(Dt_OutboundOrderDetail outboundOrderDetail)
        {
            if (outboundOrderDetail == null)
            {
                return (false, "未找到出库单明细信息");
            }
            if (outboundOrderDetail.OrderDetailStatus != OrderDetailStatusEnum.New.ObjToInt() && outboundOrderDetail.OrderDetailStatus != OrderDetailStatusEnum.AssignOverPartial.ObjToInt() && outboundOrderDetail.OrderDetailStatus != OrderDetailStatusEnum.AssignOver.ObjToInt())
            {
                return (false, "该明细不可操作");
            }
            return (true, "成功");
        }
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderService.cs
@@ -29,14 +29,16 @@
        private readonly IMapper _mapper;
        private readonly IBasicService _basicService;
        private readonly IOutboundOrderDetailRepository _outboundOrderDetailRepository;
        private readonly IStockInfoService _stockInfoService;
        public IOutboundOrderRepository Repository => BaseDal;
        public OutboundOrderService(IOutboundOrderRepository BaseDal, IMapper mapper, IBasicService basicService, IOutboundOrderDetailRepository outboundOrderDetailRepository) : base(BaseDal)
        public OutboundOrderService(IOutboundOrderRepository BaseDal, IMapper mapper, IBasicService basicService, IOutboundOrderDetailRepository outboundOrderDetailRepository, IStockInfoService stockInfoService) : base(BaseDal)
        {
            _mapper = mapper;
            _basicService = basicService;
            _outboundOrderDetailRepository = outboundOrderDetailRepository;
            _stockInfoService = stockInfoService;
        }
        public WebResponseContent ReceiveOutOrder(ErpOutOrderDTO model)
@@ -121,7 +123,7 @@
                    {
                        return WebResponseContent.Instance.Error($"未找到该明细行号信息");
                    }
                    if(outboundOrderDetail.OrderDetailStatus != OrderDetailStatusEnum.New.ObjToInt())
                    if (outboundOrderDetail.OrderDetailStatus != OrderDetailStatusEnum.New.ObjToInt())
                    {
                        return WebResponseContent.Instance.Error($"该明细不可修改");
                    }
@@ -137,6 +139,39 @@
                    _outboundOrderDetailRepository.UpdateData(outboundOrderDetail);
                }
                else if (model.Way == 3)
                {
                    if (oldOutboundOrder == null)
                    {
                        return WebResponseContent.Instance.Error($"未找到该出库单");
                    }
                }
                return WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        public WebResponseContent ReleaseOutOrder(int id)
        {
            try
            {
                Dt_OutboundOrder outboundOrder = Db.Queryable<Dt_OutboundOrder>().Where(x => x.Id == id).Includes(x => x.Details).First();
                if (outboundOrder == null)
                {
                    return WebResponseContent.Instance.Error($"未找到该出库单");
                }
                if(outboundOrder.Details == null || outboundOrder.Details.Count == 0)
                {
                    return WebResponseContent.Instance.Error($"未找到明细信息");
                }
                foreach (var item in outboundOrder.Details)
                {
                }
                return WebResponseContent.Instance.OK();
            }
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_RecordService/Service/LocationStatusChangeRecordService.cs
@@ -44,7 +44,7 @@
            }
        }
        public void AddLocationStatusChangeRecord(List<Dt_LocationInfo> locationInfos, LocationStatusEnum newStatus, LocationChangeType changeType, string? orderNo, List<int>? taskNums)
        public void AddLocationStatusChangeRecord(List<Dt_LocationInfo> locationInfos, LocationStatusEnum newStatus, LocationChangeType changeType, string? orderNo = null, List<int>? taskNums = null)
        {
            try
            {
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_StockService/Base/StockInfoDetailService.cs
ÎļþÒÑɾ³ý
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_StockService/Base/StockInfoService.cs
ÎļþÒÑɾ³ý
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_StockService/Service/StockViewService.cs
ÎļþÒÑɾ³ý
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoDetailService.cs
ÎļþÃû´Ó ´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_StockService/Service/StockInfoDetailService.cs ÐÞ¸Ä
@@ -12,6 +12,12 @@
{
    public partial class StockInfoDetailService : ServiceBase<Dt_StockInfoDetail, IStockInfoDetailRepository>, IStockInfoDetailService
    {
        public StockInfoDetailService(IStockInfoDetailRepository BaseDal) : base(BaseDal)
        {
        }
        public IStockInfoDetailRepository Repository => BaseDal;
        public bool ExistSerialNumber(string SerialNumber)
        {
            return BaseDal.QueryFirst(x => x.SerialNumber == SerialNumber) != null;
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoDetail_HtyService.cs
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoService.cs
ÎļþÃû´Ó ´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_StockService/Service/StockInfoService.cs ÐÞ¸Ä
@@ -6,7 +6,6 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Common.StockEnum;
using WIDESEA_Core;
using WIDESEA_Core.BaseServices;
using WIDESEA_Core.Enums;
@@ -23,7 +22,17 @@
{
    public partial class StockInfoService : ServiceBase<Dt_StockInfo, IStockInfoRepository>, IStockInfoService
    {
        private readonly IMapper _mapper;
        private readonly IBasicRepository _basicRepository;
        public IStockInfoRepository Repository => BaseDal;
        public StockInfoService(IStockInfoRepository BaseDal, IMapper mapper, IBasicRepository basicRepository) : base(BaseDal)
        {
            _mapper = mapper;
            _basicRepository = basicRepository;
        }
        public List<Dt_StockInfo> GetOutboundStocks(List<Dt_StockInfo> stockInfos, string materielCode, float needQuantity, out float residueQuantity)
        {
            List<Dt_StockInfo> outStocks = new List<Dt_StockInfo>();
@@ -100,5 +109,12 @@
            residueQuantity = needQuantity;
            return outStocks;
        }
        public List<Dt_StockInfo> GetUseableStocks(string materielCode, int warehoseId)
        {
            List<string> locationCodes = _basicRepository.LocationInfoRepository.GetCanOutLocationCodes(warehoseId);
            return BaseDal.GetStockInfos(materielCode, locationCodes);
        }
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfo_HtyService.cs
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockViewService.cs
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Basic/MaterielInfoController.cs
@@ -1,6 +1,10 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using WIDESEA_Core;
using WIDESEA_Core.BaseController;
using WIDESEA_Core.CodeConfigEnum;
using WIDESEA_Core.Helper;
using WIDESEA_DTO.Basic;
using WIDESEA_IBasicService;
using WIDESEA_Model.Models;
@@ -13,5 +17,24 @@
        public MaterielInfoController(IMaterielInfoService service) : base(service)
        {
        }
        /// <summary>
        /// ç‰©æ–™ç è§£æž
        /// </summary>
        /// <param name="serNum"></param>
        /// <returns></returns>
        [HttpPost, HttpGet, Route("CodeAnalysis")]
        public WebResponseContent CodeAnalysis(string serNum)
        {
            try
            {
                MatSerNumAnalysisModel model = CodeAnalysisHelper.CodeAnalysis<MatSerNumAnalysisModel>(AnalysisCodeEnum.MatSerNumAnalysis, serNum);
                return WebResponseContent.Instance.OK(data: model);
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
    }
}