using WIDESEA_Common.StockEnum; using WIDESEA_Core.BaseRepository; using WIDESEA_Core.BaseServices; using WIDESEA_DTO.Stock; using WIDESEA_IBasicService; using WIDESEA_IStockService; using WIDESEA_Model.Models; namespace WIDESEA_StockService { /// /// 库存信息服务实现类 /// public partial class StockInfoService : ServiceBase>, IStockInfoService { /// /// 获取库存信息仓储接口 /// public IRepository Repository => BaseDal; /// /// 货位信息服务接口(用于获取仓库货位信息) /// private readonly ILocationInfoService _locationInfoService; /// /// 仓库信息服务接口(用于获取仓库基本信息) /// private readonly IWarehouseService _warehouseService; /// /// 构造函数 /// /// 基础数据访问对象 public StockInfoService(IRepository baseDal, ILocationInfoService locationInfoService, IWarehouseService warehouseService) : base(baseDal) { _locationInfoService = locationInfoService; _warehouseService = warehouseService; } /// /// 获取库存信息列表(出库日期小于当前时间且库存状态为入库完成的记录) /// /// 库存信息列表 public async Task> GetStockInfoAsync() { return await BaseDal.QueryDataAsync(x => x.OutboundDate < DateTime.Now && x.StockStatus == StockStatusEmun.入库完成.GetHashCode()); } /// /// 获取库存信息列表(出库日期小于当前时间且库存状态为入库完成的记录,且仓库ID匹配) /// /// 仓库ID /// 库存信息列表 public async Task> GetStockInfoAsync(int warehouseId) { return await BaseDal.QueryDataAsync(x => x.OutboundDate < DateTime.Now && x.StockStatus == StockStatusEmun.入库完成.GetHashCode() && x.WarehouseId == warehouseId); } /// /// 获取库存信息(根据托盘码查询) /// /// 托盘编码 /// 库存信息 public async Task GetStockInfoAsync(string palletCode) { return await BaseDal.QueryDataNavFirstAsync(x => x.PalletCode == palletCode); } /// /// 更新库存数据 /// /// 库存信息对象 /// 更新是否成功 public async Task UpdateStockAsync(Dt_StockInfo stockInfo) { return await BaseDal.UpdateDataAsync(stockInfo); } /// /// 检索指定托盘在给定位置的库存详细信息 /// /// 托盘编码 /// 货位编码 /// 库存信息 public async Task GetStockInfoAsync(string palletCode, string locationCode) { return await BaseDal.QueryFirstAsync(x => x.PalletCode == palletCode && x.LocationCode == locationCode); } /// /// 获取仓库3D布局数据 /// /// 仓库ID /// 3D布局DTO public async Task Get3DLayoutAsync(int warehouseId) { // 1. 查询仓库信息 var warehouse = await _warehouseService.Repository.QueryFirstAsync(x => x.WarehouseId == warehouseId); // 2. 查询该仓库所有货位 var locations = await _locationInfoService.Repository.QueryDataAsync(x => x.WarehouseId == warehouseId); // 3. 查询该仓库所有库存信息(包含Details导航属性) var stockInfos = await Repository.QueryDataNavAsync(x => x.WarehouseId == warehouseId && x.LocationId != 0); // 4. 提取物料编号和批次号列表(去重) var materielCodeList = stockInfos .Where(s => s.Details != null) .SelectMany(s => s.Details) .Select(d => d.MaterielCode) .Where(c => !string.IsNullOrEmpty(c)) .Distinct() .ToList(); var batchNoList = stockInfos .Where(s => s.Details != null) .SelectMany(s => s.Details) .Select(d => d.BatchNo) .Where(b => !string.IsNullOrEmpty(b)) .Distinct() .ToList(); // 5. 创建库存字典用于快速查找(以LocationId为键) var stockDict = stockInfos.ToDictionary(s => s.LocationId, s => s); // 6. 映射每个货位到Location3DItemDTO const float defaultMaxCapacity = 100f; var locationItems = locations.Select(loc => { var item = new Location3DItemDTO { LocationId = loc.Id, LocationCode = loc.LocationCode, Row = loc.Row, Column = loc.Column, Layer = loc.Layer, LocationStatus = loc.LocationStatus, MaxCapacity = defaultMaxCapacity }; // 尝试从库存字典中获取库存信息 if (stockDict.TryGetValue(loc.Id, out var stockInfo)) { // 空托盘也有库存记录,只是不包含明细 item.PalletCode = stockInfo.PalletCode; item.StockStatus = stockInfo.StockStatus; // 直接使用后端库存状态 // 只有当Details不为null且有数据时才处理库存明细 if (stockInfo.Details != null && stockInfo.Details.Any()) { item.StockQuantity = stockInfo.Details.Sum(d => d.StockQuantity); // 获取第一个明细的物料信息(如果存在) var firstDetail = stockInfo.Details.FirstOrDefault(); if (firstDetail != null) { item.MaterielCode = firstDetail.MaterielCode; item.MaterielName = firstDetail.MaterielName; item.BatchNo = firstDetail.BatchNo; } // 填充库存明细列表 item.Details = stockInfo.Details.Select(d => new StockDetailItemDTO { Id = d.Id, MaterielCode = d.MaterielCode, MaterielName = d.MaterielName, BatchNo = d.BatchNo, StockQuantity = d.StockQuantity, Unit = d.Unit, ProductionDate = d.ProductionDate, EffectiveDate = d.EffectiveDate, OrderNo = d.OrderNo, Status = d.Status }).ToList(); } else { // 空托盘(无明细) item.StockQuantity = 0; item.Details = new List(); // 确保是空列表而非null } } else { // 无库存记录,货位为空 item.StockStatus = 0; // 空闲 item.StockQuantity = 0; } return item; }).ToList(); // 7. 计算仓库尺寸 var maxRow = locations.Any() ? locations.Max(l => l.Row) : 0; var maxColumn = locations.Any() ? locations.Max(l => l.Column) : 0; var maxLayer = locations.Any() ? locations.Max(l => l.Layer) : 0; // 8. 构建返回结果 return new Stock3DLayoutDTO { WarehouseId = warehouseId, WarehouseName = warehouse?.WarehouseName ?? string.Empty, MaxRow = maxRow, MaxColumn = maxColumn, MaxLayer = maxLayer, MaterielCodeList = materielCodeList, BatchNoList = batchNoList, Locations = locationItems }; } } }