修复仓储/店铺列表 ConcurrencyStamp 缺失与可空客户ID的 SQL 翻译错误。

补迁移脚本为 C_* 与 t_sales_* 表增加 ConcurrencyStamp;列表查询改用 hasCustomerFilter 模式避免 ORM 生成非法 SQL。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zzh 2026-07-11 16:48:05 +08:00
parent 36fb191f94
commit fb61fbb072
10 changed files with 94 additions and 14 deletions

View File

@ -19,6 +19,7 @@ CREATE TABLE IF NOT EXISTS `C_sku` (
`HeightCm` DECIMAL(10,2) NULL COMMENT '高(cm)', `HeightCm` DECIMAL(10,2) NULL COMMENT '高(cm)',
`Remark` VARCHAR(512) NULL COMMENT '备注', `Remark` VARCHAR(512) NULL COMMENT '备注',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT '并发戳',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人', `CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人',
`CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateUserId` INT NULL COMMENT '更新人', `UpdateUserId` INT NULL COMMENT '更新人',
@ -37,6 +38,7 @@ CREATE TABLE IF NOT EXISTS `C_bin_location` (
`IsEnabled` TINYINT NOT NULL DEFAULT 1 COMMENT '是否启用:0-否,1-是', `IsEnabled` TINYINT NOT NULL DEFAULT 1 COMMENT '是否启用:0-否,1-是',
`Remark` VARCHAR(512) NULL COMMENT '备注', `Remark` VARCHAR(512) NULL COMMENT '备注',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT '并发戳',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人', `CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人',
`CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateUserId` INT NULL COMMENT '更新人', `UpdateUserId` INT NULL COMMENT '更新人',
@ -54,6 +56,7 @@ CREATE TABLE IF NOT EXISTS `C_inventory` (
`BinLocationId` INT NOT NULL COMMENT '库位ID → C_bin_location.Id', `BinLocationId` INT NOT NULL COMMENT '库位ID → C_bin_location.Id',
`Qty` INT NOT NULL DEFAULT 0 COMMENT '可用库存数量', `Qty` INT NOT NULL DEFAULT 0 COMMENT '可用库存数量',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT '并发戳',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人', `CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人',
`CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateUserId` INT NULL COMMENT '更新人', `UpdateUserId` INT NULL COMMENT '更新人',
@ -75,6 +78,7 @@ CREATE TABLE IF NOT EXISTS `C_inbound_notice` (
`ActualArrivalTime` DATETIME NULL COMMENT '实际到货时间', `ActualArrivalTime` DATETIME NULL COMMENT '实际到货时间',
`Remark` VARCHAR(512) NULL COMMENT '备注', `Remark` VARCHAR(512) NULL COMMENT '备注',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT '并发戳',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人', `CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人',
`CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateUserId` INT NULL COMMENT '更新人', `UpdateUserId` INT NULL COMMENT '更新人',
@ -95,6 +99,7 @@ CREATE TABLE IF NOT EXISTS `C_inbound_box` (
`HeightCm` DECIMAL(10,2) NULL COMMENT '高(cm)', `HeightCm` DECIMAL(10,2) NULL COMMENT '高(cm)',
`IsReceived` TINYINT NOT NULL DEFAULT 0 COMMENT '是否已收货:0-否,1-是', `IsReceived` TINYINT NOT NULL DEFAULT 0 COMMENT '是否已收货:0-否,1-是',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT '并发戳',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人', `CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人',
`CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateUserId` INT NULL COMMENT '更新人', `UpdateUserId` INT NULL COMMENT '更新人',
@ -112,6 +117,7 @@ CREATE TABLE IF NOT EXISTS `C_inbound_box_line` (
`ReceivedQty` INT NULL COMMENT '实收数量', `ReceivedQty` INT NULL COMMENT '实收数量',
`BinLocationId` INT NULL COMMENT '上架库位ID → C_bin_location.Id', `BinLocationId` INT NULL COMMENT '上架库位ID → C_bin_location.Id',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT '并发戳',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人', `CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人',
`CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateUserId` INT NULL COMMENT '更新人', `UpdateUserId` INT NULL COMMENT '更新人',
@ -131,6 +137,7 @@ CREATE TABLE IF NOT EXISTS `C_parcel` (
`ArrivalTime` DATETIME NULL COMMENT '到仓时间', `ArrivalTime` DATETIME NULL COMMENT '到仓时间',
`Remark` VARCHAR(512) NULL COMMENT '备注', `Remark` VARCHAR(512) NULL COMMENT '备注',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT '并发戳',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人', `CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人',
`CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateUserId` INT NULL COMMENT '更新人', `UpdateUserId` INT NULL COMMENT '更新人',
@ -150,6 +157,7 @@ CREATE TABLE IF NOT EXISTS `C_parcel_item` (
`BinLocationId` INT NULL COMMENT '上架库位ID', `BinLocationId` INT NULL COMMENT '上架库位ID',
`Remark` VARCHAR(512) NULL COMMENT '备注', `Remark` VARCHAR(512) NULL COMMENT '备注',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT '并发戳',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人', `CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人',
`CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateUserId` INT NULL COMMENT '更新人', `UpdateUserId` INT NULL COMMENT '更新人',
@ -166,6 +174,7 @@ CREATE TABLE IF NOT EXISTS `C_sku_platform_map` (
`SkuId` INT NOT NULL COMMENT '库内SKU ID → C_sku.Id', `SkuId` INT NOT NULL COMMENT '库内SKU ID → C_sku.Id',
`SkuCode` VARCHAR(64) NOT NULL COMMENT '冗余SKU编码', `SkuCode` VARCHAR(64) NOT NULL COMMENT '冗余SKU编码',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT '并发戳',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人', `CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人',
`CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateUserId` INT NULL COMMENT '更新人', `UpdateUserId` INT NULL COMMENT '更新人',
@ -198,6 +207,7 @@ CREATE TABLE IF NOT EXISTS `t_sales_store` (
`IsAutoFulfill` TINYINT NOT NULL DEFAULT 0 COMMENT '是否自动发货:0-否,1-是', `IsAutoFulfill` TINYINT NOT NULL DEFAULT 0 COMMENT '是否自动发货:0-否,1-是',
`Remark` VARCHAR(512) NULL COMMENT '备注', `Remark` VARCHAR(512) NULL COMMENT '备注',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT '并发戳',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人', `CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人',
`CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateUserId` INT NULL COMMENT '更新人', `UpdateUserId` INT NULL COMMENT '更新人',
@ -231,6 +241,7 @@ CREATE TABLE IF NOT EXISTS `t_sales_store_order` (
`LastSyncTime` DATETIME NULL COMMENT '最近同步时间', `LastSyncTime` DATETIME NULL COMMENT '最近同步时间',
`PlatformExtraJson` JSON NULL COMMENT '平台扩展字段', `PlatformExtraJson` JSON NULL COMMENT '平台扩展字段',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT '并发戳',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人', `CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人',
`CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateUserId` INT NULL COMMENT '更新人', `UpdateUserId` INT NULL COMMENT '更新人',
@ -254,6 +265,7 @@ CREATE TABLE IF NOT EXISTS `t_sales_store_order_line` (
`IsShipExcluded` TINYINT NOT NULL DEFAULT 0 COMMENT '是否拒绝发货', `IsShipExcluded` TINYINT NOT NULL DEFAULT 0 COMMENT '是否拒绝发货',
`MappedSkuId` INT NULL COMMENT '映射库内SKU → C_sku.Id', `MappedSkuId` INT NULL COMMENT '映射库内SKU → C_sku.Id',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT '并发戳',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人', `CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人',
`CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateUserId` INT NULL COMMENT '更新人', `UpdateUserId` INT NULL COMMENT '更新人',

View File

@ -0,0 +1,50 @@
-- 已执行旧版 migrate_warehouse_module.sql 的库补 ConcurrencyStamp(与 AggregateRoot 实体对齐)
-- 勿在 ALTER 中使用 DEFAULT(UUID()),复制环境会报 Error 1674
ALTER TABLE `C_sku`
ADD COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '' COMMENT '并发戳' AFTER `IsDeleted`;
UPDATE `C_sku` SET `ConcurrencyStamp` = UUID() WHERE `ConcurrencyStamp` = '';
ALTER TABLE `C_bin_location`
ADD COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '' COMMENT '并发戳' AFTER `IsDeleted`;
UPDATE `C_bin_location` SET `ConcurrencyStamp` = UUID() WHERE `ConcurrencyStamp` = '';
ALTER TABLE `C_inventory`
ADD COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '' COMMENT '并发戳' AFTER `IsDeleted`;
UPDATE `C_inventory` SET `ConcurrencyStamp` = UUID() WHERE `ConcurrencyStamp` = '';
ALTER TABLE `C_inbound_notice`
ADD COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '' COMMENT '并发戳' AFTER `IsDeleted`;
UPDATE `C_inbound_notice` SET `ConcurrencyStamp` = UUID() WHERE `ConcurrencyStamp` = '';
ALTER TABLE `C_inbound_box`
ADD COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '' COMMENT '并发戳' AFTER `IsDeleted`;
UPDATE `C_inbound_box` SET `ConcurrencyStamp` = UUID() WHERE `ConcurrencyStamp` = '';
ALTER TABLE `C_inbound_box_line`
ADD COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '' COMMENT '并发戳' AFTER `IsDeleted`;
UPDATE `C_inbound_box_line` SET `ConcurrencyStamp` = UUID() WHERE `ConcurrencyStamp` = '';
ALTER TABLE `C_parcel`
ADD COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '' COMMENT '并发戳' AFTER `IsDeleted`;
UPDATE `C_parcel` SET `ConcurrencyStamp` = UUID() WHERE `ConcurrencyStamp` = '';
ALTER TABLE `C_parcel_item`
ADD COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '' COMMENT '并发戳' AFTER `IsDeleted`;
UPDATE `C_parcel_item` SET `ConcurrencyStamp` = UUID() WHERE `ConcurrencyStamp` = '';
ALTER TABLE `C_sku_platform_map`
ADD COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '' COMMENT '并发戳' AFTER `IsDeleted`;
UPDATE `C_sku_platform_map` SET `ConcurrencyStamp` = UUID() WHERE `ConcurrencyStamp` = '';
ALTER TABLE `t_sales_store`
ADD COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '' COMMENT '并发戳' AFTER `IsDeleted`;
UPDATE `t_sales_store` SET `ConcurrencyStamp` = UUID() WHERE `ConcurrencyStamp` = '';
ALTER TABLE `t_sales_store_order`
ADD COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '' COMMENT '并发戳' AFTER `IsDeleted`;
UPDATE `t_sales_store_order` SET `ConcurrencyStamp` = UUID() WHERE `ConcurrencyStamp` = '';
ALTER TABLE `t_sales_store_order_line`
ADD COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '' COMMENT '并发戳' AFTER `IsDeleted`;
UPDATE `t_sales_store_order_line` SET `ConcurrencyStamp` = UUID() WHERE `ConcurrencyStamp` = '';

View File

@ -125,8 +125,9 @@ public class PlatformStoreOrderService : ApplicationService
CustomerRepository, CustomerRepository,
CurrentUser, CurrentUser,
customerId); customerId);
var (hasCustomerFilter, customerIdValue) = WarehouseCustomerHelper.ToCustomerFilter(resolvedCustomerId);
var orders = await StoreOrderRepository.GetListAsync(x => var orders = await StoreOrderRepository.GetListAsync(x =>
(!resolvedCustomerId.HasValue || x.CustomerId == resolvedCustomerId.Value) (!hasCustomerFilter || x.CustomerId == customerIdValue)
&& (!storeId.HasValue || x.StoreId == storeId.Value)); && (!storeId.HasValue || x.StoreId == storeId.Value));
return new PlatformStoreOrderSummaryOutput return new PlatformStoreOrderSummaryOutput
@ -232,8 +233,9 @@ public class PlatformStoreOrderService : ApplicationService
CustomerRepository, CustomerRepository,
CurrentUser, CurrentUser,
input.CustomerId); input.CustomerId);
var (hasCustomerFilter, customerIdValue) = WarehouseCustomerHelper.ToCustomerFilter(customerId);
var orders = await StoreOrderRepository.GetListAsync(x => var orders = await StoreOrderRepository.GetListAsync(x =>
(!customerId.HasValue || x.CustomerId == customerId.Value) && input.Ids.Contains(x.Id)); (!hasCustomerFilter || x.CustomerId == customerIdValue) && 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);
@ -594,11 +596,12 @@ public class PlatformStoreOrderService : ApplicationService
private static Expression<Func<SalesStoreOrder, bool>> BuildListPredicate(int? customerId, PlatformStoreOrderListInput input) private static Expression<Func<SalesStoreOrder, bool>> BuildListPredicate(int? customerId, PlatformStoreOrderListInput input)
{ {
var (hasCustomerFilter, customerIdValue) = WarehouseCustomerHelper.ToCustomerFilter(customerId);
var fulfillStatus = input.FulfillStatus?.Trim(); var fulfillStatus = input.FulfillStatus?.Trim();
var platformOrderNo = input.PlatformOrderNo?.Trim(); var platformOrderNo = input.PlatformOrderNo?.Trim();
return x => return x =>
(!customerId.HasValue || x.CustomerId == customerId.Value) (!hasCustomerFilter || x.CustomerId == customerIdValue)
&& (!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

@ -142,8 +142,9 @@ public class PlatformStoreService : ApplicationService
CustomerRepository, CustomerRepository,
CurrentUser, CurrentUser,
null); null);
var (hasCustomerFilter, customerIdValue) = WarehouseCustomerHelper.ToCustomerFilter(customerId);
var entities = await StoreRepository.GetListAsync(x => var entities = await StoreRepository.GetListAsync(x =>
(!customerId.HasValue || x.CustomerId == customerId.Value) && input.Ids.Contains(x.Id)); (!hasCustomerFilter || x.CustomerId == customerIdValue) && input.Ids.Contains(x.Id));
foreach (var entity in entities) foreach (var entity in entities)
{ {
await StoreRepository.DeleteAsync(entity); await StoreRepository.DeleteAsync(entity);
@ -165,6 +166,7 @@ public class PlatformStoreService : ApplicationService
private static Expression<Func<SalesStore, bool>> BuildListPredicate(int? customerId, PlatformStorePageInput input) private static Expression<Func<SalesStore, bool>> BuildListPredicate(int? customerId, PlatformStorePageInput input)
{ {
var (hasCustomerFilter, customerIdValue) = WarehouseCustomerHelper.ToCustomerFilter(customerId);
var platformCode = input.PlatformCode?.Trim(); var platformCode = input.PlatformCode?.Trim();
var nickname = input.StoreNickname?.Trim(); var nickname = input.StoreNickname?.Trim();
var filter = input.ExpirationFilter?.Trim().ToLowerInvariant(); var filter = input.ExpirationFilter?.Trim().ToLowerInvariant();
@ -172,7 +174,7 @@ public class PlatformStoreService : ApplicationService
var within7Days = now.AddDays(7); var within7Days = now.AddDays(7);
return x => return x =>
(!customerId.HasValue || x.CustomerId == customerId.Value) (!hasCustomerFilter || x.CustomerId == customerIdValue)
&& (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

@ -18,6 +18,9 @@ public partial class WarehouseService
CurrentUser, CurrentUser,
requestedCustomerId); requestedCustomerId);
private static (bool HasFilter, int Value) CustomerFilter(int? customerId) =>
WarehouseCustomerHelper.ToCustomerFilter(customerId);
private async Task<CSku> GetSkuOrThrowAsync(int? customerId, int skuId) private async Task<CSku> GetSkuOrThrowAsync(int? customerId, int skuId)
{ {
var entity = customerId.HasValue var entity = customerId.HasValue

View File

@ -20,12 +20,13 @@ public partial class WarehouseService
public async Task<OmsPageResult<WarehouseInboundOutput>> GetInboundListAsync(WarehouseInboundListInput input) public async Task<OmsPageResult<WarehouseInboundOutput>> GetInboundListAsync(WarehouseInboundListInput input)
{ {
var customerId = await ResolveListCustomerIdAsync(input.CustomerId); var customerId = await ResolveListCustomerIdAsync(input.CustomerId);
var (hasCustomerFilter, customerIdValue) = CustomerFilter(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 =>
(!customerId.HasValue || x.CustomerId == customerId.Value) (!hasCustomerFilter || x.CustomerId == customerIdValue)
&& (!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!)));
@ -300,8 +301,9 @@ public partial class WarehouseService
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 ResolveListCustomerIdAsync(customerId); var resolvedCustomerId = await ResolveListCustomerIdAsync(customerId);
var (hasCustomerFilter, customerIdValue) = CustomerFilter(resolvedCustomerId);
var notices = await InboundNoticeRepository.GetListAsync(x => var notices = await InboundNoticeRepository.GetListAsync(x =>
(!resolvedCustomerId.HasValue || x.CustomerId == resolvedCustomerId.Value) (!hasCustomerFilter || x.CustomerId == customerIdValue)
&& (!warehouseId.HasValue || x.WarehouseId == warehouseId.Value)); && (!warehouseId.HasValue || x.WarehouseId == warehouseId.Value));
return new WarehouseInboundSummaryOutput return new WarehouseInboundSummaryOutput

View File

@ -17,8 +17,9 @@ public partial class WarehouseService
public async Task<OmsPageResult<WarehouseInventoryOutput>> GetInventoryListAsync(WarehouseInventoryListInput input) public async Task<OmsPageResult<WarehouseInventoryOutput>> GetInventoryListAsync(WarehouseInventoryListInput input)
{ {
var customerId = await ResolveListCustomerIdAsync(input.CustomerId); var customerId = await ResolveListCustomerIdAsync(input.CustomerId);
var (hasCustomerFilter, customerIdValue) = CustomerFilter(customerId);
var inventories = await InventoryRepository.GetListAsync(x => var inventories = await InventoryRepository.GetListAsync(x =>
(!customerId.HasValue || x.CustomerId == customerId.Value) (!hasCustomerFilter || x.CustomerId == customerIdValue)
&& x.Qty > 0 && x.Qty > 0
&& (!input.WarehouseId.HasValue || x.WarehouseId == input.WarehouseId.Value)); && (!input.WarehouseId.HasValue || x.WarehouseId == input.WarehouseId.Value));
@ -26,7 +27,7 @@ public partial class WarehouseService
var skus = skuIds.Length == 0 var skus = skuIds.Length == 0
? [] ? []
: await SkuRepository.GetListAsync(x => : await SkuRepository.GetListAsync(x =>
(!customerId.HasValue || x.CustomerId == customerId.Value) && skuIds.Contains(x.Id)); (!hasCustomerFilter || x.CustomerId == customerIdValue) && 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();
@ -83,10 +84,11 @@ public partial class WarehouseService
} }
var resolvedCustomerId = await ResolveListCustomerIdAsync(customerId); var resolvedCustomerId = await ResolveListCustomerIdAsync(customerId);
var (hasCustomerFilter, customerIdValue) = CustomerFilter(resolvedCustomerId);
await GetSkuOrThrowAsync(resolvedCustomerId, skuId); await GetSkuOrThrowAsync(resolvedCustomerId, skuId);
var inventories = await InventoryRepository.GetListAsync(x => var inventories = await InventoryRepository.GetListAsync(x =>
(!resolvedCustomerId.HasValue || x.CustomerId == resolvedCustomerId.Value) (!hasCustomerFilter || x.CustomerId == customerIdValue)
&& x.WarehouseId == warehouseId && x.WarehouseId == warehouseId
&& x.SkuId == skuId && x.SkuId == skuId
&& x.Qty > 0); && x.Qty > 0);

View File

@ -20,12 +20,13 @@ public partial class WarehouseService
public async Task<OmsPageResult<WarehouseParcelOutput>> GetParcelListAsync(WarehouseParcelListInput input) public async Task<OmsPageResult<WarehouseParcelOutput>> GetParcelListAsync(WarehouseParcelListInput input)
{ {
var customerId = await ResolveListCustomerIdAsync(input.CustomerId); var customerId = await ResolveListCustomerIdAsync(input.CustomerId);
var (hasCustomerFilter, customerIdValue) = CustomerFilter(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 =>
(!customerId.HasValue || x.CustomerId == customerId.Value) (!hasCustomerFilter || x.CustomerId == customerIdValue)
&& (!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!)));

View File

@ -18,11 +18,12 @@ public partial class WarehouseService
public async Task<OmsPageResult<WarehouseSkuOutput>> GetSkuListAsync(WarehouseSkuListInput input) public async Task<OmsPageResult<WarehouseSkuOutput>> GetSkuListAsync(WarehouseSkuListInput input)
{ {
var customerId = await ResolveListCustomerIdAsync(input.CustomerId); var customerId = await ResolveListCustomerIdAsync(input.CustomerId);
var (hasCustomerFilter, customerIdValue) = CustomerFilter(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 =>
(!customerId.HasValue || x.CustomerId == customerId.Value) (!hasCustomerFilter || x.CustomerId == customerIdValue)
&& (!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);
@ -38,7 +39,7 @@ public partial class WarehouseService
var inventories = skuIds.Length == 0 var inventories = skuIds.Length == 0
? [] ? []
: await InventoryRepository.GetListAsync(x => : await InventoryRepository.GetListAsync(x =>
(!customerId.HasValue || x.CustomerId == customerId.Value) && skuIds.Contains(x.SkuId)); (!hasCustomerFilter || x.CustomerId == customerIdValue) && 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));
@ -60,9 +61,10 @@ public partial class WarehouseService
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 ResolveListCustomerIdAsync(customerId); var resolvedCustomerId = await ResolveListCustomerIdAsync(customerId);
var (hasCustomerFilter, customerIdValue) = CustomerFilter(resolvedCustomerId);
var entity = await GetSkuOrThrowAsync(resolvedCustomerId, id); var entity = await GetSkuOrThrowAsync(resolvedCustomerId, id);
var inventories = await InventoryRepository.GetListAsync(x => var inventories = await InventoryRepository.GetListAsync(x =>
(!resolvedCustomerId.HasValue || x.CustomerId == resolvedCustomerId.Value) (!hasCustomerFilter || x.CustomerId == customerIdValue)
&& x.SkuId == id); && x.SkuId == id);
return MapSkuOutput(entity, inventories.Sum(x => x.Qty)); return MapSkuOutput(entity, inventories.Sum(x => x.Qty));
} }

View File

@ -35,6 +35,9 @@ public static class WarehouseCustomerHelper
return customerId.Value; return customerId.Value;
} }
public static (bool HasFilter, int Value) ToCustomerFilter(int? customerId) =>
(customerId.HasValue, customerId.GetValueOrDefault());
public static string GenerateInboundNoticeNo() => public static string GenerateInboundNoticeNo() =>
$"IN{DateTime.Now:yyyyMMddHHmmss}{Random.Shared.Next(1000, 9999)}"; $"IN{DateTime.Now:yyyyMMddHHmmss}{Random.Shared.Next(1000, 9999)}";
} }