From 8a6fc867c24c9ce90179350ebe8316d74dd045a4 Mon Sep 17 00:00:00 2001 From: MSuMshk <2039814060@qq.com> Date: Fri, 20 Feb 2026 09:55:11 +0800 Subject: [PATCH] refactor(store): remove fallback config behavior and expose isConfigured --- .../Contracts/Store/StoreDeliveryContracts.cs | 8 +- .../Contracts/Store/StoreDineInContracts.cs | 6 +- .../Contracts/Store/StoreFeesContracts.cs | 4 + .../Contracts/Store/StorePickupContracts.cs | 10 +- .../Controllers/StoreDeliveryController.cs | 109 ++++++++---------- .../Controllers/StoreDineInController.cs | 26 +++-- .../Controllers/StoreFeesController.cs | 57 ++++++--- .../Controllers/StorePickupController.cs | 79 +++++++------ .../Handlers/GetStoreFeeQueryHandler.cs | 21 +--- .../App/Stores/StoreListMapping.cs | 19 +-- 10 files changed, 166 insertions(+), 173 deletions(-) diff --git a/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreDeliveryContracts.cs b/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreDeliveryContracts.cs index db6806b..914c362 100644 --- a/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreDeliveryContracts.cs +++ b/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreDeliveryContracts.cs @@ -107,9 +107,13 @@ public sealed class StoreDeliverySettingsDto /// public string StoreId { get; set; } = string.Empty; /// + /// IsConfigured。 + /// + public bool IsConfigured { get; set; } + /// /// Mode。 /// - public string Mode { get; set; } = "radius"; + public string? Mode { get; set; } /// /// RadiusCenterLatitude。 /// @@ -129,7 +133,7 @@ public sealed class StoreDeliverySettingsDto /// /// GeneralSettings。 /// - public DeliveryGeneralSettingsDto GeneralSettings { get; set; } = new(); + public DeliveryGeneralSettingsDto? GeneralSettings { get; set; } } /// diff --git a/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreDineInContracts.cs b/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreDineInContracts.cs index 210108d..79a8aef 100644 --- a/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreDineInContracts.cs +++ b/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreDineInContracts.cs @@ -83,9 +83,13 @@ public sealed class StoreDineInSettingsDto /// public string StoreId { get; set; } = string.Empty; /// + /// IsConfigured。 + /// + public bool IsConfigured { get; set; } + /// /// BasicSettings。 /// - public DineInBasicSettingsDto BasicSettings { get; set; } = new(); + public DineInBasicSettingsDto? BasicSettings { get; set; } /// /// Areas。 /// diff --git a/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreFeesContracts.cs b/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreFeesContracts.cs index 7c94586..c6a279d 100644 --- a/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreFeesContracts.cs +++ b/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreFeesContracts.cs @@ -67,6 +67,10 @@ public sealed class StoreFeesSettingsDto /// public string StoreId { get; set; } = string.Empty; /// + /// IsConfigured。 + /// + public bool IsConfigured { get; set; } + /// /// MinimumOrderAmount。 /// public decimal MinimumOrderAmount { get; set; } diff --git a/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StorePickupContracts.cs b/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StorePickupContracts.cs index 50e7247..ecc5758 100644 --- a/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StorePickupContracts.cs +++ b/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StorePickupContracts.cs @@ -145,13 +145,17 @@ public sealed class StorePickupSettingsDto /// public string StoreId { get; set; } = string.Empty; /// + /// IsConfigured。 + /// + public bool IsConfigured { get; set; } + /// /// Mode。 /// - public string Mode { get; set; } = "big"; + public string? Mode { get; set; } /// /// BasicSettings。 /// - public PickupBasicSettingsDto BasicSettings { get; set; } = new(); + public PickupBasicSettingsDto? BasicSettings { get; set; } /// /// BigSlots。 /// @@ -159,7 +163,7 @@ public sealed class StorePickupSettingsDto /// /// FineRule。 /// - public PickupFineRuleDto FineRule { get; set; } = new(); + public PickupFineRuleDto? FineRule { get; set; } /// /// PreviewDays。 /// diff --git a/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreDeliveryController.cs b/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreDeliveryController.cs index 79ba327..0b97b1e 100644 --- a/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreDeliveryController.cs +++ b/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreDeliveryController.cs @@ -48,21 +48,25 @@ public sealed class StoreDeliveryController( .ToListAsync(cancellationToken); var radiusTiers = ParseRadiusTiers(setting?.RadiusTiersJson); + var isConfigured = setting is not null || polygonZones.Count > 0 || radiusTiers.Count > 0; return ApiResponse.Ok(new StoreDeliverySettingsDto { StoreId = parsedStoreId.ToString(), - Mode = StoreApiHelpers.ToDeliveryModeText(setting?.Mode ?? StoreDeliveryMode.Radius), + IsConfigured = isConfigured, + Mode = setting is null ? null : StoreApiHelpers.ToDeliveryModeText(setting.Mode), RadiusCenterLatitude = setting?.RadiusCenterLatitude, RadiusCenterLongitude = setting?.RadiusCenterLongitude, RadiusTiers = radiusTiers, PolygonZones = polygonZones.Select(MapPolygonZone).ToList(), - GeneralSettings = new DeliveryGeneralSettingsDto - { - EtaAdjustmentMinutes = setting?.EtaAdjustmentMinutes ?? 10, - FreeDeliveryThreshold = setting?.FreeDeliveryThreshold ?? 30m, - HourlyCapacityLimit = setting?.HourlyCapacityLimit ?? 50, - MaxDeliveryDistance = setting?.MaxDeliveryDistance ?? 5m - } + GeneralSettings = setting is null + ? null + : new DeliveryGeneralSettingsDto + { + EtaAdjustmentMinutes = setting.EtaAdjustmentMinutes, + FreeDeliveryThreshold = setting.FreeDeliveryThreshold, + HourlyCapacityLimit = setting.HourlyCapacityLimit, + MaxDeliveryDistance = setting.MaxDeliveryDistance + } }); } @@ -98,6 +102,16 @@ public sealed class StoreDeliveryController( public async Task> Save([FromBody] StoreDeliverySettingsDto request, CancellationToken cancellationToken) { var parsedStoreId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, "storeId"); + if (string.IsNullOrWhiteSpace(request.Mode)) + { + throw new BusinessException(ErrorCodes.BadRequest, "mode 不能为空"); + } + + if (request.GeneralSettings is null) + { + throw new BusinessException(ErrorCodes.BadRequest, "generalSettings 不能为空"); + } + var (tenantId, merchantId) = StoreApiHelpers.GetTenantMerchantContext(storeContextService); await StoreApiHelpers.EnsureStoreAccessibleAsync(dbContext, tenantId, merchantId, parsedStoreId, cancellationToken); @@ -203,6 +217,10 @@ public sealed class StoreDeliveryController( .AsNoTracking() .Where(x => x.TenantId == tenantId && x.StoreId == sourceStoreId) .ToListAsync(cancellationToken); + if (sourceSetting is null) + { + throw new BusinessException(ErrorCodes.BadRequest, "源门店未配置配送设置,无法复制"); + } var targetSettings = await dbContext.StoreDeliverySettings .Where(x => x.TenantId == tenantId && accessibleTargetIds.Contains(x.StoreId)) @@ -220,14 +238,14 @@ public sealed class StoreDeliveryController( await dbContext.StoreDeliverySettings.AddAsync(targetSetting, cancellationToken); } - targetSetting.Mode = sourceSetting?.Mode ?? StoreDeliveryMode.Radius; - targetSetting.EtaAdjustmentMinutes = sourceSetting?.EtaAdjustmentMinutes ?? 10; - targetSetting.FreeDeliveryThreshold = sourceSetting?.FreeDeliveryThreshold ?? 30m; - targetSetting.HourlyCapacityLimit = sourceSetting?.HourlyCapacityLimit ?? 50; - targetSetting.MaxDeliveryDistance = sourceSetting?.MaxDeliveryDistance ?? 5m; - targetSetting.RadiusCenterLatitude = sourceSetting?.RadiusCenterLatitude; - targetSetting.RadiusCenterLongitude = sourceSetting?.RadiusCenterLongitude; - targetSetting.RadiusTiersJson = sourceSetting?.RadiusTiersJson; + targetSetting.Mode = sourceSetting.Mode; + targetSetting.EtaAdjustmentMinutes = sourceSetting.EtaAdjustmentMinutes; + targetSetting.FreeDeliveryThreshold = sourceSetting.FreeDeliveryThreshold; + targetSetting.HourlyCapacityLimit = sourceSetting.HourlyCapacityLimit; + targetSetting.MaxDeliveryDistance = sourceSetting.MaxDeliveryDistance; + targetSetting.RadiusCenterLatitude = sourceSetting.RadiusCenterLatitude; + targetSetting.RadiusCenterLongitude = sourceSetting.RadiusCenterLongitude; + targetSetting.RadiusTiersJson = sourceSetting.RadiusTiersJson; } var targetZones = await dbContext.StoreDeliveryZones @@ -264,55 +282,20 @@ public sealed class StoreDeliveryController( private static List ParseRadiusTiers(string? raw) { - if (!string.IsNullOrWhiteSpace(raw)) + if (string.IsNullOrWhiteSpace(raw)) { - try - { - var parsed = JsonSerializer.Deserialize>(raw, StoreApiHelpers.JsonOptions); - if (parsed is not null && parsed.Count > 0) - { - return NormalizeRadiusTiers(parsed); - } - } - catch - { - // 忽略配置反序列化异常并回落默认值 - } + return []; } - return NormalizeRadiusTiers(new List + try { - new() - { - Id = "tier-1", - MinDistance = 0m, - MaxDistance = 1m, - DeliveryFee = 3m, - EtaMinutes = 20, - MinOrderAmount = 15m, - Color = "#52c41a" - }, - new() - { - Id = "tier-2", - MinDistance = 1m, - MaxDistance = 3m, - DeliveryFee = 5m, - EtaMinutes = 35, - MinOrderAmount = 20m, - Color = "#faad14" - }, - new() - { - Id = "tier-3", - MinDistance = 3m, - MaxDistance = 5m, - DeliveryFee = 8m, - EtaMinutes = 50, - MinOrderAmount = 25m, - Color = "#ff4d4f" - } - }); + var parsed = JsonSerializer.Deserialize>(raw, StoreApiHelpers.JsonOptions); + return NormalizeRadiusTiers(parsed); + } + catch + { + return []; + } } private static List NormalizeRadiusTiers(IEnumerable? source) @@ -343,9 +326,9 @@ public sealed class StoreDeliveryController( { Id = source.Id.ToString(), Name = source.ZoneName, - Color = source.Color ?? "#1677ff", + Color = source.Color ?? string.Empty, DeliveryFee = source.DeliveryFee ?? 0m, - EtaMinutes = source.EstimatedMinutes ?? 20, + EtaMinutes = source.EstimatedMinutes ?? 0, MinOrderAmount = source.MinimumOrderAmount ?? 0m, Priority = source.Priority, PolygonGeoJson = source.PolygonGeoJson diff --git a/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreDineInController.cs b/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreDineInController.cs index 2dd74da..ea26846 100644 --- a/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreDineInController.cs +++ b/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreDineInController.cs @@ -47,16 +47,20 @@ public sealed class StoreDineInController( .Where(x => x.TenantId == tenantId && x.StoreId == parsedStoreId) .OrderBy(x => x.TableCode) .ToListAsync(cancellationToken); + var isConfigured = basic is not null || areas.Count > 0 || tables.Count > 0; return ApiResponse.Ok(new StoreDineInSettingsDto { StoreId = parsedStoreId.ToString(), - BasicSettings = new DineInBasicSettingsDto - { - Enabled = basic?.Enabled ?? true, - DefaultDiningMinutes = basic?.DefaultDiningMinutes ?? 90, - OvertimeReminderMinutes = basic?.OvertimeReminderMinutes ?? 10 - }, + IsConfigured = isConfigured, + BasicSettings = basic is null + ? null + : new DineInBasicSettingsDto + { + Enabled = basic.Enabled, + DefaultDiningMinutes = basic.DefaultDiningMinutes, + OvertimeReminderMinutes = basic.OvertimeReminderMinutes + }, Areas = areas.Select(MapArea).ToList(), Tables = tables.Select(MapTable).ToList() }); @@ -369,6 +373,10 @@ public sealed class StoreDineInController( .Where(x => x.TenantId == tenantId && x.StoreId == sourceStoreId) .OrderBy(x => x.TableCode) .ToListAsync(cancellationToken); + if (sourceBasic is null) + { + throw new BusinessException(ErrorCodes.BadRequest, "源门店未配置堂食基础设置,无法复制"); + } foreach (var targetStoreId in accessibleTargetIds) { @@ -383,9 +391,9 @@ public sealed class StoreDineInController( await dbContext.StoreDineInSettings.AddAsync(targetBasic, cancellationToken); } - targetBasic.Enabled = sourceBasic?.Enabled ?? true; - targetBasic.DefaultDiningMinutes = sourceBasic?.DefaultDiningMinutes ?? 90; - targetBasic.OvertimeReminderMinutes = sourceBasic?.OvertimeReminderMinutes ?? 10; + targetBasic.Enabled = sourceBasic.Enabled; + targetBasic.DefaultDiningMinutes = sourceBasic.DefaultDiningMinutes; + targetBasic.OvertimeReminderMinutes = sourceBasic.OvertimeReminderMinutes; var targetTables = await dbContext.StoreTables .Where(x => x.TenantId == tenantId && x.StoreId == targetStoreId) diff --git a/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreFeesController.cs b/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreFeesController.cs index 5501c83..07eeb28 100644 --- a/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreFeesController.cs +++ b/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreFeesController.cs @@ -9,6 +9,8 @@ using TakeoutSaaS.Application.App.Stores.Services; using TakeoutSaaS.Domain.Stores.Entities; using TakeoutSaaS.Domain.Stores.Enums; using TakeoutSaaS.Infrastructure.App.Persistence; +using TakeoutSaaS.Shared.Abstractions.Constants; +using TakeoutSaaS.Shared.Abstractions.Exceptions; using TakeoutSaaS.Shared.Abstractions.Results; using TakeoutSaaS.Shared.Web.Api; using TakeoutSaaS.TenantApi.Contracts.Store; @@ -116,6 +118,10 @@ public sealed class StoreFeesController( var sourceFee = await dbContext.StoreFees .AsNoTracking() .FirstOrDefaultAsync(x => x.TenantId == tenantId && x.StoreId == sourceStoreId, cancellationToken); + if (sourceFee is null) + { + throw new BusinessException(ErrorCodes.BadRequest, "源门店未配置费用设置,无法复制"); + } var targetFees = await dbContext.StoreFees .Where(x => x.TenantId == tenantId && accessibleTargetIds.Contains(x.StoreId)) @@ -133,17 +139,17 @@ public sealed class StoreFeesController( await dbContext.StoreFees.AddAsync(targetFee, cancellationToken); } - targetFee.MinimumOrderAmount = sourceFee?.MinimumOrderAmount ?? 0m; - targetFee.BaseDeliveryFee = sourceFee?.BaseDeliveryFee ?? 0m; - targetFee.FreeDeliveryThreshold = sourceFee?.FreeDeliveryThreshold; - targetFee.PackagingFeeMode = sourceFee?.PackagingFeeMode ?? PackagingFeeMode.Fixed; - targetFee.OrderPackagingFeeMode = sourceFee?.OrderPackagingFeeMode ?? OrderPackagingFeeMode.Fixed; - targetFee.FixedPackagingFee = sourceFee?.FixedPackagingFee ?? 0m; - targetFee.PackagingFeeTiersJson = sourceFee?.PackagingFeeTiersJson; - targetFee.CutleryFeeEnabled = sourceFee?.CutleryFeeEnabled ?? false; - targetFee.CutleryFeeAmount = sourceFee?.CutleryFeeAmount ?? 0m; - targetFee.RushFeeEnabled = sourceFee?.RushFeeEnabled ?? false; - targetFee.RushFeeAmount = sourceFee?.RushFeeAmount ?? 0m; + targetFee.MinimumOrderAmount = sourceFee.MinimumOrderAmount; + targetFee.BaseDeliveryFee = sourceFee.BaseDeliveryFee; + targetFee.FreeDeliveryThreshold = sourceFee.FreeDeliveryThreshold; + targetFee.PackagingFeeMode = sourceFee.PackagingFeeMode; + targetFee.OrderPackagingFeeMode = sourceFee.OrderPackagingFeeMode; + targetFee.FixedPackagingFee = sourceFee.FixedPackagingFee; + targetFee.PackagingFeeTiersJson = sourceFee.PackagingFeeTiersJson; + targetFee.CutleryFeeEnabled = sourceFee.CutleryFeeEnabled; + targetFee.CutleryFeeAmount = sourceFee.CutleryFeeAmount; + targetFee.RushFeeEnabled = sourceFee.RushFeeEnabled; + targetFee.RushFeeAmount = sourceFee.RushFeeAmount; } await dbContext.SaveChangesAsync(cancellationToken); @@ -171,6 +177,7 @@ public sealed class StoreFeesController( return new StoreFeesSettingsDto { StoreId = storeId.ToString(), + IsConfigured = source is not null, MinimumOrderAmount = source?.MinimumOrderAmount ?? 0m, BaseDeliveryFee = source?.DeliveryFee ?? 0m, FreeDeliveryThreshold = source?.FreeDeliveryThreshold, @@ -196,9 +203,17 @@ public sealed class StoreFeesController( private static PackagingFeeMode ParsePackagingFeeMode(string? value) { - return string.Equals(value, "item", StringComparison.OrdinalIgnoreCase) - ? PackagingFeeMode.PerItem - : PackagingFeeMode.Fixed; + if (string.Equals(value, "item", StringComparison.OrdinalIgnoreCase)) + { + return PackagingFeeMode.PerItem; + } + + if (string.Equals(value, "order", StringComparison.OrdinalIgnoreCase)) + { + return PackagingFeeMode.Fixed; + } + + throw new BusinessException(ErrorCodes.BadRequest, "packagingFeeMode 非法"); } private static string ToPackagingFeeModeText(PackagingFeeMode value) @@ -208,9 +223,17 @@ public sealed class StoreFeesController( private static OrderPackagingFeeMode ParseOrderPackagingFeeMode(string? value) { - return string.Equals(value, "tiered", StringComparison.OrdinalIgnoreCase) - ? OrderPackagingFeeMode.Tiered - : OrderPackagingFeeMode.Fixed; + if (string.Equals(value, "tiered", StringComparison.OrdinalIgnoreCase)) + { + return OrderPackagingFeeMode.Tiered; + } + + if (string.Equals(value, "fixed", StringComparison.OrdinalIgnoreCase)) + { + return OrderPackagingFeeMode.Fixed; + } + + throw new BusinessException(ErrorCodes.BadRequest, "orderPackagingFeeMode 非法"); } private static string ToOrderPackagingFeeModeText(OrderPackagingFeeMode value) diff --git a/src/Api/TakeoutSaaS.TenantApi/Controllers/StorePickupController.cs b/src/Api/TakeoutSaaS.TenantApi/Controllers/StorePickupController.cs index 2b0a39e..0266981 100644 --- a/src/Api/TakeoutSaaS.TenantApi/Controllers/StorePickupController.cs +++ b/src/Api/TakeoutSaaS.TenantApi/Controllers/StorePickupController.cs @@ -7,6 +7,8 @@ using TakeoutSaaS.Application.App.Stores.Services; using TakeoutSaaS.Domain.Stores.Entities; using TakeoutSaaS.Domain.Stores.Enums; using TakeoutSaaS.Infrastructure.App.Persistence; +using TakeoutSaaS.Shared.Abstractions.Constants; +using TakeoutSaaS.Shared.Abstractions.Exceptions; using TakeoutSaaS.Shared.Abstractions.Results; using TakeoutSaaS.Shared.Web.Api; using TakeoutSaaS.TenantApi.Contracts.Store; @@ -46,18 +48,22 @@ public sealed class StorePickupController( .ToListAsync(cancellationToken); var fineRule = ParseFineRule(setting?.FineRuleJson); - var previewDays = BuildPreviewDays(fineRule); + var previewDays = fineRule is null ? [] : BuildPreviewDays(fineRule); + var isConfigured = setting is not null || slots.Count > 0; var response = new StorePickupSettingsDto { StoreId = parsedStoreId.ToString(), - Mode = StoreApiHelpers.ToPickupModeText(setting?.Mode ?? StorePickupMode.Big), - BasicSettings = new PickupBasicSettingsDto - { - AllowSameDayPickup = setting?.AllowToday ?? true, - BookingDays = setting?.AllowDaysAhead ?? 3, - MaxItemsPerOrder = setting?.MaxQuantityPerOrder ?? 20 - }, + IsConfigured = isConfigured, + Mode = setting is null ? null : StoreApiHelpers.ToPickupModeText(setting.Mode), + BasicSettings = setting is null + ? null + : new PickupBasicSettingsDto + { + AllowSameDayPickup = setting.AllowToday, + BookingDays = setting.AllowDaysAhead, + MaxItemsPerOrder = setting.MaxQuantityPerOrder + }, BigSlots = slots.Select(slot => new PickupSlotDto { Id = slot.Id.ToString(), @@ -211,6 +217,10 @@ public sealed class StorePickupController( .AsNoTracking() .Where(x => x.TenantId == tenantId && x.StoreId == sourceStoreId) .ToListAsync(cancellationToken); + if (sourceSetting is null) + { + throw new BusinessException(ErrorCodes.BadRequest, "源门店未配置自提设置,无法复制"); + } var targetSettings = await dbContext.StorePickupSettings .Where(x => x.TenantId == tenantId && accessibleTargetIds.Contains(x.StoreId)) @@ -229,12 +239,12 @@ public sealed class StorePickupController( await dbContext.StorePickupSettings.AddAsync(targetSetting, cancellationToken); } - targetSetting.AllowToday = sourceSetting?.AllowToday ?? true; - targetSetting.AllowDaysAhead = sourceSetting?.AllowDaysAhead ?? 3; - targetSetting.DefaultCutoffMinutes = sourceSetting?.DefaultCutoffMinutes ?? 30; - targetSetting.MaxQuantityPerOrder = sourceSetting?.MaxQuantityPerOrder ?? 20; - targetSetting.Mode = sourceSetting?.Mode ?? StorePickupMode.Big; - targetSetting.FineRuleJson = sourceSetting?.FineRuleJson; + targetSetting.AllowToday = sourceSetting.AllowToday; + targetSetting.AllowDaysAhead = sourceSetting.AllowDaysAhead; + targetSetting.DefaultCutoffMinutes = sourceSetting.DefaultCutoffMinutes; + targetSetting.MaxQuantityPerOrder = sourceSetting.MaxQuantityPerOrder; + targetSetting.Mode = sourceSetting.Mode; + targetSetting.FineRuleJson = sourceSetting.FineRuleJson; targetSetting.RowVersion = CreateRowVersion(); } @@ -295,46 +305,35 @@ public sealed class StorePickupController( return RandomNumberGenerator.GetBytes(16); } - private static PickupFineRuleDto ParseFineRule(string? raw) + private static PickupFineRuleDto? ParseFineRule(string? raw) { - if (!string.IsNullOrWhiteSpace(raw)) + if (string.IsNullOrWhiteSpace(raw)) { - try - { - var parsed = JsonSerializer.Deserialize(raw, StoreApiHelpers.JsonOptions); - if (parsed is not null) - { - return NormalizeFineRule(parsed); - } - } - catch - { - // 忽略反序列化异常,回落默认配置 - } + return null; } - return new PickupFineRuleDto + try { - IntervalMinutes = 30, - SlotCapacity = 5, - DayStartTime = "09:00", - DayEndTime = "20:30", - MinAdvanceHours = 2, - DayOfWeeks = [0, 1, 2, 3, 4, 5, 6] - }; + var parsed = JsonSerializer.Deserialize(raw, StoreApiHelpers.JsonOptions); + return parsed is null ? null : NormalizeFineRule(parsed); + } + catch + { + return null; + } } private static PickupFineRuleDto NormalizeFineRule(PickupFineRuleDto source) { - var start = string.IsNullOrWhiteSpace(source.DayStartTime) ? "09:00" : source.DayStartTime; - var end = string.IsNullOrWhiteSpace(source.DayEndTime) ? "20:30" : source.DayEndTime; + var start = StoreApiHelpers.ParseRequiredTime(source.DayStartTime, "fineRule.dayStartTime"); + var end = StoreApiHelpers.ParseRequiredTime(source.DayEndTime, "fineRule.dayEndTime"); return new PickupFineRuleDto { IntervalMinutes = Math.Clamp(source.IntervalMinutes, 5, 180), SlotCapacity = Math.Clamp(source.SlotCapacity, 1, 999), - DayStartTime = StoreApiHelpers.ToHHmm(StoreApiHelpers.ParseRequiredTime(start, "fineRule.dayStartTime")), - DayEndTime = StoreApiHelpers.ToHHmm(StoreApiHelpers.ParseRequiredTime(end, "fineRule.dayEndTime")), + DayStartTime = StoreApiHelpers.ToHHmm(start), + DayEndTime = StoreApiHelpers.ToHHmm(end), MinAdvanceHours = Math.Clamp(source.MinAdvanceHours, 0, 72), DayOfWeeks = (source.DayOfWeeks ?? []) .Distinct() diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreFeeQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreFeeQueryHandler.cs index 823466a..ac29821 100644 --- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreFeeQueryHandler.cs +++ b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreFeeQueryHandler.cs @@ -2,7 +2,6 @@ using MediatR; using TakeoutSaaS.Application.App.Stores; using TakeoutSaaS.Application.App.Stores.Dto; using TakeoutSaaS.Application.App.Stores.Queries; -using TakeoutSaaS.Domain.Stores.Entities; using TakeoutSaaS.Domain.Stores.Repositories; using TakeoutSaaS.Shared.Abstractions.Constants; using TakeoutSaaS.Shared.Abstractions.Exceptions; @@ -31,25 +30,7 @@ public sealed class GetStoreFeeQueryHandler( // 2. (空行后) 查询费用配置 var fee = await storeRepository.GetStoreFeeAsync(request.StoreId, tenantId, cancellationToken); - if (fee is null) - { - var fallback = new StoreFee - { - StoreId = request.StoreId, - MinimumOrderAmount = 0m, - BaseDeliveryFee = 0m, - PackagingFeeMode = Domain.Stores.Enums.PackagingFeeMode.Fixed, - OrderPackagingFeeMode = Domain.Stores.Enums.OrderPackagingFeeMode.Fixed, - FixedPackagingFee = 0m, - CutleryFeeEnabled = false, - CutleryFeeAmount = 0m, - RushFeeEnabled = false, - RushFeeAmount = 0m - }; - return StoreMapping.ToDto(fallback); - } - // 3. (空行后) 返回结果 - return StoreMapping.ToDto(fee); + return fee is null ? null : StoreMapping.ToDto(fee); } } diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/StoreListMapping.cs b/src/Application/TakeoutSaaS.Application/App/Stores/StoreListMapping.cs index 0a29b63..9b723e0 100644 --- a/src/Application/TakeoutSaaS.Application/App/Stores/StoreListMapping.cs +++ b/src/Application/TakeoutSaaS.Application/App/Stores/StoreListMapping.cs @@ -101,29 +101,12 @@ public static class StoreListMapping result.Add(ServiceType.DineIn); } - // 2. 兜底默认展示配送服务 - if (result.Count == 0) - { - result.Add(ServiceType.Delivery); - } - return result; } private static string ResolveAddress(Store store) { - // 1. 地址优先返回业务地址字段 - if (!string.IsNullOrWhiteSpace(store.Address)) - { - return store.Address; - } - - // 2. 兜底拼接省市区 - var parts = new[] { store.Province, store.City, store.District } - .Where(static part => !string.IsNullOrWhiteSpace(part)) - .ToArray(); - - return parts.Length == 0 ? string.Empty : string.Join(string.Empty, parts); + return string.IsNullOrWhiteSpace(store.Address) ? string.Empty : store.Address; } }