修复管理端访问仓储与店铺接口时客户ID必填报错。

列表/汇总/详情改用 ResolveListCustomerIdAsync,管理端未传 customerId 时可查询全部数据。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zzh 2026-07-11 16:14:44 +08:00
parent 8000162f02
commit 36fb191f94
8 changed files with 88 additions and 57 deletions

View File

@ -43,7 +43,7 @@ public class PlatformStoreOrderService : ApplicationService
[HttpPost("/order/platform-store-order/list")] [HttpPost("/order/platform-store-order/list")]
public async Task<OmsPageResult<PlatformStoreOrderOutput>> GetListAsync(PlatformStoreOrderListInput input) public async Task<OmsPageResult<PlatformStoreOrderOutput>> GetListAsync(PlatformStoreOrderListInput input)
{ {
var customerId = await WarehouseCustomerHelper.ResolveRequiredCustomerIdAsync( var customerId = await WarehouseCustomerHelper.ResolveListCustomerIdAsync(
CustomerRepository, CustomerRepository,
CurrentUser, CurrentUser,
input.CustomerId); input.CustomerId);
@ -95,7 +95,7 @@ public class PlatformStoreOrderService : ApplicationService
[HttpGet("/order/platform-store-order/detail")] [HttpGet("/order/platform-store-order/detail")]
public async Task<PlatformStoreOrderOutput> GetDetailAsync([FromQuery] int id, [FromQuery] int? customerId = null) public async Task<PlatformStoreOrderOutput> GetDetailAsync([FromQuery] int id, [FromQuery] int? customerId = null)
{ {
var resolvedCustomerId = await WarehouseCustomerHelper.ResolveRequiredCustomerIdAsync( var resolvedCustomerId = await WarehouseCustomerHelper.ResolveListCustomerIdAsync(
CustomerRepository, CustomerRepository,
CurrentUser, CurrentUser,
customerId); customerId);
@ -121,12 +121,12 @@ public class PlatformStoreOrderService : ApplicationService
[HttpGet("/order/platform-store-order/summary")] [HttpGet("/order/platform-store-order/summary")]
public async Task<PlatformStoreOrderSummaryOutput> GetSummaryAsync([FromQuery] int? customerId = null, [FromQuery] int? storeId = null) public async Task<PlatformStoreOrderSummaryOutput> GetSummaryAsync([FromQuery] int? customerId = null, [FromQuery] int? storeId = null)
{ {
var resolvedCustomerId = await WarehouseCustomerHelper.ResolveRequiredCustomerIdAsync( var resolvedCustomerId = await WarehouseCustomerHelper.ResolveListCustomerIdAsync(
CustomerRepository, CustomerRepository,
CurrentUser, CurrentUser,
customerId); customerId);
var orders = await StoreOrderRepository.GetListAsync(x => var orders = await StoreOrderRepository.GetListAsync(x =>
x.CustomerId == resolvedCustomerId (!resolvedCustomerId.HasValue || x.CustomerId == resolvedCustomerId.Value)
&& (!storeId.HasValue || x.StoreId == storeId.Value)); && (!storeId.HasValue || x.StoreId == storeId.Value));
return new PlatformStoreOrderSummaryOutput return new PlatformStoreOrderSummaryOutput
@ -228,11 +228,12 @@ public class PlatformStoreOrderService : ApplicationService
throw new BusinessException("请选择要删除的订单"); throw new BusinessException("请选择要删除的订单");
} }
var customerId = await WarehouseCustomerHelper.ResolveRequiredCustomerIdAsync( var customerId = await WarehouseCustomerHelper.ResolveListCustomerIdAsync(
CustomerRepository, CustomerRepository,
CurrentUser, CurrentUser,
input.CustomerId); input.CustomerId);
var orders = await StoreOrderRepository.GetListAsync(x => x.CustomerId == customerId && input.Ids.Contains(x.Id)); var orders = await StoreOrderRepository.GetListAsync(x =>
(!customerId.HasValue || x.CustomerId == customerId.Value) && input.Ids.Contains(x.Id));
foreach (var order in orders) foreach (var order in orders)
{ {
var lines = await StoreOrderLineRepository.GetListAsync(x => x.StoreOrderId == order.Id); var lines = await StoreOrderLineRepository.GetListAsync(x => x.StoreOrderId == order.Id);
@ -578,9 +579,11 @@ public class PlatformStoreOrderService : ApplicationService
return linked?.ServiceNo; return linked?.ServiceNo;
} }
private async Task<SalesStoreOrder> GetOrderOrThrowAsync(int customerId, int id) private async Task<SalesStoreOrder> GetOrderOrThrowAsync(int? customerId, int id)
{ {
var entity = await StoreOrderRepository.FirstOrDefaultAsync(x => x.Id == id && x.CustomerId == customerId); var entity = customerId.HasValue
? await StoreOrderRepository.FirstOrDefaultAsync(x => x.Id == id && x.CustomerId == customerId.Value)
: await StoreOrderRepository.FirstOrDefaultAsync(x => x.Id == id);
if (entity == null) if (entity == null)
{ {
throw new BusinessException("店铺订单不存在"); throw new BusinessException("店铺订单不存在");
@ -589,13 +592,13 @@ public class PlatformStoreOrderService : ApplicationService
return entity; return entity;
} }
private static Expression<Func<SalesStoreOrder, bool>> BuildListPredicate(int customerId, PlatformStoreOrderListInput input) private static Expression<Func<SalesStoreOrder, bool>> BuildListPredicate(int? customerId, PlatformStoreOrderListInput input)
{ {
var fulfillStatus = input.FulfillStatus?.Trim(); var fulfillStatus = input.FulfillStatus?.Trim();
var platformOrderNo = input.PlatformOrderNo?.Trim(); var platformOrderNo = input.PlatformOrderNo?.Trim();
return x => return x =>
x.CustomerId == customerId (!customerId.HasValue || x.CustomerId == customerId.Value)
&& (!input.StoreId.HasValue || x.StoreId == input.StoreId.Value) && (!input.StoreId.HasValue || x.StoreId == input.StoreId.Value)
&& (string.IsNullOrWhiteSpace(fulfillStatus) || x.FulfillStatus == fulfillStatus) && (string.IsNullOrWhiteSpace(fulfillStatus) || x.FulfillStatus == fulfillStatus)
&& (!input.IsSuspended.HasValue || x.IsSuspended == input.IsSuspended.Value) && (!input.IsSuspended.HasValue || x.IsSuspended == input.IsSuspended.Value)

View File

@ -28,7 +28,7 @@ public class PlatformStoreService : ApplicationService
[HttpPost("/order/platform-store/list")] [HttpPost("/order/platform-store/list")]
public async Task<OmsPageResult<PlatformStoreOutput>> GetListAsync(PlatformStorePageInput input) public async Task<OmsPageResult<PlatformStoreOutput>> GetListAsync(PlatformStorePageInput input)
{ {
var customerId = await WarehouseCustomerHelper.ResolveRequiredCustomerIdAsync( var customerId = await WarehouseCustomerHelper.ResolveListCustomerIdAsync(
CustomerRepository, CustomerRepository,
CurrentUser, CurrentUser,
input.CustomerId); input.CustomerId);
@ -138,20 +138,23 @@ public class PlatformStoreService : ApplicationService
throw new BusinessException("请选择要删除的店铺"); throw new BusinessException("请选择要删除的店铺");
} }
var customerId = await WarehouseCustomerHelper.ResolveRequiredCustomerIdAsync( var customerId = await WarehouseCustomerHelper.ResolveListCustomerIdAsync(
CustomerRepository, CustomerRepository,
CurrentUser, CurrentUser,
null); null);
var entities = await StoreRepository.GetListAsync(x => x.CustomerId == customerId && input.Ids.Contains(x.Id)); var entities = await StoreRepository.GetListAsync(x =>
(!customerId.HasValue || x.CustomerId == customerId.Value) && input.Ids.Contains(x.Id));
foreach (var entity in entities) foreach (var entity in entities)
{ {
await StoreRepository.DeleteAsync(entity); await StoreRepository.DeleteAsync(entity);
} }
} }
private async Task<SalesStore> GetStoreOrThrowAsync(int customerId, int id) private async Task<SalesStore> GetStoreOrThrowAsync(int? customerId, int id)
{ {
var entity = await StoreRepository.FirstOrDefaultAsync(x => x.Id == id && x.CustomerId == customerId); var entity = customerId.HasValue
? await StoreRepository.FirstOrDefaultAsync(x => x.Id == id && x.CustomerId == customerId.Value)
: await StoreRepository.FirstOrDefaultAsync(x => x.Id == id);
if (entity == null) if (entity == null)
{ {
throw new BusinessException("店铺不存在"); throw new BusinessException("店铺不存在");
@ -160,7 +163,7 @@ public class PlatformStoreService : ApplicationService
return entity; return entity;
} }
private static Expression<Func<SalesStore, bool>> BuildListPredicate(int customerId, PlatformStorePageInput input) private static Expression<Func<SalesStore, bool>> BuildListPredicate(int? customerId, PlatformStorePageInput input)
{ {
var platformCode = input.PlatformCode?.Trim(); var platformCode = input.PlatformCode?.Trim();
var nickname = input.StoreNickname?.Trim(); var nickname = input.StoreNickname?.Trim();
@ -169,7 +172,7 @@ public class PlatformStoreService : ApplicationService
var within7Days = now.AddDays(7); var within7Days = now.AddDays(7);
return x => return x =>
x.CustomerId == customerId (!customerId.HasValue || x.CustomerId == customerId.Value)
&& (string.IsNullOrWhiteSpace(platformCode) || x.PlatformCode == platformCode) && (string.IsNullOrWhiteSpace(platformCode) || x.PlatformCode == platformCode)
&& (string.IsNullOrWhiteSpace(nickname) || x.StoreNickname.Contains(nickname)) && (string.IsNullOrWhiteSpace(nickname) || x.StoreNickname.Contains(nickname))
&& (string.IsNullOrWhiteSpace(filter) || filter == "normal" && (string.IsNullOrWhiteSpace(filter) || filter == "normal"

View File

@ -6,15 +6,23 @@ namespace Oms.Application.Services.Warehouse;
public partial class WarehouseService public partial class WarehouseService
{ {
private async Task<int> ResolveCustomerIdAsync(int? requestedCustomerId) => private Task<int?> ResolveListCustomerIdAsync(int? requestedCustomerId) =>
await WarehouseCustomerHelper.ResolveRequiredCustomerIdAsync( WarehouseCustomerHelper.ResolveListCustomerIdAsync(
CustomerRepository, CustomerRepository,
CurrentUser, CurrentUser,
requestedCustomerId); requestedCustomerId);
private async Task<CSku> GetSkuOrThrowAsync(int customerId, int skuId) private Task<int> ResolveMutationCustomerIdAsync(int? requestedCustomerId) =>
WarehouseCustomerHelper.ResolveRequiredCustomerIdAsync(
CustomerRepository,
CurrentUser,
requestedCustomerId);
private async Task<CSku> GetSkuOrThrowAsync(int? customerId, int skuId)
{ {
var entity = await SkuRepository.FirstOrDefaultAsync(x => x.Id == skuId && x.CustomerId == customerId); var entity = customerId.HasValue
? await SkuRepository.FirstOrDefaultAsync(x => x.Id == skuId && x.CustomerId == customerId.Value)
: await SkuRepository.FirstOrDefaultAsync(x => x.Id == skuId);
if (entity == null) if (entity == null)
{ {
throw new BusinessException("SKU 不存在"); throw new BusinessException("SKU 不存在");

View File

@ -19,13 +19,13 @@ public partial class WarehouseService
[HttpPost("/warehouse/inbound/list")] [HttpPost("/warehouse/inbound/list")]
public async Task<OmsPageResult<WarehouseInboundOutput>> GetInboundListAsync(WarehouseInboundListInput input) public async Task<OmsPageResult<WarehouseInboundOutput>> GetInboundListAsync(WarehouseInboundListInput input)
{ {
var customerId = await ResolveCustomerIdAsync(input.CustomerId); var customerId = await ResolveListCustomerIdAsync(input.CustomerId);
var keyword = input.Keyword?.Trim(); var keyword = input.Keyword?.Trim();
var hasKeyword = !string.IsNullOrWhiteSpace(keyword); var hasKeyword = !string.IsNullOrWhiteSpace(keyword);
var receiptStatus = input.ReceiptStatus?.Trim(); var receiptStatus = input.ReceiptStatus?.Trim();
Expression<Func<CInboundNotice, bool>> predicate = x => Expression<Func<CInboundNotice, bool>> predicate = x =>
x.CustomerId == customerId (!customerId.HasValue || x.CustomerId == customerId.Value)
&& (!input.WarehouseId.HasValue || x.WarehouseId == input.WarehouseId.Value) && (!input.WarehouseId.HasValue || x.WarehouseId == input.WarehouseId.Value)
&& (string.IsNullOrWhiteSpace(receiptStatus) || x.ReceiptStatus == receiptStatus) && (string.IsNullOrWhiteSpace(receiptStatus) || x.ReceiptStatus == receiptStatus)
&& (!hasKeyword || x.NoticeNo.Contains(keyword!) || (x.MarkReference != null && x.MarkReference.Contains(keyword!))); && (!hasKeyword || x.NoticeNo.Contains(keyword!) || (x.MarkReference != null && x.MarkReference.Contains(keyword!)));
@ -66,7 +66,7 @@ public partial class WarehouseService
[FromQuery] int id, [FromQuery] int id,
[FromQuery] int? customerId = null) [FromQuery] int? customerId = null)
{ {
var resolvedCustomerId = await ResolveCustomerIdAsync(customerId); var resolvedCustomerId = await ResolveListCustomerIdAsync(customerId);
var notice = await GetInboundNoticeOrThrowAsync(resolvedCustomerId, id); var notice = await GetInboundNoticeOrThrowAsync(resolvedCustomerId, id);
var boxes = await InboundBoxRepository.GetListAsync(x => x.InboundNoticeId == notice.Id); var boxes = await InboundBoxRepository.GetListAsync(x => x.InboundNoticeId == notice.Id);
boxes = boxes.OrderBy(x => x.BoxSeqNo).ThenBy(x => x.Id).ToList(); boxes = boxes.OrderBy(x => x.BoxSeqNo).ThenBy(x => x.Id).ToList();
@ -103,7 +103,7 @@ public partial class WarehouseService
[HttpPost("/warehouse/inbound/save")] [HttpPost("/warehouse/inbound/save")]
public async Task<WarehouseInboundDetailOutput> SaveInboundAsync(WarehouseInboundSaveInput input) public async Task<WarehouseInboundDetailOutput> SaveInboundAsync(WarehouseInboundSaveInput input)
{ {
var customerId = await ResolveCustomerIdAsync(input.CustomerId); var customerId = await ResolveMutationCustomerIdAsync(input.CustomerId);
if (input.WarehouseId <= 0) if (input.WarehouseId <= 0)
{ {
throw new BusinessException("仓库ID不能为空"); throw new BusinessException("仓库ID不能为空");
@ -194,7 +194,7 @@ public partial class WarehouseService
[HttpPost("/warehouse/inbound/delete")] [HttpPost("/warehouse/inbound/delete")]
public async Task DeleteInboundAsync(IdInput input) public async Task DeleteInboundAsync(IdInput input)
{ {
var customerId = await ResolveCustomerIdAsync(null); var customerId = await ResolveListCustomerIdAsync(null);
var notice = await GetInboundNoticeOrThrowAsync(customerId, input.Id); var notice = await GetInboundNoticeOrThrowAsync(customerId, input.Id);
if (notice.ReceiptStatus != WarehouseReceiptStatusCodes.Forecasted) if (notice.ReceiptStatus != WarehouseReceiptStatusCodes.Forecasted)
{ {
@ -212,7 +212,7 @@ public partial class WarehouseService
[HttpPost("/warehouse/inbound/confirm-receive")] [HttpPost("/warehouse/inbound/confirm-receive")]
public async Task ConfirmInboundReceiveAsync(WarehouseInboundConfirmReceiveInput input) public async Task ConfirmInboundReceiveAsync(WarehouseInboundConfirmReceiveInput input)
{ {
var customerId = await ResolveCustomerIdAsync(input.CustomerId); var customerId = await ResolveMutationCustomerIdAsync(input.CustomerId);
var notice = await GetInboundNoticeOrThrowAsync(customerId, input.InboundNoticeId); var notice = await GetInboundNoticeOrThrowAsync(customerId, input.InboundNoticeId);
if (notice.ReceiptStatus == WarehouseReceiptStatusCodes.Completed) if (notice.ReceiptStatus == WarehouseReceiptStatusCodes.Completed)
{ {
@ -299,9 +299,9 @@ public partial class WarehouseService
[HttpGet("/warehouse/inbound/summary")] [HttpGet("/warehouse/inbound/summary")]
public async Task<WarehouseInboundSummaryOutput> GetInboundSummaryAsync([FromQuery] int? customerId = null, [FromQuery] int? warehouseId = null) public async Task<WarehouseInboundSummaryOutput> GetInboundSummaryAsync([FromQuery] int? customerId = null, [FromQuery] int? warehouseId = null)
{ {
var resolvedCustomerId = await ResolveCustomerIdAsync(customerId); var resolvedCustomerId = await ResolveListCustomerIdAsync(customerId);
var notices = await InboundNoticeRepository.GetListAsync(x => var notices = await InboundNoticeRepository.GetListAsync(x =>
x.CustomerId == resolvedCustomerId (!resolvedCustomerId.HasValue || x.CustomerId == resolvedCustomerId.Value)
&& (!warehouseId.HasValue || x.WarehouseId == warehouseId.Value)); && (!warehouseId.HasValue || x.WarehouseId == warehouseId.Value));
return new WarehouseInboundSummaryOutput return new WarehouseInboundSummaryOutput
@ -312,9 +312,11 @@ public partial class WarehouseService
}; };
} }
private async Task<CInboundNotice> GetInboundNoticeOrThrowAsync(int customerId, int id) private async Task<CInboundNotice> GetInboundNoticeOrThrowAsync(int? customerId, int id)
{ {
var entity = await InboundNoticeRepository.FirstOrDefaultAsync(x => x.Id == id && x.CustomerId == customerId); var entity = customerId.HasValue
? await InboundNoticeRepository.FirstOrDefaultAsync(x => x.Id == id && x.CustomerId == customerId.Value)
: await InboundNoticeRepository.FirstOrDefaultAsync(x => x.Id == id);
if (entity == null) if (entity == null)
{ {
throw new BusinessException("入库预报不存在"); throw new BusinessException("入库预报不存在");

View File

@ -16,16 +16,17 @@ public partial class WarehouseService
[HttpPost("/warehouse/inventory/list")] [HttpPost("/warehouse/inventory/list")]
public async Task<OmsPageResult<WarehouseInventoryOutput>> GetInventoryListAsync(WarehouseInventoryListInput input) public async Task<OmsPageResult<WarehouseInventoryOutput>> GetInventoryListAsync(WarehouseInventoryListInput input)
{ {
var customerId = await ResolveCustomerIdAsync(input.CustomerId); var customerId = await ResolveListCustomerIdAsync(input.CustomerId);
var inventories = await InventoryRepository.GetListAsync(x => var inventories = await InventoryRepository.GetListAsync(x =>
x.CustomerId == customerId (!customerId.HasValue || x.CustomerId == customerId.Value)
&& x.Qty > 0 && x.Qty > 0
&& (!input.WarehouseId.HasValue || x.WarehouseId == input.WarehouseId.Value)); && (!input.WarehouseId.HasValue || x.WarehouseId == input.WarehouseId.Value));
var skuIds = inventories.Select(x => x.SkuId).Distinct().ToArray(); var skuIds = inventories.Select(x => x.SkuId).Distinct().ToArray();
var skus = skuIds.Length == 0 var skus = skuIds.Length == 0
? [] ? []
: await SkuRepository.GetListAsync(x => x.CustomerId == customerId && skuIds.Contains(x.Id)); : await SkuRepository.GetListAsync(x =>
(!customerId.HasValue || x.CustomerId == customerId.Value) && skuIds.Contains(x.Id));
var skuMap = skus.ToDictionary(x => x.Id); var skuMap = skus.ToDictionary(x => x.Id);
var keyword = input.Keyword?.Trim(); var keyword = input.Keyword?.Trim();
@ -81,11 +82,11 @@ public partial class WarehouseService
throw new BusinessException("SKU 和仓库不能为空"); throw new BusinessException("SKU 和仓库不能为空");
} }
var resolvedCustomerId = await ResolveCustomerIdAsync(customerId); var resolvedCustomerId = await ResolveListCustomerIdAsync(customerId);
await GetSkuOrThrowAsync(resolvedCustomerId, skuId); await GetSkuOrThrowAsync(resolvedCustomerId, skuId);
var inventories = await InventoryRepository.GetListAsync(x => var inventories = await InventoryRepository.GetListAsync(x =>
x.CustomerId == resolvedCustomerId (!resolvedCustomerId.HasValue || x.CustomerId == resolvedCustomerId.Value)
&& x.WarehouseId == warehouseId && x.WarehouseId == warehouseId
&& x.SkuId == skuId && x.SkuId == skuId
&& x.Qty > 0); && x.Qty > 0);
@ -122,7 +123,7 @@ public partial class WarehouseService
[HttpPost("/warehouse/inventory/relocate")] [HttpPost("/warehouse/inventory/relocate")]
public async Task RelocateInventoryAsync(WarehouseInventoryRelocateInput input) public async Task RelocateInventoryAsync(WarehouseInventoryRelocateInput input)
{ {
var customerId = await ResolveCustomerIdAsync(input.CustomerId); var customerId = await ResolveMutationCustomerIdAsync(input.CustomerId);
if (input.SourceBinLocationId == input.TargetBinLocationId) if (input.SourceBinLocationId == input.TargetBinLocationId)
{ {
throw new BusinessException("源库位与目标库位不能相同"); throw new BusinessException("源库位与目标库位不能相同");

View File

@ -19,13 +19,13 @@ public partial class WarehouseService
[HttpPost("/warehouse/parcel/list")] [HttpPost("/warehouse/parcel/list")]
public async Task<OmsPageResult<WarehouseParcelOutput>> GetParcelListAsync(WarehouseParcelListInput input) public async Task<OmsPageResult<WarehouseParcelOutput>> GetParcelListAsync(WarehouseParcelListInput input)
{ {
var customerId = await ResolveCustomerIdAsync(input.CustomerId); var customerId = await ResolveListCustomerIdAsync(input.CustomerId);
var keyword = input.Keyword?.Trim(); var keyword = input.Keyword?.Trim();
var hasKeyword = !string.IsNullOrWhiteSpace(keyword); var hasKeyword = !string.IsNullOrWhiteSpace(keyword);
var lifecycleStatus = input.LifecycleStatus?.Trim(); var lifecycleStatus = input.LifecycleStatus?.Trim();
Expression<Func<CParcel, bool>> predicate = x => Expression<Func<CParcel, bool>> predicate = x =>
x.CustomerId == customerId (!customerId.HasValue || x.CustomerId == customerId.Value)
&& (!input.WarehouseId.HasValue || x.WarehouseId == input.WarehouseId.Value) && (!input.WarehouseId.HasValue || x.WarehouseId == input.WarehouseId.Value)
&& (string.IsNullOrWhiteSpace(lifecycleStatus) || x.LifecycleStatus == lifecycleStatus) && (string.IsNullOrWhiteSpace(lifecycleStatus) || x.LifecycleStatus == lifecycleStatus)
&& (!hasKeyword || x.TrackingNo.Contains(keyword!) || (x.CarrierName != null && x.CarrierName.Contains(keyword!))); && (!hasKeyword || x.TrackingNo.Contains(keyword!) || (x.CarrierName != null && x.CarrierName.Contains(keyword!)));
@ -59,7 +59,7 @@ public partial class WarehouseService
[HttpPost("/warehouse/parcel/save")] [HttpPost("/warehouse/parcel/save")]
public async Task<WarehouseParcelOutput> SaveParcelAsync(WarehouseParcelSaveInput input) public async Task<WarehouseParcelOutput> SaveParcelAsync(WarehouseParcelSaveInput input)
{ {
var customerId = await ResolveCustomerIdAsync(input.CustomerId); var customerId = await ResolveMutationCustomerIdAsync(input.CustomerId);
if (input.WarehouseId <= 0) if (input.WarehouseId <= 0)
{ {
throw new BusinessException("仓库ID不能为空"); throw new BusinessException("仓库ID不能为空");
@ -141,7 +141,7 @@ public partial class WarehouseService
[HttpPost("/warehouse/parcel/delete")] [HttpPost("/warehouse/parcel/delete")]
public async Task DeleteParcelAsync(IdInput input) public async Task DeleteParcelAsync(IdInput input)
{ {
var customerId = await ResolveCustomerIdAsync(null); var customerId = await ResolveListCustomerIdAsync(null);
var parcel = await GetParcelOrThrowAsync(customerId, input.Id); var parcel = await GetParcelOrThrowAsync(customerId, input.Id);
if (parcel.LifecycleStatus == WarehouseParcelLifecycleCodes.Stored) if (parcel.LifecycleStatus == WarehouseParcelLifecycleCodes.Stored)
{ {
@ -159,7 +159,7 @@ public partial class WarehouseService
[HttpPost("/warehouse/parcel/putaway")] [HttpPost("/warehouse/parcel/putaway")]
public async Task PutawayParcelAsync(WarehouseParcelPutawayInput input) public async Task PutawayParcelAsync(WarehouseParcelPutawayInput input)
{ {
var customerId = await ResolveCustomerIdAsync(input.CustomerId); var customerId = await ResolveMutationCustomerIdAsync(input.CustomerId);
var parcel = await GetParcelOrThrowAsync(customerId, input.ParcelId); var parcel = await GetParcelOrThrowAsync(customerId, input.ParcelId);
if (parcel.LifecycleStatus == WarehouseParcelLifecycleCodes.Stored) if (parcel.LifecycleStatus == WarehouseParcelLifecycleCodes.Stored)
{ {
@ -205,9 +205,11 @@ public partial class WarehouseService
await ParcelRepository.UpdateAsync(parcel); await ParcelRepository.UpdateAsync(parcel);
} }
private async Task<CParcel> GetParcelOrThrowAsync(int customerId, int id) private async Task<CParcel> GetParcelOrThrowAsync(int? customerId, int id)
{ {
var entity = await ParcelRepository.FirstOrDefaultAsync(x => x.Id == id && x.CustomerId == customerId); var entity = customerId.HasValue
? await ParcelRepository.FirstOrDefaultAsync(x => x.Id == id && x.CustomerId == customerId.Value)
: await ParcelRepository.FirstOrDefaultAsync(x => x.Id == id);
if (entity == null) if (entity == null)
{ {
throw new BusinessException("包裹不存在"); throw new BusinessException("包裹不存在");

View File

@ -17,12 +17,12 @@ public partial class WarehouseService
[HttpPost("/warehouse/sku/list")] [HttpPost("/warehouse/sku/list")]
public async Task<OmsPageResult<WarehouseSkuOutput>> GetSkuListAsync(WarehouseSkuListInput input) public async Task<OmsPageResult<WarehouseSkuOutput>> GetSkuListAsync(WarehouseSkuListInput input)
{ {
var customerId = await ResolveCustomerIdAsync(input.CustomerId); var customerId = await ResolveListCustomerIdAsync(input.CustomerId);
var keyword = input.Keyword?.Trim(); var keyword = input.Keyword?.Trim();
var hasKeyword = !string.IsNullOrWhiteSpace(keyword); var hasKeyword = !string.IsNullOrWhiteSpace(keyword);
Expression<Func<Domain.WarehouseAggregate.Entities.CSku, bool>> predicate = x => Expression<Func<Domain.WarehouseAggregate.Entities.CSku, bool>> predicate = x =>
x.CustomerId == customerId (!customerId.HasValue || x.CustomerId == customerId.Value)
&& (!hasKeyword || x.SkuCode.Contains(keyword!) || x.SkuName.Contains(keyword!)); && (!hasKeyword || x.SkuCode.Contains(keyword!) || x.SkuName.Contains(keyword!));
var pageIndex = OmsDocHelper.NormalizePage(input.Page); var pageIndex = OmsDocHelper.NormalizePage(input.Page);
@ -37,7 +37,8 @@ public partial class WarehouseService
var skuIds = entities.Select(x => x.Id).ToArray(); var skuIds = entities.Select(x => x.Id).ToArray();
var inventories = skuIds.Length == 0 var inventories = skuIds.Length == 0
? [] ? []
: await InventoryRepository.GetListAsync(x => x.CustomerId == customerId && skuIds.Contains(x.SkuId)); : await InventoryRepository.GetListAsync(x =>
(!customerId.HasValue || x.CustomerId == customerId.Value) && skuIds.Contains(x.SkuId));
var qtyMap = inventories var qtyMap = inventories
.GroupBy(x => x.SkuId) .GroupBy(x => x.SkuId)
.ToDictionary(g => g.Key, g => g.Sum(x => x.Qty)); .ToDictionary(g => g.Key, g => g.Sum(x => x.Qty));
@ -58,9 +59,11 @@ public partial class WarehouseService
[HttpGet("/warehouse/sku/detail")] [HttpGet("/warehouse/sku/detail")]
public async Task<WarehouseSkuOutput> GetSkuDetailAsync([FromQuery] int id, [FromQuery] int? customerId = null) public async Task<WarehouseSkuOutput> GetSkuDetailAsync([FromQuery] int id, [FromQuery] int? customerId = null)
{ {
var resolvedCustomerId = await ResolveCustomerIdAsync(customerId); var resolvedCustomerId = await ResolveListCustomerIdAsync(customerId);
var entity = await GetSkuOrThrowAsync(resolvedCustomerId, id); var entity = await GetSkuOrThrowAsync(resolvedCustomerId, id);
var inventories = await InventoryRepository.GetListAsync(x => x.CustomerId == resolvedCustomerId && x.SkuId == id); var inventories = await InventoryRepository.GetListAsync(x =>
(!resolvedCustomerId.HasValue || x.CustomerId == resolvedCustomerId.Value)
&& x.SkuId == id);
return MapSkuOutput(entity, inventories.Sum(x => x.Qty)); return MapSkuOutput(entity, inventories.Sum(x => x.Qty));
} }
@ -72,7 +75,7 @@ public partial class WarehouseService
[HttpPost("/warehouse/sku/save")] [HttpPost("/warehouse/sku/save")]
public async Task<WarehouseSkuOutput> SaveSkuAsync(WarehouseSkuSaveInput input) public async Task<WarehouseSkuOutput> SaveSkuAsync(WarehouseSkuSaveInput input)
{ {
var customerId = await ResolveCustomerIdAsync(input.CustomerId); var customerId = await ResolveMutationCustomerIdAsync(input.CustomerId);
var skuCode = input.SkuCode.Trim(); var skuCode = input.SkuCode.Trim();
var skuName = input.SkuName.Trim(); var skuName = input.SkuName.Trim();
if (string.IsNullOrWhiteSpace(skuCode) || string.IsNullOrWhiteSpace(skuName)) if (string.IsNullOrWhiteSpace(skuCode) || string.IsNullOrWhiteSpace(skuName))
@ -125,10 +128,10 @@ public partial class WarehouseService
[HttpPost("/warehouse/sku/delete")] [HttpPost("/warehouse/sku/delete")]
public async Task DeleteSkuAsync(IdInput input) public async Task DeleteSkuAsync(IdInput input)
{ {
var customerId = await ResolveCustomerIdAsync(null); var customerId = await ResolveListCustomerIdAsync(null);
var entity = await GetSkuOrThrowAsync(customerId, input.Id); var entity = await GetSkuOrThrowAsync(customerId, input.Id);
var hasInventory = await InventoryRepository.CountAsync(x => var hasInventory = await InventoryRepository.CountAsync(x =>
x.CustomerId == customerId && x.SkuId == entity.Id && x.Qty > 0); x.SkuId == entity.Id && x.Qty > 0);
if (hasInventory > 0) if (hasInventory > 0)
{ {
throw new BusinessException("SKU 仍有库存,不能删除"); throw new BusinessException("SKU 仍有库存,不能删除");
@ -145,7 +148,7 @@ public partial class WarehouseService
[HttpPost("/warehouse/sku/bind-mapping")] [HttpPost("/warehouse/sku/bind-mapping")]
public async Task<WarehouseSkuMappingOutput> BindSkuMappingAsync(WarehouseSkuBindMappingInput input) public async Task<WarehouseSkuMappingOutput> BindSkuMappingAsync(WarehouseSkuBindMappingInput input)
{ {
var customerId = await ResolveCustomerIdAsync(input.CustomerId); var customerId = await ResolveMutationCustomerIdAsync(input.CustomerId);
var platformSku = input.PlatformSku.Trim(); var platformSku = input.PlatformSku.Trim();
if (string.IsNullOrWhiteSpace(platformSku)) if (string.IsNullOrWhiteSpace(platformSku))
{ {

View File

@ -9,15 +9,24 @@ namespace Oms.Application.Shared;
/// </summary> /// </summary>
public static class WarehouseCustomerHelper public static class WarehouseCustomerHelper
{ {
/// <summary>
/// 列表/汇总查询用的客户 ID:客户登录强制为自身;管理员未传 customerId 时返回 null(查询全部)。
/// </summary>
public static Task<int?> ResolveListCustomerIdAsync(
ICustomerRepository customerRepository,
ICurrentUser currentUser,
int? requestedCustomerId = null) =>
OmsSessionHelper.ResolveListCustomerIdAsync(customerRepository, currentUser, requestedCustomerId);
/// <summary>
/// 写入/删除等必须明确客户归属的操作:客户登录强制为自身;管理员须传 customerId。
/// </summary>
public static async Task<int> ResolveRequiredCustomerIdAsync( public static async Task<int> ResolveRequiredCustomerIdAsync(
ICustomerRepository customerRepository, ICustomerRepository customerRepository,
ICurrentUser currentUser, ICurrentUser currentUser,
int? requestedCustomerId = null) int? requestedCustomerId = null)
{ {
var customerId = await OmsSessionHelper.ResolveListCustomerIdAsync( var customerId = await ResolveListCustomerIdAsync(customerRepository, currentUser, requestedCustomerId);
customerRepository,
currentUser,
requestedCustomerId);
if (!customerId.HasValue) if (!customerId.HasValue)
{ {
throw new BusinessException("客户ID不能为空"); throw new BusinessException("客户ID不能为空");