diff --git a/src/Api/TakeoutSaaS.TenantApi/Services/ProductSkuSaveService.cs b/src/Api/TakeoutSaaS.TenantApi/Services/ProductSkuSaveService.cs index a5dc240..75fb21c 100644 --- a/src/Api/TakeoutSaaS.TenantApi/Services/ProductSkuSaveService.cs +++ b/src/Api/TakeoutSaaS.TenantApi/Services/ProductSkuSaveService.cs @@ -89,6 +89,7 @@ public sealed class ProductSkuSaveService(TakeoutAppDbContext dbContext) .ToDictionary(group => group.Key, group => new Queue(group), StringComparer.Ordinal); var usedExistingSkuIds = new HashSet(); + var plannedSkuCodes = new HashSet(StringComparer.Ordinal); var currentProductSkuCodes = existingSkus .Where(item => !string.IsNullOrWhiteSpace(item.SkuCode)) .Select(item => item.SkuCode) @@ -119,6 +120,20 @@ public sealed class ProductSkuSaveService(TakeoutAppDbContext dbContext) if (matched is not null) { usedExistingSkuIds.Add(matched.Id); + var targetSkuCode = !string.IsNullOrWhiteSpace(normalizedSkuCode) + ? normalizedSkuCode + : NormalizeSkuCode(matched.SkuCode); + if (string.IsNullOrWhiteSpace(targetSkuCode)) + { + targetSkuCode = GenerateUniqueSkuCode(productId, currentProductSkuCodes); + } + + if (!plannedSkuCodes.Add(targetSkuCode)) + { + throw new BusinessException(ErrorCodes.BadRequest, $"SKU 编码冲突: {targetSkuCode}"); + } + + currentProductSkuCodes.Add(targetSkuCode); matched.Price = sku.Price; matched.OriginalPrice = sku.OriginalPrice; matched.StockQuantity = Math.Max(0, sku.Stock); @@ -127,15 +142,17 @@ public sealed class ProductSkuSaveService(TakeoutAppDbContext dbContext) matched.IsEnabled = sku.IsEnabled; matched.DeletedAt = null; matched.DeletedBy = null; - if (!string.IsNullOrWhiteSpace(normalizedSkuCode)) - { - matched.SkuCode = normalizedSkuCode; - } + matched.SkuCode = targetSkuCode; continue; } var generatedCode = normalizedSkuCode ?? GenerateUniqueSkuCode(productId, currentProductSkuCodes); + if (!plannedSkuCodes.Add(generatedCode)) + { + throw new BusinessException(ErrorCodes.BadRequest, $"SKU 编码冲突: {generatedCode}"); + } + currentProductSkuCodes.Add(generatedCode); createdSkus.Add(new ProductSku { @@ -157,6 +174,11 @@ public sealed class ProductSkuSaveService(TakeoutAppDbContext dbContext) continue; } + if (!string.IsNullOrWhiteSpace(existing.SkuCode) && plannedSkuCodes.Contains(existing.SkuCode)) + { + throw new BusinessException(ErrorCodes.BadRequest, $"SKU 编码已存在: {existing.SkuCode}"); + } + existing.IsEnabled = false; existing.StockQuantity = 0; }