admin/src/Oms.Application/Services/Warehouse/WarehouseService.Inventory.cs
zzh 8000162f02 docs: 仓储与店铺接口补充 Swagger 中文命名
为 WarehouseService、PlatformStoreService、PlatformStoreOrderService 全部新增接口添加 XML 注释,便于 Swagger 中文展示与前端对接。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-11 15:46:32 +08:00

147 lines
5.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Fake.Application;
using Microsoft.AspNetCore.Mvc;
using Oms.Application.Dtos.Shared;
using Oms.Application.Dtos.Warehouse;
using Oms.Application.Shared;
namespace Oms.Application.Services.Warehouse;
public partial class WarehouseService
{
/// <summary>
/// 查询库存列表。
/// </summary>
/// <param name="input">入参:库存分页查询条件。</param>
/// <returns>按 SKU 汇总的库存分页结果。</returns>
[HttpPost("/warehouse/inventory/list")]
public async Task<OmsPageResult<WarehouseInventoryOutput>> GetInventoryListAsync(WarehouseInventoryListInput input)
{
var customerId = await ResolveCustomerIdAsync(input.CustomerId);
var inventories = await InventoryRepository.GetListAsync(x =>
x.CustomerId == customerId
&& x.Qty > 0
&& (!input.WarehouseId.HasValue || x.WarehouseId == input.WarehouseId.Value));
var skuIds = inventories.Select(x => x.SkuId).Distinct().ToArray();
var skus = skuIds.Length == 0
? []
: await SkuRepository.GetListAsync(x => x.CustomerId == customerId && skuIds.Contains(x.Id));
var skuMap = skus.ToDictionary(x => x.Id);
var keyword = input.Keyword?.Trim();
var grouped = inventories
.GroupBy(x => new { x.SkuId, x.WarehouseId })
.Select(g =>
{
skuMap.TryGetValue(g.Key.SkuId, out var sku);
return new WarehouseInventoryOutput
{
SkuId = g.Key.SkuId,
SkuCode = sku?.SkuCode ?? string.Empty,
SkuName = sku?.SkuName ?? string.Empty,
WarehouseId = g.Key.WarehouseId,
TotalQty = g.Sum(x => x.Qty),
BinCount = g.Count()
};
})
.Where(x =>
string.IsNullOrWhiteSpace(keyword)
|| x.SkuCode.Contains(keyword!, StringComparison.OrdinalIgnoreCase)
|| x.SkuName.Contains(keyword!, StringComparison.OrdinalIgnoreCase))
.OrderBy(x => x.SkuCode)
.ThenBy(x => x.WarehouseId)
.ToList();
var pageIndex = OmsDocHelper.NormalizePage(input.Page);
var pageSize = OmsDocHelper.NormalizePageSize(input.PageSize);
var skip = (pageIndex - 1) * pageSize;
return new OmsPageResult<WarehouseInventoryOutput>
{
Items = grouped.Skip(skip).Take(pageSize).ToList(),
Total = grouped.Count
};
}
/// <summary>
/// 查询 SKU 在各库位的库存明细。
/// </summary>
/// <param name="skuId">SKU ID。</param>
/// <param name="warehouseId">仓库 ID。</param>
/// <param name="customerId">客户 ID(可选)。</param>
/// <returns>库位库存明细列表。</returns>
[HttpGet("/warehouse/inventory/bin-detail")]
public async Task<OmsItemsResult<WarehouseInventoryBinDetailOutput>> GetInventoryBinDetailAsync(
[FromQuery] int skuId,
[FromQuery] int warehouseId,
[FromQuery] int? customerId = null)
{
if (skuId <= 0 || warehouseId <= 0)
{
throw new BusinessException("SKU 和仓库不能为空");
}
var resolvedCustomerId = await ResolveCustomerIdAsync(customerId);
await GetSkuOrThrowAsync(resolvedCustomerId, skuId);
var inventories = await InventoryRepository.GetListAsync(x =>
x.CustomerId == resolvedCustomerId
&& x.WarehouseId == warehouseId
&& x.SkuId == skuId
&& x.Qty > 0);
var binIds = inventories.Select(x => x.BinLocationId).Distinct().ToArray();
var bins = binIds.Length == 0
? []
: await BinLocationRepository.GetListAsync(x => binIds.Contains(x.Id));
var binMap = bins.ToDictionary(x => x.Id);
return new OmsItemsResult<WarehouseInventoryBinDetailOutput>
{
Items = inventories
.OrderBy(x => x.BinLocationId)
.Select(x =>
{
binMap.TryGetValue(x.BinLocationId, out var bin);
return new WarehouseInventoryBinDetailOutput
{
Id = x.Id,
BinLocationId = x.BinLocationId,
BinCode = bin?.BinCode ?? string.Empty,
BinName = bin?.BinName,
Qty = x.Qty
};
})
.ToList()
};
}
/// <summary>
/// 库存移库(库位间调拨)。
/// </summary>
/// <param name="input">入参:源库位、目标库位与数量。</param>
[HttpPost("/warehouse/inventory/relocate")]
public async Task RelocateInventoryAsync(WarehouseInventoryRelocateInput input)
{
var customerId = await ResolveCustomerIdAsync(input.CustomerId);
if (input.SourceBinLocationId == input.TargetBinLocationId)
{
throw new BusinessException("源库位与目标库位不能相同");
}
await GetSkuOrThrowAsync(customerId, input.SkuId);
var source = await InventoryRepository.FirstOrDefaultAsync(x =>
x.CustomerId == customerId
&& x.WarehouseId == input.WarehouseId
&& x.SkuId == input.SkuId
&& x.BinLocationId == input.SourceBinLocationId);
if (source == null || source.Qty < input.Qty)
{
throw new BusinessException("源库位库存不足");
}
await UpsertInventoryQtyAsync(customerId, input.WarehouseId, input.SkuId, input.SourceBinLocationId, -input.Qty);
await UpsertInventoryQtyAsync(customerId, input.WarehouseId, input.SkuId, input.TargetBinLocationId, input.Qty);
}
}