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);
// 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) && stockInfo.Details != null)
{
item.PalletCode = stockInfo.PalletCode;
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;
}
// 计算库存状态
var ratio = item.MaxCapacity > 0 ? item.StockQuantity / item.MaxCapacity : 0;
if (ratio >= 0.9f)
item.StockStatus = 3; // 已满 (FULL)
else if (ratio >= 0.1f)
item.StockStatus = 1; // 有货 (HAS_STOCK)
else if (ratio > 0)
item.StockStatus = 2; // 库存紧张 (LOW_STOCK)
else
item.StockStatus = 0; // 无货 (EMPTY)
}
else
{
item.StockStatus = 0; // 无货 (EMPTY)
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
};
}
}
}